omlish 0.0.0.dev134__py3-none-any.whl → 0.0.0.dev137__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 (56) hide show
  1. omlish/.manifests.json +0 -12
  2. omlish/__about__.py +2 -2
  3. omlish/cached.py +2 -2
  4. omlish/collections/mappings.py +1 -1
  5. omlish/diag/_pycharm/runhack.py +3 -0
  6. omlish/formats/json/stream/lex.py +1 -1
  7. omlish/formats/json/stream/parse.py +1 -1
  8. omlish/{genmachine.py → funcs/genmachine.py} +4 -2
  9. omlish/{matchfns.py → funcs/match.py} +1 -1
  10. omlish/{fnpairs.py → funcs/pairs.py} +3 -3
  11. omlish/http/sessions.py +1 -1
  12. omlish/io/compress/__init__.py +0 -0
  13. omlish/io/compress/abc.py +104 -0
  14. omlish/io/compress/adapters.py +147 -0
  15. omlish/io/compress/bz2.py +41 -0
  16. omlish/io/compress/gzip.py +301 -0
  17. omlish/io/compress/lzma.py +31 -0
  18. omlish/io/compress/types.py +29 -0
  19. omlish/io/generators.py +50 -0
  20. omlish/lang/__init__.py +8 -1
  21. omlish/lang/generators.py +182 -0
  22. omlish/lang/iterables.py +28 -51
  23. omlish/lang/maybes.py +4 -4
  24. omlish/lite/fdio/corohttp.py +5 -1
  25. omlish/lite/marshal.py +9 -6
  26. omlish/marshal/base.py +1 -1
  27. omlish/marshal/factories.py +1 -1
  28. omlish/marshal/forbidden.py +1 -1
  29. omlish/marshal/iterables.py +1 -1
  30. omlish/marshal/mappings.py +1 -1
  31. omlish/marshal/maybes.py +1 -1
  32. omlish/marshal/standard.py +1 -1
  33. omlish/marshal/unions.py +1 -1
  34. omlish/secrets/pwhash.py +1 -1
  35. omlish/secrets/subprocesses.py +3 -1
  36. omlish/specs/jsonrpc/marshal.py +1 -1
  37. omlish/specs/openapi/marshal.py +1 -1
  38. {omlish-0.0.0.dev134.dist-info → omlish-0.0.0.dev137.dist-info}/METADATA +1 -1
  39. {omlish-0.0.0.dev134.dist-info → omlish-0.0.0.dev137.dist-info}/RECORD +49 -47
  40. omlish/formats/json/cli/__main__.py +0 -11
  41. omlish/formats/json/cli/cli.py +0 -298
  42. omlish/formats/json/cli/formats.py +0 -71
  43. omlish/formats/json/cli/io.py +0 -74
  44. omlish/formats/json/cli/parsing.py +0 -82
  45. omlish/formats/json/cli/processing.py +0 -48
  46. omlish/formats/json/cli/rendering.py +0 -92
  47. /omlish/collections/{_abc.py → abc.py} +0 -0
  48. /omlish/{formats/json/cli → funcs}/__init__.py +0 -0
  49. /omlish/{fnpipes.py → funcs/pipes.py} +0 -0
  50. /omlish/io/{_abc.py → abc.py} +0 -0
  51. /omlish/logs/{_abc.py → abc.py} +0 -0
  52. /omlish/sql/{_abc.py → abc.py} +0 -0
  53. {omlish-0.0.0.dev134.dist-info → omlish-0.0.0.dev137.dist-info}/LICENSE +0 -0
  54. {omlish-0.0.0.dev134.dist-info → omlish-0.0.0.dev137.dist-info}/WHEEL +0 -0
  55. {omlish-0.0.0.dev134.dist-info → omlish-0.0.0.dev137.dist-info}/entry_points.txt +0 -0
  56. {omlish-0.0.0.dev134.dist-info → omlish-0.0.0.dev137.dist-info}/top_level.txt +0 -0
