Skip to content

Commit 8dbc882

Browse files
committed
- fix functionality to not fail if dataset files are not downloaded (reverse dependencies and pypi stats)
- prepare aura for release on pypi to work as standalone package out of the box if installed via pip - change default cache behaviour from "ask" to "auto" - add tox-build.ini that tests the sdist package of aura for automated pypi package testing before release
1 parent 3b1e94f commit 8dbc882

File tree

11 files changed

+86
-21
lines changed

11 files changed

+86
-21
lines changed

aura/analyzers/package_enrichment.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .detections import Detection
44
from ..utils import Analyzer
55
from ..type_definitions import AnalyzerReturnType
6+
from ..exceptions import MissingFile
67

78

89
@Analyzer.ID("package_enrichment")
@@ -15,13 +16,18 @@ def analyze(*, location: ScanLocation) -> AnalyzerReturnType:
1516

1617
pkg_score = pkg.score
1718

19+
try:
20+
rev_dependencies = package.get_reverse_dependencies(pkg_name=pkg_name)
21+
except MissingFile:
22+
rev_dependencies = None
23+
1824
extra = {
1925
"source_url": pkg.source_url,
2026
"homepage_url": pkg.homepage_url,
2127
"documentation_url": pkg.documentation_url,
2228
"latest_release": pkg.get_latest_release(),
2329
"score": pkg_score.get_score_matrix(),
24-
"reverse_dependencies": package.get_reverse_dependencies(pkg_name=pkg_name),
30+
"reverse_dependencies": rev_dependencies,
2531
"classifiers": pkg.info["info"].get("classifiers", []),
2632
"version": pkg.get_latest_release()
2733
}

aura/analyzers/typosquatting.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,19 @@
44
from .. import typos
55
from ..utils import Analyzer
66
from ..type_definitions import AnalyzerReturnType
7+
from ..exceptions import MissingFile
78

89

910
@Analyzer.ID("typosquatting")
1011
def analyze(*, location: ScanLocation) -> AnalyzerReturnType:
1112
if not (pkg_name:=location.metadata.get("package_name")):
1213
return
1314

14-
typo_names = typos.check_name(pkg_name, full_list=True)
15+
try:
16+
typo_names = typos.check_name(pkg_name, full_list=True)
17+
except MissingFile:
18+
return
19+
1520

