Skip to content

Commit 87ddf5c

Browse files
committed
Separate py36+ syntax: better syntax, less errors
Signed-off-by: Alexey Stepanov <penguinolog@gmail.com>
1 parent 95f2cdd commit 87ddf5c

File tree

9 files changed

+55
-205
lines changed

9 files changed

+55
-205
lines changed

.travis.yml

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,6 @@ install:
88
- pip install --upgrade pytest-cov coveralls
99

1010
_python:
11-
- &python34
12-
name: "Python 3.4"
13-
python: 3.4
14-
- &python35
15-
name: "Python 3.5"
16-
python: 3.5
1711
- &python36
1812
name: "Python 3.6"
1913
python: 3.6
@@ -22,9 +16,6 @@ _python:
2216
python: 3.7
2317
dist: xenial
2418
sudo: true
25-
- &pypy3
26-
name: "PyPy3"
27-
python: pypy3.5
2819

2920
_helpers:
3021
- &install_cython pip install --upgrade Cython
@@ -83,7 +74,7 @@ jobs:
8374
install:
8475
- *upgrade_python_toolset
8576
- *install_deps
86-
- pip install --upgrade "mypy >= 0.620"
77+
- pip install --upgrade "mypy >= 0.630"
8778
script:
8879
- mypy --strict advanced_descriptors
8980

@@ -109,21 +100,11 @@ jobs:
109100
script:
110101
- black --check advanced_descriptors
111102

112-
- stage: test
113-
<<: *python34
114-
- stage: test
115-
<<: *python35
116103
- stage: test
117104
<<: *python36
118105
- stage: test
119106
<<: *python37
120-
- stage: test
121-
<<: *pypy3
122107

123-
- <<: *test_cythonized
124-
<<: *python34
125-
- <<: *test_cythonized
126-
<<: *python35
127108
- <<: *test_cythonized
128109
<<: *python36
129110
- <<: *test_cythonized
@@ -133,16 +114,16 @@ jobs:
133114
# This prevents job from appearing in test plan unless commit is tagged:
134115
if: tag IS present
135116
# Run on pypy to build not cythonized wheel
136-
<<: *pypy3
117+
<<: *python37
137118
name: Build universal and cythonized bdist_wheel. Deploy bdist and sdist.
138119
services:
139120
- docker
140121
install:
141122
- *upgrade_python_toolset
123+
- *install_deps
142124
script:
143125
- ./tools/run_docker.sh "Advanced_Descriptors"
144126
before_deploy:
145-
- pip install -r build_requirements.txt
146127
- *build_package
147128
deploy:
148129
- provider: pypi

advanced_descriptors/advanced_property.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515

1616
"""Property with class-wide getter."""
1717

18-
import typing
19-
2018
__all__ = ("AdvancedProperty",)
2119

20+
import typing
21+
2222

2323
class AdvancedProperty(property):
2424
"""Property with class-wide getter.
@@ -134,7 +134,7 @@ def __init__(
134134
"""
135135
super(AdvancedProperty, self).__init__(fget=fget, fset=fset, fdel=fdel)
136136

137-
self.__fcget = fcget
137+
self.__fcget: typing.Optional[typing.Callable[[typing.Any], typing.Any]] = fcget
138138