omlish/.manifests.json CHANGED
@@ -23,18 +23,6 @@
23
23
  }
24
24
  }
25
25
  },
26
- {
27
- "module": ".formats.json.cli.__main__",
28
- "attr": "_CLI_MODULE",
29
- "file": "omlish/formats/json/cli/__main__.py",
30
- "line": 1,
31
- "value": {
32
- "$omdev.cli.types.CliModule": {
33
- "cmd_name": "json",
34
- "mod_name": "omlish.formats.json.cli.__main__"
35
- }
36
- }
37
- },
38
26
  {
39
27
  "module": ".secrets.pwgen",
40
28
  "attr": "_CLI_MODULE",
omlish/__about__.py CHANGED
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev134'
2
- __revision__ = '2ce79daa2fabaed83f01745229d814bc8aeb7628'
1
+ __version__ = '0.0.0.dev137'
2
+ __revision__ = '895417d0442f51853415386ace94b1c41da0c990'
3
3
 
4
4
 
5
5
  #
omlish/cached.py CHANGED
@@ -10,9 +10,9 @@ builtins and thus not distinguish it from a normal property.
10
10
 
11
11
  """
12
12
  from .lang.cached import _CachedProperty # noqa
13
- from .lang.cached import cached_function
13
+ from .lang.cached import cached_function as _cached_function
14
14
 
15
- function = cached_function
15
+ function = _cached_function
16
16
 
17
17
  property = property # noqa
18
18
 
@@ -86,7 +86,7 @@ class DynamicTypeMap(ta.Generic[V]):
86
86
  self._items = list(items)
87
87
  self._weak = bool(weak)
88
88
 
89
- self._cache: ta.MutableMapping[type, ta.Any] = weakref.WeakKeyDictionary()
89
+ self._cache: ta.MutableMapping[type, ta.Any] = weakref.WeakKeyDictionary() if weak else {}
90
90
 
91
91
  @property
92
92
  def items(self) -> ta.Sequence[V]:
@@ -3,7 +3,10 @@
3
3
  .venv/bin/python $(curl -LsSf https://raw.githubusercontent.com/wrmsr/omlish/master/omlish/diag/_pycharm/runhack.py -o $(mktemp) && echo "$_") install
4
4
 
5
5
  ==
6
+ TODO:
7
+ - check for existing files - can't run regular dep entrypoints now
6
8
 
9
+ ==
7
10
  See:
8
11
  - https://github.com/JetBrains/intellij-community/blob/6400f70dde6f743e39a257a5a78cc51b644c835e/python/helpers/pycharm/_jb_pytest_runner.py
9
12
  - https://github.com/JetBrains/intellij-community/blob/5a4e584aa59767f2e7cf4bd377adfaaf7503984b/python/helpers/pycharm/_jb_runner_tools.py
@@ -11,7 +11,7 @@ import re
11
11
  import typing as ta
12
12
 
13
13
  from .... import check
14
- from ....genmachine import GenMachine
14
+ from ....funcs.genmachine import GenMachine
15
15
 
16
16
 
17
17
  ##
@@ -1,7 +1,7 @@
1
1
  import typing as ta
2
2
 
3
3
  from .... import lang
4
- from ....genmachine import GenMachine
4
+ from ....funcs.genmachine import GenMachine
5
5
  from .lex import SCALAR_VALUE_TYPES
6
6
  from .lex import VALUE_TOKEN_KINDS
7
7
  from .lex import ScalarValue
@@ -12,7 +12,7 @@ import typing as ta
12
12
  I = ta.TypeVar('I')
13
13
  O = ta.TypeVar('O')
14
14
 
15
- # MachineGen: ta.TypeAlias = ta.Generator[ta.Iterable[O] | None, I, ta.Optional[MachineGen[I, O]]]
15
+ # MachineGen: ta.TypeAlias = ta.Generator[ta.Iterable[O] | None, I | None, ta.Optional[MachineGen[I, O]]]
16
16
  MachineGen: ta.TypeAlias = ta.Generator[ta.Any, ta.Any, ta.Any]
17
17
 
18
18
 
@@ -93,8 +93,10 @@ class GenMachine(ta.Generic[I, O]):
93
93
  if self._gen is None:
94
94
  raise GenMachine.ClosedError
95
95
 
96
+ gi: I | None = i
96
97
  try:
97
- while (o := self._gen.send(i)) is not None:
98
+ while (o := self._gen.send(gi)) is not None:
99
+ gi = None
98
100
  yield from o
99
101
 
100
102
  except StopIteration as s:
@@ -8,7 +8,7 @@ import abc
8
8
  import dataclasses as dc
9
9
  import typing as ta
10
10
 
11
- from . import lang
11
+ from .. import lang
12
12
 
13
13
 
14
14
  T = ta.TypeVar('T')
@@ -20,7 +20,7 @@ import codecs
20
20
  import dataclasses as dc
21
21
  import typing as ta
22
22
 
23
- from . import lang
23
+ from .. import lang
24
24
 
25
25
 
26
26
  if ta.TYPE_CHECKING:
@@ -39,7 +39,7 @@ if ta.TYPE_CHECKING:
39
39
  import yaml as _yaml
40
40
  import zstandard as _zstandard
41
41
 
42
- from .formats import json as _json
42
+ from ..formats import json as _json
43
43
 
44
44
  else:
45
45
  _bz2 = lang.proxy_import('bz2')
@@ -57,7 +57,7 @@ else:
57
57
  _yaml = lang.proxy_import('yaml')
58
58
  _zstandard = lang.proxy_import('zstandard')
59
59
 
60
- _json = lang.proxy_import('.formats.json', __package__)
60
+ _json = lang.proxy_import('..formats.json', __package__)
61
61
 
62
62
 
63
63
  ##
omlish/http/sessions.py CHANGED
@@ -8,9 +8,9 @@ import time
8
8
  import typing as ta
9
9
  import zlib
10
10
 
11
- from .. import fnpairs as fpa
12
11
  from .. import lang
13
12
  from .. import secrets as sec
13
+ from ..funcs import pairs as fpa
14
14
  from .cookies import dump_cookie
15
15
  from .cookies import parse_cookie
16
16
  from .json import JSON_TAGGER
File without changes
@@ -0,0 +1,104 @@
1
+ """
2
+ https://docs.python.org/3/library/bz2.html#bz2.BZ2Compressor
3
+ https://docs.python.org/3/library/zlib.html#zlib.decompressobj
4
+ https://docs.python.org/3/library/lzma.html#lzma.LZMADecompressor
5
+ """
6
+ import abc
7
+
8
+
9
+ ##
10
+
11
+
12
+ class Compressor(abc.ABC):
13
+ @abc.abstractmethod
14
+ def compress(self, data: bytes) -> bytes:
15
+ """
16
+ Provide data to the compressor object. Returns a chunk of compressed data if possible, or an empty byte string
17
+ otherwise.
18
+
19
+ When you have finished providing data to the compressor, call the flush() method to finish the compression
20
+ process.
21
+ """
22
+
23
+ raise NotImplementedError
24
+
25
+ @abc.abstractmethod
26
+ def flush(self) -> bytes:
27
+ """
28
+ Finish the compression process. Returns the compressed data left in internal buffers.
29
+
30
+ The compressor object may not be used after this method has been called.
31
+ """
32
+
33
+ raise NotImplementedError
34
+
35
+
36
+ ##
37
+
38
+
39
+ class Decompressor(abc.ABC):
40
+ @property
41
+ @abc.abstractmethod
42
+ def unused_data(self) -> bytes:
43
+ """
44
+ Data found after the end of the compressed stream.
45
+
46
+ If this attribute is accessed before the end of the stream has been reached, its value will be b''.
47
+ """
48
+
49
+ raise NotImplementedError
50
+
51
+ @property
52
+ @abc.abstractmethod
53
+ def eof(self) -> bool:
54
+ """True if the end-of-stream marker has been reached."""
55
+
56
+ raise NotImplementedError
57
+
58
+ @abc.abstractmethod
59
+ def decompress(self, data: bytes, *max_length: int) -> bytes:
60
+ """
61
+ Decompress data, returning a bytes object containing the uncompressed data corresponding to at least part of the
62
+ data in string. This data should be concatenated to the output produced by any preceding calls to the
63
+ decompress() method. Some of the input data may be preserved in internal buffers for later processing.
64
+
65
+ If the optional parameter max_length is non-zero then the return value will be no longer than max_length.
66
+ """
67
+
68
+ raise NotImplementedError
69
+
70
+
71
+ class NeedsInputDecompressor(Decompressor):
72
+ """
73
+ Used by:
74
+ - bz2.BZ2Decompressor
75
+ - lzma.LZMADecompressor
76
+ """
77
+
78
+ @property
79
+ @abc.abstractmethod
80
+ def needs_input(self) -> bool:
81
+ """
82
+ False if the decompress() method can provide more decompressed data before requiring new uncompressed input.
83
+ """
84
+
85
+ raise NotImplementedError
86
+
87
+
88
+ class UnconsumedTailDecompressor(Decompressor):
89
+ """
90
+ Used by:
91
+ - zlib.decompressobj
92
+ """
93
+
94
+ @property
95
+ @abc.abstractmethod
96
+ def unconsumed_tail(self) -> bytes:
97
+ """
98
+ A bytes object that contains any data that was not consumed by the last decompress() call because it exceeded
99
+ the limit for the uncompressed data buffer. This data has not yet been seen by the zlib machinery, so you must
100
+ feed it (possibly with further data concatenated to it) back to a subsequent decompress() method call in order
101
+ to get correct output.
102
+ """
103
+
104
+ raise NotImplementedError
@@ -0,0 +1,147 @@
1
+ # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
2
+ # --------------------------------------------
3
+ #
4
+ # 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization
5
+ # ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated
6
+ # documentation.
7
+ #
8
+ # 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive,
9
+ # royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative
10
+ # works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License
11
+ # Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
12
+ # 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Python Software Foundation; All Rights Reserved" are retained in Python
13
+ # alone or in any derivative version prepared by Licensee.
14
+ #
15
+ # 3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and
16
+ # wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in
17
+ # any such work a brief summary of the changes made to Python.
18
+ #
19
+ # 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES,
20
+ # EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY
21
+ # OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY
22
+ # RIGHTS.
23
+ #
24
+ # 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL
25
+ # DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF
26
+ # ADVISED OF THE POSSIBILITY THEREOF.
27
+ #
28
+ # 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions.
29
+ #
30
+ # 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint
31
+ # venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade
32
+ # name in a trademark sense to endorse or promote products or services of Licensee, or any third party.
33
+ #
34
+ # 8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this
35
+ # License Agreement.
36
+ # ~> https://github.com/python/cpython/blob/f19c50a4817ffebb26132182ed8cec6a72342cc0/Lib/_compression.py
37
+ import typing as ta
38
+
39
+ from ... import check
40
+ from .abc import Compressor
41
+ from .abc import NeedsInputDecompressor
42
+ from .abc import UnconsumedTailDecompressor
43
+ from .types import IncrementalCompressor
44
+ from .types import IncrementalDecompressor
45
+
46
+
47
+ ##
48
+
49
+
50
+ class CompressorIncrementalAdapter:
51
+ def __init__(
52
+ self,
53
+ factory: ta.Callable[..., Compressor],
54
+ ) -> None:
55
+ super().__init__()
56
+
57
+ self._factory = factory
58
+
59
+ def __call__(self) -> IncrementalCompressor:
60
+ compressor = self._factory()
61
+
62
+ while True:
63
+ data = check.isinstance((yield None), bytes)
64
+ if not data:
65
+ break
66
+
67
+ compressed = compressor.compress(data)
68
+ if compressed:
69
+ check.none((yield compressed))
70
+
71
+ if (fl := compressor.flush()):
72
+ check.none((yield fl))
73
+
74
+ check.none((yield b''))
75
+
76
+
77
+ ##
78
+
79
+
80
+ class DecompressorIncrementalAdapter:
81
+ def __init__(
82
+ self,
83
+ factory: ta.Callable[..., NeedsInputDecompressor | UnconsumedTailDecompressor],
84
+ *,
85
+ trailing_error: type[BaseException] | tuple[type[BaseException], ...] = (),
86
+ ) -> None:
87
+ super().__init__()
88
+
89
+ self._factory = factory
90
+ self._trailing_error = trailing_error
91
+
92
+ def __call__(self) -> IncrementalDecompressor:
93
+ pos = 0
94
+
95
+ data = None # Default if EOF is encountered
96
+
97
+ decompressor = self._factory()
98
+
99
+ while True:
100
+ # Depending on the input data, our call to the decompressor may not return any data. In this case, try again
101
+ # after reading another block.
102
+ while True:
103
+ if decompressor.eof:
104
+ rawblock = decompressor.unused_data
105
+ if not rawblock:
106
+ rawblock = check.isinstance((yield None), bytes)
107
+ if not rawblock:
108
+ break
109
+
110
+ # Continue to next stream.
111
+ decompressor = self._factory()
112
+
113
+ try:
114
+ data = decompressor.decompress(rawblock)
115
+ except self._trailing_error:
116
+ # Trailing data isn't a valid compressed stream; ignore it.
117
+ break
118
+
119
+ else:
120
+ if hasattr(decompressor, 'needs_input'):
121
+ if decompressor.needs_input:
122
+ rawblock = check.isinstance((yield None), bytes)
123
+ if not rawblock:
124
+ raise EOFError('Compressed file ended before the end-of-stream marker was reached')
125
+ else:
126
+ rawblock = b''
127
+
128
+ elif hasattr(decompressor, 'unconsumed_tail'):
129
+ if not (rawblock := decompressor.unconsumed_tail):
130
+ rawblock = check.isinstance((yield None), bytes)
131
+ if not rawblock:
132
+ raise EOFError('Compressed file ended before the end-of-stream marker was reached')
133
+
134
+ else:
135
+ raise TypeError(decompressor)
136
+
137
+ data = decompressor.decompress(rawblock)
138
+
139
+ if data:
140
+ break
141
+
142
+ if not data:
143
+ check.none((yield b''))
144
+ return
145
+
146
+ pos += len(data)
147
+ check.none((yield data))
@@ -0,0 +1,41 @@
1
+ import functools
2
+ import typing as ta
3
+
4
+ from ... import lang
5
+ from .adapters import CompressorIncrementalAdapter
6
+ from .adapters import DecompressorIncrementalAdapter
7
+ from .types import IncrementalCompressor
8
+ from .types import IncrementalDecompressor
9
+
10
+
11
+ if ta.TYPE_CHECKING:
12
+ import bz2
13
+ else:
14
+ bz2 = lang.proxy_import('bz2')
15
+
16
+
17
+ class IncrementalBz2Compressor:
18
+ def __init__(
19
+ self,
20
+ *,
21
+ compresslevel: int = 9,
22
+ ) -> None:
23
+ super().__init__()
24
+
25
+ self._compresslevel = compresslevel
26
+
27
+ def __call__(self) -> IncrementalCompressor:
28
+ return CompressorIncrementalAdapter(
29
+ functools.partial(
30
+ bz2.BZ2Compressor, # type: ignore
31
+ self._compresslevel,
32
+ ),
33
+ )()
34
+
35
+
36
+ class IncrementalBz2Decompressor:
37
+ def __call__(self) -> IncrementalDecompressor:
38
+ return DecompressorIncrementalAdapter(
39
+ bz2.BZ2Decompressor, # type: ignore
40
+ trailing_error=OSError,
41
+ )()