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

PyPI: Python version from classifiers vs. requires_python #5551

Open
12944qwerty opened this issue Sep 17, 2020 · 37 comments
Open

PyPI: Python version from classifiers vs. requires_python #5551

12944qwerty opened this issue Sep 17, 2020 · 37 comments
Labels
service-badge Accepted and actionable changes, features, and bugs

Comments

@12944qwerty
Copy link

In #5550 I noted that to get pyversion, you need to use classifiers. However, there are a lot of python libraries out there that also use python_requires instead.
Instead of making a feature proposition there, I decided to make a new issue that was directed at this task instead of using an existing 'question' issue.

I'm proposing a feature where the pyversions look for python_requires before parsing classifiers.

@calebcartwright calebcartwright added the service-badge Accepted and actionable changes, features, and bugs label Sep 17, 2020
@12944qwerty
Copy link
Author

Note: If someone could explain to me how python-version is parsed here, I could try doing it myself.

For example, I might want to know where handle is being called, and what { egg } is. Thank you!

@chris48s
Copy link
Member

Yeah I think a badge that looks at requires_python and just reproduces the requires_python string (i.e: output is something like rather than attempting to turn that into a list of versions) would be useful. I'm leaning towards saying that should be another variant though, as opposed to a replacement for the existing badge. The format is different and it is, of course, possible for the value of requires_python to conflict with the values in classifiers 🙄

@12944qwerty
Copy link
Author

So you're saying instead of pypi/pyversions we make it so that you use pypi/pyrequires instead (or something like that?)

Omg, how did you make a badge like that?

@chris48s
Copy link
Member

So you're saying instead of pypi/pyversions we make it so that you use pypi/pyrequires instead (or something like that?)

Yeah exactly. That sounds like a good choice of URL to me 👍

Omg, how did you make a badge like that?

I'm guessing from the strike through you already figured it out, but I just used a static badge to demonstrate. The URL for that would be https://img.shields.io/badge/python-%3E%3D3.4%2C%3C4.0-blue

@chris48s chris48s added the good first issue New contributors, join in! label Sep 18, 2020
@12944qwerty
Copy link
Author

12944qwerty commented Sep 18, 2020

Great, I'll do some browsing and see if I can make a PR! Or not, to which I'll let you know.

I'm guessing from the strike through you already figured it out, but I just used a static badge to demonstrate. The URL for that would be https://img.shields.io/badge/python-%3E%3D3.4%2C%3C4.0-blue

Um.... no? lol I used the strike because it was technically offtopic.... 🤷‍♂️... I should've known though...

@12944qwerty
Copy link
Author

See #5576 for the PR related

@paulmelnikow
Copy link
Member

Yeah I think a badge that looks at requires_python and just reproduces the requires_python string (i.e: output is something like rather than attempting to turn that into a list of versions) would be useful. I'm leaning towards saying that should be another variant though, as opposed to a replacement for the existing badge. The format is different and it is, of course, possible for the value of requires_python to conflict with the values in classifiers 🙄

I'd rather we find a way to do the right thing automatically here, without authors needing to choose which method to use. Yes, there could be conflicts, however the pip resolver (or the pypi server?) must have a way of resolving these conflicts now, as it already can do things like identify the last version of a package that supports Python 2.

@calebcartwright
Copy link
Member

Reopening as referenced PR hasn't been merged and seems additional discussion is needed

@12944qwerty
Copy link
Author

@paulmelnikow You're saying to merge the classifiers and pyrequires? Which one would we parse first? Do we show both? How would this work?

@chris48s
Copy link
Member

the pip resolver must have a way of resolving these conflicts

pip only looks at python_requires. From https://packaging.python.org/guides/distributing-packages-using-setuptools/#classifiers

Although the list of classifiers is often used to declare what Python versions a project supports, this information is only used for searching & browsing projects on PyPI, not for installing projects. To actually restrict what Python versions a project can be installed on, use the python_requires argument.

https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires

In addition, only versions 9.0.0 and higher of pip recognize the python_requires metadata. Users with earlier versions of pip will be able to download & install projects on any Python version regardless of the projects’ python_requires values.


