Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
.. image:: https://www.repostatus.org/badges/latest/inactive.svg :target: https://www.repostatus.org/#inactive :alt: Project Status: Inactive – The project has reached a stable, usable state but is no longer being actively developed; support/maintenance will be provided as time allows.
.. image:: https://github.com/jwodder/read_version/workflows/Test/badge.svg?branch=master :target: https://github.com/jwodder/read_version/actions?workflow=Test :alt: CI Status
.. image:: https://codecov.io/gh/jwodder/read_version/branch/master/graph/badge.svg :target: https://codecov.io/gh/jwodder/read_version
.. image:: https://img.shields.io/pypi/pyversions/read_version.svg :target: https://pypi.org/project/read_version/
.. image:: https://img.shields.io/github/license/jwodder/read_version.svg :target: https://opensource.org/licenses/MIT :alt: MIT License
GitHub <https://github.com/jwodder/read_version>
_
| PyPI <https://pypi.org/project/read_version/>
_
| Issues <https://github.com/jwodder/read_version/issues>
_
| Changelog <https://github.com/jwodder/read_version/blob/master/CHANGELOG.md>
_
Note: As of the release of setuptools 46.4.0, setuptools natively supports
using the attr:
directive in setup.cfg
to set the project version based
on static analysis of the project source. This makes the bulk of
read_version
's use cases obsolete, and so it will not receive further
development.
When creating a setup.py
for a new project, do you find yourself always
writing the same block of code for parsing __version__
from your project's
source? Something like this?
::
with open(join(dirname(__file__), 'package_name', '__init__.py')) as fp:
for line in fp:
m = re.search(r'^\s*__version__\s*=\s*([\'"])([^\'"]+)\1\s*$', line)
if m:
version = m.group(2)
break
else:
raise RuntimeError('Unable to find own __version__ string')
setup(
version = version,
...
)
Someone needs to put all that into a reusable package, am I right? Well,
someone did, and this is that package. It exports a single function that does
the above, perfect for importing into your setup.py
, and (New in v0.2.0!)
this package even lets you map Python variables to supported metadata fields
via your pyproject.toml
.
read_version
requires Python 3.6 or higher. Just use pip <https://pip.pypa.io>
_ for Python 3 (You have pip, right?) to install
read_version
and its dependencies::
python3 -m pip install read_version
read_version
also has a toml
extra that provides support for
reading configuration from pyproject.toml
. Install it with::
python3 -m pip install "read_version[toml]"
Install read_version
in your development environment.
Add a pyproject.toml
file to your project declaring read_version
as
a build dependency. (This is needed so that other people can build your
package from source; see PEP 518 <https://www.python.org/dev/peps/pep-0518/>
_ for more information.) The
contents of the file should look like::
[build-system]
requires = [
"read_version ~= 0.3.0",
"setuptools",
"wheel"
]
build-backend = "setuptools.build_meta"
In your setup.py
, get rid of your boilerplate __version__
-finding
code and replace it with::
from read_version import read_version
setup(
version = read_version('packagename', '__init__.py'),
...
)
Build your project and double-check that the version is set to the correct value.
Done!
New in version 0.2.0!
Install read_version
in your development environment with the toml
extra::
pip install 'read_version[toml]'
You will also need version 42.0.0 or later of setuptools
::
pip install -U 'setuptools>=42'
Add a pyproject.toml
file to your project declaring
read_version[toml]
as a build dependency and also requiring version
42.0.0 or later of setuptools
. The relevant section of the file should
look like::
[build-system]
requires = [
"read_version[toml] ~= 0.3.0",
"setuptools >= 42.0.0",
"wheel"
]
build-backend = "setuptools.build_meta"
Get rid of your boilerplate __version__
-finding code in your
setup.py
. Instead, add a tool.read_version
table to your
pyproject.toml
file, and for each metadata field that you want to be
read from a variable in a Python source file, add an entry to this table of
the form FIELD = "dotted.file.path:varname"
, where:
FIELD
is replaced by the lowercase name of the field. Supported
fields are:
author
author_email
description
(Note that this is the short description or summary, not
the long description!)keywords
(It is recommended to use a list of strings as the value or
else setuptools
might mangle it)license
maintainer
maintainer_email
url
version
Entries with unsupported or unknown field names are ignored.
dotted.file.path
is replaced by the path (relative to the project
root) to the file containing the variable, with path components separated
by dots and the .py
at the end of the last path component dropped
varname
is replaced by the name of the variable to read
Examples::
[tool.read_version]
# Set the project's version to the value of __version__ in foobar.py:
version = "foobar:__version__"
# Set the project's author to the value of author_name in
# foobar/__init__.py
author = "foobar.__init__:author_name"
# Set the project's license to the value of LICENSE in
# src/foobar/about.py:
license = "src.foobar.about:LICENSE"
If this syntax doesn't work for you — say, because one of your path
components contains a period or colon in its name, or because the file
doesn't have a .py
extension — or if you want to set a default value for
when the variable isn't found, then make tool.read_version.FIELD
into a
table, like so::
# Set the project's version to the value of __version__ in
# foo.bar/__init__.pyq:
[tool.read_version.version]
path = ["foo.bar", "__init__.pyq"]
variable = "__version__"
# Set the project's author_email to the value of EMAIL in foobar.py.
# If the variable isn't found, use the value "me@example.com" instead
# of erroring
[tool.read_version.author_email]
path = ["foobar.py"]
variable = "EMAIL"
default = "me@example.com"
tool.read_version.FIELD
tables may contain the following keys:
:path: (Required) The path to the source file containing the variable to
read, relative to the project root, as a list of path components
:variable: (Required) The name of the Python variable to get the value
from
:default: (Optional) If the variable cannot be found in the source file,
use the given value instead; if the variable cannot be found and
default
is not set, an error will occur
Build your project and double-check that the metadata has all the relevant fields set to their correct values.
Done!
read_version
exports a single function, also named read_version
, whose
signature is::
read_version(*filepath, variable='__version__', default=NOTHING)
read_version()
takes one or more file path components pointing to a Python
source file to parse. The path components will be joined together with
os.path.join()
, and then, if the path isn't absolute, the path to the
directory containing the script calling read_version()
will be prepended to
the path. (No more join(dirname(__file__), ...)
boilerplate needed!)
read_version()
then parses the given Python file and searches through the
parse tree for any assignments to a variable named __version__
, returning
the last value assigned.
The variable
keyword argument can be set to the name of a variable other
than __version__
to search for assignments to a different variable instead.
Setting it to "__doc__"
causes the function to return the module docstring.
If no assignments to the variable are found, a ValueError
is raised. To
instead return a default value when this happens, set the default
keyword
argument.
read_variable
only finds assignments that occur at the top level of the
module, outside of any blocks.
Only assignments of literal values are supported; assignments to the searched-for variable involving more complicated expressions will cause an error to be raised.
FAQs
Extract your project's __version__ variable
We found that read-version demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.