Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 2 additions & 17 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,10 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ['3.9', 'pypy3.9', '3.10', 'pypy3.10', '3.11', '3.12', '3.13']
python-version: ['3.10', '3.11', 'pypy3.11', '3.12', '3.13', '3.14']
exclude:
- os: macos-latest
python-version: '3.9'
- os: macos-latest
python-version: 'pypy3.9'
- os: macos-latest
python-version: '3.10'
- os: macos-latest
python-version: 'pypy3.10'
include:
- os: macos-13
python-version: '3.9'
- os: macos-13
python-version: 'pypy3.9'
- os: macos-13
python-version: '3.10'
- os: macos-13
python-version: 'pypy3.10'
steps:
- uses: actions/checkout@v5
with:
Expand Down Expand Up @@ -65,7 +50,7 @@ jobs:
fetch-depth: 0
- uses: actions/setup-python@v6
with:
python-version: '3.13'
python-version: '3.14'
- run: pip install build~=1.2
- run: python -m build
- uses: pypa/gh-action-pypi-publish@release/v1
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ARG PYTHON_VERSION="3.13"
ARG PYTHON_VERSION="3.14"

FROM python:${PYTHON_VERSION}

Expand Down
2 changes: 1 addition & 1 deletion NOTICE
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version-query
Copyright (c) 2017-2025 Mateusz Bysiek https://mbdevpl.github.io/
Copyright (c) 2017-2026 Mateusz Bysiek https://mbdevpl.github.io/
Copyright (c) 2020 John Vandenberg https://github.com/jayvdb

Licensed under the Apache License, Version 2.0 (the "License");
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,7 @@ using version-query without any issues.
Requirements
============

Python version 3.9 or later.
Python version 3.10 or later.

Python libraries as specified in `<requirements.txt>`_.

Expand Down
3 changes: 2 additions & 1 deletion requirements_ci.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ coverage ~= 7.2
flake518 ~= 1.6
mypy ~= 1.5
pydocstyle ~= 6.3
pylint ~= 3.1
pylint ~= 3.3; python_version < '3.10'
pylint ~= 4.0; python_version >= '3.10'
twine ~= 6.1
types-setuptools >= 67.4
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ class Package(boilerplates.setup.Package):
'Operating System :: MacOS',
'Operating System :: Microsoft :: Windows',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
'Programming Language :: Python :: 3.14',
'Programming Language :: Python :: 3 :: Only',
'Topic :: Software Development :: Version Control',
'Topic :: Software Development :: Version Control :: Git',
Expand Down
3 changes: 3 additions & 0 deletions test/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,6 @@ class TestsLogging(Logging):


TestsLogging.configure()
logging.getLogger('version_query.git_query').setLevel(logging.INFO)
logging.getLogger('version_query.parser').setLevel(logging.INFO)
logging.getLogger('version_query.version').setLevel(logging.INFO)
16 changes: 16 additions & 0 deletions test/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import contextlib
import io
import logging
import os
import runpy
import sys
import unittest
Expand Down Expand Up @@ -42,20 +43,29 @@ class Tests(unittest.TestCase):
def test_not_as_main(self): # pylint: disable = no-self-use
run_module('version_query', run_name='__not_main__')

@unittest.skipUnless(
os.environ.get('TEST_CLI') or os.environ.get('CI'),
'skipping CLI test which breaks test logging')
def test_help(self):
sio = io.StringIO()
with contextlib.redirect_stderr(sio), preserve_logger_level('version_query'), \
self.assertRaises(SystemExit):
run_module('version_query')
_LOG.info('%s', sio.getvalue())

@unittest.skipUnless(
os.environ.get('TEST_CLI') or os.environ.get('CI'),
'skipping CLI test which breaks test logging')
def test_bad_usage(self):
sio = io.StringIO()
with contextlib.redirect_stderr(sio), preserve_logger_level('version_query'), \
self.assertRaises(ValueError):
run_module('version_query', '-p', '-i', '.')
_LOG.info('%s', sio.getvalue())

