Skip to content

Commit ded0aa4

Browse files
committed
.coafile: Add NoFutureImportBear
Closes #267
1 parent b4b0b53 commit ded0aa4

File tree

5 files changed

+221
-2
lines changed

5 files changed

+221
-2
lines changed

.coafile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,6 @@ shortlog_regex = ([^:]*|[^:]+[^ ]: [A-Z0-9*].*)
4242
[all.yml]
4343
bears = YAMLLintBear
4444
files = *.yml, .ci/*.yml, tests/**/*.yml
45+
46+
[all.nofutureimports]
47+
bears = NoFutureImportBear

.moban.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ dependencies:
3434
- coala_utils~=0.6.6
3535
- gemfileparser~=0.6.2
3636
- pyjsparser~=2.4.5
37+
- git+https://gitlab.com/MacBox7/coala-pyflakes.git#egg=coala-pyflakes
3738

3839

3940
configuration:

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ coala_bears~=0.12.0.dev20170722110839
33
coala_utils~=0.6.6
44
gemfileparser~=0.6.2
55
pyjsparser~=2.4.5
6+
git+https://gitlab.com/MacBox7/coala-pyflakes.git#egg=coala-pyflakes

setup.py

Lines changed: 215 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,220 @@ def run_tests(self):
5959
__dir__ = os.path.dirname(__file__)
6060

6161

