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

Add option to package build to disable normalization of version identifier #308

Closed
ghost opened this issue Dec 19, 2014 · 26 comments
Closed
Labels
enhancement major Needs Triage Issues that need to be evaluated for severity and status.

Comments

@ghost
Copy link

ghost commented Dec 19, 2014

Originally reported by: mklein0 (Bitbucket: mklein0, GitHub: mklein0)


Could an option be added to package builds to disable the use of normalized version identifiers in the final package file name?

Under previous versions of setup tools a version identifier of 20140510.003458 would generate a package name of:

dated_release-20140510.003458-cp27-none-macosx_10_9_intel.whl

After setuptools 8:

dated_release-20140510.3458-cp27-none-macosx_10_9_intel.whl

My primary concern is for older installation tool/devpy versions, the package version matching will fail if I start using the new normalized package names. And I do not want to have to test it.

Aesthetics is another aspect as in this case, the version identifier is actually an encoding of an ISO8601 timestamp.:

date -u +'%Y%m%d.%H%M%S'

This request is derived from issue #302


@kdubezerra
Copy link

I also noticed that, if I set the version number as, say, 1.2.3-rc1, setuptools normalizes it to 1.2.3rc1. This created several problems for me when generating debian packages. Allowing such kinds of normalization do be disabled would be a major improvement.

@jobevers
Copy link

Would also like to be able to disable normalization, 1.2.3-rc1 being normalized to 1.2.3rc1 is causing problems for packaging for me as well.

@jaraco
Copy link
Member

jaraco commented Dec 6, 2016

@dstufft, do you have any opinion on this? IIRC, it was your contribution that added the normalization. What would be the ramifications of allowing bypassing of this normalization?

@dstufft
Copy link
Member

dstufft commented Dec 6, 2016

@jaraco I think as long as you still validate that it is a PEP 440 version (or warn if not.. I don't think we have it set to hard fail), not doing the normalization shouldn't be a big deal. I think my only reason to normalize was just to get everyone using the normal forms as the default since that makes things a bit saner I think. However allowing a flag to bypass normalization should not have any negative affect.

@jaraco
Copy link
Member

jaraco commented Dec 7, 2016

Thanks @dstufft. Glad to hear this wouldn't be a blocker. @mklein0 or others, would you consider putting together a pull request?

@nomadlogic
Copy link

Hi there, I was wondering if there was a status update or further discussion on this issue. I've just run into this when our CI pipeline built a new package (which appends a short git has to the version string) was changed to a different hash.

Version is: 2.4.5.5513c055
/usr/local/lib/python2.7/site-packages/setuptools/dist.py:332: UserWarning: Normalizing '2.4.5.5513c055' to '2.4.5.5513rc55'

It would seem to my quick analysis that there is an overly greedy regex munging version strings...

@backbohne
Copy link

Not nice, but a workaround that works for me:

add this to your setup.py

import pkg_resources
pkg_resources.extern.packaging.version.Version = pkg_resources.SetuptoolsLegacyVersion

@richard-reece
Copy link

richard-reece commented Jul 18, 2018

Just ran into this myself. I've already disabled the PEP 440 warnings and now I have to work around this also :(

We're packaging pre-releases following the semver.org standard, entirely for internal use only. I can maybe understand PyPI rejecting "internal only" versions at registration/upload time, but rejecting it outside of a public arena seems a little heavy-handed.

My solution was to modify our version strings from "2.2.0-a046027" to "2.2.0-pre.a046027" - I couldn't figure a reasonable way to disable the normalization code through monkey-patching.

I am using this monkeypatch to disable the normalization:

from setuptools.extern.packaging import version
version.Version = version.LegacyVersion

@dstufft
Copy link
Member

dstufft commented Jul 19, 2018

I threw together a quick proof of concept for adding a normalize_version=False parameter to setup() that would allow a project to disable version normalization. It does not prevent the warning about non PEP 440 versions (because it is true that using those versions are likely to cause issues), but it does provide a path for people who need a very specific version string.

That branch can be found at https://github.com/pypa/setuptools/compare/dont-normalize, it's only two lines of code plus re-indenting a block of code to be guarded by an if statement. I don't have time right now to develop it further, it would presumably require some tests and someone to shepherd it through the contribution process, but if someone does have the time, that code there is working.

@richard-reece
Copy link

Thanks, Donald!

@pombredanne
Copy link

@dstufft do you need a hand to make this a bona fide PR ?

@dstufft
Copy link
Member

dstufft commented Jan 7, 2019

I doubt I'm going to have the time to finish up the work that's needed to make that proof of concept into a real PR. Feel free to take it and run with it.

@pombredanne
Copy link

@dstufft code has changed a little since but this patch (even updated for the latest code) does not seem to help correctly: for instance I cannot create a valid semver version such as 1.1.0-alpha1 .... it will be normalized at all times as 1.1.0a1 for an sdist and a bdist_wheel which is no longer semver compliant. At least the sdist should be left untouched IMHO.

@bulemoon
Copy link

Will you support this feature in the next release? Any plans if next release don't support the feature? Thank you.

@pombredanne
Copy link

@an-sush if you feel this is "unfair", would you consider submitting a patch then to help right this unfair wrong? 😇 ;)

