Skip to content

Commit 70605db

Browse files
Workflow maintenance and improvements 🐍
1 parent a23a2e7 commit 70605db

19 files changed

+155
-121
lines changed

.github/workflows/build.yml

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

1616
jobs:
1717
build:
18-
runs-on: ubuntu-18.04
18+
runs-on: ubuntu-latest
1919
strategy:
2020
matrix:
21-
python-version: [3.7, 3.8, 3.9, "3.10"]
21+
python-version: [3.8, 3.9, "3.10", "3.11"]
2222

2323
steps:
2424
- uses: actions/checkout@v1
@@ -27,7 +27,7 @@ jobs:
2727
submodules: false
2828

2929
- name: Use Python ${{ matrix.python-version }}
30-
uses: actions/setup-python@v1
30+
uses: actions/setup-python@v4
3131
with:
3232
python-version: ${{ matrix.python-version }}
3333

@@ -48,7 +48,15 @@ jobs:
4848
4949
- name: Run tests
5050
run: |
51-
flake8 && pytest --doctest-modules --junitxml=junit/pytest-results-${{ matrix.python-version }}.xml --cov=$PROJECT_NAME --cov-report=xml tests/
51+
pytest --doctest-modules --junitxml=junit/pytest-results-${{ matrix.python-version }}.xml --cov=$PROJECT_NAME --cov-report=xml tests/
52+
53+
- name: Run linters
54+
run: |
55+
echo "Running linters"
56+
57+
flake8 .
58+
isort --check-only . 2>&1
59+
black --check . 2>&1
5260
5361
- name: Upload pytest test results
5462
uses: actions/upload-artifact@master
@@ -63,28 +71,28 @@ jobs:
6371
6472
- name: Install distribution dependencies
6573
run: pip install --upgrade twine setuptools wheel
66-
if: matrix.python-version == 3.8 || matrix.python-version == 3.9
74+
if: matrix.python-version == 3.10
6775

6876
- name: Create distribution package
6977
run: python setup.py sdist bdist_wheel
70-
if: matrix.python-version == 3.8 || matrix.python-version == 3.9
78+
if: matrix.python-version == 3.10
7179

7280
- name: Upload distribution package
7381
uses: actions/upload-artifact@master
7482
with:
7583
name: dist-package-${{ matrix.python-version }}
7684
path: dist
77-
if: matrix.python-version == 3.8 || matrix.python-version == 3.9
85+
if: matrix.python-version == 3.10
7886

7987
publish:
80-
runs-on: ubuntu-18.04
88+
runs-on: ubuntu-latest
8189
needs: build
8290
if: github.event_name == 'release'
8391
steps:
8492
- name: Download a distribution artifact
8593
uses: actions/download-artifact@v2
8694
with:
87-
name: dist-package-3.9
95+
name: dist-package-3.10
8896
path: dist
8997
- name: Publish distribution 📦 to Test PyPI
9098
uses: pypa/gh-action-pypi-publish@master

.isort.cfg

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[settings]
2+
profile = black
3+
multi_line_output = 3

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [1.1.6] - 2022-11-05 :snake:
9+
- Workflow maintenance
10+
- Applies `black`, `flake8`, `isort`
11+
812
## [1.1.5] - 2022-03-14 :tulip:
913
- Adds `py.typed` file
1014
- Adds `ConflictException`

essentials/caching.py

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
import functools
22
import time
33
from collections import OrderedDict
4-
from typing import (Any, Callable, Generic, Iterable, Iterator, Tuple, TypeVar)
5-
4+
from typing import Any, Callable, Generic, Iterable, Iterator, Tuple, TypeVar
65

76
T = TypeVar("T")
87

98

109
class Cache(Generic[T]):
1110
"""In-memory LRU cache implementation."""
1211

13-
def __init__(
14-
self,
15-
max_size: int = 500
16-
):
12+
def __init__(self, max_size: int = 500):
1713
self._bag: OrderedDict[Any, Any] = OrderedDict()
1814
self._max_size = -1
1915
self.max_size = max_size
@@ -87,10 +83,7 @@ def clear(self) -> None:
8783
class CachedItem(Generic[T]):
8884
"""Container for cached items with update timestamp."""
8985

90-
__slots__ = (
91-
'_value',
92-
'_time'
93-
)
86+
__slots__ = ("_value", "_time")
9487

9588
def __init__(self, value: T):
9689
self._value = value
@@ -114,9 +107,7 @@ class ExpiringCache(Cache[T]):
114107
"""A cache whose items can expire by a given function."""
115108

116109
def __init__(
117-
self,
118-
expiration_policy: Callable[[CachedItem[T]], bool],
119-
max_size: int = 500
110+
self, expiration_policy: Callable[[CachedItem[T]], bool], max_size: int = 500
120111
):
121112
super().__init__(max_size)
122113
assert expiration_policy is not None
@@ -157,17 +148,12 @@ def __setitem__(self, key, value: T) -> None:
157148
self._check_size()
158149

159150
@classmethod
160-
def with_max_age(
161-
cls,
162-
max_age: float,
163-
max_size: int = 500
164-
):
151+
def with_max_age(cls, max_age: float, max_size: int = 500):
165152
"""
166153
Returns an instance of ExpiringCache whose items are invalidated
167154
when they were set more than a given number of seconds ago.
168155
"""
169-
return cls(lambda item: time.time() - item.time > max_age,
170-
max_size)
156+
return cls(lambda item: time.time() - item.time > max_age, max_size)
171157

