From ef43f84b1164a7c28cedc4f4b9e4be6eb4a7a627 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Mon, 8 Apr 2024 17:07:29 -0700 Subject: [PATCH 01/22] sage_bootstrap.package: Also take Package.distribution from requirements.txt --- build/sage_bootstrap/app.py | 3 +++ build/sage_bootstrap/package.py | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 96bca3a6d8c..0a4e984e3ff 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -256,6 +256,9 @@ def update_latest(self, package_name, commit=False): Update a package to the latest version. This modifies the Sage sources. """ pkg = Package(package_name) + if pkg.source not in ['normal', 'wheel']: + log.debug('update_latest can only update normal and wheel packages; %s is a %s package' % (pkg, pkg.source)) + return dist_name = pkg.distribution_name if dist_name is None: log.debug('%s does not have Python distribution info in version_requirements.txt' % pkg) diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index aea31e4b6a4..458297c1bec 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -47,6 +47,7 @@ def __init__(self, package_name): self._init_version() self._init_type() self._init_version_requirements() + self._init_requirements() self._init_dependencies() self._init_trees() @@ -323,7 +324,7 @@ def source(self): """ Return the package source type """ - if self.has_file('requirements.txt'): + if self.__requirements is not None: return 'pip' if self.tarball_filename: if self.tarball_filename.endswith('.whl'): @@ -346,7 +347,7 @@ def trees(self): return self.__trees if self.__version_requirements is not None: return 'SAGE_VENV' - if self.has_file('requirements.txt'): + if self.__requirements is not None: return 'SAGE_VENV' return 'SAGE_LOCAL' @@ -355,6 +356,13 @@ def distribution_name(self): """ Return the Python distribution name or ``None`` for non-Python packages """ + if self.__requirements is not None: + for line in self.__requirements.split('\n'): + line = line.strip() + if line.startswith('#'): + continue + for part in line.split(): + return part if self.__version_requirements is None: return None for line in self.__version_requirements.split('\n'): @@ -517,6 +525,13 @@ def _init_version_requirements(self): except IOError: self.__version_requirements = None + def _init_requirements(self): + try: + with open(os.path.join(self.path, 'requirements.txt')) as f: + self.__requirements = f.read().strip() + except IOError: + self.__requirements = None + def _init_dependencies(self): try: with open(os.path.join(self.path, 'dependencies')) as f: From acaf5483ea054bf180c388481b1a5beb9cfd2507 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 7 Feb 2024 19:45:26 -0800 Subject: [PATCH 02/22] sage_bootstrap.package: Do not log an error on GeneratorExit --- build/sage_bootstrap/package.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index 458297c1bec..beed1dbc04c 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -428,7 +428,7 @@ def all(cls): continue try: yield cls(subdir) - except BaseException: + except Exception: log.error('Failed to open %s', subdir) raise From e9d3d4db84aafab164ea8ca4ba0124fd127a7e49 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 7 Feb 2024 22:03:40 -0800 Subject: [PATCH 03/22] sage_bootstrap.package: Support constructing Package from 'pypi:DISTRIBUTION-NAME' --- build/sage_bootstrap/package.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index beed1dbc04c..162fa5af87c 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -25,6 +25,21 @@ class Package(object): + def __new__(cls, package_name): + if package_name.startswith("pypi:"): + def normalize(name): + return name.lower().replace('_', '-') + + pypi_name = normalize(package_name[len("pypi:"):]) + for pkg in cls.all(): + distribution = pkg.distribution_name + if distribution and normalize(distribution) == pypi_name: + return pkg # assume unique + raise ValueError('no package for distribution {0}'.format(pypi_name)) + self = object.__new__(cls) + self.__init__(package_name) + return self + def __init__(self, package_name): """ Sage Package @@ -41,6 +56,14 @@ def __init__(self, package_name): -- ``package_name`` -- string. Name of the package. The Sage convention is that all package names are lower case. """ + if package_name.startswith("pypi:"): + # Already initialized + return + if package_name != package_name.lower(): + raise ValueError('package names should be lowercase, got {0}'.format(package_name)) + if '-' in package_name: + raise ValueError('package names use underscores, not dashes, got {0}'.format(package_name)) + self.__name = package_name self.__tarball = None self._init_checksum() From 8eef2449ae0330ba8c51b2865cced6b62451eabc Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 7 Feb 2024 22:05:02 -0800 Subject: [PATCH 04/22] sage_bootstrap.expand_class: Support 'pypi:DISTRIBUTION-NAME', reject dashes in SPKG names --- build/sage_bootstrap/expand_class.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/build/sage_bootstrap/expand_class.py b/build/sage_bootstrap/expand_class.py index c7fdb308bd3..d6f9724bbe8 100644 --- a/build/sage_bootstrap/expand_class.py +++ b/build/sage_bootstrap/expand_class.py @@ -52,12 +52,18 @@ def included_in_filter(pkg): self._init_optional(predicate=included_in_filter) elif package_name_or_class == ':experimental:': self._init_experimental(predicate=included_in_filter) + elif package_name_or_class.startswith('pypi:'): + self.__names.add(Package(package_name_or_class).name) else: if ':' in package_name_or_class: - raise ValueError('a colon may only appear in designators of package types, ' + raise ValueError('a colon may only appear in pypi:DISTRIBUTION-NAME ' + 'and in designators of package types, ' 'which must be one of ' ':all:, :standard:, :optional:, or :experimental:' 'got {}'.format(package_name_or_class)) + if '-' in package_name_or_class: + raise ValueError('dashes may only appear in pypi:DISTRIBUTION-NAME; ' + 'SPKG names use underscores') self.__names.add(package_name_or_class) def include_recursive_dependencies(names, package_name): From 2d63a8c39c3bb620be4ea928d2a286ab219921a2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 7 Feb 2024 22:17:06 -0800 Subject: [PATCH 05/22] sage -package: Accept package names in the format pypi:DISTRIBUTION-NAME --- build/sage_bootstrap/app.py | 5 ++++- build/sage_bootstrap/cmdline.py | 23 +++++++++++++---------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 0a4e984e3ff..6de178a80a4 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -395,7 +395,10 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre $ sage --package create jupyterlab_markup --pypi --source wheel --type optional """ - if '-' in package_name: + if package_name.startswith('pypi:'): + pypi = True + package_name = package_name[len('pypi:'):].lower().replace('-', '_') + elif '-' in package_name: raise ValueError('package names must not contain dashes, use underscore instead') if pypi: if source is None: diff --git a/build/sage_bootstrap/cmdline.py b/build/sage_bootstrap/cmdline.py index 3ed185a9185..813a51de8d4 100644 --- a/build/sage_bootstrap/cmdline.py +++ b/build/sage_bootstrap/cmdline.py @@ -277,9 +277,10 @@ def make_parser(): formatter_class=argparse.RawDescriptionHelpFormatter, help='Print a list of packages known to Sage') parser_list.add_argument( - 'package_class', metavar='[package_name|:package_type:]', + 'package_class', metavar='[PACKAGE_NAME|pypi:DISTRIBUTION-NAME|:PACKAGE_TYPE:]', type=str, default=[':all-or-nothing:'], nargs='*', - help=('package name or designator for all packages of a given type ' + help=('package name, pypi: followed by a distribution name, ' + 'or designator for all packages of a given type ' '(one of :all:, :standard:, :optional:, and :experimental:); ' 'default: :all: (or nothing when --include-dependencies or --exclude-dependencies is given')) parser_list.add_argument( @@ -305,9 +306,10 @@ def make_parser(): formatter_class=argparse.RawDescriptionHelpFormatter, help='Print properties of given packages') parser_properties.add_argument( - 'package_class', metavar='[package_name|:package_type:]', + 'package_class', metavar='[PACKAGE_NAME|pypi:DISTRIBUTION-NAME|:PACKAGE_TYPE:]', type=str, nargs='+', - help=('package name or designator for all packages of a given type ' + help=('package name, pypi: followed by a distribution name, ' + 'or designator for all packages of a given type ' '(one of :all:, :standard:, :optional:, and :experimental:)')) parser_properties.add_argument( '--format', type=str, default='plain', @@ -410,11 +412,11 @@ def make_parser(): formatter_class=argparse.RawDescriptionHelpFormatter, help='Fix the checksum of normal packages.') parser_fix_checksum.add_argument( - 'package_class', metavar='[package_name|:package_type:]', + 'package_class', metavar='[PACKAGE_NAME|pypi:DISTRIBUTION-NAME|:PACKAGE_TYPE:]', type=str, default=[':all:'], nargs='*', - help=('package name or designator for all packages of a given type ' - '(one of :all:, :standard:, :optional:, and :experimental:); ' - 'default: :all:')) + help=('package name, pypi: followed by a distribution name, ' + 'or designator for all packages of a given type ' + '(one of :all:, :standard:, :optional:, and :experimental:; default: :all:)')) parser_create = subparsers.add_parser( 'create', epilog=epilog_create, @@ -453,9 +455,10 @@ def make_parser(): formatter_class=argparse.RawDescriptionHelpFormatter, help='Print metrics of given packages') parser_metrics.add_argument( - 'package_class', metavar='[package_name|:package_type:]', + 'package_class', metavar='[PACKAGE_NAME|pypi:DISTRIBUTION-NAME|:PACKAGE_TYPE:]', type=str, nargs='*', default=[':all:'], - help=('package name or designator for all packages of a given type ' + help=('package name, pypi: followed by a distribution name, ' + 'or designator for all packages of a given type ' '(one of :all:, :standard:, :optional:, and :experimental:; default: :all:)')) return parser From 2ab19392f39112941c0014b504808c9f96c7d189 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Tue, 7 May 2024 18:34:30 -0700 Subject: [PATCH 06/22] build/bin/sage-get-system-packages: Handle packages in the format pypi:DISTRIBUTION-NAME --- build/bin/sage-get-system-packages | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/build/bin/sage-get-system-packages b/build/bin/sage-get-system-packages index 0172155023d..aab46a54473 100755 --- a/build/bin/sage-get-system-packages +++ b/build/bin/sage-get-system-packages @@ -50,6 +50,12 @@ case "$SYSTEM" in ;; esac +case "$SPKGS" in + *pypi:*) + PATH="${SAGE_ROOT}/build/bin:$PATH" SPKGS=$(sage-package list $SPKGS) + ;; +esac + for PKG_BASE in $SPKGS; do if [ $FROM_PYPROJECT_TOML -eq 1 ]; then if [ -f "$SAGE_ROOT/src/pyproject.toml" ]; then From 92f11c69fe5d6fa241daa7b95371b2981223b84d Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 25 Feb 2024 23:07:17 -0800 Subject: [PATCH 07/22] Use PURL instead of ad-hoc package nickname --- build/bin/sage-get-system-packages | 2 +- build/sage_bootstrap/app.py | 4 ++-- build/sage_bootstrap/cmdline.py | 16 ++++++++-------- build/sage_bootstrap/expand_class.py | 6 +++--- build/sage_bootstrap/package.py | 6 +++--- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/build/bin/sage-get-system-packages b/build/bin/sage-get-system-packages index aab46a54473..980f9406a9b 100755 --- a/build/bin/sage-get-system-packages +++ b/build/bin/sage-get-system-packages @@ -51,7 +51,7 @@ case "$SYSTEM" in esac case "$SPKGS" in - *pypi:*) + *pkg:pypi/*) PATH="${SAGE_ROOT}/build/bin:$PATH" SPKGS=$(sage-package list $SPKGS) ;; esac diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 6de178a80a4..e1266443c41 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -395,9 +395,9 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre $ sage --package create jupyterlab_markup --pypi --source wheel --type optional """ - if package_name.startswith('pypi:'): + if package_name.startswith('pkg:pypi/'): pypi = True - package_name = package_name[len('pypi:'):].lower().replace('-', '_') + package_name = package_name[len('pkg:pypi/'):].lower().replace('-', '_') elif '-' in package_name: raise ValueError('package names must not contain dashes, use underscore instead') if pypi: diff --git a/build/sage_bootstrap/cmdline.py b/build/sage_bootstrap/cmdline.py index 813a51de8d4..6c30b2ad231 100644 --- a/build/sage_bootstrap/cmdline.py +++ b/build/sage_bootstrap/cmdline.py @@ -277,9 +277,9 @@ def make_parser(): formatter_class=argparse.RawDescriptionHelpFormatter, help='Print a list of packages known to Sage') parser_list.add_argument( - 'package_class', metavar='[PACKAGE_NAME|pypi:DISTRIBUTION-NAME|:PACKAGE_TYPE:]', + 'package_class', metavar='[PACKAGE_NAME|pkg:pypi/DISTRIBUTION-NAME|:PACKAGE_TYPE:]', type=str, default=[':all-or-nothing:'], nargs='*', - help=('package name, pypi: followed by a distribution name, ' + help=('package name, pkg:pypi/ followed by a distribution name, ' 'or designator for all packages of a given type ' '(one of :all:, :standard:, :optional:, and :experimental:); ' 'default: :all: (or nothing when --include-dependencies or --exclude-dependencies is given')) @@ -306,9 +306,9 @@ def make_parser(): formatter_class=argparse.RawDescriptionHelpFormatter, help='Print properties of given packages') parser_properties.add_argument( - 'package_class', metavar='[PACKAGE_NAME|pypi:DISTRIBUTION-NAME|:PACKAGE_TYPE:]', + 'package_class', metavar='[PACKAGE_NAME|pkg:pypi/DISTRIBUTION-NAME|:PACKAGE_TYPE:]', type=str, nargs='+', - help=('package name, pypi: followed by a distribution name, ' + help=('package name, pkg:pypi/ followed by a distribution name, ' 'or designator for all packages of a given type ' '(one of :all:, :standard:, :optional:, and :experimental:)')) parser_properties.add_argument( @@ -412,9 +412,9 @@ def make_parser(): formatter_class=argparse.RawDescriptionHelpFormatter, help='Fix the checksum of normal packages.') parser_fix_checksum.add_argument( - 'package_class', metavar='[PACKAGE_NAME|pypi:DISTRIBUTION-NAME|:PACKAGE_TYPE:]', + 'package_class', metavar='[PACKAGE_NAME|pkg:pypi/DISTRIBUTION-NAME|:PACKAGE_TYPE:]', type=str, default=[':all:'], nargs='*', - help=('package name, pypi: followed by a distribution name, ' + help=('package name, pkg:pypi/ followed by a distribution name, ' 'or designator for all packages of a given type ' '(one of :all:, :standard:, :optional:, and :experimental:; default: :all:)')) @@ -455,9 +455,9 @@ def make_parser(): formatter_class=argparse.RawDescriptionHelpFormatter, help='Print metrics of given packages') parser_metrics.add_argument( - 'package_class', metavar='[PACKAGE_NAME|pypi:DISTRIBUTION-NAME|:PACKAGE_TYPE:]', + 'package_class', metavar='[PACKAGE_NAME|pkg:pypi/DISTRIBUTION-NAME|:PACKAGE_TYPE:]', type=str, nargs='*', default=[':all:'], - help=('package name, pypi: followed by a distribution name, ' + help=('package name, pkg:pypi/ followed by a distribution name, ' 'or designator for all packages of a given type ' '(one of :all:, :standard:, :optional:, and :experimental:; default: :all:)')) diff --git a/build/sage_bootstrap/expand_class.py b/build/sage_bootstrap/expand_class.py index d6f9724bbe8..cdf94cd0998 100644 --- a/build/sage_bootstrap/expand_class.py +++ b/build/sage_bootstrap/expand_class.py @@ -52,17 +52,17 @@ def included_in_filter(pkg): self._init_optional(predicate=included_in_filter) elif package_name_or_class == ':experimental:': self._init_experimental(predicate=included_in_filter) - elif package_name_or_class.startswith('pypi:'): + elif package_name_or_class.startswith('pkg:pypi/'): self.__names.add(Package(package_name_or_class).name) else: if ':' in package_name_or_class: - raise ValueError('a colon may only appear in pypi:DISTRIBUTION-NAME ' + raise ValueError('a colon may only appear in pkg:pypi/DISTRIBUTION-NAME ' 'and in designators of package types, ' 'which must be one of ' ':all:, :standard:, :optional:, or :experimental:' 'got {}'.format(package_name_or_class)) if '-' in package_name_or_class: - raise ValueError('dashes may only appear in pypi:DISTRIBUTION-NAME; ' + raise ValueError('dashes may only appear in pkg:pypi/DISTRIBUTION-NAME; ' 'SPKG names use underscores') self.__names.add(package_name_or_class) diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index 162fa5af87c..56e3632e49f 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -26,11 +26,11 @@ class Package(object): def __new__(cls, package_name): - if package_name.startswith("pypi:"): + if package_name.startswith("pkg:pypi/"): def normalize(name): return name.lower().replace('_', '-') - pypi_name = normalize(package_name[len("pypi:"):]) + pypi_name = normalize(package_name[len("pkg:pypi/"):]) for pkg in cls.all(): distribution = pkg.distribution_name if distribution and normalize(distribution) == pypi_name: @@ -56,7 +56,7 @@ def __init__(self, package_name): -- ``package_name`` -- string. Name of the package. The Sage convention is that all package names are lower case. """ - if package_name.startswith("pypi:"): + if package_name.startswith("pkg:pypi/"): # Already initialized return if package_name != package_name.lower(): From 6530e59913d9d50b0e18f4737a32559ae88467f2 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 31 Mar 2024 17:48:48 -0700 Subject: [PATCH 08/22] src/doc/en/developer/packaging.rst: Use PURLs pkg:pypi/DISTRIBUTION-NAME --- src/doc/en/developer/packaging.rst | 58 ++++++++++++++++-------------- 1 file changed, 32 insertions(+), 26 deletions(-) diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index 83720282c35..c472f9c1905 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -14,7 +14,7 @@ The installation of packages is done through a bash script located in :sage_root:`build/bin/sage-spkg`. This script is typically invoked by giving the command:: - [alice@localhost sage]$ sage -i ... + [alice@localhost sage]$ ./sage -i ... options can be: @@ -1049,10 +1049,10 @@ Creating packages Assuming that you have downloaded ``$SAGE_ROOT/upstream/FoO-1.3.tar.gz``, you can use:: - [alice@localhost sage]$ sage --package create foo \ - --version 1.3 \ - --tarball FoO-VERSION.tar.gz \ - --type experimental + [alice@localhost sage]$ ./sage --package create foo \ + --version 1.3 \ + --tarball FoO-VERSION.tar.gz \ + --type experimental to create ``$SAGE_ROOT/build/pkgs/foo/package-version.txt``, ``checksums.ini``, and ``type`` in one step. @@ -1061,15 +1061,21 @@ You can skip the manual downloading of the upstream tarball by using the additional argument ``--upstream-url``. This command will also set the ``upstream_url`` field in ``checksums.ini`` described above. -For Python packages available from PyPI, you can use:: +For Python packages available from PyPI, use a PURL (Package URL, +see `PEP 725 `_):: + + [alice@localhost sage]$ ./sage --package create pkg:pypi/scikit-spatial \ + --type optional + +An equivalent command uses the SPKG name of the new package:: [alice@localhost sage]$ sage --package create scikit_spatial --pypi \ --type optional -This automatically downloads the most recent version from PyPI and also -obtains most of the necessary information by querying PyPI. In particular, -the ``SPKG.rst`` file is created as a copy of the package's README file. - +Either of these two commands automatically downloads the most recent version +from PyPI and also obtains most of the necessary information by querying PyPI. +In particular, the ``SPKG.rst`` file is created as a copy of the package's +README file. The ``dependencies`` file may need editing (watch out for warnings regarding ``--no-deps`` that Sage issues during installation of the package!). @@ -1082,15 +1088,15 @@ By default, when the package is available as a platform-independent wheel, the ``sage --package`` creates a wheel package. To create a normal package instead (for example, when the package requires patching), you can use:: - [alice@localhost sage]$ sage --package create scikit_spatial --pypi \ - --source normal \ - --type optional + [alice@localhost sage]$ ./sage --package create pkg:pypi/scikit-spatial \ + --source normal \ + --type optional To create a pip package rather than a normal or wheel package, you can use:: - [alice@localhost sage]$ sage --package create scikit_spatial --pypi \ - --source pip \ - --type optional + [alice@localhost sage]$ ./sage --package create pkg:pypi/scikit-spatial \ + --source pip \ + --type optional When the package already exists, ``sage --package create`` overwrites it. @@ -1101,14 +1107,14 @@ Updating packages to a new version A package that has the ``upstream_url`` information can be updated by simply typing:: - [alice@localhost sage]$ sage --package update numpy 3.14.59 + [alice@localhost sage]$ ./sage --package update openblas 0.3.79 which will automatically download the archive and update the -information in ``build/pkgs/numpy/``. +information in ``build/pkgs/openblas/``. For Python packages available from PyPI, there is another shortcut:: - [alice@localhost sage]$ sage --package update-latest matplotlib + [alice@localhost sage]$ ./sage --package update-latest pkg:pypi/matplotlib Updating matplotlib: 3.3.0 -> 3.3.1 Downloading tarball to ...matplotlib-3.3.1.tar.bz2 [...............................................................] @@ -1122,10 +1128,10 @@ version range! If you pass the switch ``--commit``, the script will run ``git commit`` for you. -If you prefer to make update a package ``foo`` by making manual +If you prefer to update a package ``foo`` by making manual changes to the files in ``build/pkgs/foo``, you will need to run:: - [alice@localhost sage]$ sage --package fix-checksum foo + [alice@localhost sage]$ ./sage --package fix-checksum foo which will modify the ``checksums.ini`` file with the correct checksums. @@ -1138,7 +1144,7 @@ The command ``sage --package metrics`` computes machine-readable aggregated metrics for all packages in the Sage distribution or a given list of packages:: - [alice@localhost sage]$ sage --package metrics + [alice@localhost sage]$ ./sage --package metrics has_file_distros_arch_txt=181 has_file_distros_conda_txt=289 has_file_distros_debian_txt=172 @@ -1212,20 +1218,20 @@ Sage (``FoO-1.3.tar.gz`` in the example of section Now you can install the package using:: - [alice@localhost sage]$ sage -i package_name + [alice@localhost sage]$ ./sage -i package_name or:: - [alice@localhost sage]$ sage -f package_name + [alice@localhost sage]$ ./sage -f package_name to force a reinstallation. If your package contains a ``spkg-check`` script (see :ref:`section-spkg-check`) it can be run with:: - [alice@localhost sage]$ sage -i -c package_name + [alice@localhost sage]$ ./sage -i -c package_name or:: - [alice@localhost sage]$ sage -f -c package_name + [alice@localhost sage]$ ./sage -f -c package_name If all went fine, open a PR with the code under :sage_root:`build/pkgs`. From 92a897fe306bf9c122f5ea7829fb8ae68b566b73 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 28 Feb 2024 19:27:52 -0800 Subject: [PATCH 09/22] Accept abbreviated PURL without scheme and pkg:generic/NAME, print PURL in sage --package properties --- build/bin/sage-get-system-packages | 2 +- build/sage_bootstrap/app.py | 2 +- build/sage_bootstrap/expand_class.py | 9 ++++-- build/sage_bootstrap/package.py | 47 ++++++++++++++++++++++------ 4 files changed, 46 insertions(+), 14 deletions(-) diff --git a/build/bin/sage-get-system-packages b/build/bin/sage-get-system-packages index 980f9406a9b..0a90232ed6e 100755 --- a/build/bin/sage-get-system-packages +++ b/build/bin/sage-get-system-packages @@ -51,7 +51,7 @@ case "$SYSTEM" in esac case "$SPKGS" in - *pkg:pypi/*) + *pkg:*|pypi/*|generic/*) PATH="${SAGE_ROOT}/build/bin:$PATH" SPKGS=$(sage-package list $SPKGS) ;; esac diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index e1266443c41..79a4f287dce 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -88,7 +88,7 @@ def properties(self, *package_classes, **kwds): source_maxima='normal' trees_maxima='SAGE_LOCAL' """ - props = kwds.pop('props', ['path', 'version_with_patchlevel', 'type', 'source', 'trees']) + props = kwds.pop('props', ['path', 'version_with_patchlevel', 'type', 'source', 'trees', 'purl']) format = kwds.pop('format', 'plain') log.debug('Looking up properties') pc = PackageClass(*package_classes) diff --git a/build/sage_bootstrap/expand_class.py b/build/sage_bootstrap/expand_class.py index cdf94cd0998..ee43a063c27 100644 --- a/build/sage_bootstrap/expand_class.py +++ b/build/sage_bootstrap/expand_class.py @@ -52,17 +52,20 @@ def included_in_filter(pkg): self._init_optional(predicate=included_in_filter) elif package_name_or_class == ':experimental:': self._init_experimental(predicate=included_in_filter) - elif package_name_or_class.startswith('pkg:pypi/'): + elif any(package_name_or_class.startswith(prefix) + for prefix in ["pkg:", "pypi/", "generic"]): self.__names.add(Package(package_name_or_class).name) else: if ':' in package_name_or_class: - raise ValueError('a colon may only appear in pkg:pypi/DISTRIBUTION-NAME ' + raise ValueError('a colon may only appear in a PURL such as ' + 'pkg:pypi/DISTRIBUTION-NAME ' 'and in designators of package types, ' 'which must be one of ' ':all:, :standard:, :optional:, or :experimental:' 'got {}'.format(package_name_or_class)) if '-' in package_name_or_class: - raise ValueError('dashes may only appear in pkg:pypi/DISTRIBUTION-NAME; ' + raise ValueError('dashes may only appear in a PURL such as ' + 'pkg:pypi/DISTRIBUTION-NAME; ' 'SPKG names use underscores') self.__names.add(package_name_or_class) diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index 56e3632e49f..08387d467a2 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -26,16 +26,27 @@ class Package(object): def __new__(cls, package_name): - if package_name.startswith("pkg:pypi/"): - def normalize(name): - return name.lower().replace('_', '-') - - pypi_name = normalize(package_name[len("pkg:pypi/"):]) + if package_name.startswith("pypi/") or package_name.startswith("generic/"): + package_name = "pkg:" + package_name + if package_name.startswith("pkg:"): + if package_name.startswith("pkg:generic/"): # fast path + try: + pkg = cls(package_name[len("pkg:generic/"):].replace('-', '_')) + if pkg.purl == package_name: + return pkg # assume unique + except Exception: + pass + elif package_name.startswith("pkg:pypi/"): # fast path + try: + pkg = cls(package_name[len("pkg:pypi/"):].replace('-', '_')) + if pkg.purl == package_name: + return pkg # assume unique + except Exception: + pass for pkg in cls.all(): - distribution = pkg.distribution_name - if distribution and normalize(distribution) == pypi_name: + if pkg.purl == package_name: return pkg # assume unique - raise ValueError('no package for distribution {0}'.format(pypi_name)) + raise ValueError('no package for PURL {0}'.format(package_name)) self = object.__new__(cls) self.__init__(package_name) return self @@ -56,7 +67,8 @@ def __init__(self, package_name): -- ``package_name`` -- string. Name of the package. The Sage convention is that all package names are lower case. """ - if package_name.startswith("pkg:pypi/"): + if any(package_name.startswith(prefix) + for prefix in ["pkg:", "pypi/", "generic"]): # Already initialized return if package_name != package_name.lower(): @@ -374,6 +386,23 @@ def trees(self): return 'SAGE_VENV' return 'SAGE_LOCAL' + @property + def purl(self): + """ + Return a PURL (Package URL) for the package + + OUTPUT: + + A string in the format ``SCHEME:TYPE/NAMESPACE/NAME``, + i.e., without components for version, qualifiers, and subpath. + See https://github.com/package-url/purl-spec/blob/master/PURL-SPECIFICATION.rst#package-url-specification-v10x + for details + """ + dist = self.distribution_name + if dist: + return 'pkg:pypi/' + dist.lower().replace('_', '-') + return 'pkg:generic/' + self.name.replace('_', '-') + @property def distribution_name(self): """ From e929fedf7bff1536dcd17eb612276c91dc85d490 Mon Sep 17 00:00:00 2001 From: Marc Culler Date: Wed, 6 Mar 2024 21:59:16 -0800 Subject: [PATCH 10/22] build/sage_bootstrap/app.py (create): Parse dependencies from PyPI --- build/sage_bootstrap/app.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 79a4f287dce..623f87f61e0 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -21,6 +21,7 @@ import os +import re import logging log = logging.getLogger() @@ -36,6 +37,9 @@ from sage_bootstrap.env import SAGE_DISTFILES +dep_re = re.compile('([^<>=]*)') + + class Application(object): def config(self): @@ -383,7 +387,8 @@ def fix_checksum(self, package_name): update.fix_checksum() def create(self, package_name, version=None, tarball=None, pkg_type=None, upstream_url=None, - description=None, license=None, upstream_contact=None, pypi=False, source=None): + description=None, license=None, upstream_contact=None, pypi=False, source=None, + dependencies=None): """ Create a package @@ -426,6 +431,19 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre raise ValueError('Only platform-independent wheels can be used for wheel packages, got {0}'.format(tarball)) if not version: version = pypi_version.version + if dependencies is None: + requires_dist = pypi_version.requires_dist + print(requires_dist) + if requires_dist: + dependencies = [] + for item in requires_dist: + if "extra ==" in item: + continue + try: + dep = dep_re.match(item).groups()[0] + except Exception: + continue + dependencies.append(dep) upstream_url = 'https://pypi.io/packages/{2}/{0:1.1}/{0}/{1}'.format(package_name, tarball, pypi_version.python_version) if not description: description = pypi_version.summary From b204fc662098ee0c6313c21c543ea0b5154ecba9 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Mar 2024 21:59:33 -0800 Subject: [PATCH 11/22] build/sage_bootstrap/app.py: Update copyright --- build/sage_bootstrap/app.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 623f87f61e0..87d8c6e2e67 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -10,7 +10,10 @@ # **************************************************************************** -# Copyright (C) 2016 Volker Braun +# Copyright (C) 2016 Volker Braun +# 2020-2024 Matthias Koeppe +# 2022 Thierry Monteil +# 2024 Marc Culler # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by From 920e8866229296da4fdfaa0204f3c208ae775be0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Mar 2024 22:00:19 -0800 Subject: [PATCH 12/22] sage --package create: Allow abbreviating pkg:pypi/DISTRIBUTION as pypi/DISTRIBUTION --- build/sage_bootstrap/app.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 87d8c6e2e67..ddceb23e8a1 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -403,6 +403,8 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre $ sage --package create jupyterlab_markup --pypi --source wheel --type optional """ + if package_name.startswith('pypi/'): + package_name = 'pkg:' + package_name if package_name.startswith('pkg:pypi/'): pypi = True package_name = package_name[len('pkg:pypi/'):].lower().replace('-', '_') From b68cd577d4482c57d4fdd40979a238940bdfa227 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Mar 2024 22:01:15 -0800 Subject: [PATCH 13/22] build/sage_bootstrap/creator.py: Use parameter dependencies; for wheels, use pip instead of PYTHON_TOOLCHAIN --- build/sage_bootstrap/app.py | 3 ++- build/sage_bootstrap/creator.py | 12 ++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index ddceb23e8a1..4ccc6838a5f 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -473,7 +473,8 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre if description or license or upstream_contact: creator.set_description(description, license, upstream_contact) if pypi or source == 'pip': - creator.set_python_data_and_scripts(pypi_package_name=pypi_version.name, source=source) + creator.set_python_data_and_scripts(pypi_package_name=pypi_version.name, source=source, + dependencies=dependencies) if tarball: creator.set_tarball(tarball, upstream_url) if upstream_url and version: diff --git a/build/sage_bootstrap/creator.py b/build/sage_bootstrap/creator.py index a738d772215..205a32aebab 100644 --- a/build/sage_bootstrap/creator.py +++ b/build/sage_bootstrap/creator.py @@ -105,7 +105,7 @@ def _remove_files(self, files): except OSError: pass - def set_python_data_and_scripts(self, pypi_package_name=None, source='normal'): + def set_python_data_and_scripts(self, pypi_package_name=None, source='normal', dependencies=None): """ Write the file ``dependencies`` and other files for Python packages. @@ -121,7 +121,15 @@ def set_python_data_and_scripts(self, pypi_package_name=None, source='normal'): if pypi_package_name is None: pypi_package_name = self.package_name with open(os.path.join(self.path, 'dependencies'), 'w+') as f: - f.write(' | $(PYTHON_TOOLCHAIN) $(PYTHON)\n\n') + if dependencies: + dependencies = ' '.join(dependencies) + else: + dependencies = '' + if source == 'wheel': + dependencies_order_only = 'pip $(PYTHON)' + else: + dependencies_order_only = '$(PYTHON_TOOLCHAIN) $(PYTHON)' + f.write(dependencies + ' | ' + dependencies_order_only + '\n\n') f.write('----------\nAll lines of this file are ignored except the first.\n') if source == 'normal': with open(os.path.join(self.path, 'spkg-install.in'), 'w+') as f: From 703ec234dcf2d43e0bd98740d8447078abaa1a1d Mon Sep 17 00:00:00 2001 From: Marc Culler Date: Wed, 6 Mar 2024 22:01:50 -0800 Subject: [PATCH 14/22] build/sage_bootstrap/pypi.py: Get requires_dist from json --- build/sage_bootstrap/pypi.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build/sage_bootstrap/pypi.py b/build/sage_bootstrap/pypi.py index e3ca4e560c7..346c0c0e57e 100644 --- a/build/sage_bootstrap/pypi.py +++ b/build/sage_bootstrap/pypi.py @@ -106,6 +106,13 @@ def summary(self): """ return self.json['info']['summary'] + @property + def requires_dist(self): + """ + Return the dependencies + """ + return self.json['info']['requires_dist'] + def update(self, package=None): if package is None: package = Package(self.name) From dbb78c257df0992a279a2226bd3490cdd9332a24 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Mar 2024 22:19:57 -0800 Subject: [PATCH 15/22] build/sage_bootstrap/app.py: Dots in distribution names become underscores too --- build/sage_bootstrap/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 4ccc6838a5f..eb358610ccd 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -407,7 +407,7 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre package_name = 'pkg:' + package_name if package_name.startswith('pkg:pypi/'): pypi = True - package_name = package_name[len('pkg:pypi/'):].lower().replace('-', '_') + package_name = package_name[len('pkg:pypi/'):].lower().replace('-', '_').replace('.', '_') elif '-' in package_name: raise ValueError('package names must not contain dashes, use underscore instead') if pypi: From a4b6fd20773992c2445eb71dc64a28877220d4e1 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Mar 2024 22:20:31 -0800 Subject: [PATCH 16/22] build/sage_bootstrap/app.py: Recursively create PyPI packages that are dependencies --- build/sage_bootstrap/app.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index eb358610ccd..ecc114d657b 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -438,16 +438,21 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre version = pypi_version.version if dependencies is None: requires_dist = pypi_version.requires_dist - print(requires_dist) if requires_dist: dependencies = [] for item in requires_dist: if "extra ==" in item: continue try: - dep = dep_re.match(item).groups()[0] + dep = dep_re.match(item).groups()[0].strip() except Exception: continue + dep = 'pkg:pypi/' + dep + try: + dep = Package(dep).name + except ValueError: + self.create(dep, pkg_type=pkg_type) + dep = Package(dep).name dependencies.append(dep) upstream_url = 'https://pypi.io/packages/{2}/{0:1.1}/{0}/{1}'.format(package_name, tarball, pypi_version.python_version) if not description: From 00401261ae674ef9ed4bec14471ec0f8d3409871 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Mar 2024 22:26:24 -0800 Subject: [PATCH 17/22] build/sage_bootstrap/package.py: Normalize PURLs before lookup --- build/sage_bootstrap/package.py | 1 + 1 file changed, 1 insertion(+) diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index 08387d467a2..3fe69d4327e 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -29,6 +29,7 @@ def __new__(cls, package_name): if package_name.startswith("pypi/") or package_name.startswith("generic/"): package_name = "pkg:" + package_name if package_name.startswith("pkg:"): + package_name = package_name.replace('_', '-') if package_name.startswith("pkg:generic/"): # fast path try: pkg = cls(package_name[len("pkg:generic/"):].replace('-', '_')) From f18b25826b1ab7224e0130e0da785999986dcba0 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Mar 2024 22:39:54 -0800 Subject: [PATCH 18/22] build/sage_bootstrap: Update copyright --- build/sage_bootstrap/cmdline.py | 4 +++- build/sage_bootstrap/creator.py | 3 ++- build/sage_bootstrap/download/cmdline.py | 4 +++- build/sage_bootstrap/download/mirror_list.py | 4 +++- build/sage_bootstrap/expand_class.py | 3 ++- build/sage_bootstrap/package.py | 4 +++- build/sage_bootstrap/pypi.py | 3 ++- build/sage_bootstrap/tarball.py | 4 +++- build/sage_bootstrap/uninstall.py | 4 +++- 9 files changed, 24 insertions(+), 9 deletions(-) diff --git a/build/sage_bootstrap/cmdline.py b/build/sage_bootstrap/cmdline.py index 6c30b2ad231..a9ea516b94d 100644 --- a/build/sage_bootstrap/cmdline.py +++ b/build/sage_bootstrap/cmdline.py @@ -12,7 +12,9 @@ """ # **************************************************************************** -# Copyright (C) 2016 Volker Braun +# Copyright (C) 2015-2016 Volker Braun +# 2020-2024 Matthias Koeppe +# 2022 Thierry Monteil # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/build/sage_bootstrap/creator.py b/build/sage_bootstrap/creator.py index 205a32aebab..e16002f12f9 100644 --- a/build/sage_bootstrap/creator.py +++ b/build/sage_bootstrap/creator.py @@ -4,7 +4,8 @@ """ # **************************************************************************** -# Copyright (C) 2016 Volker Braun +# Copyright (C) 2015-2016 Volker Braun +# 2020-2024 Matthias Koeppe # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/build/sage_bootstrap/download/cmdline.py b/build/sage_bootstrap/download/cmdline.py index a6afb4f92be..594cc773b38 100644 --- a/build/sage_bootstrap/download/cmdline.py +++ b/build/sage_bootstrap/download/cmdline.py @@ -6,7 +6,9 @@ """ # **************************************************************************** -# Copyright (C) 2016 Volker Braun +# Copyright (C) 2015-2016 Volker Braun +# 2015 Jeroen Demeyer +# 2020 Matthias Koeppe # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/build/sage_bootstrap/download/mirror_list.py b/build/sage_bootstrap/download/mirror_list.py index 4cab19f5d64..f464d87ffbd 100644 --- a/build/sage_bootstrap/download/mirror_list.py +++ b/build/sage_bootstrap/download/mirror_list.py @@ -4,7 +4,9 @@ """ #***************************************************************************** -# Copyright (C) 2015 Volker Braun +# Copyright (C) 2014-2016 Volker Braun +# 2015 Jeroen Demeyer +# 2023 Matthias Koeppe # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/build/sage_bootstrap/expand_class.py b/build/sage_bootstrap/expand_class.py index ee43a063c27..c5bab8a313e 100644 --- a/build/sage_bootstrap/expand_class.py +++ b/build/sage_bootstrap/expand_class.py @@ -4,7 +4,8 @@ """ # **************************************************************************** -# Copyright (C) 2016 Volker Braun +# Copyright (C) 2016 Volker Braun +# 2020-2024 Matthias Koeppe # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index 3fe69d4327e..176e842e43b 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -4,7 +4,9 @@ """ # **************************************************************************** -# Copyright (C) 2015 Volker Braun +# Copyright (C) 2015-2016 Volker Braun +# 2018 Jeroen Demeyer +# 2020-2024 Matthias Koeppe # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/build/sage_bootstrap/pypi.py b/build/sage_bootstrap/pypi.py index 346c0c0e57e..9427e9c8808 100644 --- a/build/sage_bootstrap/pypi.py +++ b/build/sage_bootstrap/pypi.py @@ -5,7 +5,8 @@ # **************************************************************************** -# Copyright (C) 2016 Volker Braun +# Copyright (C) 2016 Volker Braun +# 2020-2023 Matthias Koeppe # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/build/sage_bootstrap/tarball.py b/build/sage_bootstrap/tarball.py index 441d97cb3c6..c974d8ac310 100644 --- a/build/sage_bootstrap/tarball.py +++ b/build/sage_bootstrap/tarball.py @@ -4,7 +4,9 @@ """ # **************************************************************************** -# Copyright (C) 2015 Volker Braun +# Copyright (C) 2014-2015 Volker Braun +# 2017 Jeroen Demeyer +# 2020 Matthias Koeppe # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/build/sage_bootstrap/uninstall.py b/build/sage_bootstrap/uninstall.py index 08ce337386d..25496246ac7 100644 --- a/build/sage_bootstrap/uninstall.py +++ b/build/sage_bootstrap/uninstall.py @@ -24,7 +24,9 @@ are also removed. """ # **************************************************************************** -# Copyright (C) 2017 Erik M. Bray +# Copyright (C) 2017-2018 Erik M. Bray +# 2019 Jeroen Demeyer +# 2021-2022 Matthias Koeppe # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by From 443eaff8a4c6dc26b8ee44fe26b192f929cd6ed5 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 6 Mar 2024 22:55:55 -0800 Subject: [PATCH 19/22] build/sage_bootstrap/app.py: Better regex for PEP-508 dependencies --- build/sage_bootstrap/app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index ecc114d657b..01c27b4ef46 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -40,7 +40,8 @@ from sage_bootstrap.env import SAGE_DISTFILES -dep_re = re.compile('([^<>=]*)') +# Approximation of https://peps.python.org/pep-0508/#names dependency specification +dep_re = re.compile('^ *([-A-Z0-9._]+)', re.IGNORECASE) class Application(object): From 6e5251ef86844130a2d652130c42dabfa366c668 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sun, 31 Mar 2024 17:49:50 -0700 Subject: [PATCH 20/22] src/doc/en/developer/packaging.rst: 'sage --package create --pypi' now generates dependencies for wheels --- src/doc/en/developer/packaging.rst | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index c472f9c1905..20a6f651028 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -1077,22 +1077,27 @@ from PyPI and also obtains most of the necessary information by querying PyPI. In particular, the ``SPKG.rst`` file is created as a copy of the package's README file. -The ``dependencies`` file may need editing (watch out for warnings regarding -``--no-deps`` that Sage issues during installation of the package!). +By default, when the package is available as a platform-independent +wheel, the ``sage --package`` creates a ``wheel`` package. In this case, +the ``dependencies`` file is automatically generated from the information +on PyPI, but may still need some manual editing. + +For ``normal`` and ``pip`` packages, the ``dependencies`` file is initialized +to the bare minimum and will need manual editing. (Watch out for warnings +regarding ``--no-deps`` that Sage issues during installation of the package!). Also you may want to set lower and upper bounds for acceptable package versions in the file ``version_requirements.txt``. (Make sure that the version in ``package-version.txt`` falls within this acceptable version range!) -By default, when the package is available as a platform-independent -wheel, the ``sage --package`` creates a wheel package. To create a normal package -instead (for example, when the package requires patching), you can use:: +To create a ``normal`` package instead of a ``wheel`` package (for example, when the +package requires patching), you can use:: [alice@localhost sage]$ ./sage --package create pkg:pypi/scikit-spatial \ --source normal \ --type optional -To create a pip package rather than a normal or wheel package, you can use:: +To create a ``pip`` package rather than a ``normal`` or ``wheel`` package, you can use:: [alice@localhost sage]$ ./sage --package create pkg:pypi/scikit-spatial \ --source pip \ From 4358a66c8329c6fcbedd1b4e3cadb1a45f1588b4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Wed, 24 Apr 2024 00:40:01 -0700 Subject: [PATCH 21/22] src/doc/en/developer/packaging.rst: sage -> ./sage --- src/doc/en/developer/packaging.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index 20a6f651028..ab240e12d8c 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -1069,8 +1069,8 @@ see `PEP 725 Date: Thu, 25 Apr 2024 09:46:11 +0900 Subject: [PATCH 22/22] Remove a spurious period. --- src/doc/en/developer/packaging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index ab240e12d8c..6a778c3a71a 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -1084,7 +1084,7 @@ on PyPI, but may still need some manual editing. For ``normal`` and ``pip`` packages, the ``dependencies`` file is initialized to the bare minimum and will need manual editing. (Watch out for warnings -regarding ``--no-deps`` that Sage issues during installation of the package!). +regarding ``--no-deps`` that Sage issues during installation of the package!) Also you may want to set lower and upper bounds for acceptable package versions in the file ``version_requirements.txt``. (Make sure that the version in