@unittest.skipUnless(
os.environ.get('TEST_CLI') or os.environ.get('CI'),
'skipping CLI test which breaks test logging')
def test_here(self):
sio = io.StringIO()
with temporarily_set_logger_level('version_query', logging.ERROR), \
Expand All @@ -64,6 +74,9 @@ def test_here(self):
self.assertEqual(sio.getvalue().rstrip(), query_caller().to_str())
self.assertEqual(sio.getvalue().rstrip(), query_version_str())

@unittest.skipUnless(
os.environ.get('TEST_CLI') or os.environ.get('CI'),
'skipping CLI test which breaks test logging')
def test_increment_here(self):
sio = io.StringIO()
with temporarily_set_logger_level('version_query', logging.ERROR), \
Expand All @@ -72,6 +85,9 @@ def test_increment_here(self):
self.assertEqual(sio.getvalue().rstrip(),
query_caller().increment(VersionComponent.Patch).to_str())

@unittest.skipUnless(
os.environ.get('TEST_CLI') or os.environ.get('CI'),
'skipping CLI test which breaks test logging')
def test_predict_here(self):
sio = io.StringIO()
with temporarily_set_logger_level('version_query', logging.ERROR), \
Expand Down
14 changes: 14 additions & 0 deletions test/test_git.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import itertools
import logging
import os
import platform
import unittest

Expand Down Expand Up @@ -79,6 +80,19 @@ def test_nonversion_tags(self):
version.local = (f'git{self.repo_head_hexsha}',)
self.assertEqual(version, upcoming_version)

def test_too_short_version_tag(self):
self.git_commit_new_file()
self.repo.create_tag('v1.0')
self.git_commit_new_file()
self.repo.create_tag('v')
self.git_commit_new_file()
self.repo.create_tag('ver')
current_version = query_git_repo(self.repo_path)
_LOG.debug('current version is %s', current_version)
self.assertEqual(current_version.to_str(), '1.0')

@unittest.skipUnless(
os.environ.get('TEST_LONG') or os.environ.get('CI'), 'skipping long test')
def test_too_long_no_tag(self):
self.git_commit_new_file()
self.repo.create_tag('v4.0.0')
Expand Down
6 changes: 6 additions & 0 deletions test/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ def _query_test_case(self, paths, query_function):
else:
_LOG.debug('%s: %s', path, version)

@unittest.skipUnless(
os.environ.get('TEST_LONG') or os.environ.get('CI'), 'skipping long test')
def test_query_git_repo(self):
self._check_examples_count('git repo', GIT_REPO_EXAMPLES)
_LOG.debug('testing query_git_repo() on %i repositories', len(GIT_REPO_EXAMPLES))
self._query_test_case(GIT_REPO_EXAMPLES, query_git_repo)

def test_predict_caller_bad(self):
Expand All @@ -81,7 +84,10 @@ def test_predict_caller_bad(self):
_LOG.warning('removed %s from sys.path', project_path_str)
project_file_path.unlink()

@unittest.skipUnless(
os.environ.get('TEST_LONG') or os.environ.get('CI'), 'skipping long test')
def test_predict_git_repo(self):
_LOG.debug('testing predict_git_repo() on %i repositories', len(GIT_REPO_EXAMPLES))
self._query_test_case(GIT_REPO_EXAMPLES, predict_git_repo)

@unittest.skipIf(not METADATA_JSON_EXAMPLE_PATHS, 'no "metadata.json" files found')
Expand Down
15 changes: 6 additions & 9 deletions test/test_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import unittest

import packaging.version
import pkg_resources
import semver

from version_query.version import VersionComponent, Version
Expand All @@ -23,13 +22,12 @@ def test_from_str(self):
for version_str, (args, kwargs) in STR_CASES.items():
version_tuple = case_to_version_tuple(args, kwargs)
with self.subTest(version_str=version_str, version_tuple=version_tuple):