@ccrisan
Copy link

ccrisan commented Oct 5, 2019

I created https://github.com/ccrisan/setup-no-ver-normalize to "fix" this issue in my projects.

@pombredanne
Copy link

@ccrisan that's simple and clean. Monkey patching really allows awesome things

@KishanKishore
Copy link

Is there any update on this issue? I would like to use -alpha prefixes in my versioning as suggested by semver standard. @ccrisan your library works for the most part but converts - to _ in the wheel file.

@jaraco
Copy link
Member

jaraco commented Mar 15, 2020

I threw together a quick proof of concept for adding a normalize_version=False parameter to setup()

I took a look at this, and while it's a good proof of concept (thanks Donald), I think I'd prefer an implementation that avoided a boolean parameter alongside the version parameter, but instead have some API where the version specified carries with it the fact that it shouldn't be normalized, either by way of wrapping it in an alternate class (such as ccrisan's NoNormalizeVersion) or by setting an attribute on the str that's passed in or by accepting a function (by name or value) for normalizing.

On the other hand, I'd also like something that if it's officially supported, would also work with declarative config. I'm considering this approach:

  • a user could supply a version as version='1.2..3 (sic)', where the (sic) appended acknowledges the non-normal usage.
  • if (sic) is present, setuptools will strip the indicator and skip normalization.

While I sort-of like this approach, it also causes the value to be passed in-band (in the same string as the intended value), which I dislike.

I'm also considering:

  • Setuptools would supply a sic() function, which if called on a string would indicate to Setuptools not to use normalization. e.g. version=setuptools.sic('1.2..3').
  • This approach would not be as portable to declarative config.

Thoughts?

@KishanKishore
Copy link

I threw together a quick proof of concept for adding a normalize_version=False parameter to setup()

I took a look at this, and while it's a good proof of concept (thanks Donald), I think I'd prefer an implementation that avoided a boolean parameter alongside the version parameter, but instead have some API where the version specified carries with it the fact that it shouldn't be normalized, either by way of wrapping it in an alternate class (such as ccrisan's NoNormalizeVersion) or by setting an attribute on the str that's passed in or by accepting a function (by name or value) for normalizing.

On the other hand, I'd also like something that if it's officially supported, would also work with declarative config. I'm considering this approach:

  • a user could supply a version as version='1.2..3 (sic)', where the (sic) appended acknowledges the non-normal usage.
  • if (sic) is present, setuptools will strip the indicator and skip normalization.

While I sort-of like this approach, it also causes the value to be passed in-band (in the same string as the intended value), which I dislike.

I'm also considering:

  • Setuptools would supply a sic() function, which if called on a string would indicate to Setuptools not to use normalization. e.g. version=setuptools.sic('1.2..3').
  • This approach would not be as portable to declarative config.

Thoughts?

How about providing an option to pass an implementation for the normalize function when calling setup, if parameter is not passed then you use the default implementation, if passed as None then you return the version as it is. You could also pass a custom implementation if you like.

@pombredanne
Copy link

@KishanKishore you wrote:

How about providing an option to pass an implementation for the normalize function when calling setup, if parameter is not passed then you use the default implementation, if passed as None then you return the version as it is. You could also pass a custom implementation if you like.

can you elaborate and be more explicit and also include an example?

@dstufft
Copy link
Member

dstufft commented Mar 15, 2020