My thinking on recommending that we just make this a separate badge is that the format of python_requires is its a range (or more accurately a PEP 440 constraint so it could be >=3.4,<4.0, ~=3.3 etc) whereas the classifiers give us an explicit list of tags e.g:

Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9

In order to take into account both in one badge we've either got to try and convert ranges into a list of versions to retain the current format (knowing how to turn >=3 into a list means I have to be able to answer the questions "Is python 3.9 out yet?", "Does it matter that its still in beta?", for example which I don't think we should do) or change the existing badge format so it sometimes shows a range and sometimes a list depending on whether python_requires is populated, which will be an unexpected change for most users (PyPI - Python Version is far from our highest traffic badge but we've served >100,000 of them in the last day so it has.. a few live users).

Given that I'm in favour of just saying

PyPI - Python Version (from python_requires): /pyrequires
PyPI - Python Version (from classifiers): /pyversions

are two different badges.

My second-preference option would be to change /pyversions so it looks at python_requires first (as this enforces a stronger requirement), gives you a PEP 440 contraint if python_requires is set (e.g: ~=3.6) then otherwise falls back to an explicit list from classifiers, but provide a ?source=classifiers option or something so that users who want what they have now can opt back in to the existing behaviour.

@paulmelnikow
Copy link
Member

Although the list of classifiers is often used to declare what Python versions a project supports, this information is only used for searching & browsing projects on PyPI, not for installing projects. To actually restrict what Python versions a project can be installed on, use the python_requires argument.

https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires

Oh, interesting!

PyPI clearly does read both. An example project that shows both is requests, and one that shows just the classifier is polliwog.

I did not know pip uses python_requires. It suggests that authors, if they're only going to declare one of them, really should provide python_requires. That's why I think it should be the default for our Python versions badge – so that people who want to adopt the badge are encouraged to provide a value for the property that they really should be providing anyway.

I don't see a good reason to have two different badges for showing the the Python versions supported by a library.

I'm not sure why authors would prefer the ?source=classifiers option if they declare both, though I guess I'm fine with providing that option in case someone needs to use it.

My second-preference option would be to change /pyversions so it looks at python_requires first (as this enforces a stronger requirement), gives you a PEP 440 contraint if python_requires is set (e.g: ~=3.6) then otherwise falls back to an explicit list from classifiers

I guess this is my first choice, mainly because I don't think we should have two different badges for the same piece of information …

but provide a ?source=classifiers option or something so that users who want what they have now can opt back in to the existing behaviour.

… and I'm fine with this if you think it's important.

@paulmelnikow paulmelnikow changed the title Pypi python_requires parsing PyPI: Python version from classifiers vs python_requires Sep 21, 2020
@paulmelnikow paulmelnikow removed the good first issue New contributors, join in! label Sep 21, 2020
@12944qwerty
Copy link
Author

I have already created a PR regarding two different badges. Seeing as making a combined badge versus two separate badges is still in discussion, I'll hold off the PR for now until we decide which option to go with.

My opinion would be to make two different badges, as it's easier for me to make. I'm not experienced with js, as I've said before, and making two different badges has already proven to be easier for me.

However, making them one badge and including ?source=classifiers does seem like a better choice to go with.

@paulmelnikow
Copy link
Member

Makes sense, let's sort out the discussion first. If you can't finish the PR, it's okay, maybe someone else will want to work on this, or maybe I can pick it up.

Hmm, the python_requires format is really not that friendly for humans, is it. This is from requests:

Requires: Python >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*

The version from classifiers shows 2.7 | 3.5 | 3.6 | 3.7 | 3.8 which is much easier to understand.

"Is python 3.9 out yet?", "Does it matter that its still in beta?", for example which I don't think we should do

Now I understand now what you meant here.

I guess I'm still coming from a different place here, which is I think we should try to have one badge, and make the default behavior friendly and correct, even though it's a change from the past behavior.

@12944qwerty
Copy link
Author

"Is python 3.9 out yet?", "Does it matter that its still in beta?

The documentation says that using python_requires="~=3.3" is for everything above 3.3 but not till 4.0. I believe that the operations literally mean all the versions above, below, or within the AND group (commas would be "and" operations).

We could look at this by iterating through every version (major, minor, and micro) and delete the ones that aren't allowed. Minor and Micro could be replaced by * if all remain.

However, this wouldn't have any need for ?source as it would look the same and be the same.

@chris48s
Copy link
Member

chris48s commented Sep 22, 2020

Yeah in a lot of cases python_requires will be quite succinct and human-readable (e.g: >=3.5), but sometimes python_requires can be specified in a way which isn't very human-readable. As you've noted, requests is an excellent example of this.

(using classifiers)

is much clearer than

(using python_requires)

Fundamentally, python_requires is optimised for machines, whereas classifiers are optimised for humans, although often python_requires is also a nice format for humans :)
That example also provides a good example of why it would be non-trivial for us to infer the first format from the second in some cases.

