Skip to content

Commit

Permalink
sagemathgh-37018: sage --package properties
Browse files Browse the repository at this point in the history
    
<!-- ^^^^^
Please provide a concise, informative and self-explanatory title.
Don't put issue numbers in there, do this in the PR body below.
For example, instead of "Fixes sagemath#1234" use "Introduce new method to
calculate 1+1"
-->
<!-- Describe your changes here in detail -->

For example:
```
$ ./sage -package properties --format shell gap ecl
git:sage_package_properties
path_ecl='/Users/mkoeppe/s/sage/sage-rebasing/worktree-
pristine/build/pkgs/ecl'
version_with_patchlevel_ecl='21.2.1'
type_ecl='standard'
source_ecl='normal'
trees_ecl='SAGE_LOCAL'
path_gap='/Users/mkoeppe/s/sage/sage-rebasing/worktree-
pristine/build/pkgs/gap'
version_with_patchlevel_gap='4.12.2'
type_gap='standard'
source_gap='normal'
trees_gap='SAGE_LOCAL'
```
The output is suitable as input for `eval` in Bourne shell. (The default
output format is more human-friendly.)

<!-- Why is this change required? What problem does it solve? -->
Split out from:
- sagemath#36740

where this new interface is used to eliminate direct references to
`build/pkgs/` from various scripts and reduce code duplication and
complexity in reading SPKG metadata.

<!-- If this PR resolves an open issue, please link to it here. For
example "Fixes sagemath#12345". -->
<!-- If your change requires a documentation PR, please link it
appropriately. -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it
appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
<!-- Feel free to remove irrelevant items. -->

- [x] The title is concise, informative, and self-explanatory.
- [x] The description explains in detail what this PR is about.
- [x] I have linked a relevant issue or discussion.
- [ ] I have created tests covering the changes.
- [ ] I have updated the documentation accordingly.

### ⌛ Dependencies

<!-- List all open PRs that this PR logically depends on
- sagemath#12345: short description why this is a dependency
- sagemath#34567: ...
-->

<!-- If you're unsure about any of these, don't hesitate to ask. We're
here to help! -->
    
URL: sagemath#37018
Reported by: Matthias Köppe
Reviewer(s): Kwankyu Lee
  • Loading branch information
Release Manager committed Jan 16, 2024
2 parents 63fbac6 + b3be864 commit 753ed52
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 0 deletions.
31 changes: 31 additions & 0 deletions build/sage_bootstrap/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,37 @@ def list_cls(self, *package_classes, **filters):
for pkg_name in pc.names:
print(pkg_name)

def properties(self, *package_classes, **kwds):
"""
Show the properties of given packages
$ sage --package properties --format shell maxima
path_maxima='........./build/pkgs/maxima'
version_with_patchlevel_maxima='5.46.0'
type_maxima='standard'
source_maxima='normal'
trees_maxima='SAGE_LOCAL'
"""
props = kwds.pop('props', ['path', 'version_with_patchlevel', 'type', 'source', 'trees'])
format = kwds.pop('format', 'plain')
log.debug('Looking up properties')
pc = PackageClass(*package_classes)
for package_name in pc.names:
package = Package(package_name)
if format == 'plain':
print("{0}:".format(package_name))
for p in props:
value = getattr(package, p)
if value is None:
if p.startswith('version'):
value = 'none'
else:
value = ''
if format == 'plain':
print(" {0:28} {1}".format(p + ":", value))
else:
print("{0}_{1}='{2}'".format(p, package_name, value))

def name(self, tarball_filename):
"""
Find the package name given a tarball filename
Expand Down
31 changes: 31 additions & 0 deletions build/sage_bootstrap/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,22 @@
"""


epilog_properties = \
"""
Print properties of given package.
EXAMPLE:
$ sage --package properties maxima
maxima:
path: /.../build/pkgs/maxima
version_with_patchlevel: 5.46.0
type: standard
source: normal
trees: SAGE_LOCAL
"""


epilog_name = \
"""
Find the package name given a tarball filename
Expand Down Expand Up @@ -257,6 +273,19 @@ def make_parser():
'--exclude-dependencies', action='store_true',
help='exclude (ordinary) dependencies of the packages recursively')

parser_properties = subparsers.add_parser(
'properties', epilog=epilog_properties,
formatter_class=argparse.RawDescriptionHelpFormatter,
help='Print properties of given packages')
parser_properties.add_argument(
'package_class', metavar='[package_name|:package_type:]',
type=str, nargs='+',
help=('package 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',
help='output format (one of plain and shell; default: plain)')

parser_name = subparsers.add_parser(
'name', epilog=epilog_name,
formatter_class=argparse.RawDescriptionHelpFormatter,
Expand Down Expand Up @@ -404,6 +433,8 @@ def run():
exclude=args.exclude,
include_dependencies=args.include_dependencies,
exclude_dependencies=args.exclude_dependencies)
elif args.subcommand == 'properties':
app.properties(*args.package_class, format=args.format)
elif args.subcommand == 'name':
app.name(args.tarball_filename)
elif args.subcommand == 'tarball':
Expand Down
57 changes: 57 additions & 0 deletions build/sage_bootstrap/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def __init__(self, package_name):
self._init_type()
self._init_install_requires()
self._init_dependencies()
self._init_trees()

def __repr__(self):
return 'Package {0}'.format(self.name)
Expand Down Expand Up @@ -293,13 +294,62 @@ def patchlevel(self):
"""
return self.__patchlevel

@property
def version_with_patchlevel(self):
"""
Return the version, including the Sage-specific patchlevel
OUTPUT:
String.
"""
v = self.version
if v is None:
return v
p = self.patchlevel
if p < 0:
return v
return "{0}.p{1}".format(v, p)

@property
def type(self):
"""
Return the package type
"""
return self.__type

@property
def source(self):
"""
Return the package source type
"""
if self.has_file('requirements.txt'):
return 'pip'
if self.tarball_filename:
if self.tarball_filename.endswith('.whl'):
return 'wheel'
return 'normal'
if self.has_file('spkg-install') or self.has_file('spkg-install.in'):
return 'script'
return 'none'

@property
def trees(self):
"""
Return the installation trees for the package
OUTPUT:
A white-space-separated string of environment variable names
"""
if self.__trees is not None:
return self.__trees
if self.__install_requires is not None:
return 'SAGE_VENV'
if self.has_file('requirements.txt'):
return 'SAGE_VENV'
return 'SAGE_LOCAL'

@property
def distribution_name(self):
"""
Expand Down Expand Up @@ -466,3 +516,10 @@ def _init_dependencies(self):
self.__dependencies_order_only = f.readline()
except IOError:
self.__dependencies_order_only = ''

def _init_trees(self):
try:
with open(os.path.join(self.path, 'trees.txt')) as f:
self.__trees = f.readline().partition('#')[0].strip()
except IOError:
self.__trees = None

0 comments on commit 753ed52

Please sign in to comment.