139139
def __get__(self, instance: typing.Any, owner: typing.Any = None) -> typing.Any:
140140
"""Get descriptor.

advanced_descriptors/log_on_access.py

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515

1616
"""Property with logging on successful get/set/delete or failure."""
1717

18+
__all__ = ("LogOnAccess",)
19+
1820
import logging
1921
import sys
2022
import traceback
2123
import typing
2224

23-
__all__ = ("LogOnAccess",)
2425

25-
_logger = logging.getLogger(__name__) # type: logging.Logger
26+
_logger: logging.Logger = logging.getLogger(__name__)
2627

2728

2829
class LogOnAccess(property):
@@ -47,7 +48,7 @@ def __init__(
4748
log_success: bool = True,
4849
log_failure: bool = True,
4950
log_traceback: bool = True,
50-
override_name: typing.Optional[str] = None
51+
override_name: typing.Optional[str] = None,
5152
) -> None:
5253
"""Advanced property main entry point.
5354
@@ -88,7 +89,7 @@ def __init__(
8889
... def __init__(self, val = 'ok'):
8990
... self.val = val
9091
... def __repr__(self):
91-
... return '{cls}(val={self.val})'.format(cls=self.__class__.__name__, self=self)
92+
... return f'{self.__class__.__name__}(val={self.val})'
9293
... @LogOnAccess
9394
... def ok(self):
9495
... return self.val
@@ -165,17 +166,17 @@ def __init__(
165166
super(LogOnAccess, self).__init__(fget=fget, fset=fset, fdel=fdel, doc=doc)
166167

167168
if logger is None or isinstance(logger, logging.Logger):
168-
self.__logger = logger
169+
self.__logger: typing.Optional[logging.Logger] = logger
169170
else:
170171
self.__logger = logging.getLogger(logger)
171172

172-
self.__log_object_repr = log_object_repr
173-
self.__log_level = log_level
174-
self.__exc_level = exc_level
175-
self.__log_success = log_success
176-
self.__log_failure = log_failure
177-
self.__log_traceback = log_traceback
178-
self.__override_name = override_name
173+
self.__log_object_repr: bool = log_object_repr
174+
self.__log_level: int = log_level
175+
self.__exc_level: int = exc_level
176+
self.__log_success: bool = log_success
177+
self.__log_failure: bool = log_failure
178+
self.__log_traceback: bool = log_traceback
179+
self.__override_name: typing.Optional[str] = override_name
179180

180181
@property
181182
def __traceback(self) -> str:
@@ -186,18 +187,16 @@ def __traceback(self) -> str:
186187
stack = traceback.extract_stack()
187188
tb = traceback.extract_tb(exc_info[2])
188189
full_tb = stack[:1] + tb # cut decorator and build full traceback
189-
exc_line = traceback.format_exception_only(*exc_info[:2])
190+
exc_line: typing.List[str] = traceback.format_exception_only(*exc_info[:2])
190191
# Make standard traceback string
191192
tb_text = "\nTraceback (most recent call last):\n" + "".join(traceback.format_list(full_tb)) + "".join(exc_line)
192193
return tb_text
193194

194195
def __get_obj_source(self, instance: typing.Any, owner: typing.Optional[type] = None) -> str:
195196
"""Get object repr block."""
196197
if self.log_object_repr:
197-
return "{instance!r}".format(instance=instance)
198-
return "<{name}() at 0x{id:X}>".format(
199-
name=owner.__name__ if owner is not None else instance.__class__.__name__, id=id(instance)
200-
)
198+
return f"{instance!r}"
199+
return f"<{owner.__name__ if owner is not None else instance.__class__.__name__}() at 0x{id(instance):X}>"
201200

202201
def _get_logger_for_instance(self, instance: typing.Any) -> logging.Logger:
203202
"""Get logger for log calls.
@@ -229,26 +228,17 @@ def __get__(self, instance: typing.Any, owner: typing.Optional[type] = None) ->
229228
if instance is None or self.fget is None:
230229
raise AttributeError()
231230

232-
source = self.__get_obj_source(instance, owner)
233-
logger = self._get_logger_for_instance(instance)
231+
source: str = self.__get_obj_source(instance, owner)
232+
logger: logging.Logger = self._get_logger_for_instance(instance)
234233

235234
try:
236235
result = super(LogOnAccess, self).__get__(instance, owner)
237236
if self.log_success:
238-
logger.log(
239-
self.log_level,
240-
"{source}.{name} -> {result!r}".format(source=source, name=self.__name__, result=result),
241-
)
237+
logger.log(self.log_level, "%s.%s -> %r", source, self.__name__, result)
242238
return result
243239
except Exception:
244240
if self.log_failure:
245-
logger.log(
246-
self.exc_level,
247-
"Failed: {source}.{name}{traceback}".format(
248-
source=source, name=self.__name__, traceback=self.__traceback
249-
),
250-
exc_info=False,
251-
)
241+
logger.log(self.exc_level, "Failed: %s.%s%s", source, self.__name__, self.__traceback, exc_info=False)
252242
raise
253243

254244
def __set__(self, instance: typing.Any, value: typing.Any) -> None:
@@ -263,22 +253,22 @@ def __set__(self, instance: typing.Any, value: typing.Any) -> None:
263253
if self.fset is None:
264254
raise AttributeError()
265255

266-
source = self.__get_obj_source(instance)
267-
logger = self._get_logger_for_instance(instance)
256+
source: str = self.__get_obj_source(instance)
257+
logger: logging.Logger = self._get_logger_for_instance(instance)
268258

269259
try:
270260
super(LogOnAccess, self).__set__(instance, value)
271261
if self.log_success:
272-
logger.log(
273-
self.log_level, "{source}.{name} = {value!r}".format(source=source, name=self.__name__, value=value)
274-
)
262+
logger.log(self.log_level, "%s.%s = %r", source, self.__name__, value)
275263
except Exception:
276264
if self.log_failure:
277265
logger.log(
278266
self.exc_level,
279-
"Failed: {source}.{name} = {value!r}{traceback}".format(
280-
source=source, name=self.__name__, value=value, traceback=self.__traceback
281-
),
267+
"Failed: %s.%s = %r%s",
268+
source,
269+
self.__name__,
270+
value,
271+
self.__traceback,
282272
exc_info=False,
283273
)
284274
raise
@@ -294,21 +284,17 @@ def __delete__(self, instance: typing.Any) -> None:
294284
if self.fdel is None:
295285
raise AttributeError()
296286

297-
source = self.__get_obj_source(instance)
298-
logger = self._get_logger_for_instance(instance)
287+
source: str = self.__get_obj_source(instance)
288+
logger: logging.Logger = self._get_logger_for_instance(instance)
299289

300290
try:
301291
super(LogOnAccess, self).__delete__(instance)
302292
if self.log_success:
303-
logger.log(self.log_level, "del {source}.{name}".format(source=source, name=self.__name__))
293+
logger.log(self.log_level, "del %s.%s", source, self.__name__)
304294
except Exception:
305295
if self.log_failure:
306296
logger.log(
307-
self.exc_level,
308-
"{source}: Failed: del {name}{traceback}".format(
309-
source=source, name=self.__name__, traceback=self.__traceback
310-
),
311-
exc_info=False,
297+
self.exc_level, "%s: Failed: del %s%s", source, self.__name__, self.__traceback, exc_info=False
312298
)
313299
raise
314300

advanced_descriptors/separate_class_method.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515

1616
"""Separate class and instance methods with the same name."""
1717

18+
__all__ = ("SeparateClassMethod",)
19+
1820
import functools
1921
import typing
2022

21-
__all__ = ("SeparateClassMethod",)
22-
2323

2424
class SeparateClassMethod:
2525
"""Separate class method and instance methods with the same name.
@@ -92,7 +92,9 @@ class SeparateClassMethod:
9292
__slots__ = ("__instance_method", "__class_method", "__owner", "__name")
9393

9494
def __init__(
95-
self, imeth: typing.Optional[typing.Callable] = None, cmeth: typing.Optional[typing.Callable] = None
95+
self,
96+
imeth: typing.Optional[typing.Callable[..., typing.Any]] = None,
97+
cmeth: typing.Optional[typing.Callable[..., typing.Any]] = None,
9698
) -> None:
9799
"""Separate class method and instance methods.
98100
@@ -101,17 +103,17 @@ def __init__(
101103
:param cmeth: Class method
102104
:type cmeth: typing.Optional[typing.Callable]
103105
"""
104-
self.__instance_method = imeth
105-
self.__class_method = cmeth
106-
self.__owner = None
107-
self.__name = ""
106+
self.__instance_method: typing.Optional[typing.Callable[..., typing.Any]] = imeth
107+
self.__class_method: typing.Optional[typing.Callable[..., typing.Any]] = cmeth
108+
self.__owner: typing.Optional[typing.Any] = None
109+
self.__name: str = ""
108110

109111
def __set_name__(self, owner: typing.Any, name: str) -> None:
110112
"""Set __name__ and __objclass__ property."""
111113
self.__owner = owner
112114
self.__name = name
113115

114-
def __get__(self, instance: typing.Optional[typing.Any], owner: typing.Any) -> typing.Callable:
116+
def __get__(self, instance: typing.Optional[typing.Any], owner: typing.Any) -> typing.Callable[..., typing.Any]:
115117
"""Get descriptor.
116118
117119
:return: class method or instance method depends on call behavior
@@ -146,7 +148,7 @@ def __name__(self) -> str: # pragma: no cover
146148
"""Read-only name."""
147149
return self.__name
148150

149-
def instance_method(self, imeth: typing.Optional[typing.Callable]) -> "SeparateClassMethod":
151+
def instance_method(self, imeth: typing.Optional[typing.Callable[..., typing.Any]]) -> "SeparateClassMethod":
150152
"""Descriptor to change instance method.
151153
152154
:param imeth: New instance method.
@@ -157,7 +159,7 @@ def instance_method(self, imeth: typing.Optional[typing.Callable]) -> "SeparateC
157159
self.__instance_method = imeth
158160
return self
159161

160-
def class_method(self, cmeth: typing.Optional[typing.Callable]) -> "SeparateClassMethod":
162+
def class_method(self, cmeth: typing.Optional[typing.Callable[..., typing.Any]]) -> "SeparateClassMethod":
161163
"""Descriptor to change class method.
162164
163165
:param cmeth: New class method.
@@ -169,15 +171,15 @@ def class_method(self, cmeth: typing.Optional[typing.Callable]) -> "SeparateClas
169171
return self
170172

171173
@property
172-
def imeth(self) -> typing.Optional[typing.Callable]:
174+
def imeth(self) -> typing.Optional[typing.Callable[..., typing.Any]]:
173175
"""Instance method instance.
174176
175177
:rtype: typing.Optional[typing.Callable]
176178
"""
177179
return self.__instance_method
178180

179181
@property
180-
def cmeth(self) -> typing.Optional[typing.Callable]:
182+
def cmeth(self) -> typing.Optional[typing.Callable[..., typing.Any]]:
181183
"""Class method instance.
182184
183185
:rtype: typing.Optional[typing.Callable]

0 commit comments

Comments
 (0)