omlish 0.0.0.dev282__py3-none-any.whl → 0.0.0.dev284__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.
Files changed (59) hide show
  1. omlish/__about__.py +4 -4
  2. omlish/collections/__init__.py +1 -1
  3. omlish/collections/mappings.py +9 -0
  4. omlish/collections/utils.py +10 -1
  5. omlish/dataclasses/__init__.py +2 -2
  6. omlish/dataclasses/impl/api.py +1 -1
  7. omlish/dataclasses/impl/{exceptions.py → errors.py} +3 -0
  8. omlish/dataclasses/impl/fields.py +1 -1
  9. omlish/dataclasses/impl/init.py +1 -1
  10. omlish/dataclasses/impl/order.py +11 -1
  11. omlish/inject/__init__.py +1 -1
  12. omlish/inject/bindings.py +1 -1
  13. omlish/inject/eagers.py +1 -1
  14. omlish/inject/impl/bindings.py +1 -1
  15. omlish/inject/impl/elements.py +2 -2
  16. omlish/inject/impl/injector.py +2 -2
  17. omlish/inject/impl/inspect.py +1 -1
  18. omlish/inject/impl/scopes.py +2 -2
  19. omlish/inject/keys.py +1 -1
  20. omlish/inject/listeners.py +1 -1
  21. omlish/inject/multis.py +4 -4
  22. omlish/inject/origins.py +2 -2
  23. omlish/inject/overrides.py +1 -1
  24. omlish/inject/privates.py +2 -2
  25. omlish/inject/providers.py +4 -4
  26. omlish/inject/scopes.py +3 -3
  27. omlish/lang/__init__.py +8 -3
  28. omlish/lang/cached/function.py +9 -0
  29. omlish/lang/cached/property.py +3 -1
  30. omlish/lang/comparison.py +3 -0
  31. omlish/lang/enums.py +8 -0
  32. omlish/lang/imports.py +68 -10
  33. omlish/lang/objects.py +0 -17
  34. omlish/lite/reprs.py +84 -0
  35. omlish/marshal/__init__.py +1 -1
  36. omlish/marshal/base.py +1 -1
  37. omlish/marshal/{exceptions.py → errors.py} +3 -0
  38. omlish/marshal/objects/dataclasses.py +4 -4
  39. omlish/marshal/trivial/forbidden.py +1 -1
  40. omlish/specs/jmespath/__init__.py +1 -1
  41. omlish/specs/jmespath/cli.py +5 -5
  42. omlish/specs/jmespath/functions.py +6 -6
  43. omlish/specs/jmespath/lexer.py +2 -2
  44. omlish/specs/jmespath/parser.py +3 -3
  45. omlish/specs/jmespath/visitor.py +1 -1
  46. omlish/sql/queries/base.py +3 -3
  47. omlish/text/mangle.py +66 -7
  48. omlish/typedvalues/values.py +1 -1
  49. {omlish-0.0.0.dev282.dist-info → omlish-0.0.0.dev284.dist-info}/METADATA +3 -3
  50. {omlish-0.0.0.dev282.dist-info → omlish-0.0.0.dev284.dist-info}/RECORD +57 -57
  51. omlish/dataclasses/impl/descriptors.py +0 -93
  52. omlish/lang/exceptions.py +0 -2
  53. /omlish/collections/{exceptions.py → errors.py} +0 -0
  54. /omlish/inject/{exceptions.py → errors.py} +0 -0
  55. /omlish/specs/jmespath/{exceptions.py → errors.py} +0 -0
  56. {omlish-0.0.0.dev282.dist-info → omlish-0.0.0.dev284.dist-info}/WHEEL +0 -0
  57. {omlish-0.0.0.dev282.dist-info → omlish-0.0.0.dev284.dist-info}/entry_points.txt +0 -0
  58. {omlish-0.0.0.dev282.dist-info → omlish-0.0.0.dev284.dist-info}/licenses/LICENSE +0 -0
  59. {omlish-0.0.0.dev282.dist-info → omlish-0.0.0.dev284.dist-info}/top_level.txt +0 -0
