import pyproject-rpm-macros-1.6.2-1.el9

i9c changed/i9c/pyproject-rpm-macros-1.6.2-1.el9
MSVSphere Packaging Team 2 years ago
parent 7ba97a5693
commit 059c220dcb

@ -140,7 +140,7 @@ such plugins will be BuildRequired as well.
Not all plugins are guaranteed to play well with [tox-current-env],
in worst case, patch/sed the requirement out from the tox configuration.
Note that both `-x` and `-t` imply `-r`,
Note that neither `-x` or `-t` can be used with `-R`,
because runtime dependencies are always required for testing.
You can only use those options if the build backend supports the [prepare-metadata-for-build-wheel hook],
or together with `-w`.
@ -152,12 +152,16 @@ or together with `-w`.
Additionally to generated requirements you can supply multiple file names to `%pyproject_buildrequires` macro.
Dependencies will be loaded from them:
%pyproject_buildrequires -r requirements/tests.in requirements/docs.in requirements/dev.in
%pyproject_buildrequires requirements/tests.in requirements/docs.in requirements/dev.in
For packages not using build system you can use `-N` to entirely skip automatical
generation of requirements and install requirements only from manually specified files.
`-N` option cannot be used in combination with other options mentioned above
(`-r`, `-w`, `-e`, `-t`, `-x`).
`-N` option implies `-R` and cannot be used in combination with other options mentioned above
(`-w`, `-e`, `-t`, `-x`).
The `%pyproject_buildrequires` macro also accepts the `-r` flag for backward compatibility;
it means "include runtime dependencies" which has been the default since version 0-53.
Running tox based tests
-----------------------
@ -171,8 +175,9 @@ Then, use the `%tox` macro in `%check`:
The macro:
- Always prepends `$PATH` with `%{buildroot}%{_bindir}`
- If not defined, sets `$PYTHONPATH` to `%{buildroot}%{python3_sitearch}:%{buildroot}%{python3_sitelib}`
- Sets environment variables via `%{py3_test_envvars}`, namely:
- Always prepends `$PATH` with `%{buildroot}%{_bindir}`
- If not defined, sets `$PYTHONPATH` to `%{buildroot}%{python3_sitearch}:%{buildroot}%{python3_sitelib}`
- If not defined, sets `$TOX_TESTENV_PASSENV` to `*`
- Runs `tox` with `-q` (quiet), `--recreate` and `--current-env` (from [tox-current-env]) flags
- Implicitly uses the tox environment name stored in `%{toxenv}` - as overridden by `%pyproject_buildrequires -e`
@ -265,6 +270,7 @@ If `%pyproject_save_files` is not used, calling `%pyproject_check_import` will f
When `%pyproject_save_files` is invoked,
it creates a list of all valid and public (i.e. not starting with `_`)
importable module names found in the package.
Each top-level module name matches at least one of the globs provided as an argument to `%pyproject_save_files`.
This list is then usable by `%pyproject_check_import` which performs an import check for each listed module.
When a module fails to import, the build fails.

@ -0,0 +1,7 @@
# This file is called macros.aaa-pyproject-srpm
# to sort alphabetically before macros.pyproject.
# When this file is installed but macros.pyproject is not
# this macro will cause the package with the real macro to be installed.
# When macros.pyproject is installed, it overrides this macro.
# Note: This needs to maintain the same set of options as the real macro.
%pyproject_buildrequires(rRxtNwe:) echo 'pyproject-rpm-macros' && exit 0

@ -124,6 +124,7 @@ fi
%toxenv %{default_toxenv}
# Note: Keep the options in sync with this macro from macros.aaa-pyproject-srpm
%pyproject_buildrequires(rRxtNwe:) %{expand:\\\
%_set_pytest_addopts
# The _auto_set_build_flags feature does not do this in %%generate_buildrequires section,
@ -144,7 +145,7 @@ fi
%{-w:%{error:The -N and -w options are mutually exclusive}}
}
%{-e:%{expand:%global toxenv %(%{__python3} -s %{_rpmconfigdir}/redhat/pyproject_construct_toxenv.py %{?**})}}
echo 'pyproject-rpm-macros' # we already have this installed, but this way, it's repoqueryable
echo 'pyproject-rpm-macros' # first stdout line matches the implementation in macros.aaa-pyproject-srpm
echo 'python%{python3_pkgversion}-devel'
echo 'python%{python3_pkgversion}dist(pip) >= 19'
echo 'python%{python3_pkgversion}dist(packaging)'
@ -176,10 +177,10 @@ fi
%tox(e:) %{expand:\\\
TOX_TESTENV_PASSENV="${TOX_TESTENV_PASSENV:-*}" \\
PYTHONDONTWRITEBYTECODE=1 \\
%{?py3_test_envvars}%{?!py3_test_envvars:PYTHONDONTWRITEBYTECODE=1 \\
PATH="%{buildroot}%{_bindir}:$PATH" \\
PYTHONPATH="${PYTHONPATH:-%{buildroot}%{python3_sitearch}:%{buildroot}%{python3_sitelib}}" \\
%{?__pytest_addopts:PYTEST_ADDOPTS="${PYTEST_ADDOPTS:-} %{__pytest_addopts}"} \\
%{?__pytest_addopts:PYTEST_ADDOPTS="${PYTEST_ADDOPTS:-} %{__pytest_addopts}"}} \\
HOSTNAME="rpmbuild" \\
%{__python3} -m tox --current-env -q --recreate -e "%{-e:%{-e*}}%{!-e:%{toxenv}}" %{?*}
}