1621
for x in typo_names:
1722
yield Detection(

aura/cache.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ def purge(standard: bool=False):
495495
if Cache.DISABLE_CACHE:
496496
return
497497

498-
mode = config.CFG.get("cache", {}).get("mode", "ask")
498+
mode = config.get_cache_mode()
499499
if mode not in ("ask", "auto", "always"):
500500
raise ValueError(f"Cache mode has invalid value in the configuration: '{mode}'")
501501

aura/config.py

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
except ImportError:
2121
import json
2222

23-
from .exceptions import InvalidConfiguration
23+
from .exceptions import InvalidConfiguration, MissingFile
2424

2525

2626
CFG: Optional[dict] = None
@@ -154,7 +154,15 @@ def find_configuration() -> Path: # TODO: add tests
154154
return Path(DEFAULT_CFG_PATH)
155155

156156

157-
def get_file_location(location: str, base_path: Optional[str]=None) -> str:
157+
def get_file_location(location: str, base_path: Optional[str]=None, exc: bool=True) -> str:
158+
"""
159+
Lookup a location of a file
160+
161+
:param location: relative or absolute file location or a filename
162+
:param base_path: base path used for resolving relative paths or filenames
163+
:param exc: Flag, raise an exception if the file could not be found/does not exists
164+
:return: resolved path to the given file location
165+
"""
158166
if location.startswith("aura.data."): # Load file as a resource from aura package
159167
return location
160168

@@ -165,9 +173,14 @@ def get_file_location(location: str, base_path: Optional[str]=None) -> str:
165173
pth = Path(base_path) / location
166174
if pth.is_file():
167175
return str(pth)
176+
else:
177+
pth = location
168178

169-
# TODO: use custom exception here so we can log as fatal and sys.exit(1)
170-
raise InvalidConfiguration(f"Can't find configuration file `{location}` using base path `{base_path}`")
179+
if exc:
180+
# TODO: add location and base path directoly to the exception as variables for easy extraction
181+
raise MissingFile(f"Can't find configuration file `{location}` using base path `{base_path}`")
182+
else:
183+
return pth
171184

172185

173186
def get_file_content(location: str, base_path: Optional[str]=None) -> str:
@@ -236,14 +249,14 @@ def load_config():
236249
sys.setrecursionlimit(int(rec_limit))
237250

238251

239-
def get_pypi_stats_path() -> Path:
252+
def get_pypi_stats_path(exc=True) -> Path:
240253
pth = os.environ.get("AURA_PYPI_STATS", None) or CFG["aura"]["pypi_stats"]
241-
return Path(get_file_location(pth, CFG_PATH))
254+
return Path(get_file_location(pth, CFG_PATH, exc=exc))
242255

243256

244-
def get_reverse_dependencies_path() -> Path:
257+
def get_reverse_dependencies_path(exc=True) -> Path:
245258
pth = os.environ.get("AURA_REVERSE_DEPENDENCIES", None) or CFG["aura"]["reverse_dependencies"]
246-
return Path(get_file_location(pth, CFG_PATH))
259+
return Path(get_file_location(pth, CFG_PATH, exc=exc))
247260

248261

249262
def iter_pypi_stats() -> Generator[dict, None, None]:
@@ -253,6 +266,11 @@ def iter_pypi_stats() -> Generator[dict, None, None]:
253266
yield json.loads(line)
254267

255268

269+
def get_cache_mode() -> str:
270+
fallback = CFG.get("cache", {}).get("mode", "auto")
271+
return os.environ.get("AURA_CACHE_MODE", fallback)
272+
273+
256274
def get_maximum_archive_size() ->typing.Optional[int] :
257275
"""
258276
Get settings for a maximum archive file size that can be extracted

aura/data/aura_config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ cache: &cache
216216
# - "ask": ask if cache should be purged when running some commands (aura info, aura update ...)
217217
# - "auto": same as ask but it would purge the cage automatically without asking on specific commands
218218
# - "always": purge cache after every operation. This is same as "auto" + other non-standard operations including `aura scan`, `aura diff`
219-
mode: ask
219+
mode: auto
220220
max-size: 1G
221221
expiration:
222222
default: 72 # 3 days

aura/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class InvalidConfiguration(AuraException, ValueError):
3030
pass
3131

3232

33+
class MissingFile(InvalidLocation):
34+
pass
35+
36+
3337
class ASTNodeRewrite(AuraException):
3438
pass
3539

aura/info.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
jsonschema = None
1414

1515
from . import __version__ as version
16-
from .exceptions import InvalidConfiguration
16+
from .exceptions import MissingFile
1717
from .uri_handlers.base import URIHandler
1818
from . import github
1919
from . import plugins
@@ -35,7 +35,7 @@ def check_pypi_stats() -> dict:
3535
"enabled": True,
3636
"description": "PyPI typosquatting protection enabled"
3737
}
38-
except InvalidConfiguration:
38+
except MissingFile:
3939
pass
4040

4141
return {
@@ -51,7 +51,7 @@ def check_reverse_dependencies() -> dict:
5151
"enabled": True,
5252
"description": "Reverse dependencies dataset present. Package scoring feature is fully enabled"
5353
}
54-
except InvalidConfiguration:
54+
except MissingFile:
5555
pass
5656

5757
return {

aura/package.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from .output import table
3131
from .mirror import LocalMirror
3232
from .type_definitions import ReleaseInfo
33-
from .exceptions import NoSuchPackage
33+
from .exceptions import NoSuchPackage, MissingFile
3434

3535

3636
LOGGER = config.get_logger(__name__)
@@ -78,10 +78,10 @@ def list_packages(cls):
7878
)
7979
return list(repo.list_packages())
8080

81-
def __contains__(self, item):
81+
def __contains__(self, item: str):
8282
return item in self.info["releases"].keys()
8383

84-
def __getitem__(self, item):
84+
def __getitem__(self, item: str):
8585
return self.info[item]
8686

8787
@property
@@ -370,10 +370,17 @@ def score_pypi_downloads(self) -> Union[Value, NA]:
370370
return self.Value(downloads, normalized, "PyPI downloads", explanation)
371371
except ValueError:
372372
pass
373+
except MissingFile:
374+
pass
375+
373376
return PackageScore.NA("PyPI downloads")
374377

375378
def score_reverse_dependencies(self) -> Union[Value, NA]:
376-
dependencies = get_reverse_dependencies(self.package_name)
379+
try:
380+
dependencies = get_reverse_dependencies(self.package_name)
381+
except MissingFile:
382+
return PackageScore.NA("Reverse dependencies")
383+
377384
if not dependencies:
378385
return PackageScore.NA("Reverse dependencies")
379386

@@ -542,7 +549,7 @@ def md5_filter(release: ReleaseInfo, md5: Optional[str]=None) -> bool:
542549

543550
def get_reverse_dependencies(pkg_name: str) -> List[str]:
544551
pkg_name = canonicalize_name(pkg_name)
545-
dataset_path = Path("reverse_dependencies.json")
552+
dataset_path = config.get_reverse_dependencies_path()
546553
with dataset_path.open("r") as fd:
547554
dataset = loads(fd.read())
548555

aura/update.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from click import secho
88

9+
from . import config
910
from . import utils
1011

1112

@@ -30,7 +31,12 @@ def update_dataset():
3031

3132
archive = tarfile.open(fd.name, "r:*")
3233

33-
for f in ("reverse_dependencies.json", "pypi_stats.json"):
34+
data_files = (
35+
config.get_reverse_dependencies_path(exc=False).name,
36+
config.get_pypi_stats_path(exc=False).name
37+
)
38+
39+
for f in data_files:
3440
backup_file(cwd/f)
3541
archive.extract(f, path=cwd)
3642

File renamed without changes.

0 commit comments

Comments
 (0)