Skip to content

Commit ce95f82

Browse files
committed
Move load_api to parent class and refactor imports
The code for `load_api` was repetitive and used in all subclasses of VersionAPI, it is better suited in the parent class. `fetch` method is also now consistent and defined as an abstract method in the base class. Python ABC is not used as different implementations of `load_api` and `fetch` are allowed as done in DebianVersionAPI Signed-off-by: Hritik Vijay <hritikxx8@gmail.com>
1 parent 775aa1d commit ce95f82

1 file changed

Lines changed: 16 additions & 66 deletions

File tree

vulnerabilities/package_managers.py

Lines changed: 16 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,20 @@
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-
2322
import asyncio
2423
import dataclasses
25-
import pytz
2624
import xml.etree.ElementTree as ET
27-
from bs4 import BeautifulSoup
28-
from dateutil import parser as dateparser
25+
from datetime import datetime
2926
from json import JSONDecodeError
27+
from typing import List
3028
from typing import Mapping
3129
from typing import Set
32-
from typing import List
33-
from datetime import datetime
3430

3531
from aiohttp import ClientSession
3632
from aiohttp.client_exceptions import ClientResponseError
3733
from 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

6979
def 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

457413
class 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

Comments
 (0)