I don't think that version='1.2..3 (sic)' is any different than a boolean parameter, except instead of using a normal Python boolean it's using some weird setuptools version specific boolean. Notably this would fail really hard if someone is using an older version of setuptools.

Honestly, all of the options seem to just conceptually be a boolean argument, just with different ways of passing it, EXCEPT for the ability to pass your own normalization function.

@jaraco
Copy link
Member

jaraco commented Mar 16, 2020

In #2026, I've drafted the second approach for consideration. Test release available here.

I'm leaning strongly toward this approach as it's minimally invasive and allows the special-consideration to be indicated through the same mechanism as version but while maintaining compatibility for the nominal case.

Please give it a try.

@jaraco jaraco closed this as completed in a323a49 Mar 21, 2020
justin-ellevation added a commit to justin-ellevation/setuptools that referenced this issue Jun 5, 2020
This builds upon pypa#308 and
https://github.com/pypa/setuptools/pull/2026/files to extend support for sic versions (bypassing
normalization) into pkg_resources. I found this while trying to support versions such as
"1.2.3.alpha". While these worked for some setup.py commands, most continued to normalize the
version (egg_info, bdist_wheel for example). Both of those use safe_version in pkg_resources, so
figured extending support for sic there made the most sense.
@oxr463
Copy link

oxr463 commented Jun 19, 2020

Not nice, but a workaround that works for me:

add this to your setup.py

import pkg_resources
pkg_resources.extern.packaging.version.Version = pkg_resources.SetuptoolsLegacyVersion

I tried this, but I am getting the following error:

Traceback (most recent call last):
  File "setup.py", line 16, in <module>
    pkg_resources.extern.packaging.version.Version = pkg_resources.SetuptoolsLegacyVersion
AttributeError: 'module' object has no attribute 'SetuptoolsLegacyVersion'

@andy-maier
Copy link
Contributor

Not nice, but a workaround that works for me:
add this to your setup.py
import pkg_resources
pkg_resources.extern.packaging.version.Version = pkg_resources.SetuptoolsLegacyVersion

I tried this, but I am getting the following error:

Traceback (most recent call last):
  File "setup.py", line 16, in <module>
    pkg_resources.extern.packaging.version.Version = pkg_resources.SetuptoolsLegacyVersion
AttributeError: 'module' object has no attribute 'SetuptoolsLegacyVersion'

@oxr463 Use the newer monkey patch mentioned in a subsequent comment:

from setuptools.extern.packaging import version
version.Version = version.LegacyVersion

It worked for me with the latest setuptools version (50.3.2). I did not verify how far back this works in the setuptools versions.

@andy-maier
Copy link
Contributor

andy-maier commented Nov 22, 2020

As an update to my previous comment, and for people that run additional tests with well-defined minimum versions of dependent packages, here is an approach that works for versions of setuptools at least back to 20.2.2:

# Disable version normalization performed by setuptools.setup()
try:
    # Try the approach of using sic(), added in setuptools 46.1.0
    from setuptools import sic
except ImportError:
    # Try the approach of replacing packaging.version.Version
    sic = lambda v: v
    try:
        # setuptools >=39.0.0 uses packaging from setuptools.extern
        from setuptools.extern import packaging
    except ImportError:
        # setuptools <39.0.0 uses packaging from pkg_resources.extern
        from pkg_resources.extern import packaging
    packaging.version.Version = packaging.version.LegacyVersion

setuptools.setup(
    . . .
    version=sic('1.0.0-dev1')
    . . .
)
$ python setup.py --version
1.0.0-dev1

trini pushed a commit to trini/u-boot that referenced this issue Dec 22, 2022
Fix the following version normalization warning:
"
/usr/lib/python3/dist-packages/setuptools/dist.py:530: UserWarning: Normalizing '2023.01' to '2023.1'
"

Using suggestion from Richard Jones:
pypa/setuptools#308 (comment)

Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
trini pushed a commit to trini/u-boot that referenced this issue Dec 22, 2022
Fix the following version normalization warning:
"
/usr/lib/python3/dist-packages/setuptools/dist.py:530: UserWarning: Normalizing '2023.01' to '2023.1'
"

Using suggestion from Richard Jones:
pypa/setuptools#308 (comment)

Signed-off-by: Marek Vasut <marex@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement major Needs Triage Issues that need to be evaluated for severity and status.
Projects
None yet
Development

No branches or pull requests