diff --git a/README.md b/README.md index 5b507eae82d3d22f1c2bbbca0027c97f63d9a7f2..e80884b1ebf4a67c53e56f05dbeba9726edf5b82 100644 --- a/README.md +++ b/README.md @@ -11,32 +11,32 @@ satella [](https://github.com/piotrmaslanka/satella) [](https://github.com/pylint-dev/pylint) - -Satella is an almost-zero-requirements Python 3.5+ library for writing -server applications. It has arisen out of my requirements to have some classes or design patterns handy, and kinda -wish-they-were-in-the-stdlib ones. especially those dealing with mundane but useful things. It also runs on PyPy, and -most of it runs on Windows (the part not dealing with forking processes, you see). +Satella is an almost-zero-requirements Python 3.5+ library for writing server applications. It has arisen out of my +requirements to have some classes or design patterns handy, and kinda wish-they-were-in-the-stdlib ones. especially +those dealing with mundane but useful things. It also runs on PyPy, and most of it runs on Windows (the part not dealing +with forking processes, you see). Satella uses [semantic versioning 2.0](https://semver.org/spec/v2.0.0.html). Satella contains, among other things: - + * things to help you manage your [application's configuration](satella/configuration) * a fully equipped [metrics library](satella/instrumentation/metrics) * alongside a fully metricized [ThreadPoolExecutor](satella/instrumentation/metrics/structures/threadpool.py) - * and an exporter to [Prometheus](satella/instrumentation/metrics/exporters/prometheus.py) or really any + * and an exporter to [Prometheus](satella/instrumentation/metrics/exporters/prometheus.py) or really any [OpenMetrics](https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md) compliant ingester * as well as exporters/metricizers for the following libraries: - * [AWS](https://github.com/piotrmaslanka/aws-satella) - * [FastAPI](https://github.com/Dronehub/fastapi-satella-metrics) - * [Django](https://github.com/piotrmaslanka/django-satella-metrics) - * [Flask](https://github.com/piotrmaslanka/flask-satella-metrics) -* helpful [exception handlers](satella/exception_handling) + * [AWS](https://github.com/piotrmaslanka/aws-satella) + * [FastAPI](https://github.com/Dronehub/fastapi-satella-metrics) + * [Django](https://github.com/piotrmaslanka/django-satella-metrics) + * [Flask](https://github.com/piotrmaslanka/flask-satella-metrics) +* helpful [exception handlers](satella/exception_handling) +* monitoring [CPU usage](satella/instrumentation/cpu_time/collectors) on the system and by your own process * common programming [idioms and structures](satella/coding) -Most Satella objects make heavy use of `__slots__`, so they are memory friendly and usable on -embedded systems, where memory is at premium. +Most Satella objects make heavy use of `__slots__`, so they are memory friendly and usable on embedded systems, where +memory is at premium. Change log is kept as part of [release notes](https://github.com/piotrmaslanka/satella/releases). The [CHANGELOG.md](CHANGELOG.md) file is only to track changes since last release. @@ -44,15 +44,13 @@ The [CHANGELOG.md](CHANGELOG.md) file is only to track changes since last releas Full [documentation](http://satella.readthedocs.io/en/latest/?badge=latest) is available for the brave souls that do decide to use this library. -See [LICENSE](LICENSE) for text of the license. This library may contain -code taken from elsewhere on the internets, so this is copyright (c) respective authors. +See [LICENSE](LICENSE) for text of the license. This library may contain code taken from elsewhere on the internets, so +this is copyright (c) respective authors. -# Running unit tests +Running unit tests +------------------ -Tests run by default on CircleCI. -Just build and run the attached -[Dockerfile](Dockerfile). -These tests run on Python 3.8 +Tests run by default on CircleCI. Just build and run the attached [Dockerfile](Dockerfile). These tests run on Python +3.8. Also, if you run it under PyPy it will launch some tests targeted at that platform. -They pass on Windows too, but some tests -requiring POSIX-like functionality are skipped. +They pass on Windows too, but some tests requiring POSIX-like functionality are skipped. diff --git a/satella/coding/__init__.py b/satella/coding/__init__.py index 20d3b7ea441e9502cb0e78b04d0f56074af3f7f4..d29657213076dc82348d5f221f296bea18004dd0 100644 --- a/satella/coding/__init__.py +++ b/satella/coding/__init__.py @@ -2,13 +2,16 @@ Just useful objects to make your coding nicer every day """ -from .ctxt_managers import EmptyContextManager from .algos import merge_dicts from .concurrent import Monitor, RMonitor +from .ctxt_managers import EmptyContextManager from .decorators import precondition, short_none, has_keys, \ wraps, chain_functions, postcondition, queue_get, auto_adapt_to_methods, \ attach_arguments, for_argument +from .deep_compare import assert_equal, InequalityReason, Inequal from .deleters import ListDeleter, DictDeleter +from .environment import Context +from .expect_exception import expect_exception from .fun_static import static_var from .iterators import hint_with_length, SelfClosingGenerator, exhaust, chain from .metaclasses import metaclass_maker, wrap_with, dont_wrap, wrap_property, DocsFromParent, \ @@ -17,12 +20,9 @@ from .misc import update_if_not_none, update_key_if_none, update_attr_if_none, q update_key_if_not_none, source_to_function, update_key_if_true, \ get_arguments, call_with_arguments, chain_callables, Closeable, contains, \ enum_value, length -from .environment import Context from .overloading import overload, class_or_instancemethod, TypeSignature from .recast_exceptions import rethrow_as, silence_excs, catch_exception, log_exceptions, \ raises_exception, reraise_as -from .expect_exception import expect_exception -from .deep_compare import assert_equal, InequalityReason, Inequal __all__ = [ 'EmptyContextManager', 'Context', 'length', diff --git a/satella/coding/concurrent/__init__.py b/satella/coding/concurrent/__init__.py index 7f4840a98b144c6887b1fa60904253b369256c7d..0ff36b46195c4baba1f2e85728b855cc69d9aea4 100644 --- a/satella/coding/concurrent/__init__.py +++ b/satella/coding/concurrent/__init__.py @@ -3,16 +3,16 @@ from .callablegroup import CallableGroup, CallNoOftenThan, CancellableCallback from .functions import parallel_execute, run_as_future from .futures import Future, WrappingFuture, InvalidStateError, FutureCollection from .id_allocator import IDAllocator, SequentialIssuer +from .list_processor import parallel_construct from .locked_dataset import LockedDataset from .locked_structure import LockedStructure from .monitor import MonitorList, Monitor, MonitorDict, RMonitor, MonitorSet +from .queue import PeekableQueue from .sync import sync_threadpool from .thread import TerminableThread, Condition, SingleStartThread, call_in_separate_thread, \ BogusTerminableThread, IntervalTerminableThread -from .timer import Timer from .thread_collection import ThreadCollection -from .queue import PeekableQueue -from .list_processor import parallel_construct +from .timer import Timer __all__ = ['LockedDataset', 'Monitor', 'RMonitor', 'CallableGroup', 'TerminableThread', 'MonitorDict', 'MonitorList', 'Condition', 'LockedStructure', 'AtomicNumber', diff --git a/satella/coding/concurrent/callablegroup.py b/satella/coding/concurrent/callablegroup.py index 8b8238ee215e35ee5ebb7b2fe34ccf69b388faf7..d08ae8ad8a41aede23adf6508f190105f27ec8a5 100644 --- a/satella/coding/concurrent/callablegroup.py +++ b/satella/coding/concurrent/callablegroup.py @@ -1,6 +1,5 @@ import collections import copy -import weakref import time import typing as tp diff --git a/satella/coding/concurrent/futures/__init__.py b/satella/coding/concurrent/futures/__init__.py index d7dda493809bed8a6ccc7a10d6a0c4539bd87e20..9c7ee85c786af05258662e66904e12dcc3d9d268 100644 --- a/satella/coding/concurrent/futures/__init__.py +++ b/satella/coding/concurrent/futures/__init__.py @@ -1,7 +1,7 @@ from .call_in_future import call_in_future +from .collection import FutureCollection from .futures import Future, WrappingFuture, InvalidStateError, wrap_if from .wrapped_executor import ExecutorWrapper -from .collection import FutureCollection __all__ = ['Future', 'WrappingFuture', 'InvalidStateError', 'call_in_future', 'ExecutorWrapper', 'wrap_if', 'FutureCollection'] diff --git a/satella/coding/concurrent/id_allocator.py b/satella/coding/concurrent/id_allocator.py index a9d2665398b1c9a6e72fa6160380ec91f5be0778..b702615582775bf88373fc5333db7f7ba9433f53 100644 --- a/satella/coding/concurrent/id_allocator.py +++ b/satella/coding/concurrent/id_allocator.py @@ -1,5 +1,6 @@ import math import typing as tp + from .monitor import Monitor from ...exceptions import AlreadyAllocated, Empty diff --git a/satella/coding/concurrent/monitor.py b/satella/coding/concurrent/monitor.py index de2df68b48540befbc2423f9350368aea486d47c..d9d2bee1b424edf41085270992ea8bd85b605615 100644 --- a/satella/coding/concurrent/monitor.py +++ b/satella/coding/concurrent/monitor.py @@ -4,7 +4,6 @@ import threading import typing as tp from satella.coding.decorators.decorators import wraps - from satella.coding.typing import K, V, T diff --git a/satella/coding/concurrent/queue.py b/satella/coding/concurrent/queue.py index cb4c5088a972e5fc9b05c2dfe411527e47b05103..4c34955b9213a1717284dde4d6a0aac79d5a4e86 100644 --- a/satella/coding/concurrent/queue.py +++ b/satella/coding/concurrent/queue.py @@ -1,10 +1,9 @@ -import typing as tp - import collections import threading +import typing as tp -from satella.coding.recast_exceptions import rethrow_as from satella.coding.concurrent.thread import Condition +from satella.coding.recast_exceptions import rethrow_as from satella.coding.typing import T from satella.exceptions import WouldWaitMore, Empty from satella.time.measure import measure diff --git a/satella/coding/concurrent/timer.py b/satella/coding/concurrent/timer.py index 4847ece079c3b8c68c63cbda77873d95214b987d..bdc5a3eb1e1bedaa51be707db836ebf78ceedc6f 100644 --- a/satella/coding/concurrent/timer.py +++ b/satella/coding/concurrent/timer.py @@ -1,10 +1,10 @@ -import typing as tp import logging import threading import time +import typing as tp -from satella.coding.recast_exceptions import log_exceptions from satella.coding.concurrent.monitor import Monitor +from satella.coding.recast_exceptions import log_exceptions from satella.coding.structures.heaps.time import TimeBasedHeap from satella.coding.structures.singleton import Singleton from satella.time.parse import parse_time_string diff --git a/satella/coding/decorators/arguments.py b/satella/coding/decorators/arguments.py index 8d7bcf03684d70504e84065f4a314dbe1c58a8d3..32fed98e48ebf2b0029347e2faa761d389b2da63 100644 --- a/satella/coding/decorators/arguments.py +++ b/satella/coding/decorators/arguments.py @@ -4,10 +4,10 @@ import itertools import typing as tp from inspect import Parameter -from satella.coding.typing import T, Predicate from satella.coding.decorators.decorators import wraps from satella.coding.misc import source_to_function, get_arguments, call_with_arguments, _get_arguments from satella.coding.predicates import PredicateClass, build_structure +from satella.coding.typing import T, Predicate U = tp.TypeVar('U') diff --git a/satella/coding/decorators/flow_control.py b/satella/coding/decorators/flow_control.py index 4f556f830cd7d88d64f2cbd53441074ad2d39a5f..5ad83c6e6ea9f8bb34b41ef9e028d645f51d6b99 100644 --- a/satella/coding/decorators/flow_control.py +++ b/satella/coding/decorators/flow_control.py @@ -11,10 +11,12 @@ def repeat_forever(fun): """ A decorator that will place your function inside a while True loop. """ + @wraps(fun) def inner(*args, **kwargs): while True: fun(*args, **kwargs) + doc = '' if inner.__doc__ is None else inner.__doc__ inner.__doc__ = doc + "\nThis will be repeated forever." return inner diff --git a/satella/coding/decorators/preconditions.py b/satella/coding/decorators/preconditions.py index ae6e55fe753266b21fb9732e5b5827b6e3794ec8..f27d4315d54bee6755186278c142a02659d6dd97 100644 --- a/satella/coding/decorators/preconditions.py +++ b/satella/coding/decorators/preconditions.py @@ -3,8 +3,8 @@ import typing as tp from satella.coding.typing import T, Predicate from satella.exceptions import PreconditionError -from .decorators import wraps from .arguments import for_argument +from .decorators import wraps from ..misc import source_to_function Expression = tp.NewType('Expression', str) diff --git a/satella/coding/expect_exception.py b/satella/coding/expect_exception.py index 2353f2dcff0c99a1cd8e14a76c50ed81dfb2fc45..0caea5e798ca7a73b1bee59aba571b5d1943f293 100644 --- a/satella/coding/expect_exception.py +++ b/satella/coding/expect_exception.py @@ -1,6 +1,7 @@ -from satella.coding.typing import ExceptionList import typing as tp +from satella.coding.typing import ExceptionList + class expect_exception: """ diff --git a/satella/coding/misc.py b/satella/coding/misc.py index da3a42d7dfe342923a40ba1e2a7978416fba723f..45fc3c11625872e66d6d854ef69f9c709490270e 100644 --- a/satella/coding/misc.py +++ b/satella/coding/misc.py @@ -2,10 +2,10 @@ import enum import typing as tp import warnings from inspect import Parameter, signature +from queue import Empty from queue import Queue from satella.coding.recast_exceptions import rethrow_as -from queue import Empty def enum_value(value): diff --git a/satella/coding/overloading.py b/satella/coding/overloading.py index 85f8607c1de7ce07174182bb25f489f532cc0d55..05cd3d1d5985a614973872ee91a2afad504f054e 100644 --- a/satella/coding/overloading.py +++ b/satella/coding/overloading.py @@ -1,13 +1,7 @@ from __future__ import annotations -import functools import inspect -import operator import typing as tp -from inspect import Parameter - -from satella.coding.structures import frozendict - # Taken from https://stackoverflow.com/questions/28237955/same-name-for-classmethod-and- @@ -34,7 +28,6 @@ class class_or_instancemethod(classmethod): class TypeSignature(inspect.Signature): - __slots__ = () def __init__(self, t_sign: inspect.Signature): @@ -140,4 +133,4 @@ class overload: if not matchings: raise TypeError('No matching entries!') else: - return matchings[-1][1](*args, **kwargs) # call the most specific function you could find + return matchings[-1][1](*args, **kwargs) # call the most specific function you could find diff --git a/satella/coding/resources/cp_manager.py b/satella/coding/resources/cp_manager.py index 600f59bc0ba63551417cb2c3e76b30b5a598d6b5..91fa3f3c26700cac482c7b1d2da823f926221caf 100644 --- a/satella/coding/resources/cp_manager.py +++ b/satella/coding/resources/cp_manager.py @@ -1,8 +1,8 @@ import abc +import logging +import queue import sys import typing as tp -import queue -import logging import warnings from ..concurrent import Monitor @@ -10,7 +10,6 @@ from ..misc import Closeable from ..recast_exceptions import silence_excs from ..typing import T - logger = logging.getLogger(__name__) @@ -48,7 +47,7 @@ class CPManager(Monitor, Closeable, tp.Generic[T], metaclass=abc.ABCMeta): self.connections = queue.Queue(max_number) self.max_number = max_number self.max_cycle_no = max_cycle_no - self.id_to_times = {} # type: tp.Dict[int, int] + self.id_to_times = {} # type: tp.Dict[int, int] self.terminating = False def close(self) -> None: @@ -140,4 +139,4 @@ class CPManager(Monitor, Closeable, tp.Generic[T], metaclass=abc.ABCMeta): Is safe to block. :return: a new connection instance - """ \ No newline at end of file + """ diff --git a/satella/coding/structures/__init__.py b/satella/coding/structures/__init__.py index 15abee15ade56975219ab6caafd0cdcccce5299c..c2198f2a23520ff8ef9485d7debfe35f3da11365 100644 --- a/satella/coding/structures/__init__.py +++ b/satella/coding/structures/__init__.py @@ -4,22 +4,22 @@ from .dictionaries import DictObject, apply_dict_object, DictionaryView, TwoWayD from .hashable_objects import HashableWrapper from .heaps import Heap, SetHeap, TimeBasedHeap, TimeBasedSetHeap from .immutable import Immutable, frozendict, NotEqualToAnything, NOT_EQUAL_TO_ANYTHING +from .lru import LRU from .mixins import OmniHashableMixin, ReprableMixin, StrEqHashableMixin, ComparableIntEnum, \ HashableIntEnum, ComparableAndHashableBy, ComparableAndHashableByInt, ComparableEnum, \ HashableMixin, ComparableAndHashableByStr, DictionaryEQAble, OnStrOnlyName from .proxy import Proxy +from .push_iterable import PushIterable from .queues import Subqueue from .ranking import Ranking from .singleton import Singleton, SingletonWithRegardsTo, get_instances_for_singleton, \ delete_singleton_for from .sorted_list import SortedList, SliceableDeque from .sparse_matrix import SparseMatrix -from .typednamedtuple import typednamedtuple -from .lru import LRU from .syncable_droppable import DBStorage, SyncableDroppable from .tuples import Vector +from .typednamedtuple import typednamedtuple from .zip_dict import SetZip -from .push_iterable import PushIterable __all__ = [ 'PushIterable', 'OnStrOnlyName', diff --git a/satella/coding/structures/dictionaries/__init__.py b/satella/coding/structures/dictionaries/__init__.py index ab0cd52fccbcfd02143da2251a2fe5ccaee40b10..d26a3df09a9402d1b6ad032ad49686618a912a54 100644 --- a/satella/coding/structures/dictionaries/__init__.py +++ b/satella/coding/structures/dictionaries/__init__.py @@ -1,10 +1,10 @@ from .cache_dict import CacheDict, LRUCacheDict from .counting import CountingDict +from .default import DefaultDict from .dict_object import apply_dict_object, DictObject from .expiring import ExpiringEntryDict, SelfCleaningDefaultDict from .objects import DirtyDict, DictionaryView, KeyAwareDefaultDict, TwoWayDictionary from .writeback_cache import ExclusiveWritebackCache -from .default import DefaultDict __all__ = ['DictObject', 'DirtyDict', 'DictionaryView', 'CacheDict', 'KeyAwareDefaultDict', 'TwoWayDictionary', 'apply_dict_object', 'ExpiringEntryDict', diff --git a/satella/coding/structures/dictionaries/expiring.py b/satella/coding/structures/dictionaries/expiring.py index 67c7c4db0b8d0fc5f3692124c8a26b545c0ec0e9..4d4e8ceeccf9370957cb125afca0d05a8cee7fa1 100644 --- a/satella/coding/structures/dictionaries/expiring.py +++ b/satella/coding/structures/dictionaries/expiring.py @@ -4,10 +4,10 @@ import typing as tp import weakref from abc import ABCMeta, abstractmethod -from satella.coding.structures.heaps import TimeBasedSetHeap -from satella.coding.structures.singleton import Singleton from satella.coding.concurrent.monitor import Monitor from satella.coding.recast_exceptions import rethrow_as, silence_excs +from satella.coding.structures.heaps import TimeBasedSetHeap +from satella.coding.structures.singleton import Singleton from satella.coding.typing import K, V, NoArgCallable diff --git a/satella/coding/structures/dictionaries/objects.py b/satella/coding/structures/dictionaries/objects.py index 0ce4218948baaa0dd1ad82d9ab0b45bddaac441f..b34493a52fa785e529392ed2230e7f7ac370a48b 100644 --- a/satella/coding/structures/dictionaries/objects.py +++ b/satella/coding/structures/dictionaries/objects.py @@ -1,7 +1,7 @@ import copy import typing as tp - import warnings + from satella.coding.typing import K, V diff --git a/satella/coding/structures/dictionaries/writeback_cache.py b/satella/coding/structures/dictionaries/writeback_cache.py index 0b6ea1254fb2b15dcc101ae7efe3c06db5fce3ef..8a662e68ff6dddf33e7d614ae6877fd0bd8e91c3 100644 --- a/satella/coding/structures/dictionaries/writeback_cache.py +++ b/satella/coding/structures/dictionaries/writeback_cache.py @@ -2,8 +2,8 @@ import time import typing as tp from concurrent.futures import Executor, ThreadPoolExecutor, ProcessPoolExecutor -from satella.coding.concurrent.sync import sync_threadpool from satella.coding.concurrent.monitor import Monitor +from satella.coding.concurrent.sync import sync_threadpool from satella.coding.recast_exceptions import silence_excs from satella.coding.typing import V, K diff --git a/satella/coding/structures/heaps/time.py b/satella/coding/structures/heaps/time.py index b7e77c9e86f02f12c5015f5fc3dd385ec544fffb..fd65ad8bbfe1320c8d176bc37368133789054cf5 100644 --- a/satella/coding/structures/heaps/time.py +++ b/satella/coding/structures/heaps/time.py @@ -3,8 +3,8 @@ import time import typing as tp from satella.coding.recast_exceptions import rethrow_as -from satella.coding.typing import T, Number, NoArgCallable from satella.coding.structures.heaps.base import Heap +from satella.coding.typing import T, Number, NoArgCallable class TimeBasedHeap(Heap): diff --git a/satella/coding/structures/mixins/__init__.py b/satella/coding/structures/mixins/__init__.py index 94121dc4f95c0f11e6050a4d09eccf876dc84094..b234e9edb6504cf43b7a0ce60cfcf0aa47633173 100644 --- a/satella/coding/structures/mixins/__init__.py +++ b/satella/coding/structures/mixins/__init__.py @@ -1,8 +1,8 @@ from .enums import ComparableEnum, ComparableIntEnum, HashableIntEnum, OnStrOnlyName +from .eqable import DictionaryEQAble from .hashable import ComparableAndHashableBy, ComparableAndHashableByInt, \ OmniHashableMixin, HashableMixin, ComparableAndHashableByStr from .strings import ReprableMixin, StrEqHashableMixin -from .eqable import DictionaryEQAble __all__ = ['ComparableIntEnum', 'ComparableEnum', 'ComparableAndHashableBy', 'HashableIntEnum', 'ComparableAndHashableByInt', 'OmniHashableMixin', diff --git a/satella/coding/structures/mixins/hashable.py b/satella/coding/structures/mixins/hashable.py index 9ff9742e50b7c9eb55ccf17b7589ae1857425272..84f89431786b0e7ec625e1813ea11bac357ca959 100644 --- a/satella/coding/structures/mixins/hashable.py +++ b/satella/coding/structures/mixins/hashable.py @@ -41,7 +41,7 @@ class ComparableAndHashableBy(metaclass=ABCMeta): @property @abstractmethod - def _COMPARABLE_BY(self) -> str: # pylint: disable=invalid-name + def _COMPARABLE_BY(self) -> str: # pylint: disable=invalid-name """ Return the sequence of names of properties and attributes that will be used for __eq__ and __hash__ @@ -159,7 +159,7 @@ class OmniHashableMixin(metaclass=ABCMeta): @property @abstractmethod - def _HASH_FIELDS_TO_USE(self) -> tp.Union[str, tp.Sequence[str]]: # pylint: disable=invalid-name + def _HASH_FIELDS_TO_USE(self) -> tp.Union[str, tp.Sequence[str]]: # pylint: disable=invalid-name """ Return the sequence of names of properties and attributes that will be used for __eq__ and __hash__ @@ -197,7 +197,6 @@ class OmniHashableMixin(metaclass=ABCMeta): except AttributeError: return False - def __ne__(self, other) -> bool: if not isinstance(other, type(self)): return True @@ -217,4 +216,3 @@ class OmniHashableMixin(metaclass=ABCMeta): return False except AttributeError: return True - diff --git a/satella/coding/structures/ranking.py b/satella/coding/structures/ranking.py index 8effd7b03ca4dd4303ce3e98d45fe388a985c3d6..b4761e42aa2cc0df2c79940bdb2131a0538b3422 100644 --- a/satella/coding/structures/ranking.py +++ b/satella/coding/structures/ranking.py @@ -1,8 +1,8 @@ import collections import typing as tp -from satella.coding.typing import T from satella.coding.structures.sorted_list import SortedList +from satella.coding.typing import T class Ranking(tp.Generic[T]): diff --git a/satella/coding/structures/syncable_droppable.py b/satella/coding/structures/syncable_droppable.py index 9c05d684eadeca24c68016de4dffb3dbb644eb21..fc02064f0c985163561f3ba5902776acc90d8008 100644 --- a/satella/coding/structures/syncable_droppable.py +++ b/satella/coding/structures/syncable_droppable.py @@ -1,8 +1,8 @@ import bisect import itertools import math -from abc import ABCMeta, abstractmethod import typing as tp +from abc import ABCMeta, abstractmethod from satella.coding.concurrent.monitor import RMonitor from satella.coding.sequences import try_close diff --git a/satella/coding/structures/zip_dict.py b/satella/coding/structures/zip_dict.py index 56ab1670236e5ad7f4dcf3a1008191d1d26af0be..a1b37c7f5f7d1acee4c82240c41f2eee45b41a36 100644 --- a/satella/coding/structures/zip_dict.py +++ b/satella/coding/structures/zip_dict.py @@ -13,6 +13,7 @@ class SetZip: Provided arguments must implement contains, length and iter. """ + def __iadd__(self, other: set): self.args.append(other) return self diff --git a/satella/coding/transforms/__init__.py b/satella/coding/transforms/__init__.py index 4f9f518f5ac3f428153f1d5eed9d11ac407f0ee3..ec6192641883e9031477b2c3a97de9eddbfa67ea 100644 --- a/satella/coding/transforms/__init__.py +++ b/satella/coding/transforms/__init__.py @@ -4,14 +4,14 @@ import random import typing as tp from satella.coding.decorators import for_argument +from .base64 import b64encode +from .interpol import linear_interpolate from .jsonify import jsonify -from .merger import merge_series from .merge_list import merge_list +from .merger import merge_series from .percentile import percentile -from .base64 import b64encode -from .interpol import linear_interpolate -from .words import hashables_to_int from .predicates import is_subset +from .words import hashables_to_int __all__ = ['stringify', 'split_shuffle_and_join', 'one_tuple', 'none_if_false', 'merge_series', 'pad_to_multiple_of_length', 'clip', 'hashables_to_int', diff --git a/satella/coding/transforms/interpol.py b/satella/coding/transforms/interpol.py index 40f0b343804f3741ddb069f7d3a81a60f968c498..659a4fc9fa037e5a4e503a80e22ae81105feb72f 100644 --- a/satella/coding/transforms/interpol.py +++ b/satella/coding/transforms/interpol.py @@ -1,6 +1,7 @@ +import bisect import typing as tp + from satella.coding.typing import U, K -import bisect def linear_interpolate(series: tp.Sequence[tp.Tuple[K, U]], t: K, diff --git a/satella/coding/transforms/jsonify.py b/satella/coding/transforms/jsonify.py index 62ae160eb4559d0e3c2bf65f68f64c8b42979a20..1b4184fac66a55fab7515a4174ed303c39b809b9 100644 --- a/satella/coding/transforms/jsonify.py +++ b/satella/coding/transforms/jsonify.py @@ -1,7 +1,7 @@ +import enum import typing as tp from satella.json import JSONAble -import enum def jsonify(data: tp.Any) -> tp.Optional[tp.Union[str, int, float, list, dict]]: diff --git a/satella/coding/transforms/merge_list.py b/satella/coding/transforms/merge_list.py index 99a03839c8f6763a8707d001f5b58898c8ac8337..c47d8f1c42909412addcf520a9da69c5734c2cc8 100644 --- a/satella/coding/transforms/merge_list.py +++ b/satella/coding/transforms/merge_list.py @@ -1,6 +1,7 @@ +import typing as tp + from satella.coding.structures import Heap from satella.coding.typing import K, V -import typing as tp class merge_list(tp.Iterator[tp.Tuple[K, V]]): diff --git a/satella/db.py b/satella/db.py index 6884ee412bd2f04dea136243cc8cfd66a716606b..d874a898883ce40880f2b36179b32e06bb9dc1f0 100644 --- a/satella/db.py +++ b/satella/db.py @@ -22,6 +22,7 @@ class transaction: :param close_the_connection_after: whether the connection should be closed after use :param log_exception: whether to log an exception if it happens """ + def __init__(self, connection_or_getter, close_the_connection_after: bool = False, log_exception: bool = True): self._connection = connection_or_getter diff --git a/satella/debug/tainting/environment.py b/satella/debug/tainting/environment.py index 57d2cdde81d58352b31df3e71055fe69426951cd..fb4eb322095d88735c6d70be3eaeb90126cb8e15 100644 --- a/satella/debug/tainting/environment.py +++ b/satella/debug/tainting/environment.py @@ -1,15 +1,13 @@ from __future__ import annotations import dis -import inspect +import gc import sys import threading -import gc import typing as tp import warnings from satella.coding.typing import T - from .tainteds import TaintedObject, access_tainted, taint local = threading.local() diff --git a/satella/debug/tainting/tainteds.py b/satella/debug/tainting/tainteds.py index d268900c081fc8a7d71b8872ed30cd9639ed2111..5f04002f3598708bb7853803f4094480fb780647 100644 --- a/satella/debug/tainting/tainteds.py +++ b/satella/debug/tainting/tainteds.py @@ -1,4 +1,5 @@ from __future__ import annotations + import functools import typing as tp @@ -12,6 +13,7 @@ def might_accept_tainted(taint_result: bool = False): This both unpacks your first argument if is was a TaintedObject, you'll receive it's value :param taint_result: result will be tainted """ + def outer(fun): @functools.wraps(fun) def inner(self, *args): @@ -22,7 +24,9 @@ def might_accept_tainted(taint_result: bool = False): return taint(p) else: return p + return inner + return outer @@ -69,7 +73,7 @@ class TaintedObject(tp.Generic[T]): return taint(next(self.__v)) @might_accept_tainted() - def __str__(self) -> str: # it must be a str otherwise Python will complain + def __str__(self) -> str: # it must be a str otherwise Python will complain return str(self.__v) def __call__(self, *args, **kwargs): @@ -83,7 +87,7 @@ class TaintedObject(tp.Generic[T]): def __getattr__(self, item: str) -> TaintedObject[T]: return getattr(self.__v, item) - def __len__(self) -> int: # This has to return an int otherwise Python will break + def __len__(self) -> int: # This has to return an int otherwise Python will break return len(self.__v) def __bool__(self) -> bool: # This has to return a bool otherwise Python will break @@ -186,4 +190,3 @@ def taint(v: T) -> TaintedObject[T]: :raises RuntimeError: no tainting session in progress """ return v if isinstance(v, TaintedObject) else TaintedObject(v) - diff --git a/satella/debug/test_environment.py b/satella/debug/test_environment.py index 361a6156116de941299286e1865ad4f5de3c9521..2b1e959af21d37f6e388afaeffff5fa39385ee22 100644 --- a/satella/debug/test_environment.py +++ b/satella/debug/test_environment.py @@ -40,4 +40,3 @@ class TestEnvs(unittest.TestCase): new_ctxt.value = 66 assert new_ctxt.value == 66 assert ctxt.value == 55 - diff --git a/satella/files.py b/satella/files.py index dcc5edce4692d9072b7ae66e0d89027e6ec31fa6..5cbcf93ced806c54f7621aa637b884c7c2f0806c 100644 --- a/satella/files.py +++ b/satella/files.py @@ -1,4 +1,5 @@ from __future__ import annotations + import codecs import functools import io @@ -11,8 +12,6 @@ __all__ = ['read_re_sub_and_write', 'find_files', 'split', 'read_in_file', 'writ 'write_out_file_if_different', 'make_noncolliding_name', 'try_unlink', 'DevNullFilelikeObject', 'read_lines', 'AutoflushFile'] -import warnings - from satella.coding import wraps from satella.coding.recast_exceptions import silence_excs, reraise_as from satella.coding.structures import Proxy @@ -29,7 +28,9 @@ def value_error_on_closed_file(getter): if getter(self): raise ValueError('File closed') return fun(self, *args, **kwargs) + return inner + return outer @@ -395,6 +396,7 @@ def open_file(fun): @wraps(fun) def inner(self, *args, **kwargs): return fun(self, self._open_file(), *args, **kwargs) + return inner @@ -499,7 +501,7 @@ class AutoflushFile(Proxy[io.FileIO]): @is_closed_getter @open_file @close_file_after - def close(self, fle) -> None: # pylint: disable=unused-argument + def close(self, fle) -> None: # pylint: disable=unused-argument """ Closes the file. """ @@ -526,4 +528,3 @@ class AutoflushFile(Proxy[io.FileIO]): v = fle.truncate(__size) self.__dict__['pointer'] = fle.tell() return v - diff --git a/satella/instrumentation/cpu_time/collector.py b/satella/instrumentation/cpu_time/collector.py index f6243f7236c05479f29af336fa27b0c0e1189728..8d1bd7a6c4e06962fcd7b48b9e25a70e87650478 100644 --- a/satella/instrumentation/cpu_time/collector.py +++ b/satella/instrumentation/cpu_time/collector.py @@ -1,10 +1,11 @@ from __future__ import annotations + +import collections +import multiprocessing import os -import typing as tp import threading -import multiprocessing import time -import collections +import typing as tp import psutil @@ -16,10 +17,9 @@ from satella.time import parse_time_string DEFAULT_REFRESH_EACH = '10s' DEFAULT_WINDOW_SECONDS = '10s' - pCPUtimes = collections.namedtuple('pcputimes', - ['user', 'system', 'children_user', 'children_system', - 'iowait']) + ['user', 'system', 'children_user', 'children_system', + 'iowait']) class _CPUProfileBuilderThread(threading.Thread): @@ -46,7 +46,7 @@ class _CPUProfileBuilderThread(threading.Thread): self.percentile_values = [] self.percentiles_regenerated = False self.started = False - self.own_load_average = collections.deque() # typing: tuple[float, pCPUtimes] + self.own_load_average = collections.deque() # typing: tuple[float, pCPUtimes] @staticmethod def get_instance(): @@ -83,7 +83,7 @@ class _CPUProfileBuilderThread(threading.Thread): if difference == 0: return None tuple_build = {} - for field in times_v._fields: # pylint: disable=protected-access + for field in times_v._fields: # pylint: disable=protected-access tuple_build[field] = (getattr(times_c, field) - getattr(times_v, field)) / difference return pCPUtimes(**tuple_build) diff --git a/satella/instrumentation/cpu_time/concurrency.py b/satella/instrumentation/cpu_time/concurrency.py index a4247b36e2e4fd589624e3e0545d60b9912a0eaf..0f847bad270845fa5bc175404750463c375dba80 100644 --- a/satella/instrumentation/cpu_time/concurrency.py +++ b/satella/instrumentation/cpu_time/concurrency.py @@ -2,8 +2,8 @@ import typing as tp from abc import abstractmethod, ABCMeta from satella.coding.concurrent import IntervalTerminableThread -from .collector import sleep_cpu_aware, _CPUProfileBuilderThread from satella.time import measure, parse_time_string +from .collector import sleep_cpu_aware, _CPUProfileBuilderThread class CPUTimeAwareIntervalTerminableThread(IntervalTerminableThread, metaclass=ABCMeta): diff --git a/satella/instrumentation/memory/__init__.py b/satella/instrumentation/memory/__init__.py index 7d01e97028724fb5a316b91635b891c88df3d661..e88180c04dbb51779719dd408dcace30e62910ad 100644 --- a/satella/instrumentation/memory/__init__.py +++ b/satella/instrumentation/memory/__init__.py @@ -1,9 +1,9 @@ from .conditions import Any, All, GlobalRelativeValue, GlobalAbsoluteValue, LocalAbsoluteValue, \ LocalRelativeValue, GB, MB, KB, CustomCondition, Not from .default import install_force_gc_collect -from .memthread import MemoryPressureManager from .dump_frames_on import dump_memory_on, install_dump_memory_on from .get_object_size import get_size +from .memthread import MemoryPressureManager __all__ = ['Any', 'All', 'MemoryPressureManager', 'GlobalAbsoluteValue', 'GB', 'GlobalRelativeValue', 'LocalRelativeValue', 'LocalAbsoluteValue', 'MB', 'KB', diff --git a/satella/instrumentation/memory/memthread.py b/satella/instrumentation/memory/memthread.py index f412bb181a020668ba33c36eae771fdd47500468..247ae15fcc599526fb89f66f44254676d42f1e16 100644 --- a/satella/instrumentation/memory/memthread.py +++ b/satella/instrumentation/memory/memthread.py @@ -1,6 +1,5 @@ import logging import os -import time import typing as tp import psutil @@ -8,7 +7,6 @@ import psutil from satella.coding.concurrent import CallableGroup, CallNoOftenThan, CancellableCallback, \ IntervalTerminableThread from satella.coding.structures import Singleton -from satella.time import measure from .conditions import BaseCondition, ZerothSeverity logger = logging.getLogger(__name__) diff --git a/satella/instrumentation/metrics/metric_types/summary.py b/satella/instrumentation/metrics/metric_types/summary.py index f3d13ed967389a54002acd99a11f8d9090195576..856ebe140cc98589be0678679ba5a36cef5db3f3 100644 --- a/satella/instrumentation/metrics/metric_types/summary.py +++ b/satella/instrumentation/metrics/metric_types/summary.py @@ -1,5 +1,4 @@ import collections -import math import typing as tp import warnings diff --git a/satella/json.py b/satella/json.py index 50b969bca11de157c51e0692dbd38d35cffa8aac..9a74d00065d1efc4f5b1a01e58933a421456334c 100644 --- a/satella/json.py +++ b/satella/json.py @@ -1,11 +1,10 @@ import enum +import json import typing as tp from abc import ABCMeta, abstractmethod -import json - -from satella.files import write_out_file_if_different from satella.coding.typing import NoneType +from satella.files import write_out_file_if_different __all__ = ['JSONEncoder', 'JSONAble', 'json_encode', 'read_json_from_file', 'write_json_to_file', 'write_json_to_file_if_different'] diff --git a/satella/os/misc.py b/satella/os/misc.py index da33c22e48618f9998f007da1e94139cac2d79ba..5794078c12cf1d2703a122be8d42945a2b419f8b 100644 --- a/satella/os/misc.py +++ b/satella/os/misc.py @@ -1,7 +1,7 @@ -import stat -import typing as tp import os +import stat import sys +import typing as tp import warnings from satella.coding import silence_excs diff --git a/satella/parsing.py b/satella/parsing.py index 0eb73c5f7ded6d94aee243f8027ed874295f629c..b2e5d9b912bb6ec26fef1ab678b88f11b43e5420 100644 --- a/satella/parsing.py +++ b/satella/parsing.py @@ -1,4 +1,5 @@ from __future__ import absolute_import + import struct import typing as tp diff --git a/satella/random.py b/satella/random.py index ba42308d0b610e9e3acaa91aea2657a5e4f834c4..f4761644c4920cadde6e178b82efcd3bdb247e7b 100644 --- a/satella/random.py +++ b/satella/random.py @@ -1,8 +1,7 @@ -import typing as tp import os import random -import typing as tp import string +import typing as tp __all__ = ['shuffle_together', 'random_binary', 'random_word'] diff --git a/satella/time/__init__.py b/satella/time/__init__.py index 927f9b32421eb6be29fa27649df640025eb91bc8..0ea7c920160826b9b103d92dbd2a3c7acd923213 100644 --- a/satella/time/__init__.py +++ b/satella/time/__init__.py @@ -1,7 +1,7 @@ +from satella.time.backoff import ExponentialBackoff from satella.time.measure import measure, TimeSignal from satella.time.misc import time_us, time_ms, time_as_int, sleep from satella.time.parse import parse_time_string -from satella.time.backoff import ExponentialBackoff __all__ = ['measure', 'TimeSignal', 'ExponentialBackoff', 'time_us', 'time_ms', 'time_as_int', 'parse_time_string', 'sleep'] diff --git a/satella/time/backoff.py b/satella/time/backoff.py index d152d10ca79c4659881617f982f0cf9ca4725a4b..06587cac52a96d2d890d1f0561c690b92339935f 100644 --- a/satella/time/backoff.py +++ b/satella/time/backoff.py @@ -1,13 +1,11 @@ import time import typing as tp +from satella.coding.concurrent.thread import Condition from satella.coding.decorators.decorators import wraps - from satella.coding.typing import ExceptionList - -from satella.coding.concurrent.thread import Condition -from satella.time.measure import measure from satella.exceptions import WouldWaitMore +from satella.time.measure import measure class ExponentialBackoff: diff --git a/satella/time/measure.py b/satella/time/measure.py index c5a91f199be7a90dbe9de4a650b1a215b62443be..5ae57a54f4b1224fa5eaa5f5f80ec1a03983143b 100644 --- a/satella/time/measure.py +++ b/satella/time/measure.py @@ -1,17 +1,19 @@ from __future__ import annotations -import typing as tp -import time + import copy import inspect +import time +import typing as tp import warnings from concurrent.futures import Future from functools import wraps # import from functools to prevent circular import exception + from satella.exceptions import WouldWaitMore TimeSignal = tp.Callable[[], float] -class measure: # pylint: disable=invalid-name +class measure: # pylint: disable=invalid-name """ A class used to measure time elapsed. Use for example like this: @@ -92,7 +94,7 @@ class measure: # pylint: disable=invalid-name def __init__(self, future_to_measure: tp.Optional[Future] = None, stop_on_stop: bool = True, adjust: float = 0.0, time_getter_callable: TimeSignal = time.monotonic, create_stopped: bool = False, - timeout: tp.Optional[float] = None): # pylint: disable=too-many-arguments + timeout: tp.Optional[float] = None): # pylint: disable=too-many-arguments self.time_getter_callable = time_getter_callable self.timeout = timeout self.started_on = time_getter_callable() + adjust diff --git a/satella/warnings.py b/satella/warnings.py index b5bba5a746b47b56f19d3b3e17b26a36ccb20e02..ea0d4468d42f4315ce9ad56d691b23aa2ff7142d 100644 --- a/satella/warnings.py +++ b/satella/warnings.py @@ -1,4 +1,5 @@ import warnings + __all__ = ['ExperimentalWarning', 'warnings', 'mark_temporarily_disabled'] @@ -22,12 +23,15 @@ def mark_temporarily_disabled(reason: str = ''): >>> def serialize_report(analysis): >>> ... """ + def outer(fun): def inner(*args, **kwargs): """ Function temporarily disabled. Don't call it. """ raise NotImplementedError(f'Function disabled due to {reason}') + warnings.warn(f'Function {fun.__name__} temporarily disabled due to {reason}') return inner + return outer