@ -4,9 +4,9 @@ import os
import sys
import importlib.metadata
import argparse
import tempfile
import traceback
import contextlib
from io import StringIO
import json
import subprocess
import re
@ -48,11 +48,35 @@ from pyproject_convert import convert
@contextlib.contextmanager
def hook_call():
captured_out = StringIO()
with contextlib.redirect_stdout(captured_out):
"""Context manager that records all stdout content (on FD level)
and prints it to stderr at the end, with a 'HOOK STDOUT: ' prefix."""
tmpfile = io.TextIOWrapper(
tempfile.TemporaryFile(buffering=0),
encoding='utf-8',
errors='replace',
write_through=True,
)
stdout_fd = 1
stdout_fd_dup = os.dup(stdout_fd)
stdout_orig = sys.stdout
# begin capture
sys.stdout = tmpfile
os.dup2(tmpfile.fileno(), stdout_fd)
try:
yield
for line in captured_out.getvalue().splitlines():
print_err('HOOK STDOUT:', line)
finally:
# end capture
sys.stdout = stdout_orig
os.dup2(stdout_fd_dup, stdout_fd)
tmpfile.seek(0) # rewind
for line in tmpfile:
print_err('HOOK STDOUT:', line, end='')
tmpfile.close()
def guess_reason_for_invalid_requirement(requirement_str):
@ -100,7 +124,7 @@ class Requirements:
return [{'extra': e} for e in sorted(self.extras)]
return [{'extra': ''}]
def evaluate_all_environamnets(self, requirement):
def evaluate_all_environments(self, requirement):
for marker_env in self.marker_envs:
if requirement.marker.evaluate(environment=marker_env):
return True
@ -126,7 +150,7 @@ class Requirements:
name = canonicalize_name(requirement.name)
if (requirement.marker is not None and
not self.evaluate_all_environamnets(requirement)):
not self.evaluate_all_environments(requirement)):
print_err(f'Ignoring alien requirement:', requirement_str)
return
@ -424,29 +448,35 @@ def generate_requires(
def main(argv):
parser = argparse.ArgumentParser(
description='Generate BuildRequires for a Python project.'
description='Generate BuildRequires for a Python project.',
prog='%pyproject_buildrequires',
add_help=False,
)
parser.add_argument(
'--help', action='help',
default=argparse.SUPPRESS,
help=argparse.SUPPRESS,
)
parser.add_argument(
'-r', '--runtime', action='store_true', default=True,
help='Generate run-time requirements (default, disable with -R)',
help=argparse.SUPPRESS, # Generate run-time requirements (backwards-compatibility only)
)
parser.add_argument(
'-w', '--wheel', action='store_true', default=False,
help=('Generate run-time requirements by building the wheel '
'(useful for build backends without the prepare_metadata_for_build_wheel hook)'),
'--generate-extras', action='store_true',
help=argparse.SUPPRESS,
)
parser.add_argument(
'--wheeldir', metavar='PATH', default=None,
help='The directory with wheel, used when -w.',
'-p', '--python3_pkgversion', metavar='PYTHON3_PKGVERSION',
default="3", help=argparse.SUPPRESS,
)
parser.add_argument(
'-R', '--no-runtime', action='store_false', dest='runtime',
help="Don't generate run-time requirements (implied by -N)",
'--wheeldir', metavar='PATH', default=None,
help=argparse.SUPPRESS,
)
parser.add_argument(
'-e', '--toxenv', metavar='TOXENVS', action='append',
help=('specify tox environments (comma separated and/or repeated)'
'(implies --tox)'),
'-x', '--extras', metavar='EXTRAS', action='append',
help='comma separated list of "extras" for runtime requirements '
'(e.g. -x testing,feature-x) (implies --runtime, can be repeated)',
)
parser.add_argument(
'-t', '--tox', action='store_true',
@ -454,25 +484,26 @@ def main(argv):
'(implies --runtime)'),
)
parser.add_argument(
'-x', '--extras', metavar='EXTRAS', action='append',
help='comma separated list of "extras" for runtime requirements '
'(e.g. -x testing,feature-x) (implies --runtime, can be repeated)',
'-e', '--toxenv', metavar='TOXENVS', action='append',
help=('specify tox environments (comma separated and/or repeated)'
'(implies --tox)'),
)
parser.add_argument(
'--generate-extras', action='store_true',
help='Generate build requirements on Python Extras',
'-w', '--wheel', action='store_true', default=False,
help=('Generate run-time requirements by building the wheel '
'(useful for build backends without the prepare_metadata_for_build_wheel hook)'),
)
parser.add_argument(
'-p', '--python3_pkgversion', metavar='PYTHON3_PKGVERSION',
default="3", help=('Python version for pythonXdist()'
'or pythonX.Ydist() requirements'),
'-R', '--no-runtime', action='store_false', dest='runtime',
help="Don't generate run-time requirements (implied by -N)",
)
parser.add_argument(
'-N', '--no-use-build-system', dest='use_build_system',
action='store_false', help='Use -N to indicate that project does not use any build system',
)
parser.add_argument(
'requirement_files', nargs='*', type=argparse.FileType('r'),
'requirement_files', nargs='*', type=argparse.FileType('r'),
metavar='REQUIREMENTS.TXT',
help=('Add buildrequires from file'),
)