omlish/lang/objects.py CHANGED
@@ -11,23 +11,6 @@ T = ta.TypeVar('T')
11
11
  ##
12
12
 
13
13
 
14
- def attr_repr(
15
- obj: ta.Any,
16
- *attrs: str,
17
- with_module: bool = False,
18
- use_qualname: bool = False,
19
- with_id: bool = False,
20
- ) -> str:
21
- return (
22
- f'{obj.__class__.__module__ + "." if with_module else ""}'
23
- f'{obj.__class__.__qualname__ if use_qualname else obj.__class__.__name__}'
24
- f'{("@" + hex(id(obj))[2:]) if with_id else ""}'
25
- f'('
26
- f'{", ".join(f"{attr}={getattr(obj, attr)!r}" for attr in attrs)}'
27
- f')'
28
- )
29
-
30
-
31
14
  def arg_repr(*args: ta.Any, **kwargs: ta.Any) -> str:
32
15
  return ', '.join(*(
33
16
  list(map(repr, args)) +
omlish/lite/reprs.py ADDED
@@ -0,0 +1,84 @@
1
+ # ruff: noqa: UP007
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+
6
+ ##
7
+
8
+
9
+ @dc.dataclass(frozen=True)
10
+ class AttrRepr:
11
+ attrs: ta.Sequence[str]
12
+
13
+ # _: dc.KW_ONLY
14
+
15
+ with_module: bool = False
16
+ use_qualname: bool = False
17
+ with_id: bool = False
18
+ value_filter: ta.Optional[ta.Callable[[ta.Any], bool]] = None
19
+ recursive: bool = False
20
+
21
+ @classmethod
22
+ def of(cls, *attrs: str, **kwargs: ta.Any) -> 'AttrRepr':
23
+ return cls(attrs, **kwargs)
24
+
25
+ #
26
+
27
+ def _build_(self, obj: ta.Any) -> str:
28
+ vs = ', '.join(
29
+ f'{attr}={v!r}'
30
+ for attr in self.attrs
31
+ for v in [getattr(obj, attr)]
32
+ if self.value_filter is None or self.value_filter(v)
33
+ )
34
+
35
+ return (
36
+ f'{obj.__class__.__module__ + "." if self.with_module else ""}'
37
+ f'{obj.__class__.__qualname__ if self.use_qualname else obj.__class__.__name__}'
38
+ f'{("@" + hex(id(obj))[2:]) if self.with_id else ""}'
39
+ f'({vs})'
40
+ )
41
+
42
+ _build: ta.ClassVar[ta.Callable[[ta.Any], str]]
43
+
44
+ def __call__(self, obj: ta.Any) -> str:
45
+ try:
46
+ build: ta.Any = self._build
47
+
48
+ except AttributeError:
49
+ build = self._build_
50
+ if self.recursive:
51
+ build = self._reprlib().recursive_repr()(build)
52
+ object.__setattr__(self, '_build', build)
53
+
54
+ return build(obj)
55
+
56
+ #
57
+
58
+ def __get__(self, instance, owner):
59
+ if instance is None:
60
+ return self
61
+
62
+ def __repr__(other): # noqa
63
+ return self(other)
64
+
65
+ return __repr__.__get__(instance, owner)
66
+
67
+ #
68
+
69
+ _reprlib_: ta.ClassVar[ta.Any]
70
+
71
+ @classmethod
72
+ def _reprlib(cls) -> ta.Any:
73
+ try:
74
+ return cls._reprlib_
75
+ except AttributeError:
76
+ pass
77
+
78
+ reprlib = __import__('reprlib')
79
+ cls._reprlib_ = reprlib
80
+ return reprlib
81
+
82
+
83
+ def attr_repr(obj: ta.Any, *attrs: str, **kwargs: ta.Any) -> str:
84
+ return AttrRepr(attrs, **kwargs)(obj)
@@ -50,7 +50,7 @@ from .composite.wrapped import ( # noqa
50
50
  WrappedUnmarshaler,
51
51
  )
52
52
 
53
- from .exceptions import ( # noqa
53
+ from .errors import ( # noqa
54
54
  ForbiddenTypeError,
55
55
  MarshalError,
56
56
  UnhandledTypeError,
omlish/marshal/base.py CHANGED
@@ -92,7 +92,7 @@ from .. import dataclasses as dc
92
92
  from .. import lang
93
93
  from .. import reflect as rfl
94
94
  from ..funcs import match as mfs
95
- from .exceptions import UnhandledTypeError
95
+ from .errors import UnhandledTypeError
96
96
  from .factories import RecursiveTypeFactory
97
97
  from .factories import TypeCacheFactory
98
98
  from .factories import TypeMapFactory
@@ -1,6 +1,9 @@
1
1
  from .. import reflect as rfl
2
2
 
3
3
 
4
+ ##
5
+
6
+
4
7
  class MarshalError(Exception):
5
8
  pass
6
9
 
@@ -50,7 +50,7 @@ def get_dataclass_field_infos(
50
50
 
51
51
  dc_md = get_dataclass_metadata(ty)
52
52
  dc_naming = dc_md.field_naming or opts.get(Naming)
53
- dc_rf = dc.reflect(ty)
53
+ dc_rfl = dc.reflect(ty)
54
54
 
55
55
  fi_defaults = {
56
56
  k: v
@@ -66,7 +66,7 @@ def get_dataclass_field_infos(
66
66
  type_hints = ta.get_type_hints(ty)
67
67
 
68
68
  ret: list[FieldInfo] = []
69
- for field in dc_rf.instance_fields:
69
+ for field in dc_rfl.instance_fields:
70
70
  if (f_naming := field.metadata.get(Naming, dc_naming)) is not None:
71
71
  um_name = translate_name(field.name, f_naming)
72
72
  else:
@@ -76,10 +76,10 @@ def get_dataclass_field_infos(
76
76
 
77
77
  f_ty: ta.Any
78
78
  if (
79
- ((cpx := dc_rf.cls_params_extras) is not None and cpx.generic_init) or
79
+ ((cpx := dc_rfl.cls_params_extras) is not None and cpx.generic_init) or
80
80
  (fmd is not None and fmd.options.generic_replace)
81
81
  ):
82
- f_ty = rfl.to_annotation(dc_rf.generic_replaced_field_type(field.name))
82
+ f_ty = rfl.to_annotation(dc_rfl.generic_replaced_field_type(field.name))
83
83
  else:
84
84
  f_ty = type_hints[field.name]
85
85
 
@@ -9,7 +9,7 @@ from ..base import SimpleMarshalerFactory
9
9
  from ..base import SimpleUnmarshalerFactory
10
10
  from ..base import UnmarshalContext
11
11
  from ..base import Unmarshaler
12
- from ..exceptions import ForbiddenTypeError
12
+ from ..errors import ForbiddenTypeError
13
13
 
14
14
 
15
15
  C = ta.TypeVar('C')
@@ -27,7 +27,7 @@ See:
27
27
  - https://github.com/jmespath-community/jmespath.spec/discussions?discussions_q=label%3Ajep-candidate
28
28
  - https://github.com/jmespath-community/jmespath.spec/discussions/97
29
29
  """ # noqa
30
- from . import exceptions # noqa
30
+ from . import errors # noqa
31
31
  from . import functions # noqa
32
32
  from . import lexer # noqa
33
33
  from . import parser # noqa
@@ -5,11 +5,11 @@ import typing as ta
5
5
 
6
6
  from ...formats import json
7
7
  from .ast import Node
8
- from .exceptions import ArityError
9
- from .exceptions import JmespathTypeError
10
- from .exceptions import JmespathValueError
11
- from .exceptions import ParseError
12
- from .exceptions import UnknownFunctionError
8
+ from .errors import ArityError
9
+ from .errors import JmespathTypeError
10
+ from .errors import JmespathValueError
11
+ from .errors import ParseError
12
+ from .errors import UnknownFunctionError
13
13
  from .parser import compile # noqa
14
14
  from .parser import search
15
15
  from .visitor import node_type
@@ -5,12 +5,12 @@ import math
5
5
  import re
6
6
  import typing as ta
7
7
 
8
- from .exceptions import ArityError
9
- from .exceptions import JmespathError
10
- from .exceptions import JmespathTypeError
11
- from .exceptions import JmespathValueError
12
- from .exceptions import UnknownFunctionError
13
- from .exceptions import VariadicArityError
8
+ from .errors import ArityError
9
+ from .errors import JmespathError
10
+ from .errors import JmespathTypeError
11
+ from .errors import JmespathValueError
12
+ from .errors import UnknownFunctionError
13
+ from .errors import VariadicArityError
14
14
 
15
15
 
16
16
  T = ta.TypeVar('T')
@@ -4,8 +4,8 @@ import typing as ta
4
4
  import warnings
5
5
 
6
6
  from ... import check
7
- from .exceptions import EmptyExpressionError
8
- from .exceptions import LexerError
7
+ from .errors import EmptyExpressionError
8
+ from .errors import LexerError
9
9
  from .visitor import Options
10
10
 
11
11
 
@@ -57,9 +57,9 @@ from .ast import Subexpression
57
57
  from .ast import UnaryArithmeticOperator
58
58
  from .ast import ValueProjection
59
59
  from .ast import VariableRef
60
- from .exceptions import IncompleteExpressionError
61
- from .exceptions import LexerError
62
- from .exceptions import ParseError
60
+ from .errors import IncompleteExpressionError
61
+ from .errors import LexerError
62
+ from .errors import ParseError
63
63
  from .lexer import Lexer
64
64
  from .lexer import Token
65
65
  from .visitor import GraphvizVisitor
@@ -36,7 +36,7 @@ from .ast import Subexpression
36
36
  from .ast import UnaryArithmeticOperator
37
37
  from .ast import ValueProjection
38
38
  from .ast import VariableRef
39
- from .exceptions import UndefinedVariableError
39
+ from .errors import UndefinedVariableError
40
40
  from .functions import DefaultFunctions
41
41
  from .functions import Functions
42
42
  from .scope import ScopedChainDict
@@ -61,10 +61,10 @@ class Node(
61
61
  except KeyError:
62
62
  pass
63
63
 
64
- dc_info = dc.reflect(cls)
64
+ dc_rfl = dc.reflect(cls)
65
65
  fields = Node._Fields(
66
- cmp_fields=tuple(f.name for f in dc_info.instance_fields if f.compare),
67
- hash_fields=tuple(f.name for f in dc_info.instance_fields if (f.compare if f.hash is None else f.hash)),
66
+ cmp_fields=tuple(f.name for f in dc_rfl.instance_fields if f.compare),
67
+ hash_fields=tuple(f.name for f in dc_rfl.instance_fields if (f.compare if f.hash is None else f.hash)),
68
68
  )
69
69
 
70
70
  setattr(cls, '__node_fields__', fields)
omlish/text/mangle.py CHANGED
@@ -1,6 +1,7 @@
1
1
  # ruff: noqa: UP006 UP007
2
2
  # @omlish-lite
3
3
  import dataclasses as dc
4
+ import re
4
5
  import typing as ta
5
6
 
6
7
  from ..lite.cached import cached_nullary
@@ -26,16 +27,74 @@ class StringMangler:
26
27
  check.not_in(self.escape, self.escaped)
27
28
  check.arg(len(set(self.escaped)) == len(self.escaped))
28
29
 
30
+ #
31
+
32
+ @cached_nullary
33
+ def replaced(self) -> ta.Tuple[str, ...]:
34
+ return (self.escape, *self.escaped)
35
+
36
+ @cached_nullary
37
+ def replaced_set(self) -> ta.FrozenSet[str]:
38
+ return frozenset(self.replaced())
39
+
40
+ @cached_nullary
41
+ def replaced_indexes(self) -> ta.Mapping[str, int]:
42
+ return {s: i for i, s in enumerate(self.replaced())}
43
+
44
+ @cached_nullary
45
+ def replaced_pat(self) -> re.Pattern:
46
+ return re.compile('|'.join(re.escape(k) for k in self.replaced()))
47
+
48
+ #
49
+
50
+ @cached_nullary
51
+ def replacement_pad(self) -> int:
52
+ return len('%x' % (len(self.replaced()),)) # noqa
53
+
29
54
  @cached_nullary
30
55
  def replacements(self) -> ta.Sequence[ta.Tuple[str, str]]:
31
- return [(l, self.escape + str(i)) for i, l in enumerate([self.escape, *self.escaped])]
56
+ fmt = f'%0{self.replacement_pad()}x'
57
+ return [
58
+ (l, self.escape + fmt % (i,))
59
+ for i, l in enumerate(self.replaced())
60
+ ]
61
+
62
+ @cached_nullary
63
+ def replacements_dict(self) -> ta.Mapping[str, str]:
64
+ return dict(self.replacements())
65
+
66
+ @cached_nullary
67
+ def inverse_replacements_dict(self) -> ta.Mapping[str, str]:
68
+ return {v: k for k, v in self.replacements()}
69
+
70
+ @cached_nullary
71
+ def replacements_pat(self) -> re.Pattern:
72
+ return re.compile(''.join([re.escape(self.escape), '.' * self.replacement_pad()]))
73
+
74
+ #
75
+
76
+ # def mangle(self, s: str) -> str:
77
+ # ecs = sorted(
78
+ # frozenset(s) & self.replaced_set(),
79
+ # key=self.replaced_indexes().__getitem__,
80
+ # )
81
+ # rd = self.replacements_dict()
82
+ # for l in ecs:
83
+ # r = rd[l]
84
+ # s = s.replace(l, r)
85
+ # return s
32
86
 
33
87
  def mangle(self, s: str) -> str:
34
- for l, r in self.replacements():
35
- s = s.replace(l, r)
36
- return s
88
+ rd = self.replacements_dict()
89
+ return self.replaced_pat().sub(lambda m: rd[m.group(0)], s)
90
+
91
+ #
92
+
93
+ # def unmangle(self, s: str) -> str:
94
+ # for l, r in reversed(self.replacements()):
95
+ # s = s.replace(r, l)
96
+ # return s
37
97
 
38
98
  def unmangle(self, s: str) -> str:
39
- for l, r in reversed(self.replacements()):
40
- s = s.replace(r, l)
41
- return s
99
+ ird = self.inverse_replacements_dict()
100
+ return self.replacements_pat().sub(lambda m: ird[m.group(0)], s)
@@ -36,7 +36,7 @@ class UniqueTypedValue(TypedValue, lang.Abstract):
36
36
 
37
37
 
38
38
  @dc.dataclass(frozen=True)
39
- @dc.extra_params(generic_init=True)
39
+ @dc.extra_class_params(generic_init=True)
40
40
  class ScalarTypedValue(TypedValue, lang.Abstract, ta.Generic[T]):
41
41
  v: T
42
42
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: omlish
3
- Version: 0.0.0.dev282
3
+ Version: 0.0.0.dev284
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -15,7 +15,7 @@ License-File: LICENSE
15
15
  Provides-Extra: all
16
16
  Requires-Dist: anyio~=4.9; extra == "all"
17
17
  Requires-Dist: sniffio~=1.3; extra == "all"
18
- Requires-Dist: greenlet~=3.1; extra == "all"
18
+ Requires-Dist: greenlet~=3.2; extra == "all"
19
19
  Requires-Dist: trio~=0.29; extra == "all"
20
20
  Requires-Dist: trio-asyncio~=0.15; extra == "all"
21
21
  Requires-Dist: lz4~=4.4; extra == "all"
@@ -53,7 +53,7 @@ Requires-Dist: wrapt~=1.17; extra == "all"
53
53
  Provides-Extra: async
54
54
  Requires-Dist: anyio~=4.9; extra == "async"
55
55
  Requires-Dist: sniffio~=1.3; extra == "async"
56
- Requires-Dist: greenlet~=3.1; extra == "async"
56
+ Requires-Dist: greenlet~=3.2; extra == "async"
57
57
  Requires-Dist: trio~=0.29; extra == "async"
58
58
  Requires-Dist: trio-asyncio~=0.15; extra == "async"
59
59
  Provides-Extra: compress