The other reason I think its important to provide a choice is because this wouldn't be a breaking change in the sense that https://img.shields.io/pypi/pyversions/django.svg renders a badge before and https://img.shields.io/pypi/pyversions/django.svg will render a badge after. But changing which value from the API response we display on the badge and the visual format of the badge (in lots of cases) is a big behavioural change. For a popular badge like this, if we make a big change like that to the default behaviour there will be some non-zero number of users who will want it to continue to work the way it has worked for the last ~5 years and I think we should provide a way to do that even if we changed the default, especially given we can (its not like classifiers are being removed or anything).

@12944qwerty
Copy link
Author

I agree that it would change the way it looks and many people could become confused and may want the original back. However, since most python_requires uses only one "requires" it would be fine to use that as default. But if there is more than one "requires" we could use classifiers instead. Of course, you can always change default with ?source=.

@paulmelnikow
Copy link
Member

paulmelnikow commented Sep 22, 2020

I still feel like wrangling these formats is sort of an implementation detail that makes our life difficult, rather than something we fundamentally want to provide two options for.

Fundamentally, python_requires is optimised for machines, whereas classifiers are optimised for humans, although often python_requires is also a nice format for humans :)
That example also provides a good example of why it would be non-trivial for us to infer the first format from the second in some cases.

I agree, it doesn't look trivial. Although I think this is what I'd like to try to do: attempt to provide a nice human-readable badge by interpreting python_requires and cross-referencing it with a list of released Python versions.

Maybe the first course of action is to attempt to produce that function, see how good the results are, and then we can see if there is a use case for the old behavior (i.e. a project where we can't produce the right thing from python_requires but can produce the right thing from classifiers).

Normally I don't advocate deep logic like this in Shields, though the state of Python packaging being what it is – and in this case specifically, two ways of specifying the same thing! – I think it's worth our effort to paper over the complexity. There are a few other precedents, such as the PHP version badges which fetch the latest release of PHP.

I could also put the function in its own npm module.

Added: There is a JS implementation of PEP 440 which could help.

@calebcartwright
Copy link
Member

For a popular badge like this, if we make a big change like that to the default behaviour there will be some non-zero number of users who will want it to continue to work the way it has worked for the last ~5 years and I think we should provide a way to do that even if we changed the default, especially given we can (its not like classifiers are being removed or anything).

This is a point of concern for me, especially in light of other badge changes being applied semi-recently and the feedback we subsequently received from users. If a change could potentially result in a user seeing one badge message foo today, and a different message bar tomorrow without changing anything on their end, then that's going to fall in the "breaking change" bucket for me. That's complicated even more so if there's no way for users to get back to the foo message.

Regardless of our desired state, the status quo bias weighs heavily. If we're targeting making such a breaking change, and do so in a permanent way (i.e. no back to old foo) then I think we need to communicate this loudly to users and give them a chance to weigh in, via a poll or whatever else.

(also haven't been following super closely so apologies if I've misunderstood something 😄)

@paulmelnikow
Copy link
Member

Agree with requesting comments before making the change.

@12944qwerty
Copy link
Author

So we're going to poll the public IF we decide on combining the two badges? That's sensible.

What would happen if the public goes against combining? Should we make the default classifiers? Make two separate badges? Etc...

@paulmelnikow
Copy link
Member

I propose we use the list of Active Python Releases at https://www.python.org/downloads/, and filter that using @renovate/pep440 with requires_python when that field is present. If that list conflicts with the classifiers, I'm sort of reversing my previous thought, and thinking we should let the classifiers. win The purpose of the classifiers is 100% to signal things to humans, so if a maintainer is going through the effort to maintain a different list of classifiers, maybe we ought to just show it. If they want to change what shows up on the badge, they can remove or modify the classifiers, and the badge just works. Also, if a developer doesn't like what we produce based on requires_python they can easily override it by specifying version classifiers.

For packages with classifiers, this means we'll see the same thing as before. For packages with requires_python and no classifiers, we'll now see a version where before is was "missing." So this has the advantage of not being a major change in behavior, and I don't think we need an RFC. (I think we really do need to develop an RFC process, though that's a project of its own.)

