bump version number, Merge pull request #44 from tqdm/lrq3000-makefile

This commit is contained in:
Casper da Costa-Luis 2015-11-01 16:15:41 +00:00
commit 8a11ecf554
9 changed files with 321 additions and 48 deletions

View File

@ -1,6 +1,10 @@
sudo: false
language: python
python: 3.4
branches: # remove travis double-check on pull requests in main repo
only:
- master
- /^\d\.\d+$/
env:
- TOXENV=py26
- TOXENV=py27

View File

@ -4,19 +4,25 @@ HOW TO CONTRIBUTE TO TQDM
This file describes how to contribute changes to the project, and how to
upload to the pypi repository.
Most of the management commands have been directly placed inside the
Makefile: `python setup.py make [alias]`, (or simply `make [alias]` in
UNIX-like environments).
Note: to use the Makefile on Windows, you need to install make.exe,
for example by installing [MinGW MSYS](http://www.mingw.org/wiki/msys).
HOW TO COMMIT YOUR CONTRIBUTIONS
--------------------------------
Contributions to the project is made using the "Fork & Pull" model. Here's a
quickstart on how to do that (your mileage may vary depending on your git
config):
Contributions to the project are made using the "Fork & Pull" model. The
typical steps would be:
- create an account on [github](https://github.com)
- fork [tqdm](https://github.com/tqdm/tqdm)
- make a local clone: `git clone https://github.com/your_account/tqdm.git`
- make your changes on your local copy
- commit your changes `git commit -m "my message"`
- commit your changes `git commit -a -m "my message"`
- TEST YOUR CHANGES (see below)
- `push` to your github account: `git push origin`
- finally, create a Pull Request (PR) from your github fork
@ -30,22 +36,57 @@ TESTING
To test functionality on your machine (such as before submitting a Pull
Request), there are a number of unit tests.
To run the tests,
Standard unit testing
~~~~~~~~~~~~~~~~~~~~~
The standard way to run the tests:
- install `tox`
- `cd` to the root of the `tqdm` directory (in the same folder as this file)
- run the following commands:
- run the following command:
```
python setup.py make test
```
or
```
make test
make coverage
make flake8
```
Alternatively (if you can't use `make`)
or
- install `nosetest`
- run the following commands:
```
tox --skip-missing-interpreters
```
This will build the module and run the tests in a virtual environment.
Errors and coverage rates will be output to the console/log. (Ignore missing
interpreters errors - these are due to the local machine missing certain
versions of Python.)
Note: to install all versions of the Python interpreter that are specified
in [tox.ini](https://raw.githubusercontent.com/tqdm/tqdm/master/tox.ini),
you can use `MiniConda` to install a minimal setup. You must also make sure
that each distribution has an alias to call the Python interpreter:
`python27` for Python 2.7's interpreter, `python32` for Python 3.2's, etc.
Alternative unit testing with Nose
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Alternatively, use `nose` to run the tests just for your Python version:
- install `nose` and `flake8`
- run the following command:
```
python setup.py make alltests
```
or
```
nosetests --with-coverage --cover-package=tqdm -v tqdm/

View File

@ -1,13 +1,76 @@
.PHONY: all flake8 test coverage
# IMPORTANT: for compatibility with `python setup.py make [alias]`, ensure:
# 1. A line return after every alias
# 2. One command per line
# E.g.:
# ```
# all:
# @make test
# @make install
# test:
# nosetest
# install:
# python setup.py install
# ```
.PHONY:
alltests
all
flake8
test
testnose
testsetup
testcoverage
installdev
install
build
pypimeta
pypi
none
alltests:
@make testcoverage
@make flake8
@make testsetup
all:
@make alltests
@make build
all: flake8 coverage
flake8:
flake8 --max-line-length=80 --count --statistics --exit-zero tqdm/
flake8 --max-line-length=80 --count --statistics --exit-zero examples/
flake8 --max-line-length=80 --count --statistics --exit-zero .
test:
tox --skip-missing-interpreters
testnose:
nosetests tqdm -v
coverage:
testsetup:
python setup.py check --restructuredtext --strict
python setup.py make none
testcoverage:
rm -f .coverage # coverage erase
nosetests tqdm --with-coverage --cover-package=tqdm -v
installdev:
python setup.py develop --uninstall
python setup.py develop
install:
python setup.py install
build:
python setup.py sdist --formats=gztar,zip bdist_wininst
python setup.py sdist bdist_wheel
pypimeta:
python setup.py register
pypi:
twine upload dist/*
none:
# used for unit testing

View File

@ -225,13 +225,14 @@ with the following command:
$ make test
$ make coverage
See the `CONTRIBUTE <CONTRIBUTE>`__ file for more information.
See the `CONTRIBUTE <https://raw.githubusercontent.com/tqdm/tqdm/master/CONTRIBUTE>`__
file for more information.
License
-------
`MIT LICENSE <LICENSE>`__.
`MIT LICENSE <https://raw.githubusercontent.com/tqdm/tqdm/master/LICENSE>`__.
Authors

40
RELEASE
View File

@ -4,13 +4,20 @@ HOW TO MANAGE A NEW RELEASE
This file is intended for the project's maintainers and it describes
how to update, build and upload a new release.
Most of the management commands have been directly placed inside the
Makefile: `python setup.py make [alias]`, (or simply `make [alias]` in
UNIX-like environments).
Note: to use the Makefile on Windows, you need to install make.exe,
for example by installing [MinGW MSYS](http://www.mingw.org/wiki/msys).
SEMANTIC VERSIONING
-------------------
The tqdm repository managers should regularly bump the version number in the
VERSION file to follow the [Semantic Versioning](http://semver.org/)
convention.
[_version.py](https://raw.githubusercontent.com/tqdm/tqdm/master/tqdm/_version.py)
file to follow the [Semantic Versioning](http://semver.org/) convention.
Tools can be used to automate this process, such as
[bumpversion](https://github.com/peritus/bumpversion) or
@ -18,23 +25,22 @@ Tools can be used to automate this process, such as
to automate this task.
The managers should take care of this instead of users to avoid PR conflicts
solely due to the VERSION file bumping.
solely due to the version file bumping.
CHECKING SETUP.PY
-----------------
To check that the setup.py is OK for PyPi (eg, version number,
reStructuredText in README.rst intelligible for PyPi, which uses a
awkward RST lib, etc.) you can use the following command to make
sure everything's ok:
To check that the `setup.py` file is compliant with PyPi requirements (e.g.
version number; reStructuredText in README.rst) use the following command:
```
python setup.py check --restructuredtext --strict
```
Also, if you happen to mistakenly upload a broken release to PyPi,
you can fix the metadata by using: `python setup.py register`.
If you happen to mistakenly upload a broken release to PyPi,
you can fix the metadata by using: `python setup.py make pypimeta`
or `python setup.py register`.
BUILDING A RELEASE AND UPLOADING TO PYPI
@ -46,24 +52,22 @@ process and info that will be uploaded to [pypi](pypi.python.org).
Check the result by using the following commands:
```
python setup.py develop --uninstall
python setup.py develop
python setup.py make installdev
```
Secondly, build tqdm into a distributable python package:
```
python setup.py sdist --formats=gztar,zip bdist_wininst --plat-name=win32
python setup.py sdist bdist_wheel --plat-name=win32
python setup.py make build
```
This will generate several builds in the `dist/` folder.
Finally, we can upload everything to pypi. Uploading to pypi can be done
easily using the [twine](https://github.com/pypa/twine) module:
Finally, upload everything to pypi. This can be done easily using the
[twine](https://github.com/pypa/twine) module:
```
twine upload dist/*
python setup.py make pypi
```
NOTE:
@ -74,7 +78,7 @@ before the real deployment
cannot re-upload another with the same version number!
- in case of a mistake in the metadata on pypi (like the long description README
getting garbled because of a silent error), you can use the following
command to update the metadata: `python setup.py register`
command to update the metadata: `make pypimeta` or `python setup.py register`
Also, the new release can be added to the Github by creating a new release
Also, the new release can be added to github by creating a new release
from the web interface.

View File

@ -26,5 +26,5 @@ stmts = (
' [i for i in ProgressBar()(xrange(int(1e8)))]')
for s in stmts:
print s
print timeit(stmt=s, number=1), 'seconds'
print(s)
print(timeit(stmt=s, number=1), 'seconds')

166
setup.py
View File

@ -1,14 +1,161 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from setuptools import setup
import sys
import subprocess
# For Makefile parsing
try: # pragma: no cover
import ConfigParser
import StringIO
except ImportError: # pragma: no cover
# Python 3 compatibility
import configparser as ConfigParser
import io as StringIO
""" Makefile auxiliary functions """
def parse_makefile_aliases(filepath):
'''
Parse a makefile to find commands and substitute variables. Expects a
makefile with only aliases and a line return between each command, i.e.:
```
all:
test
install
test:
nosetest
install:
python setup.py install
```
Returns a dict, with a list of commands for each alias.
'''
# -- Parsing the Makefile using ConfigParser
# Adding a fake section to make the Makefile a valid Ini file
ini_str = '[root]\n'
with open(filepath, 'r') as fd:
ini_str = ini_str + fd.read().replace('@make ', '')
ini_fp = StringIO.StringIO(ini_str)
# Parse using ConfigParser
config = ConfigParser.RawConfigParser()
config.readfp(ini_fp)
# Fetch the list of aliases
aliases = config.options('root')
# -- Extracting commands for each alias
commands = {}
for alias in aliases:
# strip the first line return, and then split by any line return
commands[alias] = config.get('root', alias).lstrip('\n').split('\n')
# -- Commands substitution
# Loop until all aliases are substituted by their commands:
# Check each command of each alias, and if there is one command that is to
# be substituted by an alias, try to do it right away. If this is not
# possible because this alias itself points to other aliases , then stop
# and put the current alias back in the queue to be processed again later.
# Create the queue of aliases to process
aliases_todo = commands.keys()
# Create the dict that will hold the full commands
commands_new = {}
# Loop until we have processed all aliases
while aliases_todo:
# Pick the first alias in the queue
alias = aliases_todo.pop(0)
# Create a new entry in the resulting dict
commands_new[alias] = []
# For each command of this alias
for cmd in commands[alias]:
# Ignore self-referencing (alias points to itself)
if cmd == alias:
pass
# Substitute full command
elif cmd in aliases and cmd in commands_new:
# Append all the commands referenced by the alias
commands_new[alias].extend(commands_new[cmd])
# Delay substituting another alias, waiting for the other alias to
# be substituted first
elif cmd in aliases and cmd not in commands_new:
# Delete the current entry to avoid other aliases
# to reference this one wrongly (as it is empty)
del commands_new[alias]
aliases_todo.append(alias)
break
# Full command (no aliases)
else:
commands_new[alias].append(cmd)
commands = commands_new
del commands_new
# -- Prepending prefix to avoid conflicts with standard setup.py commands
# for alias in commands.keys():
# commands['make_'+alias] = commands[alias]
# del commands[alias]
return commands
def execute_makefile_commands(commands, alias, verbose=False):
cmds = commands[alias]
for cmd in cmds:
if verbose:
print("Running command: " + cmd)
subprocess.check_call(cmd.split())
""" Main setup.py config """
# Get version from tqdm/_version.py
__version__ = None
version_file = os.path.join(os.path.dirname(__file__), 'tqdm', '_version.py')
for line in open(version_file).readlines():
if (line.startswith('version_info') or line.startswith('__version__')):
exec(line.strip())
with open(version_file) as fd:
exec(fd.read())
# Executing makefile commands if specified
if sys.argv[1].lower().strip() == 'make':
# Filename of the makefile
fpath = 'Makefile'
# Parse the makefile, substitute the aliases and extract the commands
commands = parse_makefile_aliases(fpath)
# If no alias (only `python setup.py make`), print the list of aliases
if len(sys.argv) < 3 or sys.argv[-1] == '--help':
print("Shortcut to use commands via aliases. List of aliases:")
for alias in sorted(commands.keys()):
print("- " + alias)
# Else process the commands for this alias
else:
arg = sys.argv[-1]
# if unit testing, we do nothing (we just checked the makefile parsing)
if arg == 'none':
sys.exit(0)
# else if the alias exists, we execute its commands
elif arg in commands.keys():
execute_makefile_commands(commands, arg, verbose=True)
# else the alias cannot be found
else:
raise Exception("Provided alias cannot be found: make " + arg)
# Stop the processing of setup.py here:
# It's important to avoid setup.py raising an error because of the command
# not being standard
sys.exit(0)
""" Python package config """
README_rst = ''
with open('README.rst', 'r') as fd:
README_rst = fd.read()
setup(
name='tqdm',
@ -20,10 +167,12 @@ setup(
url='https://github.com/tqdm/tqdm',
maintainer='tqdm developers',
maintainer_email='python.tqdm@gmail.com',
platforms = ["any"],
platforms=['any'],
packages=['tqdm'],
long_description = open("README.rst", "r").read(),
classifiers=[ # Trove classifiers, see https://pypi.python.org/pypi?%3Aaction=list_classifiers
long_description=README_rst,
classifiers=[
# Trove classifiers
# (https://pypi.python.org/pypi?%3Aaction=list_classifiers)
'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: MIT License',
'Environment :: Console',
@ -48,5 +197,8 @@ setup(
'Topic :: Utilities',
'Intended Audience :: Developers',
],
keywords = 'progressbar progressmeter progress bar meter rate eta console terminal time',
keywords='progressbar progressmeter progress bar meter'
' rate eta console terminal time',
test_suite='nose.collector',
tests_require=['nose', 'flake8', 'coverage'],
)

16
tox.ini
View File

@ -4,7 +4,7 @@
# and then run "tox" from this directory.
[tox]
envlist = py26, py27, py32, py33, py34, pypy, pypy3, flake8
envlist = py26, py27, py32, py33, py34, pypy, pypy3, flake8, setup.py
[testenv]
passenv = TRAVIS TRAVIS_JOB_ID TRAVIS_BRANCH
@ -17,8 +17,16 @@ commands =
coveralls
[testenv:flake8]
basepython = python2.7
deps = flake8
commands =
flake8 --count --statistics tqdm/
flake8 --count --statistics examples/
flake8 --max-line-length=80 --count --statistics --exit-zero tqdm/
flake8 --max-line-length=80 --count --statistics --exit-zero examples/
flake8 --max-line-length=80 --count --statistics --exit-zero .
[testenv:setup.py]
deps =
docutils
pygments
commands =
python setup.py check --restructuredtext --metadata --strict
python setup.py make none

View File

@ -1,5 +1,5 @@
# Definition of the version number
version_info = 2, 1, 0 # major, minor, patch, -extra
version_info = 2, 2, 0 # major, minor, patch, -extra
# Nice string for the version
__version__ = '.'.join(map(str, version_info)).replace('.-', '-').strip('.-')