172158
def __contains__(self, key) -> bool:
173159
if key not in self._bag:
@@ -188,10 +174,7 @@ def __iter__(self) -> Iterator[Tuple[Any, T]]:
188174
yield (key, item.value)
189175

190176

191-
def lazy(
192-
max_seconds: int = 1,
193-
cache=None
194-
):
177+
def lazy(max_seconds: int = 1, cache=None):
195178
"""
196179
Wraps a function so that it is called up to once
197180
every max_seconds, by input arguments.
@@ -217,6 +200,7 @@ def wrapper(*args):
217200
value = fn(*args)
218201
cache[args] = (value, now)
219202
return value
203+
220204
return wrapper
221205

222206
return lazy_decorator

essentials/decorators/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
from functools import wraps
22
from inspect import iscoroutinefunction
33
from typing import Type
4-
from .retry import retry, CatchException, OnException # noqa
4+
5+
from .retry import CatchException, OnException, retry # noqa
56

67

78
def exception_handle(
8-
exception_type: Type[Exception],
9-
catch_exceptions_types: CatchException = None
9+
exception_type: Type[Exception], catch_exceptions_types: CatchException = None
1010
):
1111
"""
1212
Wraps a given function to catch all exceptions that might happen during

essentials/decorators/retry.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import time
21
import asyncio
2+
import time
33
from functools import wraps
44
from inspect import iscoroutinefunction
5-
from typing import Optional, Tuple, Type, Union, Callable
6-
5+
from typing import Callable, Optional, Tuple, Type, Union
76

87
CatchException = Union[Tuple[Type[Exception]], Type[Exception], None]
98
OnException = Optional[Callable[[Type[Exception], int], None]]

essentials/meta.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,57 @@
11
import warnings
22
from functools import wraps
3+
from inspect import iscoroutinefunction
34

45

56
class DeprecatedException(Exception):
67
def __init__(self, param_name):
7-
super().__init__("Member `%s` is deprecated" % param_name)
8+
super().__init__("The function `%s` is deprecated" % param_name)
89

910

1011
def deprecated(message=None, raise_exception=False):
1112
"""
1213
This is a decorator which can be used to mark functions
1314
as deprecated. It will result in a warning being emitted
14-
when the function is used."""
15+
when the function is used, or optionally an exception raised.
16+
"""
1517
if message:
1618
message = " " + message
1719
else:
1820
message = ""
1921

20-
def _deprecated(f):
21-
@wraps(f)
22-
def wrapped(*args, **kwargs):
23-
warnings.warn_explicit(
24-
f"`{f.__name__}` is deprecated.{message}",
25-
category=DeprecationWarning,
26-
filename=f.__code__.co_filename,
27-
lineno=f.__code__.co_firstlineno + 1,
28-
)
22+
def _deprecated(fn):
23+
if iscoroutinefunction(fn):
24+
25+
@wraps(fn)
26+
async def async_wrapper(*args, **kwargs):
27+
with warnings.catch_warnings():
28+
warnings.simplefilter("always")
29+
warnings.warn_explicit(
30+
f"`{fn.__name__}` is deprecated.{message}",
31+
category=DeprecationWarning,
32+
filename=fn.__code__.co_filename,
33+
lineno=fn.__code__.co_firstlineno + 1,
34+
)
35+
if raise_exception:
36+
raise DeprecatedException(fn.__name__)
37+
return await fn(*args, **kwargs)
38+
39+
return async_wrapper
40+
41+
@wraps(fn)
42+
def wrapper(*args, **kwargs):
43+
with warnings.catch_warnings():
44+
warnings.simplefilter("always")
45+
warnings.warn_explicit(
46+
f"`{fn.__name__}` is deprecated.{message}",
47+
category=DeprecationWarning,
48+
filename=fn.__code__.co_filename,
49+
lineno=fn.__code__.co_firstlineno + 1,
50+
)
2951
if raise_exception:
30-
raise DeprecatedException(f.__name__)
31-
return f(*args, **kwargs)
52+
raise DeprecatedException(fn.__name__)
53+
return fn(*args, **kwargs)
3254

33-
return wrapped
55+
return wrapper
3456

3557
return _deprecated

requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ pytest-cov
33
pytest-asyncio
44
flake8
55
dataclasses==0.7;python_version<'3.7'
6+
isort
7+
black

setup.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ def readme():
88

99
setup(
1010
name="essentials",
11-
version="1.1.5",
12-
description="General purpose classes and functions, "
13-
"reusable in any kind of Python application",
11+
version="1.1.6",
12+
description="General purpose classes and functions",
1413
long_description=readme(),
1514
long_description_content_type="text/markdown",
1615
classifiers=[
@@ -21,6 +20,8 @@ def readme():
2120
"Programming Language :: Python :: 3.7",
2221
"Programming Language :: Python :: 3.8",
2322
"Programming Language :: Python :: 3.9",
23+
"Programming Language :: Python :: 3.10",
24+
"Programming Language :: Python :: 3.11",
2425
"Operating System :: OS Independent",
2526
],
2627
url="https://github.com/Neoteroi/essentials",

0 commit comments

Comments
 (0)