62+
from distutils.version import LooseVersion # noqa (late-import)
63+
64+
65+
class PEP440Version(LooseVersion):
66+
"""
67+
Basic PEP440 version with a few features.
68+
69+
Uses the same version semantics as LooseVersion,
70+
with the addition that a ``v`` prefix is allowed
71+
in the version as required by PEP 440.
72+
73+
vstring may be a list, tuple or string.
74+
75+
v_prefix indicates whether output of the version
76+
should include a v prefix.
77+
78+
v_prefix is auto-detected by default.
79+
Set to False to remove if present, or True to add if missing.
80+
"""
81+
82+
def __init__(self, vstring=None, v_prefix=None):
83+
self._v_prefix = v_prefix
84+
85+
if isinstance(vstring, (list, tuple)):
86+
type_ = type(vstring)
87+
vstring = '.'.join(str(i) for i in vstring)
88+
else:
89+
type_ = list
90+
91+
vstring = vstring.strip()
92+
93+
if vstring.startswith('v'):
94+
vstring = vstring[1:]
95+
if vstring.startswith('!'):
96+
raise ValueError('Invalid use of epoch')
97+
if v_prefix is not False:
98+
self._v_prefix = True
99+
100+
# Can not use super(..) on Python 2.7
101+
LooseVersion.__init__(self, vstring)
102+
if self._v_prefix:
103+
self.vstring = 'v' + self.vstring
104+
if len(self.version) > 1 and self.version[1] == '!':
105+
self._epoch = self.version[0]
106+
if not isinstance(self._epoch, int) or len(self.version) < 3:
107+
raise ValueError('Invalid use of epoch')
108+
109+
# Normalise to lower case
110+
self.version = [
111+
x if isinstance(x, int) else x.lower() for x in self.version
112+
if x not in ('-', '_')]
113+
114+
if self.version[-1] != '*' and not isinstance(self.version[-1], int):
115+
self.version += (0, )
116+
117+
if type_ is tuple:
118+
self.version = tuple(self.version)
119+
120+
self._final = None
121+
self._previous = None
122+
123+
def __repr__(self):
124+
return "%s('%s')" % (self.__class__.__name__, str(self))
125+
126+
@property
127+
def is_dev(self):
128+
return any(part == 'dev' for part in self.version)
129+
130+
@property
131+
def has_epoch(self):
132+
return any(part == '!' for part in self.version)
133+
134+
@property
135+
def final(self):
136+
"""
137+
Provide only the final component of the version.
138+
139+
A new instance is return if this instance is not final.
140+
"""
141+
if self.has_epoch:
142+
raise NotImplementedError
143+
144+
if self._final is not None:
145+
return self._final
146+
147+
for i, part in enumerate(self.version):
148+
if not isinstance(part, int):
149+
final = self.version[:i]
150+
break
151+
else:
152+
self._final = self
153+
return self
154+
155+
self._final = PEP440Version(final, self._v_prefix)
156+
157+
return self._final
158+
159+
@property
160+
def is_final(self):
161+
return self.final == self
162+
163+
@property
164+
def is_zero(self):
165+
return all(part == 0 for part in self.version)
166+
167+
_zero_message = 'version prior to 0.0 can not exist'
168+
169+
def _estimate_previous(self):
170+
"""
171+
Return a new version calculated to be the previous version.
172+
173+
Currently only handles when the current instance is a final version.
174+
175+
To really get the previous for 1.0.0, we need to consult PyPi,
176+
git tags, or some other source of all released versions,
177+
to find the highest patch release in the prior minor release, or
178+
highest minor releases if there were no patch releases in the
179+
last minor release, etc.
180+
181+
As a result, currently this assumes that release x.(x-1).0 exists
182+
in that instance.
183+
"""
184+
if self._previous:
185+
return self._previous
186+
187+
assert self.is_final, '%r is not final' % self
188+
189+
if self.is_zero:
190+
raise ValueError(self._zero_message)
191+
192+
previous = self._decrement(self.version)
193+
self._previous = PEP440Version(previous, self._v_prefix)
194+
return self._previous
195+
196+
@staticmethod
197+
def _decrement(version):
198+
pos = len(version) - 1
199+
200+
# Look for non-zero int part
201+
while pos != 0 and not (isinstance(version[pos], int) and version[pos]):
202+
pos -= 1
203+
204+
previous = []
205+
if pos:
206+
previous = version[:pos]
207+
208+
previous += (version[pos] - 1, )
209+
210+
if len(previous) == len(version):
211+
return previous
212+
213+
remaining = version[pos + 1:-1]
214+
215+
previous += tuple(
216+
0 if isinstance(i, int) else i for i in remaining)
217+
218+
previous += ('*', )
219+
220+
return previous
221+
222+
223+
def egg_name_to_requirement(name):
224+
name = name.strip()
225+
parts = name.split('-')
226+
227+
# The first part may be v or v0, which would be considered a version
228+
# if processed in the following loop.
229+
name_parts = [parts[0]]
230+
# Pre-releases may contain a '-' and be alpha only, so we must
231+
# parse from the second part to find the first version-like part.
232+
for part in parts[1:]:
233+
version = PEP440Version(part)
234+
if isinstance(version.version[0], int):
235+
break
236+
name_parts.append(part)
237+
238+
version_parts = parts[len(name_parts):]
239+
240+
if not version_parts:
241+
return name
242+
243+
name = '-'.join(name_parts)
244+
245+
version = PEP440Version('-'.join(version_parts))
246+
247+
# Assume that alpha, beta, pre, post & final releases
248+
# are in PyPi so setuptools can find it.
249+
if not version.is_dev:
250+
return name + '==' + str(version)
251+
252+
# setuptools fails if a version is given with any specifier such as
253+
# `==`, `=~`, `>`, if the version is not in PyPi.
254+
255+
# For development releases, which will not usually be PyPi,
256+
# setuptools will typically fail.
257+
258+
# So we estimate a previous release that should exist in PyPi,
259+
# by decrementing the lowest final version part, and use version
260+
# specifier `>` so that the installed package from VCS will have a
261+
# version acceptable to the requirement.
262+
263+
# With major and minor releases, the previous version must be guessed.
264+
# If the version was `2.1.0`, the previous_version will be literally
265+
# `2.0.*` as it assumes that a prior minor release occurred and used
266+
# the same versioning convention.
267+
previous_version = version.final._estimate_previous()
268+
269+
if previous_version.is_zero:
270+
raise ValueError(
271+
'Version %s could not be decremented' % version)
272+
273+
return name + '>' + str(previous_version)
274+
275+
62276
def read_requirements(filename):
63277
"""
64278
Parse a requirements file.
@@ -84,7 +298,7 @@ def read_requirements(filename):
84298

85299
DEPENDENCY_LINKS.append(line)
86300

87-
line = egg_name.replace('-', '==')
301+
line = egg_name_to_requirement(egg_name)
88302

89303
data.append(line)
90304

test-requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ pytest-timeout~=1.3.0
1717
pytest-travis-fold~=1.3.0
1818
pytest-xdist~=1.15
1919
requests-mock~=1.2
20-
pip!=9.0.2, !=10.0.*
20+
pip!=9.0.2, !=10.0.*, !=18.0
2121
wheel~=0.29

0 commit comments

Comments
 (0)