1919# for any legal advice.
2020# VulnerableCode is a free software code scanning tool from nexB Inc. and others.
2121# Visit https://github.com/nexB/vulnerablecode/ for support and download.
22-
2322import asyncio
2423import dataclasses
25- import pytz
2624import xml .etree .ElementTree as ET
27- from bs4 import BeautifulSoup
28- from dateutil import parser as dateparser
25+ from datetime import datetime
2926from json import JSONDecodeError
27+ from typing import List
3028from typing import Mapping
3129from typing import Set
32- from typing import List
33- from datetime import datetime
3430
3531from aiohttp import ClientSession
3632from aiohttp .client_exceptions import ClientResponseError
3733from aiohttp .client_exceptions import ServerDisconnectedError
34+ from bs4 import BeautifulSoup
35+ from dateutil import parser as dateparser
3836
3937
4038@dataclasses .dataclass (frozen = True )
@@ -65,6 +63,18 @@ def get(self, package_name, until=None) -> Set[str]:
6563
6664 return VersionResponse (valid_versions = valid_versions , newer_versions = new_versions )
6765
66+ async def load_api (self , pkg_set ):
67+ async with client_session () as session :
68+ await asyncio .gather (
69+ * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
70+ )
71+
72+ async def fetch (self , pkg , session ):
73+ """
74+ Override this method to fetch the pkg's version in the cache
75+ """
76+ raise NotImplementedError
77+
6878
6979def client_session ():
7080 return ClientSession (raise_for_status = True , trust_env = True )
@@ -74,12 +84,6 @@ class LaunchpadVersionAPI(VersionAPI):
7484
7585 package_type = "deb"
7686
77- async def load_api (self , pkg_set ):
78- async with client_session () as session :
79- await asyncio .gather (
80- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
81- )
82-
8387 async def fetch (self , pkg , session ):
8488 url = (
8589 "https://api.launchpad.net/1.0/ubuntu/+archive/"
@@ -109,12 +113,6 @@ class PypiVersionAPI(VersionAPI):
109113
110114 package_type = "pypi"
111115
112- async def load_api (self , pkg_set ):
113- async with client_session () as session :
114- await asyncio .gather (
115- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
116- )
117-
118116 async def fetch (self , pkg , session ):
119117 url = f"https://pypi.org/pypi/{ pkg } /json"
120118 versions = set ()
@@ -148,12 +146,6 @@ class CratesVersionAPI(VersionAPI):
148146
149147 package_type = "cargo"
150148
151- async def load_api (self , pkg_set ):
152- async with client_session () as session :
153- await asyncio .gather (
154- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
155- )
156-
157149 async def fetch (self , pkg , session ):
158150 url = f"https://crates.io/api/v1/crates/{ pkg } "
159151 response = await session .request (method = "GET" , url = url )
@@ -174,12 +166,6 @@ class RubyVersionAPI(VersionAPI):
174166
175167 package_type = "gem"
176168
177- async def load_api (self , pkg_set ):
178- async with client_session () as session :
179- await asyncio .gather (
180- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
181- )
182-
183169 async def fetch (self , pkg , session ):
184170 url = f"https://rubygems.org/api/v1/versions/{ pkg } .json"
185171 versions = set ()
@@ -203,12 +189,6 @@ class NpmVersionAPI(VersionAPI):
203189
204190 package_type = "npm"
205191
206- async def load_api (self , pkg_set ):
207- async with client_session () as session :
208- await asyncio .gather (
209- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
210- )
211-
212192 async def fetch (self , pkg , session ):
213193 url = f"https://registry.npmjs.org/{ pkg } "
214194 versions = set ()
@@ -267,12 +247,6 @@ class MavenVersionAPI(VersionAPI):
267247
268248 package_type = "maven"
269249
270- async def load_api (self , pkg_set ):
271- async with client_session () as session :
272- await asyncio .gather (
273- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
274- )
275-
276250 async def fetch (self , pkg , session ) -> None :
277251 artifact_comps = pkg .split (":" )
278252 endpoint = self .artifact_url (artifact_comps )
@@ -323,12 +297,6 @@ class NugetVersionAPI(VersionAPI):
323297
324298 package_type = "nuget"
325299
326- async def load_api (self , pkg_set ):
327- async with client_session () as session :
328- await asyncio .gather (
329- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
330- )
331-
332300 async def fetch (self , pkg , session ) -> None :
333301 endpoint = self .nuget_url (pkg )
334302 resp = await session .request (method = "GET" , url = endpoint )
@@ -366,12 +334,6 @@ class ComposerVersionAPI(VersionAPI):
366334
367335 package_type = "composer"
368336
369- async def load_api (self , pkg_set ):
370- async with client_session () as session :
371- await asyncio .gather (
372- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
373- )
374-
375337 async def fetch (self , pkg , session ) -> None :
376338 endpoint = self .composer_url (pkg )
377339 if endpoint :
@@ -411,12 +373,6 @@ class GitHubTagsAPI(VersionAPI):
411373
412374 package_type = "github"
413375
414- async def load_api (self , pkg_set ):
415- async with client_session () as session :
416- await asyncio .gather (
417- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
418- )
419-
420376 async def fetch (self , owner_repo : str , session ) -> None :
421377 """
422378 owner_repo is a string of format "{repo_owner}/{repo_name}"
@@ -455,12 +411,6 @@ async def fetch(self, owner_repo: str, session) -> None:
455411
456412
457413class HexVersionAPI (VersionAPI ):
458- async def load_api (self , pkg_set ):
459- async with client_session () as session :
460- await asyncio .gather (
461- * [self .fetch (pkg , session ) for pkg in pkg_set if pkg not in self .cache ]
462- )
463-
464414 async def fetch (self , pkg , session ):
465415 url = f"https://hex.pm/api/packages/{ pkg } "
466416 versions = set ()
0 commit comments