Commit bcf3fe03 authored by Craig Weber's avatar Craig Weber
Browse files

Initial commit

parents
# Created by https://www.gitignore.io/api/sublimetext,osx,linux,python,django
### SublimeText ###
# cache files for sublime text
*.tmlanguage.cache
*.tmPreferences.cache
*.stTheme.cache
# workspace files are user-specific
*.sublime-workspace
# project files should be checked into the repository, unless a significant
# proportion of contributors will probably not be using SublimeText
# *.sublime-project
# sftp configuration file
sftp-config.json
### OSX ###
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Linux ###
*~
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
env3/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
# Translations
*.mo
*.pot
# Django stuff:
*.log
# Sphinx documentation
docs/_build/
# PyBuilder
target/
### Django ###
*.log
*.pot
*.pyc
__pycache__/
local_settings.py
image: python:latest
before_script:
- pip install -r requirements.txt
stages:
- build
- test
run_unittests:
stage: test
script:
- python -m unittest discover
language: python
python:
- "2.7"
- "3.3"
- "3.4"
- "3.5"
- "3.5-dev"
install:
- pip install -r requirements.txt
script: python -m unittest discover
Copyright (c) 2015, Craig Weber <crgwbr@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
\ No newline at end of file
include *.txt *.md *.rst
recursive-include docs *.txt *.md *.rst
\ No newline at end of file
python-versiontag
=============================
.. image:: https://img.shields.io/pypi/v/versiontag.svg
:target: https://pypi.python.org/pypi/versiontag
.. image:: https://img.shields.io/pypi/dm/versiontag.svg
:target: https://pypi.python.org/pypi/versiontag
.. image:: https://travis-ci.org/crgwbr/python-versiontag.svg
:target: https://travis-ci.org/crgwbr/python-versiontag
What?
-----
This is an ultra-simple library design to make accessing the current version number of
your software easy.
Why?
----
Version numbers are all too often duplicated among setup.py, git tags, and others sources
of truth. This library makes it possible to consolidate on git tags as a single source of
truth regarding version numbers.
How?
----
Install python-versiontag using pip.
::
pip install versiontag
Add version.txt to your .gitignore file.
::
echo "version.txt" >> .gitignore
Add versiontag to your package's setup.py file.
::
from versiontag import get_version, cache_git_tag
# This caches for version in version.txt so that it is still accessible if
# the .git folder disappears, for example, after the slug is built on Heroku.
cache_git_tag()
setup(name='My Package',
version=get_version(pypi=True),
...
Use versiontag where ever you want to access the version number.
::
>>> from versiontag import get_version
>>> print( get_version() )
'r1.2.3'
#!/usr/bin/env python
import codecs
import os.path
from distutils.core import setup
packages = [
'versiontag',
]
def fpath(name):
return os.path.join(os.path.dirname(__file__), name)
def read(fname):
return codecs.open(fpath(fname), encoding='utf-8').read()
setup(
name='versiontag',
version='0.1.0',
description='Simple git tag based version numbers',
long_description=read(fpath('README.rst')),
author='Craig Weber',
author_email='crgwbr@gmail.com',
url='https://github.com/crgwbr/python-versiontag',
packages=packages,
license='LICENSE.md'
)
#!/usr/bin/env bash
python3 -m unittest discover
import subprocess
import tempfile
import unittest
import os
import versiontag
def silent_call(*args):
with open(os.devnull, 'wb') as devnull:
subprocess.check_call(args, stdout=devnull, stderr=devnull)
class VersionTagTest(unittest.TestCase):
def setUp(self):
self.repo_dir = tempfile.TemporaryDirectory()
os.chdir(self.repo_dir.name)
def tearDown(self):
self.repo_dir.cleanup()
def test_no_repo(self):
"""No repo returns default version"""
self.assertEqual(versiontag.get_version(), 'r0.0.0')
self.assertEqual(versiontag.get_version(pypi=True), '0.0.0')
def test_no_commits(self):
"""No tags returns default version"""
silent_call('git', 'init')
self.assertEqual(versiontag.get_version(), 'r0.0.0')
self.assertEqual(versiontag.get_version(pypi=True), '0.0.0')
def test_head_is_tagged(self):
"""Should return most recent tag"""
silent_call('git', 'init')
silent_call('git', 'commit', '--allow-empty', '-m', 'Initial Commit')
silent_call('git', 'tag', 'r1.2.3')
self.assertEqual(versiontag.get_version(), 'r1.2.3')
self.assertEqual(versiontag.get_version(pypi=True), '1.2.3')
def test_head_is_post_release(self):
"""Subsequent commits show as post releases"""
silent_call('git', 'init')
silent_call('git', 'commit', '--allow-empty', '-m', 'Initial Commit')
silent_call('git', 'tag', 'r1.2.3')
silent_call('git', 'commit', '--allow-empty', '-m', 'another commit')
self.assertTrue( versiontag.get_version().startswith('r1.2.3-1-') )
self.assertEqual(versiontag.get_version(pypi=True), '1.2.3-1')
silent_call('git', 'commit', '--allow-empty', '-m', 'another commit')
self.assertTrue(versiontag.get_version().startswith('r1.2.3-2-'))
self.assertEqual(versiontag.get_version(pypi=True), '1.2.3-2')
silent_call('git', 'tag', 'r1.2.4')
self.assertTrue( versiontag.get_version().startswith('r1.2.4') )
self.assertEqual(versiontag.get_version(pypi=True), '1.2.4')
def test_caching_with_removed_git_folder(self):
"""Caching continues to return release even if git repository disappears"""
silent_call('git', 'init')
silent_call('git', 'commit', '--allow-empty', '-m', 'Initial Commit')
silent_call('git', 'tag', 'r1.2.3')
versiontag.cache_git_tag()
self.assertTrue( versiontag.get_version().startswith('r1.2.3') )
self.assertEqual(versiontag.get_version(pypi=True), '1.2.3')
silent_call('rm', '-rf', os.path.join(self.repo_dir.name, '.git'))
self.assertTrue( versiontag.get_version().startswith('r1.2.3') )
self.assertEqual(versiontag.get_version(pypi=True), '1.2.3')
# Remove the version cache file and get_version goes back to return the default
silent_call('rm', os.path.join(self.repo_dir.name, 'version.txt'))
self.assertEqual(versiontag.get_version(), 'r0.0.0')
self.assertEqual(versiontag.get_version(pypi=True), '0.0.0')
import os
import subprocess
import re
__default_version__ = 'r0.0.0'
def __get_git_tag():
with open(os.devnull, 'wb') as devnull:
version = subprocess.check_output(['git', 'describe', '--tags'], stderr=devnull)
version = version.rstrip()
if hasattr(version, 'decode'):
version = version.decode('utf-8')
return version
def __get_cache_file():
return os.path.join(os.getcwd(), 'version.txt')
def cache_git_tag():
try:
version = __get_git_tag()
except:
version = __default_version__
with open(__get_cache_file(), 'w') as vf:
vf.write(version)
return version
def get_version(pypi=False):
version = __default_version__
try:
with open(__get_cache_file(), 'r') as vf:
version = vf.read().strip()
except:
pass
try:
version = __get_git_tag()
except:
pass
if pypi:
# Convert to pypi valid version:
# 1. Drop the r prefix we use on git tags: r1.0.1-12-geaea7b6 => 1.0.1-12-geaea7b6
# 2. Drop the commit hash from the end: 1.0.1-12-geaea7b6 => 1.0.1-12
v = re.search('^[r,v]{0,1}(([0-9\.]+)(\-[0-9]+)?)(\-.+)?$', version)
version = v.group(1) if v else __default_version__
return version
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment