def test_strict(self) -> None: with tempfile.TemporaryDirectory() as d: c = FakeCache( d, {("woah", None): WOAH_INDEX_CONTENTS.replace(b"woah-0.1", b"woah")} ) with self.assertRaises(UnexpectedFilename): parse_index("woah", c, strict=True) # type: ignore
def test_error_on_unexpected_filename_regex(self) -> None: with tempfile.TemporaryDirectory() as d: c = FakeCache( d, {("woah", None): re.sub(rb'#.*?"', b'"', WOAH_INDEX_CONTENTS)} ) with self.assertRaises(UnexpectedFilename): parse_index("woah", c, strict=True) # type: ignore
def test_get_entries_json(self) -> None: with tempfile.TemporaryDirectory() as d: c = FakeCache( d, {("woah", "https://pypi.org/pypi/woah/json"): WOAH_JSON_CONTENTS} ) pkg = parse_index("woah", c, use_json=True) # type: ignore self.assertEqual("woah", pkg.name) self.assertEqual(2, len(pkg.releases)) v01 = pkg.releases["0.1"] self.assertEqual(2, len(v01.files)) self.assertEqual( "https://files.pythonhosted.org/packages/69/c9/a9951fcb2e706dd14cfc5d57a33eadc38a2b7477c82c12c229de5f6115db/woah-0.1-py3-none-any.whl", v01.files[0].url, ) self.assertEqual("woah-0.1-py3-none-any.whl", v01.files[0].basename) self.assertEqual( "sha256=e705573ea8a88ec772174deea6a80c79f1e8b7e96130e27eee14b21d63f4e7f8", v01.files[0].checksum, ) self.assertEqual(">=3.6", v01.files[0].requires_python) self.assertEqual( datetime.datetime( 2019, 9, 19, 14, 32, 17, 358350, tzinfo=datetime.timezone.utc ), v01.files[0].upload_time, )
def list(package_name: str) -> None: package = parse_index(package_name) print(f"package {package.name}") print("releases:") for k, v in package.releases.items(): print(f" {k}:") for f in v.files: print(f" {f.basename}")
def test_non_strict(self) -> None: with tempfile.TemporaryDirectory() as d: c = FakeCache( d, {("woah", None): WOAH_INDEX_CONTENTS.replace(b"woah-0.1", b"woah")} ) pkg = parse_index("woah", c, strict=False) # type: ignore self.assertEqual(1, len(pkg.releases)) v02 = pkg.releases["0.2"] self.assertEqual(2, len(v02.files))
def native(verbose: bool, fresh: bool, package_name: str, version: str) -> None: package = parse_index(package_name, fresh=fresh) if version == "latest": if not package.releases: raise click.ClickException("No releases at all") version = sorted(package.releases, key=pkg_resources.parse_version)[-1] if verbose: click.echo(f"check {package_name} {version}") if has_nativemodules(package, version, verbose=verbose): sys.exit(1)
def check(verbose: bool, fresh: bool, nouse_json: bool, package_name: str) -> None: with Cache(fresh_index=fresh) as cache: package_name, operator, version = package_name.partition("==") package = parse_index(package_name, cache, use_json=not nouse_json) selected_versions = select_versions(package, operator, version) if verbose: click.echo(f"check {package_name} {selected_versions}") rc = 0 for v in selected_versions: rc |= run_checker(package, v, verbose=verbose, cache=cache) if rc != 0: sys.exit(rc)
def check(verbose: bool, fresh: bool, package_name: str, version: str) -> None: package = parse_index(package_name, fresh=fresh) if version == "latest": if not package.releases: raise click.ClickException("No releases at all") version = sorted(package.releases, key=pkg_resources.parse_version)[-1] if verbose: click.echo(f"check {package_name} {version}") rc = 0 if version == "*": for v in sorted(package.releases, key=pkg_resources.parse_version): rc |= run_checker(package, v, verbose=verbose) else: rc |= run_checker(package, version, verbose=verbose) if rc != 0: sys.exit(rc)
def license(verbose: bool, fresh: bool, nouse_json: bool, package_name: str) -> None: with Cache(fresh_index=fresh) as cache: package_name, operator, version = package_name.partition("==") package = parse_index(package_name, cache, use_json=not nouse_json) selected_versions = select_versions(package, operator, version) if verbose: click.echo(f"check {package_name} {selected_versions}") rc = 0 for v in selected_versions: license = guess_license(package, v, verbose=verbose, cache=cache) if license is not None and not isinstance(license, str): license = license.shortname if license is None: rc |= 1 print(f"{package_name}=={v}: {license or 'Unknown'}") if rc != 0: sys.exit(rc)
def test_get_entries(self, mock_fetch: Any) -> None: with tempfile.NamedTemporaryFile(mode="wb") as f: f.write(WOAH_INDEX_CONTENTS) f.flush() mock_fetch.return_value = Path(f.name) pkg = parse_index("woah") self.assertEqual("woah", pkg.name) self.assertEqual(2, len(pkg.releases)) v01 = pkg.releases["0.1"] self.assertEqual(2, len(v01.files)) self.assertEqual( "https://files.pythonhosted.org/packages/69/c9/a9951fcb2e706dd14cfc5d57a33eadc38a2b7477c82c12c229de5f6115db/woah-0.1-py3-none-any.whl", v01.files[0].url, ) self.assertEqual("woah-0.1-py3-none-any.whl", v01.files[0].basename) self.assertEqual( "sha256=e705573ea8a88ec772174deea6a80c79f1e8b7e96130e27eee14b21d63f4e7f8", v01.files[0].checksum, )
def test_get_entries(self) -> None: with tempfile.TemporaryDirectory() as d: c = FakeCache(d, {("woah", None): WOAH_INDEX_CONTENTS}) pkg = parse_index("woah", c) # type: ignore self.assertEqual("woah", pkg.name) self.assertEqual(2, len(pkg.releases)) v01 = pkg.releases["0.1"] self.assertEqual(2, len(v01.files)) self.assertEqual( "https://files.pythonhosted.org/packages/69/c9/a9951fcb2e706dd14cfc5d57a33eadc38a2b7477c82c12c229de5f6115db/woah-0.1-py3-none-any.whl", v01.files[0].url, ) self.assertEqual("woah-0.1-py3-none-any.whl", v01.files[0].basename) self.assertEqual( "sha256=e705573ea8a88ec772174deea6a80c79f1e8b7e96130e27eee14b21d63f4e7f8", v01.files[0].checksum, ) self.assertEqual(">=3.6", v01.files[0].requires_python) self.assertEqual(None, v01.files[0].upload_time)
def __init__( self, path: Path, variable: List[str], fixed: List[str], command: str, extend: List[str], fast: bool, ) -> None: self.path = path self.command = command self.extend = extend self.fast = fast self.names: Set[str] = set() self.packages: Dict[str, Package] = {} self.versions: Dict[str, List[Version]] = {} env = EnvironmentMarkers.for_python( ".".join(map(str, sys.version_info[:3])), sys.platform) self.pip_lines = [line for line in fixed if self._is_pip_line(line)] fixed = [line for line in fixed if not self._is_pip_line(line)] for req_str in [*fixed, *variable]: req = Requirement(req_str) if req.marker and not env.match(req.marker): continue self.names.add(canonicalize_name(req.name)) with Cache(fresh_index=True) as cache: # First fetch "fixed" and see how many match: # 0: that's an error # 1: great! # >1: warning, and pick the newest (because that's what CI is likely # to do; open to other ideas here though) for req_str in fixed: req = Requirement(req_str) if req.marker and not env.match(req.marker): continue name = canonicalize_name(req.name) pkg = parse_index(name, cache, use_json=True) self.packages[name] = pkg versions: List[Version] = list( req.specifier.filter(pkg.releases.keys()) # type: ignore ) if len(versions) == 0: raise DepError( "No versions match {req_str!r}; maybe pre-only?") if len(versions) > 1: LOG.warning( f"More than one version matched {req_str!r}; picking one arbitrarily." ) self.versions[name] = [versions[-1]] LOG.info( f" [fixed] fetched {req.name}: {len(versions)}/{len(pkg.releases)} allowed; keeping {versions[-1]!r}" ) for req_str in variable: req = Requirement(req_str) if req.marker and not env.match(req.marker): continue name = canonicalize_name(req.name) pkg = parse_index(name, cache, use_json=True) self.packages[name] = pkg if name in self.extend or "*" in self.extend: versions = list(pkg.releases.keys()) # type: ignore else: versions = list( req.specifier.filter( pkg.releases.keys()) # type: ignore ) LOG.info( f" [variable] fetched {name}: {len(versions)}/{len(pkg.releases)} allowed" ) if len(versions) == 0: raise DepError( "No versions match {req_str!r}; maybe pre-only?") if name in versions: # Presumably this came from being in 'fixed' too; not being # in 'variable' twice. If so it will only have one version. if self.versions[name][0] not in versions: LOG.warning( f" [variable] fixed version {self.versions[name][0]!r} not in {versions!r} for {req_str!r}" ) LOG.info( f" [variable] widen due to variable: {req_str!r} -> {versions!r}" ) if fast: if len(versions) == 1: self.versions[name] = [versions[0]] else: # zero-length already raised DepError self.versions[name] = [versions[0], versions[-1]] else: self.versions[name] = versions