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

Embed pep-0008 / pep-0396 version number #787

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

clach04
Copy link

@clach04 clach04 commented Aug 3, 2019

Sample:

Python 2.7.10 (default, May 23 2015, 09:40:32) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import gpiozero
>>> gpiozero.__version__
u'1.5.1'
>>> gpiozero.version
u'1.5.1'

@lurch
Copy link
Contributor

lurch commented Aug 5, 2019

@lurch
Copy link
Contributor

lurch commented Aug 5, 2019

Ahhh, I thought I remembered this cropping up before... see #381

@bennuttall
Copy link
Member

We tend to do it this way in projects now:

https://github.com/piwheels/piwheels/blob/master/setup.py#L18
https://github.com/piwheels/piwheels/blob/master/piwheels/__init__.py#L70

So maybe we should move to that style here.

@clach04
Copy link
Author

clach04 commented Aug 6, 2019

Out of curiosity, how does this interact with https://gpiozero.readthedocs.io/en/stable/faq.html#how-can-i-tell-what-version-of-gpiozero-i-have-installed ?

No change. You can still use setuptools and have that meta data available. The differences are :

  • that this also works without requiring setup tools
  • for maintenance; edit the module rather than the setup.py (which means when the module changes, the version number is changed inside the same file, rather than needing to open another file

@clach04
Copy link
Author

clach04 commented Aug 6, 2019

We tend to do it this way in projects now:

https://github.com/piwheels/piwheels/blob/master/setup.py#L18
https://github.com/piwheels/piwheels/blob/master/piwheels/__init__.py#L70

So maybe we should move to that style here.

I only moved version information, I wanted to see if there was an appetite for this approach. I don't feel strongly that the other meta data should move (note I've moved most meta data into modules I personally maintain so its all in one place).

I do feel strongly that both version string and version tuple should be available, I noticed that in the link above the Python version tuple was made use of :) https://github.com/piwheels/piwheels/blob/master/setup.py#L6 (note this is called version_info, I used version_tuple). Using a tuple means that:

In [4]: '1.0.2' > '1.0.10'
Out[4]: True

In [5]: (1, 0, 2) > (1, 0, 10)
Out[5]: False

behaves sanely, as does:

In [12]: (1, 0, 1) > (1, 0, 0, 'dev')
Out[12]: True

In [13]: (1, 0, 1) > (1, 0, 1, 'dev')
Out[13]: False

In [14]: (1, 0, 0) >= (1, 0, 1, 'dev')
Out[14]: False

In [15]: (1, 0, 1) >= (1, 0, 1, 'dev')
Out[15]: False

In [16]: (1, 0, 2) > (1, 0, 1, 'dev')
Out[16]: True

whilst avoiding shenanigans with:

# from https://www.python.org/dev/peps/pep-0440/
tuple(map(int, release_segment.split(".")))

which then fail if non-numeric version entries are present.

@ukBaz
Copy link
Contributor

ukBaz commented Aug 6, 2019

For reference I looked up the python packaging documentation:
https://packaging.python.org/guides/single-sourcing-package-version/

It does post the following warning about this technique

Warning

Although this technique is common, beware that it will fail if sample/init.py imports packages from install_requires dependencies, which will very likely not be installed yet when setup.py is run.

@bennuttall
Copy link
Member

It does post the following warning about this technique

Yes I found that out on the first round of building for piwheels - many projects failed to run setup.py for this reason! I think it's safe if there's only metadata in your __init__.py

@bennuttall
Copy link
Member

@waveform80 do you have any thoughts? Should we move to the piwheels way?

@bennuttall
Copy link
Member

I have a feeling this won't work because running __init__ with setup.py will inadvertently import stuff that might make it fail, due to missing pin factory and things.

@waveform80
Copy link
Member

I have a feeling this won't work because running init with setup.py will inadvertently import stuff that might make it fail, due to missing pin factory and things.

Precisely - there's a lot of stuff that implicitly happens when gpiozero is imported, which is why I really don't want to do that in setup.py. It is possible to work around this by "parsing" the __init__.py from setup.py instead of importing/executing it but firstly this results in a complex setup.py (something I also tend to avoid) and secondly this usually restricts what can go in __init__.py (which can come back to bite you later).

(Aside: incidentally, I do tend to include the version in this way when building applications (as opposed to libraries) but that's because the root __init__.py in those tend to be entirely empty because setuptools' entry_points are used to launch things.)

Anyway, I'm afraid I don't see the trade-off of having __version__ as useful enough to go for such a work-around in the case of gpiozero.

@bennuttall
Copy link
Member

We could add __version__ to __init__.py but we can't import it into setup.py, so there's no guarantee it's correct. However, it could be part of the release procedure, or maybe the tests.

Or... could we create, say meta.py in the module dir, add __version__ and things there, and import them into setup.py instead of __init__.py?

@ukBaz
Copy link
Contributor

ukBaz commented Sep 18, 2019

I use a little utility called bumpversion that updates the version string in the files I specify. This might be helpful if you go with the above idea:
https://pypi.org/project/bumpversion/
some recommend bump2version:
https://medium.com/@williamhayes/versioning-using-bumpversion-4d13c914e9b8

@waveform80
Copy link
Member

We could add __version__ to __init__.py but we can't import it into setup.py, so there's no guarantee it's correct. However, it could be part of the release procedure, or maybe the tests.

Or... could we create, say meta.py in the module dir, add __version__ and things there, and import them into setup.py instead of __init__.py?

Nope, importing any module under gpiozero will implicitly import init.py too - that's just how the importer machinery works (traverses the hierarchy of modules above the one you're importing). For now, this won't work unless we want to incorporate some parsing machinery into setup.py which I'm not terribly keen on. Once we ditch 2.7 support in 2.x, there are actually some ways around this (using some of the built-in parsing facilities in setup.cfg), but for now this'll have to wait.

@septatrix
Copy link

For newer version this is not required anymore as the importlib module from the standard library provides this functionality since Python 3.8. For gpiozero the following already works:

>>> import importlib.metadata
>>> importlib.metadata.version("gpiozero")
'1.5.1'
>>> tuple(int(x) for x in importlib.metadata.version("gpiozero").split("."))
(1, 5, 1)

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

Successfully merging this pull request may close these issues.

None yet

6 participants