-
Notifications
You must be signed in to change notification settings - Fork 166
/
vendor.py
73 lines (64 loc) · 3.42 KB
/
vendor.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
import fileinput
import os.path
# header lines we want to have, disabling some annoying pylint checks
# and adhering to Ansible standards
header_lines = [
'# pylint: disable=ansible-format-automatic-specification,raise-missing-from',
'from __future__ import absolute_import, division, print_function',
'__metaclass__ = type',
]
# buffer to store lines we might want to adjust/drop
buffer_lines = []
# normal output
output_lines = []
# typing imports
typing_imports = set()
with fileinput.input() as f:
for line in f:
if os.path.basename(fileinput.filename()) == '__init__.py':
fileinput.nextfile()
continue
if fileinput.isfirstline():
output_lines.extend(['', ''])
line = line.rstrip()
# Ansible doesn't like `basestring` because it doesn't exist in Python3
# but our code actually catches that and uses `str` in that case.
# So let's use `base_string` instead, which doesn't trip Ansible's check.
if line == ' basestring # type: ignore[used-before-def] # pylint: disable=used-before-assignment':
line = ' base_string = basestring'
elif 'basestring' in line:
line = line.replace('basestring', 'base_string')
# empty lines trigger buffer flushes
if line == '':
output_lines.extend(buffer_lines)
buffer_lines.clear()
if output_lines and output_lines[-1] != '':
output_lines.append(line)
# drop apypie imports (we have one file now) and future imports (they are already present in the header)
elif line.startswith('from apypie') or line.startswith('from __future__'):
continue
# we can't just import requests, Ansible's "import" sanity test fails without the try/except
elif line == 'import requests':
output_lines.extend(['try:', ' import requests', 'except ImportError:', ' pass'])
# drop blocks that only handle typing imports (fenced by either try or if TYPE_CHECKING)
elif line in ['try:', 'if TYPE_CHECKING:'] or buffer_lines:
buffer_lines.append(line)
if "from typing" in line:
typing_imports.update([element.strip(',') for element in line.split('#')[0].strip().split(' ')[3:]
if not element.strip(',') == 'TYPE_CHECKING'])
if (('pass' in line or 'TYPE_CHECKING =' in line or ('from apypie' in line and 'if TYPE_CHECKING:' in buffer_lines)) and
('from typing' in buffer_lines[1] or 'from apypie' in buffer_lines[1])):
buffer_lines.clear()
elif "from typing" in line:
typing_imports.update([element.strip(',') for element in line.split('#')[0].strip().split(' ')[3:] if not element.strip(',') == 'TYPE_CHECKING'])
else:
# inject a blank line before class or import statements
if (line.startswith('class ') or line.startswith('import ') or line.startswith('def ')) and not output_lines[-1].startswith('import '):
output_lines.append('')
output_lines.append(line)
# anything left in the buffer? flush it!
if buffer_lines:
output_lines.extend(buffer_lines)
buffer_lines.clear()
typing_lines = ['from typing import {} # pylint: disable=unused-import # noqa: F401'.format(', '.join(sorted(typing_imports)))]
print("\n".join(header_lines + typing_lines + output_lines))