diff --git a/test/Testing.py b/test/Testing.py index 18cc0c93a..e386f181d 100644 --- a/test/Testing.py +++ b/test/Testing.py @@ -62,7 +62,51 @@ def get_tested_spec_package(name): return FakePkg(candidates[0]) -def get_tested_mock_package(files=None, header=None, name='mockPkg'): +class LazyMock: + """ + Class to store mock package definition and create the actual mock package + when needed, when some internal attribute or method is requested. + """ + + def __init__(self, files, header, name): + self._lazy_pkg = None + self._lazy_files = files + self._lazy_header = header + self._lazy_name = name + + @property + def _fake_pkg(self): + if not self._lazy_pkg: + self._lazy_pkg = get_tested_mock_package(self._lazy_files, + self._lazy_header, + self._lazy_name) + return self._lazy_pkg + + def clone(self, files=None, header=None, name=None): + """ + Copies this LazyMock modifying some properties + """ + + if files is None: + files = self._lazy_files + if header is None: + header = self._lazy_header + if name is None: + name = self._lazy_name + + return LazyMock(files, header, name) + + def __getitem__(self, key): + return self._fake_pkg.__getitem__(key) + + def __getattr__(self, name): + return getattr(self._fake_pkg, name) + + +def get_tested_mock_package(files=None, header=None, name='mockPkg', lazyload=False): + if lazyload: + return LazyMock(files, header, name) + mockPkg = FakePkg(name) if files is not None: if isinstance(files, dict): diff --git a/test/mock_packages.py b/test/mock_packages.py index 8a2ab32e3..9d3fbac85 100644 --- a/test/mock_packages.py +++ b/test/mock_packages.py @@ -1,7 +1,13 @@ -# mock_packages.py from Testing import get_tested_mock_package -PythonSitePackage = get_tested_mock_package( + +######################## +# Python mock packages # +######################## + +# Not valid doc folder in python packages +PythonDocFolderPackage = get_tested_mock_package( + lazyload=True, files=[ '/usr/lib/python2.7/site-packages/python-mypackage/doc', '/usr/lib/python2.7/site-packages/python-mypackage/docs', @@ -14,7 +20,10 @@ ] ) -PythonModuleMockPackage = get_tested_mock_package( + +# Valid doc folder in python package if it's a python module +PythonDocModulePackage = get_tested_mock_package( + lazyload=True, files={ '/usr/lib/python2.7/site-packages/python-mypackage/doc/__init__.py': {'create_dirs': True, 'include_dirs': 2}, '/usr/lib/python2.7/site-packages/python-mypackage/docs/__init__.py': {'create_dirs': True, 'include_dirs': 1}, @@ -27,7 +36,10 @@ } ) -PythonDistutilsMockPackage = get_tested_mock_package( + +# Python package with old egginfo file, not folder +PythonEggInfoFileackage = get_tested_mock_package( + lazyload=True, files={ '/usr/lib/python2.7/site-packages/mydistutilspackage.egg-info': {'content': 'Metadata-Version: 2.1\nName: pythoncheck'}, '/usr/lib/python3.10/site-packages/mydistutilspackage.egg-info': {'content': 'Metadata-Version: 2.1\nName: pythoncheck'}, @@ -36,7 +48,9 @@ } ) + PythonFlitMockPackage = get_tested_mock_package( + lazyload=True, files={ '/usr/lib/python3.10/site-packages/flit-3.8.0.dist-info/METADATA': { 'content-path': 'files/python-flit-metadata.txt', @@ -53,7 +67,35 @@ }, ) + +# Python package with missing require +PythonFlitMissingRequirePackage = PythonFlitMockPackage.clone( + header={ + 'requires': [ + 'python3-flit-core', + 'python3-requests', + 'python3-tomli-w', + ], + }, +) + + +# Python package with missing require +PythonFlitLeftoverRequirePackage = PythonFlitMockPackage.clone( + header={ + 'requires': [ + 'python3-docutils', + 'python3-flit-core', + 'python3-poetry', + 'python3-requests', + 'python3-tomli-w', + ], + }, +) + + PythonJupyterServerFileidMockPackage = get_tested_mock_package( + lazyload=True, files={ '/usr/lib/python3.10/site-packages/jupyter_server_fileid-0.9.0.dist-info/METADATA': { 'content-path': 'files/python-jupyter_server_fileid-metadata.txt', @@ -69,7 +111,9 @@ }, ) + PythonJupyterEventsMockPackage = get_tested_mock_package( + lazyload=True, files={ '/usr/lib/python3.10/site-packages/jupyter_events-0.6.3.dist-info/METADATA': { 'content-path': 'files/python-jupyter-events-metadata.txt', @@ -102,7 +146,9 @@ }, ) + PythonScikitBuildMockPackage = get_tested_mock_package( + lazyload=True, files={ '/usr/lib/python3.10/site-packages/scikit_build-0.17.2.dist-info/METADATA': { 'content-path': 'files/python-scikit_build-metadata.txt', @@ -120,7 +166,10 @@ }, ) -PythonFlitUpdatedMockPackage = get_tested_mock_package( + +# Python flit package with python3.12dist(foo) requirements (used in Fedora see #1171) +PythonFlitFedoraMockPackage = get_tested_mock_package( + lazyload=True, files={ '/usr/lib/python3.10/site-packages/flit-3.8.0.dist-info/METADATA': { 'content-path': 'files/python-flit-metadata.txt', @@ -137,7 +186,10 @@ }, ) + +# Python package with old setuptools metadata format, egg-info folder PythonIcecreamPackage = get_tested_mock_package( + lazyload=True, files={ '/usr/lib/python3.10/site-packages/icecream-2.1.3-py3.10.egg-info/requires.txt': { 'content': """ @@ -160,7 +212,36 @@ ) -PythonBlinkerMockPackage = get_tested_mock_package( +# Python package with missing require +PythonIcecreamMissingRequirePackage = PythonIcecreamPackage.clone( + header={ + 'requires': [ + 'asttokens>=2.0.1', + 'executing>=0.3.1', + 'pygments>=2.2.0', + ], + }, +) + + +# Python package with leftover require +PythonIcecreamLeftoverRequirePackage = PythonIcecreamPackage.clone( + header={ + 'requires': [ + 'python3-asttokens >= 2.0.1', + 'python3-colorama >= 0.3.9', + 'python3-executing >= 0.3.1', + 'python3-poetry', + 'python3-pygments >= 2.2.0', + ], + }, +) + + +# Python package with multiple pyc for different python versions in the same +# sitelib +PythonMultiplePYCMockPackage = get_tested_mock_package( + lazyload=True, files=[ '/usr/lib/python3.9/site-packages/blinker/__pycache__/base.cpython-310.pyc', '/usr/lib/python3.9/site-packages/blinker/__pycache__/base.cpython-39.opt-1.pyc', @@ -177,7 +258,10 @@ ] ) -PythonSiteBlinkerMockPackage = get_tested_mock_package( + +# Python package with pyc files but just the correct version +PythonSinglePYCMockPackage = get_tested_mock_package( + lazyload=True, files=[ '/usr/lib/python3.9/site-packages/blinker/__pycache__/base.cpython-39.opt-1.pyc', '/usr/lib/python3.9/site-packages/blinker/__pycache__/base.cpython-39.pyc', diff --git a/test/test_python.py b/test/test_python.py index 700844e92..fa9e6cf44 100644 --- a/test/test_python.py +++ b/test/test_python.py @@ -1,15 +1,19 @@ from mock_packages import ( - PythonBlinkerMockPackage, - PythonDistutilsMockPackage, + PythonDocFolderPackage, + PythonDocModulePackage, + PythonEggInfoFileackage, + PythonFlitFedoraMockPackage, + PythonFlitLeftoverRequirePackage, + PythonFlitMissingRequirePackage, PythonFlitMockPackage, - PythonFlitUpdatedMockPackage, + PythonIcecreamLeftoverRequirePackage, + PythonIcecreamMissingRequirePackage, PythonIcecreamPackage, PythonJupyterEventsMockPackage, PythonJupyterServerFileidMockPackage, - PythonModuleMockPackage, + PythonMultiplePYCMockPackage, PythonScikitBuildMockPackage, - PythonSiteBlinkerMockPackage, - PythonSitePackage, + PythonSinglePYCMockPackage, ) import pytest from rpmlint.checks.PythonCheck import PythonCheck @@ -38,7 +42,7 @@ def test(pythoncheck): yield test -@pytest.mark.parametrize('package', [PythonSitePackage]) +@pytest.mark.parametrize('package', [PythonDocFolderPackage]) def test_python_doc_in_package(package, test, output): test.check(package) out = output.print_results(output.results) @@ -52,7 +56,7 @@ def test_python_doc_in_package(package, test, output): assert 'W: python-doc-in-package /usr/lib64/python3.10/site-packages/python-mypackage/docs' in out -@pytest.mark.parametrize('package', [PythonModuleMockPackage]) +@pytest.mark.parametrize('package', [PythonDocModulePackage]) def test_python_doc_module_in_package(package, test, output): test.check(package) out = output.print_results(output.results) @@ -66,7 +70,7 @@ def test_python_doc_module_in_package(package, test, output): assert 'W: python-doc-in-package /usr/lib64/python3.10/site-packages/python-mypackage/docs' not in out -@pytest.mark.parametrize('package', [PythonDistutilsMockPackage]) +@pytest.mark.parametrize('package', [PythonEggInfoFileackage]) def test_python_distutils_egg_info(package, test, output): test.check(package) out = output.print_results(output.results) @@ -147,7 +151,7 @@ def test_python_tests_in_site_packages(package, test, output): PythonJupyterServerFileidMockPackage, PythonJupyterEventsMockPackage, PythonScikitBuildMockPackage, - PythonFlitUpdatedMockPackage,]) + PythonFlitFedoraMockPackage,]) def test_python_dependencies_metadata(package, test, output): test.check(package) out = output.print_results(output.results) @@ -163,47 +167,14 @@ def test_python_dependencies_requires(package, test, output): assert 'W: python-leftover-require' not in out -@pytest.mark.parametrize('package', [get_tested_mock_package( - files={ - '/usr/lib/python3.10/site-packages/icecream-2.1.3-py3.10.egg-info/requires.txt': { - 'content': """ -asttokens>=2.0.1 -colorama>=0.3.9 -executing>=0.3.1 -pygments>=2.2.0 -""", - 'create_dirs': True - }, - }, - header={ - 'requires': [ - 'asttokens>=2.0.1', - 'executing>=0.3.1', - 'pygments>=2.2.0', - ], - }, -)]) +@pytest.mark.parametrize('package', [PythonIcecreamMissingRequirePackage]) def test_python_dependencies_missing_requires(package, test, output): test.check(package) out = output.print_results(output.results) assert 'W: python-missing-require' in out -@pytest.mark.parametrize('package', [get_tested_mock_package( - files={ - '/usr/lib/python3.10/site-packages/flit-3.8.0.dist-info/METADATA': { - 'content-path': 'files/python-flit-metadata.txt', - 'create_dirs': True - }, - }, - header={ - 'requires': [ - 'python3-flit-core', - 'python3-requests', - 'python3-tomli-w', - ], - }, -)]) +@pytest.mark.parametrize('package', [PythonFlitMissingRequirePackage]) def test_python_dependencies_missing_metadata(package, test, output): test.check(package) out = output.print_results(output.results) @@ -211,45 +182,8 @@ def test_python_dependencies_missing_metadata(package, test, output): @pytest.mark.parametrize('package', [ - get_tested_mock_package( - files={ - '/usr/lib/python3.10/site-packages/icecream-2.1.3-py3.10.egg-info/requires.txt': { - 'content': """ -asttokens>=2.0.1 -colorama>=0.3.9 -executing>=0.3.1 -pygments>=2.2.0 -""", - 'create_dirs': True - }, - }, - header={ - 'requires': [ - 'python3-asttokens >= 2.0.1', - 'python3-colorama >= 0.3.9', - 'python3-executing >= 0.3.1', - 'python3-poetry', - 'python3-pygments >= 2.2.0', - ], - }, - ), - get_tested_mock_package( - files={ - '/usr/lib/python3.10/site-packages/flit-3.8.0.dist-info/METADATA': { - 'content-path': 'files/python-flit-metadata.txt', - 'create_dirs': True - }, - }, - header={ - 'requires': [ - 'python3-docutils', - 'python3-flit-core', - 'python3-poetry', - 'python3-requests', - 'python3-tomli-w', - ], - }, - ), + PythonIcecreamLeftoverRequirePackage, + PythonFlitLeftoverRequirePackage, ]) def test_python_dependencies_leftover(package, test, output): test.check(package) @@ -257,14 +191,14 @@ def test_python_dependencies_leftover(package, test, output): assert 'W: python-leftover-require' in out -@pytest.mark.parametrize('package', [PythonBlinkerMockPackage]) +@pytest.mark.parametrize('package', [PythonMultiplePYCMockPackage]) def test_python_pyc_multiple_versions(package, test, output): test.check(package) out = output.print_results(output.results) assert 'W: python-pyc-multiple-versions expected: 310' in out -@pytest.mark.parametrize('package', [PythonSiteBlinkerMockPackage]) +@pytest.mark.parametrize('package', [PythonSinglePYCMockPackage]) def test_python_pyc_single_version(package, test, output): test.check(package) out = output.print_results(output.results)