One implementation challenge is getting a machine-readable list of active python releases. We could use the ftp listing, though it shows prereleases so we'd have to filter those out. I'd suggest that initially I hard-code the list from that web page, since it only changes every couple of years and it's minimal maintenance burden. Then I can open a follow-up issue to reach out to the python.org folks and see if they have a suggestion about fetching a machine-readable list.

@paulmelnikow paulmelnikow changed the title PyPI: Python version from classifiers vs python_requires PyPI: Python version from classifiers vs. requires_python Sep 22, 2020
@chris48s
Copy link
Member

I'm sort of reversing my previous thought

This is a good indication that different users are going to have different expectations of how this should work: It is not completely clear-cut how this should work and will end up being somewhat opaque to users.

If they want to change what shows up on the badge, they can remove or modify the classifiers

if a developer doesn't like what we produce based on requires_python they can easily override it by specifying version classifiers.

I think if you want the badge to look at a different value, the solution should be to change the badge(params) not change your package manifest.

Broadly although #5576 is not currently mergeable I think I'm still in favour of that general approach over #5592

@12944qwerty
Copy link
Author

I'm trying to fix #5576 's problem so if someone can help, please do. It's very confusing.

communicate this loudly to users and give them a chance to weigh in, via a poll or whatever else.

Should we poll this right now?

@paulmelnikow
Copy link
Member

I recognize that I'm a bit in the weeds on this, so please bear with me…

I think if you want the badge to look at a different value, the solution should be to change the badge(params) not change your package manifest.

This doesn’t really make sense in the context of my proposal. Let me try to clarify what I meant.

If they want to change what shows up on the badge, they can remove or modify the classifiers

If the PyPI status, implementation, python, or django version badges displayed the wrong information today, it means the project has been published with the wrong information. You’d fix them by changing the classifiers and republishing, not changing the badge. The same is true of of the npmjs dependency, Node version, and /npm/types badges. In these cases, changing the badge is only what you’d do if you just gave up on having Shields detect the right thing.

if a developer doesn't like what we produce based on requires_python they can easily override it by specifying version classifiers.

Since classifiers would take priority over requires_python, if a developer doesn't like what we produce based on requires_python it follows that the package has no version classifiers. Hence telling us to render a badge from classifiers is pointless because it would mean rendering an empty badge. Whether we provide this badge option or not, the package author would need to add classifiers in order for us to display the python versions from classifiers.

As far as I can recall, when we have multiple badges that display the same piece of information, they are pulled from completely different data sources. An example is the Node version pulled from npmjs vs the Node version pulled from a package.json file on GitHub.

The Python version badges are for users to know what Python versions a package supports, and I feel pretty strongly that it's one badge since the source is PyPI. While it's unfortunate that PyPI provides two ways of expressing this information, #5550 was a request to consider the source where it was specified instead of showing "unknown". It wasn't a request to choose between two conflicting sources.

