Skip to content

Commit 09839b9

Browse files
authored
Merge pull request #495 from Hritik14/refactor/package_manager
Refactor package_managers
2 parents e9943b0 + ce95f82 commit 09839b9

1 file changed

Lines changed: 24 additions & 86 deletions

File tree

vulnerabilities/package_managers.py

Lines changed: 24 additions & 86 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,15 +84,7 @@ 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.set_api(pkg, session) for pkg in pkg_set if pkg not in self.cache]
81-
)
82-
83-
async def set_api(self, pkg, session):
84-
if pkg in self.cache:
85-
return
87+
async def fetch(self, pkg, session):
8688
url = (
8789
"https://api.launchpad.net/1.0/ubuntu/+archive/"
8890
"primary?ws.op=getPublishedSources&"
@@ -111,12 +113,6 @@ class PypiVersionAPI(VersionAPI):
111113

112114
package_type = "pypi"
113115

114-
async def load_api(self, pkg_set):
115-
async with client_session() as session:
116-
await asyncio.gather(
117-
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
118-
)
119-
120116
async def fetch(self, pkg, session):
121117
url = f"https://pypi.org/pypi/{pkg}/json"
122118
versions = set()
@@ -150,12 +146,6 @@ class CratesVersionAPI(VersionAPI):
150146

151147
package_type = "cargo"
152148

153-
async def load_api(self, pkg_set):
154-
async with client_session() as session:
155-
await asyncio.gather(
156-
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
157-
)
158-
159149
async def fetch(self, pkg, session):
160150
url = f"https://crates.io/api/v1/crates/{pkg}"
161151
response = await session.request(method="GET", url=url)
@@ -176,12 +166,6 @@ class RubyVersionAPI(VersionAPI):
176166

177167
package_type = "gem"
178168

179-
async def load_api(self, pkg_set):
180-
async with client_session() as session:
181-
await asyncio.gather(
182-
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
183-
)
184-
185169
async def fetch(self, pkg, session):
186170
url = f"https://rubygems.org/api/v1/versions/{pkg}.json"
187171
versions = set()
@@ -205,12 +189,6 @@ class NpmVersionAPI(VersionAPI):
205189

206190
package_type = "npm"
207191

208-
async def load_api(self, pkg_set):
209-
async with client_session() as session:
210-
await asyncio.gather(
211-
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
212-
)
213-
214192
async def fetch(self, pkg, session):
215193
url = f"https://registry.npmjs.org/{pkg}"
216194
versions = set()
@@ -242,12 +220,10 @@ async def load_api(self, pkg_set):
242220
raise_for_status=True, headers={"Connection": "keep-alive"}
243221
) as session:
244222
await asyncio.gather(
245-
*[self.set_api(pkg, session) for pkg in pkg_set if pkg not in self.cache]
223+
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
246224
)
247225

248-
async def set_api(self, pkg, session, retry_count=5):
249-
if pkg in self.cache:
250-
return
226+
async def fetch(self, pkg, session, retry_count=5):
251227
url = "https://sources.debian.org/api/src/{}".format(pkg)
252228
try:
253229
all_versions = set()
@@ -271,12 +247,6 @@ class MavenVersionAPI(VersionAPI):
271247

272248
package_type = "maven"
273249

274-
async def load_api(self, pkg_set):
275-
async with client_session() as session:
276-
await asyncio.gather(
277-
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
278-
)
279-
280250
async def fetch(self, pkg, session) -> None:
281251
artifact_comps = pkg.split(":")
282252
endpoint = self.artifact_url(artifact_comps)
@@ -327,12 +297,6 @@ class NugetVersionAPI(VersionAPI):
327297

328298
package_type = "nuget"
329299

330-
async def load_api(self, pkg_set):
331-
async with client_session() as session:
332-
await asyncio.gather(
333-
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
334-
)
335-
336300
async def fetch(self, pkg, session) -> None:
337301
endpoint = self.nuget_url(pkg)
338302
resp = await session.request(method="GET", url=endpoint)
@@ -370,12 +334,6 @@ class ComposerVersionAPI(VersionAPI):
370334

371335
package_type = "composer"
372336

373-
async def load_api(self, pkg_set):
374-
async with client_session() as session:
375-
await asyncio.gather(
376-
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
377-
)
378-
379337
async def fetch(self, pkg, session) -> None:
380338
endpoint = self.composer_url(pkg)
381339
if endpoint:
@@ -415,30 +373,16 @@ class GitHubTagsAPI(VersionAPI):
415373

416374
package_type = "github"
417375

418-
async def load_api(self, repo_set):
419-
session = client_session()
420-
async with session as session:
421-
await asyncio.gather(
422-
*[
423-
self.fetch(owner_repo.lower())
424-
for owner_repo in repo_set
425-
if owner_repo.lower() not in self.cache
426-
]
427-
)
428-
429-
async def fetch(self, owner_repo: str, endpoint=None) -> None:
376+
async def fetch(self, owner_repo: str, session) -> None:
430377
"""
431378
owner_repo is a string of format "{repo_owner}/{repo_name}"
432379
Example value of owner_repo = "nexB/scancode-toolkit"
433380
"""
434-
if owner_repo not in self.cache:
435-
self.cache[owner_repo] = set()
381+
self.cache[owner_repo] = set()
382+
endpoint = f"https://github.com/{owner_repo}/tags"
436383

437-
if not endpoint:
438-
endpoint = f"https://github.com/{owner_repo}/tags"
439-
async with client_session() as session:
440-
resp = await session.get(endpoint)
441-
resp = await resp.read()
384+
resp = await session.get(endpoint)
385+
resp = await resp.read()
442386

443387
soup = BeautifulSoup(resp, features="lxml")
444388
for release_entry in soup.find_all("div", {"class": "commit"}):
@@ -467,12 +411,6 @@ async def fetch(self, owner_repo: str, endpoint=None) -> None:
467411

468412

469413
class HexVersionAPI(VersionAPI):
470-
async def load_api(self, pkg_set):
471-
async with client_session() as session:
472-
await asyncio.gather(
473-
*[self.fetch(pkg, session) for pkg in pkg_set if pkg not in self.cache]
474-
)
475-
476414
async def fetch(self, pkg, session):
477415
url = f"https://hex.pm/api/packages/{pkg}"
478416
versions = set()

0 commit comments

Comments
 (0)