True solution requires a N:M multi-map because two strings should map to one. And it has a interesting case of modifying the list with version numbers being removed and added, which requires logical analysis not just syntax.

Before

1#!/usr/bin/env python
2#
3# Copyright (c) nexB Inc. and others. All rights reserved.
4# ScanCode is a trademark of nexB Inc.
5# SPDX-License-Identifier: Apache-2.0
6# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
7# See https://github.com/aboutcode-org/skeleton for support or download.
8# See https://aboutcode.org for more information about nexB OSS projects.
…lines 9–20 unchanged (12 lines)
21
22import attr
23import license_expression
24import packageurl
25import requests
26import saneyaml
27import utils_pip_compatibility_tags
28from commoncode import fileutils
29from commoncode.hash import multi_checksums
30from commoncode.text import python_safe_name
31from packvers import tags as packaging_tags
32from packvers import version as packaging_version
33
…lines 34–87 unchanged (54 lines)
88
89"""
90Wheel downloader
91
92- parse requirement file
93- create a TODO queue of requirements to process
94- done: create an empty map of processed binary requirements as
95 {package name: (list of versions/tags}
96
97
98- while we have package reqs in TODO queue, process one requirement:
99 - for each PyPI simple index:
100 - fetch through cache the PyPI simple index for this package
101 - for each environment:
…lines 102–110 unchanged (9 lines)
111
112TRACE = False
113TRACE_DEEP = False
114TRACE_ULTRA_DEEP = False
115
116# Supported environments
117PYTHON_VERSIONS = "37", "38", "39", "310"
118
119PYTHON_DOT_VERSIONS_BY_VER = {
120 "37": "3.7",
121 "38": "3.8",
122 "39": "3.9",
123 "310": "3.10",
124}
125
126
127def get_python_dot_version(version):
128 """
129 Return a dot version from a plain, non-dot version.
130 """
131 return PYTHON_DOT_VERSIONS_BY_VER[version]
132
133
134ABIS_BY_PYTHON_VERSION = {
135 "37": ["cp37", "cp37m", "abi3"],
136 "38": ["cp38", "cp38m", "abi3"],
137 "39": ["cp39", "cp39m", "abi3"],
138 "310": ["cp310", "cp310m", "abi3"],
139}
140
141PLATFORMS_BY_OS = {
142 "linux": [
143 "linux_x86_64",
144 "manylinux1_x86_64",
145 "manylinux2010_x86_64",
…lines 146–549 unchanged (404 lines)
550
551 def download(self, dest_dir=THIRDPARTY_DIR):
552 """
553 Download this distribution into `dest_dir` directory.
554 Return the fetched filename.
555 """
556 if not self.filename:
557 raise ValueError(f"self.filename has no value but is required: {self.filename!r}")
558 if TRACE_DEEP:
559 print(
560 f"Fetching distribution of {self.name}=={self.version}:",
561 self.filename,
562 )
563
…lines 564–818 unchanged (255 lines)
819 """
820 Fetch license files if missing in `dest_dir`.
821 Return True if license files were fetched.
822 """
823 urls = LinksRepository.from_url(use_cached_index=use_cached_index).links
824 errors = []
825 extra_lic_names = [lic.get("file") for lic in self.extra_data.get("licenses", {})]
826 extra_lic_names += [self.extra_data.get("license_file")]
827 extra_lic_names = [eln for eln in extra_lic_names if eln]
828 lic_names = [f"{key}.LICENSE" for key in self.get_license_keys()]
829 for filename in lic_names + extra_lic_names:
830 floc = os.path.join(dest_dir, filename)
831 if os.path.exists(floc):
832 continue
833
…lines 834–840 unchanged (7 lines)
841 filename=filename,
842 as_text=True,
843 )
844 if TRACE:
845 print(f"Fetched license from remote: {lic_url}")
846
847 except Exception:
848 try:
849 # try licensedb second
850 lic_url = f"{LICENSEDB_API_URL}/{filename}"
851 fetch_and_save(
852 path_or_url=lic_url,
853 dest_dir=dest_dir,
854 filename=filename,
855 as_text=True,
856 )
857 if TRACE:
858 print(f"Fetched license from licensedb: {lic_url}")
859
860 except Exception:
861 msg = f"No text for license {filename} in expression "
862 f"{self.license_expression!r} from {self}"
863 print(msg)
864 errors.append(msg)
865
866 return errors
867
868 def extract_pkginfo(self, dest_dir=THIRDPARTY_DIR):
…lines 869–995 unchanged (127 lines)
996def get_license_link_for_filename(filename, urls):
997 """
998 Return a link for `filename` found in the `links` list of URLs or paths. Raise an
999 exception if no link is found or if there are more than one link for that
1000 file name.
1001 """
1002 path_or_url = [url for url in urls if url.endswith(f"/{filename}")]
1003 if not path_or_url:
1004 raise Exception(f"Missing link to file: {filename}")
1005 if not len(path_or_url) == 1:
1006 raise Exception(f"Multiple links to file: {filename}: \n" + "\n".join(path_or_url))
1007 return path_or_url[0]
1008
…lines 1009–1284 unchanged (276 lines)
1285 return "py3" in self.python_versions and "none" in self.abis and "any" in self.platforms
1286
1287
1288def is_pure_wheel(filename):
1289 try:
1290 return Wheel.from_filename(filename).is_pure()
1291 except Exception:
1292 return False
1293
1294
1295@attr.attributes
1296class PypiPackage(NameVer):
1297 """
…lines 1298–1480 unchanged (183 lines)
1481 def get_distributions(self):
1482 """
1483 Yield all distributions available for this PypiPackage
1484 """
1485 if self.sdist:
1486 yield self.sdist
1487 yield from self.wheels
1488
1489 def get_url_for_filename(self, filename):
1490 """
1491 Return the URL for this filename or None.
1492 """
1493 for dist in self.get_distributions():
…lines 1494–1609 unchanged (116 lines)
1610 # the inner versions mapping is sorted by version from oldest to newest
1611
1612 packages = attr.ib(
1613 type=dict,
1614 default=attr.Factory(lambda: defaultdict(dict)),
1615 metadata=dict(
1616 help="Mapping of {name: {version: PypiPackage, version: PypiPackage, etc} "
1617 "available in this repo"
1618 ),
1619 )
1620
1621 fetched_package_normalized_names = attr.ib(
1622 type=set,
1623 default=attr.Factory(set),
1624 metadata=dict(help="A set of already fetched package normalized names."),
1625 )
1626
1627 use_cached_index = attr.ib(
1628 type=bool,
1629 default=False,
1630 metadata=dict(
1631 help="If True, use any existing on-disk cached PyPI index files. "
1632 "Otherwise, fetch and cache."
1633 ),
1634 )
1635
1636 def _get_package_versions_map(self, name):
1637 """
1638 Return a mapping of all available PypiPackage version for this package name.
1639 The mapping may be empty. It is ordered by version from oldest to newest
1640 """
1641 if not name:
1642 raise ValueError(f"name is required: {name!r}")
1643 normalized_name = NameVer.normalize_name(name)
1644 versions = self.packages[normalized_name]
1645 if not versions and normalized_name not in self.fetched_package_normalized_names:
1646 self.fetched_package_normalized_names.add(normalized_name)
1647 try:
1648 links = self.fetch_links(normalized_name=normalized_name)
…lines 1649–1690 unchanged (42 lines)
1691 path_or_url=package_url,
1692 as_text=True,
1693 force=not self.use_cached_index,
1694 )
1695 links = collect_urls(text)
1696 # TODO: keep sha256
1697 links = [link.partition("#sha256=") for link in links]
1698 links = [url for url, _, _sha256 in links]
1699 return links
1700
1701
1702PYPI_PUBLIC_REPO = PypiSimpleRepository(index_url=PYPI_SIMPLE_URL)
1703PYPI_SELFHOSTED_REPO = PypiSimpleRepository(index_url=ABOUT_PYPI_SIMPLE_URL)
…lines 1704–1911 unchanged (208 lines)
1912 time.sleep(_delay)
1913 headers = headers or {}
1914 # using a GET with stream=True ensure we get the the final header from
1915 # several redirects and that we can ignore content there. A HEAD request may
1916 # not get us this last header
1917 print(f" DOWNLOADING: {url}")
1918 with requests.get(url, allow_redirects=True, stream=True, headers=headers) as response: # noqa: S113
1919 status = response.status_code
1920 if status != requests.codes.ok: # NOQA
1921 if status == 429 and _delay < 20:
1922 # too many requests: start some exponential delay
1923 increased_delay = (_delay * 2) or 1
1924
…lines 1925–2130 unchanged (206 lines)
2131 """
2132 Call args in a subprocess and display output on the fly if ``trace`` is True.
2133 Return a tuple of (returncode, stdout, stderr)
2134 """
2135 if TRACE_DEEP:
2136 print("Calling:", " ".join(args))
2137 with subprocess.Popen( # noqa: S603
2138 args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8"
2139 ) as process:
2140 stdouts = []
2141 while True:
2142 line = process.stdout.readline()
2143 if not line and process.poll() is not None:
…lines 2144–2195 unchanged (52 lines)
2196
2197 cli_args.extend(requirements_specifiers)
2198 for req_file in requirements_files:
2199 cli_args.extend(["--requirement", req_file])
2200
2201 if TRACE:
2202 print("Downloading wheels using command:", " ".join(cli_args))
2203
2204 existing = set(os.listdir(dest_dir))
2205 error = False
2206 try:
2207 returncode, _stdout, stderr = call(cli_args, verbose=True)
2208 if returncode != 0:
…lines 2209–2228 unchanged (20 lines)
2229#
2230################################################################################
2231
2232
2233def check_about(dest_dir=THIRDPARTY_DIR):
2234 try:
2235 subprocess.check_output(f"venv/bin/about check {dest_dir}".split()) # noqa: S603
2236 except subprocess.CalledProcessError as cpe:
2237 print()
2238 print("Invalid ABOUT files:")
2239 print(cpe.output.decode("utf-8", errors="replace"))
2240
2241
…lines 2242–2279 unchanged (38 lines)
2280 try:
2281 from packagedcode.licensing import get_only_expression_from_extracted_license
2282
2283 return get_only_expression_from_extracted_license(declared_licenses)
2284 except ImportError:
2285 # Scancode is not installed, clean and join all the licenses
2286 lics = [python_safe_name(lic).lower() for lic in declared_licenses]
2287 return " AND ".join(lics).lower()
2288