Choosing the source feels less like a different badge, and more like the ?sort=date and ?sort=semver options we use in various places. In those cases, the user has a concrete reason to tell us which versioning convention we should use. It's clear these are needed because (1) some projects follow semver and some don't, (2) we can’t easily detect which, and (3) we'll show the wrong information if we assume wrong.

I'm open to making a parameter here too. Though before we do, I think it would be useful to find a concrete example that justifies it (or wait for someone to provide one).

So far I'm not able to think of such an example. These are the things I'm thinking about:

  • If a package declares classifiers which conflict with requires_python, is this an error or could it be deliberate? If it's deliberate, why?
  • Aren't python version classifiers expressly intended for conveying the version support information to humans? If so, why couldn't the classifiers, if present, be the ultimate source of truth? Why would a package want to declare one set of versions in the classifiers and want a different set of versions to appear on the badge?

I'm sort of reversing my previous thought

This is a good indication that different users are going to have different expectations of how this should work: It is not completely clear-cut how this should work and will end up being somewhat opaque to users.

Maybe, though I think it's more a result of implementing it the other way, and then not being able to identify a use case where a badge should use requires_python when classifiers are present.

@12944qwerty
Copy link
Author

requires_python was meant to force pip from not installing if the python version was incorrect. I believe that would be the right source of data, especially because classifiers don't have a micro option. Specificity is always the best way to go in my mind.

Why would a package want to declare one set of versions in the classifiers and want a different set of versions to appear on the badge?

However, you are also right. It makes no sense for someone to write two different sets of versions for their package. However if this were to happen, I would go towards using the more readable option.

In some cases this could be requires, but in all other cases, it would probably be classifiers.

@chris48s
Copy link
Member

I think part of the reason we disagree is because we're thinking about slightly different things. I'm partly thinking about this also giving us an alternate display format.

So to give a concrete example from one of my projects where I actually use this badge https://github.com/chris48s/arcgis2geojson , one of the things that is potentially quite nice about being able to pick which value you want is if your list of classifiers is long but your python_requires is human-readable (which tbh in a lot of cases it is), it would be quite nice to just bung python_requires on a badge. i.e:

- https://img.shields.io/pypi/pyversions/arcgis2geojson.svg is quite long, especially once 3.9 gets added to that list. It would be quite nice to be able to switch to a badge that does the equivilent of
- https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fpypi.org%2Fpypi%2Farcgis2geojson%2Fjson&query=info.requires_python&label=python which conveys compatability information in less space and has the advantage that its still correct when python 3.9 is generally available - I don't need to push a release to add a classifier.

