Merge ~cjwatson/lazr.config:drop-py2 into lazr.config:main
- Git
- lp:~cjwatson/lazr.config
- drop-py2
- Merge into main
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | e5cd66ae708ad90f3fc51ca405bd6aae52366758 |
Proposed branch: | ~cjwatson/lazr.config:drop-py2 |
Merge into: | lazr.config:main |
Diff against target: |
308 lines (+27/-50) 11 files modified
.pre-commit-config.yaml (+4/-0) NEWS.rst (+3/-3) pyproject.toml (+1/-0) setup.py (+1/-1) src/lazr/config/_config.py (+15/-25) src/lazr/config/_version.py (+1/-1) src/lazr/config/docs/conf.py (+0/-2) src/lazr/config/interfaces.py (+1/-4) src/lazr/config/tests/test_config.py (+0/-3) src/lazr/config/tests/test_docs.py (+1/-10) tox.ini (+0/-1) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Guruprasad | Approve | ||
Review via email: mp+437444@code.launchpad.net |
Commit message
Drop Python 2 support
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml | |||
2 | index 6382dc7..4753587 100644 | |||
3 | --- a/.pre-commit-config.yaml | |||
4 | +++ b/.pre-commit-config.yaml | |||
5 | @@ -18,6 +18,10 @@ repos: | |||
6 | 18 | - id: black | 18 | - id: black |
7 | 19 | # skip namespace package declaration | 19 | # skip namespace package declaration |
8 | 20 | exclude: ^src/lazr/__init__\.py$ | 20 | exclude: ^src/lazr/__init__\.py$ |
9 | 21 | - repo: https://github.com/asottile/pyupgrade | ||
10 | 22 | rev: v3.3.1 | ||
11 | 23 | hooks: | ||
12 | 24 | - id: pyupgrade | ||
13 | 21 | - repo: https://github.com/PyCQA/isort | 25 | - repo: https://github.com/PyCQA/isort |
14 | 22 | rev: 5.12.0 | 26 | rev: 5.12.0 |
15 | 23 | hooks: | 27 | hooks: |
16 | diff --git a/NEWS.rst b/NEWS.rst | |||
17 | index d298c85..ea61f16 100644 | |||
18 | --- a/NEWS.rst | |||
19 | +++ b/NEWS.rst | |||
20 | @@ -2,14 +2,14 @@ | |||
21 | 2 | NEWS for lazr.config | 2 | NEWS for lazr.config |
22 | 3 | ==================== | 3 | ==================== |
23 | 4 | 4 | ||
26 | 5 | 2.2.4 | 5 | 3.0 |
27 | 6 | ===== | 6 | === |
28 | 7 | - Add basic pre-commit configuration. | 7 | - Add basic pre-commit configuration. |
29 | 8 | - Publish Documentation on Read the Docs. | 8 | - Publish Documentation on Read the Docs. |
30 | 9 | - Apply inclusive naming via the woke pre-commit hook. | 9 | - Apply inclusive naming via the woke pre-commit hook. |
31 | 10 | - Test using ``zope.testrunner`` rather than ``nose``. | 10 | - Test using ``zope.testrunner`` rather than ``nose``. |
32 | 11 | - Officially add support for Python 3.9 and 3.10. | 11 | - Officially add support for Python 3.9 and 3.10. |
34 | 12 | - Drop support for Python 2.6 and 3.4. | 12 | - Drop support for Python 2.6, 2.7, and 3.4. |
35 | 13 | - Apply ``black`` and ``isort``. | 13 | - Apply ``black`` and ``isort``. |
36 | 14 | 14 | ||
37 | 15 | 2.2.3 (2021-01-26) | 15 | 2.2.3 (2021-01-26) |
38 | diff --git a/pyproject.toml b/pyproject.toml | |||
39 | index a8f43fe..1eb96ee 100644 | |||
40 | --- a/pyproject.toml | |||
41 | +++ b/pyproject.toml | |||
42 | @@ -1,2 +1,3 @@ | |||
43 | 1 | [tool.black] | 1 | [tool.black] |
44 | 2 | line-length = 79 | 2 | line-length = 79 |
45 | 3 | target-version = ["py35"] | ||
46 | diff --git a/setup.py b/setup.py | |||
47 | index 5448a20..f5a5da9 100755 | |||
48 | --- a/setup.py | |||
49 | +++ b/setup.py | |||
50 | @@ -61,7 +61,6 @@ files. The format supports schema validation. | |||
51 | 61 | "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", # noqa | 61 | "License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)", # noqa |
52 | 62 | "Operating System :: OS Independent", | 62 | "Operating System :: OS Independent", |
53 | 63 | "Programming Language :: Python", | 63 | "Programming Language :: Python", |
54 | 64 | "Programming Language :: Python :: 2.7", | ||
55 | 65 | "Programming Language :: Python :: 3", | 64 | "Programming Language :: Python :: 3", |
56 | 66 | "Programming Language :: Python :: 3.5", | 65 | "Programming Language :: Python :: 3.5", |
57 | 67 | "Programming Language :: Python :: 3.6", | 66 | "Programming Language :: Python :: 3.6", |
58 | @@ -73,4 +72,5 @@ files. The format supports schema validation. | |||
59 | 73 | extras_require=dict( | 72 | extras_require=dict( |
60 | 74 | docs=["Sphinx"], | 73 | docs=["Sphinx"], |
61 | 75 | ), | 74 | ), |
62 | 75 | python_requires=">=3.5", | ||
63 | 76 | ) | 76 | ) |
64 | diff --git a/src/lazr/config/_config.py b/src/lazr/config/_config.py | |||
65 | index 0f12bf7..b8a56a7 100644 | |||
66 | --- a/src/lazr/config/_config.py | |||
67 | +++ b/src/lazr/config/_config.py | |||
68 | @@ -16,9 +16,6 @@ | |||
69 | 16 | 16 | ||
70 | 17 | """Implementation classes for config.""" | 17 | """Implementation classes for config.""" |
71 | 18 | 18 | ||
72 | 19 | from __future__ import absolute_import, print_function, unicode_literals | ||
73 | 20 | |||
74 | 21 | __metaclass__ = type | ||
75 | 22 | __all__ = [ | 19 | __all__ = [ |
76 | 23 | "Config", | 20 | "Config", |
77 | 24 | "ConfigData", | 21 | "ConfigData", |
78 | @@ -41,7 +38,6 @@ import logging | |||
79 | 41 | import os | 38 | import os |
80 | 42 | import pwd | 39 | import pwd |
81 | 43 | import re | 40 | import re |
82 | 44 | import sys | ||
83 | 45 | from os.path import abspath, basename, dirname | 41 | from os.path import abspath, basename, dirname |
84 | 46 | from textwrap import dedent | 42 | from textwrap import dedent |
85 | 47 | 43 | ||
86 | @@ -86,7 +82,7 @@ _missing = object() | |||
87 | 86 | 82 | ||
88 | 87 | def read_content(filename): | 83 | def read_content(filename): |
89 | 88 | """Return the content of a file at filename as a string.""" | 84 | """Return the content of a file at filename as a string.""" |
91 | 89 | with open(filename, "rt") as fp: | 85 | with open(filename) as fp: |
92 | 90 | return fp.read() | 86 | return fp.read() |
93 | 91 | 87 | ||
94 | 92 | 88 | ||
95 | @@ -111,8 +107,7 @@ class SectionSchema: | |||
96 | 111 | 107 | ||
97 | 112 | def __iter__(self): | 108 | def __iter__(self): |
98 | 113 | """See `ISectionSchema`""" | 109 | """See `ISectionSchema`""" |
101 | 114 | for key in self._options.keys(): | 110 | yield from self._options.keys() |
100 | 115 | yield key | ||
102 | 116 | 111 | ||
103 | 117 | def __contains__(self, name): | 112 | def __contains__(self, name): |
104 | 118 | """See `ISectionSchema`""" | 113 | """See `ISectionSchema`""" |
105 | @@ -150,7 +145,7 @@ class Section: | |||
106 | 150 | # Use __dict__ because __getattr__ limits access to self.options. | 145 | # Use __dict__ because __getattr__ limits access to self.options. |
107 | 151 | self.__dict__["schema"] = schema | 146 | self.__dict__["schema"] = schema |
108 | 152 | if _options is None: | 147 | if _options is None: |
110 | 153 | _options = dict((key, schema[key]) for key in schema) | 148 | _options = {key: schema[key] for key in schema} |
111 | 154 | self.__dict__["_options"] = _options | 149 | self.__dict__["_options"] = _options |
112 | 155 | 150 | ||
113 | 156 | def __getitem__(self, key): | 151 | def __getitem__(self, key): |
114 | @@ -184,7 +179,7 @@ class Section: | |||
115 | 184 | if key in self._options: | 179 | if key in self._options: |
116 | 185 | self._options[key] = value | 180 | self._options[key] = value |
117 | 186 | else: | 181 | else: |
119 | 187 | msg = "%s does not have a %s key." % (self.name, key) | 182 | msg = "{} does not have a {} key.".format(self.name, key) |
120 | 188 | errors.append(UnknownKeyError(msg)) | 183 | errors.append(UnknownKeyError(msg)) |
121 | 189 | return errors | 184 | return errors |
122 | 190 | 185 | ||
123 | @@ -240,12 +235,12 @@ class ImplicitTypeSection(Section): | |||
124 | 240 | 235 | ||
125 | 241 | def __getitem__(self, key): | 236 | def __getitem__(self, key): |
126 | 242 | """See `ISection`.""" | 237 | """See `ISection`.""" |
128 | 243 | value = super(ImplicitTypeSection, self).__getitem__(key) | 238 | value = super().__getitem__(key) |
129 | 244 | return self._convert(value) | 239 | return self._convert(value) |
130 | 245 | 240 | ||
131 | 246 | def __getattr__(self, name): | 241 | def __getattr__(self, name): |
132 | 247 | """See `ISection`.""" | 242 | """See `ISection`.""" |
134 | 248 | value = super(ImplicitTypeSection, self).__getattr__(name) | 243 | value = super().__getattr__(name) |
135 | 249 | return self._convert(value) | 244 | return self._convert(value) |
136 | 250 | 245 | ||
137 | 251 | 246 | ||
138 | @@ -396,8 +391,7 @@ class ConfigSchema: | |||
139 | 396 | 391 | ||
140 | 397 | def __iter__(self): | 392 | def __iter__(self): |
141 | 398 | """See `IConfigSchema`.""" | 393 | """See `IConfigSchema`.""" |
144 | 399 | for value in self._section_schemas.values(): | 394 | yield from self._section_schemas.values() |
143 | 400 | yield value | ||
145 | 401 | 395 | ||
146 | 402 | def __contains__(self, name): | 396 | def __contains__(self, name): |
147 | 403 | """See `IConfigSchema`.""" | 397 | """See `IConfigSchema`.""" |
148 | @@ -500,8 +494,7 @@ class ConfigData: | |||
149 | 500 | 494 | ||
150 | 501 | def __iter__(self): | 495 | def __iter__(self): |
151 | 502 | """See `IConfigData`.""" | 496 | """See `IConfigData`.""" |
154 | 503 | for value in self._sections.values(): | 497 | yield from self._sections.values() |
153 | 504 | yield value | ||
155 | 505 | 498 | ||
156 | 506 | def __contains__(self, name): | 499 | def __contains__(self, name): |
157 | 507 | """See `IConfigData`.""" | 500 | """See `IConfigData`.""" |
158 | @@ -618,16 +611,13 @@ class Config: | |||
159 | 618 | # option and in Python 3.2, this argument changed its default from | 611 | # option and in Python 3.2, this argument changed its default from |
160 | 619 | # False to True. This breaks behavior compatibility with Python 2, so | 612 | # False to True. This breaks behavior compatibility with Python 2, so |
161 | 620 | # under Python 3, always force strict=False. | 613 | # under Python 3, always force strict=False. |
166 | 621 | kws = {} | 614 | parser = RawConfigParser(strict=False) |
163 | 622 | if sys.version_info >= (3,): | ||
164 | 623 | kws["strict"] = False | ||
165 | 624 | parser = RawConfigParser(**kws) | ||
167 | 625 | _parser_read_file(parser, StringIO(conf_data), conf_filename) | 615 | _parser_read_file(parser, StringIO(conf_data), conf_filename) |
168 | 626 | confs.append((conf_filename, parser, encoding_errors)) | 616 | confs.append((conf_filename, parser, encoding_errors)) |
169 | 627 | if parser.has_option("meta", "extends"): | 617 | if parser.has_option("meta", "extends"): |
170 | 628 | base_path = dirname(conf_filename) | 618 | base_path = dirname(conf_filename) |
171 | 629 | extends_name = parser.get("meta", "extends") | 619 | extends_name = parser.get("meta", "extends") |
173 | 630 | extends_filename = abspath("%s/%s" % (base_path, extends_name)) | 620 | extends_filename = abspath("{}/{}".format(base_path, extends_name)) |
174 | 631 | extends_data = read_content(extends_filename) | 621 | extends_data = read_content(extends_filename) |
175 | 632 | self._getExtendedConfs(extends_filename, extends_data, confs) | 622 | self._getExtendedConfs(extends_filename, extends_data, confs) |
176 | 633 | return confs | 623 | return confs |
177 | @@ -676,7 +666,7 @@ class Config: | |||
178 | 676 | and master_name not in self.schema | 666 | and master_name not in self.schema |
179 | 677 | ): | 667 | ): |
180 | 678 | # Any section not in the the schema is an error. | 668 | # Any section not in the the schema is an error. |
182 | 679 | msg = "%s does not have a %s section." % ( | 669 | msg = "{} does not have a {} section.".format( |
183 | 680 | self.schema.name, | 670 | self.schema.name, |
184 | 681 | section_name, | 671 | section_name, |
185 | 682 | ) | 672 | ) |
186 | @@ -784,7 +774,7 @@ class Category: | |||
187 | 784 | 774 | ||
188 | 785 | def __getattr__(self, name): | 775 | def __getattr__(self, name): |
189 | 786 | """See `ICategory`.""" | 776 | """See `ICategory`.""" |
191 | 787 | full_name = "%s.%s" % (self.name, name) | 777 | full_name = "{}.{}".format(self.name, name) |
192 | 788 | if full_name in self._sections: | 778 | if full_name in self._sections: |
193 | 789 | return self._sections[full_name] | 779 | return self._sections[full_name] |
194 | 790 | raise AttributeError("No section named %s." % name) | 780 | raise AttributeError("No section named %s." % name) |
195 | @@ -872,10 +862,10 @@ def as_timedelta(value): | |||
196 | 872 | # Complain if the components are out of order. | 862 | # Complain if the components are out of order. |
197 | 873 | if "".join(components) != value: | 863 | if "".join(components) != value: |
198 | 874 | raise ValueError | 864 | raise ValueError |
201 | 875 | keywords = dict( | 865 | keywords = { |
202 | 876 | (interval[0].lower(), interval) | 866 | interval[0].lower(): interval |
203 | 877 | for interval in ("weeks", "days", "hours", "minutes", "seconds") | 867 | for interval in ("weeks", "days", "hours", "minutes", "seconds") |
205 | 878 | ) | 868 | } |
206 | 879 | keyword_arguments = {} | 869 | keyword_arguments = {} |
207 | 880 | for interval in components: | 870 | for interval in components: |
208 | 881 | if len(interval) == 0: | 871 | if len(interval) == 0: |
209 | diff --git a/src/lazr/config/_version.py b/src/lazr/config/_version.py | |||
210 | index f394e69..ecd0eec 100644 | |||
211 | --- a/src/lazr/config/_version.py | |||
212 | +++ b/src/lazr/config/_version.py | |||
213 | @@ -1 +1 @@ | |||
215 | 1 | __version__ = "2.2.3" | 1 | __version__ = "3.0.dev0" |
216 | diff --git a/src/lazr/config/docs/conf.py b/src/lazr/config/docs/conf.py | |||
217 | index f9eabe9..160b12a 100644 | |||
218 | --- a/src/lazr/config/docs/conf.py | |||
219 | +++ b/src/lazr/config/docs/conf.py | |||
220 | @@ -1,5 +1,3 @@ | |||
221 | 1 | # -*- coding: utf-8 -*- | ||
222 | 2 | # | ||
223 | 3 | # lazr.config documentation build configuration file, created by | 1 | # lazr.config documentation build configuration file, created by |
224 | 4 | # sphinx-quickstart on Mon Jan 7 10:37:37 2013. | 2 | # sphinx-quickstart on Mon Jan 7 10:37:37 2013. |
225 | 5 | # | 3 | # |
226 | diff --git a/src/lazr/config/interfaces.py b/src/lazr/config/interfaces.py | |||
227 | index 3c6527e..273c7c3 100644 | |||
228 | --- a/src/lazr/config/interfaces.py | |||
229 | +++ b/src/lazr/config/interfaces.py | |||
230 | @@ -17,9 +17,6 @@ | |||
231 | 17 | # pylint: disable-msg=E0211,E0213,W0231 | 17 | # pylint: disable-msg=E0211,E0213,W0231 |
232 | 18 | """Interfaces for process configuration..""" | 18 | """Interfaces for process configuration..""" |
233 | 19 | 19 | ||
234 | 20 | from __future__ import absolute_import, print_function, unicode_literals | ||
235 | 21 | |||
236 | 22 | __metaclass__ = type | ||
237 | 23 | __all__ = [ | 20 | __all__ = [ |
238 | 24 | "ConfigErrors", | 21 | "ConfigErrors", |
239 | 25 | "ConfigSchemaError", | 22 | "ConfigSchemaError", |
240 | @@ -90,7 +87,7 @@ class ConfigErrors(ConfigSchemaError): | |||
241 | 90 | self.errors = errors | 87 | self.errors = errors |
242 | 91 | 88 | ||
243 | 92 | def __str__(self): | 89 | def __str__(self): |
245 | 93 | return "%s: %s" % (self.__class__.__name__, self.message) | 90 | return "{}: {}".format(self.__class__.__name__, self.message) |
246 | 94 | 91 | ||
247 | 95 | 92 | ||
248 | 96 | class ISectionSchema(Interface): | 93 | class ISectionSchema(Interface): |
249 | diff --git a/src/lazr/config/tests/test_config.py b/src/lazr/config/tests/test_config.py | |||
250 | index 723e3e2..8817325 100644 | |||
251 | --- a/src/lazr/config/tests/test_config.py | |||
252 | +++ b/src/lazr/config/tests/test_config.py | |||
253 | @@ -16,9 +16,6 @@ | |||
254 | 16 | 16 | ||
255 | 17 | """Tests of lazr.config.""" | 17 | """Tests of lazr.config.""" |
256 | 18 | 18 | ||
257 | 19 | from __future__ import absolute_import, print_function, unicode_literals | ||
258 | 20 | |||
259 | 21 | __metaclass__ = type | ||
260 | 22 | __all__ = [ | 19 | __all__ = [ |
261 | 23 | "TestConfig", | 20 | "TestConfig", |
262 | 24 | ] | 21 | ] |
263 | diff --git a/src/lazr/config/tests/test_docs.py b/src/lazr/config/tests/test_docs.py | |||
264 | index 4c17208..698a94d 100644 | |||
265 | --- a/src/lazr/config/tests/test_docs.py | |||
266 | +++ b/src/lazr/config/tests/test_docs.py | |||
267 | @@ -16,9 +16,6 @@ | |||
268 | 16 | 16 | ||
269 | 17 | """Test harness for doctests.""" | 17 | """Test harness for doctests.""" |
270 | 18 | 18 | ||
271 | 19 | from __future__ import absolute_import, print_function, unicode_literals | ||
272 | 20 | |||
273 | 21 | __metaclass__ = type | ||
274 | 22 | __all__ = [] | 19 | __all__ = [] |
275 | 23 | 20 | ||
276 | 24 | import atexit | 21 | import atexit |
277 | @@ -49,18 +46,12 @@ def load_tests(loader, tests, pattern): | |||
278 | 49 | ) | 46 | ) |
279 | 50 | ) | 47 | ) |
280 | 51 | atexit.register(cleanup_resources) | 48 | atexit.register(cleanup_resources) |
281 | 52 | globs = { | ||
282 | 53 | "absolute_import": absolute_import, | ||
283 | 54 | "print_function": print_function, | ||
284 | 55 | "unicode_literals": unicode_literals, | ||
285 | 56 | } | ||
286 | 57 | tests.addTest( | 49 | tests.addTest( |
287 | 58 | doctest.DocFileSuite( | 50 | doctest.DocFileSuite( |
288 | 59 | *doctest_files, | 51 | *doctest_files, |
289 | 60 | module_relative=False, | 52 | module_relative=False, |
290 | 61 | optionflags=DOCTEST_FLAGS, | 53 | optionflags=DOCTEST_FLAGS, |
293 | 62 | globs=globs, | 54 | encoding="UTF-8", |
292 | 63 | encoding="UTF-8" | ||
294 | 64 | ) | 55 | ) |
295 | 65 | ) | 56 | ) |
296 | 66 | return tests | 57 | return tests |
297 | diff --git a/tox.ini b/tox.ini | |||
298 | index 186f2bd..4615990 100644 | |||
299 | --- a/tox.ini | |||
300 | +++ b/tox.ini | |||
301 | @@ -1,7 +1,6 @@ | |||
302 | 1 | [tox] | 1 | [tox] |
303 | 2 | envlist = | 2 | envlist = |
304 | 3 | pre-commit | 3 | pre-commit |
305 | 4 | py27 | ||
306 | 5 | py35 | 4 | py35 |
307 | 6 | py36 | 5 | py36 |
308 | 7 | py37 | 6 | py37 |
LGTM 👍