Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Restore support for newlines in Summary #2893

Closed
1 task done
kiorky opened this issue Nov 17, 2021 · 35 comments
Closed
1 task done

Restore support for newlines in Summary #2893

kiorky opened this issue Nov 17, 2021 · 35 comments

Comments

@kiorky
Copy link

kiorky commented Nov 17, 2021

setuptools version

>= 59

Python version

3.8

OS

linux

Additional environment information

No response

Description

builds failing with

 File "/code/venv/lib/python3.8/site-packages/setuptools/dist.py", line 151, in single_line
   raise ValueError('Newlines are not allowed')

Expected behavior

Warning or nothing, just escape silently \n for oneline metadata fields

Lot of already released eggs wont ever comply to this policy, but we need to install them at the version they are pinned in our builds for the sake of reproducibility.

How to Reproduce

pip install django-hijack==2.1.10

Output

  ERROR: Command errored out with exit status 1:
   command: venv/bugpip/bin/python -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-10qe4uxx/django-hijack_c7b8d72ff0ad41998610fe76e5822048/setup.py'"'"'; __file__='"'"'/tmp/pip-install-10qe4uxx/django-hijack_c7b8d72ff0ad41998610fe76e5822048/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-pip-egg-info-awfzhldp
       cwd: /tmp/pip-install-10qe4uxx/django-hijack_c7b8d72ff0ad41998610fe76e5822048/
  Complete output (26 lines):
  running egg_info
  creating /tmp/pip-pip-egg-info-awfzhldp/django_hijack.egg-info
  writing /tmp/pip-pip-egg-info-awfzhldp/django_hijack.egg-info/PKG-INFO
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/tmp/pip-install-10qe4uxx/django-hijack_c7b8d72ff0ad41998610fe76e5822048/setup.py", line 44, in <module>
      setup(name="django-hijack",
    File "venv/bugpip/lib/python3.8/site-packages/setuptools/__init__.py", line 153, in setup
      return distutils.core.setup(**attrs)
    File "/usr/lib/python3.8/distutils/core.py", line 148, in setup
      dist.run_commands()
    File "/usr/lib/python3.8/distutils/dist.py", line 966, in run_commands
      self.run_command(cmd)
    File "/usr/lib/python3.8/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "venv/bugpip/lib/python3.8/site-packages/setuptools/command/egg_info.py", line 292, in run
      writer(self, ep.name, os.path.join(self.egg_info, ep.name))
    File "venv/bugpip/lib/python3.8/site-packages/setuptools/command/egg_info.py", line 656, in write_pkg_info
      metadata.write_pkg_info(cmd.egg_info)
    File "/usr/lib/python3.8/distutils/dist.py", line 1117, in write_pkg_info
      self.write_pkg_file(pkg_info)
    File "venv/bugpip/lib/python3.8/site-packages/setuptools/dist.py", line 167, in write_pkg_file
      write_field('Summary', single_line(self.get_description()))
    File "venv/bugpip/lib/python3.8/site-packages/setuptools/dist.py", line 151, in single_line
      raise ValueError('Newlines are not allowed')
  ValueError: Newlines are not allowed

Code of Conduct

  • I agree to follow the PSF Code of Conduct
@kiorky kiorky added bug Needs Triage Issues that need to be evaluated for severity and status. labels Nov 17, 2021
@kiorky
Copy link
Author

kiorky commented Nov 17, 2021

cf #1390 (comment)

@kiorky kiorky changed the title [BUG] setuptools should be less harmful on NewLines for description [BUG] setuptools should be less harmful on NewLines for description and other oneline metadata fields Nov 17, 2021
@mriedem
Copy link

mriedem commented Nov 17, 2021

Came here to report the same. Last week setuptools-58.5.3 was OK but now with setuptools-59.1.1 we're failing to install this package because of the newline in the description:

https:/qiskit-community/qiskit-textbook/blob/stable/qiskit-textbook-src/setup.py#L8

Was this a regression from #1390?

@mriedem
Copy link

mriedem commented Nov 17, 2021

Was this a regression from #1390?

Oh I guess this is intentional in v59.0.0:

https:/pypa/setuptools/blob/main/CHANGES.rst#v5900

Per #2870.

@jaraco jaraco changed the title [BUG] setuptools should be less harmful on NewLines for description and other oneline metadata fields Restore support for newlines in Summary Nov 18, 2021
@jaraco jaraco removed bug Needs Triage Issues that need to be evaluated for severity and status. labels Nov 18, 2021
@jaraco
Copy link
Member

jaraco commented Nov 18, 2021

As mentioned in #1390, this change was introduced intentionally in order to prevent these invalid inputs.

It sounds like this issue only affects older packages installed with the latest Setuptools. These environments are pinning their requirements but not pinning Setuptools. As a result, the maintainers of these environments are asking Setuptools to carry the burden of the legacy introduced by pinning their requirements.

I'd prefer for these projects to advance their dependencies to versions that no longer have the defective usage. But maybe there are other workarounds as well.

Why can't these environments work around the issue by pinning Setuptools as well? Or find another workaround such as installing from wheels (built from older Setuptools)?

For example, I was able to build the affected package thus:

draft $ pip-run -q 'setuptools<59' wheel -- -m pip wheel --no-deps django-hijack==2.1
Collecting django-hijack==2.1
  Using cached django-hijack-2.1.0.tar.gz (16 kB)
  Preparing metadata (setup.py) ... done
Building wheels for collected packages: django-hijack
  Building wheel for django-hijack (setup.py) ... done
  Created wheel for django-hijack: filename=django_hijack-2.1.0-py3-none-any.whl size=24148 sha256=51049e0c5eadb29e31a8c393db68891b61376eeef8311920048a7d3fd97bb838
  Stored in directory: /Users/jaraco/Library/Caches/pip/wheels/8b/57/f0/2cecaf262d2f06211ab69602ac2cd5d64cb093068cb7ee1c65
Successfully built django-hijack
draft $ ls
django_hijack-2.1.0-py3-none-any.whl

I've tried to think of ways Setuptools could support these legacy cases but reject new cases, but I haven't been able to come up with a good approach. I'd really like to avoid leaving Setuptools indefinitely dependent on the legacy of older packages.

@kiorky
Copy link
Author

kiorky commented Nov 18, 2021

It sounds like this issue only affects older packages installed with the latest Setuptools. These environments are pinning their requirements but not pinning Setuptools. As a result, the maintainers of these environments are asking Setuptools to carry the burden of the legacy introduced by pinning their requirements.

Because every project has it's own pace to release and needs stability and depinning/upgrading those requirements imply extra maintenance and tests time and in case of paid work: costs which are not justified here.
Version pinning is essential to ensure your build is reproducible.
Breaking a build just because a metadata in a dependence, which may not be direct misses a \n which was not even mandatory at the time of the release of that dependence is a total non-sense.

I agree that quality should be enforced on new uploaded releases but installation of older packages should and must be still possible wiithout any change.

Seriously, guys, stripping eternally \n is not a big deal, and if we want to ensure packages now strictly validate, we just should ensure offending dists could not be uploaded.

Another (bad solution i think as it will break integrity of uploaded dists and break custom hash verifications) and also do not work with alternative mirrors where artefacts wont be patched is to patch already uploaded artefacts to make them comply with new code.

@kiorky
Copy link
Author

kiorky commented Nov 18, 2021

Not to also mention that newer releases of dependences are maybe not compatible with every stack and every stack may not be that easily upgradable, just for an \n.

Seriously, reconsider that non sense breaking change...

@jaraco
Copy link
Member

jaraco commented Nov 18, 2021

I've created a plugin, setuptools_hacks.bypass_summary_newline that provides a workaround for the issue. Users encountering this issue can install this plugin alongside setuptools 59+ to bypass the error by stripping everything from the first newline. Demo:

~ $ pip-run -q setuptools wheel setuptools_hacks.bypass_summary_newline -- -m pip-run --no-deps --no-binary :all: django-hijack==2.1.10 -- -c pass
Collecting django-hijack==2.1.10
  Using cached django-hijack-2.1.10.tar.gz (20 kB)
  Preparing metadata (setup.py) ... done
Skipping wheel build for django-hijack, due to binaries being disabled for it.
Installing collected packages: django-hijack
    Running setup.py install for django-hijack ... done
Successfully installed django-hijack-2.1.10

This approach allows these select environments dependent on the broken packages to work around the breakage while also retaining the check for new packages. It also clearly pushes the legacy maintenance to the environment maintainers instead of Setuptools itself.

@jaraco jaraco closed this as completed Nov 18, 2021
@kiorky
Copy link
Author

kiorky commented Nov 18, 2021

Sorry but no, its not AT ALL an acceptable solution, please reopen.

I don't want to figure out to push a new plugin in every build pipeline i have.

What we need is build stability and reproducibility.

Futherthemore, no one want to put a "legacy maintenance" on setuptools folks, we just want to have already and running fine build systems not to break for a \n detail.

@jaraco
Copy link
Member

jaraco commented Nov 18, 2021

I appreciate your enthusiasm and concern. I too have managed private pipelines that would be affected by upstream changes in Setuptools, and it was indeed a hassle when an incompatible change to Setuptools, intentional or unintentional, would break the builds. Some of our projects avoided this issue by pinning Setuptools and only bumping it periodically. And while I would discourage that approach, it does provide for more stability in exchange for toil to occasionally update.

If reproducible builds is something you seek, then it's probably recommended not to leave Setuptools unpinned. Each release of Setuptools could potentially tweak the build, potentially changing the discovery of files or metadata format or a host of other behaviors.

Although the goal is to maintain compatibility, sometimes backward-incompatible changes are necessary. Setuptools has recently made much more impactful backward-incompatible changes, such as dropping support for Python 2 and 2to3. These changes are necessary to move Setuptools incrementally toward a more usable, maintainable, and correct solution, built on PyPA standards. This change also falls into that category.

Setuptools serves millions of downloads per day, and best I can tell, the fallout of this change has affected only a couple of environments. In my opinion, it doesn't make sense for Setuptools to adopt the indefinite burden of adapting incorrect inputs for a few cases. If this issue was widespread, I'd definitely like to consider it.

But when the issue is with a few select environments, I would implore the maintainers of those environments to find a way to adapt. Setuptools has provided several workarounds:

  • build wheels of affected libraries explicitly
  • pin to old versions of setuptools
  • install the compatibility plugin
  • upgrade affected libraries
  • affected packages may be able to upload wheels
  • affected packages may release a new bugfix release with only a fix for the metadata

If it can be shown that these workarounds are inadequate or impose a grievous burden or affect a significant portion of the users, we can reconsider this issue.

@kiorky
Copy link
Author

kiorky commented Nov 18, 2021

As you see, many users are beginning to fall upon the change, @jaraco, you should reconsider reopening this bug.

Here pinning setuptools down the road wont help in longterm maintenance, as sooner or later, the pin will have to be upgraded and no solution wont be here except adding a plugin in a stack, just for a newline that could be escaped... It's just crazy.

Already uploaded dists should just be as easily installable as the first day they were uploaded, point, you just broken many -AT-THE-UPLOAD-TIME valid artefacts.

What's wrong with you folks ?

We can totally understand that things should now be enforced, but already --valid-artefacts-- should still be installable, specially when it comes only to a newline metadata enforcement... So let this only fail for newly uploaded artefacts and at most warn for other already uploaded artefacts.

@jaraco
Copy link
Member

jaraco commented Nov 19, 2021

As you see, many users are beginning to fall upon the change, @jaraco, you should reconsider reopening this bug.

You can also see from this change, the package owners were unaware of the defects they introduced by copying their long description into the description including any newlines. Without having introduced the breaking change, they may have gone on happily ignoring the warnings indefinitely, continuing to publish packages with broken metadata.

It occurred to me there's a possible fifth workaround:

  • Since this issue only affects source distributions, the affected packages could upload wheels for their packages and that would bypass the error for most installs.

What's wrong with you folks ?

Please limit your comments to the facts of the matter and your opinions, but avoid personal attacks. These won't be tolerated. Please read the PSF code of conduct and consider yourself warned.

To be sure, us folks is basically me. Other maintainers have not yet weighed in.

So let this only fail for newly uploaded artefacts and at most warn for other already uploaded artefacts.

I'm unaware of a way to do this. The validation that's happening is happening at the time that the metadata is written. That's the problem with these source artifacts - they're effectively indistinguishable from a package that was built from repo source.

I suppose it's conceivable that Setuptools could somehow detect the presence of a PKG-INFO from a previous build and if it detects invalid metadata, bypass the failure. I guess another way could be to enumerate all of the package/version combinations that are affected (essentially an allow-list for already-published artifacts).

related bugs

Thanks for collecting these (and linking them to increase visibility). I've read through these issues. It looks like a lot of them are issues that were only surfaced as a result of raising an error and probably would have continued to be broken except for this release. In that sense, the change is working as intended (creating the impetus to fix the broken usage).

It would be a real shame to introduce all this disruption only to once again allow the broken behavior to pass.

Thusfar, the only proposal to address the issue has been to back out the change and retain the warning behavior forever. In my opinion, that's unacceptable. I'd like to see a proposal that ends in Setuptools being able to enforce the standard.

@kiorky
Copy link
Author

kiorky commented Nov 19, 2021

Please limit your comments to the facts of the matter and your opinions, but avoid personal attacks. These won't be tolerated. Please read the PSF code of conduct and consider yourself warned.

I stop you, nothing personal here. I do not understand the matter of risking to break stability for a bad prio \n stripping.
I also agree with you that bad metadata is a real problem.
Problem is that it was "tolerated" and we should act of this fact.
Related bugs are only a few surfacing. How many like for django-hijack which isn't on the reported list are not yet surfacing ?
Maybe scanning pypi, (i did not not to spam as it implies checking every version of every package), may give us some numbers ?

Indeed, i we saw, already released versions are still totally broken for installation right now.
So that's not true that the existence of a newer release that's easyinstallable addresses the issue i'm reporting.
Neither the existence of a setuptools plugin that would let me bypass the issue by obtaining the previous setuptools behavior.

I don't want to upgrade a (NON DIRECT) dependency of stable builds, i want to be able to install the release that was pinned, and battle tested. Specially for builds that we know are all plain of bad habits but we can't upgrade them to latest release because they are incompatibles.
If there was a CVE or any other real bug of the artifact why not, but that not the case and that's a pity to be blocked just because of a spurious \n in a description field. Specially when newer versions of the incriminated package may not be compatible with vendor stacks puting your build at risk by the way incurring non justified extra maintenance costs.

I reassure you, we all know and we all pin everything, i hope, in stable stacks including setuptools itself, i hope. But it's only closing eyes and that problem will it us badly sooner or later. That's why we mostly all have also dev pipelines with some laxism in certain dependencies toinstallable anticipate such changes.

So let this only fail for newly uploaded artefacts and at most warn for other already uploaded artefacts.
Problem is mainly for distributed packages, so a warning for users on localhost who don't want to patch their defective eggs and impossibility to upload is a good compromise.

I knew better 10 years ago than now setuptools code, and specially twine, but the command could fail at upload time. And server side speaking, we can also add an extra check as a belt and braces approach.

On the other hand, if nothing is done to revert that change, for already uploaded artifacts that would be scanned as broken, patching them by stripping out the \n that make them not installable may be a solution. In all cases, they won't be installable. Most of us rely on automatic hash verifications, breakages should be minor that right now with such a repair. In my case, that would, i hope, address the issue. And nothing would have then to be done to revert the new metadata enforcement.Technically speaking, i see this as way more tedious than stripping out \n.

@nascheme
Copy link
Contributor

You can also see from this change, the package owners were unaware of the defects they introduced by copying their long description into the description including any newlines. Without having introduced the breaking change, they may have gone on happily ignoring the warnings indefinitely, continuing to publish packages with broken metadata.

Where were these warnings supposed to show up? I didn't see them and this afternoon when trying to build new container images, the build process failed, because of newlines in description for a (non-public) package the build depends on. Adding a plug-in or pinning setuptools doesn't seem like a great solution. I try to be diligent about fixing warnings that "pip" gives me so this breakage was unexpected. It turned what should be a 5 minute automated build into a long debugging process.

I have Python package dependencies pinned using "pip-compile" but I don't have "pip" and "setuptools" pinned since they get installed by "ensurepip" as part of the CPython build. I guess I need to go into that build automation and pin the pip and setuptools versions somehow. It seems there is a significant risk of new versions of setuptools breaking my builds.

I think pinning versions is a good idea in terms of security (e.g. avoiding malware injected into the supply chain). I think it's not so great when we have to do it for compatibility reasons. I recently had to spend quite a bit of time to try to get scipy to build for Python 3.10. They were pinning the build on Python <= 3.9. I hope this idea of pinning for compatibility doesn't spread more. Abseil's idea to "Live at Head"[1] is better.

  1. https://www.youtube.com/watch?v=tISy7EJQPzI&t=1032s

@jaraco
Copy link
Member

jaraco commented Nov 20, 2021

Where were these warnings supposed to show up?

They show up in the pip log if you run with -v.

~ $ pip-run -q 'setuptools<59' wheel -- -m pip-run -v --no-binary :all: --no-deps django-hijack==2.1.10 -- -c pass
Using pip 21.3.1 from /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pip (python 3.10)
Collecting django-hijack==2.1.10
  Using cached django-hijack-2.1.10.tar.gz (20 kB)
  Running command python setup.py egg_info
  running egg_info
  creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-ioph6cek/django_hijack.egg-info
  writing /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-ioph6cek/django_hijack.egg-info/PKG-INFO
  /var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-lwuyk2bs/setuptools/dist.py:151: UserWarning: newlines not allowed and will break in the future
    warnings.warn("newlines not allowed and will break in the future")
  writing dependency_links to /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-ioph6cek/django_hijack.egg-info/dependency_links.txt
  writing requirements to /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-ioph6cek/django_hijack.egg-info/requires.txt
  writing top-level names to /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-ioph6cek/django_hijack.egg-info/top_level.txt
  writing manifest file '/private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-ioph6cek/django_hijack.egg-info/SOURCES.txt'
  reading manifest file '/private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-ioph6cek/django_hijack.egg-info/SOURCES.txt'
  reading manifest template 'MANIFEST.in'
  warning: no previously-included files matching '*.orig' found anywhere in distribution
  warning: no previously-included files matching '*.log' found anywhere in distribution
  warning: no previously-included files matching '*.swp' found anywhere in distribution
  no previously-included directories found matching 'hijack/tests/coverage'
  no previously-included directories found matching 'hijack/.ropeproject'
  adding license file 'LICENSE'
  adding license file 'AUTHORS'
  writing manifest file '/private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-ioph6cek/django_hijack.egg-info/SOURCES.txt'
  Preparing metadata (setup.py) ... done
Skipping wheel build for django-hijack, due to binaries being disabled for it.
Installing collected packages: django-hijack
    Running command /Library/Frameworks/Python.framework/Versions/3.10/bin/python3.10 -u -c 'import io, os, sys, setuptools, tokenize; sys.argv[0] = '"'"'/private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-install-7laxh3jc/django-hijack_131101cee3434fdc98893d6c92521c5e/setup.py'"'"'; __file__='"'"'/private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-install-7laxh3jc/django-hijack_131101cee3434fdc98893d6c92521c5e/setup.py'"'"';f = getattr(tokenize, '"'"'open'"'"', open)(__file__) if os.path.exists(__file__) else io.StringIO('"'"'from setuptools import setup; setup()'"'"');code = f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-record-49juixv3/install-record.txt --single-version-externally-managed --home /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo --compile --install-headers /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/include/python/django-hijack
    running install
    /var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-lwuyk2bs/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
      warnings.warn(
    running build
    running build_py
    creating build
    creating build/lib
    creating build/lib/hijack
    copying hijack/signals.py -> build/lib/hijack
    copying hijack/models.py -> build/lib/hijack
    copying hijack/checks.py -> build/lib/hijack
    copying hijack/__init__.py -> build/lib/hijack
    copying hijack/apps.py -> build/lib/hijack
    copying hijack/admin.py -> build/lib/hijack
    copying hijack/settings.py -> build/lib/hijack
    copying hijack/urls.py -> build/lib/hijack
    copying hijack/helpers.py -> build/lib/hijack
    copying hijack/middleware.py -> build/lib/hijack
    copying hijack/views.py -> build/lib/hijack
    copying hijack/decorators.py -> build/lib/hijack
    creating build/lib/hijack/templatetags
    copying hijack/templatetags/__init__.py -> build/lib/hijack/templatetags
    copying hijack/templatetags/hijack_tags.py -> build/lib/hijack/templatetags
    creating build/lib/hijack/tests
    copying hijack/tests/__init__.py -> build/lib/hijack/tests
    copying hijack/tests/test_hijack.py -> build/lib/hijack/tests
    copying hijack/tests/utils.py -> build/lib/hijack/tests
    copying hijack/tests/south_settings.py -> build/lib/hijack/tests
    copying hijack/tests/test_hijack_url_settings.py -> build/lib/hijack/tests
    copying hijack/tests/manage_settings.py -> build/lib/hijack/tests
    copying hijack/tests/test_checks.py -> build/lib/hijack/tests
    copying hijack/tests/urls.py -> build/lib/hijack/tests
    copying hijack/tests/test_settings.py -> build/lib/hijack/tests
    creating build/lib/hijack/tests/test_app
    copying hijack/tests/test_app/authorization_checks.py -> build/lib/hijack/tests/test_app
    copying hijack/tests/test_app/models.py -> build/lib/hijack/tests/test_app
    copying hijack/tests/test_app/__init__.py -> build/lib/hijack/tests/test_app
    copying hijack/tests/test_app/urls.py -> build/lib/hijack/tests/test_app
    copying hijack/tests/test_app/views.py -> build/lib/hijack/tests/test_app
    copying hijack/tests/test_app/decorators.py -> build/lib/hijack/tests/test_app
    running egg_info
    writing django_hijack.egg-info/PKG-INFO
    /var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-lwuyk2bs/setuptools/dist.py:151: UserWarning: newlines not allowed and will break in the future
      warnings.warn("newlines not allowed and will break in the future")
    writing dependency_links to django_hijack.egg-info/dependency_links.txt
    writing requirements to django_hijack.egg-info/requires.txt
    writing top-level names to django_hijack.egg-info/top_level.txt
    reading manifest file 'django_hijack.egg-info/SOURCES.txt'
    reading manifest template 'MANIFEST.in'
    warning: no previously-included files matching '*.orig' found anywhere in distribution
    warning: no previously-included files matching '*.log' found anywhere in distribution
    warning: no previously-included files matching '*.swp' found anywhere in distribution
    no previously-included directories found matching 'hijack/tests/coverage'
    no previously-included directories found matching 'hijack/.ropeproject'
    adding license file 'LICENSE'
    adding license file 'AUTHORS'
    writing manifest file 'django_hijack.egg-info/SOURCES.txt'
    creating build/lib/hijack/locale
    creating build/lib/hijack/locale/cs
    creating build/lib/hijack/locale/cs/LC_MESSAGES
    copying hijack/locale/cs/LC_MESSAGES/django.mo -> build/lib/hijack/locale/cs/LC_MESSAGES
    copying hijack/locale/cs/LC_MESSAGES/django.po -> build/lib/hijack/locale/cs/LC_MESSAGES
    creating build/lib/hijack/locale/da
    creating build/lib/hijack/locale/da/LC_MESSAGES
    copying hijack/locale/da/LC_MESSAGES/django.mo -> build/lib/hijack/locale/da/LC_MESSAGES
    copying hijack/locale/da/LC_MESSAGES/django.po -> build/lib/hijack/locale/da/LC_MESSAGES
    creating build/lib/hijack/locale/de
    creating build/lib/hijack/locale/de/LC_MESSAGES
    copying hijack/locale/de/LC_MESSAGES/django.mo -> build/lib/hijack/locale/de/LC_MESSAGES
    copying hijack/locale/de/LC_MESSAGES/django.po -> build/lib/hijack/locale/de/LC_MESSAGES
    creating build/lib/hijack/locale/en
    creating build/lib/hijack/locale/en/LC_MESSAGES
    copying hijack/locale/en/LC_MESSAGES/django.mo -> build/lib/hijack/locale/en/LC_MESSAGES
    copying hijack/locale/en/LC_MESSAGES/django.po -> build/lib/hijack/locale/en/LC_MESSAGES
    creating build/lib/hijack/locale/es
    creating build/lib/hijack/locale/es/LC_MESSAGES
    copying hijack/locale/es/LC_MESSAGES/django.mo -> build/lib/hijack/locale/es/LC_MESSAGES
    copying hijack/locale/es/LC_MESSAGES/django.po -> build/lib/hijack/locale/es/LC_MESSAGES
    creating build/lib/hijack/locale/fr
    creating build/lib/hijack/locale/fr/LC_MESSAGES
    copying hijack/locale/fr/LC_MESSAGES/django.mo -> build/lib/hijack/locale/fr/LC_MESSAGES
    copying hijack/locale/fr/LC_MESSAGES/django.po -> build/lib/hijack/locale/fr/LC_MESSAGES
    creating build/lib/hijack/locale/pt_BR
    creating build/lib/hijack/locale/pt_BR/LC_MESSAGES
    copying hijack/locale/pt_BR/LC_MESSAGES/django.mo -> build/lib/hijack/locale/pt_BR/LC_MESSAGES
    copying hijack/locale/pt_BR/LC_MESSAGES/django.po -> build/lib/hijack/locale/pt_BR/LC_MESSAGES
    creating build/lib/hijack/locale/ru
    creating build/lib/hijack/locale/ru/LC_MESSAGES
    copying hijack/locale/ru/LC_MESSAGES/django.mo -> build/lib/hijack/locale/ru/LC_MESSAGES
    copying hijack/locale/ru/LC_MESSAGES/django.po -> build/lib/hijack/locale/ru/LC_MESSAGES
    creating build/lib/hijack/locale/sk
    creating build/lib/hijack/locale/sk/LC_MESSAGES
    copying hijack/locale/sk/LC_MESSAGES/django.mo -> build/lib/hijack/locale/sk/LC_MESSAGES
    copying hijack/locale/sk/LC_MESSAGES/django.po -> build/lib/hijack/locale/sk/LC_MESSAGES
    creating build/lib/hijack/static
    creating build/lib/hijack/static/hijack
    copying hijack/static/hijack/hijack-styles.css -> build/lib/hijack/static/hijack
    creating build/lib/hijack/templates
    creating build/lib/hijack/templates/hijack
    copying hijack/templates/hijack/notifications.html -> build/lib/hijack/templates/hijack
    copying hijack/templates/hijack/notifications_bootstrap.html -> build/lib/hijack/templates/hijack
    creating build/lib/hijack/tests/test_app/templates
    copying hijack/tests/test_app/templates/404.html -> build/lib/hijack/tests/test_app/templates
    copying hijack/tests/test_app/templates/hello.html -> build/lib/hijack/tests/test_app/templates
    copying hijack/tests/test_app/templates/hello_filter.html -> build/lib/hijack/tests/test_app/templates
    running install_lib
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/templatetags
    copying build/lib/hijack/templatetags/__init__.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/templatetags
    copying build/lib/hijack/templatetags/hijack_tags.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/templatetags
    copying build/lib/hijack/signals.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/sk
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/sk/LC_MESSAGES
    copying build/lib/hijack/locale/sk/LC_MESSAGES/django.mo -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/sk/LC_MESSAGES
    copying build/lib/hijack/locale/sk/LC_MESSAGES/django.po -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/sk/LC_MESSAGES
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/da
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/da/LC_MESSAGES
    copying build/lib/hijack/locale/da/LC_MESSAGES/django.mo -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/da/LC_MESSAGES
    copying build/lib/hijack/locale/da/LC_MESSAGES/django.po -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/da/LC_MESSAGES
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/pt_BR
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/pt_BR/LC_MESSAGES
    copying build/lib/hijack/locale/pt_BR/LC_MESSAGES/django.mo -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/pt_BR/LC_MESSAGES
    copying build/lib/hijack/locale/pt_BR/LC_MESSAGES/django.po -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/pt_BR/LC_MESSAGES
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/cs
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/cs/LC_MESSAGES
    copying build/lib/hijack/locale/cs/LC_MESSAGES/django.mo -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/cs/LC_MESSAGES
    copying build/lib/hijack/locale/cs/LC_MESSAGES/django.po -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/cs/LC_MESSAGES
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/ru
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/ru/LC_MESSAGES
    copying build/lib/hijack/locale/ru/LC_MESSAGES/django.mo -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/ru/LC_MESSAGES
    copying build/lib/hijack/locale/ru/LC_MESSAGES/django.po -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/ru/LC_MESSAGES
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/de
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/de/LC_MESSAGES
    copying build/lib/hijack/locale/de/LC_MESSAGES/django.mo -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/de/LC_MESSAGES
    copying build/lib/hijack/locale/de/LC_MESSAGES/django.po -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/de/LC_MESSAGES
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/fr
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/fr/LC_MESSAGES
    copying build/lib/hijack/locale/fr/LC_MESSAGES/django.mo -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/fr/LC_MESSAGES
    copying build/lib/hijack/locale/fr/LC_MESSAGES/django.po -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/fr/LC_MESSAGES
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/es
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/es/LC_MESSAGES
    copying build/lib/hijack/locale/es/LC_MESSAGES/django.mo -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/es/LC_MESSAGES
    copying build/lib/hijack/locale/es/LC_MESSAGES/django.po -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/es/LC_MESSAGES
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/en
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/en/LC_MESSAGES
    copying build/lib/hijack/locale/en/LC_MESSAGES/django.mo -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/en/LC_MESSAGES
    copying build/lib/hijack/locale/en/LC_MESSAGES/django.po -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/locale/en/LC_MESSAGES
    copying build/lib/hijack/models.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    copying build/lib/hijack/checks.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app
    copying build/lib/hijack/tests/test_app/authorization_checks.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app
    copying build/lib/hijack/tests/test_app/models.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app
    copying build/lib/hijack/tests/test_app/__init__.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/templates
    copying build/lib/hijack/tests/test_app/templates/404.html -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/templates
    copying build/lib/hijack/tests/test_app/templates/hello.html -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/templates
    copying build/lib/hijack/tests/test_app/templates/hello_filter.html -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/templates
    copying build/lib/hijack/tests/test_app/urls.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app
    copying build/lib/hijack/tests/test_app/views.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app
    copying build/lib/hijack/tests/test_app/decorators.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app
    copying build/lib/hijack/tests/__init__.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    copying build/lib/hijack/tests/test_hijack.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    copying build/lib/hijack/tests/utils.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    copying build/lib/hijack/tests/south_settings.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    copying build/lib/hijack/tests/test_hijack_url_settings.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    copying build/lib/hijack/tests/manage_settings.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    copying build/lib/hijack/tests/test_checks.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    copying build/lib/hijack/tests/urls.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    copying build/lib/hijack/tests/test_settings.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests
    copying build/lib/hijack/__init__.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    copying build/lib/hijack/apps.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    copying build/lib/hijack/admin.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/static
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/static/hijack
    copying build/lib/hijack/static/hijack/hijack-styles.css -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/static/hijack
    copying build/lib/hijack/settings.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/templates
    creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/templates/hijack
    copying build/lib/hijack/templates/hijack/notifications.html -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/templates/hijack
    copying build/lib/hijack/templates/hijack/notifications_bootstrap.html -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/templates/hijack
    copying build/lib/hijack/urls.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    copying build/lib/hijack/helpers.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    copying build/lib/hijack/middleware.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    copying build/lib/hijack/views.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    copying build/lib/hijack/decorators.py -> /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/templatetags/__init__.py to __init__.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/templatetags/hijack_tags.py to hijack_tags.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/signals.py to signals.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/models.py to models.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/checks.py to checks.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/authorization_checks.py to authorization_checks.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/models.py to models.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/__init__.py to __init__.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/urls.py to urls.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/views.py to views.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_app/decorators.py to decorators.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/__init__.py to __init__.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_hijack.py to test_hijack.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/utils.py to utils.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/south_settings.py to south_settings.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_hijack_url_settings.py to test_hijack_url_settings.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/manage_settings.py to manage_settings.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_checks.py to test_checks.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/urls.py to urls.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/tests/test_settings.py to test_settings.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/__init__.py to __init__.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/apps.py to apps.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/admin.py to admin.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/settings.py to settings.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/urls.py to urls.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/helpers.py to helpers.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/middleware.py to middleware.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/views.py to views.cpython-310.pyc
    byte-compiling /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/hijack/decorators.py to decorators.cpython-310.pyc
    running install_egg_info
    Copying django_hijack.egg-info to /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-target-80vsa2wo/lib/python/django_hijack-2.1.10-py3.10.egg-info
    running install_scripts
    writing list of installed files to '/private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-record-49juixv3/install-record.txt'
    Running setup.py install for django-hijack ... done
Successfully installed django-hijack-2.1.10

I do acknowledge that it's a poor experience that warnings from a backend are completely invisible during normal operation. Probably that's something that can be addressed in the packaging ecosystem (/pypa/packaging-problems), but not something that Setuptools can do.

I do observe that one can run with PYTHONWARNINGS=error and that will trigger errors on warnings, but unfortunately, that won't help if there are other unrelated warnings that error. Selecting down to UserWarning does reveal the error:

~ $ $PYTHONWARNINGS='error::UserWarning' pip-run -q 'setuptools<59' wheel -- -m pip-run -v --no-binary :all: --no-deps django-hijack==2.1.10 -- -c pass
Using pip 21.3.1 from /Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/pip (python 3.10)
Collecting django-hijack==2.1.10
  Using cached django-hijack-2.1.10.tar.gz (20 kB)
  Running command python setup.py egg_info
  running egg_info
  creating /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-yeuujh57/django_hijack.egg-info
  writing /private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-pip-egg-info-yeuujh57/django_hijack.egg-info/PKG-INFO
  Traceback (most recent call last):
    File "<string>", line 1, in <module>
    File "/private/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-install-grrjuapq/django-hijack_5f8edcb097854aea8e95cf55a6b59322/setup.py", line 44, in <module>
      setup(name="django-hijack",
    File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-jdny9588/setuptools/__init__.py", line 159, in setup
      return distutils.core.setup(**attrs)
    File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/distutils/core.py", line 148, in setup
      dist.run_commands()
    File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/distutils/dist.py", line 966, in run_commands
      self.run_command(cmd)
    File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/distutils/dist.py", line 985, in run_command
      cmd_obj.run()
    File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-jdny9588/setuptools/command/egg_info.py", line 292, in run
      writer(self, ep.name, os.path.join(self.egg_info, ep.name))
    File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-jdny9588/setuptools/command/egg_info.py", line 655, in write_pkg_info
      metadata.write_pkg_info(cmd.egg_info)
    File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/distutils/dist.py", line 1117, in write_pkg_info
      self.write_pkg_file(pkg_info)
    File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-jdny9588/setuptools/dist.py", line 167, in write_pkg_file
      write_field('Summary', single_line(self.get_description()))
    File "/var/folders/c6/v7hnmq453xb6p2dbz1gqc6rr0000gn/T/pip-run-jdny9588/setuptools/dist.py", line 151, in single_line
      warnings.warn("newlines not allowed and will break in the future")
  UserWarning: newlines not allowed and will break in the future
  Preparing metadata (setup.py) ... error
WARNING: Discarding https://files.pythonhosted.org/packages/17/1d/0ca80a5f49c34c363d273612e05d4772a760f9ef5ca838528f1f59c11cd8/django-hijack-2.1.10.tar.gz#sha256=be484f0ca67a092d5bf9bf8a5307beb716dc2e86b56a69796479183fdeb9036c (from https://pypi.org/simple/django-hijack/). Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
ERROR: Could not find a version that satisfies the requirement django-hijack==2.1.10 (from versions: 0.1, 0.1.1, 0.1.2, 0.1.3, 0.1.4, 1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.0.9, 1.0.10, 2.0.0, 2.0.1, 2.0.2, 2.0.3, 2.0.6, 2.0.7, 2.0.8, 2.1.0, 2.1.1, 2.1.2, 2.1.3, 2.1.4, 2.1.5, 2.1.6, 2.1.7, 2.1.8, 2.1.9, 2.1.10, 2.2.0, 2.2.1, 2.3.0, 3.0rc1, 3.0rc2, 3.0rc3, 3.0rc4, 3.0.0, 3.0.1, 3.0.2, 3.0.3, 3.0.4, 3.1.0, 3.1.1, 3.1.2)
ERROR: No matching distribution found for django-hijack==2.1.10

But still "UserWarning" doesn't match precisely. Better would be if the filter could match "SetuptoolsDeprecationWarning", but alas, the filter doesn't seem to be able to honor warning subclasses.

@jaraco
Copy link
Member

jaraco commented Nov 20, 2021

I don't want to upgrade a (NON DIRECT) dependency of stable builds, i want to be able to install the release that was pinned, and battle tested. Specially for builds that we know are all plain of bad habits but we can't upgrade them to latest release because they are incompatibles.

It occurred to me that in this scenario, there's another option - the maintainer of an affected package can provide a bugfix to the specifically-affected versions in the wild. In the reported scenario, django-hijack==2.1.10 is affected, but the latest release is not. Presumably the version was pinned for a specific compatibility issue. Regardless, it's the responsibility of the person or project that pinned the version to address the consequences of the pin. In this case, I'd recommend for that user to reach out to the django-hijack project and request a new version be released with the easy fix, something like 2.1.11 or 2.1.10.1.

@jaraco
Copy link
Member

jaraco commented Nov 20, 2021

In pypa/pip#10669, I've recognized a limitation in the build/install process that would make it difficult if not impossible to adopt some of the above workarounds, especially in a PEP 517 isolated build environment. To that end, I'm proposing an extension of pip that would give installers more control over the builds. If such a feature were to be implemented, it would readily facilitate working around issues like these.

@kiorky
Copy link
Author

kiorky commented Nov 20, 2021

Seriously, I would be curious to find one maintainer that will be willing to patch every dotpoint release for a single \n metadata tweak. Specially on a big package which would be affected by this change. I just pretend to think that no one will ever have the time to spend on this, specially while being frustrated to see that all of their older packages are broken.

I understand the point of setuptools maintainers when we are going on the theory of "Who is responsible for an \n replacement in metadatas", but in real life, replacing it eternally with a is just a nobrainer question when it comes to stability and retrocompatibility that will upset lot of us, python users.

Also, i totally disagree on one responsibility point: you can't put it of each maintainer to patch all of their releases that were still legit at upload time and so should still remain installable except security problems (moreover when we are speaking of a \n metadata detail)...

Also, we, as users, don't want to use any "workaround" for such simple cases, as already said nascheme. So any of those is unacceptable in long term and really increase the maintenance burden: pinning way down eternally setuptools, using a pip plugin, patching requirements to use a constrained setuptools version as proposed in pypa/pip#10669, specially when it will come to mix versions for differents packages that have different needs.

(Dont misread me, details have all their importance, but they still have to be balanced)

@kiorky
Copy link
Author

kiorky commented Nov 20, 2021

Sorry, but no, this is just a temporary fix to continue operation and this bug is still present.

Formulating workarounds are not addressing the issue of keeping stability and retrocompatiblity.

As i said, we use longterm maintenance scenarii with everything pinned including setuptools, and short term ones where we don't just to detect by advance further breakages like this one, bingo...
Although, we are considering the latest one to be less stable than the former, we assume it to keep green the most possible.

Here we are, to currently use a temporary workaround, and we so are considering our pipelines unstable and partially broken as this day and the solutions you proposed. We dont either want to stay blocked with a previous setuptools version which may become unsupported, or patch every single pipeline we got to add another one workaround plugin. Something is really wrong in this flow.

@nascheme
Copy link
Contributor

Perhaps, but [replacing newlines] also creates a crutch, causing users to end up with junk in their metadata (summaries that are multi-page descriptions, summaries with trailing whitespace), all the while thinking their package is perfectly satisfactory.

It seems to me that the current cure is much worse than the disease. Couldn't new versions of setuptools refuse to do uploads of packages with junk in the metadata? Also, it could warn loudly when building or installing packages with bad metadata (not requiring the -v flag to see the warnings). If the description is so broken that it can't be used, I would suggest that using a generic description or no description at all would be better than outright refusing to install/build the package. Is junk in the description really a serious enough problem to make the package unusable? The package installed with previous versions of setuptools and the resulting application passed all of our QC testing. In my case, the package was never uploaded to PyPI and I don't think anything ever looked at the description.

@jaraco
Copy link
Member

jaraco commented Nov 20, 2021

Couldn't new versions of setuptools refuse to do uploads of packages with junk in the metadata?

Setuptools doesn't do uploads, but even if it did, I explained above why it's not possible to detect the invalid data reliably.

Also, it could warn loudly when building or installing packages with bad metadata (not requiring the -v flag to see the warnings).

Yes, that's probably an action worth investigation. Unfortunately, it would probably require extensions to the standards between build frontends and build backends (such that warnings in the backend could be surfaced in the frontend). As it is now, pip only surfaces errors in the backend and otherwise hides the output. If someone is interested, that would be an interesting and valuable challenge to tackle, but certainly more than a quick patch.

If the description is so broken that it can't be used, I would suggest that using a generic description or no description at all would be better than outright refusing to install/build the package. Is junk in the description really a serious enough problem to make the package unusable?

See #1390 why this was an issue. Yes, it would be trivial to implement a change that transforms invalid input to valid metadata. That's what Setuptools has done for the past 6 months. Unfortunately, as you can see, that change had little if any effect on the invalid packages (even new releases). I've pointed out above I don't believe there's any way to distinguish between prior invalid metadata and brand new invalid metadata. If someone can propose such a mechanism, I'd be interested in exploring a fix.

In my case, the package was never uploaded to PyPI and I don't think anything ever looked at the description.

I'm glad to hear this change has helped you identify the invalid and correct the invalid metadata.

At this point, I'm convinced the change as drafted has had the intended effect (even if more disruptive than originally intended) and there are no open proposals on how to move forward. I still welcome proposals on how to move forward, but any proposal should include a proof-of-concept implementation, as the nuances seem to be getting lost in the discussion.

@kiorky
Copy link
Author

kiorky commented Nov 21, 2021

I know that you are not a big fan of words with strength, but i won't be alone to think it's like sabotage.

I don't know what is bothering me more between knowing that setuptools broke retro-compatibility totally on purpose for no good reason (at least not enough legitimate to not let install a package that installed fine in the past and has no security concern today) or that something is not done to repair something which has an obvious flaw.

There is some kind of double talk when your users are still have to use workarounds to install packages, at equivalent pinning, and have no longterm solutions, and you just say them that there are solutions and "everything works as expected, no issue".

The issues you are describing here look like HTTP Smuggling, but the countermeasures taken are like using an sledgehammer to kill a fly.
There is a balance to have, and also retro-compatibility to take in account...
It would be as if you are asking the whole earth to have strictly W3C compliant HTML. We all know that the offenders are badly behaving, but most of time, it just works enough.
IOW, we can live with a now badly indexed package, but there is no reason to make it's installation more difficult than before.
No one is asking here setuptools to be responsible for bad metadatas and make you responsible for this.

As filtering out bad formatted fields is possible, it was already done before,
But, also, detection is also possible, as you are doing it right now by raising the aforementioned exception,
There is a serious flaw when we are breaking retro-compatibility instead of keeping to let install packages that were known to be 100%legit,
Albeit the cosmetic metadatas that run out fine after some automatic data filtering.

@nascheme had a good idea to restore non breaking mode with a long, big, verbose message, without needed extra arguments, and maybe i would suggest to send a mail to maintainers on upload to pypi to make the issue really visible to maintainers.
That should really help them to fix, but only on their new releases.
If package maintainer want's its package to be correctly rendered or indexed, he will certainly fix the package metadatas, but there is no reason here to break all his past work, even if package metadatas are not 100% perfect.

But please, restore the old behavior or arrange it, or fix already released packages with the final purpose to let them install without errors as before and don't put this burden on users or maintainers (that should for them had to be done before letting them upload).

Arbitrary changing the rules of the game really would really upset most of us and the majority would always keep silent, and maybe doesn't even identify the root of the problem.

EDIT: Well the time.sleep() is maybe not a good idea as it will continue to break already released artifacts... removing it

@jakoblover
Copy link

Thanks for breaking my toolchain :) Doubt some of the packages I use will update their descriptions, so I will freeze setuptools to 58 for the foreseeable future.

@jaraco
Copy link
Member

jaraco commented Nov 26, 2021

Thanks Jakob for reporting. Can you share some of the packages that affect your environment? I’d you consider using the workaround plugin so you wouldn’t have to pin Setuptools? If not, why not?

@boegel
Copy link

boegel commented Nov 26, 2021

I strongly support the request to let setuptools strip out the excess newlines, rather than making this a hard error and essentially breaking the installation of existing Python package releases that happen to have a newline in the description field (see easybuilders/easybuild-easyblocks#2623 for our particular case, where is happened by accident due to fixing code style issues that were being reported by flake8, and we were totally unaware of it).

I fully understand the motivation for trying to get people to not using newlines in packages (cfr. #1390), but frankly I think this is the wrong approach...

Considering looking at this from the point of view of someone who is not very familiar with installing Python packages.
All of a sudden, they're starting to see errors like this:

ValueError: Newlines are not allowed

First of all: the error is very confusing, since it doesn't mention at all where newlines are not allowed. In the code? In the package name? What's going on?!
In #2870 it was acknowledged that the error message could be better, and it was mentioned that "I expect these errors to be rare.". I think this lengthy discussion counters that last argument...

The first reaction from someone hitting this error is most likely going to be "I knew packaging was messy in Python, but this is just... wow".
What's worse is that the end user has no easy way around it. I appreciate the suggested workarounds mentioned in #2893 (comment), but I think these are outside of what a person who doesn't have extensive experience in installing Python packages would consider doing.
Sure, most of those suggestions are targeted at package maintainers, but what if the package maintainer is unaware, or not responsive?

Even a simple workaround like using setuptools<59 is probably too much for non-experienced people.
They often use whatever setuptools/pip/python comes with their OS, and they wouldn't even know where to begin to figure out this problem, let alone fix it.
I'm very sure that most people just use pip install example. If that fails, they're likely to just give up quite quickly... (I don't applaud this, but I do feel it's a common reaction)

I have seen my share of problems with getting software installed, and I must say it took me a while to get my head around what was happening when I first ran into this problem.
I simply couldn't understand why setuptools wouldn't just actively strip out the problematic newline characters, print a big fat warning, and then just go ahead and install the package anyway (because why wouldn't it).

Please consider changing this aggressive behavior of breaking a package installation for what most would consider a very silly problem that is easy to bypass (by just stripping out the newlines, replacing them with a space), before the setuptools versions that make this a hard error are being picked up in various Linux distributions and start causing more trouble around the world.
For some environments (like Gentoo Prefix), it is already too late, but they will likely also pick up a new setuptools version, so hopefully the breakage can be short-lived.

It's now clear that there are dozens of Python packages out there that have a range of versions that are essentially no longer installable with a recent version of setuptools, although there's no good reason for it (since the workaround in setuptools is trivial).

I'm happy to contribute to help with working out a better approach for dealing with excess newlines in package descriptions, without massively disrupting the user experience.

ra1nb0w added a commit to macports/macports-ports that referenced this issue Nov 27, 2021
@fjsj
Copy link

fjsj commented Nov 27, 2021

I just want my old packages to keep building... IMHO it makes no sense to introduce a breaking change on old released packages due to package metadata.

Yes, I could pin the setuptools version and that's exactly what I'll do, but I'm a developer with 10 years of Python experience: I can do that, I know pinning everything is necessary for reproducible and future-proof builds. But this issue is about the net gain for the community. What's the harm caused by this change and what's the gain for the Python community? Picture a beginner dev trying to install a not-so-old library that always had those newlines and getting this error. This change is basically blocking the usage of several old Python packages for many developers. This is not nice at all.

--- Edit:
Right here: macports/macports-ports@8477e9d there's an example of how even well-intended devs can make packages with this issue. For readability, the person might add newlines on description in setup.cfg! The dev is mislead by how setup.cfg works.

@lucasjinreal
Copy link

lucasjinreal commented Nov 28, 2021

I upgraded setuptools just now on my server, and come to this error, then lead me to this discussion. for the reason why I stupid upgrade setuptools is that it introduced a lot of errors internally on setuptools old version.

I don't know what's wrong with newlines in description, but I strongly recommand avoid it gracefully rather than broken all packages in this world, this setuptools is so foundamental that it's not good to easily and ignore users experiences just for this tiny can be avoided newlines mistakes.

To be honest, please stop raise any errors, using a warning instead....

@martyanov
Copy link

The bug really shows what a mess is the current Python packaging ecosystem nowadays. There are many reasonable complaints in the thread. What should we do if we have several dated, but quite ok packages like https:/jucacrispim/asyncblink?

@jaraco your workaround package with such an awkward name as setuptools-hacks.bypass-summary-newline feels like a trolling, sorry!

I'm pinning setuptools to v58.5.3 for now. :(

@jaraco
Copy link
Member

jaraco commented Nov 28, 2021

@jaraco your workaround package with such an awkward name as setuptools-hacks.bypass-summary-newline feels like a trolling, sorry!

Perhaps it feels like trolling, but I assure you, it's not. It is meant to have a descriptive but unfriendly name to make it obvious to the person implementing it that it's meant to be a workaround with a very specific purpose and as a wart reflect that it's not an optimal solution. I know setuptools < 59 is simple and elegant, but it hides the purpose behind why it's there.

Here it is in action:

~ $ pip-run setuptools setuptools-hacks.bypass-summary-newline -q -- -m pip-run --no-binary asyncblink --no-deps asyncblink -- -c pass
Collecting asyncblink
  Using cached asyncblink-0.3.2.tar.gz (3.2 kB)
  Preparing metadata (setup.py) ... done
Skipping wheel build for asyncblink, due to binaries being disabled for it.
Installing collected packages: asyncblink
    Running setup.py install for asyncblink ... done
Successfully installed asyncblink-0.3.2

What should we do if we have several dated, but quite ok packages like https:/jucacrispim/asyncblink?

This question feels like trolling, especially when there's a thread above that provides no less than 6 potential workarounds.

Additionally, I've provided guidance above on what I'd like to see to change the situation - a proposal with a demonstration of how you would go about fixing the issue. The only concrete, actionable proposal given thusfar is to just revert and allow the broken behavior forever. Other proposals are inactionable because they make assumptions and don't take into consideration the considerations I've enumerated above.

Furthermore, I don't get the impression that anyone has even tried the plugin.

I get it, you're offended that in principle setuptools should support building older packages. I agree. But the issue hasn't been important enough that someone could step up and come up with a solution or even volunteer to own the debt that reverting the change would have. And no one has stepped up to help with developing a solution between pip and build backends to surface warnings.

It's a lot of work just to roll out this change, first issuing the warning months ago, then following up, cutting a backward-incompatible release, then responding to the fallout. Now you're asking that we back out that change in order to satisfy a small number of broken packages, undoing that work and re-accumulating the debt.

And to be sure, the number and impact is larger than I had anticipated, but I'm asking for help here. Please help us make the ecosystem better by sending the signal to these packages that their metadata is invalid. Please help be a part of the solution. Thanks.

jaraco added a commit that referenced this issue Nov 29, 2021
…y-on-invalid-summary"

This reverts commit 77678ab, reversing
changes made to f2de347.

Fixes #2893.
@jaraco
Copy link
Member

jaraco commented Nov 29, 2021

In v59.4.0, I've reverted the change, restoring support for bad metadata.

@kiorky
Copy link
Author

kiorky commented Nov 29, 2021

In v59.4.0, I've reverted the change, restoring support for bad metadata.

Thx @jaraco !

archlinux-github pushed a commit to archlinux/svntogit-community that referenced this issue Jan 26, 2022
Closes https://bugs.archlinux.org/task/73510

Although setuptools >= 59.4.0 has reverted the backward-incompatible
change [1], Arch package is not updated yet.

[1] pypa/setuptools#2893

git-svn-id: file:///srv/repos/svn-community/svn@1115671 9fca08f4-af9d-4005-b8df-a31f2cc04f65
archlinux-github pushed a commit to archlinux/svntogit-community that referenced this issue Jan 26, 2022
Closes https://bugs.archlinux.org/task/73510

Although setuptools >= 59.4.0 has reverted the backward-incompatible
change [1], Arch package is not updated yet.

[1] pypa/setuptools#2893



git-svn-id: file:///srv/repos/svn-community/svn@1115671 9fca08f4-af9d-4005-b8df-a31f2cc04f65
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants