forked from toptal/license-cop
-
Notifications
You must be signed in to change notification settings - Fork 0
/
package_registry.py
94 lines (75 loc) · 2.79 KB
/
package_registry.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import sys
import requests
from abc import *
from app.data_object import *
from app.github.repository import *
class PackageVersionNotFoundError(Exception):
pass
class PackageRegistry(ABC):
class __Id(DataObject):
def __init__(self, name, number=None):
self.name = name
self.number = number
def __iter__(self):
data = (self.name, ) if self.number is None\
else (self.name, self.number)
return data.__iter__()
def __str__(self):
return '{0}:{1}'.format(
self.name,
'latest' if self.number is None else self.number
)
def __init__(self, http_compression=True):
self._session = requests.Session()
if not http_compression:
self._session.headers.update({'Accept-Encoding': 'identity'})
self._http_compression = http_compression
self.__cache = {}
@abstractmethod
def _fetch_version(self, name, number):
pass
@abstractmethod
def _fetch_latest_version(self, name):
pass
def fetch_version(self, name, number):
id = self.__Id(name, number)
return self.__cached_fetch(id, self._fetch_version)
def fetch_latest_version(self, name):
id = self.__Id(name)
return self.__cached_fetch(id, self._fetch_latest_version)
def __cached_fetch(self, id, fetch_function):
if id in self.__cache:
return self.__cache[id]
return self.__cache_miss(id, fetch_function)
def __cache_miss(self, id, fetch_function):
try:
self.__report_progress(f' → {id}')
version = fetch_function(*id)
self.__cache[id] = version
return version
except requests.exceptions.HTTPError as e:
raise PackageVersionNotFoundError(f'Could not find package version {id}. {e}')
def __report_progress(self, message):
sys.stdout.write('\033[K')
print(message)
sys.stdout.write('\033[F')
sys.stdout.flush()
def _find_licenses_in_code_repository_urls(self, urls):
for url in urls:
try:
license = self.__fetch_license(url)
if license:
return [license]
except requests.exceptions.HTTPError as e:
continue
return []
# Right now, only GitHub is supported, but this could be extended
# to support BitBucket or other platforms.
def __fetch_license(self, url):
if url:
repository = self.__github_repository(url)
if repository:
return repository.license()
def __github_repository(self, url):
return GithubRepository.from_url(
url, http_compression=self._http_compression)