omlish 0.0.0.dev244__py3-none-any.whl → 0.0.0.dev246__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omlish/__about__.py +2 -2
- omlish/cached.py +4 -3
- omlish/collections/__init__.py +0 -1
- omlish/collections/frozen.py +2 -2
- omlish/collections/hasheq.py +1 -2
- omlish/collections/identity.py +1 -2
- omlish/collections/mappings.py +0 -16
- omlish/collections/sorted/sorted.py +1 -2
- omlish/daemons/services.py +7 -0
- omlish/dataclasses/__init__.py +3 -0
- omlish/dataclasses/utils.py +14 -0
- omlish/http/handlers.py +16 -0
- omlish/lang/__init__.py +46 -16
- omlish/lang/attrs.py +161 -0
- omlish/lang/cached/__init__.py +0 -0
- omlish/lang/{cached.py → cached/function.py} +125 -83
- omlish/lang/cached/property.py +118 -0
- omlish/lang/classes/__init__.py +0 -41
- omlish/lang/collections.py +50 -0
- omlish/marshal/__init__.py +23 -0
- omlish/marshal/composite/wrapped.py +26 -0
- omlish/marshal/objects/dataclasses.py +36 -11
- omlish/marshal/objects/namedtuples.py +9 -9
- omlish/marshal/polymorphism/marshal.py +16 -2
- omlish/marshal/polymorphism/unmarshal.py +16 -2
- omlish/os/pidfiles/pidfile.py +20 -4
- omlish/os/signals.py +5 -1
- {omlish-0.0.0.dev244.dist-info → omlish-0.0.0.dev246.dist-info}/METADATA +1 -1
- {omlish-0.0.0.dev244.dist-info → omlish-0.0.0.dev246.dist-info}/RECORD +33 -28
- {omlish-0.0.0.dev244.dist-info → omlish-0.0.0.dev246.dist-info}/WHEEL +1 -1
- {omlish-0.0.0.dev244.dist-info → omlish-0.0.0.dev246.dist-info}/LICENSE +0 -0
- {omlish-0.0.0.dev244.dist-info → omlish-0.0.0.dev246.dist-info}/entry_points.txt +0 -0
- {omlish-0.0.0.dev244.dist-info → omlish-0.0.0.dev246.dist-info}/top_level.txt +0 -0
omlish/__about__.py
CHANGED
omlish/cached.py
CHANGED
@@ -9,11 +9,12 @@ builtins and thus not distinguish it from a normal property.
|
|
9
9
|
def p(self) -> str: ...
|
10
10
|
|
11
11
|
"""
|
12
|
-
from .lang.cached import
|
13
|
-
from .lang.cached import
|
12
|
+
from .lang.cached.function import cached_function as _cached_function
|
13
|
+
from .lang.cached.property import cached_property as _cached_property
|
14
|
+
|
14
15
|
|
15
16
|
function = _cached_function
|
16
17
|
|
17
18
|
property = property # noqa
|
18
19
|
|
19
|
-
globals()['property'] =
|
20
|
+
globals()['property'] = _cached_property # noqa
|
omlish/collections/__init__.py
CHANGED
omlish/collections/frozen.py
CHANGED
@@ -3,7 +3,7 @@ import collections.abc
|
|
3
3
|
import itertools
|
4
4
|
import typing as ta
|
5
5
|
|
6
|
-
from
|
6
|
+
from .. import lang
|
7
7
|
|
8
8
|
|
9
9
|
T = ta.TypeVar('T')
|
@@ -27,7 +27,7 @@ class FrozenDict(ta.Mapping[K, V], Frozen):
|
|
27
27
|
if len(args) > 1:
|
28
28
|
raise TypeError(args)
|
29
29
|
self._dct: dict[K, V] = {}
|
30
|
-
self._dct.update(yield_dict_init(*args, **kwargs))
|
30
|
+
self._dct.update(lang.yield_dict_init(*args, **kwargs))
|
31
31
|
|
32
32
|
@property
|
33
33
|
def debug(self) -> ta.Mapping[K, V]:
|
omlish/collections/hasheq.py
CHANGED
@@ -8,7 +8,6 @@ import dataclasses as dc
|
|
8
8
|
import typing as ta
|
9
9
|
|
10
10
|
from .. import lang
|
11
|
-
from .mappings import yield_dict_init
|
12
11
|
|
13
12
|
|
14
13
|
K = ta.TypeVar('K')
|
@@ -64,7 +63,7 @@ class HashEqMap(ta.MutableMapping[K, V]):
|
|
64
63
|
self._dct: dict[int, list[HashEqMap._Node[K, V]]] = {}
|
65
64
|
self._len = 0
|
66
65
|
|
67
|
-
for k, v in yield_dict_init(*args, **kwargs):
|
66
|
+
for k, v in lang.yield_dict_init(*args, **kwargs):
|
68
67
|
self[k] = v
|
69
68
|
|
70
69
|
def __len__(self) -> int:
|
omlish/collections/identity.py
CHANGED
@@ -4,7 +4,6 @@ import typing as ta
|
|
4
4
|
import weakref
|
5
5
|
|
6
6
|
from .. import lang
|
7
|
-
from .mappings import yield_dict_init
|
8
7
|
|
9
8
|
|
10
9
|
T = ta.TypeVar('T')
|
@@ -38,7 +37,7 @@ class IdentityKeyDict(ta.MutableMapping[K, V]):
|
|
38
37
|
def __init__(self, *args, **kwargs) -> None:
|
39
38
|
super().__init__()
|
40
39
|
self._dict: dict[int, tuple[K, V]] = {}
|
41
|
-
for k, v in yield_dict_init(*args, **kwargs):
|
40
|
+
for k, v in lang.yield_dict_init(*args, **kwargs):
|
42
41
|
self[k] = v
|
43
42
|
|
44
43
|
@property
|
omlish/collections/mappings.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import collections.abc
|
2
1
|
import typing as ta
|
3
2
|
import weakref
|
4
3
|
|
@@ -33,21 +32,6 @@ def guarded_map_update(
|
|
33
32
|
return dst
|
34
33
|
|
35
34
|
|
36
|
-
def yield_dict_init(*args, **kwargs) -> ta.Iterable[tuple[ta.Any, ta.Any]]:
|
37
|
-
if len(args) > 1:
|
38
|
-
raise TypeError
|
39
|
-
if args:
|
40
|
-
[src] = args
|
41
|
-
if isinstance(src, collections.abc.Mapping):
|
42
|
-
for k in src:
|
43
|
-
yield (k, src[k])
|
44
|
-
else:
|
45
|
-
for k, v in src:
|
46
|
-
yield (k, v)
|
47
|
-
for k, v in kwargs.items():
|
48
|
-
yield (k, v)
|
49
|
-
|
50
|
-
|
51
35
|
class TypeMap(ta.Generic[T]):
|
52
36
|
def __init__(self, items: ta.Iterable[T] = ()) -> None:
|
53
37
|
super().__init__()
|
@@ -2,7 +2,6 @@ import abc
|
|
2
2
|
import typing as ta
|
3
3
|
|
4
4
|
from ... import lang
|
5
|
-
from ..mappings import yield_dict_init
|
6
5
|
|
7
6
|
|
8
7
|
T = ta.TypeVar('T')
|
@@ -83,7 +82,7 @@ class SortedListDict(SortedMutableMapping[K, V]):
|
|
83
82
|
def __init__(self, impl: SortedCollection, *args, **kwargs) -> None:
|
84
83
|
super().__init__()
|
85
84
|
self._impl = impl
|
86
|
-
for k, v in yield_dict_init(*args, **kwargs):
|
85
|
+
for k, v in lang.yield_dict_init(*args, **kwargs):
|
87
86
|
self[k] = v
|
88
87
|
|
89
88
|
@property
|
omlish/daemons/services.py
CHANGED
omlish/dataclasses/__init__.py
CHANGED
omlish/dataclasses/utils.py
CHANGED
@@ -32,6 +32,9 @@ def fields_dict(cls_or_instance: ta.Any) -> dict[str, dc.Field]:
|
|
32
32
|
return {f.name: f for f in dc.fields(cls_or_instance)}
|
33
33
|
|
34
34
|
|
35
|
+
##
|
36
|
+
|
37
|
+
|
35
38
|
class field_modifier: # noqa
|
36
39
|
def __init__(self, fn: ta.Callable[[dc.Field], dc.Field]) -> None:
|
37
40
|
super().__init__()
|
@@ -112,6 +115,17 @@ def update_fields_metadata(
|
|
112
115
|
##
|
113
116
|
|
114
117
|
|
118
|
+
def shallow_astuple(o: ta.Any) -> tuple[ta.Any, ...]:
|
119
|
+
return tuple(getattr(o, f.name) for f in dc.fields(o))
|
120
|
+
|
121
|
+
|
122
|
+
def shallow_asdict(o: ta.Any) -> dict[str, ta.Any]:
|
123
|
+
return {f.name: getattr(o, f.name) for f in dc.fields(o)}
|
124
|
+
|
125
|
+
|
126
|
+
##
|
127
|
+
|
128
|
+
|
115
129
|
def deep_replace(o: T, *args: str | ta.Callable[[ta.Any], ta.Mapping[str, ta.Any]]) -> T:
|
116
130
|
if not args:
|
117
131
|
return o
|
omlish/http/handlers.py
CHANGED
@@ -79,6 +79,22 @@ class LoggingHttpHandler(HttpHandler_):
|
|
79
79
|
return resp
|
80
80
|
|
81
81
|
|
82
|
+
@dc.dataclass(frozen=True)
|
83
|
+
class ExceptionLoggingHttpHandler(HttpHandler_):
|
84
|
+
handler: HttpHandler
|
85
|
+
log: logging.Logger
|
86
|
+
message: ta.Union[str, ta.Callable[[HttpHandlerRequest, BaseException], str]] = 'Error in http handler'
|
87
|
+
|
88
|
+
def __call__(self, req: HttpHandlerRequest) -> HttpHandlerResponse:
|
89
|
+
try:
|
90
|
+
return self.handler(req)
|
91
|
+
except Exception as e: # noqa
|
92
|
+
if callable(msg := self.message):
|
93
|
+
msg = msg(req, e)
|
94
|
+
self.log.exception(msg)
|
95
|
+
raise
|
96
|
+
|
97
|
+
|
82
98
|
##
|
83
99
|
|
84
100
|
|
omlish/lang/__init__.py
CHANGED
@@ -1,39 +1,64 @@
|
|
1
|
-
from .
|
1
|
+
from .attrs import ( # noqa
|
2
|
+
AttrOps,
|
3
|
+
DictAttrOps,
|
4
|
+
STD_ATTR_OPS,
|
5
|
+
StdAttrOps,
|
6
|
+
TRANSIENT_ATTR_OPS,
|
7
|
+
TransientAttrOps,
|
8
|
+
TransientDict,
|
9
|
+
transient_delattr,
|
10
|
+
transient_getattr,
|
11
|
+
transient_setattr,
|
12
|
+
)
|
13
|
+
|
14
|
+
from .cached.function import ( # noqa
|
2
15
|
cached_function,
|
3
|
-
cached_property,
|
4
16
|
static_init,
|
5
17
|
)
|
6
18
|
|
7
|
-
from .
|
19
|
+
from .cached.property import ( # noqa
|
20
|
+
cached_property,
|
21
|
+
)
|
22
|
+
|
23
|
+
from .classes.abstract import ( # noqa
|
8
24
|
Abstract,
|
9
25
|
AbstractTypeError,
|
26
|
+
get_abstract_methods,
|
27
|
+
is_abstract,
|
28
|
+
is_abstract_class,
|
29
|
+
is_abstract_method,
|
30
|
+
make_abstract,
|
31
|
+
unabstract_class,
|
32
|
+
)
|
33
|
+
|
34
|
+
from .classes.restrict import ( # noqa
|
10
35
|
AnySensitive,
|
11
|
-
Callable,
|
12
|
-
Descriptor,
|
13
36
|
Final,
|
14
37
|
FinalTypeError,
|
15
|
-
LazySingleton,
|
16
|
-
Marker,
|
17
|
-
Namespace,
|
18
38
|
NoBool,
|
19
39
|
NotInstantiable,
|
20
40
|
NotPicklable,
|
21
41
|
PackageSealed,
|
22
|
-
Picklable,
|
23
42
|
SENSITIVE_ATTR,
|
24
43
|
Sealed,
|
25
44
|
SealedError,
|
26
45
|
Sensitive,
|
46
|
+
no_bool,
|
47
|
+
)
|
48
|
+
|
49
|
+
from .classes.simple import ( # noqa
|
50
|
+
LazySingleton,
|
51
|
+
Marker,
|
52
|
+
Namespace,
|
27
53
|
SimpleMetaDict,
|
28
54
|
Singleton,
|
55
|
+
)
|
56
|
+
|
57
|
+
from .classes.virtual import ( # noqa
|
58
|
+
Callable,
|
59
|
+
Descriptor,
|
60
|
+
Picklable,
|
29
61
|
Virtual,
|
30
|
-
get_abstract_methods,
|
31
|
-
is_abstract,
|
32
|
-
is_abstract_class,
|
33
|
-
is_abstract_method,
|
34
|
-
make_abstract,
|
35
|
-
no_bool,
|
36
|
-
unabstract_class,
|
37
62
|
virtual_check,
|
38
63
|
)
|
39
64
|
|
@@ -52,6 +77,11 @@ from .cmp import ( # noqa
|
|
52
77
|
cmp,
|
53
78
|
)
|
54
79
|
|
80
|
+
from .collections import ( # noqa
|
81
|
+
merge_dicts,
|
82
|
+
yield_dict_init,
|
83
|
+
)
|
84
|
+
|
55
85
|
from .contextmanagers import ( # noqa
|
56
86
|
AsyncContextManager,
|
57
87
|
ContextManaged,
|
omlish/lang/attrs.py
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
import abc
|
2
|
+
import collections.abc
|
3
|
+
import typing as ta
|
4
|
+
|
5
|
+
|
6
|
+
##
|
7
|
+
|
8
|
+
|
9
|
+
class AttrOps(abc.ABC):
|
10
|
+
class NOT_SET: # noqa
|
11
|
+
def __new__(cls, *args, **kwargs): # noqa
|
12
|
+
raise TypeError
|
13
|
+
|
14
|
+
@abc.abstractmethod
|
15
|
+
def getattr(self, obj: ta.Any, name: str, default: ta.Any = NOT_SET) -> ta.Any:
|
16
|
+
raise NotImplementedError
|
17
|
+
|
18
|
+
@abc.abstractmethod
|
19
|
+
def setattr(self, obj: ta.Any, name: str, value: ta.Any) -> None:
|
20
|
+
raise NotImplementedError
|
21
|
+
|
22
|
+
@abc.abstractmethod
|
23
|
+
def delattr(self, obj: ta.Any, name: str) -> None:
|
24
|
+
raise NotImplementedError
|
25
|
+
|
26
|
+
|
27
|
+
##
|
28
|
+
|
29
|
+
|
30
|
+
class StdAttrOps(AttrOps):
|
31
|
+
def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrOps.NOT_SET) -> ta.Any:
|
32
|
+
if default is AttrOps.NOT_SET:
|
33
|
+
return getattr(obj, name)
|
34
|
+
else:
|
35
|
+
return getattr(obj, name, default)
|
36
|
+
|
37
|
+
def setattr(self, obj: ta.Any, name: str, value: ta.Any) -> None:
|
38
|
+
setattr(obj, name, value)
|
39
|
+
|
40
|
+
def delattr(self, obj: ta.Any, name: str) -> None:
|
41
|
+
delattr(obj, name)
|
42
|
+
|
43
|
+
|
44
|
+
STD_ATTR_OPS = StdAttrOps()
|
45
|
+
|
46
|
+
|
47
|
+
##
|
48
|
+
|
49
|
+
|
50
|
+
class DictAttrOps(AttrOps):
|
51
|
+
def __init__(self, dct: ta.MutableMapping[str, ta.Any] | None = None) -> None:
|
52
|
+
super().__init__()
|
53
|
+
|
54
|
+
if dct is None:
|
55
|
+
dct = {}
|
56
|
+
self._dct = dct
|
57
|
+
|
58
|
+
def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrOps.NOT_SET) -> ta.Any:
|
59
|
+
try:
|
60
|
+
return self._dct[name]
|
61
|
+
except KeyError:
|
62
|
+
if default is not AttrOps.NOT_SET:
|
63
|
+
return default
|
64
|
+
raise AttributeError(name) from None
|
65
|
+
|
66
|
+
def setattr(self, obj: ta.Any, name: str, value: ta.Any) -> None:
|
67
|
+
self._dct[name] = value
|
68
|
+
|
69
|
+
def delattr(self, obj: ta.Any, name: str) -> None:
|
70
|
+
try:
|
71
|
+
del self._dct[name]
|
72
|
+
except KeyError:
|
73
|
+
raise AttributeError(name) from None
|
74
|
+
|
75
|
+
|
76
|
+
##
|
77
|
+
|
78
|
+
|
79
|
+
class TransientDict(collections.abc.MutableMapping):
|
80
|
+
def __init__(self) -> None:
|
81
|
+
super().__init__()
|
82
|
+
|
83
|
+
self._dct: dict = {}
|
84
|
+
|
85
|
+
def __reduce__(self):
|
86
|
+
return (TransientDict, ())
|
87
|
+
|
88
|
+
def __getitem__(self, item):
|
89
|
+
return self._dct[item]
|
90
|
+
|
91
|
+
def __setitem__(self, key, value):
|
92
|
+
self._dct[key] = value
|
93
|
+
|
94
|
+
def __delitem__(self, key):
|
95
|
+
del self._dct[key]
|
96
|
+
|
97
|
+
def __len__(self):
|
98
|
+
return len(self._dct)
|
99
|
+
|
100
|
+
def __iter__(self):
|
101
|
+
return iter(self._dct)
|
102
|
+
|
103
|
+
def clear(self):
|
104
|
+
self._dct.clear()
|
105
|
+
|
106
|
+
def items(self):
|
107
|
+
return self._dct.items()
|
108
|
+
|
109
|
+
def keys(self):
|
110
|
+
return self._dct.keys()
|
111
|
+
|
112
|
+
def values(self):
|
113
|
+
return self._dct.values()
|
114
|
+
|
115
|
+
def __contains__(self, key, /):
|
116
|
+
return super().__contains__(key)
|
117
|
+
|
118
|
+
def __eq__(self, other, /):
|
119
|
+
raise TypeError(self)
|
120
|
+
|
121
|
+
|
122
|
+
#
|
123
|
+
|
124
|
+
|
125
|
+
_TRANSIENT_DICT_ATTR = '__transient_dict__'
|
126
|
+
|
127
|
+
|
128
|
+
def _get_object_transient_dict(obj: ta.Any) -> TransientDict:
|
129
|
+
try:
|
130
|
+
return obj.__dict__[_TRANSIENT_DICT_ATTR]
|
131
|
+
except KeyError:
|
132
|
+
return obj.__dict__.setdefault(_TRANSIENT_DICT_ATTR, TransientDict())
|
133
|
+
|
134
|
+
|
135
|
+
class TransientAttrOps(AttrOps):
|
136
|
+
def getattr(self, obj: ta.Any, name: str, default: ta.Any = AttrOps.NOT_SET) -> ta.Any:
|
137
|
+
td = _get_object_transient_dict(obj)
|
138
|
+
try:
|
139
|
+
return td[name]
|
140
|
+
except KeyError:
|
141
|
+
if default is not AttrOps.NOT_SET:
|
142
|
+
return default
|
143
|
+
raise AttributeError(name) from None
|
144
|
+
|
145
|
+
def setattr(self, obj: ta.Any, name: str, value: ta.Any) -> None:
|
146
|
+
td = _get_object_transient_dict(obj)
|
147
|
+
td[name] = value
|
148
|
+
|
149
|
+
def delattr(self, obj: ta.Any, name: str) -> None:
|
150
|
+
td = _get_object_transient_dict(obj)
|
151
|
+
try:
|
152
|
+
del td[name]
|
153
|
+
except KeyError:
|
154
|
+
raise AttributeError(name) from None
|
155
|
+
|
156
|
+
|
157
|
+
TRANSIENT_ATTR_OPS = TransientAttrOps()
|
158
|
+
|
159
|
+
transient_getattr = TRANSIENT_ATTR_OPS.getattr
|
160
|
+
transient_setattr = TRANSIENT_ATTR_OPS.setattr
|
161
|
+
transient_delattr = TRANSIENT_ATTR_OPS.delattr
|
File without changes
|