@ -413,14 +413,24 @@ Tox dependencies:
toxdep2
commands =
true
expected: |
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(toxdep1)
python3dist(toxdep2)
python3dist(inst)
expected:
- | # tox 3
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(toxdep1)
python3dist(toxdep2)
python3dist(inst)
- | # tox 4
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(tox)
python3dist(toxdep1)
python3dist(toxdep2)
python3dist(inst)
result: 0
Tox extras:
@ -455,20 +465,36 @@ Tox extras:
extra1
commands =
true
expected: |
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(toxdep)
python3dist(inst)
python3dist(dep11) > 11.0
python3dist(dep12)
python3dist(dep21)
python3dist(dep22)
python3dist(dep23)
python3dist(extra-dep)
python3dist(extra-dep[extra_dep])
expected:
- | # tox 3
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(toxdep)
python3dist(inst)
python3dist(dep11) > 11.0
python3dist(dep12)
python3dist(dep21)
python3dist(dep22)
python3dist(dep23)
python3dist(extra-dep)
python3dist(extra-dep[extra_dep])
- | # tox 4
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(tox)
python3dist(toxdep)
python3dist(inst)
python3dist(dep11) > 11.0
python3dist(dep12)
python3dist(dep21)
python3dist(dep22)
python3dist(dep23)
python3dist(extra-dep)
python3dist(extra-dep[extra_dep])
result: 0
Tox provision unsatisfied:
@ -496,14 +522,24 @@ Tox provision unsatisfied:
deps =
toxdep1
toxdep2
expected: |
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(tox) >= 3.999
python3dist(setuptools) > 40.0
python3dist(wheel) > 2.0
expected:
- | # tox 3
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(tox) >= 3.999
python3dist(setuptools) > 40.0
python3dist(wheel) > 2.0
- | # tox 4
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(tox) >= 3.999
python3dist(setuptools) > 40.0
python3dist(wheel) > 2.0
python3dist(tox) >= 3.999
result: 0
Tox provision satisfied:
@ -530,16 +566,27 @@ Tox provision satisfied:
deps =
toxdep1
toxdep2
expected: |
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(tox) >= 3.5
python3dist(setuptools) > 40.0
python3dist(toxdep1)
python3dist(toxdep2)
python3dist(inst)
expected:
- | # tox 3
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(tox) >= 3.5
python3dist(setuptools) > 40.0
python3dist(toxdep1)
python3dist(toxdep2)
python3dist(inst)
- | # tox 4
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
python3dist(tox-current-env) >= 0.0.6
python3dist(setuptools) > 40.0
python3dist(tox) >= 3.5
python3dist(toxdep1)
python3dist(toxdep2)
python3dist(inst)
result: 0
Default build system, unmet deps in requirements file:
@ -771,3 +818,21 @@ Pre-releases are accepted:
python3dist(wheel)
stderr_contains: "Requirement satisfied: cffi"
result: 0
Wrapped subprocess prints to stdout from setup.py:
installed:
setuptools: 50
wheel: 1
include_runtime: false
setup.py: |
import os
os.system('echo LEAK?')
from setuptools import setup
setup(name='test', version='0.1')
expected: |
python3dist(setuptools) >= 40.8
python3dist(wheel)
python3dist(wheel)
stderr_contains: "HOOK STDOUT: LEAK?"
result: 0

