Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sage --package metrics: New tool to assist discussions of the Sage distribution #36977

Merged
merged 10 commits into from
Jan 14, 2024
Merged
15 changes: 15 additions & 0 deletions .github/workflows/ci-linux-incremental.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,21 @@ jobs:
echo "uninstall_targets=$(echo $(for a in '' ${{ steps.changed-packages.outputs.configures_all_changed_files }}; do echo $a | sed -E 's,build/pkgs/([a-z0-9][_.a-z0-9]*)/spkg-configure[.]m4 *,\1-uninstall,'; done | sort -u))" >> $GITHUB_OUTPUT
echo "build_targets=$(echo $(for a in '' ${{ steps.changed-packages.outputs.pkgs_all_changed_files }}; do SPKG=$(echo $a | sed -E 's,-,_,g;s,(build/)?pkgs/([a-z0-9][-_.a-z0-9]*)/[^ ]* *,\2,;'); if [ -f "build/pkgs/$SPKG/checksums.ini" -o -f "build/pkgs/$SPKG/requirements.txt" -o -f "build/pkgs/$SPKG/spkg-install" ]; then echo "$SPKG-ensure"; fi; done | sort -u))" >> $GITHUB_OUTPUT
cat $GITHUB_OUTPUT
- uses: actions/checkout@v4
with:
ref: ${{ github.base_ref }}
path: worktree-base
if: github.base_ref
- name: Compute metrics
run: |
export PATH=build/bin:$PATH
if [ -d worktree-base ]; then
(echo "# $GITHUB_BASE_REF"; SAGE_ROOT=worktree-base sage-package metrics :all:) > base-metrics.txt
(echo "# $GITHUB_REF"; sage-package metrics :all:) > metrics.txt
diff --color=always --width=100 --side-by-side --left-column base-metrics.txt metrics.txt || true
else
sage-package metrics :all:
fi

test:
needs: [changed_files]
Expand Down
10 changes: 5 additions & 5 deletions build/pkgs/tzdata/checksums.ini
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
tarball=tzdata-VERSION.tar.gz
sha1=e244bf1bde63515d3f8a452d3bbe9f97738e1e70
md5=2ad4652fecc6ef4f6794726d3f367363
cksum=2894139369
upstream_url=https://pypi.io/packages/source/t/tzdata/tzdata-VERSION.tar.gz
tarball=tzdata-VERSION-py2.py3-none-any.whl
sha1=4686c7c91a01d5af9075903937c343afa05c141b
md5=5e534124c0c916ab617421247649b193
cksum=2929397850
upstream_url=https://pypi.io/packages/py2.py3/t/tzdata/tzdata-VERSION-py2.py3-none-any.whl
2 changes: 1 addition & 1 deletion build/pkgs/tzdata/package-version.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2022.6
2023.3
2 changes: 0 additions & 2 deletions build/pkgs/tzdata/spkg-install.in

This file was deleted.

62 changes: 62 additions & 0 deletions build/sage_bootstrap/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
import logging
log = logging.getLogger()

from collections import defaultdict

from sage_bootstrap.package import Package
from sage_bootstrap.tarball import Tarball, FileNotMirroredError
from sage_bootstrap.updater import ChecksumUpdater, PackageUpdater
Expand Down Expand Up @@ -366,3 +368,63 @@ def clean(self):
os.remove(filepath)
count += 1
print('{} files were removed from the {} directory'.format(count, SAGE_DISTFILES))

