rbarrois / python-semanticversion Goto Github PK
View Code? Open in Web Editor NEWSemantic version comparison for Python (see http://semver.org/)
License: BSD 2-Clause "Simplified" License
Semantic version comparison for Python (see http://semver.org/)
License: BSD 2-Clause "Simplified" License
I would like to filter and match 'best' stable version.
Current behavior:
versions = [1.0.0, 1.1.0, 1.2.0-pre]
s = Spec(">=1.0.0")
s.select(versions)
Out: Version('1.2.0-pre')
I would expect pre-releases to be exclude unless explicitly ask for.
Expected behavior:
s = Spec(">=1.0.0-") # with a '-'
s.select(versions)
Out: Version('1.2.0-pre')
s = Spec(">=1.0.0")
Out: Version('1.1.0')
Is python-semanticversion compatible with Semver 3.0?
This adds an #examples section (of potential test cases):
This seems like a cool project and I'd like to include it in a project I'm working on. Is there any chance you'd be willing to support implicit comparison of Version
and Spec
objects with string types? For example, I'd like the following cases to work:
import semantic_version as sv
assert sv.Version('1.0.0') == '1.0.0'
spec = sv.Spec('>=2.0.0')
assert spec.match('2.1.0')
It's less important, but I also think this would be useful with tuples:
assert sv.Version('1.0.0') == (1,0,0)
It doesn't seem like this would be very difficult or unreasonable to support. I'd be willing to submit a PR myself.
npm and composer support the use of tilde (~
) and caret (^
) in version requirements. Would you accept a well written and tested patch that implements support for this in comparisons?
Warnings upon launching a Django 1.9.5 project using semantic_version
:
/<snipped>/.venv/lib/python3.5/site-packages/semantic_version/django_fields.py:38: RemovedInDjango110Warning: SubfieldBase has been deprecated. Use Field.from_db_value instead.
str('SemVerField'), (BaseSemVerField, models.CharField), {})
/<snipped>/.venv/lib/python3.5/site-packages/semantic_version/django_fields.py:41: RemovedInDjango110Warning: SubfieldBase has been deprecated. Use Field.from_db_value instead.
class VersionField(SemVerField):
/<snipped>/.venv/lib/python3.5/site-packages/semantic_version/django_fields.py:64: RemovedInDjango110Warning: SubfieldBase has been deprecated. Use Field.from_db_value instead.
class SpecField(SemVerField):
It looks like the solution is to remove __metaclass__
and manually define the to/from Python methods: https://stackoverflow.com/questions/35166085/how-to-deal-with-subfieldbase-has-been-deprecated-use-field-from-db-value-inst
Ironically, semver library does not follow semver. For example, removing specs
property from Spec
broke compatibility with version 2.6. Please, introduce breaking changes with major bump only.
I'm currently investigating a problem in an application of mime which works fine with 2.6.0 and breaks with 2.7.0 and later versions including 2.8.1.
The exception I get is (with 2.8.1):
s1:4: DeprecationWarning: Partial versions will be removed in 3.0; use SimpleSpec('1.x.x') instead.
version_obj = semantic_version.Version(version, partial=True)
Traceback (most recent call last):
File "s1", line 5, in <module>
if version_obj not in supported:
File "venv/lib64/python3.7/site-packages/semantic_version/base.py", line 642, in __contains__
return self.match(version)
File "venv/lib64/python3.7/site-packages/semantic_version/base.py", line 630, in match
return self.clause.match(version)
File "venv/lib64/python3.7/site-packages/semantic_version/base.py", line 745, in match
return all(clause.match(version) for clause in self.clauses)
File "venv/lib64/python3.7/site-packages/semantic_version/base.py", line 745, in <genexpr>
return all(clause.match(version) for clause in self.clauses)
File "venv/lib64/python3.7/site-packages/semantic_version/base.py", line 910, in match
return version >= self.target
File "venv/lib64/python3.7/site-packages/semantic_version/base.py", line 467, in __ge__
return self.precedence_key >= other.precedence_key
TypeError: '>=' not supported between instances of 'NoneType' and 'int'
Here is a code snippet to reproduce the issue:
import semantic_version
supported=semantic_version.Spec('>=1,<2')
version = '1'
version_obj = semantic_version.Version(version, partial=True)
if version_obj not in supported:
raise RuntimeError('Configuration has unsupported version of "{}".'.format(version))
It obviously has something to do with the partial version specification and it's possible that I'm not using semantic-version
correctly.
Hello
1 - Create a Django model containing a VersionField, and insert values with different versions
2 - Use an order_by clause ordering by the VersionField field
3 - The ordering is done as text, not as version numbers
One example of ordering (this is with reverse ordering): [Version('1.2.3'), Version('1.10.3'), Version('1.0.3')]
Regards
PEP 440 allows version strings like this: 0.1b2.dev3
. it would be neat to have the Version
class and the validate
function would support these when passed an option to parse with regards to that syntax.
A new feature was added in #38, we still need to add the doc :)
It would be useful to be able to do the following:
import semantic_version as sv
version = sv.Version((1,0,0))
I would be willing to take on a PR for this feature myself, if it seems reasonable.
I'm packaging python-semanticversion for Fedora, and documentation fails to build due to docs/credits.rst being a symbolic link to CREDITS which is not shipped in 2.3.1 tarball.
It's not critical, but packagers would be grateful if you fix it in the next release :)
Hi,
I created an arbitrary version and have found bug. None of these come to true. I would assume that a>b
has an outcome as True
import semantic_version
a = semantic_version.Version.coerce('0.1.2.3.4.3-beta4.5.6.7-alpha')
b = semantic_version.Version('0.1.2')
print(a > b) # False
print(a < b) # False
print(a ==b) # False
I'm getting wrong results comparing versions using partials :
print semantic_version.Version('1.2.0-beta', partial=True) > semantic_version.Version('1.2.0', partial=True)
print semantic_version.Version('1.2.0-beta', partial=True) < semantic_version.Version('1.2.0', partial=True)
print semantic_version.Version('1.2.0-beta', partial=True) == semantic_version.Version('1.2.0', partial=True)
print semantic_version.Version('1.2-beta', partial=True) > semantic_version.Version('1.2', partial=True)
print semantic_version.Version('1.2-beta', partial=True) < semantic_version.Version('1.2', partial=True)
print semantic_version.Version('1.2-beta', partial=True) == semantic_version.Version('1.2', partial=True)
print semantic_version.Version('1.2.0-beta') > semantic_version.Version('1.2.0')
print semantic_version.Version('1.2.0-beta') < semantic_version.Version('1.2.0')
print semantic_version.Version('1.2.0-beta') == semantic_version.Version('1.2.0')
False
False
True
False
False
True
False
True
False
rust utilizes wildcard in away:
* := >=0.0.0
1.* := >=1.0.0 <2.0.0
1.2.* := >=1.2.0 <1.3.0
it's definitely possible to workaround on my side, but would be very cool enhancement!
And thanks for making this library!
npm treats ^ differently for 0.x versions, see the node-semver docs: https://github.com/npm/node-semver#caret-ranges-123-025-004
(and fwiw yotta also treats it differently, treating ^ for 0.x versions as meaning exact version, as semver technically has no compatibility guarantees for 0.x versions)
(While I was checking the code i also noticed a double-return here: https://github.com/rbarrois/python-semanticversion/blob/master/semantic_version/base.py#L462-L463)
Hi,
I think there is a bug in next_major()
function when certain conditions are met:
In [32]: semantic_version.Version("3.0.0").next_major()
Out[32]: Version('4.0.0') # Correct
In [33]: semantic_version.Version("3.0-slim",partial=True).next_major()
Out[33]: Version('4.0.0') # Correct
In [34]: semantic_version.Version("3.0",partial=True).next_major()
Out[34]: Version('4.0.0') # Correct
In [31]: semantic_version.Version("3.0.0-slim").next_major()
Out[31]: Version('3.0.0') # WRONG - should be 4.0.0
In [35]: v = semantic_version.Version("3.0.0-slim")
In [36]: v.prerelease = None
In [37]: v.next_major()
Out[37]: Version('4.0.0') # Correct
Is it really a bug or am I missing something?
Thanks
The fix for #18 (2ed3d39) now causes specifications like: >=1.0.0+somebuild
to fail to parse (ValueError: Invalid requirement specification <whatever>: build numbers have no ordering.
).
I'd suggest that the correct behaviour would be to treat >=1.0.0+whatever
as equivalent to >=1.0.0
. For example:
>1.0.0+somebuild
would match: 1.0.1
, would not match: 1.0.0+somebuild
or 1.0.0+somethingelse
>=1.0.0+something
would match: 1.0.0
, 1.0.0+something
and 1.0.0+somethingelse
According to semver 2.0.0, spec rule number 10, two versions that differ only in build metadata should have the same precedence. However, cmp
of two such versions returns non-zero:
$ python
Python 2.7.6 (default, Sep 9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from semantic_version import Version
>>> cmp(Version('1.0.0'), Version('1.0.0+build'))
-1
I almost started working on a fix and pull request, but it looks from pydoc in the code that this might be intentional?
The current carat match algorithm matches pre-release versions (-alpha, -beta). NPM only considers those versions which are not pre-releases. Given that the carat match was added explicitly to mirror the NPM extension, it seems like identical behavior is desired.
For example, search for the "babel" package from semver and then use "^5.0.0" as the search term. None of the 5.0.0-betas are selected. Using python-semanticversion, they would match.
To fix this will require adjusting existing tests -- and therefore potentially breaking existing behavior.
The new constructor leveraging Python3 syntax is a breaking change and should result in a major version bump to 3.0 per SemVer2.0
I was expecting that a prerelease version, when bumped, would go up to the 'full' or release version without bumping the main version number if not needed.
Probably makes more sense if I give examples.
What I expected:
1.0.0-dev --[major]--> 1.0.0
1.0.1-dev --[major]--> 2.0.0
1.1.0-dev --[major]--> 2.0.0
1.0.0-dev --[minor]--> 1.0.0
1.0.1-dev --[minor]--> 1.1.0
1.1.0-dev --[minor]--> 1.1.0
1.0.0-dev --[patch]--> 1.0.0
1.0.1-dev --[patch]--> 1.0.1
1.1.0-dev --[patch]--> 1.1.0
What currently happens:
1.0.0-dev --[major]--> 2.0.0
1.0.1-dev --[major]--> 2.0.0
1.1.0-dev --[major]--> 2.0.0
1.0.0-dev --[minor]--> 1.1.0
1.0.1-dev --[minor]--> 1.1.0
1.1.0-dev --[minor]--> 1.2.0
1.0.0-dev --[patch]--> 1.0.1
1.0.1-dev --[patch]--> 1.0.2
1.1.0-dev --[patch]--> 1.1.1
If this a bug in the implementation, or have I missed something in the spec? Thanks!
When the module is being setup, you are defaulting to system-level encoding, which can sometimes be ascii, which fails when it parses the non-ascii character here: https://github.com/rbarrois/python-semanticversion/blob/master/semantic_version/__init__.py#L6.
Traceback (most recent call last): File "", line 17, in File "/sites/preprod/.virtual_python/build/semantic-version/setup.py", line 31, in version=get_version(PACKAGE), File "/sites/preprod/.virtual_python/build/semantic-version/setup.py", line 19, in get_version for line in f: File "/sites/preprod/.virtual_python/lib/python3.3/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 167: ordinal not in range(128) Complete output from command python setup.py egg_info: Traceback (most recent call last): File "", line 17, in File "/sites/preprod/.virtual_python/build/semantic-version/setup.py", line 31, in version=get_version(PACKAGE), File "/sites/preprod/.virtual_python/build/semantic-version/setup.py", line 19, in get_version for line in f: File "/sites/preprod/.virtual_python/lib/python3.3/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 167: ordinal not in range(128)
This is probably what you wanna do before parsing files in setup.py:
import sys
sys.setdefaultencoding("UTF-8")
An alternative fix is to set
LANG="en_us.UTF-8"
in .bashrc
of the user that does the pip install
Hi, I found that it would be nice to support the following case
In [64]: sv.Spec('>0.8.0').select([sv.Version('0.8.1')])
Out[64]:
Version('0.8.1')
In [65]: sv.Spec('>0.8').select([sv.Version('0.8.1')])
# Expected to get 0.8.1 but it returns None
I know there is version coercing, maybe we need to do the same coercing to the one in the spec ?
Thanks
I would expect this to return False
, but when comparing the versions mentioned in the title, I'm getting a True
result. Is my interpretation of the rules incorrect, or is this a bug?
Example:
>>> semantic_version.match('~=1.1.0', '1.2.0-foobar')
True
What would you think of something like:
version.bump_major()
version.bump_minor()
version.bump_patch()
Each of these would reset any lower levels in the versioning 'hierarchy'. So running version.bump_major()
on 1.0.0-prerelease+build
would result in 2.0.0
.
Per https://docs.npmjs.com/misc/semver#advanced-range-syntax, using ||
as logical-or for ranges is allowed.
Requesting to add Spec()
be aware of such initializers.
On: semantic-version==2.6.0
and python==3.6
,
Spec("1.0.0 || <=0.9.4")
throws with:
ValueError: Invalid version string: '1.0.0 || <=0.9.4'
PEP 0440 states the following:
Whitespace between a conditional operator and the following version identifier is optional, as is the whitespace around the commas.
However, currently the following fails:
Spec('== 1.4.0') # ValueError
What specification of semantic version is valid for your module?
v2.0.0 v2.0.0-rc.2 v2.0.0-rc.1
Thanks for the great project.
It appears that when django 1.7 or newer is installed, some unit tests have errors. I tested with 1.4.20, 1.5.12, and 1.6.11 which all pass.
Examples below are using a fresh python 2.7.9 virtualenv, with the stated django version, and South==1.0.2
On 1.7.8, this happens:
======================================================================
ERROR: setUpClass (tests.test_django.DbInteractingTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/mhrivnak/git/python-semanticversion/tests/test_django.py", line 182, in setUpClass
cls.old_state = DjangoTestSuiteRunner().setup_databases()
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/test/runner.py", line 109, in setup_databases
return setup_databases(self.verbosity, self.interactive, **kwargs)
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/test/runner.py", line 299, in setup_databases
serialize=connection.settings_dict.get("TEST", {}).get("SERIALIZE", True),
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/db/backends/creation.py", line 377, in create_test_db
test_flush=True,
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 93, in call_command
app_name = get_commands()[name]
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/utils/lru_cache.py", line 101, in wrapper
result = user_function(*args, **kwds)
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 73, in get_commands
for app_config in reversed(list(apps.get_app_configs())):
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/apps/registry.py", line 137, in get_app_configs
self.check_apps_ready()
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/apps/registry.py", line 124, in check_apps_ready
raise AppRegistryNotReady("Apps aren't loaded yet.")
AppRegistryNotReady: Apps aren't loaded yet.
======================================================================
ERROR: test_serialization (tests.test_django.DjangoFieldTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/mhrivnak/git/python-semanticversion/tests/test_django.py", line 97, in test_serialization
obj1, obj2 = serializers.deserialize('json', data)
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/serializers/json.py", line 81, in Deserializer
six.reraise(DeserializationError, DeserializationError(e), sys.exc_info()[2])
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/serializers/json.py", line 75, in Deserializer
for obj in PythonDeserializer(objects, **options):
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/serializers/python.py", line 93, in Deserializer
Model = _get_model(d["model"])
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/serializers/python.py", line 156, in _get_model
return apps.get_model(model_identifier)
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/apps/registry.py", line 199, in get_model
self.check_models_ready()
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/apps/registry.py", line 131, in check_models_ready
raise AppRegistryNotReady("Models aren't loaded yet.")
DeserializationError: Models aren't loaded yet.
======================================================================
ERROR: test_serialization_partial (tests.test_django.DjangoFieldTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/mhrivnak/git/python-semanticversion/tests/test_django.py", line 109, in test_serialization_partial
obj1, obj2 = serializers.deserialize('json', data)
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/serializers/json.py", line 81, in Deserializer
six.reraise(DeserializationError, DeserializationError(e), sys.exc_info()[2])
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/serializers/json.py", line 75, in Deserializer
for obj in PythonDeserializer(objects, **options):
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/serializers/python.py", line 93, in Deserializer
Model = _get_model(d["model"])
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/core/serializers/python.py", line 156, in _get_model
return apps.get_model(model_identifier)
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/apps/registry.py", line 199, in get_model
self.check_models_ready()
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/apps/registry.py", line 131, in check_models_ready
raise AppRegistryNotReady("Models aren't loaded yet.")
DeserializationError: Models aren't loaded yet.
======================================================================
ERROR: test_freezing_app (tests.test_django.SouthTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/mhrivnak/git/python-semanticversion/tests/test_django.py", line 147, in test_freezing_app
frozen = south.creator.freezer.freeze_apps('django_test_app')
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/south/creator/freezer.py", line 26, in freeze_apps
for model in models.get_models(models.get_app(app)):
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/db/models/__init__.py", line 54, in alias
return getattr(loading, function_name)(*args, **kwargs)
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/apps/registry.py", line 372, in get_app
models_module = self.get_app_config(app_label).models_module
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/apps/registry.py", line 146, in get_app_config
self.check_apps_ready()
File "/home/mhrivnak/pythons/semver-d17/local/lib/python2.7/site-packages/django/apps/registry.py", line 124, in check_apps_ready
raise AppRegistryNotReady("Apps aren't loaded yet.")
AppRegistryNotReady: Apps aren't loaded yet.
----------------------------------------------------------------------
Ran 57 tests in 0.027s
FAILED (errors=4, skipped=1)
And on 1.8.2, this...
$ python setup.py test
running test
running egg_info
writing semantic_version.egg-info/PKG-INFO
writing top-level names to semantic_version.egg-info/top_level.txt
writing dependency_links to semantic_version.egg-info/dependency_links.txt
reading manifest file 'semantic_version.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
no previously-included directories found matching 'docs/_build'
writing manifest file 'semantic_version.egg-info/SOURCES.txt'
running build_ext
Traceback (most recent call last):
File "setup.py", line 58, in <module>
test_suite='tests',
File "/usr/lib/python2.7/distutils/core.py", line 151, in setup
dist.run_commands()
File "/usr/lib/python2.7/distutils/dist.py", line 953, in run_commands
self.run_command(cmd)
File "/usr/lib/python2.7/distutils/dist.py", line 972, in run_command
cmd_obj.run()
File "/home/mhrivnak/pythons/semver/local/lib/python2.7/site-packages/setuptools/command/test.py", line 142, in run
self.with_project_on_sys_path(self.run_tests)
File "/home/mhrivnak/pythons/semver/local/lib/python2.7/site-packages/setuptools/command/test.py", line 122, in with_project_on_sys_path
func()
File "/home/mhrivnak/pythons/semver/local/lib/python2.7/site-packages/setuptools/command/test.py", line 163, in run_tests
testRunner=self._resolve_as_ep(self.test_runner),
File "/usr/lib/python2.7/unittest/main.py", line 94, in __init__
self.parseArgs(argv)
File "/usr/lib/python2.7/unittest/main.py", line 149, in parseArgs
self.createTests()
File "/usr/lib/python2.7/unittest/main.py", line 158, in createTests
self.module)
File "/usr/lib/python2.7/unittest/loader.py", line 130, in loadTestsFromNames
suites = [self.loadTestsFromName(name, module) for name in names]
File "/usr/lib/python2.7/unittest/loader.py", line 103, in loadTestsFromName
return self.loadTestsFromModule(obj)
File "/home/mhrivnak/pythons/semver/local/lib/python2.7/site-packages/setuptools/command/test.py", line 37, in loadTestsFromModule
tests.append(self.loadTestsFromName(submodule))
File "/usr/lib/python2.7/unittest/loader.py", line 100, in loadTestsFromName
parent, obj = obj, getattr(obj, part)
AttributeError: 'module' object has no attribute 'test_django'
The problem on 1.8.2 appears to be the result of this import failing: https://github.com/rbarrois/python-semanticversion/blob/v2.4.1/tests/test_django.py#L176
That class was removed as of django 1.8: https://docs.djangoproject.com/en/1.8/releases/1.8/
If you fix that import to instead use django.test.runner.DiscoverRunner, then the same errors from 1.7.8 appear.
catching the ValueError
of, let's say Version('we12we.12we.23')
, doesn't seem to be very performant
so maybe you could add a similar implementation of the following code to the public API?
def isValid(version):
try:
Version(version)
except ValueError:
return False
return True
I can make a specifier with '~1'
but when doing a match
or select
on it, it causes a TypeError
. I tried to provide the relevant details below, thanks!
Successfully installed semantic-version-2.6.0
(sv) awc:env$ python3
Python 3.6.8 (default, Jan 27 2019, 09:00:23)
[GCC 8.2.1 20181215 (Red Hat 8.2.1-6)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import semantic_version
>>> v = semantic_version.Version('1.1.2')
>>> s_major = semantic_version.Spec('~1')
>>> s_minor = semantic_version.Spec('~1.1')
>>> s_minor.match(v)
True
>>> s_major.match(v)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/awc/code/env/sv/lib/python3.6/site-packages/semantic_version/base.py", line 515, in match
return all(spec.match(version) for spec in self.specs)
File "/home/awc/code/env/sv/lib/python3.6/site-packages/semantic_version/base.py", line 515, in <genexpr>
return all(spec.match(version) for spec in self.specs)
File "/home/awc/code/env/sv/lib/python3.6/site-packages/semantic_version/base.py", line 478, in match
return self.spec <= version < self.spec.next_minor()
File "/home/awc/code/env/sv/lib/python3.6/site-packages/semantic_version/base.py", line 104, in next_minor
'.'.join(str(x) for x in [self.major, self.minor + 1, 0]))
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
>>> s_major
<Spec: (<SpecItem: ~ Version('1', partial=True)>,)>
v1 = semantic_version.Version('1.1.1-pre+build')
v2 = v1.next_patch()
str(v2)
'1.1.1'
See e.g. https://github.com/rbarrois/python-semanticversion/blob/master/semantic_version/base.py#L94 -- it's implementation specific as to whether any given int is the same actual object as any other.
It happens to be this will work fine on CPython at the minute, which is unlikely to change its behavior, but that's not guaranteed across implementations (and there's no disadvantage to using == :).
I noticed that this library has support for npm's range syntax.
Is the intention to support any sufficiently prominent syntax?
E.g. SpecItem("~>2.1.1")
fails. This is Ruby's pessimistic operator, used in Gemfile extensively, and also used by D.
Another one is (,1.0]
and similar used by Maven and Ivy (and most of the Java world), and also "Visual Studio" (and many many friends)
Hi!
Here's an example:
Spec('~=1.5.6') # results in a ValueError
https://www.python.org/dev/peps/pep-0440/#compatible-release
The current __repr__
implementation hard codes Version
as the class name. This means any subclasses will be represented with Version
instead of their class name. Would it be feasible to change this so the class name was shown instead of the hard coded Version
.
I'm willing to work on this, and in fact, already have a commit staged up in a fork, if this change is acceptable.
A common convention I have seen across various projects is to prefix the semantic version string with a v
(e.g. v1.2.3
). I was wondering if there would be interest in supporting it here. I would believe the scope to be fairly limited (allow users to specify strings prefixed with v
when instantiating and make the str
of the Version
class include a v
prefix, if appropriate).
I respect this deviates from the semver standards and would understand if you declined the request. I was unsure how you were balancing strictly following the semver standards versus user convenience in this library.
The development team at my employer uses this library a ton and has adapted the current version to accept v
prefixes. We would be willing to share our implementation if there was an appetite for supporting this customization, but are, of course, open to other implementations and suggestions.
Thank you again for all of your work on this project. We have found it very useful and use it almost everywhere.
I was able to install 2.2.1 fine, but had this issue when installing 2.2.2.
Downloading semantic_version-2.2.2.tar.gz
Running setup.py egg_info for package semantic-version
Traceback (most recent call last):
File "<string>", line 16, in <module>
File "/private/tmp/pip_build_root/semantic-version/setup.py", line 58, in <module>
test_suite='tests',
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/distutils/core.py", line 112, in setup
_setup_distribution = dist = klass(attrs)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/setuptools/dist.py", line 260, in __init__
self.fetch_build_eggs(attrs.pop('setup_requires'))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/setuptools/dist.py", line 284, in fetch_build_eggs
parse_requirements(requires), installer=self.fetch_build_egg
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 569, in resolve
raise VersionConflict(dist,req) # XXX put more info here
pkg_resources.VersionConflict: (setuptools 0.6c12dev-r88846 (/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python), Requirement.parse('setuptools>=0.8'))
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 16, in <module>
File "/private/tmp/pip_build_root/semantic-version/setup.py", line 58, in <module>
test_suite='tests',
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/distutils/core.py", line 112, in setup
_setup_distribution = dist = klass(attrs)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/setuptools/dist.py", line 260, in __init__
self.fetch_build_eggs(attrs.pop('setup_requires'))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/setuptools/dist.py", line 284, in fetch_build_eggs
parse_requirements(requires), installer=self.fetch_build_egg
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/pkg_resources.py", line 569, in resolve
raise VersionConflict(dist,req) # XXX put more info here
pkg_resources.VersionConflict: (setuptools 0.6c12dev-r88846 (/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python), Requirement.parse('setuptools>=0.8'))
----------------------------------------
Cleaning up...
The Readme suggests that
semantic_version.Version('0.1.1').build
should be []
, but in version 2.6.0 of semantic_version it is instead ()
.
This makes little practical difference in most cases, except when you do something like
if v.build == []:
...
which will never work.
If I pass '2.0' to the Version
constructor, I get a ValueError
regardless of whether I specified partial=True
or not. I suspect that this is because version_re
and partial_version_re
are completely identical.
If this is intended behavior, then the documentation should be fixed to reflect that.
I'm not really sure who is responsible for patching packages in pypi so I am going to start by posting the bug here. The semantic_version package for v2.2.1 contained in pypi has a symbolic link from ChangeLog at the top level to doc/changelog.rst but there is no doc/ directory in the package so I get the warning message,
In the tar file /tmp/pip-BEK853-unpack/semantic_version-2.2.1.tar.gz the member semantic_version-2.2.1/ChangeLog is invalid: "linkname 'semantic_version-2.2.1/doc/changelog.rst' not found"
This does not prevent the package from being installed but it would be nice to not have this message displayed.
We are currently writing an API for which will be accessed with PHP and/or JS. Both have a semver package that supports ranges, however they split the ranges using spaces rather than spaces, e.g.
>=1.2.3 <2.0.0
and not
>=1.2.3,<2.0.0
AFAIK ranges are not part of semver, but it would be awesome to be compatible.
There are two ways I can think of fixing this:
I could create a PR if you want, it seems these are the only lines that have to be adjusted:
What do you think?
Related:
Shouldn't partial versions be compared too?
At the moment Version('1.0', partial=True) == Version('1.0.5', partial=True)
is True
.
According to NPM semver documentation .x behaviour is supposed to act like:
Patch releases: 1.0 or 1.0.x or ~1.0.4
Minor releases: 1 or 1.x or ^1.0.4
Major releases: * or x
However Spec class doesn't parse versions with 'x' instead of a digit
Hi there - running on Django 1.8. I have a model that has an optional VersionField (null=True, blank=True). If I save the model, I can see in the database that the value is stored as the string 'None', which then subsequently fails on rehydration:
Traceback (most recent call last):
File "/Projects/python-semanticversion/tests/test_django.py", line 56, in test_null_version
self.assertRaises(ValueError, models.PartialVersionModel.objects.get(id=obj.id))
File "/Users/hugo/.virtualenvs/semver/lib/python2.7/site-packages/django/db/models/manager.py", line 127, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/Users/hugo/.virtualenvs/semver/lib/python2.7/site-packages/django/db/models/query.py", line 328, in get
num = len(clone)
File "/Users/hugo/.virtualenvs/semver/lib/python2.7/site-packages/django/db/models/query.py", line 144, in __len__
self._fetch_all()
File "/Users/hugo/.virtualenvs/semver/lib/python2.7/site-packages/django/db/models/query.py", line 965, in _fetch_all
self._result_cache = list(self.iterator())
File "/Users/hugo/.virtualenvs/semver/lib/python2.7/site-packages/django/db/models/query.py", line 255, in iterator
obj = model_cls.from_db(db, init_list, row[model_fields_start:model_fields_end])
File "/Users/hugo/.virtualenvs/semver/lib/python2.7/site-packages/django/db/models/base.py", line 489, in from_db
new = cls(*values)
File "/Users/hugo/.virtualenvs/semver/lib/python2.7/site-packages/django/db/models/base.py", line 410, in __init__
setattr(self, field.attname, val)
File "/Users/hugo/.virtualenvs/semver/lib/python2.7/site-packages/django/db/models/fields/subclassing.py", line 44, in __set__
obj.__dict__[self.field.name] = self.field.to_python(value)
File "/Users/hugo/Projects/src/github.com/yunojuno/python-semanticversion/semantic_version/django_fields.py", line 61, in to_python
return base.Version(value, partial=self.partial)
File "/Users/hugo/Projects/src/github.com/yunojuno/python-semanticversion/semantic_version/base.py", line 75, in __init__
major, minor, patch, prerelease, build = self.parse(version_string, partial)
File "/Users/hugo/Projects/src/github.com/yunojuno/python-semanticversion/semantic_version/base.py", line 192, in parse
raise ValueError('Invalid version string: %r' % version_string)
ValueError: Invalid version string: u'None'
You can test this with the following test:
def test_optional_field(self):
"""Test storing a null value in optional VersionField."""
obj = models.PartialVersionModel()
obj.save()
self.assertIsNone(obj.optional)
self.assertRaises(ValueError, models.PartialVersionModel.objects.get, id=obj.id)
This makes some sense, as the VersionField.to_python
method doesn't check for 'None':
def to_python(self, value):
"""Converts any value to a base.Version field."""
if value is None or value == '':
return value
if isinstance(value, base.Version):
return value
if self.coerce:
return base.Version.coerce(value, partial=self.partial)
else:
return base.Version(value, partial=self.partial)
Possibly looking at the BaseSemVerField.get_prep_value
method, which just str's the object value:
def get_prep_value(self, obj):
return str(obj)
This would turn None
into 'None'
The latest version on http://semver.org is 2.0.0. Let’s ditch that rc1
for this module’s semver conformance! :)
Python versions: 3.7.4 and 3.6.9
OS: Windows 10
I've found interesting behavior in version 2.8.1 which I believe is a bug.
>>> # Expected, good
>>> Version("1.0.0") in Spec("==1.0.0")
True
>>> Version("1.0.0") in Spec("!=1.0.0")
False
>>> # Unexpected, probably a bug
>>> # Expected that these would match above without partial
>>> Version("1.0.0", partial=True) in Spec("==1.0.0")
True
>>> Version("1.0.0", partial=True) in Spec("!=1.0.0")
True
>>> # Unexpected, probably a bug
>>> # Expected that these would match above without partial
>>> Version("1", partial=True) in Spec("==1.0.0")
False
>>> Version("1", partial=True) in Spec("!=1.0.0")
True
In version 2.6.0, the partial
keyword argument seemed to add missing minor / patch numbers as 0
. It seems to be doing something different now.
>>> Version("1.0.0") == Version("1.0.0", partial=True)
True
>>> Version("1.0.0") != Version("1.0.0", partial=True)
True
>>> Version("1.0.0") == Version("1", partial=True)
False
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.