After

1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3#
4# Copyright (c) nexB Inc. and others. All rights reserved.
5# ScanCode is a trademark of nexB Inc.
6# SPDX-License-Identifier: Apache-2.0
7# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
8# See https://github.com/aboutcode-org/skeleton for support or download.
…lines 9–27 unchanged (19 lines)
28from commoncode import fileutils
29from commoncode.hash import multi_checksums
30from commoncode.text import python_safe_name
31from packvers import tags as packaging_tags
32from packvers import version as packaging_version
33
34import utils_pip_compatibility_tags
35
36"""
37Utilities to manage Python thirparty libraries source, binaries and metadata in
38local directories and remote repositories.
39
40- download wheels for packages for all each supported operating systems
…lines 41–85 unchanged (45 lines)
86The Wheel models code is partially derived from the mit-licensed pip and the
87Distribution/Wheel/Sdist design has been heavily inspired by the packaging-
88dists library https://github.com/uranusjr/packaging-dists by Tzu-ping Chung
89"""
90
91"""
92Wheel downloader
93
94- parse requirement file
95- create a TODO queue of requirements to process
96- done: create an empty map of processed binary requirements as {package name: (list of versions/tags}
97
98
…lines 99–111 unchanged (13 lines)
112
113TRACE = False
114TRACE_DEEP = False
115TRACE_ULTRA_DEEP = False
116
117# Supported environments
118PYTHON_VERSIONS = "39", "310", "311", "312", "313"
119
120PYTHON_DOT_VERSIONS_BY_VER = {
121 "39": "3.9",
122 "310": "3.10",
123 "311": "3.11",
124 "312": "3.12",
125 "313": "3.13",
126}
127
128
129def get_python_dot_version(version):
130 """
131 Return a dot version from a plain, non-dot version.
132 """
133 return PYTHON_DOT_VERSIONS_BY_VER[version]
134
135
136ABIS_BY_PYTHON_VERSION = {
137 "39": ["cp39", "cp39m", "abi3"],
138 "310": ["cp310", "cp310m", "abi3"],
139 "311": ["cp311", "cp311m", "abi3"],
140 "312": ["cp312", "cp312m", "abi3"],
141 "313": ["cp313", "cp313m", "abi3"],
142}
143
144PLATFORMS_BY_OS = {
145 "linux": [
146 "linux_x86_64",
147 "manylinux1_x86_64",
…lines 148–552 unchanged (405 lines)
553
554 def download(self, dest_dir=THIRDPARTY_DIR):
555 """
556 Download this distribution into `dest_dir` directory.
557 Return the fetched filename.
558 """
559 assert self.filename
560 if TRACE_DEEP:
561 print(
562 f"Fetching distribution of {self.name}=={self.version}:",
563 self.filename,
564 )
565
566 # FIXME:
…lines 567–820 unchanged (254 lines)
821 """
822 Fetch license files if missing in `dest_dir`.
823 Return True if license files were fetched.
824 """
825 urls = LinksRepository.from_url(use_cached_index=use_cached_index).links
826 errors = []
827 extra_lic_names = [l.get("file") for l in self.extra_data.get("licenses", {})]
828 extra_lic_names += [self.extra_data.get("license_file")]
829 extra_lic_names = [ln for ln in extra_lic_names if ln]
830 lic_names = [f"{key}.LICENSE" for key in self.get_license_keys()]
831 for filename in lic_names + extra_lic_names:
832 floc = os.path.join(dest_dir, filename)
833 if os.path.exists(floc):
834 continue
835
…lines 836–842 unchanged (7 lines)
843 filename=filename,
844 as_text=True,
845 )
846 if TRACE:
847 print(f"Fetched license from remote: {lic_url}")
848
849 except:
850 try:
851 # try licensedb second
852 lic_url = f"{LICENSEDB_API_URL}/{filename}"
853 fetch_and_save(
854 path_or_url=lic_url,
855 dest_dir=dest_dir,
856 filename=filename,
857 as_text=True,
858 )
859 if TRACE:
860 print(f"Fetched license from licensedb: {lic_url}")
861
862 except:
863 msg = f'No text for license {filename} in expression "{self.license_expression}" from {self}'
864 print(msg)
865 errors.append(msg)
866
867 return errors
868
869 def extract_pkginfo(self, dest_dir=THIRDPARTY_DIR):
…lines 870–996 unchanged (127 lines)
997def get_license_link_for_filename(filename, urls):
998 """
999 Return a link for `filename` found in the `links` list of URLs or paths. Raise an
1000 exception if no link is found or if there are more than one link for that
1001 file name.
1002 """
1003 path_or_url = [l for l in urls if l.endswith(f"/{filename}")]
1004 if not path_or_url:
1005 raise Exception(f"Missing link to file: {filename}")
1006 if not len(path_or_url) == 1:
1007 raise Exception(f"Multiple links to file: {filename}: \n" + "\n".join(path_or_url))
1008 return path_or_url[0]
1009
…lines 1010–1285 unchanged (276 lines)
1286 return "py3" in self.python_versions and "none" in self.abis and "any" in self.platforms
1287
1288
1289def is_pure_wheel(filename):
1290 try:
1291 return Wheel.from_filename(filename).is_pure()
1292 except:
1293 return False
1294
1295
1296@attr.attributes
1297class PypiPackage(NameVer):
1298 """
…lines 1299–1481 unchanged (183 lines)
1482 def get_distributions(self):
1483 """
1484 Yield all distributions available for this PypiPackage
1485 """
1486 if self.sdist:
1487 yield self.sdist
1488 for wheel in self.wheels:
1489 yield wheel
1490
1491 def get_url_for_filename(self, filename):
1492 """
1493 Return the URL for this filename or None.
1494 """
1495 for dist in self.get_distributions():
…lines 1496–1611 unchanged (116 lines)
1612 # the inner versions mapping is sorted by version from oldest to newest
1613
1614 packages = attr.ib(
1615 type=dict,
1616 default=attr.Factory(lambda: defaultdict(dict)),
1617 metadata=dict(
1618 help="Mapping of {name: {version: PypiPackage, version: PypiPackage, etc} available in this repo"
1619 ),
1620 )
1621
1622 fetched_package_normalized_names = attr.ib(
1623 type=set,
1624 default=attr.Factory(set),
1625 metadata=dict(help="A set of already fetched package normalized names."),
1626 )
1627
1628 use_cached_index = attr.ib(
1629 type=bool,
1630 default=False,
1631 metadata=dict(
1632 help="If True, use any existing on-disk cached PyPI index files. Otherwise, fetch and cache."
1633 ),
1634 )
1635
1636 def _get_package_versions_map(self, name):
1637 """
1638 Return a mapping of all available PypiPackage version for this package name.
1639 The mapping may be empty. It is ordered by version from oldest to newest
1640 """
1641 assert name
1642 normalized_name = NameVer.normalize_name(name)
1643 versions = self.packages[normalized_name]
1644 if not versions and normalized_name not in self.fetched_package_normalized_names:
1645 self.fetched_package_normalized_names.add(normalized_name)
1646 try:
1647 links = self.fetch_links(normalized_name=normalized_name)
1648 # note that thsi is sorted so the mapping is also sorted
…lines 1649–1689 unchanged (41 lines)
1690 path_or_url=package_url,
1691 as_text=True,
1692 force=not self.use_cached_index,
1693 )
1694 links = collect_urls(text)
1695 # TODO: keep sha256
1696 links = [l.partition("#sha256=") for l in links]
1697 links = [url for url, _, _sha256 in links]
1698 return links
1699
1700
1701PYPI_PUBLIC_REPO = PypiSimpleRepository(index_url=PYPI_SIMPLE_URL)
1702PYPI_SELFHOSTED_REPO = PypiSimpleRepository(index_url=ABOUT_PYPI_SIMPLE_URL)
…lines 1703–1911 unchanged (209 lines)
1912 headers = headers or {}
1913 # using a GET with stream=True ensure we get the the final header from
1914 # several redirects and that we can ignore content there. A HEAD request may
1915 # not get us this last header
1916 print(f" DOWNLOADING: {url}")
1917 with requests.get(url, allow_redirects=True, stream=True, headers=headers) as response:
1918 status = response.status_code
1919 if status != requests.codes.ok: # NOQA
1920 if status == 429 and _delay < 20:
1921 # too many requests: start some exponential delay
1922 increased_delay = (_delay * 2) or 1
1923
1924 return get_remote_file_content(
…lines 1925–2130 unchanged (206 lines)
2131 Call args in a subprocess and display output on the fly if ``trace`` is True.
2132 Return a tuple of (returncode, stdout, stderr)
2133 """
2134 if TRACE_DEEP:
2135 print("Calling:", " ".join(args))
2136 with subprocess.Popen(
2137 args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding="utf-8"
2138 ) as process:
2139 stdouts = []
2140 while True:
2141 line = process.stdout.readline()
2142 if not line and process.poll() is not None:
2143 break
…lines 2144–2194 unchanged (51 lines)
2195
2196 cli_args.extend(requirements_specifiers)
2197 for req_file in requirements_files:
2198 cli_args.extend(["--requirement", req_file])
2199
2200 if TRACE:
2201 print(f"Downloading wheels using command:", " ".join(cli_args))
2202
2203 existing = set(os.listdir(dest_dir))
2204 error = False
2205 try:
2206 returncode, _stdout, stderr = call(cli_args, verbose=True)
2207 if returncode != 0:
…lines 2208–2228 unchanged (21 lines)
2229################################################################################
2230
2231
2232def check_about(dest_dir=THIRDPARTY_DIR):
2233 try:
2234 subprocess.check_output(f"venv/bin/about check {dest_dir}".split())
2235 except subprocess.CalledProcessError as cpe:
2236 print()
2237 print("Invalid ABOUT files:")
2238 print(cpe.output.decode("utf-8", errors="replace"))
2239
2240
2241def find_problems(
…lines 2242–2278 unchanged (37 lines)
2279 try:
2280 from packagedcode.licensing import get_only_expression_from_extracted_license
2281
2282 return get_only_expression_from_extracted_license(declared_licenses)
2283 except ImportError:
2284 # Scancode is not installed, clean and join all the licenses
2285 lics = [python_safe_name(l).lower() for l in declared_licenses]
2286 return " AND ".join(lics).lower()
2287

Before

module
comment "#!/usr/bin/env python"
comment "#"
comment "# Copyright (c) nexB Inc. and others. All rights reserved."
comment "# ScanCode is a trademark of nexB Inc."
comment "# SPDX-License-Identifier: Apache-2.0"
comment "# See http://www.apache.org/licenses/LICENSE-2.0 for the lic"...
comment "# See https://github.com/aboutcode-org/skeleton for support "...
comment "# See https://aboutcode.org for more information about nexB "...
comment "#"
import_statement
import "import"
dotted_name
identifier "email"
import_statement
import "import"
dotted_name
identifier "itertools"
import_statement
import "import"
dotted_name
identifier "os"
import_statement
import "import"
dotted_name
identifier "re"
import_statement
import "import"
dotted_name
identifier "shutil"
import_statement
import "import"
dotted_name
identifier "subprocess"
import_statement
import "import"
dotted_name
identifier "tempfile"
import_statement
import "import"
dotted_name
identifier "time"
import_statement
import "import"
dotted_name
identifier "urllib"
import_from_statement
from "from"
dotted_name
identifier "collections"
import "import"
dotted_name
identifier "defaultdict"
import_from_statement
from "from"
dotted_name
identifier "urllib"
. "."
identifier "parse"
import "import"
dotted_name
identifier "quote_plus"
import_statement
import "import"
dotted_name
identifier "attr"
import_statement
import "import"
dotted_name
identifier "license_expression"
import_statement
import "import"
dotted_name
identifier "packageurl"
import_statement
import "import"
dotted_name
identifier "requests"
import_statement
import "import"
dotted_name
identifier "saneyaml"
import_statement
import "import"
dotted_name
identifier "utils_pip_compatibility_tags"
import_from_statement
from "from"
dotted_name
identifier "commoncode"
import "import"
dotted_name
identifier "fileutils"
import_from_statement
from "from"
dotted_name
identifier "commoncode"
. "."
identifier "hash"
import "import"
dotted_name
identifier "multi_checksums"
import_from_statement
from "from"
dotted_name
identifier "commoncode"
. "."
identifier "text"
import "import"
dotted_name
identifier "python_safe_name"
import_from_statement
from "from"
dotted_name
identifier "packvers"
import "import"
aliased_import
dotted_name
identifier "tags"
as "as"
identifier "packaging_tags"
import_from_statement
from "from"
dotted_name
identifier "packvers"
import "import"
aliased_import
dotted_name
identifier "version"
as "as"
identifier "packaging_version"
expression_statement
string
string_start "\"\"\""
string_content "\nUtilities to manage Python thirparty libraries source, bina"...
string_end "\"\"\""
expression_statement
string
string_start "\"\"\""
string_content "\nWheel downloader\n\n- parse requirement file\n- create a TODO "...
string_end "\"\"\""
expression_statement
assignment
identifier "TRACE"
= "="
false "False"
expression_statement
assignment
identifier "TRACE_DEEP"
= "="
false "False"
expression_statement
assignment
identifier "TRACE_ULTRA_DEEP"
= "="
false "False"
comment "# Supported environments"
expression_statement
assignment
identifier "PYTHON_VERSIONS"
= "="
expression_list
string
string_start "\""
string_content "37"
string_end "\""
, ","
string
string_start "\""
string_content "38"
string_end "\""
, ","
string
string_start "\""
string_content "39"
string_end "\""
, ","
string
string_start "\""
string_content "310"
string_end "\""
expression_statement
assignment
identifier "PYTHON_DOT_VERSIONS_BY_VER"
= "="
dictionary
{ "{"
pair
string
string_start "\""
string_content "37"
string_end "\""
: ":"
string
string_start "\""
string_content "3.7"
string_end "\""
, ","
pair
string
string_start "\""
string_content "38"
string_end "\""
: ":"
string
string_start "\""
string_content "3.8"
string_end "\""
, ","
pair
string
string_start "\""
string_content "39"
string_end "\""
: ":"
string
string_start "\""
string_content "3.9"
string_end "\""
, ","
pair
string
string_start "\""
string_content "310"
string_end "\""
: ":"
string
string_start "\""
string_content "3.10"
string_end "\""
, ","
} "}"
function_definition (+21 nodes collapsed)
expression_statement
assignment
identifier "ABIS_BY_PYTHON_VERSION"
= "="
dictionary
{ "{"
pair
string
string_start "\""
string_content "37"
string_end "\""
: ":"
list
[ "["
string
string_start "\""
string_content "cp37"
string_end "\""
, ","
string
string_start "\""
string_content "cp37m"
string_end "\""
, ","
string
string_start "\""
string_content "abi3"
string_end "\""
] "]"
, ","
pair
string
string_start "\""
string_content "38"
string_end "\""
: ":"
list
[ "["
string
string_start "\""
string_content "cp38"
string_end "\""
, ","
string
string_start "\""
string_content "cp38m"
string_end "\""
, ","
string
string_start "\""
string_content "abi3"
string_end "\""
] "]"
, ","
pair (+23 nodes collapsed)
, ","
pair (+23 nodes collapsed)
, ","
} "}"
expression_statement (+203 nodes collapsed)
expression_statement
assignment
identifier "THIRDPARTY_DIR"
= "="
string
string_start "\""
string_content "thirdparty"
string_end "\""
expression_statement
assignment
identifier "CACHE_THIRDPARTY_DIR"
= "="
string
string_start "\""
string_content ".cache/thirdparty"
string_end "\""
comment "############################################################"...
expression_statement
assignment
identifier "ABOUT_BASE_URL"
= "="
string
string_start "\""
string_content "https://thirdparty.aboutcode.org/pypi"
string_end "\""
expression_statement
assignment
identifier "ABOUT_PYPI_SIMPLE_URL"
= "="
string
string_start "f\""
interpolation
{ "{"
identifier "ABOUT_BASE_URL"
} "}"
string_content "/simple"
string_end "\""
expression_statement
assignment
identifier "ABOUT_LINKS_URL"
= "="
string
string_start "f\""
interpolation
{ "{"
identifier "ABOUT_PYPI_SIMPLE_URL"
} "}"
string_content "/links.html"
string_end "\""
expression_statement
assignment
identifier "PYPI_SIMPLE_URL"
= "="
string
string_start "\""
string_content "https://pypi.org/simple"
string_end "\""
expression_statement
assignment
identifier "PYPI_INDEX_URLS"
= "="
tuple
( "("
identifier "PYPI_SIMPLE_URL"
, ","
identifier "ABOUT_PYPI_SIMPLE_URL"
) ")"
comment "############################################################"...
expression_statement
assignment
identifier "EXTENSIONS_APP"
= "="
tuple
( "("
string
string_start "\""
string_content ".pyz"
string_end "\""
, ","
) ")"
expression_statement (+22 nodes collapsed)
expression_statement
assignment
identifier "EXTENSIONS_INSTALLABLE"
= "="
binary_operator
identifier "EXTENSIONS_SDIST"
+ "+"
tuple
( "("
string
string_start "\""
string_content ".whl"
string_end "\""
, ","
) ")"
expression_statement (+22 nodes collapsed)
expression_statement
assignment
identifier "EXTENSIONS"
= "="
binary_operator
binary_operator
identifier "EXTENSIONS_INSTALLABLE"
+ "+"
identifier "EXTENSIONS_ABOUT"
+ "+"
identifier "EXTENSIONS_APP"
expression_statement
assignment
identifier "LICENSEDB_API_URL"
= "="
string
string_start "\""
string_content "https://scancode-licensedb.aboutcode.org"
string_end "\""
expression_statement
assignment
identifier "LICENSING"
= "="
call
attribute
identifier "license_expression"
. "."
identifier "Licensing"
argument_list
( "("
) ")"
expression_statement
assignment
identifier "collect_urls"
= "="
attribute
call
attribute
identifier "re"
. "."
identifier "compile"
argument_list
( "("
string
string_start "'"
string_content "href=\"([^\"]+)\""
string_end "'"
) ")"
. "."
identifier "findall"
comment "############################################################"...
comment "# Fetch wheels and sources locally"
comment "############################################################"...
class_definition
class "class"
identifier "DistributionNotFound"
argument_list
( "("
identifier "Exception"
) ")"
: ":"
block
pass_statement
pass "pass"
function_definition (+275 nodes collapsed)
function_definition (+233 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# Core models"
comment "#"
comment "############################################################"...
decorated_definition (+227 nodes collapsed)
decorated_definition
decorator
@ "@"
attribute
identifier "attr"
. "."
identifier "attributes"
class_definition
class "class"
identifier "Distribution"
argument_list
( "("
identifier "NameVer"
) ")"
: ":"
comment "# field names that can be updated from another Distribution "...
block
expression_statement (+42 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+43 nodes collapsed)
expression_statement (+46 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+51 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+46 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+51 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+51 nodes collapsed)
decorated_definition (+81 nodes collapsed)
decorated_definition (+23 nodes collapsed)
function_definition (+179 nodes collapsed)
function_definition
def "def"
identifier "download"
parameters
( "("
identifier "self"
, ","
default_parameter
identifier "dest_dir"
= "="
identifier "THIRDPARTY_DIR"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Download this distribution into `dest_dir` director"...
string_end "\"\"\""
if_statement
if "if"
not_operator
not "not"
attribute
identifier "self"
. "."
identifier "filename"
: ":"
block
raise_statement
raise "raise"
call
identifier "ValueError"
argument_list
( "("
string
string_start "f\""
string_content "self.filename has no value but is required: "
interpolation
{ "{"
attribute
identifier "self"
. "."
identifier "filename"
type_conversion "!r"
} "}"
string_end "\""
) ")"
if_statement (+37 nodes collapsed)
comment "# FIXME:"
expression_statement (+32 nodes collapsed)
return_statement
return "return"
attribute
identifier "self"
. "."
identifier "filename"
decorated_definition (+26 nodes collapsed)
decorated_definition (+30 nodes collapsed)
decorated_definition (+26 nodes collapsed)
decorated_definition (+30 nodes collapsed)
decorated_definition (+71 nodes collapsed)
decorated_definition (+70 nodes collapsed)
decorated_definition (+71 nodes collapsed)
function_definition (+50 nodes collapsed)
function_definition (+235 nodes collapsed)
function_definition (+49 nodes collapsed)
function_definition (+248 nodes collapsed)
function_definition (+411 nodes collapsed)
function_definition (+176 nodes collapsed)
function_definition (+94 nodes collapsed)
function_definition (+42 nodes collapsed)
function_definition (+100 nodes collapsed)
function_definition (+60 nodes collapsed)
function_definition
def "def"
identifier "fetch_license_files"
parameters
( "("
identifier "self"
, ","
default_parameter
identifier "dest_dir"
= "="
identifier "THIRDPARTY_DIR"
, ","
default_parameter
identifier "use_cached_index"
= "="
false "False"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Fetch license files if missing in `dest_dir`.\n "...
string_end "\"\"\""
expression_statement
assignment
identifier "urls"
= "="
attribute
call
attribute
identifier "LinksRepository"
. "."
identifier "from_url"
argument_list
( "("
keyword_argument
identifier "use_cached_index"
= "="
identifier "use_cached_index"
) ")"
. "."
identifier "links"
expression_statement
assignment
identifier "errors"
= "="
list
[ "["
] "]"
expression_statement
assignment
identifier "extra_lic_names"
= "="
list_comprehension
[ "["
call
attribute
identifier "lic"
. "."
identifier "get"
argument_list
( "("
string
string_start "\""
string_content "file"
string_end "\""
) ")"
for_in_clause
for "for"
identifier "lic"
in "in"
call
attribute
attribute
identifier "self"
. "."
identifier "extra_data"
. "."
identifier "get"
argument_list
( "("
string
string_start "\""
string_content "licenses"
string_end "\""
, ","
dictionary
{ "{"
} "}"
) ")"
] "]"
expression_statement (+22 nodes collapsed)
expression_statement
assignment
identifier "extra_lic_names"
= "="
list_comprehension
[ "["
identifier "eln"
for_in_clause
for "for"
identifier "eln"
in "in"
identifier "extra_lic_names"
if_clause
if "if"
identifier "eln"
] "]"
expression_statement (+27 nodes collapsed)
for_statement
for "for"
identifier "filename"
in "in"
binary_operator
identifier "lic_names"
+ "+"
identifier "extra_lic_names"
: ":"
block
expression_statement
assignment
identifier "floc"
= "="
call
attribute
attribute
identifier "os"
. "."
identifier "path"
. "."
identifier "join"
argument_list
( "("
identifier "dest_dir"
, ","
identifier "filename"
) ")"
if_statement
if "if"
call
attribute
attribute
identifier "os"
. "."
identifier "path"
. "."
identifier "exists"
argument_list
( "("
identifier "floc"
) ")"
: ":"
block
continue_statement
continue "continue"
try_statement
try "try"
: ":"
comment "# try remotely first"
block (+64 nodes collapsed)
except_clause
except "except"
identifier "Exception"
: ":"
block
try_statement
try "try"
: ":"
comment "# try licensedb second"
block (+62 nodes collapsed)
except_clause
except "except"
identifier "Exception"
: ":"
block
expression_statement
assignment
identifier "msg"
= "="
string
string_start "f\""
string_content "No text for license "
interpolation
{ "{"
identifier "filename"
} "}"
string_content " in expression "
string_end "\""
expression_statement
string
string_start "f\""
interpolation
{ "{"
attribute
identifier "self"
. "."
identifier "license_expression"
type_conversion "!r"
} "}"
string_content " from "
interpolation
{ "{"
identifier "self"
} "}"
string_end "\""
expression_statement
call
identifier "print"
argument_list
( "("
identifier "msg"
) ")"
expression_statement
call
attribute
identifier "errors"
. "."
identifier "append"
argument_list
( "("
identifier "msg"
) ")"
return_statement
return "return"
identifier "errors"
function_definition (+230 nodes collapsed)
function_definition (+331 nodes collapsed)
function_definition (+34 nodes collapsed)
function_definition (+65 nodes collapsed)
function_definition (+364 nodes collapsed)
function_definition
def "def"
identifier "get_license_link_for_filename"
parameters
( "("
identifier "filename"
, ","
identifier "urls"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Return a link for `filename` found in the `links` list "...
string_end "\"\"\""
expression_statement
assignment
identifier "path_or_url"
= "="
list_comprehension
[ "["
identifier "url"
for_in_clause
for "for"
identifier "url"
in "in"
identifier "urls"
if_clause
if "if"
call
attribute
identifier "url"
. "."
identifier "endswith"
argument_list
( "("
string
string_start "f\""
string_content "/"
interpolation
{ "{"
identifier "filename"
} "}"
string_end "\""
) ")"
] "]"
if_statement (+22 nodes collapsed)
if_statement (+47 nodes collapsed)
return_statement
return "return"
subscript
identifier "path_or_url"
[ "["
integer "0"
] "]"
class_definition
class "class"
identifier "InvalidDistributionFilename"
argument_list
( "("
identifier "Exception"
) ")"
: ":"
block
pass_statement
pass "pass"
function_definition (+365 nodes collapsed)
decorated_definition (+193 nodes collapsed)
decorated_definition (+833 nodes collapsed)
function_definition
def "def"
identifier "is_pure_wheel"
parameters
( "("
identifier "filename"
) ")"
: ":"
block
try_statement
try "try"
: ":"
block
return_statement
return "return"
call
attribute
call
attribute
identifier "Wheel"
. "."
identifier "from_filename"
argument_list
( "("
identifier "filename"
) ")"
. "."
identifier "is_pure"
argument_list
( "("
) ")"
except_clause
except "except"
identifier "Exception"
: ":"
block
return_statement
return "return"
false "False"
decorated_definition
decorator
@ "@"
attribute
identifier "attr"
. "."
identifier "attributes"
class_definition
class "class"
identifier "PypiPackage"
argument_list
( "("
identifier "NameVer"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n A Python package contains one or more wheels and one so"...
string_end "\"\"\""
expression_statement (+43 nodes collapsed)
expression_statement (+51 nodes collapsed)
function_definition (+77 nodes collapsed)
decorated_definition (+305 nodes collapsed)
decorated_definition (+109 nodes collapsed)
decorated_definition (+124 nodes collapsed)
decorated_definition (+178 nodes collapsed)
function_definition
def "def"
identifier "get_distributions"
parameters
( "("
identifier "self"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Yield all distributions available for this PypiPack"...
string_end "\"\"\""
if_statement
if "if"
attribute
identifier "self"
. "."
identifier "sdist"
: ":"
block
expression_statement
yield
yield "yield"
attribute
identifier "self"
. "."
identifier "sdist"
expression_statement
yield
yield "yield"
from "from"
attribute
identifier "self"
. "."
identifier "wheels"
function_definition (+47 nodes collapsed)
decorated_definition (+515 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# PyPI repo and link index for package wheels and sources"
comment "#"
comment "############################################################"...
decorated_definition
decorator
@ "@"
attribute
identifier "attr"
. "."
identifier "attributes"
class_definition
class "class"
identifier "PypiSimpleRepository"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n A PyPI repository of Python packages: wheels, sdist, et"...
string_end "\"\"\""
expression_statement (+38 nodes collapsed)
comment "# we keep a nested mapping of PypiPackage that has this shap"...
comment "# {name: {version: PypiPackage, version: PypiPackage, etc}"
comment "# the inner versions mapping is sorted by version from oldes"...
expression_statement
assignment
identifier "packages"
= "="
call
attribute
identifier "attr"
. "."
identifier "ib"
argument_list
( "("
keyword_argument
identifier "type"
= "="
identifier "dict"
, ","
keyword_argument
identifier "default"
= "="
call
attribute
identifier "attr"
. "."
identifier "Factory"
argument_list
( "("
lambda
lambda "lambda"
: ":"
call
identifier "defaultdict"
argument_list
( "("
identifier "dict"
) ")"
) ")"
, ","
keyword_argument
identifier "metadata"
= "="
call
identifier "dict"
argument_list
( "("
keyword_argument
identifier "help"
= "="
concatenated_string
string
string_start "\""
string_content "Mapping of {name: {version: PypiPackage, version: PypiPackag"...
string_end "\""
string
string_start "\""
string_content "available in this repo"
string_end "\""
) ")"
, ","
) ")"
expression_statement (+46 nodes collapsed)
expression_statement
assignment
identifier "use_cached_index"
= "="
call
attribute
identifier "attr"
. "."
identifier "ib"
argument_list
( "("
keyword_argument
identifier "type"
= "="
identifier "bool"
, ","
keyword_argument
identifier "default"
= "="
false "False"
, ","
keyword_argument
identifier "metadata"
= "="
call
identifier "dict"
argument_list
( "("
keyword_argument
identifier "help"
= "="
concatenated_string
string
string_start "\""
string_content "If True, use any existing on-disk cached PyPI index files. "
string_end "\""
string
string_start "\""
string_content "Otherwise, fetch and cache."
string_end "\""
) ")"
, ","
) ")"
function_definition
def "def"
identifier "_get_package_versions_map"
parameters
( "("
identifier "self"
, ","
identifier "name"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Return a mapping of all available PypiPackage versi"...
string_end "\"\"\""
if_statement
if "if"
not_operator
not "not"
identifier "name"
: ":"
block
raise_statement
raise "raise"
call
identifier "ValueError"
argument_list
( "("
string
string_start "f\""
string_content "name is required: "
interpolation
{ "{"
identifier "name"
type_conversion "!r"
} "}"
string_end "\""
) ")"
expression_statement
assignment
identifier "normalized_name"
= "="
call
attribute
identifier "NameVer"
. "."
identifier "normalize_name"
argument_list
( "("
identifier "name"
) ")"
expression_statement
assignment
identifier "versions"
= "="
subscript
attribute
identifier "self"
. "."
identifier "packages"
[ "["
identifier "normalized_name"
] "]"
if_statement (+136 nodes collapsed)
if_statement (+32 nodes collapsed)
return_statement
return "return"
identifier "versions"
function_definition (+32 nodes collapsed)
function_definition (+89 nodes collapsed)
function_definition
def "def"
identifier "fetch_links"
parameters
( "("
identifier "self"
, ","
identifier "normalized_name"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Return a list of download link URLs found in a PyPI"...
string_end "\"\"\""
expression_statement
assignment
identifier "package_url"
= "="
string
string_start "f\""
interpolation
{ "{"
attribute
identifier "self"
. "."
identifier "index_url"
} "}"
string_content "/"
interpolation
{ "{"
identifier "normalized_name"
} "}"
string_end "\""
expression_statement (+32 nodes collapsed)
expression_statement
assignment
identifier "links"
= "="
call
identifier "collect_urls"
argument_list
( "("
identifier "text"
) ")"
comment "# TODO: keep sha256"
expression_statement
assignment
identifier "links"
= "="
list_comprehension
[ "["
call
attribute
identifier "link"
. "."
identifier "partition"
argument_list
( "("
string
string_start "\""
string_content "#sha256="
string_end "\""
) ")"
for_in_clause
for "for"
identifier "link"
in "in"
identifier "links"
] "]"
expression_statement
assignment
identifier "links"
= "="
list_comprehension
[ "["
identifier "url"
for_in_clause
for "for"
pattern_list
identifier "url"
, ","
identifier "_"
, ","
identifier "_sha256"
in "in"
identifier "links"
] "]"
return_statement
return "return"
identifier "links"
expression_statement
assignment
identifier "PYPI_PUBLIC_REPO"
= "="
call
identifier "PypiSimpleRepository"
argument_list
( "("
keyword_argument
identifier "index_url"
= "="
identifier "PYPI_SIMPLE_URL"
) ")"
expression_statement
assignment
identifier "PYPI_SELFHOSTED_REPO"
= "="
call
identifier "PypiSimpleRepository"
argument_list
( "("
keyword_argument
identifier "index_url"
= "="
identifier "ABOUT_PYPI_SIMPLE_URL"
) ")"
expression_statement
assignment
identifier "DEFAULT_PYPI_REPOS"
= "="
expression_list
identifier "PYPI_PUBLIC_REPO"
, ","
identifier "PYPI_SELFHOSTED_REPO"
expression_statement
assignment
identifier "DEFAULT_PYPI_REPOS_BY_URL"
= "="
dictionary_comprehension
{ "{"
pair
attribute
identifier "r"
. "."
identifier "index_url"
: ":"
identifier "r"
for_in_clause
for "for"
identifier "r"
in "in"
identifier "DEFAULT_PYPI_REPOS"
} "}"
decorated_definition (+603 nodes collapsed)
comment "############################################################"...
comment "# Globals for remote repos to be lazily created and cached o"...
comment "# life of the session together with some convenience functio"...
comment "############################################################"...
function_definition (+36 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# Basic file and URL-based operations using a persistent fil"...
comment "#"
comment "############################################################"...
decorated_definition (+277 nodes collapsed)
expression_statement
assignment
identifier "CACHE"
= "="
call
identifier "Cache"
argument_list
( "("
) ")"
function_definition (+160 nodes collapsed)
function_definition (+90 nodes collapsed)
class_definition
class "class"
identifier "RemoteNotFetchedException"
argument_list
( "("
identifier "Exception"
) ")"
: ":"
block
pass_statement
pass "pass"
function_definition
def "def"
identifier "get_remote_file_content"
parameters (+25 nodes collapsed)
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Fetch and return a tuple of (headers, content) at `url`"...
string_end "\"\"\""
expression_statement
call
attribute
identifier "time"
. "."
identifier "sleep"
argument_list
( "("
identifier "_delay"
) ")"
expression_statement
assignment
identifier "headers"
= "="
boolean_operator
identifier "headers"
or "or"
dictionary
{ "{"
} "}"
comment "# using a GET with stream=True ensure we get the the final h"...
comment "# several redirects and that we can ignore content there. A "...
comment "# not get us this last header"
expression_statement
call
identifier "print"
argument_list
( "("
string
string_start "f\""
string_content " DOWNLOADING: "
interpolation
{ "{"
identifier "url"
} "}"
string_end "\""
) ")"
with_statement
with "with"
with_clause (+30 nodes collapsed)
: ":"
comment "# noqa: S113"
block (+135 nodes collapsed)
function_definition (+111 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# Functions to update or fetch ABOUT and license files"
comment "#"
comment "############################################################"...
function_definition (+120 nodes collapsed)
function_definition (+863 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# Functions to build new Python wheels including native on m"...
comment "#"
comment "############################################################"...
function_definition
def "def"
identifier "call"
parameters
( "("
identifier "args"
, ","
default_parameter
identifier "verbose"
= "="
identifier "TRACE"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Call args in a subprocess and display output on the fly"...
string_end "\"\"\""
if_statement (+28 nodes collapsed)
with_statement
with "with"
with_clause
with_item
as_pattern
call
attribute
identifier "subprocess"
. "."
identifier "Popen"
argument_list
( "("
comment "# noqa: S603"
identifier "args"
, ","
keyword_argument
identifier "stdout"
= "="
attribute
identifier "subprocess"
. "."
identifier "PIPE"
, ","
keyword_argument
identifier "stderr"
= "="
attribute
identifier "subprocess"
. "."
identifier "PIPE"
, ","
keyword_argument
identifier "encoding"
= "="
string
string_start "\""
string_content "utf-8"
string_end "\""
) ")"
as "as"
as_pattern_target
identifier "process"
: ":"
block (+143 nodes collapsed)
function_definition
def "def"
identifier "download_wheels_with_pip"
parameters (+41 nodes collapsed)
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Fetch binary wheel(s) using pip for the ``envt`` Enviro"...
string_end "\"\"\""
expression_statement (+79 nodes collapsed)
if_statement (+41 nodes collapsed)
expression_statement
call
attribute
identifier "cli_args"
. "."
identifier "extend"
argument_list
( "("
identifier "requirements_specifiers"
) ")"
for_statement (+25 nodes collapsed)
if_statement
if "if"
identifier "TRACE"
: ":"
block
expression_statement
call
identifier "print"
argument_list
( "("
string
string_start "\""
string_content "Downloading wheels using command:"
string_end "\""
, ","
call
attribute
string
string_start "\""
string_content " "
string_end "\""
. "."
identifier "join"
argument_list
( "("
identifier "cli_args"
) ")"
) ")"
expression_statement
assignment
identifier "existing"
= "="
call
identifier "set"
argument_list
( "("
call
attribute
identifier "os"
. "."
identifier "listdir"
argument_list
( "("
identifier "dest_dir"
) ")"
) ")"
expression_statement
assignment
identifier "error"
= "="
false "False"
try_statement (+56 nodes collapsed)
if_statement (+64 nodes collapsed)
expression_statement (+21 nodes collapsed)
return_statement
return "return"
expression_list
call
identifier "sorted"
argument_list
( "("
identifier "downloaded"
) ")"
, ","
identifier "error"
comment "############################################################"...
comment "#"
comment "# Functions to check for problems"
comment "#"
comment "############################################################"...
function_definition
def "def"
identifier "check_about"
parameters
( "("
default_parameter
identifier "dest_dir"
= "="
identifier "THIRDPARTY_DIR"
) ")"
: ":"
block
try_statement
try "try"
: ":"
block
expression_statement (+24 nodes collapsed)
comment "# noqa: S603"
except_clause (+57 nodes collapsed)
function_definition (+308 nodes collapsed)
function_definition
def "def"
identifier "get_license_expression"
parameters
( "("
identifier "declared_licenses"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Return a normalized license expression or None.\n "
string_end "\"\"\""
if_statement
if "if"
not_operator
not "not"
identifier "declared_licenses"
: ":"
block
return_statement
return "return"
try_statement
try "try"
: ":"
block
import_from_statement
from "from"
dotted_name
identifier "packagedcode"
. "."
identifier "licensing"
import "import"
dotted_name
identifier "get_only_expression_from_extracted_license"
return_statement
return "return"
call
identifier "get_only_expression_from_extracted_license"
argument_list
( "("
identifier "declared_licenses"
) ")"
except_clause
except "except"
identifier "ImportError"
: ":"
comment "# Scancode is not installed, clean and join all the licenses"
block
expression_statement
assignment
identifier "lics"
= "="
list_comprehension
[ "["
call
attribute
call
identifier "python_safe_name"
argument_list
( "("
identifier "lic"
) ")"
. "."
identifier "lower"
argument_list
( "("
) ")"
for_in_clause
for "for"
identifier "lic"
in "in"
identifier "declared_licenses"
] "]"
return_statement (+21 nodes collapsed)

After

module
comment "#!/usr/bin/env python"
comment "# -*- coding: utf-8 -*-"
comment "#"
comment "# Copyright (c) nexB Inc. and others. All rights reserved."
comment "# ScanCode is a trademark of nexB Inc."
comment "# SPDX-License-Identifier: Apache-2.0"
comment "# See http://www.apache.org/licenses/LICENSE-2.0 for the lic"...
comment "# See https://github.com/aboutcode-org/skeleton for support "...
comment "# See https://aboutcode.org for more information about nexB "...
comment "#"
import_statement
import "import"
dotted_name
identifier "email"
import_statement
import "import"
dotted_name
identifier "itertools"
import_statement
import "import"
dotted_name
identifier "os"
import_statement
import "import"
dotted_name
identifier "re"
import_statement
import "import"
dotted_name
identifier "shutil"
import_statement
import "import"
dotted_name
identifier "subprocess"
import_statement
import "import"
dotted_name
identifier "tempfile"
import_statement
import "import"
dotted_name
identifier "time"
import_statement
import "import"
dotted_name
identifier "urllib"
import_from_statement
from "from"
dotted_name
identifier "collections"
import "import"
dotted_name
identifier "defaultdict"
import_from_statement
from "from"
dotted_name
identifier "urllib"
. "."
identifier "parse"
import "import"
dotted_name
identifier "quote_plus"
import_statement
import "import"
dotted_name
identifier "attr"
import_statement
import "import"
dotted_name
identifier "license_expression"
import_statement
import "import"
dotted_name
identifier "packageurl"
import_statement
import "import"
dotted_name
identifier "requests"
import_statement
import "import"
dotted_name
identifier "saneyaml"
import_from_statement
from "from"
dotted_name
identifier "commoncode"
import "import"
dotted_name
identifier "fileutils"
import_from_statement
from "from"
dotted_name
identifier "commoncode"
. "."
identifier "hash"
import "import"
dotted_name
identifier "multi_checksums"
import_from_statement
from "from"
dotted_name
identifier "commoncode"
. "."
identifier "text"
import "import"
dotted_name
identifier "python_safe_name"
import_from_statement
from "from"
dotted_name
identifier "packvers"
import "import"
aliased_import
dotted_name
identifier "tags"
as "as"
identifier "packaging_tags"
import_from_statement
from "from"
dotted_name
identifier "packvers"
import "import"
aliased_import
dotted_name
identifier "version"
as "as"
identifier "packaging_version"
import_statement
import "import"
dotted_name
identifier "utils_pip_compatibility_tags"
expression_statement
string
string_start "\"\"\""
string_content "\nUtilities to manage Python thirparty libraries source, bina"...
string_end "\"\"\""
expression_statement
string
string_start "\"\"\""
string_content "\nWheel downloader\n\n- parse requirement file\n- create a TODO "...
string_end "\"\"\""
expression_statement
assignment
identifier "TRACE"
= "="
false "False"
expression_statement
assignment
identifier "TRACE_DEEP"
= "="
false "False"
expression_statement
assignment
identifier "TRACE_ULTRA_DEEP"
= "="
false "False"
comment "# Supported environments"
expression_statement
assignment
identifier "PYTHON_VERSIONS"
= "="
expression_list
string
string_start "\""
string_content "39"
string_end "\""
, ","
string
string_start "\""
string_content "310"
string_end "\""
, ","
string
string_start "\""
string_content "311"
string_end "\""
, ","
string
string_start "\""
string_content "312"
string_end "\""
, ","
string
string_start "\""
string_content "313"
string_end "\""
expression_statement
assignment
identifier "PYTHON_DOT_VERSIONS_BY_VER"
= "="
dictionary
{ "{"
pair
string
string_start "\""
string_content "39"
string_end "\""
: ":"
string
string_start "\""
string_content "3.9"
string_end "\""
, ","
pair
string
string_start "\""
string_content "310"
string_end "\""
: ":"
string
string_start "\""
string_content "3.10"
string_end "\""
, ","
pair
string
string_start "\""
string_content "311"
string_end "\""
: ":"
string
string_start "\""
string_content "3.11"
string_end "\""
, ","
pair
string
string_start "\""
string_content "312"
string_end "\""
: ":"
string
string_start "\""
string_content "3.12"
string_end "\""
, ","
pair
string
string_start "\""
string_content "313"
string_end "\""
: ":"
string
string_start "\""
string_content "3.13"
string_end "\""
, ","
} "}"
function_definition (+21 nodes collapsed)
expression_statement
assignment
identifier "ABIS_BY_PYTHON_VERSION"
= "="
dictionary
{ "{"
pair (+23 nodes collapsed)
, ","
pair (+23 nodes collapsed)
, ","
pair
string
string_start "\""
string_content "311"
string_end "\""
: ":"
list
[ "["
string
string_start "\""
string_content "cp311"
string_end "\""
, ","
string
string_start "\""
string_content "cp311m"
string_end "\""
, ","
string
string_start "\""
string_content "abi3"
string_end "\""
] "]"
, ","
pair
string
string_start "\""
string_content "312"
string_end "\""
: ":"
list
[ "["
string
string_start "\""
string_content "cp312"
string_end "\""
, ","
string
string_start "\""
string_content "cp312m"
string_end "\""
, ","
string
string_start "\""
string_content "abi3"
string_end "\""
] "]"
, ","
pair
string
string_start "\""
string_content "313"
string_end "\""
: ":"
list
[ "["
string
string_start "\""
string_content "cp313"
string_end "\""
, ","
string
string_start "\""
string_content "cp313m"
string_end "\""
, ","
string
string_start "\""
string_content "abi3"
string_end "\""
] "]"
, ","
} "}"
expression_statement (+203 nodes collapsed)
expression_statement
assignment
identifier "THIRDPARTY_DIR"
= "="
string
string_start "\""
string_content "thirdparty"
string_end "\""
expression_statement
assignment
identifier "CACHE_THIRDPARTY_DIR"
= "="
string
string_start "\""
string_content ".cache/thirdparty"
string_end "\""
comment "############################################################"...
expression_statement
assignment
identifier "ABOUT_BASE_URL"
= "="
string
string_start "\""
string_content "https://thirdparty.aboutcode.org/pypi"
string_end "\""
expression_statement
assignment
identifier "ABOUT_PYPI_SIMPLE_URL"
= "="
string
string_start "f\""
interpolation
{ "{"
identifier "ABOUT_BASE_URL"
} "}"
string_content "/simple"
string_end "\""
expression_statement
assignment
identifier "ABOUT_LINKS_URL"
= "="
string
string_start "f\""
interpolation
{ "{"
identifier "ABOUT_PYPI_SIMPLE_URL"
} "}"
string_content "/links.html"
string_end "\""
expression_statement
assignment
identifier "PYPI_SIMPLE_URL"
= "="
string
string_start "\""
string_content "https://pypi.org/simple"
string_end "\""
expression_statement
assignment
identifier "PYPI_INDEX_URLS"
= "="
tuple
( "("
identifier "PYPI_SIMPLE_URL"
, ","
identifier "ABOUT_PYPI_SIMPLE_URL"
) ")"
comment "############################################################"...
expression_statement
assignment
identifier "EXTENSIONS_APP"
= "="
tuple
( "("
string
string_start "\""
string_content ".pyz"
string_end "\""
, ","
) ")"
expression_statement (+22 nodes collapsed)
expression_statement
assignment
identifier "EXTENSIONS_INSTALLABLE"
= "="
binary_operator
identifier "EXTENSIONS_SDIST"
+ "+"
tuple
( "("
string
string_start "\""
string_content ".whl"
string_end "\""
, ","
) ")"
expression_statement (+22 nodes collapsed)
expression_statement
assignment
identifier "EXTENSIONS"
= "="
binary_operator
binary_operator
identifier "EXTENSIONS_INSTALLABLE"
+ "+"
identifier "EXTENSIONS_ABOUT"
+ "+"
identifier "EXTENSIONS_APP"
expression_statement
assignment
identifier "LICENSEDB_API_URL"
= "="
string
string_start "\""
string_content "https://scancode-licensedb.aboutcode.org"
string_end "\""
expression_statement
assignment
identifier "LICENSING"
= "="
call
attribute
identifier "license_expression"
. "."
identifier "Licensing"
argument_list
( "("
) ")"
expression_statement
assignment
identifier "collect_urls"
= "="
attribute
call
attribute
identifier "re"
. "."
identifier "compile"
argument_list
( "("
string
string_start "'"
string_content "href=\"([^\"]+)\""
string_end "'"
) ")"
. "."
identifier "findall"
comment "############################################################"...
comment "# Fetch wheels and sources locally"
comment "############################################################"...
class_definition
class "class"
identifier "DistributionNotFound"
argument_list
( "("
identifier "Exception"
) ")"
: ":"
block
pass_statement
pass "pass"
function_definition (+275 nodes collapsed)
function_definition (+233 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# Core models"
comment "#"
comment "############################################################"...
decorated_definition (+227 nodes collapsed)
decorated_definition
decorator
@ "@"
attribute
identifier "attr"
. "."
identifier "attributes"
class_definition
class "class"
identifier "Distribution"
argument_list
( "("
identifier "NameVer"
) ")"
: ":"
comment "# field names that can be updated from another Distribution "...
block
expression_statement (+42 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+43 nodes collapsed)
expression_statement (+46 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+51 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+46 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+51 nodes collapsed)
expression_statement (+45 nodes collapsed)
expression_statement (+51 nodes collapsed)
decorated_definition (+81 nodes collapsed)
decorated_definition (+23 nodes collapsed)
function_definition (+179 nodes collapsed)
function_definition
def "def"
identifier "download"
parameters
( "("
identifier "self"
, ","
default_parameter
identifier "dest_dir"
= "="
identifier "THIRDPARTY_DIR"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Download this distribution into `dest_dir` director"...
string_end "\"\"\""
assert_statement
assert "assert"
attribute
identifier "self"
. "."
identifier "filename"
if_statement (+37 nodes collapsed)
comment "# FIXME:"
expression_statement (+32 nodes collapsed)
return_statement
return "return"
attribute
identifier "self"
. "."
identifier "filename"
decorated_definition (+26 nodes collapsed)
decorated_definition (+30 nodes collapsed)
decorated_definition (+26 nodes collapsed)
decorated_definition (+30 nodes collapsed)
decorated_definition (+71 nodes collapsed)
decorated_definition (+70 nodes collapsed)
decorated_definition (+71 nodes collapsed)
function_definition (+50 nodes collapsed)
function_definition (+235 nodes collapsed)
function_definition (+49 nodes collapsed)
function_definition (+248 nodes collapsed)
function_definition (+411 nodes collapsed)
function_definition (+176 nodes collapsed)
function_definition (+94 nodes collapsed)
function_definition (+42 nodes collapsed)
function_definition (+100 nodes collapsed)
function_definition (+60 nodes collapsed)
function_definition
def "def"
identifier "fetch_license_files"
parameters
( "("
identifier "self"
, ","
default_parameter
identifier "dest_dir"
= "="
identifier "THIRDPARTY_DIR"
, ","
default_parameter
identifier "use_cached_index"
= "="
false "False"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Fetch license files if missing in `dest_dir`.\n "...
string_end "\"\"\""
expression_statement
assignment
identifier "urls"
= "="
attribute
call
attribute
identifier "LinksRepository"
. "."
identifier "from_url"
argument_list
( "("
keyword_argument
identifier "use_cached_index"
= "="
identifier "use_cached_index"
) ")"
. "."
identifier "links"
expression_statement
assignment
identifier "errors"
= "="
list
[ "["
] "]"
expression_statement
assignment
identifier "extra_lic_names"
= "="
list_comprehension
[ "["
call
attribute
identifier "l"
. "."
identifier "get"
argument_list
( "("
string
string_start "\""
string_content "file"
string_end "\""
) ")"
for_in_clause
for "for"
identifier "l"
in "in"
call
attribute
attribute
identifier "self"
. "."
identifier "extra_data"
. "."
identifier "get"
argument_list
( "("
string
string_start "\""
string_content "licenses"
string_end "\""
, ","
dictionary
{ "{"
} "}"
) ")"
] "]"
expression_statement (+22 nodes collapsed)
expression_statement
assignment
identifier "extra_lic_names"
= "="
list_comprehension
[ "["
identifier "ln"
for_in_clause
for "for"
identifier "ln"
in "in"
identifier "extra_lic_names"
if_clause
if "if"
identifier "ln"
] "]"
expression_statement (+27 nodes collapsed)
for_statement
for "for"
identifier "filename"
in "in"
binary_operator
identifier "lic_names"
+ "+"
identifier "extra_lic_names"
: ":"
block
expression_statement
assignment
identifier "floc"
= "="
call
attribute
attribute
identifier "os"
. "."
identifier "path"
. "."
identifier "join"
argument_list
( "("
identifier "dest_dir"
, ","
identifier "filename"
) ")"
if_statement
if "if"
call
attribute
attribute
identifier "os"
. "."
identifier "path"
. "."
identifier "exists"
argument_list
( "("
identifier "floc"
) ")"
: ":"
block
continue_statement
continue "continue"
try_statement
try "try"
: ":"
comment "# try remotely first"
block (+64 nodes collapsed)
except_clause
except "except"
: ":"
block
try_statement
try "try"
: ":"
comment "# try licensedb second"
block (+62 nodes collapsed)
except_clause
except "except"
: ":"
block
expression_statement
assignment
identifier "msg"
= "="
string
string_start "f'"
string_content "No text for license "
interpolation
{ "{"
identifier "filename"
} "}"
string_content " in expression \""
interpolation
{ "{"
attribute
identifier "self"
. "."
identifier "license_expression"
} "}"
string_content "\" from "
interpolation
{ "{"
identifier "self"
} "}"
string_end "'"
expression_statement
call
identifier "print"
argument_list
( "("
identifier "msg"
) ")"
expression_statement
call
attribute
identifier "errors"
. "."
identifier "append"
argument_list
( "("
identifier "msg"
) ")"
return_statement
return "return"
identifier "errors"
function_definition (+230 nodes collapsed)
function_definition (+331 nodes collapsed)
function_definition (+34 nodes collapsed)
function_definition (+65 nodes collapsed)
function_definition (+364 nodes collapsed)
function_definition
def "def"
identifier "get_license_link_for_filename"
parameters
( "("
identifier "filename"
, ","
identifier "urls"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Return a link for `filename` found in the `links` list "...
string_end "\"\"\""
expression_statement
assignment
identifier "path_or_url"
= "="
list_comprehension
[ "["
identifier "l"
for_in_clause
for "for"
identifier "l"
in "in"
identifier "urls"
if_clause
if "if"
call
attribute
identifier "l"
. "."
identifier "endswith"
argument_list
( "("
string
string_start "f\""
string_content "/"
interpolation
{ "{"
identifier "filename"
} "}"
string_end "\""
) ")"
] "]"
if_statement (+22 nodes collapsed)
if_statement (+47 nodes collapsed)
return_statement
return "return"
subscript
identifier "path_or_url"
[ "["
integer "0"
] "]"
class_definition
class "class"
identifier "InvalidDistributionFilename"
argument_list
( "("
identifier "Exception"
) ")"
: ":"
block
pass_statement
pass "pass"
function_definition (+365 nodes collapsed)
decorated_definition (+193 nodes collapsed)
decorated_definition (+833 nodes collapsed)
function_definition
def "def"
identifier "is_pure_wheel"
parameters
( "("
identifier "filename"
) ")"
: ":"
block
try_statement
try "try"
: ":"
block
return_statement
return "return"
call
attribute
call
attribute
identifier "Wheel"
. "."
identifier "from_filename"
argument_list
( "("
identifier "filename"
) ")"
. "."
identifier "is_pure"
argument_list
( "("
) ")"
except_clause
except "except"
: ":"
block
return_statement
return "return"
false "False"
decorated_definition
decorator
@ "@"
attribute
identifier "attr"
. "."
identifier "attributes"
class_definition
class "class"
identifier "PypiPackage"
argument_list
( "("
identifier "NameVer"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n A Python package contains one or more wheels and one so"...
string_end "\"\"\""
expression_statement (+43 nodes collapsed)
expression_statement (+51 nodes collapsed)
function_definition (+77 nodes collapsed)
decorated_definition (+305 nodes collapsed)
decorated_definition (+109 nodes collapsed)
decorated_definition (+124 nodes collapsed)
decorated_definition (+178 nodes collapsed)
function_definition
def "def"
identifier "get_distributions"
parameters
( "("
identifier "self"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Yield all distributions available for this PypiPack"...
string_end "\"\"\""
if_statement
if "if"
attribute
identifier "self"
. "."
identifier "sdist"
: ":"
block
expression_statement
yield
yield "yield"
attribute
identifier "self"
. "."
identifier "sdist"
for_statement
for "for"
identifier "wheel"
in "in"
attribute
identifier "self"
. "."
identifier "wheels"
: ":"
block
expression_statement
yield
yield "yield"
identifier "wheel"
function_definition (+47 nodes collapsed)
decorated_definition (+515 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# PyPI repo and link index for package wheels and sources"
comment "#"
comment "############################################################"...
decorated_definition
decorator
@ "@"
attribute
identifier "attr"
. "."
identifier "attributes"
class_definition
class "class"
identifier "PypiSimpleRepository"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n A PyPI repository of Python packages: wheels, sdist, et"...
string_end "\"\"\""
expression_statement (+38 nodes collapsed)
comment "# we keep a nested mapping of PypiPackage that has this shap"...
comment "# {name: {version: PypiPackage, version: PypiPackage, etc}"
comment "# the inner versions mapping is sorted by version from oldes"...
expression_statement
assignment
identifier "packages"
= "="
call
attribute
identifier "attr"
. "."
identifier "ib"
argument_list
( "("
keyword_argument
identifier "type"
= "="
identifier "dict"
, ","
keyword_argument
identifier "default"
= "="
call
attribute
identifier "attr"
. "."
identifier "Factory"
argument_list
( "("
lambda
lambda "lambda"
: ":"
call
identifier "defaultdict"
argument_list
( "("
identifier "dict"
) ")"
) ")"
, ","
keyword_argument
identifier "metadata"
= "="
call
identifier "dict"
argument_list
( "("
keyword_argument
identifier "help"
= "="
string
string_start "\""
string_content "Mapping of {name: {version: PypiPackage, version: PypiPackag"...
string_end "\""
) ")"
, ","
) ")"
expression_statement (+46 nodes collapsed)
expression_statement
assignment
identifier "use_cached_index"
= "="
call
attribute
identifier "attr"
. "."
identifier "ib"
argument_list
( "("
keyword_argument
identifier "type"
= "="
identifier "bool"
, ","
keyword_argument
identifier "default"
= "="
false "False"
, ","
keyword_argument
identifier "metadata"
= "="
call
identifier "dict"
argument_list
( "("
keyword_argument
identifier "help"
= "="
string
string_start "\""
string_content "If True, use any existing on-disk cached PyPI index files. O"...
string_end "\""
) ")"
, ","
) ")"
function_definition
def "def"
identifier "_get_package_versions_map"
parameters
( "("
identifier "self"
, ","
identifier "name"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Return a mapping of all available PypiPackage versi"...
string_end "\"\"\""
assert_statement
assert "assert"
identifier "name"
expression_statement
assignment
identifier "normalized_name"
= "="
call
attribute
identifier "NameVer"
. "."
identifier "normalize_name"
argument_list
( "("
identifier "name"
) ")"
expression_statement
assignment
identifier "versions"
= "="
subscript
attribute
identifier "self"
. "."
identifier "packages"
[ "["
identifier "normalized_name"
] "]"
if_statement (+136 nodes collapsed)
if_statement (+32 nodes collapsed)
return_statement
return "return"
identifier "versions"
function_definition (+32 nodes collapsed)
function_definition (+89 nodes collapsed)
function_definition
def "def"
identifier "fetch_links"
parameters
( "("
identifier "self"
, ","
identifier "normalized_name"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Return a list of download link URLs found in a PyPI"...
string_end "\"\"\""
expression_statement
assignment
identifier "package_url"
= "="
string
string_start "f\""
interpolation
{ "{"
attribute
identifier "self"
. "."
identifier "index_url"
} "}"
string_content "/"
interpolation
{ "{"
identifier "normalized_name"
} "}"
string_end "\""
expression_statement (+32 nodes collapsed)
expression_statement
assignment
identifier "links"
= "="
call
identifier "collect_urls"
argument_list
( "("
identifier "text"
) ")"
comment "# TODO: keep sha256"
expression_statement
assignment
identifier "links"
= "="
list_comprehension
[ "["
call
attribute
identifier "l"
. "."
identifier "partition"
argument_list
( "("
string
string_start "\""
string_content "#sha256="
string_end "\""
) ")"
for_in_clause
for "for"
identifier "l"
in "in"
identifier "links"
] "]"
expression_statement
assignment
identifier "links"
= "="
list_comprehension
[ "["
identifier "url"
for_in_clause
for "for"
pattern_list
identifier "url"
, ","
identifier "_"
, ","
identifier "_sha256"
in "in"
identifier "links"
] "]"
return_statement
return "return"
identifier "links"
expression_statement
assignment
identifier "PYPI_PUBLIC_REPO"
= "="
call
identifier "PypiSimpleRepository"
argument_list
( "("
keyword_argument
identifier "index_url"
= "="
identifier "PYPI_SIMPLE_URL"
) ")"
expression_statement
assignment
identifier "PYPI_SELFHOSTED_REPO"
= "="
call
identifier "PypiSimpleRepository"
argument_list
( "("
keyword_argument
identifier "index_url"
= "="
identifier "ABOUT_PYPI_SIMPLE_URL"
) ")"
expression_statement
assignment
identifier "DEFAULT_PYPI_REPOS"
= "="
expression_list
identifier "PYPI_PUBLIC_REPO"
, ","
identifier "PYPI_SELFHOSTED_REPO"
expression_statement
assignment
identifier "DEFAULT_PYPI_REPOS_BY_URL"
= "="
dictionary_comprehension
{ "{"
pair
attribute
identifier "r"
. "."
identifier "index_url"
: ":"
identifier "r"
for_in_clause
for "for"
identifier "r"
in "in"
identifier "DEFAULT_PYPI_REPOS"
} "}"
decorated_definition (+603 nodes collapsed)
comment "############################################################"...
comment "# Globals for remote repos to be lazily created and cached o"...
comment "# life of the session together with some convenience functio"...
comment "############################################################"...
function_definition (+36 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# Basic file and URL-based operations using a persistent fil"...
comment "#"
comment "############################################################"...
decorated_definition (+277 nodes collapsed)
expression_statement
assignment
identifier "CACHE"
= "="
call
identifier "Cache"
argument_list
( "("
) ")"
function_definition (+160 nodes collapsed)
function_definition (+90 nodes collapsed)
class_definition
class "class"
identifier "RemoteNotFetchedException"
argument_list
( "("
identifier "Exception"
) ")"
: ":"
block
pass_statement
pass "pass"
function_definition
def "def"
identifier "get_remote_file_content"
parameters (+25 nodes collapsed)
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Fetch and return a tuple of (headers, content) at `url`"...
string_end "\"\"\""
expression_statement
call
attribute
identifier "time"
. "."
identifier "sleep"
argument_list
( "("
identifier "_delay"
) ")"
expression_statement
assignment
identifier "headers"
= "="
boolean_operator
identifier "headers"
or "or"
dictionary
{ "{"
} "}"
comment "# using a GET with stream=True ensure we get the the final h"...
comment "# several redirects and that we can ignore content there. A "...
comment "# not get us this last header"
expression_statement
call
identifier "print"
argument_list
( "("
string
string_start "f\""
string_content " DOWNLOADING: "
interpolation
{ "{"
identifier "url"
} "}"
string_end "\""
) ")"
with_statement
with "with"
with_clause (+30 nodes collapsed)
: ":"
block (+135 nodes collapsed)
function_definition (+111 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# Functions to update or fetch ABOUT and license files"
comment "#"
comment "############################################################"...
function_definition (+120 nodes collapsed)
function_definition (+863 nodes collapsed)
comment "############################################################"...
comment "#"
comment "# Functions to build new Python wheels including native on m"...
comment "#"
comment "############################################################"...
function_definition
def "def"
identifier "call"
parameters
( "("
identifier "args"
, ","
default_parameter
identifier "verbose"
= "="
identifier "TRACE"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Call args in a subprocess and display output on the fly"...
string_end "\"\"\""
if_statement (+28 nodes collapsed)
with_statement
with "with"
with_clause
with_item
as_pattern
call
attribute
identifier "subprocess"
. "."
identifier "Popen"
argument_list
( "("
identifier "args"
, ","
keyword_argument
identifier "stdout"
= "="
attribute
identifier "subprocess"
. "."
identifier "PIPE"
, ","
keyword_argument
identifier "stderr"
= "="
attribute
identifier "subprocess"
. "."
identifier "PIPE"
, ","
keyword_argument
identifier "encoding"
= "="
string
string_start "\""
string_content "utf-8"
string_end "\""
) ")"
as "as"
as_pattern_target
identifier "process"
: ":"
block (+143 nodes collapsed)
function_definition
def "def"
identifier "download_wheels_with_pip"
parameters (+41 nodes collapsed)
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Fetch binary wheel(s) using pip for the ``envt`` Enviro"...
string_end "\"\"\""
expression_statement (+79 nodes collapsed)
if_statement (+41 nodes collapsed)
expression_statement
call
attribute
identifier "cli_args"
. "."
identifier "extend"
argument_list
( "("
identifier "requirements_specifiers"
) ")"
for_statement (+25 nodes collapsed)
if_statement
if "if"
identifier "TRACE"
: ":"
block
expression_statement
call
identifier "print"
argument_list
( "("
string
string_start "f\""
string_content "Downloading wheels using command:"
string_end "\""
, ","
call
attribute
string
string_start "\""
string_content " "
string_end "\""
. "."
identifier "join"
argument_list
( "("
identifier "cli_args"
) ")"
) ")"
expression_statement
assignment
identifier "existing"
= "="
call
identifier "set"
argument_list
( "("
call
attribute
identifier "os"
. "."
identifier "listdir"
argument_list
( "("
identifier "dest_dir"
) ")"
) ")"
expression_statement
assignment
identifier "error"
= "="
false "False"
try_statement (+56 nodes collapsed)
if_statement (+64 nodes collapsed)
expression_statement (+21 nodes collapsed)
return_statement
return "return"
expression_list
call
identifier "sorted"
argument_list
( "("
identifier "downloaded"
) ")"
, ","
identifier "error"
comment "############################################################"...
comment "#"
comment "# Functions to check for problems"
comment "#"
comment "############################################################"...
function_definition
def "def"
identifier "check_about"
parameters
( "("
default_parameter
identifier "dest_dir"
= "="
identifier "THIRDPARTY_DIR"
) ")"
: ":"
block
try_statement
try "try"
: ":"
block
expression_statement (+24 nodes collapsed)
except_clause (+57 nodes collapsed)
function_definition (+308 nodes collapsed)
function_definition
def "def"
identifier "get_license_expression"
parameters
( "("
identifier "declared_licenses"
) ")"
: ":"
block
expression_statement
string
string_start "\"\"\""
string_content "\n Return a normalized license expression or None.\n "
string_end "\"\"\""
if_statement
if "if"
not_operator
not "not"
identifier "declared_licenses"
: ":"
block
return_statement
return "return"
try_statement
try "try"
: ":"
block
import_from_statement
from "from"
dotted_name
identifier "packagedcode"
. "."
identifier "licensing"
import "import"
dotted_name
identifier "get_only_expression_from_extracted_license"
return_statement
return "return"
call
identifier "get_only_expression_from_extracted_license"
argument_list
( "("
identifier "declared_licenses"
) ")"
except_clause
except "except"
identifier "ImportError"
: ":"
comment "# Scancode is not installed, clean and join all the licenses"
block
expression_statement
assignment
identifier "lics"
= "="
list_comprehension
[ "["
call
attribute
call
identifier "python_safe_name"
argument_list
( "("
identifier "l"
) ")"
. "."
identifier "lower"
argument_list
( "("
) ")"
for_in_clause
for "for"
identifier "l"
in "in"
identifier "declared_licenses"
] "]"
return_statement (+21 nodes collapsed)