forked from tqdm/tqdm
-
Notifications
You must be signed in to change notification settings - Fork 1
/
setup.py
executable file
·180 lines (162 loc) · 6.73 KB
/
setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from setuptools import setup
# For Makefile parsing
try: # pragma: no cover
import ConfigParser
import StringIO
except NameError: # pragma: no cover
# Python 3 compatibility
import configparser as ConfigParser
import io as StringIO
import sys, subprocess
### Makefile auxiliary functions ###
def parse_makefile_aliases(filepath):
'''Parse a makefile to find commands and substitute variables.
Note that this function is not a total replacement of make, it only
parse aliases.
Expects a makefile with only aliases and ALWAYS a line return between
each command, eg:
```
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' + open(filepath, 'r').read()
ini_fp = StringIO.StringIO(ini_str)
# Parse it 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
# We loop until we can substitute all aliases by their commands
# What we do is that we check each command of each alias, and
# if there is one command that is to be substituted by an alias,
# we try to do it right away, but if it's not possible because
# this alias himself points to other aliases, then we stop
# and put the current alias back in the queue, which we
# will process again later when we have substituted the
# other aliases.
# Create the queue of aliases to process
aliases_todo = commands.keys()
# Create the dict that will hold the substituted aliases by their 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]:
# If the alias points to itself, we pass
if cmd == alias:
pass
# If the alias points to a full command, we substitute
elif cmd in aliases and cmd in commands_new:
# Append all the commands referenced by the alias
commands_new[alias].extend(commands_new[cmd])
# If the alias points to another alias, we delay,
# 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]
# Put back into the queue
aliases_todo.append(alias)
# Break the loop for the current alias
break
# Else this is just a full command (no reference to an alias)
# so we just append it
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: %s" % 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())
# Executing makefile commands if specified
if len(sys.argv) >= 3 and sys.argv[1].lower().strip() == 'make':
arg = sys.argv[-1]
fpath = 'Makefile'
commands = parse_makefile_aliases(fpath)
if arg == 'none': # unit testing, we do nothing (we just checked the makefile parsing)
sys.exit(0)
elif arg in commands.keys(): # else if the alias exists, we execute its commands
execute_makefile_commands(commands, arg, verbose=True)
else: # else the alias cannot be found
raise Exception("Provided argument cannot be found: make %s" % (arg))
# Stop the processing of setup.py here
sys.exit(0) # Important to avoid setup.py to spit an error because of the command not being standard
# Python package config
setup(
name='tqdm',
version=__version__,
description='A Fast, Extensible Progress Meter',
license='MIT License',
author='Noam Yorav-Raphael',
author_email='noamraph@gmail.com',
url='https://github.com/tqdm/tqdm',
maintainer='tqdm developers',
maintainer_email='python.tqdm@gmail.com',
platforms = ["any"],
packages=['tqdm'],
long_description = open("README.rst", "r").read(),
classifiers=[ # Trove classifiers, see https://pypi.python.org/pypi?%3Aaction=list_classifiers
'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: MIT License',
'Environment :: Console',
'Framework :: IPython',
'Operating System :: Microsoft :: Windows',
'Operating System :: MacOS :: MacOS X',
'Operating System :: POSIX :: Linux',
'Programming Language :: Python',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Software Development :: Libraries',
'Topic :: Software Development :: Libraries :: Python Modules',
'Topic :: Software Development :: User Interfaces',
'Topic :: System :: Monitoring',
'Topic :: Terminals',
'Topic :: Utilities',
'Intended Audience :: Developers',
],
keywords = 'progressbar progressmeter progress bar meter rate eta console terminal time',
test_suite='nose.collector',
tests_require=['nose', 'flake8', 'coverage'],
)