Import upstream version 1.0.2+git20220411.1.b98e6f4
Debian Janitor
1 year, 3 months ago
0 | Metadata-Version: 1.1 | |
1 | Name: flake8-polyfill | |
0 | Metadata-Version: 2.1 | |
1 | Name: flake8_polyfill | |
2 | 2 | Version: 1.0.2 |
3 | 3 | Summary: Polyfill package for Flake8 plugins |
4 | Home-page: https://gitlab.com/pycqa/flake8-polyfill | |
5 | Author: Ian Cordasco | |
4 | Home-page: https://github.com/pycqa/flake8-polyfill | |
5 | Author: Ian Stapleton Cordasco | |
6 | 6 | Author-email: graffatcolmingov@gmail.com |
7 | 7 | License: MIT |
8 | Description-Content-Type: UNKNOWN | |
9 | Description: ============================= | |
10 | Polyfill for Flake8 Plugins | |
11 | ============================= | |
12 | ||
13 | ``flake8-polyfill`` is a package that provides some compatibility helpers for | |
14 | Flake8 plugins that intend to support Flake8 2.x and 3.x simultaneously. | |
15 | ||
16 | ||
17 | Installation | |
18 | ============ | |
19 | ||
20 | .. code-block:: bash | |
21 | ||
22 | pip install flake8-polyfill | |
23 | ||
24 | ||
25 | Usage | |
26 | ===== | |
27 | ||
28 | Option Handling | |
29 | --------------- | |
30 | ||
31 | One problem area with compatibility with Flake8 2.x and 3.x is the registering | |
32 | options and receiving the parsed values. | |
33 | ||
34 | Flake8 3.0 added extra parameters to the ``add_option`` method which don't | |
35 | have the same effect on Flake8 2.x. To accomodate the change, this polyfill | |
36 | module allows you to do: | |
37 | ||
38 | .. code-block:: python | |
39 | ||
40 | from flake8_polyfill import options | |
41 | ||
42 | class MyFlake8Plugin(object): | |
43 | @classmethod | |
44 | def add_options(cls, parser): | |
45 | options.register(parser, '--my-long-option-name', | |
46 | parse_from_config=True, | |
47 | comma_separated_list=True, | |
48 | default='...', | |
49 | help='...') | |
50 | options.register(parser, '-m', '--my-other-long-option-name', | |
51 | parse_from_config=True, | |
52 | normalize_paths=True, | |
53 | default='...', | |
54 | help='...') | |
55 | ||
56 | @classmethod | |
57 | def parse_options(cls, values): | |
58 | cls.my_long_option_name = values.my_long_option_name | |
59 | cls.my_other_long_option_name = values.my_other_long_option_name | |
60 | ||
61 | And have the code work the same way on both versions. | |
62 | ||
63 | Retrieving Standard In | |
64 | ---------------------- | |
65 | ||
66 | Until Flake8 2.6, getting the code on standard in from a plugin has been | |
67 | simple: | |
68 | ||
69 | .. code-block:: python | |
70 | ||
71 | import pep8 | |
72 | ||
73 | stdin = pep8.get_stdin_value() | |
74 | ||
75 | In 2.6 you now have to know whether to use ``pep8`` or ``pycodestyle`` since | |
76 | Flake8 2.6 made a hard change to ``pycodestyle``. | |
77 | ||
78 | The reason you need to know which module to use is because standard in can be | |
79 | exhausted and Flake8 does some work to cache the value so that call always | |
80 | returns the desired data. | |
81 | ||
82 | In 3.0, Flake8 no longer monkey-patches those modules. | |
83 | ||
84 | To accommodate this, this package provides: | |
85 | ||
86 | .. code-block:: python | |
87 | ||
88 | from flake8_polyfill import stdin | |
89 | ||
90 | stdin.monkey_patch('all') | |
91 | stdin.monkey_patch('pep8') | |
92 | stdin.monkey_patch('pycodestyle') | |
93 | ||
94 | This allows you to have the polyfill module monkey-patch what you want so it | |
95 | is always monkey-patched. It will also do so in an intelligent way. | |
96 | ||
97 | Version Comparison | |
98 | ------------------ | |
99 | ||
100 | Flake8 2.x did not include an object that would allow for easy version | |
101 | comparison. Flake8 3.0, however, added a ``__version_info__`` attribute. For | |
102 | consistency, Flake8 Polyfill will turn 2.x's version string into a tuple | |
103 | suitable for comparison. | |
104 | ||
105 | .. code-block:: python | |
106 | ||
107 | from flake8_polyfill import version | |
108 | ||
109 | if (2, 4) <= version.version_info < (2, 6): | |
110 | # ... | |
111 | elif (2, 6) <= version.version_info < (3, 0): | |
112 | # ... | |
113 | elif (3, 0) <= version.version_info < (4, 0): | |
114 | # ... | |
115 | ||
116 | ||
117 | License | |
118 | ======= | |
119 | ||
120 | MIT | |
121 | ||
122 | ||
123 | Creator | |
124 | ======= | |
125 | ||
126 | Ian Cordasco | |
127 | ||
128 | Platform: UNKNOWN | |
129 | 8 | Classifier: Environment :: Console |
130 | 9 | Classifier: Framework :: Flake8 |
131 | 10 | Classifier: Intended Audience :: Developers |
132 | 11 | Classifier: License :: OSI Approved :: MIT License |
133 | 12 | Classifier: Programming Language :: Python |
134 | Classifier: Programming Language :: Python :: 2 | |
135 | Classifier: Programming Language :: Python :: 2.7 | |
136 | 13 | Classifier: Programming Language :: Python :: 3 |
137 | Classifier: Programming Language :: Python :: 3.4 | |
138 | Classifier: Programming Language :: Python :: 3.5 | |
14 | Classifier: Programming Language :: Python :: 3 :: Only | |
15 | Classifier: Programming Language :: Python :: 3.6 | |
16 | Classifier: Programming Language :: Python :: 3.7 | |
17 | Classifier: Programming Language :: Python :: 3.8 | |
18 | Classifier: Programming Language :: Python :: 3.9 | |
19 | Classifier: Programming Language :: Python :: 3.10 | |
20 | Classifier: Programming Language :: Python :: Implementation :: CPython | |
139 | 21 | Classifier: Topic :: Software Development :: Libraries :: Python Modules |
140 | 22 | Classifier: Topic :: Software Development :: Quality Assurance |
23 | Requires-Python: >=3.6 | |
24 | Description-Content-Type: text/x-rst | |
25 | License-File: LICENSE | |
26 | ||
27 | ============================= | |
28 | Polyfill for Flake8 Plugins | |
29 | ============================= | |
30 | ||
31 | ``flake8-polyfill`` is a package that provides some compatibility helpers for | |
32 | Flake8 plugins that intend to support Flake8 2.x and 3.x simultaneously. | |
33 | ||
34 | ||
35 | Installation | |
36 | ============ | |
37 | ||
38 | .. code-block:: bash | |
39 | ||
40 | pip install flake8-polyfill | |
41 | ||
42 | ||
43 | Usage | |
44 | ===== | |
45 | ||
46 | Option Handling | |
47 | --------------- | |
48 | ||
49 | One problem area with compatibility with Flake8 2.x and 3.x is the registering | |
50 | options and receiving the parsed values. | |
51 | ||
52 | Flake8 3.0 added extra parameters to the ``add_option`` method which don't | |
53 | have the same effect on Flake8 2.x. To accomodate the change, this polyfill | |
54 | module allows you to do: | |
55 | ||
56 | .. code-block:: python | |
57 | ||
58 | from flake8_polyfill import options | |
59 | ||
60 | class MyFlake8Plugin(object): | |
61 | @classmethod | |
62 | def add_options(cls, parser): | |
63 | options.register(parser, '--my-long-option-name', | |
64 | parse_from_config=True, | |
65 | comma_separated_list=True, | |
66 | default='...', | |
67 | help='...') | |
68 | options.register(parser, '-m', '--my-other-long-option-name', | |
69 | parse_from_config=True, | |
70 | normalize_paths=True, | |
71 | default='...', | |
72 | help='...') | |
73 | ||
74 | @classmethod | |
75 | def parse_options(cls, values): | |
76 | cls.my_long_option_name = values.my_long_option_name | |
77 | cls.my_other_long_option_name = values.my_other_long_option_name | |
78 | ||
79 | And have the code work the same way on both versions. | |
80 | ||
81 | Retrieving Standard In | |
82 | ---------------------- | |
83 | ||
84 | Until Flake8 2.6, getting the code on standard in from a plugin has been | |
85 | simple: | |
86 | ||
87 | .. code-block:: python | |
88 | ||
89 | import pep8 | |
90 | ||
91 | stdin = pep8.get_stdin_value() | |
92 | ||
93 | In 2.6 you now have to know whether to use ``pep8`` or ``pycodestyle`` since | |
94 | Flake8 2.6 made a hard change to ``pycodestyle``. | |
95 | ||
96 | The reason you need to know which module to use is because standard in can be | |
97 | exhausted and Flake8 does some work to cache the value so that call always | |
98 | returns the desired data. | |
99 | ||
100 | In 3.0, Flake8 no longer monkey-patches those modules. | |
101 | ||
102 | To accommodate this, this package provides: | |
103 | ||
104 | .. code-block:: python | |
105 | ||
106 | from flake8_polyfill import stdin | |
107 | ||
108 | stdin.monkey_patch('all') | |
109 | stdin.monkey_patch('pep8') | |
110 | stdin.monkey_patch('pycodestyle') | |
111 | ||
112 | This allows you to have the polyfill module monkey-patch what you want so it | |
113 | is always monkey-patched. It will also do so in an intelligent way. | |
114 | ||
115 | Version Comparison | |
116 | ------------------ | |
117 | ||
118 | Flake8 2.x did not include an object that would allow for easy version | |
119 | comparison. Flake8 3.0, however, added a ``__version_info__`` attribute. For | |
120 | consistency, Flake8 Polyfill will turn 2.x's version string into a tuple | |
121 | suitable for comparison. | |
122 | ||
123 | .. code-block:: python | |
124 | ||
125 | from flake8_polyfill import version | |
126 | ||
127 | if (2, 4) <= version.version_info < (2, 6): | |
128 | # ... | |
129 | elif (2, 6) <= version.version_info < (3, 0): | |
130 | # ... | |
131 | elif (3, 0) <= version.version_info < (4, 0): | |
132 | # ... | |
133 | ||
134 | ||
135 | License | |
136 | ======= | |
137 | ||
138 | MIT | |
139 | ||
140 | ||
141 | Creator | |
142 | ======= | |
143 | ||
144 | Ian Cordasco |
0 | [metadata] | |
1 | name = flake8_polyfill | |
2 | version = attr: flake8_polyfill.__version__ | |
3 | description = Polyfill package for Flake8 plugins | |
4 | long_description = file: README.rst | |
5 | long_description_content_type = text/x-rst | |
6 | url = https://github.com/pycqa/flake8-polyfill | |
7 | author = Ian Stapleton Cordasco | |
8 | author_email = graffatcolmingov@gmail.com | |
9 | license = MIT | |
10 | license_file = LICENSE | |
11 | classifiers = | |
12 | Environment :: Console | |
13 | Framework :: Flake8 | |
14 | Intended Audience :: Developers | |
15 | License :: OSI Approved :: MIT License | |
16 | Programming Language :: Python | |
17 | Programming Language :: Python :: 3 | |
18 | Programming Language :: Python :: 3 :: Only | |
19 | Programming Language :: Python :: 3.6 | |
20 | Programming Language :: Python :: 3.7 | |
21 | Programming Language :: Python :: 3.8 | |
22 | Programming Language :: Python :: 3.9 | |
23 | Programming Language :: Python :: 3.10 | |
24 | Programming Language :: Python :: Implementation :: CPython | |
25 | Topic :: Software Development :: Libraries :: Python Modules | |
26 | Topic :: Software Development :: Quality Assurance | |
27 | ||
28 | [options] | |
29 | packages = flake8_polyfill | |
30 | install_requires = | |
31 | flake8 | |
32 | python_requires = >=3.6 | |
33 | package_dir = =src | |
34 | ||
0 | 35 | [bdist_wheel] |
1 | 36 | universal = 1 |
2 | 37 | |
3 | [pytest] | |
38 | [tool:pytest] | |
4 | 39 | norecursedirs = .git .* *.egg* old docs dist build |
5 | 40 | addopts = -rw |
6 | 41 |
0 | # -*- coding: utf-8 -*- | |
1 | """Packaging logic for Flake8's polyfill.""" | |
2 | import io | |
3 | import os | |
4 | import sys | |
5 | ||
0 | """Installation and packaging.""" | |
6 | 1 | import setuptools |
7 | 2 | |
8 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src')) | |
9 | ||
10 | import flake8_polyfill # noqa | |
11 | ||
12 | requires = ['flake8'] | |
13 | ||
14 | ||
15 | def get_long_description(): | |
16 | """Generate a long description from the README file.""" | |
17 | descr = [] | |
18 | for fname in ('README.rst',): | |
19 | with io.open(fname, encoding='utf-8') as f: | |
20 | descr.append(f.read()) | |
21 | return '\n\n'.join(descr) | |
22 | ||
23 | ||
24 | setuptools.setup( | |
25 | name='flake8-polyfill', | |
26 | license='MIT', | |
27 | version=flake8_polyfill.__version__, | |
28 | description='Polyfill package for Flake8 plugins', | |
29 | long_description=get_long_description(), | |
30 | author='Ian Cordasco', | |
31 | author_email='graffatcolmingov@gmail.com', | |
32 | url='https://gitlab.com/pycqa/flake8-polyfill', | |
33 | package_dir={'': 'src'}, | |
34 | packages=[ | |
35 | 'flake8_polyfill', | |
36 | ], | |
37 | install_requires=requires, | |
38 | classifiers=[ | |
39 | "Environment :: Console", | |
40 | "Framework :: Flake8", | |
41 | "Intended Audience :: Developers", | |
42 | "License :: OSI Approved :: MIT License", | |
43 | "Programming Language :: Python", | |
44 | "Programming Language :: Python :: 2", | |
45 | "Programming Language :: Python :: 2.7", | |
46 | "Programming Language :: Python :: 3", | |
47 | "Programming Language :: Python :: 3.4", | |
48 | "Programming Language :: Python :: 3.5", | |
49 | "Topic :: Software Development :: Libraries :: Python Modules", | |
50 | "Topic :: Software Development :: Quality Assurance", | |
51 | ], | |
52 | ) | |
3 | setuptools.setup() |
0 | 0 | """The polyfill package for Flake8 plugins.""" |
1 | 1 | |
2 | __version__ = '1.0.2' | |
3 | __version_info__ = tuple(int(i) for i in __version__.split('.') if i.isdigit()) | |
2 | __version__ = "1.0.2" | |
3 | __version_info__ = tuple(int(i) for i in __version__.split(".") if i.isdigit()) |
19 | 19 | # Flake8 2.x registration |
20 | 20 | # Pop Flake8 3 parameters out of the kwargs so they don't cause a |
21 | 21 | # conflict. |
22 | parse_from_config = kwargs.pop('parse_from_config', False) | |
23 | comma_separated_list = kwargs.pop('comma_separated_list', False) | |
24 | normalize_paths = kwargs.pop('normalize_paths', False) | |
22 | parse_from_config = kwargs.pop("parse_from_config", False) | |
23 | comma_separated_list = kwargs.pop("comma_separated_list", False) | |
24 | normalize_paths = kwargs.pop("normalize_paths", False) | |
25 | 25 | # In the unlikely event that the developer has specified their own |
26 | 26 | # callback, let's pop that and deal with that as well. |
27 | base_callback = kwargs.pop('callback', store_callback) | |
28 | callback = generate_callback_from(comma_separated_list, | |
29 | normalize_paths, | |
30 | base_callback) | |
31 | kwargs['callback'] = callback | |
32 | kwargs['action'] = 'callback' | |
27 | base_callback = kwargs.pop("callback", store_callback) | |
28 | callback = generate_callback_from( | |
29 | comma_separated_list, normalize_paths, base_callback | |
30 | ) | |
31 | kwargs["callback"] = callback | |
32 | kwargs["action"] = "callback" | |
33 | 33 | |
34 | 34 | # We've updated our args and kwargs and can now rather confidently |
35 | 35 | # call add_option. |
36 | 36 | option = parser.add_option(*args, **kwargs) |
37 | 37 | if parse_from_config: |
38 | parser.config_options.append(option.get_opt_string().lstrip('-')) | |
38 | parser.config_options.append(option.get_opt_string().lstrip("-")) | |
39 | 39 | |
40 | 40 | |
41 | 41 | def parse_comma_separated_list(value): |
52 | 52 | return [] |
53 | 53 | |
54 | 54 | if not isinstance(value, (list, tuple)): |
55 | value = value.split(',') | |
55 | value = value.split(",") | |
56 | 56 | |
57 | 57 | return [item.strip() for item in value] |
58 | 58 | |
87 | 87 | setattr(parser.values, option.dest, value) |
88 | 88 | |
89 | 89 | |
90 | def generate_callback_from(comma_separated_list, normalize_paths, | |
91 | base_callback): | |
90 | def generate_callback_from( | |
91 | comma_separated_list, normalize_paths, base_callback | |
92 | ): | |
92 | 93 | """Generate a callback from parameters provided for the option.""" |
94 | ||
93 | 95 | def _callback(option, opt_str, value, parser, *args, **kwargs): |
94 | 96 | """Wrap `base_callback` by transforming `value` for option params.""" |
95 | 97 | if comma_separated_list: |
10 | 10 | |
11 | 11 | from flake8_polyfill import version |
12 | 12 | |
13 | __all__ = ('monkey_patch',) | |
13 | __all__ = ("monkey_patch",) | |
14 | 14 | |
15 | 15 | modules = { |
16 | 'pep8': [pep8], | |
17 | 'pycodestyle': [pycodestyle], | |
18 | 'all': [pep8, pycodestyle], | |
16 | "pep8": [pep8], | |
17 | "pycodestyle": [pycodestyle], | |
18 | "all": [pep8, pycodestyle], | |
19 | 19 | } |
20 | 20 | |
21 | 21 | |
50 | 50 | """ |
51 | 51 | if (2, 0) <= version.version_info < (3, 0): |
52 | 52 | from flake8.engine import pep8 as _pep8 |
53 | ||
53 | 54 | stdin_get_value = _pep8.stdin_get_value |
54 | 55 | elif (3, 0) <= version.version_info < (4, 0): |
55 | 56 | from flake8 import utils |
57 | ||
56 | 58 | stdin_get_value = utils.stdin_get_value |
57 | 59 | |
58 | 60 | for module in modules[which]: |
0 | 0 | """Version information for Flake8 2.x and 3.x.""" |
1 | ||
2 | 1 | import flake8 |
3 | 2 | |
4 | version_info = getattr(flake8, '__version_info__', None) | |
3 | version_info = getattr(flake8, "__version_info__", None) | |
5 | 4 | if version_info is None: |
6 | 5 | version_info = tuple( |
7 | int(i) for i in flake8.__version__.split('.') if i.isdigit() | |
6 | int(i) for i in flake8.__version__.split(".") if i.isdigit() | |
8 | 7 | ) |
0 | Metadata-Version: 1.1 | |
0 | Metadata-Version: 2.1 | |
1 | 1 | Name: flake8-polyfill |
2 | 2 | Version: 1.0.2 |
3 | 3 | Summary: Polyfill package for Flake8 plugins |
4 | Home-page: https://gitlab.com/pycqa/flake8-polyfill | |
5 | Author: Ian Cordasco | |
4 | Home-page: https://github.com/pycqa/flake8-polyfill | |
5 | Author: Ian Stapleton Cordasco | |
6 | 6 | Author-email: graffatcolmingov@gmail.com |
7 | 7 | License: MIT |
8 | Description-Content-Type: UNKNOWN | |
9 | Description: ============================= | |
10 | Polyfill for Flake8 Plugins | |
11 | ============================= | |
12 | ||
13 | ``flake8-polyfill`` is a package that provides some compatibility helpers for | |
14 | Flake8 plugins that intend to support Flake8 2.x and 3.x simultaneously. | |
15 | ||
16 | ||
17 | Installation | |
18 | ============ | |
19 | ||
20 | .. code-block:: bash | |
21 | ||
22 | pip install flake8-polyfill | |
23 | ||
24 | ||
25 | Usage | |
26 | ===== | |
27 | ||
28 | Option Handling | |
29 | --------------- | |
30 | ||
31 | One problem area with compatibility with Flake8 2.x and 3.x is the registering | |
32 | options and receiving the parsed values. | |
33 | ||
34 | Flake8 3.0 added extra parameters to the ``add_option`` method which don't | |
35 | have the same effect on Flake8 2.x. To accomodate the change, this polyfill | |
36 | module allows you to do: | |
37 | ||
38 | .. code-block:: python | |
39 | ||
40 | from flake8_polyfill import options | |
41 | ||
42 | class MyFlake8Plugin(object): | |
43 | @classmethod | |
44 | def add_options(cls, parser): | |
45 | options.register(parser, '--my-long-option-name', | |
46 | parse_from_config=True, | |
47 | comma_separated_list=True, | |
48 | default='...', | |
49 | help='...') | |
50 | options.register(parser, '-m', '--my-other-long-option-name', | |
51 | parse_from_config=True, | |
52 | normalize_paths=True, | |
53 | default='...', | |
54 | help='...') | |
55 | ||
56 | @classmethod | |
57 | def parse_options(cls, values): | |
58 | cls.my_long_option_name = values.my_long_option_name | |
59 | cls.my_other_long_option_name = values.my_other_long_option_name | |
60 | ||
61 | And have the code work the same way on both versions. | |
62 | ||
63 | Retrieving Standard In | |
64 | ---------------------- | |
65 | ||
66 | Until Flake8 2.6, getting the code on standard in from a plugin has been | |
67 | simple: | |
68 | ||
69 | .. code-block:: python | |
70 | ||
71 | import pep8 | |
72 | ||
73 | stdin = pep8.get_stdin_value() | |
74 | ||
75 | In 2.6 you now have to know whether to use ``pep8`` or ``pycodestyle`` since | |
76 | Flake8 2.6 made a hard change to ``pycodestyle``. | |
77 | ||
78 | The reason you need to know which module to use is because standard in can be | |
79 | exhausted and Flake8 does some work to cache the value so that call always | |
80 | returns the desired data. | |
81 | ||
82 | In 3.0, Flake8 no longer monkey-patches those modules. | |
83 | ||
84 | To accommodate this, this package provides: | |
85 | ||
86 | .. code-block:: python | |
87 | ||
88 | from flake8_polyfill import stdin | |
89 | ||
90 | stdin.monkey_patch('all') | |
91 | stdin.monkey_patch('pep8') | |
92 | stdin.monkey_patch('pycodestyle') | |
93 | ||
94 | This allows you to have the polyfill module monkey-patch what you want so it | |
95 | is always monkey-patched. It will also do so in an intelligent way. | |
96 | ||
97 | Version Comparison | |
98 | ------------------ | |
99 | ||
100 | Flake8 2.x did not include an object that would allow for easy version | |
101 | comparison. Flake8 3.0, however, added a ``__version_info__`` attribute. For | |
102 | consistency, Flake8 Polyfill will turn 2.x's version string into a tuple | |
103 | suitable for comparison. | |
104 | ||
105 | .. code-block:: python | |
106 | ||
107 | from flake8_polyfill import version | |
108 | ||
109 | if (2, 4) <= version.version_info < (2, 6): | |
110 | # ... | |
111 | elif (2, 6) <= version.version_info < (3, 0): | |
112 | # ... | |
113 | elif (3, 0) <= version.version_info < (4, 0): | |
114 | # ... | |
115 | ||
116 | ||
117 | License | |
118 | ======= | |
119 | ||
120 | MIT | |
121 | ||
122 | ||
123 | Creator | |
124 | ======= | |
125 | ||
126 | Ian Cordasco | |
127 | ||
128 | Platform: UNKNOWN | |
129 | 8 | Classifier: Environment :: Console |
130 | 9 | Classifier: Framework :: Flake8 |
131 | 10 | Classifier: Intended Audience :: Developers |
132 | 11 | Classifier: License :: OSI Approved :: MIT License |
133 | 12 | Classifier: Programming Language :: Python |
134 | Classifier: Programming Language :: Python :: 2 | |
135 | Classifier: Programming Language :: Python :: 2.7 | |
136 | 13 | Classifier: Programming Language :: Python :: 3 |
137 | Classifier: Programming Language :: Python :: 3.4 | |
138 | Classifier: Programming Language :: Python :: 3.5 | |
14 | Classifier: Programming Language :: Python :: 3 :: Only | |
15 | Classifier: Programming Language :: Python :: 3.6 | |
16 | Classifier: Programming Language :: Python :: 3.7 | |
17 | Classifier: Programming Language :: Python :: 3.8 | |
18 | Classifier: Programming Language :: Python :: 3.9 | |
19 | Classifier: Programming Language :: Python :: 3.10 | |
20 | Classifier: Programming Language :: Python :: Implementation :: CPython | |
139 | 21 | Classifier: Topic :: Software Development :: Libraries :: Python Modules |
140 | 22 | Classifier: Topic :: Software Development :: Quality Assurance |
23 | Requires-Python: >=3.6 | |
24 | Description-Content-Type: text/x-rst | |
25 | License-File: LICENSE | |
26 | ||
27 | ============================= | |
28 | Polyfill for Flake8 Plugins | |
29 | ============================= | |
30 | ||
31 | ``flake8-polyfill`` is a package that provides some compatibility helpers for | |
32 | Flake8 plugins that intend to support Flake8 2.x and 3.x simultaneously. | |
33 | ||
34 | ||
35 | Installation | |
36 | ============ | |
37 | ||
38 | .. code-block:: bash | |
39 | ||
40 | pip install flake8-polyfill | |
41 | ||
42 | ||
43 | Usage | |
44 | ===== | |
45 | ||
46 | Option Handling | |
47 | --------------- | |
48 | ||
49 | One problem area with compatibility with Flake8 2.x and 3.x is the registering | |
50 | options and receiving the parsed values. | |
51 | ||
52 | Flake8 3.0 added extra parameters to the ``add_option`` method which don't | |
53 | have the same effect on Flake8 2.x. To accomodate the change, this polyfill | |
54 | module allows you to do: | |
55 | ||
56 | .. code-block:: python | |
57 | ||
58 | from flake8_polyfill import options | |
59 | ||
60 | class MyFlake8Plugin(object): | |
61 | @classmethod | |
62 | def add_options(cls, parser): | |
63 | options.register(parser, '--my-long-option-name', | |
64 | parse_from_config=True, | |
65 | comma_separated_list=True, | |
66 | default='...', | |
67 | help='...') | |
68 | options.register(parser, '-m', '--my-other-long-option-name', | |
69 | parse_from_config=True, | |
70 | normalize_paths=True, | |
71 | default='...', | |
72 | help='...') | |
73 | ||
74 | @classmethod | |
75 | def parse_options(cls, values): | |
76 | cls.my_long_option_name = values.my_long_option_name | |
77 | cls.my_other_long_option_name = values.my_other_long_option_name | |
78 | ||
79 | And have the code work the same way on both versions. | |
80 | ||
81 | Retrieving Standard In | |
82 | ---------------------- | |
83 | ||
84 | Until Flake8 2.6, getting the code on standard in from a plugin has been | |
85 | simple: | |
86 | ||
87 | .. code-block:: python | |
88 | ||
89 | import pep8 | |
90 | ||
91 | stdin = pep8.get_stdin_value() | |
92 | ||
93 | In 2.6 you now have to know whether to use ``pep8`` or ``pycodestyle`` since | |
94 | Flake8 2.6 made a hard change to ``pycodestyle``. | |
95 | ||
96 | The reason you need to know which module to use is because standard in can be | |
97 | exhausted and Flake8 does some work to cache the value so that call always | |
98 | returns the desired data. | |
99 | ||
100 | In 3.0, Flake8 no longer monkey-patches those modules. | |
101 | ||
102 | To accommodate this, this package provides: | |
103 | ||
104 | .. code-block:: python | |
105 | ||
106 | from flake8_polyfill import stdin | |
107 | ||
108 | stdin.monkey_patch('all') | |
109 | stdin.monkey_patch('pep8') | |
110 | stdin.monkey_patch('pycodestyle') | |
111 | ||
112 | This allows you to have the polyfill module monkey-patch what you want so it | |
113 | is always monkey-patched. It will also do so in an intelligent way. | |
114 | ||
115 | Version Comparison | |
116 | ------------------ | |
117 | ||
118 | Flake8 2.x did not include an object that would allow for easy version | |
119 | comparison. Flake8 3.0, however, added a ``__version_info__`` attribute. For | |
120 | consistency, Flake8 Polyfill will turn 2.x's version string into a tuple | |
121 | suitable for comparison. | |
122 | ||
123 | .. code-block:: python | |
124 | ||
125 | from flake8_polyfill import version | |
126 | ||
127 | if (2, 4) <= version.version_info < (2, 6): | |
128 | # ... | |
129 | elif (2, 6) <= version.version_info < (3, 0): | |
130 | # ... | |
131 | elif (3, 0) <= version.version_info < (4, 0): | |
132 | # ... | |
133 | ||
134 | ||
135 | License | |
136 | ======= | |
137 | ||
138 | MIT | |
139 | ||
140 | ||
141 | Creator | |
142 | ======= | |
143 | ||
144 | Ian Cordasco |
0 | 0 | """Tests for our options submodule.""" |
1 | 1 | import optparse |
2 | 2 | import os |
3 | from unittest import mock | |
3 | 4 | |
4 | import mock | |
5 | 5 | import pytest |
6 | 6 | |
7 | 7 | from flake8_polyfill import options |
8 | 8 | |
9 | 9 | |
10 | @pytest.mark.parametrize('value,expected', [ | |
11 | ('E123,\n\tW234,\n E206', ['E123', 'W234', 'E206']), | |
12 | ('E123,W234,E206', ['E123', 'W234', 'E206']), | |
13 | (['E123', 'W234', 'E206'], ['E123', 'W234', 'E206']), | |
14 | (['E123', '\n\tW234', '\n E206'], ['E123', 'W234', 'E206']), | |
15 | ]) | |
10 | @pytest.mark.parametrize( | |
11 | "value,expected", | |
12 | [ | |
13 | ("E123,\n\tW234,\n E206", ["E123", "W234", "E206"]), | |
14 | ("E123,W234,E206", ["E123", "W234", "E206"]), | |
15 | (["E123", "W234", "E206"], ["E123", "W234", "E206"]), | |
16 | (["E123", "\n\tW234", "\n E206"], ["E123", "W234", "E206"]), | |
17 | ], | |
18 | ) | |
16 | 19 | def test_parse_comma_separated_list(value, expected): |
17 | 20 | """Verify that similar inputs produce identical outputs.""" |
18 | 21 | assert options.parse_comma_separated_list(value) == expected |
19 | 22 | |
20 | 23 | |
21 | @pytest.mark.parametrize('value,expected', [ | |
22 | ('flake8', 'flake8'), | |
23 | ('../flake8', os.path.abspath('../flake8')), | |
24 | ('flake8/', os.path.abspath('flake8')), | |
25 | ]) | |
24 | @pytest.mark.parametrize( | |
25 | "value,expected", | |
26 | [ | |
27 | ("flake8", "flake8"), | |
28 | ("../flake8", os.path.abspath("../flake8")), | |
29 | ("flake8/", os.path.abspath("flake8")), | |
30 | ], | |
31 | ) | |
26 | 32 | def test_normalize_path(value, expected): |
27 | 33 | """Verify that we normalize paths provided to the tool.""" |
28 | 34 | assert options.normalize_path(value) == expected |
29 | 35 | |
30 | 36 | |
31 | @pytest.mark.parametrize('value,expected', [ | |
32 | ('file.py', 'file.py'), | |
33 | ('path/file.py', os.path.abspath('path/file.py')), | |
34 | (['file.py', 'path/file.py'], | |
35 | ['file.py', os.path.abspath('path/file.py')]), | |
36 | ]) | |
37 | @pytest.mark.parametrize( | |
38 | "value,expected", | |
39 | [ | |
40 | ("file.py", "file.py"), | |
41 | ("path/file.py", os.path.abspath("path/file.py")), | |
42 | ( | |
43 | ["file.py", "path/file.py"], | |
44 | ["file.py", os.path.abspath("path/file.py")], | |
45 | ), | |
46 | ], | |
47 | ) | |
37 | 48 | def test_parse_normalized_paths(value, expected): |
38 | 49 | """Verify that we handle strings and lists when normalizing paths.""" |
39 | 50 | assert options.parse_normalized_paths(value) == expected |
42 | 53 | @pytest.mark.parametrize( |
43 | 54 | # NOTE: `defaults` has NO impact, since the callback being called implies |
44 | 55 | # that a `value` was specified. |
45 | 'comma_separated_list, normalize_paths, defaults, value, expected_value', [ | |
46 | (True, True, {}, 'val', 'N(C(val))'), | |
47 | (True, True, {'foo': 'defaultval'}, 'val', 'N(C(val))'), | |
48 | (True, False, {}, 'val', 'C(val)'), | |
49 | (True, False, {'foo': 'defaultval'}, 'val', 'C(val)'), | |
50 | (False, False, {}, 'val', 'val'), | |
51 | (False, False, {'foo': 'defaultval'}, 'val', 'val'), | |
52 | ] | |
56 | "comma_separated_list, normalize_paths, defaults, value, expected_value", | |
57 | [ | |
58 | (True, True, {}, "val", "N(C(val))"), | |
59 | (True, True, {"foo": "defaultval"}, "val", "N(C(val))"), | |
60 | (True, False, {}, "val", "C(val)"), | |
61 | (True, False, {"foo": "defaultval"}, "val", "C(val)"), | |
62 | (False, False, {}, "val", "val"), | |
63 | (False, False, {"foo": "defaultval"}, "val", "val"), | |
64 | ], | |
53 | 65 | ) |
54 | 66 | def test_generate_callback_from_composition( |
55 | comma_separated_list, normalize_paths, defaults, | |
56 | value, expected_value, | |
67 | comma_separated_list, | |
68 | normalize_paths, | |
69 | defaults, | |
70 | value, | |
71 | expected_value, | |
57 | 72 | ): |
58 | 73 | """Verify our generate_callback_from composition. |
59 | 74 | |
60 | 75 | We mock out parse_comma_separated_list and parse_normalized_paths with |
61 | 76 | simple string transformations for better readability. |
62 | 77 | """ |
63 | dest = 'foo' | |
64 | opt_str = '--foo' | |
78 | dest = "foo" | |
79 | opt_str = "--foo" | |
65 | 80 | option = optparse.Option(opt_str, dest=dest) |
66 | 81 | parser = mock.Mock(values=optparse.Values(defaults)) |
67 | 82 | |
72 | 87 | base_callback=base_callback, |
73 | 88 | ) |
74 | 89 | |
75 | with mock.patch('flake8_polyfill.options.parse_comma_separated_list') as \ | |
76 | parse_comma_separated_list, \ | |
77 | mock.patch('flake8_polyfill.options.parse_normalized_paths') as \ | |
78 | parse_normalized_paths: | |
90 | with mock.patch( | |
91 | "flake8_polyfill.options.parse_comma_separated_list" | |
92 | ) as parse_comma_separated_list, mock.patch( | |
93 | "flake8_polyfill.options.parse_normalized_paths" | |
94 | ) as parse_normalized_paths: | |
79 | 95 | |
80 | parse_comma_separated_list.side_effect = lambda v: 'C({})'.format(v) | |
81 | parse_normalized_paths.side_effect = lambda v: 'N({})'.format(v) | |
96 | parse_comma_separated_list.side_effect = lambda v: f"C({v})" | |
97 | parse_normalized_paths.side_effect = lambda v: f"N({v})" | |
82 | 98 | callback(option, opt_str, value, parser) |
83 | 99 | |
84 | 100 | base_callback.assert_called_with(option, opt_str, expected_value, parser) |
86 | 102 | |
87 | 103 | def test_store_callback(): |
88 | 104 | """Verify the default callback behaves like option with action='store'.""" |
89 | dest = 'foo' | |
90 | opt_str = '--foo' | |
105 | dest = "foo" | |
106 | opt_str = "--foo" | |
91 | 107 | option = optparse.Option(opt_str, dest=dest) |
92 | parser = mock.Mock(values=optparse.Values({'foo': 'defaultval'})) | |
93 | options.store_callback(option, opt_str, 'val', parser) | |
94 | assert parser.values.foo == 'val' | |
108 | parser = mock.Mock(values=optparse.Values({"foo": "defaultval"})) | |
109 | options.store_callback(option, opt_str, "val", parser) | |
110 | assert parser.values.foo == "val" | |
95 | 111 | |
96 | 112 | |
97 | 113 | @pytest.fixture |
98 | 114 | def parser(): |
99 | 115 | """Provide a pycodestyle-esque OptionParser instance.""" |
100 | parser = optparse.OptionParser('flake8') | |
116 | parser = optparse.OptionParser("flake8") | |
101 | 117 | parser.config_options = [] |
102 | 118 | return parser |
103 | 119 | |
104 | 120 | |
105 | 121 | def test_register_with_store_callback(parser): |
106 | 122 | """Verify we handle typical no-custom-callback case (integration test).""" |
107 | options.register(parser, '--foo', default=['path/file.py'], type='string', | |
108 | comma_separated_list=True, normalize_paths=True) | |
123 | options.register( | |
124 | parser, | |
125 | "--foo", | |
126 | default=["path/file.py"], | |
127 | type="string", | |
128 | comma_separated_list=True, | |
129 | normalize_paths=True, | |
130 | ) | |
109 | 131 | values, _ = parser.parse_args([]) |
110 | assert values.foo == ['path/file.py'] # default is used in its entirety | |
111 | values, _ = parser.parse_args(['--foo=file.py,path/file.py']) | |
112 | assert values.foo == ['file.py', os.path.abspath('path/file.py')] | |
132 | assert values.foo == ["path/file.py"] # default is used in its entirety | |
133 | values, _ = parser.parse_args(["--foo=file.py,path/file.py"]) | |
134 | assert values.foo == ["file.py", os.path.abspath("path/file.py")] | |
113 | 135 | |
114 | 136 | |
115 | 137 | def test_register_with_custom_callback(parser): |
116 | 138 | """Verify we handle custom callback (integration test).""" |
139 | ||
117 | 140 | def custom_callback(option, opt_str, value, parser, *args, **kwargs): |
118 | 141 | parser.values.count = len(value) |
119 | 142 | |
120 | options.register(parser, '--foo', type='string', callback=custom_callback, | |
121 | comma_separated_list=True, normalize_paths=True) | |
122 | values, _ = parser.parse_args(['--foo=file.py,path/file.py']) | |
143 | options.register( | |
144 | parser, | |
145 | "--foo", | |
146 | type="string", | |
147 | callback=custom_callback, | |
148 | comma_separated_list=True, | |
149 | normalize_paths=True, | |
150 | ) | |
151 | values, _ = parser.parse_args(["--foo=file.py,path/file.py"]) | |
123 | 152 | assert values.count == 2 |
124 | 153 | |
125 | 154 | |
126 | 155 | def test_register_parse_from_config(parser): |
127 | 156 | """Verify we append to config_options on registration.""" |
128 | options.register(parser, '--select', default='E123,W504', | |
129 | parse_from_config=True) | |
130 | assert 'select' in parser.config_options | |
157 | options.register( | |
158 | parser, "--select", default="E123,W504", parse_from_config=True | |
159 | ) | |
160 | assert "select" in parser.config_options |
0 | 0 | """Tests for polyfill's stdin monkey patching.""" |
1 | import flake8 | |
1 | 2 | import pep8 |
2 | 3 | import pycodestyle |
3 | 4 | import pytest |
5 | 6 | from flake8_polyfill import stdin |
6 | 7 | from flake8_polyfill import version |
7 | 8 | |
9 | if (4, 0, 0) <= flake8.__version_info__: | |
10 | pytestmark = pytest.mark.skip | |
11 | ||
8 | 12 | |
9 | 13 | def test_modules_dict(): |
10 | 14 | """Verify that it works the way we expect.""" |
11 | assert len(stdin.modules['pep8']) == 1 | |
12 | assert stdin.modules['pep8'] == [pep8] | |
13 | assert len(stdin.modules['pycodestyle']) == 1 | |
14 | assert stdin.modules['pycodestyle'] == [pycodestyle] | |
15 | assert len(stdin.modules['all']) == 2 | |
16 | assert stdin.modules['all'] == [pep8, pycodestyle] | |
15 | assert len(stdin.modules["pep8"]) == 1 | |
16 | assert stdin.modules["pep8"] == [pep8] | |
17 | assert len(stdin.modules["pycodestyle"]) == 1 | |
18 | assert stdin.modules["pycodestyle"] == [pycodestyle] | |
19 | assert len(stdin.modules["all"]) == 2 | |
20 | assert stdin.modules["all"] == [pep8, pycodestyle] | |
17 | 21 | |
18 | 22 | |
19 | 23 | @pytest.fixture |
44 | 48 | # better way to test these. |
45 | 49 | def test_monkey_patch_all(pep8_mod, pycodestyle_mod): |
46 | 50 | """Verify we monkey patch everything.""" |
47 | stdin.monkey_patch('all') | |
51 | stdin.monkey_patch("all") | |
48 | 52 | assert pep8_mod.stdin_get_value is pycodestyle_mod.stdin_get_value |
49 | 53 | |
50 | 54 | |
51 | 55 | @pytest.mark.skipif( |
52 | 56 | (2, 5) < version.version_info < (2, 7), |
53 | reason='They are the same on everything less than 2.6.' | |
57 | reason="They are the same on everything less than 2.6.", | |
54 | 58 | ) |
55 | 59 | def test_monkey_patch_pep8(pep8_mod): |
56 | 60 | """Verify we monkey patch pep8 only.""" |
57 | stdin.monkey_patch('pep8') | |
61 | stdin.monkey_patch("pep8") | |
58 | 62 | assert pep8_mod.stdin_get_value is not pycodestyle.stdin_get_value |
59 | 63 | |
60 | 64 | |
61 | 65 | @pytest.mark.skipif( |
62 | 66 | version.version_info < (2, 6), |
63 | reason='They are the same on everything less than 2.6.' | |
67 | reason="They are the same on everything less than 2.6.", | |
64 | 68 | ) |
65 | 69 | def test_monkey_patch_pycodestyle(pycodestyle_mod): |
66 | 70 | """Verify we monkey patch pycodestyle only.""" |
67 | stdin.monkey_patch('pycodestyle') | |
71 | stdin.monkey_patch("pycodestyle") | |
68 | 72 | assert pep8.stdin_get_value is not pycodestyle_mod.stdin_get_value |
69 | 73 | |
70 | 74 | |
71 | 75 | @pytest.mark.skipif( |
72 | 76 | version.version_info < (3, 0) or version.version_info > (4, 0), |
73 | reason='Requires Flake8 3.x' | |
77 | reason="Requires Flake8 3.x", | |
74 | 78 | ) |
75 | 79 | def test_uses_flake8_util_stdin(pep8_mod, pycodestyle_mod): |
76 | 80 | """Verify we monkey-patch using internal flake8 functions.""" |
77 | 81 | import flake8.utils |
78 | 82 | |
79 | stdin.monkey_patch('all') | |
83 | stdin.monkey_patch("all") | |
80 | 84 | assert pep8_mod.stdin_get_value is flake8.utils.stdin_get_value |
81 | 85 | assert pycodestyle_mod.stdin_get_value is flake8.utils.stdin_get_value |