py_version = \
pkg_resources.parse_version(version_str)
packaging.version.parse(version_str)
_LOG.debug('packaging parsed version string %s into %s: %s',
repr(version_str), type(py_version), py_version)
# self.assertIsInstance(
# py_version, packaging.version.Version, msg=(type(py_version), py_version))
self.assertIsInstance(
py_version, packaging.version.Version, msg=(type(py_version), py_version))

try:
sem_version = semver.VersionInfo.parse(version_str)
Expand All @@ -38,8 +36,8 @@ def test_from_str(self):
else:
_LOG.debug('semver parsed version string %s into %s: %s',
repr(version_str), type(sem_version), sem_version)
# self.assertIsInstance(
# sem_version, semver.VersionInfo, msg=(type(sem_version), sem_version))
self.assertIsInstance(
sem_version, semver.VersionInfo, msg=(type(sem_version), sem_version))

self.assertEqual(Version.from_str(version_str).to_tuple(), version_tuple)

Expand All @@ -59,7 +57,7 @@ def test_from_py_version(self):
py_version = packaging.version.Version(version_str)
self.assertEqual(Version.from_py_version(py_version).to_tuple(),
version_tuple, py_version)
py_version_setuptools = pkg_resources.parse_version(version_str)
py_version_setuptools = packaging.version.parse(version_str)
self.assertEqual(Version.from_py_version(py_version_setuptools).to_tuple(),
version_tuple, py_version_setuptools)

Expand All @@ -71,7 +69,6 @@ def test_to_py_version(self):
py_version = packaging.version.Version(version_str)
self.assertEqual(version.to_py_version(), py_version,
msg=(version.to_py_version(), py_version))
# py_version_setuptools = pkg_resources.parse_version(version_str)

def test_from_sem_version(self):
for version_str, (args, kwargs) in COMPATIBLE_STR_CASES.items():
Expand Down
10 changes: 7 additions & 3 deletions version_query/git_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,31 @@
def preprocess_git_version_tag(tag: str):
"""Remove a prefix from a version tag."""
if tag.startswith('ver'):
if len(tag) == 3:
raise ValueError(f'the tag "{tag}" does not contain any version information')
return tag[3:]
if tag.startswith('v'):
if len(tag) == 1:
raise ValueError(f'the tag "{tag}" does not contain any version information')
return tag[1:]
if tag and tag[0] in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9'):
return tag
raise ValueError(f'given tag "{tag}" does not appear to be a version tag')
raise ValueError(f'the tag "{tag}" does not appear to be a version tag')


def _git_version_tags(repo: git.Repo) -> t.Mapping[git.Tag, Version]:
versions = {}
for tag in repo.tags:
try:
tag_str = preprocess_git_version_tag(str(tag))
tag_str = preprocess_git_version_tag(tag.name)
except ValueError:
_LOG.debug('%s: ignoring non-version tag %s', repo, tag)
continue
try:
versions[tag] = Version.from_str(tag_str)
except ValueError:
# except packaging.version.InvalidVersion:
_LOG.warning('%s: failed to convert %s to version', repo, tag_str)
_LOG.warning('%s: failed to convert %s (%r) to version', repo, tag.name, tag_str)
continue
return versions

Expand Down
2 changes: 1 addition & 1 deletion version_query/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def main(args=None, namespace=None) -> None:
description='''Tool for querying current versions of Python packages. Use LOGGING_LEVEL
environment variable to adjust logging level.''',
epilog=make_copyright_notice(
2017, 2025, author='the contributors', url='https://github.com/mbdevpl/version-query'),
2017, 2026, author='the contributors', url='https://github.com/mbdevpl/version-query'),
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
add_version_option(parser, VERSION)

Expand Down
Loading