Repository: pypa/setuptools_scm

Issue:
document/gracefully handle when users create own dev versions in tags
I had already created the tag "0.15.0.dev0" of my package, before uploading that development version to PyPI. I made some further progress and wanted to release a new development version, and so I created the tag "0.15.0.dev1". It seems I've found out the hard way though (doesn't seem to be documented?) that dev versions greater than 0 are currently unsupported – I'm now hitting this AssertionError:

https://github.com/pypa/setuptools_scm/blob/46df188a54e3eb2b0dfb93dbae59fb23249fbcce/setuptools_scm/version.py#L124

(``assert tail == '0', 'own dev numbers are unsupported'``)

If I comment out that assertion, `guess_next_dev_version` works like a charm. Could you please explain why that assertion is there, whether there are any plans to add support for "own dev numbers" (seems like totally valid usage, no?), and what you recommend doing in the meantime?

Thanks 😊

Discussion:

Patch:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index dbce446..c570357 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -12,6 +12,7 @@ v4.2.0
 * add a version_tuple to write_to templates
 * fix #321: add suppport for the ``SETUPTOOLS_SCM_PRETEND_VERSION_FOR_${DISTRIBUTION_NAME}`` env var to target the pretend key
 * fix #142: clearly list supported scm
+* fix #213: better error message for non-zero dev numbers in tags
 
 
 v4.1.2
diff --git a/README.rst b/README.rst
index a826b1f..f9193c1 100644
--- a/README.rst
+++ b/README.rst
@@ -277,6 +277,7 @@ distance and not clean:
 The next version is calculated by adding ``1`` to the last numeric component of
 the tag.
 
+
 For Git projects, the version relies on `git describe <https://git-scm.com/docs/git-describe>`_,
 so you will see an additional ``g`` prepended to the ``{revision hash}``.
 
@@ -507,6 +508,8 @@ Version number construction
     :guess-next-dev: Automatically guesses the next development version (default).
         Guesses the upcoming release by incrementing the pre-release segment if present,
         otherwise by incrementing the micro segment. Then appends :code:`.devN`.
+        In case the tag ends with ``.dev0`` the version is not bumped
+        and custom ``.devN`` versions will trigger a error.
     :post-release: generates post release versions (adds :code:`.postN`)
     :python-simplified-semver: Basic semantic versioning. Guesses the upcoming release
         by incrementing the minor segment and setting the micro segment to zero if the
diff --git a/src/setuptools_scm/version.py b/src/setuptools_scm/version.py
index 40eadc8..f97dca5 100644
--- a/src/setuptools_scm/version.py
+++ b/src/setuptools_scm/version.py
@@ -230,7 +230,13 @@ def _bump_dev(version):
         return
 
     prefix, tail = version.rsplit(".dev", 1)
-    assert tail == "0", "own dev numbers are unsupported"
+    if tail != "0":
+        raise ValueError(
+            "choosing custom numbers for the `.devX` distance "
+            "is not supported.\n "
+            "The {version} can't be bumped\n"
+            "Please drop the tag or create a new supported one".format(version=version)
+        )
     return prefix
 
 
diff --git a/tox.ini b/tox.ini
index 5f1143e..030dbd4 100644
--- a/tox.ini
+++ b/tox.ini
@@ -48,6 +48,7 @@ setenv = SETUPTOOLS_SCM_PRETEND_VERSION=2.0
 deps=
     check-manifest
     docutils
+    pygments
 commands=
     rst2html.py README.rst {envlogdir}/README.html --strict []
     check-manifest


Test patch:
diff --git a/testing/test_version.py b/testing/test_version.py
index 722b8e8..ee13801 100644
--- a/testing/test_version.py
+++ b/testing/test_version.py
@@ -120,6 +120,22 @@ def test_no_guess_version(version, expected_next):
     assert computed == expected_next
 
 
+def test_bump_dev_version_zero():
+    guess_next_version("1.0.dev0")
+
+
+def test_bump_dev_version_nonzero_raises():
+    with pytest.raises(ValueError) as excinfo:
+        guess_next_version("1.0.dev1")
+
+    assert str(excinfo.value) == (
+        "choosing custom numbers for the `.devX` distance "
+        "is not supported.\n "
+        "The 1.0.dev1 can't be bumped\n"
+        "Please drop the tag or create a new supported one"
+    )
+
+
 @pytest.mark.parametrize(
     "tag, expected",
     [