Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
test_egg_info.py1307 linesDownload Raw Back to tests
1from __future__ import annotations2 3import ast4import glob5import os6import re7import stat8import sys9import time10from pathlib import Path11from unittest import mock12 13import pytest14from jaraco import path15 16from setuptools import errors17from setuptools.command.egg_info import egg_info, manifest_maker, write_entries18from setuptools.dist import Distribution19 20from . import contexts, environment21from .textwrap import DALS22 23 24class Environment(str):25    pass26 27 28@pytest.fixture29def env():30    with contexts.tempdir(prefix='setuptools-test.') as env_dir:31        env = Environment(env_dir)32        os.chmod(env_dir, stat.S_IRWXU)33        subs = 'home', 'lib', 'scripts', 'data', 'egg-base'34        env.paths = dict((dirname, os.path.join(env_dir, dirname)) for dirname in subs)35        list(map(os.mkdir, env.paths.values()))36        path.build({37            env.paths['home']: {38                '.pydistutils.cfg': DALS(39                    """40                [egg_info]41                egg-base = {egg-base}42                """.format(**env.paths)43                )44            }45        })46        yield env47 48 49class TestEggInfo:50    setup_script = DALS(51        """52        from setuptools import setup53 54        setup(55            name='foo',56            py_modules=['hello'],57            entry_points={'console_scripts': ['hi = hello.run']},58            zip_safe=False,59        )60        """61    )62 63    def _create_project(self):64        path.build({65            'setup.py': self.setup_script,66            'hello.py': DALS(67                """68                def run():69                    print('hello')70                """71            ),72        })73 74    @staticmethod75    def _extract_mv_version(pkg_info_lines: list[str]) -> tuple[int, int]:76        version_str = pkg_info_lines[0].split(' ')[1]77        major, minor = map(int, version_str.split('.')[:2])78        return major, minor79 80    def test_egg_info_save_version_info_setup_empty(self, tmpdir_cwd, env):81        """82        When the egg_info section is empty or not present, running83        save_version_info should add the settings to the setup.cfg84        in a deterministic order.85        """86        setup_cfg = os.path.join(env.paths['home'], 'setup.cfg')87        dist = Distribution()88        ei = egg_info(dist)89        ei.initialize_options()90        ei.save_version_info(setup_cfg)91 92        with open(setup_cfg, 'r', encoding="utf-8") as f:93            content = f.read()94 95        assert '[egg_info]' in content96        assert 'tag_build =' in content97        assert 'tag_date = 0' in content98 99        expected_order = (100            'tag_build',101            'tag_date',102        )103 104        self._validate_content_order(content, expected_order)105 106    @staticmethod107    def _validate_content_order(content, expected):108        """109        Assert that the strings in expected appear in content110        in order.111        """112        pattern = '.*'.join(expected)113        flags = re.MULTILINE | re.DOTALL114        assert re.search(pattern, content, flags)115 116    def test_egg_info_save_version_info_setup_defaults(self, tmpdir_cwd, env):117        """118        When running save_version_info on an existing setup.cfg119        with the 'default' values present from a previous run,120        the file should remain unchanged.121        """122        setup_cfg = os.path.join(env.paths['home'], 'setup.cfg')123        path.build({124            setup_cfg: DALS(125                """126            [egg_info]127            tag_build =128            tag_date = 0129            """130            ),131        })132        dist = Distribution()133        ei = egg_info(dist)134        ei.initialize_options()135        ei.save_version_info(setup_cfg)136 137        with open(setup_cfg, 'r', encoding="utf-8") as f:138            content = f.read()139 140        assert '[egg_info]' in content141        assert 'tag_build =' in content142        assert 'tag_date = 0' in content143 144        expected_order = (145            'tag_build',146            'tag_date',147        )148 149        self._validate_content_order(content, expected_order)150 151    def test_expected_files_produced(self, tmpdir_cwd, env):152        self._create_project()153 154        self._run_egg_info_command(tmpdir_cwd, env)155        actual = os.listdir('foo.egg-info')156 157        expected = [158            'PKG-INFO',159            'SOURCES.txt',160            'dependency_links.txt',161            'entry_points.txt',162            'not-zip-safe',163            'top_level.txt',164        ]165        assert sorted(actual) == expected166 167    def test_handling_utime_error(self, tmpdir_cwd, env):168        dist = Distribution()169        ei = egg_info(dist)170        utime_patch = mock.patch('os.utime', side_effect=OSError("TEST"))171        mkpath_patch = mock.patch(172            'setuptools.command.egg_info.egg_info.mkpath', return_val=None173        )174 175        with utime_patch, mkpath_patch:176            import distutils.errors177 178            msg = r"Cannot update time stamp of directory 'None'"179            with pytest.raises(distutils.errors.DistutilsFileError, match=msg):180                ei.run()181 182    def test_license_is_a_string(self, tmpdir_cwd, env):183        setup_config = DALS(184            """185            [metadata]186            name=foo187            version=0.0.1188            license=file:MIT189            """190        )191 192        setup_script = DALS(193            """194            from setuptools import setup195 196            setup()197            """198        )199 200        path.build({201            'setup.py': setup_script,202            'setup.cfg': setup_config,203        })204 205        # This command should fail with a ValueError, but because it's206        # currently configured to use a subprocess, the actual traceback207        # object is lost and we need to parse it from stderr208        with pytest.raises(AssertionError) as exc:209            self._run_egg_info_command(tmpdir_cwd, env)210 211        # The only argument to the assertion error should be a traceback212        # containing a ValueError213        assert 'ValueError' in exc.value.args[0]214 215    def test_rebuilt(self, tmpdir_cwd, env):216        """Ensure timestamps are updated when the command is re-run."""217        self._create_project()218 219        self._run_egg_info_command(tmpdir_cwd, env)220        timestamp_a = os.path.getmtime('foo.egg-info')221 222        # arbitrary sleep just to handle *really* fast systems223        time.sleep(0.001)224 225        self._run_egg_info_command(tmpdir_cwd, env)226        timestamp_b = os.path.getmtime('foo.egg-info')227 228        assert timestamp_a != timestamp_b229 230    def test_manifest_template_is_read(self, tmpdir_cwd, env):231        self._create_project()232        path.build({233            'MANIFEST.in': DALS(234                """235                recursive-include docs *.rst236            """237            ),238            'docs': {239                'usage.rst': "Run 'hi'",240            },241        })242        self._run_egg_info_command(tmpdir_cwd, env)243        egg_info_dir = os.path.join('.', 'foo.egg-info')244        sources_txt = os.path.join(egg_info_dir, 'SOURCES.txt')245        with open(sources_txt, encoding="utf-8") as f:246            assert 'docs/usage.rst' in f.read().split('\n')247 248    def _setup_script_with_requires(self, requires, use_setup_cfg=False):249        setup_script = DALS(250            """251            from setuptools import setup252 253            setup(name='foo', zip_safe=False, %s)254            """255        ) % ('' if use_setup_cfg else requires)256        setup_config = requires if use_setup_cfg else ''257        path.build({258            'setup.py': setup_script,259            'setup.cfg': setup_config,260        })261 262    mismatch_marker = f"python_version<'{sys.version_info[0]}'"263    # Alternate equivalent syntax.264    mismatch_marker_alternate = f'python_version < "{sys.version_info[0]}"'265    invalid_marker = "<=>++"266 267    class RequiresTestHelper:268        @staticmethod269        def parametrize(*test_list, **format_dict):270            idlist = []271            argvalues = []272            for test in test_list:273                test_params = test.lstrip().split('\n\n', 3)274                name_kwargs = test_params.pop(0).split('\n')275                if len(name_kwargs) > 1:276                    val = name_kwargs[1].strip()277                    install_cmd_kwargs = ast.literal_eval(val)278                else:279                    install_cmd_kwargs = {}280                name = name_kwargs[0].strip()281                setup_py_requires, setup_cfg_requires, expected_requires = [282                    DALS(a).format(**format_dict) for a in test_params283                ]284                for id_, requires, use_cfg in (285                    (name, setup_py_requires, False),286                    (name + '_in_setup_cfg', setup_cfg_requires, True),287                ):288                    idlist.append(id_)289                    marks = ()290                    if requires.startswith('@xfail\n'):291                        requires = requires[7:]292                        marks = pytest.mark.xfail293                    argvalues.append(294                        pytest.param(295                            requires,296                            use_cfg,297                            expected_requires,298                            install_cmd_kwargs,299                            marks=marks,300                        )301                    )302            return pytest.mark.parametrize(303                (304                    "requires",305                    "use_setup_cfg",306                    "expected_requires",307                    "install_cmd_kwargs",308                ),309                argvalues,310                ids=idlist,311            )312 313    @RequiresTestHelper.parametrize(314        # Format of a test:315        #316        # id317        # install_cmd_kwargs [optional]318        #319        # requires block (when used in setup.py)320        #321        # requires block (when used in setup.cfg)322        #323        # expected contents of requires.txt324        """325        install_requires_deterministic326 327        install_requires=["wheel>=0.5", "pytest"]328 329        [options]330        install_requires =331            wheel>=0.5332            pytest333 334        wheel>=0.5335        pytest336        """,337        """338        install_requires_ordered339 340        install_requires=["pytest>=3.0.2,!=10.9999"]341 342        [options]343        install_requires =344            pytest>=3.0.2,!=10.9999345 346        pytest!=10.9999,>=3.0.2347        """,348        """349        install_requires_with_marker350 351        install_requires=["barbazquux;{mismatch_marker}"],352 353        [options]354        install_requires =355            barbazquux; {mismatch_marker}356 357        [:{mismatch_marker_alternate}]358        barbazquux359        """,360        """361        install_requires_with_extra362        {'cmd': ['egg_info']}363 364        install_requires=["barbazquux [test]"],365 366        [options]367        install_requires =368            barbazquux [test]369 370        barbazquux[test]371        """,372        """373        install_requires_with_extra_and_marker374 375        install_requires=["barbazquux [test]; {mismatch_marker}"],376 377        [options]378        install_requires =379            barbazquux [test]; {mismatch_marker}380 381        [:{mismatch_marker_alternate}]382        barbazquux[test]383        """,384        """385        setup_requires_with_markers386 387        setup_requires=["barbazquux;{mismatch_marker}"],388 389        [options]390        setup_requires =391            barbazquux; {mismatch_marker}392 393        """,394        """395        extras_require_with_extra396        {'cmd': ['egg_info']}397 398        extras_require={{"extra": ["barbazquux [test]"]}},399 400        [options.extras_require]401        extra = barbazquux [test]402 403        [extra]404        barbazquux[test]405        """,406        """407        extras_require_with_extra_and_marker_in_req408 409        extras_require={{"extra": ["barbazquux [test]; {mismatch_marker}"]}},410 411        [options.extras_require]412        extra =413            barbazquux [test]; {mismatch_marker}414 415        [extra]416 417        [extra:{mismatch_marker_alternate}]418        barbazquux[test]419        """,420        # FIXME: ConfigParser does not allow : in key names!421        """422        extras_require_with_marker423 424        extras_require={{":{mismatch_marker}": ["barbazquux"]}},425 426        @xfail427        [options.extras_require]428        :{mismatch_marker} = barbazquux429 430        [:{mismatch_marker}]431        barbazquux432        """,433        """434        extras_require_with_marker_in_req435 436        extras_require={{"extra": ["barbazquux; {mismatch_marker}"]}},437 438        [options.extras_require]439        extra =440            barbazquux; {mismatch_marker}441 442        [extra]443 444        [extra:{mismatch_marker_alternate}]445        barbazquux446        """,447        """448        extras_require_with_empty_section449 450        extras_require={{"empty": []}},451 452        [options.extras_require]453        empty =454 455        [empty]456        """,457        # Format arguments.458        invalid_marker=invalid_marker,459        mismatch_marker=mismatch_marker,460        mismatch_marker_alternate=mismatch_marker_alternate,461    )462    def test_requires(463        self,464        tmpdir_cwd,465        env,466        requires,467        use_setup_cfg,468        expected_requires,469        install_cmd_kwargs,470    ):471        self._setup_script_with_requires(requires, use_setup_cfg)472        self._run_egg_info_command(tmpdir_cwd, env, **install_cmd_kwargs)473        egg_info_dir = os.path.join('.', 'foo.egg-info')474        requires_txt = os.path.join(egg_info_dir, 'requires.txt')475        if os.path.exists(requires_txt):476            with open(requires_txt, encoding="utf-8") as fp:477                install_requires = fp.read()478        else:479            install_requires = ''480        assert install_requires.lstrip() == expected_requires481        assert glob.glob(os.path.join(env.paths['lib'], 'barbazquux*')) == []482 483    def test_install_requires_unordered_disallowed(self, tmpdir_cwd, env):484        """485        Packages that pass unordered install_requires sequences486        should be rejected as they produce non-deterministic487        builds. See #458.488        """489        req = 'install_requires={"fake-factory==0.5.2", "pytz"}'490        self._setup_script_with_requires(req)491        with pytest.raises(AssertionError):492            self._run_egg_info_command(tmpdir_cwd, env)493 494    def test_extras_require_with_invalid_marker(self, tmpdir_cwd, env):495        tmpl = 'extras_require={{":{marker}": ["barbazquux"]}},'496        req = tmpl.format(marker=self.invalid_marker)497        self._setup_script_with_requires(req)498        with pytest.raises(AssertionError):499            self._run_egg_info_command(tmpdir_cwd, env)500        assert glob.glob(os.path.join(env.paths['lib'], 'barbazquux*')) == []501 502    def test_extras_require_with_invalid_marker_in_req(self, tmpdir_cwd, env):503        tmpl = 'extras_require={{"extra": ["barbazquux; {marker}"]}},'504        req = tmpl.format(marker=self.invalid_marker)505        self._setup_script_with_requires(req)506        with pytest.raises(AssertionError):507            self._run_egg_info_command(tmpdir_cwd, env)508        assert glob.glob(os.path.join(env.paths['lib'], 'barbazquux*')) == []509 510    def test_provides_extra(self, tmpdir_cwd, env):511        self._setup_script_with_requires('extras_require={"foobar": ["barbazquux"]},')512        environ = os.environ.copy().update(513            HOME=env.paths['home'],514        )515        environment.run_setup_py(516            cmd=['egg_info'],517            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),518            data_stream=1,519            env=environ,520        )521        egg_info_dir = os.path.join('.', 'foo.egg-info')522        with open(os.path.join(egg_info_dir, 'PKG-INFO'), encoding="utf-8") as fp:523            pkg_info_lines = fp.read().split('\n')524        assert 'Provides-Extra: foobar' in pkg_info_lines525        assert 'Metadata-Version: 2.4' in pkg_info_lines526 527    def test_doesnt_provides_extra(self, tmpdir_cwd, env):528        self._setup_script_with_requires(529            """install_requires=["spam ; python_version<'3.6'"]"""530        )531        environ = os.environ.copy().update(532            HOME=env.paths['home'],533        )534        environment.run_setup_py(535            cmd=['egg_info'],536            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),537            data_stream=1,538            env=environ,539        )540        egg_info_dir = os.path.join('.', 'foo.egg-info')541        with open(os.path.join(egg_info_dir, 'PKG-INFO'), encoding="utf-8") as fp:542            pkg_info_text = fp.read()543        assert 'Provides-Extra:' not in pkg_info_text544 545    @pytest.mark.parametrize(546        ('files', 'license_in_sources'),547        [548            (549                {550                    'setup.cfg': DALS(551                        """552                              [metadata]553                              license_file = LICENSE554                              """555                    ),556                    'LICENSE': "Test license",557                },558                True,559            ),  # with license560            (561                {562                    'setup.cfg': DALS(563                        """564                              [metadata]565                              license_file = INVALID_LICENSE566                              """567                    ),568                    'LICENSE': "Test license",569                },570                False,571            ),  # with an invalid license572            (573                {574                    'setup.cfg': DALS(575                        """576                              """577                    ),578                    'LICENSE': "Test license",579                },580                True,581            ),  # no license_file attribute, LICENSE auto-included582            (583                {584                    'setup.cfg': DALS(585                        """586                              [metadata]587                              license_file = LICENSE588                              """589                    ),590                    'MANIFEST.in': "exclude LICENSE",591                    'LICENSE': "Test license",592                },593                True,594            ),  # manifest is overwritten by license_file595            pytest.param(596                {597                    'setup.cfg': DALS(598                        """599                              [metadata]600                              license_file = LICEN[CS]E*601                              """602                    ),603                    'LICENSE': "Test license",604                },605                True,606                id="glob_pattern",607            ),608        ],609    )610    def test_setup_cfg_license_file(self, tmpdir_cwd, env, files, license_in_sources):611        self._create_project()612        path.build(files)613 614        environment.run_setup_py(615            cmd=['egg_info'],616            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),617        )618        egg_info_dir = os.path.join('.', 'foo.egg-info')619 620        sources_text = Path(egg_info_dir, "SOURCES.txt").read_text(encoding="utf-8")621 622        if license_in_sources:623            assert 'LICENSE' in sources_text624        else:625            assert 'LICENSE' not in sources_text626            # for invalid license test627            assert 'INVALID_LICENSE' not in sources_text628 629    @pytest.mark.parametrize(630        ('files', 'incl_licenses', 'excl_licenses'),631        [632            (633                {634                    'setup.cfg': DALS(635                        """636                              [metadata]637                              license_files =638                                  LICENSE-ABC639                                  LICENSE-XYZ640                              """641                    ),642                    'LICENSE-ABC': "ABC license",643                    'LICENSE-XYZ': "XYZ license",644                },645                ['LICENSE-ABC', 'LICENSE-XYZ'],646                [],647            ),  # with licenses648            (649                {650                    'setup.cfg': DALS(651                        """652                              [metadata]653                              license_files = LICENSE-ABC, LICENSE-XYZ654                              """655                    ),656                    'LICENSE-ABC': "ABC license",657                    'LICENSE-XYZ': "XYZ license",658                },659                ['LICENSE-ABC', 'LICENSE-XYZ'],660                [],661            ),  # with commas662            (663                {664                    'setup.cfg': DALS(665                        """666                              [metadata]667                              license_files =668                                  LICENSE-ABC669                              """670                    ),671                    'LICENSE-ABC': "ABC license",672                    'LICENSE-XYZ': "XYZ license",673                },674                ['LICENSE-ABC'],675                ['LICENSE-XYZ'],676            ),  # with one license677            (678                {679                    'setup.cfg': DALS(680                        """681                              [metadata]682                              license_files =683                              """684                    ),685                    'LICENSE-ABC': "ABC license",686                    'LICENSE-XYZ': "XYZ license",687                },688                [],689                ['LICENSE-ABC', 'LICENSE-XYZ'],690            ),  # empty691            (692                {693                    'setup.cfg': DALS(694                        """695                              [metadata]696                              license_files = LICENSE-XYZ697                              """698                    ),699                    'LICENSE-ABC': "ABC license",700                    'LICENSE-XYZ': "XYZ license",701                },702                ['LICENSE-XYZ'],703                ['LICENSE-ABC'],704            ),  # on same line705            (706                {707                    'setup.cfg': DALS(708                        """709                              [metadata]710                              license_files =711                                  LICENSE-ABC712                                  INVALID_LICENSE713                              """714                    ),715                    'LICENSE-ABC': "Test license",716                },717                ['LICENSE-ABC'],718                ['INVALID_LICENSE'],719            ),  # with an invalid license720            (721                {722                    'setup.cfg': DALS(723                        """724                              """725                    ),726                    'LICENSE': "Test license",727                },728                ['LICENSE'],729                [],730            ),  # no license_files attribute, LICENSE auto-included731            (732                {733                    'setup.cfg': DALS(734                        """735                              [metadata]736                              license_files = LICENSE737                              """738                    ),739                    'MANIFEST.in': "exclude LICENSE",740                    'LICENSE': "Test license",741                },742                ['LICENSE'],743                [],744            ),  # manifest is overwritten by license_files745            (746                {747                    'setup.cfg': DALS(748                        """749                              [metadata]750                              license_files =751                                  LICENSE-ABC752                                  LICENSE-XYZ753                              """754                    ),755                    'MANIFEST.in': "exclude LICENSE-XYZ",756                    'LICENSE-ABC': "ABC license",757                    'LICENSE-XYZ': "XYZ license",758                    # manifest is overwritten by license_files759                },760                ['LICENSE-ABC', 'LICENSE-XYZ'],761                [],762            ),763            pytest.param(764                {765                    'setup.cfg': "",766                    'LICENSE-ABC': "ABC license",767                    'COPYING-ABC': "ABC copying",768                    'NOTICE-ABC': "ABC notice",769                    'AUTHORS-ABC': "ABC authors",770                    'LICENCE-XYZ': "XYZ license",771                    'LICENSE': "License",772                    'INVALID-LICENSE': "Invalid license",773                },774                [775                    'LICENSE-ABC',776                    'COPYING-ABC',777                    'NOTICE-ABC',778                    'AUTHORS-ABC',779                    'LICENCE-XYZ',780                    'LICENSE',781                ],782                ['INVALID-LICENSE'],783                # ('LICEN[CS]E*', 'COPYING*', 'NOTICE*', 'AUTHORS*')784                id="default_glob_patterns",785            ),786            pytest.param(787                {788                    'setup.cfg': DALS(789                        """790                              [metadata]791                              license_files =792                                  LICENSE*793                              """794                    ),795                    'LICENSE-ABC': "ABC license",796                    'NOTICE-XYZ': "XYZ notice",797                },798                ['LICENSE-ABC'],799                ['NOTICE-XYZ'],800                id="no_default_glob_patterns",801            ),802            pytest.param(803                {804                    'setup.cfg': DALS(805                        """806                              [metadata]807                              license_files =808                                  LICENSE-ABC809                                  LICENSE*810                              """811                    ),812                    'LICENSE-ABC': "ABC license",813                },814                ['LICENSE-ABC'],815                [],816                id="files_only_added_once",817            ),818            pytest.param(819                {820                    'setup.cfg': DALS(821                        """822                              [metadata]823                              license_files = **/LICENSE824                              """825                    ),826                    'LICENSE': "ABC license",827                    'LICENSE-OTHER': "Don't include",828                    'vendor': {'LICENSE': "Vendor license"},829                },830                ['LICENSE', 'vendor/LICENSE'],831                ['LICENSE-OTHER'],832                id="recursive_glob",833            ),834        ],835    )836    def test_setup_cfg_license_files(837        self, tmpdir_cwd, env, files, incl_licenses, excl_licenses838    ):839        self._create_project()840        path.build(files)841 842        environment.run_setup_py(843            cmd=['egg_info'],844            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),845        )846        egg_info_dir = os.path.join('.', 'foo.egg-info')847 848        sources_text = Path(egg_info_dir, "SOURCES.txt").read_text(encoding="utf-8")849        sources_lines = [line.strip() for line in sources_text.splitlines()]850 851        for lf in incl_licenses:852            assert sources_lines.count(lf) == 1853 854        for lf in excl_licenses:855            assert sources_lines.count(lf) == 0856 857    @pytest.mark.parametrize(858        ('files', 'incl_licenses', 'excl_licenses'),859        [860            (861                {862                    'setup.cfg': DALS(863                        """864                              [metadata]865                              license_file =866                              license_files =867                              """868                    ),869                    'LICENSE-ABC': "ABC license",870                    'LICENSE-XYZ': "XYZ license",871                },872                [],873                ['LICENSE-ABC', 'LICENSE-XYZ'],874            ),  # both empty875            (876                {877                    'setup.cfg': DALS(878                        """879                              [metadata]880                              license_file =881                                  LICENSE-ABC882                                  LICENSE-XYZ883                              """884                    ),885                    'LICENSE-ABC': "ABC license",886                    'LICENSE-XYZ': "XYZ license",887                    # license_file is still singular888                },889                [],890                ['LICENSE-ABC', 'LICENSE-XYZ'],891            ),892            (893                {894                    'setup.cfg': DALS(895                        """896                              [metadata]897                              license_file = LICENSE-ABC898                              license_files =899                                  LICENSE-XYZ900                                  LICENSE-PQR901                              """902                    ),903                    'LICENSE-ABC': "ABC license",904                    'LICENSE-PQR': "PQR license",905                    'LICENSE-XYZ': "XYZ license",906                },907                ['LICENSE-ABC', 'LICENSE-PQR', 'LICENSE-XYZ'],908                [],909            ),  # combined910            (911                {912                    'setup.cfg': DALS(913                        """914                              [metadata]915                              license_file = LICENSE-ABC916                              license_files =917                                  LICENSE-ABC918                                  LICENSE-XYZ919                                  LICENSE-PQR920                              """921                    ),922                    'LICENSE-ABC': "ABC license",923                    'LICENSE-PQR': "PQR license",924                    'LICENSE-XYZ': "XYZ license",925                    # duplicate license926                },927                ['LICENSE-ABC', 'LICENSE-PQR', 'LICENSE-XYZ'],928                [],929            ),930            (931                {932                    'setup.cfg': DALS(933                        """934                              [metadata]935                              license_file = LICENSE-ABC936                              license_files =937                                  LICENSE-XYZ938                              """939                    ),940                    'LICENSE-ABC': "ABC license",941                    'LICENSE-PQR': "PQR license",942                    'LICENSE-XYZ': "XYZ license",943                    # combined subset944                },945                ['LICENSE-ABC', 'LICENSE-XYZ'],946                ['LICENSE-PQR'],947            ),948            (949                {950                    'setup.cfg': DALS(951                        """952                              [metadata]953                              license_file = LICENSE-ABC954                              license_files =955                                  LICENSE-XYZ956                                  LICENSE-PQR957                              """958                    ),959                    'LICENSE-PQR': "Test license",960                    # with invalid licenses961                },962                ['LICENSE-PQR'],963                ['LICENSE-ABC', 'LICENSE-XYZ'],964            ),965            (966                {967                    'setup.cfg': DALS(968                        """969                              [metadata]970                              license_file = LICENSE-ABC971                              license_files =972                                LICENSE-PQR973                                LICENSE-XYZ974                              """975                    ),976                    'MANIFEST.in': "exclude LICENSE-ABC\nexclude LICENSE-PQR",977                    'LICENSE-ABC': "ABC license",978                    'LICENSE-PQR': "PQR license",979                    'LICENSE-XYZ': "XYZ license",980                    # manifest is overwritten981                },982                ['LICENSE-ABC', 'LICENSE-PQR', 'LICENSE-XYZ'],983                [],984            ),985            pytest.param(986                {987                    'setup.cfg': DALS(988                        """989                              [metadata]990                              license_file = LICENSE*991                              """992                    ),993                    'LICENSE-ABC': "ABC license",994                    'NOTICE-XYZ': "XYZ notice",995                },996                ['LICENSE-ABC'],997                ['NOTICE-XYZ'],998                id="no_default_glob_patterns",999            ),1000            pytest.param(1001                {1002                    'setup.cfg': DALS(1003                        """1004                              [metadata]1005                              license_file = LICENSE*1006                              license_files =1007                                NOTICE*1008                              """1009                    ),1010                    'LICENSE-ABC': "ABC license",1011                    'NOTICE-ABC': "ABC notice",1012                    'AUTHORS-ABC': "ABC authors",1013                },1014                ['LICENSE-ABC', 'NOTICE-ABC'],1015                ['AUTHORS-ABC'],1016                id="combined_glob_patterrns",1017            ),1018        ],1019    )1020    def test_setup_cfg_license_file_license_files(1021        self, tmpdir_cwd, env, files, incl_licenses, excl_licenses1022    ):1023        self._create_project()1024        path.build(files)1025 1026        environment.run_setup_py(1027            cmd=['egg_info'],1028            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),1029        )1030        egg_info_dir = os.path.join('.', 'foo.egg-info')1031 1032        sources_text = Path(egg_info_dir, "SOURCES.txt").read_text(encoding="utf-8")1033        sources_lines = [line.strip() for line in sources_text.splitlines()]1034 1035        for lf in incl_licenses:1036            assert sources_lines.count(lf) == 11037 1038        for lf in excl_licenses:1039            assert sources_lines.count(lf) == 01040 1041    def test_license_file_attr_pkg_info(self, tmpdir_cwd, env):1042        """All matched license files should have a corresponding License-File."""1043        self._create_project()1044        path.build({1045            "setup.cfg": DALS(1046                """1047                              [metadata]1048                              license_files =1049                                  NOTICE*1050                                  LICENSE*1051                                  **/LICENSE1052                              """1053            ),1054            "LICENSE-ABC": "ABC license",1055            "LICENSE-XYZ": "XYZ license",1056            "NOTICE": "included",1057            "IGNORE": "not include",1058            "vendor": {'LICENSE': "Vendor license"},1059        })1060 1061        environment.run_setup_py(1062            cmd=['egg_info'],1063            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),1064        )1065        egg_info_dir = os.path.join('.', 'foo.egg-info')1066        with open(os.path.join(egg_info_dir, 'PKG-INFO'), encoding="utf-8") as fp:1067            pkg_info_lines = fp.read().split('\n')1068        license_file_lines = [1069            line for line in pkg_info_lines if line.startswith('License-File:')1070        ]1071 1072        # Only 'NOTICE', LICENSE-ABC', and 'LICENSE-XYZ' should have been matched1073        # Also assert that order from license_files is keeped1074        assert len(license_file_lines) == 41075        assert "License-File: NOTICE" == license_file_lines[0]1076        assert "License-File: LICENSE-ABC" in license_file_lines[1:]1077        assert "License-File: LICENSE-XYZ" in license_file_lines[1:]1078        assert "License-File: vendor/LICENSE" in license_file_lines[3]1079 1080    def test_metadata_version(self, tmpdir_cwd, env):1081        """Make sure latest metadata version is used by default."""1082        self._setup_script_with_requires("")1083        environment.run_setup_py(1084            cmd=['egg_info'],1085            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),1086            data_stream=1,1087        )1088        egg_info_dir = os.path.join('.', 'foo.egg-info')1089        with open(os.path.join(egg_info_dir, 'PKG-INFO'), encoding="utf-8") as fp:1090            pkg_info_lines = fp.read().split('\n')1091        # Update metadata version if changed1092        assert self._extract_mv_version(pkg_info_lines) == (2, 4)1093 1094    def test_long_description_content_type(self, tmpdir_cwd, env):1095        # Test that specifying a `long_description_content_type` keyword arg to1096        # the `setup` function results in writing a `Description-Content-Type`1097        # line to the `PKG-INFO` file in the `<distribution>.egg-info`1098        # directory.1099        # `Description-Content-Type` is described at1100        # https://github.com/pypa/python-packaging-user-guide/pull/2581101 1102        self._setup_script_with_requires(1103            """long_description_content_type='text/markdown',"""1104        )1105        environ = os.environ.copy().update(1106            HOME=env.paths['home'],1107        )1108        environment.run_setup_py(1109            cmd=['egg_info'],1110            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),1111            data_stream=1,1112            env=environ,1113        )1114        egg_info_dir = os.path.join('.', 'foo.egg-info')1115        with open(os.path.join(egg_info_dir, 'PKG-INFO'), encoding="utf-8") as fp:1116            pkg_info_lines = fp.read().split('\n')1117        expected_line = 'Description-Content-Type: text/markdown'1118        assert expected_line in pkg_info_lines1119        assert 'Metadata-Version: 2.4' in pkg_info_lines1120 1121    def test_long_description(self, tmpdir_cwd, env):1122        # Test that specifying `long_description` and `long_description_content_type`1123        # keyword args to the `setup` function results in writing1124        # the description in the message payload of the `PKG-INFO` file1125        # in the `<distribution>.egg-info` directory.1126        self._setup_script_with_requires(1127            "long_description='This is a long description\\nover multiple lines',"1128            "long_description_content_type='text/markdown',"1129        )1130        environment.run_setup_py(1131            cmd=['egg_info'],1132            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),1133            data_stream=1,1134        )1135        egg_info_dir = os.path.join('.', 'foo.egg-info')1136        with open(os.path.join(egg_info_dir, 'PKG-INFO'), encoding="utf-8") as fp:1137            pkg_info_lines = fp.read().split('\n')1138        assert 'Metadata-Version: 2.4' in pkg_info_lines1139        assert '' == pkg_info_lines[-1]  # last line should be empty1140        long_desc_lines = pkg_info_lines[pkg_info_lines.index('') :]1141        assert 'This is a long description' in long_desc_lines1142        assert 'over multiple lines' in long_desc_lines1143 1144    def test_project_urls(self, tmpdir_cwd, env):1145        # Test that specifying a `project_urls` dict to the `setup`1146        # function results in writing multiple `Project-URL` lines to1147        # the `PKG-INFO` file in the `<distribution>.egg-info`1148        # directory.1149        # `Project-URL` is described at https://packaging.python.org1150        #     /specifications/core-metadata/#project-url-multiple-use1151 1152        self._setup_script_with_requires(1153            """project_urls={1154                'Link One': 'https://example.com/one/',1155                'Link Two': 'https://example.com/two/',1156                },"""1157        )1158        environ = os.environ.copy().update(1159            HOME=env.paths['home'],1160        )1161        environment.run_setup_py(1162            cmd=['egg_info'],1163            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),1164            data_stream=1,1165            env=environ,1166        )1167        egg_info_dir = os.path.join('.', 'foo.egg-info')1168        with open(os.path.join(egg_info_dir, 'PKG-INFO'), encoding="utf-8") as fp:1169            pkg_info_lines = fp.read().split('\n')1170        expected_line = 'Project-URL: Link One, https://example.com/one/'1171        assert expected_line in pkg_info_lines1172        expected_line = 'Project-URL: Link Two, https://example.com/two/'1173        assert expected_line in pkg_info_lines1174        assert self._extract_mv_version(pkg_info_lines) >= (1, 2)1175 1176    def test_license(self, tmpdir_cwd, env):1177        """Test single line license."""1178        self._setup_script_with_requires("license='MIT',")1179        environment.run_setup_py(1180            cmd=['egg_info'],1181            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),1182            data_stream=1,1183        )1184        egg_info_dir = os.path.join('.', 'foo.egg-info')1185        with open(os.path.join(egg_info_dir, 'PKG-INFO'), encoding="utf-8") as fp:1186            pkg_info_lines = fp.read().split('\n')1187        assert 'License: MIT' in pkg_info_lines1188 1189    def test_license_escape(self, tmpdir_cwd, env):1190        """Test license is escaped correctly if longer than one line."""1191        self._setup_script_with_requires(1192            "license='This is a long license text \\nover multiple lines',"1193        )1194        environment.run_setup_py(1195            cmd=['egg_info'],1196            pypath=os.pathsep.join([env.paths['lib'], str(tmpdir_cwd)]),1197            data_stream=1,1198        )1199        egg_info_dir = os.path.join('.', 'foo.egg-info')1200        with open(os.path.join(egg_info_dir, 'PKG-INFO'), encoding="utf-8") as fp:

Showing the first 1,200 of 1307 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai