android-notify 1.60.0__py3-none-any.whl → 1.60.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of android-notify might be problematic. Click here for more details.
- android_notify/config.py +1 -1
- {android_notify-1.60.0.dist-info → android_notify-1.60.2.dist-info}/METADATA +4 -4
- {android_notify-1.60.0.dist-info → android_notify-1.60.2.dist-info}/RECORD +375 -6
- venv/Lib/site-packages/_distutils_hack/__init__.py +239 -0
- venv/Lib/site-packages/_distutils_hack/override.py +1 -0
- venv/Lib/site-packages/pkg_resources/__init__.py +3713 -0
- venv/Lib/site-packages/pkg_resources/py.typed +0 -0
- venv/Lib/site-packages/pkg_resources/tests/__init__.py +0 -0
- venv/Lib/site-packages/pkg_resources/tests/data/my-test-package-source/setup.py +7 -0
- venv/Lib/site-packages/pkg_resources/tests/test_find_distributions.py +56 -0
- venv/Lib/site-packages/pkg_resources/tests/test_integration_zope_interface.py +54 -0
- venv/Lib/site-packages/pkg_resources/tests/test_markers.py +8 -0
- venv/Lib/site-packages/pkg_resources/tests/test_pkg_resources.py +485 -0
- venv/Lib/site-packages/pkg_resources/tests/test_resources.py +869 -0
- venv/Lib/site-packages/pkg_resources/tests/test_working_set.py +505 -0
- venv/Lib/site-packages/setuptools/__init__.py +248 -0
- venv/Lib/site-packages/setuptools/_core_metadata.py +337 -0
- venv/Lib/site-packages/setuptools/_discovery.py +33 -0
- venv/Lib/site-packages/setuptools/_distutils/__init__.py +14 -0
- venv/Lib/site-packages/setuptools/_distutils/_log.py +3 -0
- venv/Lib/site-packages/setuptools/_distutils/_macos_compat.py +12 -0
- venv/Lib/site-packages/setuptools/_distutils/_modified.py +95 -0
- venv/Lib/site-packages/setuptools/_distutils/_msvccompiler.py +16 -0
- venv/Lib/site-packages/setuptools/_distutils/archive_util.py +294 -0
- venv/Lib/site-packages/setuptools/_distutils/ccompiler.py +26 -0
- venv/Lib/site-packages/setuptools/_distutils/cmd.py +554 -0
- venv/Lib/site-packages/setuptools/_distutils/command/__init__.py +23 -0
- venv/Lib/site-packages/setuptools/_distutils/command/_framework_compat.py +54 -0
- venv/Lib/site-packages/setuptools/_distutils/command/bdist.py +167 -0
- venv/Lib/site-packages/setuptools/_distutils/command/bdist_dumb.py +141 -0
- venv/Lib/site-packages/setuptools/_distutils/command/bdist_rpm.py +598 -0
- venv/Lib/site-packages/setuptools/_distutils/command/build.py +156 -0
- venv/Lib/site-packages/setuptools/_distutils/command/build_clib.py +201 -0
- venv/Lib/site-packages/setuptools/_distutils/command/build_ext.py +812 -0
- venv/Lib/site-packages/setuptools/_distutils/command/build_py.py +407 -0
- venv/Lib/site-packages/setuptools/_distutils/command/build_scripts.py +160 -0
- venv/Lib/site-packages/setuptools/_distutils/command/check.py +152 -0
- venv/Lib/site-packages/setuptools/_distutils/command/clean.py +77 -0
- venv/Lib/site-packages/setuptools/_distutils/command/config.py +358 -0
- venv/Lib/site-packages/setuptools/_distutils/command/install.py +805 -0
- venv/Lib/site-packages/setuptools/_distutils/command/install_data.py +94 -0
- venv/Lib/site-packages/setuptools/_distutils/command/install_egg_info.py +91 -0
- venv/Lib/site-packages/setuptools/_distutils/command/install_headers.py +46 -0
- venv/Lib/site-packages/setuptools/_distutils/command/install_lib.py +238 -0
- venv/Lib/site-packages/setuptools/_distutils/command/install_scripts.py +62 -0
- venv/Lib/site-packages/setuptools/_distutils/command/sdist.py +521 -0
- venv/Lib/site-packages/setuptools/_distutils/compat/__init__.py +18 -0
- venv/Lib/site-packages/setuptools/_distutils/compat/numpy.py +2 -0
- venv/Lib/site-packages/setuptools/_distutils/compat/py39.py +66 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/base.py +1394 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/cygwin.py +340 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/errors.py +24 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/msvc.py +614 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/tests/test_base.py +83 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/tests/test_cygwin.py +76 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/tests/test_mingw.py +48 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/tests/test_msvc.py +136 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/tests/test_unix.py +413 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/unix.py +422 -0
- venv/Lib/site-packages/setuptools/_distutils/compilers/C/zos.py +230 -0
- venv/Lib/site-packages/setuptools/_distutils/core.py +289 -0
- venv/Lib/site-packages/setuptools/_distutils/cygwinccompiler.py +31 -0
- venv/Lib/site-packages/setuptools/_distutils/debug.py +5 -0
- venv/Lib/site-packages/setuptools/_distutils/dep_util.py +14 -0
- venv/Lib/site-packages/setuptools/_distutils/dir_util.py +244 -0
- venv/Lib/site-packages/setuptools/_distutils/dist.py +1386 -0
- venv/Lib/site-packages/setuptools/_distutils/errors.py +108 -0
- venv/Lib/site-packages/setuptools/_distutils/extension.py +258 -0
- venv/Lib/site-packages/setuptools/_distutils/fancy_getopt.py +471 -0
- venv/Lib/site-packages/setuptools/_distutils/file_util.py +236 -0
- venv/Lib/site-packages/setuptools/_distutils/filelist.py +431 -0
- venv/Lib/site-packages/setuptools/_distutils/log.py +56 -0
- venv/Lib/site-packages/setuptools/_distutils/spawn.py +134 -0
- venv/Lib/site-packages/setuptools/_distutils/sysconfig.py +598 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/__init__.py +42 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/compat/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/compat/py39.py +40 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/support.py +134 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_archive_util.py +353 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_bdist.py +47 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_bdist_dumb.py +78 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_bdist_rpm.py +127 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_build.py +49 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_build_clib.py +134 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_build_ext.py +628 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_build_py.py +196 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_build_scripts.py +96 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_check.py +194 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_clean.py +45 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_cmd.py +107 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_config_cmd.py +87 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_core.py +130 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_dir_util.py +139 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_dist.py +552 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_extension.py +117 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_file_util.py +95 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_filelist.py +336 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_install.py +245 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_install_data.py +74 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_install_headers.py +33 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_install_lib.py +110 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_install_scripts.py +52 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_log.py +12 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_modified.py +126 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_sdist.py +470 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_spawn.py +141 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_sysconfig.py +319 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_text_file.py +127 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_util.py +243 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_version.py +80 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/test_versionpredicate.py +0 -0
- venv/Lib/site-packages/setuptools/_distutils/tests/unix_compat.py +17 -0
- venv/Lib/site-packages/setuptools/_distutils/text_file.py +286 -0
- venv/Lib/site-packages/setuptools/_distutils/unixccompiler.py +9 -0
- venv/Lib/site-packages/setuptools/_distutils/util.py +518 -0
- venv/Lib/site-packages/setuptools/_distutils/version.py +348 -0
- venv/Lib/site-packages/setuptools/_distutils/versionpredicate.py +175 -0
- venv/Lib/site-packages/setuptools/_distutils/zosccompiler.py +3 -0
- venv/Lib/site-packages/setuptools/_entry_points.py +94 -0
- venv/Lib/site-packages/setuptools/_imp.py +87 -0
- venv/Lib/site-packages/setuptools/_importlib.py +9 -0
- venv/Lib/site-packages/setuptools/_itertools.py +23 -0
- venv/Lib/site-packages/setuptools/_normalization.py +177 -0
- venv/Lib/site-packages/setuptools/_path.py +93 -0
- venv/Lib/site-packages/setuptools/_reqs.py +42 -0
- venv/Lib/site-packages/setuptools/_scripts.py +361 -0
- venv/Lib/site-packages/setuptools/_shutil.py +59 -0
- venv/Lib/site-packages/setuptools/_static.py +188 -0
- venv/Lib/site-packages/setuptools/_vendor/autocommand/__init__.py +27 -0
- venv/Lib/site-packages/setuptools/_vendor/autocommand/autoasync.py +142 -0
- venv/Lib/site-packages/setuptools/_vendor/autocommand/autocommand.py +70 -0
- venv/Lib/site-packages/setuptools/_vendor/autocommand/automain.py +59 -0
- venv/Lib/site-packages/setuptools/_vendor/autocommand/autoparse.py +333 -0
- venv/Lib/site-packages/setuptools/_vendor/autocommand/errors.py +23 -0
- venv/Lib/site-packages/setuptools/_vendor/backports/__init__.py +1 -0
- venv/Lib/site-packages/setuptools/_vendor/backports/tarfile/__init__.py +2937 -0
- venv/Lib/site-packages/setuptools/_vendor/backports/tarfile/__main__.py +5 -0
- venv/Lib/site-packages/setuptools/_vendor/backports/tarfile/compat/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/_vendor/backports/tarfile/compat/py38.py +24 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/__init__.py +1083 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_adapters.py +83 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_collections.py +30 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_compat.py +57 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_functools.py +104 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_itertools.py +73 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_meta.py +67 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/_text.py +99 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/compat/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/compat/py311.py +22 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/compat/py39.py +36 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/diagnose.py +21 -0
- venv/Lib/site-packages/setuptools/_vendor/importlib_metadata/py.typed +0 -0
- venv/Lib/site-packages/setuptools/_vendor/inflect/__init__.py +3986 -0
- venv/Lib/site-packages/setuptools/_vendor/inflect/compat/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/_vendor/inflect/compat/py38.py +7 -0
- venv/Lib/site-packages/setuptools/_vendor/inflect/py.typed +0 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/collections/__init__.py +1091 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/collections/py.typed +0 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/context.py +361 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/functools/__init__.py +633 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/functools/__init__.pyi +125 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/functools/py.typed +0 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/text/__init__.py +624 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/text/layouts.py +25 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/text/show-newlines.py +33 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/text/strip-prefix.py +21 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/text/to-dvorak.py +6 -0
- venv/Lib/site-packages/setuptools/_vendor/jaraco/text/to-qwerty.py +6 -0
- venv/Lib/site-packages/setuptools/_vendor/more_itertools/__init__.py +6 -0
- venv/Lib/site-packages/setuptools/_vendor/more_itertools/__init__.pyi +2 -0
- venv/Lib/site-packages/setuptools/_vendor/more_itertools/more.py +4806 -0
- venv/Lib/site-packages/setuptools/_vendor/more_itertools/more.pyi +709 -0
- venv/Lib/site-packages/setuptools/_vendor/more_itertools/py.typed +0 -0
- venv/Lib/site-packages/setuptools/_vendor/more_itertools/recipes.py +1046 -0
- venv/Lib/site-packages/setuptools/_vendor/more_itertools/recipes.pyi +136 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/__init__.py +15 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/_elffile.py +110 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/_manylinux.py +263 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/_musllinux.py +85 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/_parser.py +354 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/_structures.py +61 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/_tokenizer.py +194 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/licenses/__init__.py +145 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/licenses/_spdx.py +759 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/markers.py +331 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/metadata.py +863 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/py.typed +0 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/requirements.py +91 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/specifiers.py +1020 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/tags.py +617 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/utils.py +163 -0
- venv/Lib/site-packages/setuptools/_vendor/packaging/version.py +582 -0
- venv/Lib/site-packages/setuptools/_vendor/platformdirs/__init__.py +627 -0
- venv/Lib/site-packages/setuptools/_vendor/platformdirs/__main__.py +55 -0
- venv/Lib/site-packages/setuptools/_vendor/platformdirs/android.py +249 -0
- venv/Lib/site-packages/setuptools/_vendor/platformdirs/api.py +292 -0
- venv/Lib/site-packages/setuptools/_vendor/platformdirs/macos.py +130 -0
- venv/Lib/site-packages/setuptools/_vendor/platformdirs/py.typed +0 -0
- venv/Lib/site-packages/setuptools/_vendor/platformdirs/unix.py +275 -0
- venv/Lib/site-packages/setuptools/_vendor/platformdirs/version.py +16 -0
- venv/Lib/site-packages/setuptools/_vendor/platformdirs/windows.py +272 -0
- venv/Lib/site-packages/setuptools/_vendor/tomli/__init__.py +11 -0
- venv/Lib/site-packages/setuptools/_vendor/tomli/_parser.py +691 -0
- venv/Lib/site-packages/setuptools/_vendor/tomli/_re.py +107 -0
- venv/Lib/site-packages/setuptools/_vendor/tomli/_types.py +10 -0
- venv/Lib/site-packages/setuptools/_vendor/tomli/py.typed +1 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/__init__.py +48 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_checkers.py +993 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_config.py +108 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_decorators.py +235 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_exceptions.py +42 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_functions.py +308 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_importhook.py +213 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_memo.py +48 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_pytest_plugin.py +127 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_suppression.py +86 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_transformer.py +1229 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_union_transformer.py +55 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/_utils.py +173 -0
- venv/Lib/site-packages/setuptools/_vendor/typeguard/py.typed +0 -0
- venv/Lib/site-packages/setuptools/_vendor/typing_extensions.py +3641 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/__init__.py +3 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/__main__.py +23 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/_bdist_wheel.py +613 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/_setuptools_logging.py +26 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/bdist_wheel.py +26 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/cli/__init__.py +155 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/cli/convert.py +332 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/cli/pack.py +85 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/cli/tags.py +139 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/cli/unpack.py +30 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/macosx_libfile.py +482 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/metadata.py +183 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/util.py +17 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/_elffile.py +108 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/_manylinux.py +260 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/_musllinux.py +83 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/_parser.py +356 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/_structures.py +61 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/_tokenizer.py +192 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/markers.py +253 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/requirements.py +90 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/specifiers.py +1011 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/tags.py +571 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/utils.py +172 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/vendored/packaging/version.py +561 -0
- venv/Lib/site-packages/setuptools/_vendor/wheel/wheelfile.py +227 -0
- venv/Lib/site-packages/setuptools/_vendor/zipp/__init__.py +501 -0
- venv/Lib/site-packages/setuptools/_vendor/zipp/compat/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/_vendor/zipp/compat/py310.py +11 -0
- venv/Lib/site-packages/setuptools/_vendor/zipp/glob.py +106 -0
- venv/Lib/site-packages/setuptools/archive_util.py +219 -0
- venv/Lib/site-packages/setuptools/build_meta.py +548 -0
- venv/Lib/site-packages/setuptools/command/__init__.py +21 -0
- venv/Lib/site-packages/setuptools/command/_requirestxt.py +131 -0
- venv/Lib/site-packages/setuptools/command/alias.py +77 -0
- venv/Lib/site-packages/setuptools/command/bdist_egg.py +477 -0
- venv/Lib/site-packages/setuptools/command/bdist_rpm.py +42 -0
- venv/Lib/site-packages/setuptools/command/bdist_wheel.py +604 -0
- venv/Lib/site-packages/setuptools/command/build.py +135 -0
- venv/Lib/site-packages/setuptools/command/build_clib.py +103 -0
- venv/Lib/site-packages/setuptools/command/build_ext.py +470 -0
- venv/Lib/site-packages/setuptools/command/build_py.py +400 -0
- venv/Lib/site-packages/setuptools/command/develop.py +55 -0
- venv/Lib/site-packages/setuptools/command/dist_info.py +103 -0
- venv/Lib/site-packages/setuptools/command/easy_install.py +30 -0
- venv/Lib/site-packages/setuptools/command/editable_wheel.py +908 -0
- venv/Lib/site-packages/setuptools/command/egg_info.py +718 -0
- venv/Lib/site-packages/setuptools/command/install.py +131 -0
- venv/Lib/site-packages/setuptools/command/install_egg_info.py +58 -0
- venv/Lib/site-packages/setuptools/command/install_lib.py +137 -0
- venv/Lib/site-packages/setuptools/command/install_scripts.py +67 -0
- venv/Lib/site-packages/setuptools/command/rotate.py +65 -0
- venv/Lib/site-packages/setuptools/command/saveopts.py +21 -0
- venv/Lib/site-packages/setuptools/command/sdist.py +217 -0
- venv/Lib/site-packages/setuptools/command/setopt.py +141 -0
- venv/Lib/site-packages/setuptools/command/test.py +45 -0
- venv/Lib/site-packages/setuptools/compat/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/compat/py310.py +20 -0
- venv/Lib/site-packages/setuptools/compat/py311.py +27 -0
- venv/Lib/site-packages/setuptools/compat/py312.py +13 -0
- venv/Lib/site-packages/setuptools/compat/py39.py +9 -0
- venv/Lib/site-packages/setuptools/config/__init__.py +43 -0
- venv/Lib/site-packages/setuptools/config/_apply_pyprojecttoml.py +526 -0
- venv/Lib/site-packages/setuptools/config/_validate_pyproject/__init__.py +34 -0
- venv/Lib/site-packages/setuptools/config/_validate_pyproject/error_reporting.py +336 -0
- venv/Lib/site-packages/setuptools/config/_validate_pyproject/extra_validations.py +82 -0
- venv/Lib/site-packages/setuptools/config/_validate_pyproject/fastjsonschema_exceptions.py +51 -0
- venv/Lib/site-packages/setuptools/config/_validate_pyproject/fastjsonschema_validations.py +1412 -0
- venv/Lib/site-packages/setuptools/config/_validate_pyproject/formats.py +402 -0
- venv/Lib/site-packages/setuptools/config/expand.py +452 -0
- venv/Lib/site-packages/setuptools/config/pyprojecttoml.py +468 -0
- venv/Lib/site-packages/setuptools/config/setupcfg.py +780 -0
- venv/Lib/site-packages/setuptools/depends.py +185 -0
- venv/Lib/site-packages/setuptools/discovery.py +614 -0
- venv/Lib/site-packages/setuptools/dist.py +1119 -0
- venv/Lib/site-packages/setuptools/errors.py +67 -0
- venv/Lib/site-packages/setuptools/extension.py +177 -0
- venv/Lib/site-packages/setuptools/glob.py +185 -0
- venv/Lib/site-packages/setuptools/installer.py +155 -0
- venv/Lib/site-packages/setuptools/launch.py +36 -0
- venv/Lib/site-packages/setuptools/logging.py +40 -0
- venv/Lib/site-packages/setuptools/modified.py +18 -0
- venv/Lib/site-packages/setuptools/monkey.py +126 -0
- venv/Lib/site-packages/setuptools/msvc.py +1536 -0
- venv/Lib/site-packages/setuptools/namespaces.py +106 -0
- venv/Lib/site-packages/setuptools/tests/__init__.py +13 -0
- venv/Lib/site-packages/setuptools/tests/compat/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/tests/compat/py39.py +3 -0
- venv/Lib/site-packages/setuptools/tests/config/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/tests/config/downloads/__init__.py +59 -0
- venv/Lib/site-packages/setuptools/tests/config/downloads/preload.py +18 -0
- venv/Lib/site-packages/setuptools/tests/config/test_apply_pyprojecttoml.py +772 -0
- venv/Lib/site-packages/setuptools/tests/config/test_expand.py +247 -0
- venv/Lib/site-packages/setuptools/tests/config/test_pyprojecttoml.py +396 -0
- venv/Lib/site-packages/setuptools/tests/config/test_pyprojecttoml_dynamic_deps.py +109 -0
- venv/Lib/site-packages/setuptools/tests/config/test_setupcfg.py +980 -0
- venv/Lib/site-packages/setuptools/tests/contexts.py +131 -0
- venv/Lib/site-packages/setuptools/tests/environment.py +95 -0
- venv/Lib/site-packages/setuptools/tests/fixtures.py +392 -0
- venv/Lib/site-packages/setuptools/tests/integration/__init__.py +0 -0
- venv/Lib/site-packages/setuptools/tests/integration/helpers.py +77 -0
- venv/Lib/site-packages/setuptools/tests/integration/test_pbr.py +20 -0
- venv/Lib/site-packages/setuptools/tests/integration/test_pip_install_sdist.py +223 -0
- venv/Lib/site-packages/setuptools/tests/mod_with_constant.py +1 -0
- venv/Lib/site-packages/setuptools/tests/namespaces.py +90 -0
- venv/Lib/site-packages/setuptools/tests/script-with-bom.py +1 -0
- venv/Lib/site-packages/setuptools/tests/test_archive_util.py +36 -0
- venv/Lib/site-packages/setuptools/tests/test_bdist_deprecations.py +28 -0
- venv/Lib/site-packages/setuptools/tests/test_bdist_egg.py +73 -0
- venv/Lib/site-packages/setuptools/tests/test_bdist_wheel.py +708 -0
- venv/Lib/site-packages/setuptools/tests/test_build.py +33 -0
- venv/Lib/site-packages/setuptools/tests/test_build_clib.py +84 -0
- venv/Lib/site-packages/setuptools/tests/test_build_ext.py +293 -0
- venv/Lib/site-packages/setuptools/tests/test_build_meta.py +959 -0
- venv/Lib/site-packages/setuptools/tests/test_build_py.py +480 -0
- venv/Lib/site-packages/setuptools/tests/test_config_discovery.py +647 -0
- venv/Lib/site-packages/setuptools/tests/test_core_metadata.py +622 -0
- venv/Lib/site-packages/setuptools/tests/test_depends.py +15 -0
- venv/Lib/site-packages/setuptools/tests/test_develop.py +112 -0
- venv/Lib/site-packages/setuptools/tests/test_dist.py +278 -0
- venv/Lib/site-packages/setuptools/tests/test_dist_info.py +147 -0
- venv/Lib/site-packages/setuptools/tests/test_distutils_adoption.py +198 -0
- venv/Lib/site-packages/setuptools/tests/test_editable_install.py +1263 -0
- venv/Lib/site-packages/setuptools/tests/test_egg_info.py +1306 -0
- venv/Lib/site-packages/setuptools/tests/test_extern.py +15 -0
- venv/Lib/site-packages/setuptools/tests/test_find_packages.py +218 -0
- venv/Lib/site-packages/setuptools/tests/test_find_py_modules.py +73 -0
- venv/Lib/site-packages/setuptools/tests/test_glob.py +45 -0
- venv/Lib/site-packages/setuptools/tests/test_install_scripts.py +89 -0
- venv/Lib/site-packages/setuptools/tests/test_logging.py +76 -0
- venv/Lib/site-packages/setuptools/tests/test_manifest.py +622 -0
- venv/Lib/site-packages/setuptools/tests/test_namespaces.py +138 -0
- venv/Lib/site-packages/setuptools/tests/test_scripts.py +12 -0
- venv/Lib/site-packages/setuptools/tests/test_sdist.py +984 -0
- venv/Lib/site-packages/setuptools/tests/test_setopt.py +40 -0
- venv/Lib/site-packages/setuptools/tests/test_setuptools.py +290 -0
- venv/Lib/site-packages/setuptools/tests/test_shutil_wrapper.py +23 -0
- venv/Lib/site-packages/setuptools/tests/test_unicode_utils.py +10 -0
- venv/Lib/site-packages/setuptools/tests/test_virtualenv.py +113 -0
- venv/Lib/site-packages/setuptools/tests/test_warnings.py +106 -0
- venv/Lib/site-packages/setuptools/tests/test_wheel.py +690 -0
- venv/Lib/site-packages/setuptools/tests/test_windows_wrappers.py +258 -0
- venv/Lib/site-packages/setuptools/tests/text.py +4 -0
- venv/Lib/site-packages/setuptools/tests/textwrap.py +6 -0
- venv/Lib/site-packages/setuptools/unicode_utils.py +102 -0
- venv/Lib/site-packages/setuptools/version.py +6 -0
- venv/Lib/site-packages/setuptools/warnings.py +110 -0
- venv/Lib/site-packages/setuptools/wheel.py +261 -0
- venv/Lib/site-packages/setuptools/windows_support.py +30 -0
- {android_notify-1.60.0.dist-info → android_notify-1.60.2.dist-info}/WHEEL +0 -0
- {android_notify-1.60.0.dist-info → android_notify-1.60.2.dist-info}/entry_points.txt +0 -0
- {android_notify-1.60.0.dist-info → android_notify-1.60.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1263 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import platform
|
|
5
|
+
import stat
|
|
6
|
+
import subprocess
|
|
7
|
+
import sys
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
from importlib import import_module
|
|
10
|
+
from importlib.machinery import EXTENSION_SUFFIXES
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from textwrap import dedent
|
|
13
|
+
from typing import Any
|
|
14
|
+
from unittest.mock import Mock
|
|
15
|
+
from uuid import uuid4
|
|
16
|
+
|
|
17
|
+
import jaraco.envs
|
|
18
|
+
import jaraco.path
|
|
19
|
+
import pytest
|
|
20
|
+
from path import Path as _Path
|
|
21
|
+
|
|
22
|
+
from setuptools._importlib import resources as importlib_resources
|
|
23
|
+
from setuptools.command.editable_wheel import (
|
|
24
|
+
_encode_pth,
|
|
25
|
+
_find_namespaces,
|
|
26
|
+
_find_package_roots,
|
|
27
|
+
_find_virtual_namespaces,
|
|
28
|
+
_finder_template,
|
|
29
|
+
_LinkTree,
|
|
30
|
+
_TopLevelFinder,
|
|
31
|
+
editable_wheel,
|
|
32
|
+
)
|
|
33
|
+
from setuptools.dist import Distribution
|
|
34
|
+
from setuptools.extension import Extension
|
|
35
|
+
from setuptools.warnings import SetuptoolsDeprecationWarning
|
|
36
|
+
|
|
37
|
+
from . import contexts, namespaces
|
|
38
|
+
|
|
39
|
+
from distutils.core import run_setup
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@pytest.fixture(params=["strict", "lenient"])
|
|
43
|
+
def editable_opts(request):
|
|
44
|
+
if request.param == "strict":
|
|
45
|
+
return ["--config-settings", "editable-mode=strict"]
|
|
46
|
+
return []
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
EXAMPLE = {
|
|
50
|
+
'pyproject.toml': dedent(
|
|
51
|
+
"""\
|
|
52
|
+
[build-system]
|
|
53
|
+
requires = ["setuptools"]
|
|
54
|
+
build-backend = "setuptools.build_meta"
|
|
55
|
+
|
|
56
|
+
[project]
|
|
57
|
+
name = "mypkg"
|
|
58
|
+
version = "3.14159"
|
|
59
|
+
license = {text = "MIT"}
|
|
60
|
+
description = "This is a Python package"
|
|
61
|
+
dynamic = ["readme"]
|
|
62
|
+
classifiers = [
|
|
63
|
+
"Development Status :: 5 - Production/Stable",
|
|
64
|
+
"Intended Audience :: Developers"
|
|
65
|
+
]
|
|
66
|
+
urls = {Homepage = "https://github.com"}
|
|
67
|
+
|
|
68
|
+
[tool.setuptools]
|
|
69
|
+
package-dir = {"" = "src"}
|
|
70
|
+
packages = {find = {where = ["src"]}}
|
|
71
|
+
license-files = ["LICENSE*"]
|
|
72
|
+
|
|
73
|
+
[tool.setuptools.dynamic]
|
|
74
|
+
readme = {file = "README.rst"}
|
|
75
|
+
|
|
76
|
+
[tool.distutils.egg_info]
|
|
77
|
+
tag-build = ".post0"
|
|
78
|
+
"""
|
|
79
|
+
),
|
|
80
|
+
"MANIFEST.in": dedent(
|
|
81
|
+
"""\
|
|
82
|
+
global-include *.py *.txt
|
|
83
|
+
global-exclude *.py[cod]
|
|
84
|
+
prune dist
|
|
85
|
+
prune build
|
|
86
|
+
"""
|
|
87
|
+
).strip(),
|
|
88
|
+
"README.rst": "This is a ``README``",
|
|
89
|
+
"LICENSE.txt": "---- placeholder MIT license ----",
|
|
90
|
+
"src": {
|
|
91
|
+
"mypkg": {
|
|
92
|
+
"__init__.py": dedent(
|
|
93
|
+
"""\
|
|
94
|
+
import sys
|
|
95
|
+
from importlib.metadata import PackageNotFoundError, version
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
__version__ = version(__name__)
|
|
99
|
+
except PackageNotFoundError:
|
|
100
|
+
__version__ = "unknown"
|
|
101
|
+
"""
|
|
102
|
+
),
|
|
103
|
+
"__main__.py": dedent(
|
|
104
|
+
"""\
|
|
105
|
+
from importlib.resources import read_text
|
|
106
|
+
from . import __version__, __name__ as parent
|
|
107
|
+
from .mod import x
|
|
108
|
+
|
|
109
|
+
data = read_text(parent, "data.txt")
|
|
110
|
+
print(__version__, data, x)
|
|
111
|
+
"""
|
|
112
|
+
),
|
|
113
|
+
"mod.py": "x = ''",
|
|
114
|
+
"data.txt": "Hello World",
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
SETUP_SCRIPT_STUB = "__import__('setuptools').setup()"
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@pytest.mark.xfail(sys.platform == "darwin", reason="pypa/setuptools#4328")
|
|
124
|
+
@pytest.mark.parametrize(
|
|
125
|
+
"files",
|
|
126
|
+
[
|
|
127
|
+
{**EXAMPLE, "setup.py": SETUP_SCRIPT_STUB},
|
|
128
|
+
EXAMPLE, # No setup.py script
|
|
129
|
+
],
|
|
130
|
+
)
|
|
131
|
+
def test_editable_with_pyproject(tmp_path, venv, files, editable_opts):
|
|
132
|
+
project = tmp_path / "mypkg"
|
|
133
|
+
project.mkdir()
|
|
134
|
+
jaraco.path.build(files, prefix=project)
|
|
135
|
+
|
|
136
|
+
cmd = [
|
|
137
|
+
"python",
|
|
138
|
+
"-m",
|
|
139
|
+
"pip",
|
|
140
|
+
"install",
|
|
141
|
+
"--no-build-isolation", # required to force current version of setuptools
|
|
142
|
+
"-e",
|
|
143
|
+
str(project),
|
|
144
|
+
*editable_opts,
|
|
145
|
+
]
|
|
146
|
+
print(venv.run(cmd))
|
|
147
|
+
|
|
148
|
+
cmd = ["python", "-m", "mypkg"]
|
|
149
|
+
assert venv.run(cmd).strip() == "3.14159.post0 Hello World"
|
|
150
|
+
|
|
151
|
+
(project / "src/mypkg/data.txt").write_text("foobar", encoding="utf-8")
|
|
152
|
+
(project / "src/mypkg/mod.py").write_text("x = 42", encoding="utf-8")
|
|
153
|
+
assert venv.run(cmd).strip() == "3.14159.post0 foobar 42"
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def test_editable_with_flat_layout(tmp_path, venv, editable_opts):
|
|
157
|
+
files = {
|
|
158
|
+
"mypkg": {
|
|
159
|
+
"pyproject.toml": dedent(
|
|
160
|
+
"""\
|
|
161
|
+
[build-system]
|
|
162
|
+
requires = ["setuptools", "wheel"]
|
|
163
|
+
build-backend = "setuptools.build_meta"
|
|
164
|
+
|
|
165
|
+
[project]
|
|
166
|
+
name = "mypkg"
|
|
167
|
+
version = "3.14159"
|
|
168
|
+
|
|
169
|
+
[tool.setuptools]
|
|
170
|
+
packages = ["pkg"]
|
|
171
|
+
py-modules = ["mod"]
|
|
172
|
+
"""
|
|
173
|
+
),
|
|
174
|
+
"pkg": {"__init__.py": "a = 4"},
|
|
175
|
+
"mod.py": "b = 2",
|
|
176
|
+
},
|
|
177
|
+
}
|
|
178
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
179
|
+
project = tmp_path / "mypkg"
|
|
180
|
+
|
|
181
|
+
cmd = [
|
|
182
|
+
"python",
|
|
183
|
+
"-m",
|
|
184
|
+
"pip",
|
|
185
|
+
"install",
|
|
186
|
+
"--no-build-isolation", # required to force current version of setuptools
|
|
187
|
+
"-e",
|
|
188
|
+
str(project),
|
|
189
|
+
*editable_opts,
|
|
190
|
+
]
|
|
191
|
+
print(venv.run(cmd))
|
|
192
|
+
cmd = ["python", "-c", "import pkg, mod; print(pkg.a, mod.b)"]
|
|
193
|
+
assert venv.run(cmd).strip() == "4 2"
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def test_editable_with_single_module(tmp_path, venv, editable_opts):
|
|
197
|
+
files = {
|
|
198
|
+
"mypkg": {
|
|
199
|
+
"pyproject.toml": dedent(
|
|
200
|
+
"""\
|
|
201
|
+
[build-system]
|
|
202
|
+
requires = ["setuptools", "wheel"]
|
|
203
|
+
build-backend = "setuptools.build_meta"
|
|
204
|
+
|
|
205
|
+
[project]
|
|
206
|
+
name = "mod"
|
|
207
|
+
version = "3.14159"
|
|
208
|
+
|
|
209
|
+
[tool.setuptools]
|
|
210
|
+
py-modules = ["mod"]
|
|
211
|
+
"""
|
|
212
|
+
),
|
|
213
|
+
"mod.py": "b = 2",
|
|
214
|
+
},
|
|
215
|
+
}
|
|
216
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
217
|
+
project = tmp_path / "mypkg"
|
|
218
|
+
|
|
219
|
+
cmd = [
|
|
220
|
+
"python",
|
|
221
|
+
"-m",
|
|
222
|
+
"pip",
|
|
223
|
+
"install",
|
|
224
|
+
"--no-build-isolation", # required to force current version of setuptools
|
|
225
|
+
"-e",
|
|
226
|
+
str(project),
|
|
227
|
+
*editable_opts,
|
|
228
|
+
]
|
|
229
|
+
print(venv.run(cmd))
|
|
230
|
+
cmd = ["python", "-c", "import mod; print(mod.b)"]
|
|
231
|
+
assert venv.run(cmd).strip() == "2"
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class TestLegacyNamespaces:
|
|
235
|
+
# legacy => pkg_resources.declare_namespace(...) + setup(namespace_packages=...)
|
|
236
|
+
|
|
237
|
+
def test_nspkg_file_is_unique(self, tmp_path, monkeypatch):
|
|
238
|
+
deprecation = pytest.warns(
|
|
239
|
+
SetuptoolsDeprecationWarning, match=".*namespace_packages parameter.*"
|
|
240
|
+
)
|
|
241
|
+
installation_dir = tmp_path / ".installation_dir"
|
|
242
|
+
installation_dir.mkdir()
|
|
243
|
+
examples = (
|
|
244
|
+
"myns.pkgA",
|
|
245
|
+
"myns.pkgB",
|
|
246
|
+
"myns.n.pkgA",
|
|
247
|
+
"myns.n.pkgB",
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
for name in examples:
|
|
251
|
+
pkg = namespaces.build_namespace_package(tmp_path, name, version="42")
|
|
252
|
+
with deprecation, monkeypatch.context() as ctx:
|
|
253
|
+
ctx.chdir(pkg)
|
|
254
|
+
dist = run_setup("setup.py", stop_after="config")
|
|
255
|
+
cmd = editable_wheel(dist)
|
|
256
|
+
cmd.finalize_options()
|
|
257
|
+
editable_name = cmd.get_finalized_command("dist_info").name
|
|
258
|
+
cmd._install_namespaces(installation_dir, editable_name)
|
|
259
|
+
|
|
260
|
+
files = list(installation_dir.glob("*-nspkg.pth"))
|
|
261
|
+
assert len(files) == len(examples)
|
|
262
|
+
|
|
263
|
+
@pytest.mark.parametrize(
|
|
264
|
+
"impl",
|
|
265
|
+
(
|
|
266
|
+
"pkg_resources",
|
|
267
|
+
# "pkgutil", => does not work
|
|
268
|
+
),
|
|
269
|
+
)
|
|
270
|
+
@pytest.mark.parametrize("ns", ("myns.n",))
|
|
271
|
+
def test_namespace_package_importable(
|
|
272
|
+
self, venv, tmp_path, ns, impl, editable_opts
|
|
273
|
+
):
|
|
274
|
+
"""
|
|
275
|
+
Installing two packages sharing the same namespace, one installed
|
|
276
|
+
naturally using pip or `--single-version-externally-managed`
|
|
277
|
+
and the other installed in editable mode should leave the namespace
|
|
278
|
+
intact and both packages reachable by import.
|
|
279
|
+
(Ported from test_develop).
|
|
280
|
+
"""
|
|
281
|
+
build_system = """\
|
|
282
|
+
[build-system]
|
|
283
|
+
requires = ["setuptools"]
|
|
284
|
+
build-backend = "setuptools.build_meta"
|
|
285
|
+
"""
|
|
286
|
+
pkg_A = namespaces.build_namespace_package(tmp_path, f"{ns}.pkgA", impl=impl)
|
|
287
|
+
pkg_B = namespaces.build_namespace_package(tmp_path, f"{ns}.pkgB", impl=impl)
|
|
288
|
+
(pkg_A / "pyproject.toml").write_text(build_system, encoding="utf-8")
|
|
289
|
+
(pkg_B / "pyproject.toml").write_text(build_system, encoding="utf-8")
|
|
290
|
+
# use pip to install to the target directory
|
|
291
|
+
opts = editable_opts[:]
|
|
292
|
+
opts.append("--no-build-isolation") # force current version of setuptools
|
|
293
|
+
venv.run(["python", "-m", "pip", "install", str(pkg_A), *opts])
|
|
294
|
+
venv.run(["python", "-m", "pip", "install", "-e", str(pkg_B), *opts])
|
|
295
|
+
venv.run(["python", "-c", f"import {ns}.pkgA; import {ns}.pkgB"])
|
|
296
|
+
# additionally ensure that pkg_resources import works
|
|
297
|
+
venv.run(["python", "-c", "import pkg_resources"])
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
class TestPep420Namespaces:
|
|
301
|
+
def test_namespace_package_importable(self, venv, tmp_path, editable_opts):
|
|
302
|
+
"""
|
|
303
|
+
Installing two packages sharing the same namespace, one installed
|
|
304
|
+
normally using pip and the other installed in editable mode
|
|
305
|
+
should allow importing both packages.
|
|
306
|
+
"""
|
|
307
|
+
pkg_A = namespaces.build_pep420_namespace_package(tmp_path, 'myns.n.pkgA')
|
|
308
|
+
pkg_B = namespaces.build_pep420_namespace_package(tmp_path, 'myns.n.pkgB')
|
|
309
|
+
# use pip to install to the target directory
|
|
310
|
+
opts = editable_opts[:]
|
|
311
|
+
opts.append("--no-build-isolation") # force current version of setuptools
|
|
312
|
+
venv.run(["python", "-m", "pip", "install", str(pkg_A), *opts])
|
|
313
|
+
venv.run(["python", "-m", "pip", "install", "-e", str(pkg_B), *opts])
|
|
314
|
+
venv.run(["python", "-c", "import myns.n.pkgA; import myns.n.pkgB"])
|
|
315
|
+
|
|
316
|
+
def test_namespace_created_via_package_dir(self, venv, tmp_path, editable_opts):
|
|
317
|
+
"""Currently users can create a namespace by tweaking `package_dir`"""
|
|
318
|
+
files = {
|
|
319
|
+
"pkgA": {
|
|
320
|
+
"pyproject.toml": dedent(
|
|
321
|
+
"""\
|
|
322
|
+
[build-system]
|
|
323
|
+
requires = ["setuptools", "wheel"]
|
|
324
|
+
build-backend = "setuptools.build_meta"
|
|
325
|
+
|
|
326
|
+
[project]
|
|
327
|
+
name = "pkgA"
|
|
328
|
+
version = "3.14159"
|
|
329
|
+
|
|
330
|
+
[tool.setuptools]
|
|
331
|
+
package-dir = {"myns.n.pkgA" = "src"}
|
|
332
|
+
"""
|
|
333
|
+
),
|
|
334
|
+
"src": {"__init__.py": "a = 1"},
|
|
335
|
+
},
|
|
336
|
+
}
|
|
337
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
338
|
+
pkg_A = tmp_path / "pkgA"
|
|
339
|
+
pkg_B = namespaces.build_pep420_namespace_package(tmp_path, 'myns.n.pkgB')
|
|
340
|
+
pkg_C = namespaces.build_pep420_namespace_package(tmp_path, 'myns.n.pkgC')
|
|
341
|
+
|
|
342
|
+
# use pip to install to the target directory
|
|
343
|
+
opts = editable_opts[:]
|
|
344
|
+
opts.append("--no-build-isolation") # force current version of setuptools
|
|
345
|
+
venv.run(["python", "-m", "pip", "install", str(pkg_A), *opts])
|
|
346
|
+
venv.run(["python", "-m", "pip", "install", "-e", str(pkg_B), *opts])
|
|
347
|
+
venv.run(["python", "-m", "pip", "install", "-e", str(pkg_C), *opts])
|
|
348
|
+
venv.run(["python", "-c", "from myns.n import pkgA, pkgB, pkgC"])
|
|
349
|
+
|
|
350
|
+
def test_namespace_accidental_config_in_lenient_mode(self, venv, tmp_path):
|
|
351
|
+
"""Sometimes users might specify an ``include`` pattern that ignores parent
|
|
352
|
+
packages. In a normal installation this would ignore all modules inside the
|
|
353
|
+
parent packages, and make them namespaces (reported in issue #3504),
|
|
354
|
+
so the editable mode should preserve this behaviour.
|
|
355
|
+
"""
|
|
356
|
+
files = {
|
|
357
|
+
"pkgA": {
|
|
358
|
+
"pyproject.toml": dedent(
|
|
359
|
+
"""\
|
|
360
|
+
[build-system]
|
|
361
|
+
requires = ["setuptools", "wheel"]
|
|
362
|
+
build-backend = "setuptools.build_meta"
|
|
363
|
+
|
|
364
|
+
[project]
|
|
365
|
+
name = "pkgA"
|
|
366
|
+
version = "3.14159"
|
|
367
|
+
|
|
368
|
+
[tool.setuptools]
|
|
369
|
+
packages.find.include = ["mypkg.*"]
|
|
370
|
+
"""
|
|
371
|
+
),
|
|
372
|
+
"mypkg": {
|
|
373
|
+
"__init__.py": "",
|
|
374
|
+
"other.py": "b = 1",
|
|
375
|
+
"n": {
|
|
376
|
+
"__init__.py": "",
|
|
377
|
+
"pkgA.py": "a = 1",
|
|
378
|
+
},
|
|
379
|
+
},
|
|
380
|
+
"MANIFEST.in": EXAMPLE["MANIFEST.in"],
|
|
381
|
+
},
|
|
382
|
+
}
|
|
383
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
384
|
+
pkg_A = tmp_path / "pkgA"
|
|
385
|
+
|
|
386
|
+
# use pip to install to the target directory
|
|
387
|
+
opts = ["--no-build-isolation"] # force current version of setuptools
|
|
388
|
+
venv.run(["python", "-m", "pip", "-v", "install", "-e", str(pkg_A), *opts])
|
|
389
|
+
out = venv.run(["python", "-c", "from mypkg.n import pkgA; print(pkgA.a)"])
|
|
390
|
+
assert out.strip() == "1"
|
|
391
|
+
cmd = """\
|
|
392
|
+
try:
|
|
393
|
+
import mypkg.other
|
|
394
|
+
except ImportError:
|
|
395
|
+
print("mypkg.other not defined")
|
|
396
|
+
"""
|
|
397
|
+
out = venv.run(["python", "-c", dedent(cmd)])
|
|
398
|
+
assert "mypkg.other not defined" in out
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def test_editable_with_prefix(tmp_path, sample_project, editable_opts):
|
|
402
|
+
"""
|
|
403
|
+
Editable install to a prefix should be discoverable.
|
|
404
|
+
"""
|
|
405
|
+
prefix = tmp_path / 'prefix'
|
|
406
|
+
|
|
407
|
+
# figure out where pip will likely install the package
|
|
408
|
+
site_packages_all = [
|
|
409
|
+
prefix / Path(path).relative_to(sys.prefix)
|
|
410
|
+
for path in sys.path
|
|
411
|
+
if 'site-packages' in path and path.startswith(sys.prefix)
|
|
412
|
+
]
|
|
413
|
+
|
|
414
|
+
for sp in site_packages_all:
|
|
415
|
+
sp.mkdir(parents=True)
|
|
416
|
+
|
|
417
|
+
# install workaround
|
|
418
|
+
_addsitedirs(site_packages_all)
|
|
419
|
+
|
|
420
|
+
env = dict(os.environ, PYTHONPATH=os.pathsep.join(map(str, site_packages_all)))
|
|
421
|
+
cmd = [
|
|
422
|
+
sys.executable,
|
|
423
|
+
'-m',
|
|
424
|
+
'pip',
|
|
425
|
+
'install',
|
|
426
|
+
'--editable',
|
|
427
|
+
str(sample_project),
|
|
428
|
+
'--prefix',
|
|
429
|
+
str(prefix),
|
|
430
|
+
'--no-build-isolation',
|
|
431
|
+
*editable_opts,
|
|
432
|
+
]
|
|
433
|
+
subprocess.check_call(cmd, env=env)
|
|
434
|
+
|
|
435
|
+
# now run 'sample' with the prefix on the PYTHONPATH
|
|
436
|
+
bin = 'Scripts' if platform.system() == 'Windows' else 'bin'
|
|
437
|
+
exe = prefix / bin / 'sample'
|
|
438
|
+
subprocess.check_call([exe], env=env)
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
class TestFinderTemplate:
|
|
442
|
+
"""This test focus in getting a particular implementation detail right.
|
|
443
|
+
If at some point in time the implementation is changed for something different,
|
|
444
|
+
this test can be modified or even excluded.
|
|
445
|
+
"""
|
|
446
|
+
|
|
447
|
+
def install_finder(self, finder):
|
|
448
|
+
loc = {}
|
|
449
|
+
exec(finder, loc, loc)
|
|
450
|
+
loc["install"]()
|
|
451
|
+
|
|
452
|
+
def test_packages(self, tmp_path):
|
|
453
|
+
files = {
|
|
454
|
+
"src1": {
|
|
455
|
+
"pkg1": {
|
|
456
|
+
"__init__.py": "",
|
|
457
|
+
"subpkg": {"mod1.py": "a = 42"},
|
|
458
|
+
},
|
|
459
|
+
},
|
|
460
|
+
"src2": {"mod2.py": "a = 43"},
|
|
461
|
+
}
|
|
462
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
463
|
+
|
|
464
|
+
mapping = {
|
|
465
|
+
"pkg1": str(tmp_path / "src1/pkg1"),
|
|
466
|
+
"mod2": str(tmp_path / "src2/mod2"),
|
|
467
|
+
}
|
|
468
|
+
template = _finder_template(str(uuid4()), mapping, {})
|
|
469
|
+
|
|
470
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
471
|
+
for mod in ("pkg1", "pkg1.subpkg", "pkg1.subpkg.mod1", "mod2"):
|
|
472
|
+
sys.modules.pop(mod, None)
|
|
473
|
+
|
|
474
|
+
self.install_finder(template)
|
|
475
|
+
mod1 = import_module("pkg1.subpkg.mod1")
|
|
476
|
+
mod2 = import_module("mod2")
|
|
477
|
+
subpkg = import_module("pkg1.subpkg")
|
|
478
|
+
|
|
479
|
+
assert mod1.a == 42
|
|
480
|
+
assert mod2.a == 43
|
|
481
|
+
expected = str((tmp_path / "src1/pkg1/subpkg").resolve())
|
|
482
|
+
assert_path(subpkg, expected)
|
|
483
|
+
|
|
484
|
+
def test_namespace(self, tmp_path):
|
|
485
|
+
files = {"pkg": {"__init__.py": "a = 13", "text.txt": "abc"}}
|
|
486
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
487
|
+
|
|
488
|
+
mapping = {"ns.othername": str(tmp_path / "pkg")}
|
|
489
|
+
namespaces = {"ns": []}
|
|
490
|
+
|
|
491
|
+
template = _finder_template(str(uuid4()), mapping, namespaces)
|
|
492
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
493
|
+
for mod in ("ns", "ns.othername"):
|
|
494
|
+
sys.modules.pop(mod, None)
|
|
495
|
+
|
|
496
|
+
self.install_finder(template)
|
|
497
|
+
pkg = import_module("ns.othername")
|
|
498
|
+
text = importlib_resources.files(pkg) / "text.txt"
|
|
499
|
+
|
|
500
|
+
expected = str((tmp_path / "pkg").resolve())
|
|
501
|
+
assert_path(pkg, expected)
|
|
502
|
+
assert pkg.a == 13
|
|
503
|
+
|
|
504
|
+
# Make sure resources can also be found
|
|
505
|
+
assert text.read_text(encoding="utf-8") == "abc"
|
|
506
|
+
|
|
507
|
+
def test_combine_namespaces(self, tmp_path):
|
|
508
|
+
files = {
|
|
509
|
+
"src1": {"ns": {"pkg1": {"__init__.py": "a = 13"}}},
|
|
510
|
+
"src2": {"ns": {"mod2.py": "b = 37"}},
|
|
511
|
+
}
|
|
512
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
513
|
+
|
|
514
|
+
mapping = {
|
|
515
|
+
"ns.pkgA": str(tmp_path / "src1/ns/pkg1"),
|
|
516
|
+
"ns": str(tmp_path / "src2/ns"),
|
|
517
|
+
}
|
|
518
|
+
namespaces_ = {"ns": [str(tmp_path / "src1"), str(tmp_path / "src2")]}
|
|
519
|
+
template = _finder_template(str(uuid4()), mapping, namespaces_)
|
|
520
|
+
|
|
521
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
522
|
+
for mod in ("ns", "ns.pkgA", "ns.mod2"):
|
|
523
|
+
sys.modules.pop(mod, None)
|
|
524
|
+
|
|
525
|
+
self.install_finder(template)
|
|
526
|
+
pkgA = import_module("ns.pkgA")
|
|
527
|
+
mod2 = import_module("ns.mod2")
|
|
528
|
+
|
|
529
|
+
expected = str((tmp_path / "src1/ns/pkg1").resolve())
|
|
530
|
+
assert_path(pkgA, expected)
|
|
531
|
+
assert pkgA.a == 13
|
|
532
|
+
assert mod2.b == 37
|
|
533
|
+
|
|
534
|
+
def test_combine_namespaces_nested(self, tmp_path):
|
|
535
|
+
"""
|
|
536
|
+
Users may attempt to combine namespace packages in a nested way via
|
|
537
|
+
``package_dir`` as shown in pypa/setuptools#4248.
|
|
538
|
+
"""
|
|
539
|
+
|
|
540
|
+
files = {
|
|
541
|
+
"src": {"my_package": {"my_module.py": "a = 13"}},
|
|
542
|
+
"src2": {"my_package2": {"my_module2.py": "b = 37"}},
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
stack = jaraco.path.DirectoryStack()
|
|
546
|
+
with stack.context(tmp_path):
|
|
547
|
+
jaraco.path.build(files)
|
|
548
|
+
attrs = {
|
|
549
|
+
"script_name": "%PEP 517%",
|
|
550
|
+
"package_dir": {
|
|
551
|
+
"different_name": "src/my_package",
|
|
552
|
+
"different_name.subpkg": "src2/my_package2",
|
|
553
|
+
},
|
|
554
|
+
"packages": ["different_name", "different_name.subpkg"],
|
|
555
|
+
}
|
|
556
|
+
dist = Distribution(attrs)
|
|
557
|
+
finder = _TopLevelFinder(dist, str(uuid4()))
|
|
558
|
+
code = next(v for k, v in finder.get_implementation() if k.endswith(".py"))
|
|
559
|
+
|
|
560
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
561
|
+
for mod in attrs["packages"]:
|
|
562
|
+
sys.modules.pop(mod, None)
|
|
563
|
+
|
|
564
|
+
self.install_finder(code)
|
|
565
|
+
mod1 = import_module("different_name.my_module")
|
|
566
|
+
mod2 = import_module("different_name.subpkg.my_module2")
|
|
567
|
+
|
|
568
|
+
expected = str((tmp_path / "src/my_package/my_module.py").resolve())
|
|
569
|
+
assert str(Path(mod1.__file__).resolve()) == expected
|
|
570
|
+
|
|
571
|
+
expected = str((tmp_path / "src2/my_package2/my_module2.py").resolve())
|
|
572
|
+
assert str(Path(mod2.__file__).resolve()) == expected
|
|
573
|
+
|
|
574
|
+
assert mod1.a == 13
|
|
575
|
+
assert mod2.b == 37
|
|
576
|
+
|
|
577
|
+
def test_dynamic_path_computation(self, tmp_path):
|
|
578
|
+
# Follows the example in PEP 420
|
|
579
|
+
files = {
|
|
580
|
+
"project1": {"parent": {"child": {"one.py": "x = 1"}}},
|
|
581
|
+
"project2": {"parent": {"child": {"two.py": "x = 2"}}},
|
|
582
|
+
"project3": {"parent": {"child": {"three.py": "x = 3"}}},
|
|
583
|
+
}
|
|
584
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
585
|
+
mapping = {}
|
|
586
|
+
namespaces_ = {"parent": [str(tmp_path / "project1/parent")]}
|
|
587
|
+
template = _finder_template(str(uuid4()), mapping, namespaces_)
|
|
588
|
+
|
|
589
|
+
mods = (f"parent.child.{name}" for name in ("one", "two", "three"))
|
|
590
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
591
|
+
for mod in ("parent", "parent.child", "parent.child", *mods):
|
|
592
|
+
sys.modules.pop(mod, None)
|
|
593
|
+
|
|
594
|
+
self.install_finder(template)
|
|
595
|
+
|
|
596
|
+
one = import_module("parent.child.one")
|
|
597
|
+
assert one.x == 1
|
|
598
|
+
|
|
599
|
+
with pytest.raises(ImportError):
|
|
600
|
+
import_module("parent.child.two")
|
|
601
|
+
|
|
602
|
+
sys.path.append(str(tmp_path / "project2"))
|
|
603
|
+
two = import_module("parent.child.two")
|
|
604
|
+
assert two.x == 2
|
|
605
|
+
|
|
606
|
+
with pytest.raises(ImportError):
|
|
607
|
+
import_module("parent.child.three")
|
|
608
|
+
|
|
609
|
+
sys.path.append(str(tmp_path / "project3"))
|
|
610
|
+
three = import_module("parent.child.three")
|
|
611
|
+
assert three.x == 3
|
|
612
|
+
|
|
613
|
+
def test_no_recursion(self, tmp_path):
|
|
614
|
+
# See issue #3550
|
|
615
|
+
files = {
|
|
616
|
+
"pkg": {
|
|
617
|
+
"__init__.py": "from . import pkg",
|
|
618
|
+
},
|
|
619
|
+
}
|
|
620
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
621
|
+
|
|
622
|
+
mapping = {
|
|
623
|
+
"pkg": str(tmp_path / "pkg"),
|
|
624
|
+
}
|
|
625
|
+
template = _finder_template(str(uuid4()), mapping, {})
|
|
626
|
+
|
|
627
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
628
|
+
sys.modules.pop("pkg", None)
|
|
629
|
+
|
|
630
|
+
self.install_finder(template)
|
|
631
|
+
with pytest.raises(ImportError, match="pkg"):
|
|
632
|
+
import_module("pkg")
|
|
633
|
+
|
|
634
|
+
def test_similar_name(self, tmp_path):
|
|
635
|
+
files = {
|
|
636
|
+
"foo": {
|
|
637
|
+
"__init__.py": "",
|
|
638
|
+
"bar": {
|
|
639
|
+
"__init__.py": "",
|
|
640
|
+
},
|
|
641
|
+
},
|
|
642
|
+
}
|
|
643
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
644
|
+
|
|
645
|
+
mapping = {
|
|
646
|
+
"foo": str(tmp_path / "foo"),
|
|
647
|
+
}
|
|
648
|
+
template = _finder_template(str(uuid4()), mapping, {})
|
|
649
|
+
|
|
650
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
651
|
+
sys.modules.pop("foo", None)
|
|
652
|
+
sys.modules.pop("foo.bar", None)
|
|
653
|
+
|
|
654
|
+
self.install_finder(template)
|
|
655
|
+
with pytest.raises(ImportError, match="foobar"):
|
|
656
|
+
import_module("foobar")
|
|
657
|
+
|
|
658
|
+
def test_case_sensitivity(self, tmp_path):
|
|
659
|
+
files = {
|
|
660
|
+
"foo": {
|
|
661
|
+
"__init__.py": "",
|
|
662
|
+
"lowercase.py": "x = 1",
|
|
663
|
+
"bar": {
|
|
664
|
+
"__init__.py": "",
|
|
665
|
+
"lowercase.py": "x = 2",
|
|
666
|
+
},
|
|
667
|
+
},
|
|
668
|
+
}
|
|
669
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
670
|
+
mapping = {
|
|
671
|
+
"foo": str(tmp_path / "foo"),
|
|
672
|
+
}
|
|
673
|
+
template = _finder_template(str(uuid4()), mapping, {})
|
|
674
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
675
|
+
sys.modules.pop("foo", None)
|
|
676
|
+
|
|
677
|
+
self.install_finder(template)
|
|
678
|
+
with pytest.raises(ImportError, match="'FOO'"):
|
|
679
|
+
import_module("FOO")
|
|
680
|
+
|
|
681
|
+
with pytest.raises(ImportError, match="'foo\\.LOWERCASE'"):
|
|
682
|
+
import_module("foo.LOWERCASE")
|
|
683
|
+
|
|
684
|
+
with pytest.raises(ImportError, match="'foo\\.bar\\.Lowercase'"):
|
|
685
|
+
import_module("foo.bar.Lowercase")
|
|
686
|
+
|
|
687
|
+
with pytest.raises(ImportError, match="'foo\\.BAR'"):
|
|
688
|
+
import_module("foo.BAR.lowercase")
|
|
689
|
+
|
|
690
|
+
with pytest.raises(ImportError, match="'FOO'"):
|
|
691
|
+
import_module("FOO.bar.lowercase")
|
|
692
|
+
|
|
693
|
+
mod = import_module("foo.lowercase")
|
|
694
|
+
assert mod.x == 1
|
|
695
|
+
|
|
696
|
+
mod = import_module("foo.bar.lowercase")
|
|
697
|
+
assert mod.x == 2
|
|
698
|
+
|
|
699
|
+
def test_namespace_case_sensitivity(self, tmp_path):
|
|
700
|
+
files = {
|
|
701
|
+
"pkg": {
|
|
702
|
+
"__init__.py": "a = 13",
|
|
703
|
+
"foo": {
|
|
704
|
+
"__init__.py": "b = 37",
|
|
705
|
+
"bar.py": "c = 42",
|
|
706
|
+
},
|
|
707
|
+
},
|
|
708
|
+
}
|
|
709
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
710
|
+
|
|
711
|
+
mapping = {"ns.othername": str(tmp_path / "pkg")}
|
|
712
|
+
namespaces = {"ns": []}
|
|
713
|
+
|
|
714
|
+
template = _finder_template(str(uuid4()), mapping, namespaces)
|
|
715
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
716
|
+
for mod in ("ns", "ns.othername"):
|
|
717
|
+
sys.modules.pop(mod, None)
|
|
718
|
+
|
|
719
|
+
self.install_finder(template)
|
|
720
|
+
pkg = import_module("ns.othername")
|
|
721
|
+
expected = str((tmp_path / "pkg").resolve())
|
|
722
|
+
assert_path(pkg, expected)
|
|
723
|
+
assert pkg.a == 13
|
|
724
|
+
|
|
725
|
+
foo = import_module("ns.othername.foo")
|
|
726
|
+
assert foo.b == 37
|
|
727
|
+
|
|
728
|
+
bar = import_module("ns.othername.foo.bar")
|
|
729
|
+
assert bar.c == 42
|
|
730
|
+
|
|
731
|
+
with pytest.raises(ImportError, match="'NS'"):
|
|
732
|
+
import_module("NS.othername.foo")
|
|
733
|
+
|
|
734
|
+
with pytest.raises(ImportError, match="'ns\\.othername\\.FOO\\'"):
|
|
735
|
+
import_module("ns.othername.FOO")
|
|
736
|
+
|
|
737
|
+
with pytest.raises(ImportError, match="'ns\\.othername\\.foo\\.BAR\\'"):
|
|
738
|
+
import_module("ns.othername.foo.BAR")
|
|
739
|
+
|
|
740
|
+
def test_intermediate_packages(self, tmp_path):
|
|
741
|
+
"""
|
|
742
|
+
The finder should not import ``fullname`` if the intermediate segments
|
|
743
|
+
don't exist (see pypa/setuptools#4019).
|
|
744
|
+
"""
|
|
745
|
+
files = {
|
|
746
|
+
"src": {
|
|
747
|
+
"mypkg": {
|
|
748
|
+
"__init__.py": "",
|
|
749
|
+
"config.py": "a = 13",
|
|
750
|
+
"helloworld.py": "b = 13",
|
|
751
|
+
"components": {
|
|
752
|
+
"config.py": "a = 37",
|
|
753
|
+
},
|
|
754
|
+
},
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
758
|
+
|
|
759
|
+
mapping = {"mypkg": str(tmp_path / "src/mypkg")}
|
|
760
|
+
template = _finder_template(str(uuid4()), mapping, {})
|
|
761
|
+
|
|
762
|
+
with contexts.save_paths(), contexts.save_sys_modules():
|
|
763
|
+
for mod in (
|
|
764
|
+
"mypkg",
|
|
765
|
+
"mypkg.config",
|
|
766
|
+
"mypkg.helloworld",
|
|
767
|
+
"mypkg.components",
|
|
768
|
+
"mypkg.components.config",
|
|
769
|
+
"mypkg.components.helloworld",
|
|
770
|
+
):
|
|
771
|
+
sys.modules.pop(mod, None)
|
|
772
|
+
|
|
773
|
+
self.install_finder(template)
|
|
774
|
+
|
|
775
|
+
config = import_module("mypkg.components.config")
|
|
776
|
+
assert config.a == 37
|
|
777
|
+
|
|
778
|
+
helloworld = import_module("mypkg.helloworld")
|
|
779
|
+
assert helloworld.b == 13
|
|
780
|
+
|
|
781
|
+
with pytest.raises(ImportError):
|
|
782
|
+
import_module("mypkg.components.helloworld")
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
def test_pkg_roots(tmp_path):
|
|
786
|
+
"""This test focus in getting a particular implementation detail right.
|
|
787
|
+
If at some point in time the implementation is changed for something different,
|
|
788
|
+
this test can be modified or even excluded.
|
|
789
|
+
"""
|
|
790
|
+
files = {
|
|
791
|
+
"a": {"b": {"__init__.py": "ab = 1"}, "__init__.py": "a = 1"},
|
|
792
|
+
"d": {"__init__.py": "d = 1", "e": {"__init__.py": "de = 1"}},
|
|
793
|
+
"f": {"g": {"h": {"__init__.py": "fgh = 1"}}},
|
|
794
|
+
"other": {"__init__.py": "abc = 1"},
|
|
795
|
+
"another": {"__init__.py": "abcxyz = 1"},
|
|
796
|
+
"yet_another": {"__init__.py": "mnopq = 1"},
|
|
797
|
+
}
|
|
798
|
+
jaraco.path.build(files, prefix=tmp_path)
|
|
799
|
+
package_dir = {
|
|
800
|
+
"a.b.c": "other",
|
|
801
|
+
"a.b.c.x.y.z": "another",
|
|
802
|
+
"m.n.o.p.q": "yet_another",
|
|
803
|
+
}
|
|
804
|
+
packages = [
|
|
805
|
+
"a",
|
|
806
|
+
"a.b",
|
|
807
|
+
"a.b.c",
|
|
808
|
+
"a.b.c.x.y",
|
|
809
|
+
"a.b.c.x.y.z",
|
|
810
|
+
"d",
|
|
811
|
+
"d.e",
|
|
812
|
+
"f",
|
|
813
|
+
"f.g",
|
|
814
|
+
"f.g.h",
|
|
815
|
+
"m.n.o.p.q",
|
|
816
|
+
]
|
|
817
|
+
roots = _find_package_roots(packages, package_dir, tmp_path)
|
|
818
|
+
assert roots == {
|
|
819
|
+
"a": str(tmp_path / "a"),
|
|
820
|
+
"a.b.c": str(tmp_path / "other"),
|
|
821
|
+
"a.b.c.x.y.z": str(tmp_path / "another"),
|
|
822
|
+
"d": str(tmp_path / "d"),
|
|
823
|
+
"f": str(tmp_path / "f"),
|
|
824
|
+
"m.n.o.p.q": str(tmp_path / "yet_another"),
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
ns = set(dict(_find_namespaces(packages, roots)))
|
|
828
|
+
assert ns == {"f", "f.g"}
|
|
829
|
+
|
|
830
|
+
ns = set(_find_virtual_namespaces(roots))
|
|
831
|
+
assert ns == {"a.b", "a.b.c.x", "a.b.c.x.y", "m", "m.n", "m.n.o", "m.n.o.p"}
|
|
832
|
+
|
|
833
|
+
|
|
834
|
+
class TestOverallBehaviour:
|
|
835
|
+
PYPROJECT = """\
|
|
836
|
+
[build-system]
|
|
837
|
+
requires = ["setuptools"]
|
|
838
|
+
build-backend = "setuptools.build_meta"
|
|
839
|
+
|
|
840
|
+
[project]
|
|
841
|
+
name = "mypkg"
|
|
842
|
+
version = "3.14159"
|
|
843
|
+
"""
|
|
844
|
+
|
|
845
|
+
# Any: Would need a TypedDict. Keep it simple for tests
|
|
846
|
+
FLAT_LAYOUT: dict[str, Any] = {
|
|
847
|
+
"pyproject.toml": dedent(PYPROJECT),
|
|
848
|
+
"MANIFEST.in": EXAMPLE["MANIFEST.in"],
|
|
849
|
+
"otherfile.py": "",
|
|
850
|
+
"mypkg": {
|
|
851
|
+
"__init__.py": "",
|
|
852
|
+
"mod1.py": "var = 42",
|
|
853
|
+
"subpackage": {
|
|
854
|
+
"__init__.py": "",
|
|
855
|
+
"mod2.py": "var = 13",
|
|
856
|
+
"resource_file.txt": "resource 39",
|
|
857
|
+
},
|
|
858
|
+
},
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
EXAMPLES = {
|
|
862
|
+
"flat-layout": FLAT_LAYOUT,
|
|
863
|
+
"src-layout": {
|
|
864
|
+
"pyproject.toml": dedent(PYPROJECT),
|
|
865
|
+
"MANIFEST.in": EXAMPLE["MANIFEST.in"],
|
|
866
|
+
"otherfile.py": "",
|
|
867
|
+
"src": {"mypkg": FLAT_LAYOUT["mypkg"]},
|
|
868
|
+
},
|
|
869
|
+
"custom-layout": {
|
|
870
|
+
"pyproject.toml": dedent(PYPROJECT)
|
|
871
|
+
+ dedent(
|
|
872
|
+
"""\
|
|
873
|
+
[tool.setuptools]
|
|
874
|
+
packages = ["mypkg", "mypkg.subpackage"]
|
|
875
|
+
|
|
876
|
+
[tool.setuptools.package-dir]
|
|
877
|
+
"mypkg.subpackage" = "other"
|
|
878
|
+
"""
|
|
879
|
+
),
|
|
880
|
+
"MANIFEST.in": EXAMPLE["MANIFEST.in"],
|
|
881
|
+
"otherfile.py": "",
|
|
882
|
+
"mypkg": {
|
|
883
|
+
"__init__.py": "",
|
|
884
|
+
"mod1.py": FLAT_LAYOUT["mypkg"]["mod1.py"],
|
|
885
|
+
},
|
|
886
|
+
"other": FLAT_LAYOUT["mypkg"]["subpackage"],
|
|
887
|
+
},
|
|
888
|
+
"namespace": {
|
|
889
|
+
"pyproject.toml": dedent(PYPROJECT),
|
|
890
|
+
"MANIFEST.in": EXAMPLE["MANIFEST.in"],
|
|
891
|
+
"otherfile.py": "",
|
|
892
|
+
"src": {
|
|
893
|
+
"mypkg": {
|
|
894
|
+
"mod1.py": FLAT_LAYOUT["mypkg"]["mod1.py"],
|
|
895
|
+
"subpackage": FLAT_LAYOUT["mypkg"]["subpackage"],
|
|
896
|
+
},
|
|
897
|
+
},
|
|
898
|
+
},
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
@pytest.mark.xfail(sys.platform == "darwin", reason="pypa/setuptools#4328")
|
|
902
|
+
@pytest.mark.parametrize("layout", EXAMPLES.keys())
|
|
903
|
+
def test_editable_install(self, tmp_path, venv, layout, editable_opts):
|
|
904
|
+
project, _ = install_project(
|
|
905
|
+
"mypkg", venv, tmp_path, self.EXAMPLES[layout], *editable_opts
|
|
906
|
+
)
|
|
907
|
+
|
|
908
|
+
# Ensure stray files are not importable
|
|
909
|
+
cmd_import_error = """\
|
|
910
|
+
try:
|
|
911
|
+
import otherfile
|
|
912
|
+
except ImportError as ex:
|
|
913
|
+
print(ex)
|
|
914
|
+
"""
|
|
915
|
+
out = venv.run(["python", "-c", dedent(cmd_import_error)])
|
|
916
|
+
assert "No module named 'otherfile'" in out
|
|
917
|
+
|
|
918
|
+
# Ensure the modules are importable
|
|
919
|
+
cmd_get_vars = """\
|
|
920
|
+
import mypkg, mypkg.mod1, mypkg.subpackage.mod2
|
|
921
|
+
print(mypkg.mod1.var, mypkg.subpackage.mod2.var)
|
|
922
|
+
"""
|
|
923
|
+
out = venv.run(["python", "-c", dedent(cmd_get_vars)])
|
|
924
|
+
assert "42 13" in out
|
|
925
|
+
|
|
926
|
+
# Ensure resources are reachable
|
|
927
|
+
cmd_get_resource = """\
|
|
928
|
+
import mypkg.subpackage
|
|
929
|
+
from setuptools._importlib import resources as importlib_resources
|
|
930
|
+
text = importlib_resources.files(mypkg.subpackage) / "resource_file.txt"
|
|
931
|
+
print(text.read_text(encoding="utf-8"))
|
|
932
|
+
"""
|
|
933
|
+
out = venv.run(["python", "-c", dedent(cmd_get_resource)])
|
|
934
|
+
assert "resource 39" in out
|
|
935
|
+
|
|
936
|
+
# Ensure files are editable
|
|
937
|
+
mod1 = next(project.glob("**/mod1.py"))
|
|
938
|
+
mod2 = next(project.glob("**/mod2.py"))
|
|
939
|
+
resource_file = next(project.glob("**/resource_file.txt"))
|
|
940
|
+
|
|
941
|
+
mod1.write_text("var = 17", encoding="utf-8")
|
|
942
|
+
mod2.write_text("var = 781", encoding="utf-8")
|
|
943
|
+
resource_file.write_text("resource 374", encoding="utf-8")
|
|
944
|
+
|
|
945
|
+
out = venv.run(["python", "-c", dedent(cmd_get_vars)])
|
|
946
|
+
assert "42 13" not in out
|
|
947
|
+
assert "17 781" in out
|
|
948
|
+
|
|
949
|
+
out = venv.run(["python", "-c", dedent(cmd_get_resource)])
|
|
950
|
+
assert "resource 39" not in out
|
|
951
|
+
assert "resource 374" in out
|
|
952
|
+
|
|
953
|
+
|
|
954
|
+
class TestLinkTree:
|
|
955
|
+
FILES = deepcopy(TestOverallBehaviour.EXAMPLES["src-layout"])
|
|
956
|
+
FILES["pyproject.toml"] += dedent(
|
|
957
|
+
"""\
|
|
958
|
+
[tool.setuptools]
|
|
959
|
+
# Temporary workaround: both `include-package-data` and `package-data` configs
|
|
960
|
+
# can be removed after #3260 is fixed.
|
|
961
|
+
include-package-data = false
|
|
962
|
+
package-data = {"*" = ["*.txt"]}
|
|
963
|
+
|
|
964
|
+
[tool.setuptools.packages.find]
|
|
965
|
+
where = ["src"]
|
|
966
|
+
exclude = ["*.subpackage*"]
|
|
967
|
+
"""
|
|
968
|
+
)
|
|
969
|
+
FILES["src"]["mypkg"]["resource.not_in_manifest"] = "abc"
|
|
970
|
+
|
|
971
|
+
def test_generated_tree(self, tmp_path):
|
|
972
|
+
jaraco.path.build(self.FILES, prefix=tmp_path)
|
|
973
|
+
|
|
974
|
+
with _Path(tmp_path):
|
|
975
|
+
name = "mypkg-3.14159"
|
|
976
|
+
dist = Distribution({"script_name": "%PEP 517%"})
|
|
977
|
+
dist.parse_config_files()
|
|
978
|
+
|
|
979
|
+
wheel = Mock()
|
|
980
|
+
aux = tmp_path / ".aux"
|
|
981
|
+
build = tmp_path / ".build"
|
|
982
|
+
aux.mkdir()
|
|
983
|
+
build.mkdir()
|
|
984
|
+
|
|
985
|
+
build_py = dist.get_command_obj("build_py")
|
|
986
|
+
build_py.editable_mode = True
|
|
987
|
+
build_py.build_lib = str(build)
|
|
988
|
+
build_py.ensure_finalized()
|
|
989
|
+
outputs = build_py.get_outputs()
|
|
990
|
+
output_mapping = build_py.get_output_mapping()
|
|
991
|
+
|
|
992
|
+
make_tree = _LinkTree(dist, name, aux, build)
|
|
993
|
+
make_tree(wheel, outputs, output_mapping)
|
|
994
|
+
|
|
995
|
+
mod1 = next(aux.glob("**/mod1.py"))
|
|
996
|
+
expected = tmp_path / "src/mypkg/mod1.py"
|
|
997
|
+
assert_link_to(mod1, expected)
|
|
998
|
+
|
|
999
|
+
assert next(aux.glob("**/subpackage"), None) is None
|
|
1000
|
+
assert next(aux.glob("**/mod2.py"), None) is None
|
|
1001
|
+
assert next(aux.glob("**/resource_file.txt"), None) is None
|
|
1002
|
+
|
|
1003
|
+
assert next(aux.glob("**/resource.not_in_manifest"), None) is None
|
|
1004
|
+
|
|
1005
|
+
def test_strict_install(self, tmp_path, venv):
|
|
1006
|
+
opts = ["--config-settings", "editable-mode=strict"]
|
|
1007
|
+
install_project("mypkg", venv, tmp_path, self.FILES, *opts)
|
|
1008
|
+
|
|
1009
|
+
out = venv.run(["python", "-c", "import mypkg.mod1; print(mypkg.mod1.var)"])
|
|
1010
|
+
assert "42" in out
|
|
1011
|
+
|
|
1012
|
+
# Ensure packages excluded from distribution are not importable
|
|
1013
|
+
cmd_import_error = """\
|
|
1014
|
+
try:
|
|
1015
|
+
from mypkg import subpackage
|
|
1016
|
+
except ImportError as ex:
|
|
1017
|
+
print(ex)
|
|
1018
|
+
"""
|
|
1019
|
+
out = venv.run(["python", "-c", dedent(cmd_import_error)])
|
|
1020
|
+
assert "cannot import name 'subpackage'" in out
|
|
1021
|
+
|
|
1022
|
+
# Ensure resource files excluded from distribution are not reachable
|
|
1023
|
+
cmd_get_resource = """\
|
|
1024
|
+
import mypkg
|
|
1025
|
+
from setuptools._importlib import resources as importlib_resources
|
|
1026
|
+
try:
|
|
1027
|
+
text = importlib_resources.files(mypkg) / "resource.not_in_manifest"
|
|
1028
|
+
print(text.read_text(encoding="utf-8"))
|
|
1029
|
+
except FileNotFoundError as ex:
|
|
1030
|
+
print(ex)
|
|
1031
|
+
"""
|
|
1032
|
+
out = venv.run(["python", "-c", dedent(cmd_get_resource)])
|
|
1033
|
+
assert "No such file or directory" in out
|
|
1034
|
+
assert "resource.not_in_manifest" in out
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
@pytest.mark.filterwarnings("ignore:.*compat.*:setuptools.SetuptoolsDeprecationWarning")
|
|
1038
|
+
def test_compat_install(tmp_path, venv):
|
|
1039
|
+
# TODO: Remove `compat` after Dec/2022.
|
|
1040
|
+
opts = ["--config-settings", "editable-mode=compat"]
|
|
1041
|
+
files = TestOverallBehaviour.EXAMPLES["custom-layout"]
|
|
1042
|
+
install_project("mypkg", venv, tmp_path, files, *opts)
|
|
1043
|
+
|
|
1044
|
+
out = venv.run(["python", "-c", "import mypkg.mod1; print(mypkg.mod1.var)"])
|
|
1045
|
+
assert "42" in out
|
|
1046
|
+
|
|
1047
|
+
expected_path = comparable_path(str(tmp_path))
|
|
1048
|
+
|
|
1049
|
+
# Compatible behaviour will make spurious modules and excluded
|
|
1050
|
+
# files importable directly from the original path
|
|
1051
|
+
for cmd in (
|
|
1052
|
+
"import otherfile; print(otherfile)",
|
|
1053
|
+
"import other; print(other)",
|
|
1054
|
+
"import mypkg; print(mypkg)",
|
|
1055
|
+
):
|
|
1056
|
+
out = comparable_path(venv.run(["python", "-c", cmd]))
|
|
1057
|
+
assert expected_path in out
|
|
1058
|
+
|
|
1059
|
+
# Compatible behaviour will not consider custom mappings
|
|
1060
|
+
cmd = """\
|
|
1061
|
+
try:
|
|
1062
|
+
from mypkg import subpackage;
|
|
1063
|
+
except ImportError as ex:
|
|
1064
|
+
print(ex)
|
|
1065
|
+
"""
|
|
1066
|
+
out = venv.run(["python", "-c", dedent(cmd)])
|
|
1067
|
+
assert "cannot import name 'subpackage'" in out
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
@pytest.mark.uses_network
|
|
1071
|
+
def test_pbr_integration(pbr_package, venv, editable_opts):
|
|
1072
|
+
"""Ensure editable installs work with pbr, issue #3500"""
|
|
1073
|
+
cmd = [
|
|
1074
|
+
'python',
|
|
1075
|
+
'-m',
|
|
1076
|
+
'pip',
|
|
1077
|
+
'-v',
|
|
1078
|
+
'install',
|
|
1079
|
+
'--editable',
|
|
1080
|
+
pbr_package,
|
|
1081
|
+
*editable_opts,
|
|
1082
|
+
]
|
|
1083
|
+
venv.run(cmd, stderr=subprocess.STDOUT)
|
|
1084
|
+
out = venv.run(["python", "-c", "import mypkg.hello"])
|
|
1085
|
+
assert "Hello world!" in out
|
|
1086
|
+
|
|
1087
|
+
|
|
1088
|
+
class TestCustomBuildPy:
|
|
1089
|
+
"""
|
|
1090
|
+
Issue #3501 indicates that some plugins/customizations might rely on:
|
|
1091
|
+
|
|
1092
|
+
1. ``build_py`` not running
|
|
1093
|
+
2. ``build_py`` always copying files to ``build_lib``
|
|
1094
|
+
|
|
1095
|
+
During the transition period setuptools should prevent potential errors from
|
|
1096
|
+
happening due to those assumptions.
|
|
1097
|
+
"""
|
|
1098
|
+
|
|
1099
|
+
# TODO: Remove tests after _run_build_steps is removed.
|
|
1100
|
+
|
|
1101
|
+
FILES = {
|
|
1102
|
+
**TestOverallBehaviour.EXAMPLES["flat-layout"],
|
|
1103
|
+
"setup.py": dedent(
|
|
1104
|
+
"""\
|
|
1105
|
+
import pathlib
|
|
1106
|
+
from setuptools import setup
|
|
1107
|
+
from setuptools.command.build_py import build_py as orig
|
|
1108
|
+
|
|
1109
|
+
class my_build_py(orig):
|
|
1110
|
+
def run(self):
|
|
1111
|
+
super().run()
|
|
1112
|
+
raise ValueError("TEST_RAISE")
|
|
1113
|
+
|
|
1114
|
+
setup(cmdclass={"build_py": my_build_py})
|
|
1115
|
+
"""
|
|
1116
|
+
),
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
def test_safeguarded_from_errors(self, tmp_path, venv):
|
|
1120
|
+
"""Ensure that errors in custom build_py are reported as warnings"""
|
|
1121
|
+
# Warnings should show up
|
|
1122
|
+
_, out = install_project("mypkg", venv, tmp_path, self.FILES)
|
|
1123
|
+
assert "SetuptoolsDeprecationWarning" in out
|
|
1124
|
+
assert "ValueError: TEST_RAISE" in out
|
|
1125
|
+
# but installation should be successful
|
|
1126
|
+
out = venv.run(["python", "-c", "import mypkg.mod1; print(mypkg.mod1.var)"])
|
|
1127
|
+
assert "42" in out
|
|
1128
|
+
|
|
1129
|
+
|
|
1130
|
+
class TestCustomBuildWheel:
|
|
1131
|
+
def install_custom_build_wheel(self, dist):
|
|
1132
|
+
bdist_wheel_cls = dist.get_command_class("bdist_wheel")
|
|
1133
|
+
|
|
1134
|
+
class MyBdistWheel(bdist_wheel_cls):
|
|
1135
|
+
def get_tag(self):
|
|
1136
|
+
# In issue #3513, we can see that some extensions may try to access
|
|
1137
|
+
# the `plat_name` property in bdist_wheel
|
|
1138
|
+
if self.plat_name.startswith("macosx-"):
|
|
1139
|
+
_ = "macOS platform"
|
|
1140
|
+
return super().get_tag()
|
|
1141
|
+
|
|
1142
|
+
dist.cmdclass["bdist_wheel"] = MyBdistWheel
|
|
1143
|
+
|
|
1144
|
+
def test_access_plat_name(self, tmpdir_cwd):
|
|
1145
|
+
# Even when a custom bdist_wheel tries to access plat_name the build should
|
|
1146
|
+
# be successful
|
|
1147
|
+
jaraco.path.build({"module.py": "x = 42"})
|
|
1148
|
+
dist = Distribution()
|
|
1149
|
+
dist.script_name = "setup.py"
|
|
1150
|
+
dist.set_defaults()
|
|
1151
|
+
self.install_custom_build_wheel(dist)
|
|
1152
|
+
cmd = editable_wheel(dist)
|
|
1153
|
+
cmd.ensure_finalized()
|
|
1154
|
+
cmd.run()
|
|
1155
|
+
wheel_file = str(next(Path().glob('dist/*.whl')))
|
|
1156
|
+
assert "editable" in wheel_file
|
|
1157
|
+
|
|
1158
|
+
|
|
1159
|
+
class TestCustomBuildExt:
|
|
1160
|
+
def install_custom_build_ext_distutils(self, dist):
|
|
1161
|
+
from distutils.command.build_ext import build_ext as build_ext_cls
|
|
1162
|
+
|
|
1163
|
+
class MyBuildExt(build_ext_cls):
|
|
1164
|
+
pass
|
|
1165
|
+
|
|
1166
|
+
dist.cmdclass["build_ext"] = MyBuildExt
|
|
1167
|
+
|
|
1168
|
+
@pytest.mark.skipif(
|
|
1169
|
+
sys.platform != "linux", reason="compilers may fail without correct setup"
|
|
1170
|
+
)
|
|
1171
|
+
def test_distutils_leave_inplace_files(self, tmpdir_cwd):
|
|
1172
|
+
jaraco.path.build({"module.c": ""})
|
|
1173
|
+
attrs = {
|
|
1174
|
+
"ext_modules": [Extension("module", ["module.c"])],
|
|
1175
|
+
}
|
|
1176
|
+
dist = Distribution(attrs)
|
|
1177
|
+
dist.script_name = "setup.py"
|
|
1178
|
+
dist.set_defaults()
|
|
1179
|
+
self.install_custom_build_ext_distutils(dist)
|
|
1180
|
+
cmd = editable_wheel(dist)
|
|
1181
|
+
cmd.ensure_finalized()
|
|
1182
|
+
cmd.run()
|
|
1183
|
+
wheel_file = str(next(Path().glob('dist/*.whl')))
|
|
1184
|
+
assert "editable" in wheel_file
|
|
1185
|
+
files = [p for p in Path().glob("module.*") if p.suffix != ".c"]
|
|
1186
|
+
assert len(files) == 1
|
|
1187
|
+
name = files[0].name
|
|
1188
|
+
assert any(name.endswith(ext) for ext in EXTENSION_SUFFIXES)
|
|
1189
|
+
|
|
1190
|
+
|
|
1191
|
+
def test_debugging_tips(tmpdir_cwd, monkeypatch):
|
|
1192
|
+
"""Make sure to display useful debugging tips to the user."""
|
|
1193
|
+
jaraco.path.build({"module.py": "x = 42"})
|
|
1194
|
+
dist = Distribution()
|
|
1195
|
+
dist.script_name = "setup.py"
|
|
1196
|
+
dist.set_defaults()
|
|
1197
|
+
cmd = editable_wheel(dist)
|
|
1198
|
+
cmd.ensure_finalized()
|
|
1199
|
+
|
|
1200
|
+
SimulatedErr = type("SimulatedErr", (Exception,), {})
|
|
1201
|
+
simulated_failure = Mock(side_effect=SimulatedErr())
|
|
1202
|
+
monkeypatch.setattr(cmd, "get_finalized_command", simulated_failure)
|
|
1203
|
+
|
|
1204
|
+
with pytest.raises(SimulatedErr) as ctx:
|
|
1205
|
+
cmd.run()
|
|
1206
|
+
assert any('debugging-tips' in note for note in ctx.value.__notes__)
|
|
1207
|
+
|
|
1208
|
+
|
|
1209
|
+
@pytest.mark.filterwarnings("error")
|
|
1210
|
+
def test_encode_pth():
|
|
1211
|
+
"""Ensure _encode_pth function does not produce encoding warnings"""
|
|
1212
|
+
content = _encode_pth("tkmilan_ç_utf8") # no warnings (would be turned into errors)
|
|
1213
|
+
assert isinstance(content, bytes)
|
|
1214
|
+
|
|
1215
|
+
|
|
1216
|
+
def install_project(name, venv, tmp_path, files, *opts):
|
|
1217
|
+
project = tmp_path / name
|
|
1218
|
+
project.mkdir()
|
|
1219
|
+
jaraco.path.build(files, prefix=project)
|
|
1220
|
+
opts = [*opts, "--no-build-isolation"] # force current version of setuptools
|
|
1221
|
+
out = venv.run(
|
|
1222
|
+
["python", "-m", "pip", "-v", "install", "-e", str(project), *opts],
|
|
1223
|
+
stderr=subprocess.STDOUT,
|
|
1224
|
+
)
|
|
1225
|
+
return project, out
|
|
1226
|
+
|
|
1227
|
+
|
|
1228
|
+
def _addsitedirs(new_dirs):
|
|
1229
|
+
"""To use this function, it is necessary to insert new_dir in front of sys.path.
|
|
1230
|
+
The Python process will try to import a ``sitecustomize`` module on startup.
|
|
1231
|
+
If we manipulate sys.path/PYTHONPATH, we can force it to run our code,
|
|
1232
|
+
which invokes ``addsitedir`` and ensure ``.pth`` files are loaded.
|
|
1233
|
+
"""
|
|
1234
|
+
content = '\n'.join(
|
|
1235
|
+
("import site",)
|
|
1236
|
+
+ tuple(f"site.addsitedir({os.fspath(new_dir)!r})" for new_dir in new_dirs)
|
|
1237
|
+
)
|
|
1238
|
+
(new_dirs[0] / "sitecustomize.py").write_text(content, encoding="utf-8")
|
|
1239
|
+
|
|
1240
|
+
|
|
1241
|
+
# ---- Assertion Helpers ----
|
|
1242
|
+
|
|
1243
|
+
|
|
1244
|
+
def assert_path(pkg, expected):
|
|
1245
|
+
# __path__ is not guaranteed to exist, so we have to account for that
|
|
1246
|
+
if pkg.__path__:
|
|
1247
|
+
path = next(iter(pkg.__path__), None)
|
|
1248
|
+
if path:
|
|
1249
|
+
assert str(Path(path).resolve()) == expected
|
|
1250
|
+
|
|
1251
|
+
|
|
1252
|
+
def assert_link_to(file: Path, other: Path) -> None:
|
|
1253
|
+
if file.is_symlink():
|
|
1254
|
+
assert str(file.resolve()) == str(other.resolve())
|
|
1255
|
+
else:
|
|
1256
|
+
file_stat = file.stat()
|
|
1257
|
+
other_stat = other.stat()
|
|
1258
|
+
assert file_stat[stat.ST_INO] == other_stat[stat.ST_INO]
|
|
1259
|
+
assert file_stat[stat.ST_DEV] == other_stat[stat.ST_DEV]
|
|
1260
|
+
|
|
1261
|
+
|
|
1262
|
+
def comparable_path(str_with_path: str) -> str:
|
|
1263
|
+
return str_with_path.lower().replace(os.sep, "/").replace("//", "/")
|