Note my classifiers list is not inconsistent with my python_requires statement as such (although it probably will become inconsistent for a bit when python comes out in October 🙈 we'll come back to that later), but I would see utility in having that choice. I also wouldn't like to see us trying to reverse-engineer constraints from a list to try and achieve that.
Maybe the solution is just use https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fpypi.org%2Fpypi%2Farcgis2geojson%2Fjson&query=info.requires_python&label=python if you want that functionality.. 🤷


If a package declares classifiers which conflict with requires_python, is this an error or could it be deliberate?

Interesting philosophical question in its own right. If a tree falls in the forest.. 🌳
I think if your python_requires says ">=3" and your classifier list is

Programming Language :: Python :: 2.3
Programming Language :: Python :: 2.4
Programming Language :: Python :: 2.5

that's just silly. I don't think PyPI actively stops you doing it (I've not tried), but it doesn't mean anything sensible.

I think there are probably 2 sensible-ish cases where python_requires and classifiers can conflict though, one of which is probably really common.

The common one is going to be where you've set your python_requires to >=3.5 or >=3.5,<4.0 and your classifiers list is

Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8

At the point you uploaded the package, they were totally consistent but then python 3.9 comes out, Programming Language :: Python :: 3.9 becomes a valid classifier and your python_requires now disagrees with classifiers. Maybe sometimes that's a conscious communication that means "I haven't added 3.9 to my test matrix yet, so I'm actively not choosing to declare python 3.9 support" (but equally the maintainer isn't going to actively make pip throw an error if you want to install on python 3.9 - generally there's not going to be a non-BC change in a point-release). Sometimes it probably just means "I haven't bothered to update my package (metdata) yet". You could argue this means python_requires is wrong and you should really be declaring >=3.5,<3.9 but this case is going to be really common out there in the wild, especially at a time like now when a new python version is at release candidate stage. There's going to be a lot of packages that don't change that often where the maintainer doesn't instantly publish a release on new python day just to add a classifier (my own package listed above will probably be in this state for some period of time). The intent in this case is somewhat ambiguous - I don't think we can correctly apply one assumption to all packages.

I guess maybe another valid-ish case where python_requires denotes compatibility, but classifiers denote support or testing is where python_requires is like >=3 but your classifiers say

Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8

so I'm not going to actively prevent you installing on python 3.4 and it will probably work, but the classifiers describe my test matrix or what I'm willing to deal with support requests on (e.g: because my CI provider makes it hard to test on unsupported versions, or whatever but I'm not actually relying on any feature/syntax that is only available in python 3.5+). Not sure how valid/common that is - I don't have a concrete example.

I don't think that tells us anything other what what we already know from https://packaging.python.org/guides/distributing-packages-using-setuptools/#classifiers though: python_requires enforces a constraint on where a package can be installed. Classifiers are a looser indicator of support. Dunno if that helps?


Hopefully we can arrive at a consensus on this one way or another fairly soon. I appreciate that although we've got different perspectives at the moment we're keeping the conversation constructive (I think) and we both want to arrive at a solution which is correct and provides value to the community. Simultaneously, there is something a bit exhausting about spending the evening drafting another wall o' text on this. 😄 Might need to take a break

@paulmelnikow
Copy link
Member

Hopefully we can arrive at a consensus on this one way or another fairly soon. I appreciate that although we've got different perspectives at the moment we're keeping the conversation constructive (I think) and we both want to arrive at a solution which is correct and provides value to the community. Simultaneously, there is something a bit exhausting about spending the evening drafting another wall o' text on this. 😄 Might need to take a break

Yea, I just wanna echo that. I feel like we started in really different places and covered a lot of ground, which feels constructive to me. It feels good to be engaging more deeply and passionately on Shields, and kinda neat that this is a topic we both have strong feelings about. This has felt constructive to me, too. Also spent a while on this last night and felt a little exhausted after. Shall we let it rest a few days?

@12944qwerty
Copy link
Author

Shall we let it rest a few days?

I guess we could let this go idle. If anyone has any ideas they could just send it here. But we can finally come back "officially" with a fresh mind later.

@chris48s
Copy link
Member

Also spent a while on this last night and felt a little exhausted after

Python packaging is a topic capable of driving the most rational minds to the edge of reason at times.

@paulmelnikow
Copy link
Member

Python packaging is a topic capable of driving the most rational minds to the edge of reason at times.

Too true.

@chris48s
Copy link
Member

No pressure to jump back into this conversation yet, but I've been slowly churning this over and I've thought of another interesting example of a case where python_requires and classifiers intentionally communicate slightly different things, and that's the typing module. the purpose of this module is to backport type hints to python 2.7 and python 3.5 (they're native in 3.5+).

This package can be installed on python 3.5+ (it is compatible - python_requires will let you do it) but if you do that, it will just do nothing (or it will get out of the way and let the standard library do its thing) - this allows you to just bung typing in your project requirements if you're using type hints but want to shim support for old versions - you don't need to have context-dependent package requirements.

https://github.com/python/typing/blob/95d6776c0d07e7b096ca153ed6c5b1b30db738e1/setup.py#L70

but the classifiers declare support for (or perhaps "relevance to") python 2.7 and python 3.4 (which is where this package will actually do something )

https://github.com/python/typing/blob/95d6776c0d07e7b096ca153ed6c5b1b30db738e1/setup.py#L52-L53

Admittedly this is a quite uncommon type of package. Simultaneously I reckon I'm happy to say this list of authors know how to do python packaging properly:

https://github.com/python/typing/blob/95d6776c0d07e7b096ca153ed6c5b1b30db738e1/setup.py#L61

@paulmelnikow
Copy link
Member

paulmelnikow commented Sep 29, 2020

backport type hints to python 2.7 and python 3.5

I think you meant 2.7 and 3.4?

I'm amused that you found a package that's relevant to certain versions of Python and compatible with others. 😀

In thinking about what badge or badges we want to have available for this package…

  1. I think showing 2.7 | 3.4 for this package (the relevant versions) makes a lot of sense.
  2. Is there a need for a second badge that shows the complete list of compatible versions? 2.7 | 3.4 | 3.5 | 3.6 | 3.7 | 3.8
  3. It seems clear that, for this package, the list of active versions that are compatible is completely useless, as it omits 3.4: 2.7 | 3.5 | 3.6 | 3.7 | 3.8

@chris48s
Copy link
Member

Yes sorry - it backports types to python 3.4 - they're native in 3.5

  1. I think showing 2.7 | 3.4 for this package (the relevant versions) makes a lot of sense.

Agreed. The list of classifiers (whatever the package maintainer has decided that means) on a badge is a useful thing. That's what we already have.

  1. Is there a need for a second badge that shows the complete list of compatible versions?

I think it is also useful to be able to communicate compatibility as a different concept from classifiers sometimes.
One way to do that is as a range/constraint, another is as a list. Where trying to present it as a list becomes potentially useful is if the thing you want to present is compatibility and your constraint is non-human readable (like in the requests example) but its not necessarily super-common.

  1. It seems clear that, for this package, the list of active versions that are compatible is completely useless

Yes. If we are going to turn the range into a list, we have to take into account all versions matching the constraint. Assuming the maintainer only cares about active versions is too much of a leap - we don't know. i.e: if the maintainer says the constraint is>=3.2 then if we're going to try and infer a list from that, the correct list to infer is 3.2 | 3.3 | 3.4 | 3.5 | 3.6 | 3.7 | 3.8 not 3.5 | 3.6 | 3.7 | 3.8.

@12944qwerty
Copy link
Author

Hmm, I think this is enough of a break? I still have no idea how to do this, still very inexperienced with javascript.

Current ideas we had:

  • Make it so that the badges go in order. If classifiers aren't found, then requires_python will be used. OR vice versa. This way, many badges won't be changed and people won't wonder what had happened.
  • Make two separate badges, one for each
    • For requires_python, we list every python we can. However, this can take up a lot of space
    • Alternative would be to just list all python versions the way it is written on pypi. Eg >=3.5, <=4.0. Unfortunately, not many people know the syntax PyPI use.
    • Or, we can still parse the versions possible and if it's less than a certain number, we put that on the badge.
  • We can combine all of the above and use args to make badges one way or the other, depending on how the maintainer likes it.

Should we continue with one idea? Or should we still discuss more ideas and find the best fit.

@chris48s
Copy link
Member

chris48s commented Jan 6, 2021

Yeah its a useful bump 👍

I think I'm still in favour of 2 badges: one which shows python_requires formatted as a range and one that shows the classifiers formatted as a list.

Since having this conversation I just swapped out all the badges on all my own python projects to a custom json badge that shows python_requires as a range e.g: https://img.shields.io/badge/dynamic/json?query=info.requires_python&label=python&url=https%3A%2F%2Fpypi.org%2Fpypi%2Fgeojson-rewind%2Fjson as I think that's the most useful. It would be handy to have a built-in badge for that, but if shields ends up going in a different direction, there's always that workaround for those of us who prefer it..

@chris48s
Copy link
Member

chris48s commented Jan 6, 2021

It is also worth noting that there is a slightly different but somewhat related conversation going on in #6013

@12944qwerty
Copy link
Author

Hmm, seeing as there haven't been many updates on this Issue lately, I think I will close this. I think the best way is what Chris just showed with the link/embed above.
The only thing I can think of in addition to that is to make something that will just generate that link quickly, in case someone doesn't understand how to make an embed quickly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
service-badge Accepted and actionable changes, features, and bugs
Projects
None yet
Development

No branches or pull requests

4 participants