@ -98,6 +98,4 @@ def expand_env_vars(lines):
return match['var']
return value
for line in lines:
if match := ENV_VAR_RE.search(line):
var = match['var']
yield ENV_VAR_RE.sub(repl, line)

@ -154,8 +154,8 @@ def add_lang_to_module(paths, module_name, path):
Returns True if the language code detection was successful
"""
for i, parent in enumerate(path.parents):
if i > 0 and parent.name == 'locale':
lang_country_code = path.parents[i-1].name
if parent.name == 'LC_MESSAGES':
lang_country_code = path.parents[i+1].name
break
else:
return False
@ -286,6 +286,36 @@ def module_names_from_path(path):
return {'.'.join(parts[:x+1]) for x in range(len(parts))}
def is_license_file(path, license_files, license_directories):
"""
Check if the given BuildrootPath path matches any of the "License-File" entries.
The path is considered matched when resolved from any of the license_directories
matches string-wise what is stored in any "License-File" entry (license_files).
Examples:
>>> site_packages = BuildrootPath('/usr/lib/python3.12/site-packages')
>>> distinfo = site_packages / 'foo-1.0.dist-info'
>>> license_directories = [distinfo / 'licenses', distinfo]
>>> license_files = ['LICENSE.txt', 'AUTHORS.md']
>>> is_license_file(distinfo / 'AUTHORS.md', license_files, license_directories)
True
>>> is_license_file(distinfo / 'licenses/LICENSE.txt', license_files, license_directories)
True
>>> # we don't match based on directory only
>>> is_license_file(distinfo / 'licenses/COPYING', license_files, license_directories)
False
>>> is_license_file(site_packages / 'foo/LICENSE.txt', license_files, license_directories)
False
"""
if not license_files or not license_directories:
return False
for license_dir in license_directories:
if (path.is_relative_to(license_dir) and
str(path.relative_to(license_dir)) in license_files):
return True
return False
def classify_paths(
record_path, parsed_record_content, metadata, sitedirs, python_version, prefix
):
@ -311,10 +341,17 @@ def classify_paths(
"other": {"files": []}, # regular %file entries we could not parse :(
}
license_files = metadata.get_all('License-File')
license_directory = distinfo / 'licenses' # See PEP 369 "Root License Directory"
# setuptools was the first known build backend to implement License-File.
# Unfortunately they don't put licenses to the license directory (yet):
# https://github.com/pypa/setuptools/issues/3596
# Hence, we check licenses in both licenses and dist-info
license_directories = (license_directory, distinfo)
# In RECORDs generated by pip, there are no directories, only files.
# The example RECORD from PEP 376 does not contain directories either.
# Hence, we'll only assume files, but TODO get it officially documented.
license_files = metadata.get_all('License-File')
for path in parsed_record_content:
if path.suffix == ".pyc":
# we handle bytecode separately
@ -325,7 +362,7 @@ def classify_paths(
# RECORD and REQUESTED files are removed in %pyproject_install
# See PEP 627
continue
if license_files and str(path.relative_to(distinfo)) in license_files:
if is_license_file(path, license_files, license_directories):
paths["metadata"]["licenses"].append(path)
else:
paths["metadata"]["files"].append(path)
@ -499,6 +536,50 @@ def generate_file_list(paths_dict, module_globs, include_others=False):
return sorted(files)
def generate_module_list(paths_dict, module_globs):
"""
This function takes the paths_dict created by the classify_paths() function and
reads the modules names from it.
It filters those whose top-level module names match any of the provided module_globs.
Returns list with matching qualified module names.
Examples:
>>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'foo'})
['foo', 'foo.bar']
>>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'*foo'})
['foo', 'foo.bar']
>>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'foo', 'baz'})
['baz', 'foo', 'foo.bar']
>>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'*'})
['baz', 'foo', 'foo.bar']
>>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'bar'})
[]
Submodules aren't discovered:
>>> generate_module_list({'module_names': {'foo', 'foo.bar', 'baz'}}, {'*bar'})
[]
"""
module_names = paths_dict['module_names']
filtered_module_names = set()
for glob in module_globs:
for name in module_names:
# Match the top-level part of the qualified name, eg. 'foo.bar.baz' -> 'foo'
top_level_name = name.split('.')[0]
if fnmatch.fnmatchcase(top_level_name, glob):
filtered_module_names.add(name)
return sorted(filtered_module_names)
def parse_varargs(varargs):
"""
Parse varargs from the %pyproject_save_files macro
@ -627,7 +708,7 @@ def pyproject_save_files_and_modules(buildroot, sitelib, sitearch, python_versio
parsed_records = load_parsed_record(pyproject_record)
final_file_list = []
all_module_names = set()
final_module_list = []
for record_path, files in parsed_records.items():
metadata = dist_metadata(buildroot, record_path)
@ -638,12 +719,11 @@ def pyproject_save_files_and_modules(buildroot, sitelib, sitearch, python_versio
final_file_list.extend(
generate_file_list(paths_dict, globs, include_auto)
)
all_module_names.update(paths_dict["module_names"])
# Sort values, so they are always checked in the same order
all_module_names = sorted(all_module_names)
final_module_list.extend(
generate_module_list(paths_dict, globs)
)
return final_file_list, all_module_names
return final_file_list, final_module_list
def main(cli_args):
@ -662,17 +742,31 @@ def main(cli_args):
def argparser():
parser = argparse.ArgumentParser()
parser = argparse.ArgumentParser(
description="Create %{pyproject_files} for a Python project.",
prog="%pyproject_save_files",
add_help=False,
# custom usage to add +auto
usage="%(prog)s MODULE_GLOB [MODULE_GLOB ...] [+auto]",
)
parser.add_argument(
'--help', action='help',
default=argparse.SUPPRESS,
help=argparse.SUPPRESS,
)
r = parser.add_argument_group("required arguments")
r.add_argument("--output-files", type=PosixPath, required=True)
r.add_argument("--output-modules", type=PosixPath, required=True)
r.add_argument("--buildroot", type=PosixPath, required=True)
r.add_argument("--sitelib", type=BuildrootPath, required=True)
r.add_argument("--sitearch", type=BuildrootPath, required=True)
r.add_argument("--python-version", type=str, required=True)
r.add_argument("--pyproject-record", type=PosixPath, required=True)
r.add_argument("--prefix", type=PosixPath, required=True)
parser.add_argument("varargs", nargs="+")
r.add_argument("--output-files", type=PosixPath, required=True, help=argparse.SUPPRESS)
r.add_argument("--output-modules", type=PosixPath, required=True, help=argparse.SUPPRESS)
r.add_argument("--buildroot", type=PosixPath, required=True, help=argparse.SUPPRESS)
r.add_argument("--sitelib", type=BuildrootPath, required=True, help=argparse.SUPPRESS)
r.add_argument("--sitearch", type=BuildrootPath, required=True, help=argparse.SUPPRESS)
r.add_argument("--python-version", type=str, required=True, help=argparse.SUPPRESS)
r.add_argument("--pyproject-record", type=PosixPath, required=True, help=argparse.SUPPRESS)
r.add_argument("--prefix", type=PosixPath, required=True, help=argparse.SUPPRESS)
parser.add_argument(
"varargs", nargs="+", metavar="MODULE_GLOB",
help="Shell-like glob matching top-level module names to save into %%{pyproject_files}",
)
return parser

@ -230,6 +230,28 @@ classified:
- /usr/lib/python3.7/site-packages/ipykernel-5.2.1.dist-info/COPYING.md
- /usr/lib/python3.7/site-packages/ipykernel-5.2.1.dist-info/INSTALLER
licenses: []
lang:
ipykernel:
fr:
- /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR/LC_MESSAGES/nbjs.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR/LC_MESSAGES/nbui.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR/LC_MESSAGES/notebook.mo
ja:
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP/LC_MESSAGES/nbjs.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP/LC_MESSAGES/nbui.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP/LC_MESSAGES/notebook.mo
nl:
- /usr/lib/python3.7/site-packages/ipykernel/i18n/nl/LC_MESSAGES/nbjs.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/nl/LC_MESSAGES/nbui.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/nl/LC_MESSAGES/notebook.mo
ru:
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU/LC_MESSAGES/nbjs.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU/LC_MESSAGES/nbui.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU/LC_MESSAGES/notebook.mo
zh:
- /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN/LC_MESSAGES/nbjs.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN/LC_MESSAGES/nbui.mo
- /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN/LC_MESSAGES/notebook.mo
modules:
ipykernel:
- files:
@ -279,6 +301,8 @@ classified:
- /usr/lib/python3.7/site-packages/ipykernel/gui/gtk3embed.py
- /usr/lib/python3.7/site-packages/ipykernel/gui/gtkembed.py
- /usr/lib/python3.7/site-packages/ipykernel/heartbeat.py
- /usr/lib/python3.7/site-packages/ipykernel/i18n/__init__.py
- /usr/lib/python3.7/site-packages/ipykernel/i18n/__pycache__/__init__.cpython-37{,.opt-?}.pyc
- /usr/lib/python3.7/site-packages/ipykernel/inprocess/__init__.py
- /usr/lib/python3.7/site-packages/ipykernel/inprocess/__pycache__/__init__.cpython-37{,.opt-?}.pyc
- /usr/lib/python3.7/site-packages/ipykernel/inprocess/__pycache__/blocking.cpython-37{,.opt-?}.pyc
@ -362,6 +386,18 @@ classified:
- /usr/lib/python3.7/site-packages/ipykernel/comm/__pycache__
- /usr/lib/python3.7/site-packages/ipykernel/gui
- /usr/lib/python3.7/site-packages/ipykernel/gui/__pycache__
- /usr/lib/python3.7/site-packages/ipykernel/i18n
- /usr/lib/python3.7/site-packages/ipykernel/i18n/__pycache__
- /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR
- /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR/LC_MESSAGES
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP/LC_MESSAGES
- /usr/lib/python3.7/site-packages/ipykernel/i18n/nl
- /usr/lib/python3.7/site-packages/ipykernel/i18n/nl/LC_MESSAGES
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU
- /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU/LC_MESSAGES
- /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN
- /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN/LC_MESSAGES
- /usr/lib/python3.7/site-packages/ipykernel/inprocess
- /usr/lib/python3.7/site-packages/ipykernel/inprocess/__pycache__
- /usr/lib/python3.7/site-packages/ipykernel/inprocess/tests
@ -7559,6 +7595,18 @@ dumped:
- '%dir /usr/lib/python3.7/site-packages/ipykernel/comm/__pycache__'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/gui'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/gui/__pycache__'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/__pycache__'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR/LC_MESSAGES'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP/LC_MESSAGES'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/nl'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/nl/LC_MESSAGES'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU/LC_MESSAGES'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN/LC_MESSAGES'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/inprocess'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/inprocess/__pycache__'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/inprocess/tests'
@ -7568,6 +7616,21 @@ dumped:
- '%dir /usr/lib/python3.7/site-packages/ipykernel/resources'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/tests'
- '%dir /usr/lib/python3.7/site-packages/ipykernel/tests/__pycache__'
- '%lang(fr) /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR/LC_MESSAGES/nbjs.mo'
- '%lang(fr) /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR/LC_MESSAGES/nbui.mo'
- '%lang(fr) /usr/lib/python3.7/site-packages/ipykernel/i18n/fr_FR/LC_MESSAGES/notebook.mo'
- '%lang(ja) /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP/LC_MESSAGES/nbjs.mo'
- '%lang(ja) /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP/LC_MESSAGES/nbui.mo'
- '%lang(ja) /usr/lib/python3.7/site-packages/ipykernel/i18n/ja_JP/LC_MESSAGES/notebook.mo'
- '%lang(nl) /usr/lib/python3.7/site-packages/ipykernel/i18n/nl/LC_MESSAGES/nbjs.mo'
- '%lang(nl) /usr/lib/python3.7/site-packages/ipykernel/i18n/nl/LC_MESSAGES/nbui.mo'
- '%lang(nl) /usr/lib/python3.7/site-packages/ipykernel/i18n/nl/LC_MESSAGES/notebook.mo'
- '%lang(ru) /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU/LC_MESSAGES/nbjs.mo'
- '%lang(ru) /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU/LC_MESSAGES/nbui.mo'
- '%lang(ru) /usr/lib/python3.7/site-packages/ipykernel/i18n/ru_RU/LC_MESSAGES/notebook.mo'
- '%lang(zh) /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN/LC_MESSAGES/nbjs.mo'
- '%lang(zh) /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN/LC_MESSAGES/nbui.mo'
- '%lang(zh) /usr/lib/python3.7/site-packages/ipykernel/i18n/zh_CN/LC_MESSAGES/notebook.mo'
- /usr/lib/python3.7/site-packages/ipykernel-5.2.1.dist-info/COPYING.md
- /usr/lib/python3.7/site-packages/ipykernel-5.2.1.dist-info/INSTALLER
- /usr/lib/python3.7/site-packages/ipykernel-5.2.1.dist-info/METADATA
@ -7619,6 +7682,8 @@ dumped:
- /usr/lib/python3.7/site-packages/ipykernel/gui/gtk3embed.py
- /usr/lib/python3.7/site-packages/ipykernel/gui/gtkembed.py
- /usr/lib/python3.7/site-packages/ipykernel/heartbeat.py
- /usr/lib/python3.7/site-packages/ipykernel/i18n/__init__.py
- /usr/lib/python3.7/site-packages/ipykernel/i18n/__pycache__/__init__.cpython-37{,.opt-?}.pyc
- /usr/lib/python3.7/site-packages/ipykernel/inprocess/__init__.py
- /usr/lib/python3.7/site-packages/ipykernel/inprocess/__pycache__/__init__.cpython-37{,.opt-?}.pyc
- /usr/lib/python3.7/site-packages/ipykernel/inprocess/__pycache__/blocking.cpython-37{,.opt-?}.pyc
@ -7713,6 +7778,7 @@ dumped:
- ipykernel.gui.gtk3embed
- ipykernel.gui.gtkembed
- ipykernel.heartbeat
- ipykernel.i18n
- ipykernel.inprocess
- ipykernel.inprocess.blocking
- ipykernel.inprocess.channels
@ -7755,7 +7821,6 @@ dumped:
- ipykernel.tests.utils
- ipykernel.trio_runner
- ipykernel.zmqshell
- ipykernel_launcher
- - zope
- zope
- - '%dir /usr/lib/python3.7/site-packages/zope'
@ -15484,8 +15549,8 @@ metadata:
content: |
Name: Django
Version: 3.0.7
License-File: licenses/LICENSE
License-File: licenses/LICENSE.python
License-File: LICENSE
License-File: LICENSE.python
Whatever: False data
records:
@ -15674,6 +15739,24 @@ records:
ipykernel/gui/gtk3embed.py,sha256=mjUXqAzPxF956OcmWdWzvU2VLJoZ4ZyXrqCImJcn_Ug,3222
ipykernel/gui/gtkembed.py,sha256=yYp-Npg8jPrfXiN6mrzFy8L6JS7JeBOHz5WxTxSdvMA,3131
ipykernel/heartbeat.py,sha256=ZwIsWYgvjZQgFLjw6PrD9GJnN9XO1CzafUc89DEiPaA,4194
ipykernel/i18n/__init__.py,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/__pycache__/__init__.cpython-37.opt-1.pyc,,
ipykernel/i18n/__pycache__/__init__.cpython-37.pyc,,
ipykernel/i18n/fr_FR/LC_MESSAGES/nbjs.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/fr_FR/LC_MESSAGES/nbui.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/fr_FR/LC_MESSAGES/notebook.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/ja_JP/LC_MESSAGES/nbjs.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/ja_JP/LC_MESSAGES/nbui.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/ja_JP/LC_MESSAGES/notebook.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/nl/LC_MESSAGES/nbjs.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/nl/LC_MESSAGES/nbui.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/nl/LC_MESSAGES/notebook.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/ru_RU/LC_MESSAGES/nbjs.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/ru_RU/LC_MESSAGES/nbui.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/ru_RU/LC_MESSAGES/notebook.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/zh_CN/LC_MESSAGES/nbjs.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/zh_CN/LC_MESSAGES/nbui.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/i18n/zh_CN/LC_MESSAGES/notebook.mo,sha256=0000000000000000000000000000000000000000000,10
ipykernel/inprocess/__init__.py,sha256=UrsfQEevAq5OZ3au4Fn9bu_7c6b_QqroRIE7vE4PB_o,211
ipykernel/inprocess/__pycache__/__init__.cpython-37.pyc,,
ipykernel/inprocess/__pycache__/blocking.cpython-37.pyc,,

@ -71,7 +71,12 @@ def test_data(case_name, capfd, tmp_path, monkeypatch):
out, err = capfd.readouterr()
if 'expected' in case:
assert out == case['expected']
expected = case['expected']
if isinstance(expected, list):
# at least one of them needs to match
assert any(out == e for e in expected)
else:
assert out == expected
# stderr_contains may be a string or list of strings
stderr_contains = case.get('stderr_contains')

@ -12,11 +12,12 @@ License: MIT
# Increment Y and reset Z when new macros or features are added
# Increment Z when this is a bugfix or a cosmetic change
# Dropping support for EOL Fedoras is *not* considered a breaking change
Version: 1.3.3
Version: 1.6.2
Release: 1%{?dist}
# Macro files
Source001: macros.pyproject
Source002: macros.aaa-pyproject-srpm
# Implementation files
Source101: pyproject_buildrequires.py
@ -48,6 +49,7 @@ BuildArch: noarch
%if %{with tests}
BuildRequires: python3dist(pytest)
BuildRequires: python3dist(pytest-xdist)
BuildRequires: python3dist(pyyaml)
BuildRequires: python3dist(packaging)
BuildRequires: python3dist(pip)
@ -64,6 +66,7 @@ BuildRequires: python3-rpm-macros
Requires: python-rpm-macros
Requires: python-srpm-macros
Requires: python3-rpm-macros
Requires: (pyproject-srpm-macros = %{?epoch:%{epoch}:}%{version}-%{release} if pyproject-srpm-macros)
# We use the following tools outside of coreutils
Requires: /usr/bin/find
@ -84,6 +87,17 @@ These macros replace %%py3_build and %%py3_install,
which only work with setup.py.
%package -n pyproject-srpm-macros
Summary: Minimal implementation of %%pyproject_buildrequires
Requires: (pyproject-rpm-macros = %{?epoch:%{epoch}:}%{version}-%{release} if pyproject-rpm-macros)
%description -n pyproject-srpm-macros
This package contains a minimal implementation of %%pyproject_buildrequires.
When used in %%generate_buildrequires, it will generate BuildRequires
for pyproject-rpm-macros. When both packages are installed, the full version
takes precedence.
%prep
# Not strictly necessary but allows working on file names instead
# of source numbers in install section
@ -97,6 +111,7 @@ cp -p %{sources} .
mkdir -p %{buildroot}%{_rpmmacrodir}
mkdir -p %{buildroot}%{_rpmconfigdir}/redhat
install -pm 644 macros.pyproject %{buildroot}%{_rpmmacrodir}/
install -pm 644 macros.aaa-pyproject-srpm %{buildroot}%{_rpmmacrodir}/
install -pm 644 pyproject_buildrequires.py %{buildroot}%{_rpmconfigdir}/redhat/
install -pm 644 pyproject_convert.py %{buildroot}%{_rpmconfigdir}/redhat/
install -pm 644 pyproject_save_files.py %{buildroot}%{_rpmconfigdir}/redhat/
@ -108,7 +123,7 @@ install -pm 644 pyproject_wheel.py %{buildroot}%{_rpmconfigdir}/redhat/
%if %{with tests}
%check
export HOSTNAME="rpmbuild" # to speedup tox in network-less mock, see rhbz#1856356
%pytest -vv --doctest-modules
%pytest -vv --doctest-modules -n auto
# brp-compress is provided as an argument to get the right directory macro expansion
%{python3} compare_mandata.py -f %{_rpmconfigdir}/brp-compress
@ -128,10 +143,38 @@ export HOSTNAME="rpmbuild" # to speedup tox in network-less mock, see rhbz#1856
%doc README.md
%license LICENSE
%files -n pyproject-srpm-macros
%{_rpmmacrodir}/macros.aaa-pyproject-srpm
%license LICENSE
%changelog
* Wed Mar 15 2023 MSVSphere Packaging Team <packager@msvsphere.ru> - 1.3.3-1
- Rebuilt for MSVSphere 9.1.
* Wed Feb 08 2023 Lumír Balhar <lbalhar@redhat.com> - 1.6.2-1
- Improve detection of lang files
* Fri Feb 03 2023 Miro Hrončok <mhroncok@redhat.com> - 1.6.1-1
- %%pyproject_buildrequires: Avoid leaking stdout from subprocesses
* Fri Jan 20 2023 Miro Hrončok <miro@hroncok.cz> - 1.6.0-1
- Add pyproject-srpm-macros with a minimal %%pyproject_buildrequires macro
* Fri Jan 13 2023 Miro Hrončok <mhroncok@redhat.com> - 1.5.1-1
- Adjusts %%pyproject_buildrequires tests for tox 4
* Mon Nov 28 2022 Miro Hrončok <mhroncok@redhat.com> - 1.5.0-1
- Use %%py3_test_envvars in %%tox when available
* Mon Sep 19 2022 Python Maint <python-maint@redhat.com> - 1.4.0-1
- %%pyproject_save_files: Support License-Files installed into the *Root License Directory* from PEP 369
- %%pyproject_check_import: Import only the modules whose top-level names
match any of the globs provided to %%pyproject_save_files
* Tue Aug 30 2022 Otto Liljalaakso <otto.liljalaakso@iki.fi> - 1.3.4-1
- Fix typo in internal function name
* Tue Aug 09 2022 Karolina Surma <ksurma@redhat.com> - 1.3.3-1
- Don't fail %%pyproject_save_files '*' if no modules are detected

Loading…
Cancel
Save