def metrics_cls(self, *package_classes):
"""
Show the metrics of given packages

$ sage --package metrics :standard:
has_file_distros_arch_txt=131
has_file_distros_conda_txt=216
has_file_distros_debian_txt=125
has_file_distros_fedora_txt=138
has_file_distros_gentoo_txt=181
has_file_distros_homebrew_txt=61
has_file_distros_macports_txt=129
has_file_distros_nix_txt=51
has_file_distros_opensuse_txt=146
has_file_distros_slackware_txt=25
has_file_distros_void_txt=184
has_file_patches=35
has_file_spkg_check=59
has_file_spkg_configure_m4=222
has_file_spkg_install=198
has_tarball_upstream_url=231
line_count_file_patches=22561
line_count_file_spkg_check=402
line_count_file_spkg_configure_m4=2792
line_count_file_spkg_install=2960
packages=272
type_standard=272
"""
log.debug('Computing metrics')
metrics = defaultdict(int)
pc = PackageClass(*package_classes)
for package_name in pc.names:
package = Package(package_name)
metrics['packages'] += 1
metrics['type_' + package.type] += 1
for filenames in [['spkg-configure.m4'],
['spkg-install', 'spkg-install.in'],
['spkg-check', 'spkg-check.in'],
['distros/arch.txt'],
['distros/conda.txt'],
['distros/debian.txt'],
['distros/fedora.txt'],
['distros/gentoo.txt'],
['distros/homebrew.txt'],
['distros/macports.txt'],
['distros/nix.txt'],
['distros/opensuse.txt'],
['distros/slackware.txt'],
['distros/void.txt'],
['patches']]:
key = filenames[0].replace('.', '_').replace('-', '_').replace('/', '_')
metrics['has_file_' + key] += int(any(package.has_file(filename)
for filename in filenames))
if not key.startswith('distros_'):
metrics['line_count_file_' + key] += sum(package.line_count_file(filename)
for filename in filenames)
metrics['has_tarball_upstream_url'] += int(bool(package.tarball_upstream_url))
for key, value in sorted(metrics.items()):
print('{0}={1}'.format(key, value))
33 changes: 33 additions & 0 deletions build/sage_bootstrap/cmdline.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,27 @@
42 files were removed from the .../upstream directory
"""

epilog_metrics = \
"""
Print metrics of given package.

EXAMPLE:

$ sage --package metrics :standard:
has_file_distros_arch_txt=131
...
has_file_distros_void_txt=184
has_file_patches=35
has_file_spkg_check=59
has_file_spkg_configure_m4=222
has_file_spkg_install=198
has_tarball_upstream_url=231
line_count_file_patches=22561
...
packages=272
type_standard=272
"""


def make_parser():
"""
Expand Down Expand Up @@ -346,6 +367,16 @@ def make_parser():
formatter_class=argparse.RawDescriptionHelpFormatter,
help='Remove outdated source tarballs from the upstream/ directory')

parser_metrics = subparsers.add_parser(
'metrics', epilog=epilog_metrics,
formatter_class=argparse.RawDescriptionHelpFormatter,
help='Print metrics of given packages')
parser_metrics.add_argument(
'package_class', metavar='[package_name|:package_type:]',
type=str, nargs='*', default=[':all:'],
help=('package name or designator for all packages of a given type '
'(one of :all:, :standard:, :optional:, and :experimental:; default: :all:)'))

return parser


Expand Down Expand Up @@ -403,6 +434,8 @@ def run():
app.fix_checksum_cls(*args.package_class)
elif args.subcommand == 'clean':
app.clean()
elif args.subcommand == 'metrics':
app.metrics_cls(*args.package_class)
else:
raise RuntimeError('unknown subcommand: {0}'.format(args))

Expand Down
22 changes: 22 additions & 0 deletions build/sage_bootstrap/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,28 @@ def has_file(self, filename):
"""
return os.path.exists(os.path.join(self.path, filename))

def line_count_file(self, filename):
"""
Return the number of lines of the file

Directories are traversed recursively.

OUTPUT:

integer; 0 if the file cannot be read, 1 if it is a symlink
"""
path = os.path.join(self.path, filename)
if os.path.islink(path):
return 1
if os.path.isdir(path):
return sum(self.line_count_file(os.path.join(filename, entry))
for entry in os.listdir(path))
try:
with open(path, "rb") as f:
return len(list(f))
except OSError:
return 0

def _init_checksum(self):
"""
Load the checksums from the appropriate ``checksums.ini`` file
Expand Down
Loading
Loading