kisstdlib 0.0.1__tar.gz

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.
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.1
2
+ Name: kisstdlib
3
+ Version: 0.0.1
4
+ Summary: Keep It Simple STandarD LIBraries set for Python
5
+ Author-email: Jan Malakhovski <oxij@oxij.org>
6
+ Keywords: sys,stdlib
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: License :: OSI Approved :: Python Software Foundation License
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+
14
+ # What?
15
+
16
+ Keep It Simple STandarD LIBraries set for Python.
17
+
18
+ A very alpha Work In Progress kind of thing ATM.
@@ -0,0 +1,5 @@
1
+ # What?
2
+
3
+ Keep It Simple STandarD LIBraries set for Python.
4
+
5
+ A very alpha Work In Progress kind of thing ATM.
@@ -0,0 +1,25 @@
1
+ # Copyright (c) 2018-2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
@@ -0,0 +1,27 @@
1
+ # Copyright (c) 2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ from .better import *
@@ -0,0 +1,208 @@
1
+ # Copyright (c) 2022-2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ import typing as _t
28
+ from argparse import *
29
+ from gettext import gettext as _
30
+
31
+ class BetterHelpFormatter(HelpFormatter):
32
+ """Like argparse.HelpFormatter, but with better formatting.
33
+ Also, it adds `add_code` function.
34
+ """
35
+
36
+ def _fill_text(self, text : str, width : int, indent : str) -> str:
37
+ import textwrap
38
+ res = []
39
+ for line in text.splitlines():
40
+ if line == "":
41
+ res.append(line)
42
+ continue
43
+
44
+ for sub in textwrap.wrap(line, width - len(indent)):
45
+ sub = indent + sub
46
+ res.append(sub)
47
+ return "\n".join(res)
48
+
49
+ def _split_lines(self, text : str, width : int) -> list[str]:
50
+ import textwrap
51
+ res = []
52
+ for line in text.splitlines():
53
+ res += textwrap.wrap(line, width)
54
+ return res
55
+
56
+ def add_code(self, text : str) -> None:
57
+ self.add_text(text.strip())
58
+
59
+ class MarkdownBetterHelpFormatter(BetterHelpFormatter):
60
+ """BetterHelpFormatter that outputs stuff formatted in Markdown"""
61
+
62
+ def add_code(self, text : str) -> None:
63
+ self.add_text("```\n" + text.strip() + "\n```")
64
+
65
+ def _format_usage(self, usage : str | None, actions : _t.Any, groups : _t.Any, prefix : str | None) -> str:
66
+ return super()._format_usage(usage, actions, groups, "")
67
+
68
+ def _format_action(self, action : _t.Any) -> str:
69
+ # determine the required width and the entry label
70
+ action_header = self._format_action_invocation(action)
71
+
72
+ tup = self._current_indent, '', "`" + action_header + "`"
73
+ action_header = '%*s- %s\n' % tup
74
+
75
+ # collect the pieces of the action help
76
+ parts = [action_header]
77
+
78
+ # if there was help for the action, add it
79
+ if action.help and action.help.strip():
80
+ first = True
81
+ for line in self._expand_help(action).splitlines():
82
+ if first:
83
+ parts.append('%*s: %s\n' % (self._current_indent, '', line))
84
+ else:
85
+ parts.append('%*s %s\n' % (self._current_indent, '', line))
86
+ first = False
87
+
88
+ # or add a newline if the description doesn't end with one
89
+ elif not action_header.endswith('\n'):
90
+ parts.append('\n')
91
+
92
+ # if there are any sub-actions, add their help as well
93
+ for subaction in self._iter_indented_subactions(action):
94
+ parts.append(self._format_action(subaction))
95
+
96
+ # return a single string
97
+ return self._join_parts(parts)
98
+
99
+ class _Section(HelpFormatter._Section):
100
+ def format_help(self) -> str:
101
+ if self.parent is not None:
102
+ self.formatter._indent()
103
+ join = self.formatter._join_parts
104
+ item_help = join([func(*args) for func, args in self.items])
105
+ if self.parent is not None:
106
+ self.formatter._dedent()
107
+
108
+ # return nothing if the section was empty
109
+ if not item_help:
110
+ return ''
111
+
112
+ # add the heading if the section was non-empty
113
+ if self.heading is not SUPPRESS and self.heading is not None:
114
+ heading = '%*s- %s:\n' % (self.formatter._current_indent, '', self.heading)
115
+ else:
116
+ heading = ''
117
+
118
+ # join the section-initial newline, the heading and the help
119
+ return join(['\n', heading, item_help, '\n'])
120
+
121
+ class BetterArgumentParser(ArgumentParser):
122
+ """Like argparse.ArgumentParser but uses BetterHelpFormatter by default,
123
+ adds `--help` only to the root node, and
124
+ that `--help` prints the help for all the subcommands at once.
125
+ Also, provides `add_version` option.
126
+ """
127
+
128
+ formatter_class : type[BetterHelpFormatter]
129
+
130
+ def __init__(self,
131
+ prog : str | None = None,
132
+ version : str | None = None,
133
+ add_version : bool = False, # we set these two to False by default
134
+ add_help : bool = False, # so that subparsers don't get them enabled by default
135
+ additional_sections : list[_t.Callable[[BetterHelpFormatter], None]] = [],
136
+ formatter_class : type[BetterHelpFormatter] = BetterHelpFormatter,
137
+ *args : _t.Any, **kwargs : _t.Any) -> None:
138
+ super().__init__(prog, *args, formatter_class = formatter_class, add_help = False, **kwargs) # type: ignore
139
+
140
+ if version is None:
141
+ version = "dev"
142
+ if prog is not None:
143
+ try:
144
+ import importlib.metadata as meta
145
+ try:
146
+ version = meta.version(prog)
147
+ except meta.PackageNotFoundError:
148
+ pass
149
+ except ImportError:
150
+ pass
151
+
152
+ self.version = version
153
+ self.add_version = add_version
154
+ self.add_help = add_help
155
+ self.additional_sections = additional_sections
156
+
157
+ default_prefix = '-' if '-' in self.prefix_chars else self.prefix_chars[0]
158
+ if self.add_version:
159
+ self.add_argument(default_prefix*2 + "version", action="version", version="%(prog)s " + version)
160
+
161
+ if self.add_help:
162
+ self.add_argument(
163
+ default_prefix + "h", default_prefix*2 + "help", action='help',
164
+ default=SUPPRESS, help=_('show this help message and exit'))
165
+
166
+ def set_formatter_class(self, formatter_class : type[BetterHelpFormatter]) -> None:
167
+ self.formatter_class = formatter_class
168
+ if hasattr(self._subparsers, "_group_actions"):
169
+ for grp in self._subparsers._group_actions: # type: ignore
170
+ for choice, e in grp.choices.items(): # type: ignore
171
+ if e.formatter_class != formatter_class:
172
+ e.formatter_class = formatter_class
173
+
174
+ def format_help(self, width : int | None = None) -> str:
175
+ if width is None:
176
+ import shutil
177
+ width = shutil.get_terminal_size().columns - 2
178
+ formatter = self.formatter_class(prog=self.prog, width=width)
179
+
180
+ formatter.add_usage(self.usage, self._actions, self._mutually_exclusive_groups)
181
+ formatter.add_text(self.description)
182
+
183
+ if hasattr(self, "_action_groups"):
184
+ for action_group in self._action_groups:
185
+ formatter.start_section(action_group.title)
186
+ formatter.add_text(action_group.description)
187
+ formatter.add_arguments(action_group._group_actions)
188
+ formatter.end_section()
189
+
190
+ res : str = "# " + formatter.format_help()
191
+
192
+ if hasattr(self._subparsers, "_group_actions"):
193
+ seen = set()
194
+ for grp in self._subparsers._group_actions: # type: ignore
195
+ for choice, e in grp.choices.items(): # type: ignore
196
+ if e in seen: continue
197
+ seen.add(e)
198
+ e.formatter_class = self.formatter_class
199
+ res += "\n#" + e.format_help(width=width)
200
+
201
+ for gen in self.additional_sections:
202
+ formatter = self.formatter_class(prog=self.prog, width=width)
203
+ gen(formatter)
204
+ res += "\n" + formatter.format_help()
205
+
206
+ formatter.add_text(self.epilog)
207
+
208
+ return res
@@ -0,0 +1,44 @@
1
+ # Copyright (c) 2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ """Exceptions with printable descriptions.
28
+ """
29
+
30
+ import typing as _t
31
+
32
+ class CatastrophicFailure(Exception):
33
+ def __init__(self, what : str, *args : _t.Any) -> None:
34
+ super().__init__()
35
+ self.description = what % args
36
+
37
+ def __str__(self) -> str:
38
+ return self.description
39
+
40
+ def elaborate(self, what : str, *args : _t.Any) -> None:
41
+ self.description = what % args + ": " + self.description
42
+
43
+ class Failure(CatastrophicFailure):
44
+ pass
@@ -0,0 +1,57 @@
1
+ # Copyright (c) 2018-2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ """KISS IO File Object hierarchy.
28
+
29
+ What?
30
+
31
+ An alternative to Python's `io` module.
32
+
33
+ Why?
34
+
35
+ APIs of Python's `io` module are way too complex. It only really works well
36
+ when you use either buffered raw or buffered textual IO and never try to mix
37
+ them.
38
+
39
+ The problem stems from the fact that Python's `io.RawIOBase` and
40
+ `io.TextIOBase` are trying to give the same APIs, but they do different
41
+ things. Which, after being multiplied with the differences of buffered and
42
+ unbuffered `read`s and `write`s, essentially gives FOUR different file
43
+ object semantics under the same file object API.
44
+
45
+ Here, instead we have separate calls for `bytes` and `str` versions of
46
+ `read` and `write` calls, buffering is completely transparent, reading and
47
+ writing parts are split into different interfaces, and text encoding
48
+ handling is split between them (because it has to be handled differently).
49
+
50
+ This also provides `TIOEncoder` and (WIP `TIODecoder`) classes that can do
51
+ simple serialization/de-serialization a-la Pascal.
52
+
53
+ """
54
+
55
+ from .base import *
56
+ from .wrapper import *
57
+ from .encoder import *
@@ -0,0 +1,109 @@
1
+ # Copyright (c) 2018-2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ import abc as _abc
28
+ import sys as _sys
29
+ import typing as _t
30
+
31
+ MEGABYTE = 1024 * 1024
32
+
33
+ # anything that can be `write`n
34
+ ByteString = _t.Union[bytes, bytearray, memoryview]
35
+
36
+ ShutdownState = int # _t.NewType("ShutdownState", int), ideally, but then ~ and | operations won't work
37
+ SHUT_NONE = ShutdownState(0)
38
+ SHUT_READ = ShutdownState(1)
39
+ SHUT_WRITE = ShutdownState(2)
40
+ SHUT_BOTH = ShutdownState(3)
41
+
42
+ class MinimalIO(metaclass=_abc.ABCMeta):
43
+ def __repr__(self) -> str:
44
+ return "<%s %s>" % (self.__class__.__name__, hex(id(self)))
45
+
46
+ @_abc.abstractmethod
47
+ def close(self) -> None:
48
+ raise NotImplementedError()
49
+
50
+ @property
51
+ @_abc.abstractmethod
52
+ def closed(self) -> bool:
53
+ raise NotImplementedError()
54
+
55
+ @_abc.abstractmethod
56
+ def shutdown(self, what : ShutdownState) -> None:
57
+ raise NotImplementedError()
58
+
59
+ @property
60
+ @_abc.abstractmethod
61
+ def shutdown_state(self) -> ShutdownState:
62
+ raise NotImplementedError()
63
+
64
+ class MinimalIOReader(MinimalIO):
65
+ @_abc.abstractmethod
66
+ def read_some_bytes(self, size : int) -> bytes:
67
+ raise NotImplementedError()
68
+
69
+ def read_all_bytes(self, chunk_size : int = MEGABYTE) -> bytes:
70
+ data : list[bytes] = []
71
+ while True:
72
+ res = self.read_some_bytes(chunk_size)
73
+ rlen = len(res)
74
+ if rlen == 0: break
75
+ data.append(res)
76
+ return b"".join(data)
77
+
78
+ def read_exactly_bytes(self, size : int) -> bytes:
79
+ data : list[bytes] = []
80
+ total = 0
81
+ while total < size:
82
+ res = self.read_some_bytes(size - total)
83
+ rlen = len(res)
84
+ if rlen == 0: break
85
+ data.append(res)
86
+ total += rlen
87
+ return b"".join(data)
88
+
89
+ def read_bytes(self, size : int | None = None) -> bytes:
90
+ if size is None:
91
+ return self.read_all_bytes()
92
+ else:
93
+ return self.read_exactly_bytes(size)
94
+
95
+ class MinimalIOWriter(MinimalIO):
96
+ @_abc.abstractmethod
97
+ def write_some_bytes(self, data : ByteString) -> int:
98
+ raise NotImplementedError()
99
+
100
+ def write_bytes(self, data : ByteString) -> None:
101
+ done = 0
102
+ view = memoryview(data)
103
+ datalen = len(data)
104
+ while done < datalen:
105
+ done += self.write_some_bytes(view[done:])
106
+
107
+ @_abc.abstractmethod
108
+ def flush(self) -> None:
109
+ raise NotImplementedError()
@@ -0,0 +1,28 @@
1
+ # Copyright (c) 2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ from .base import *
28
+ from .pyrepr import *
@@ -0,0 +1,80 @@
1
+ # Copyright (c) 2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ import sys as _sys
28
+ import typing as _t
29
+
30
+ from ..wrapper import *
31
+
32
+ class TIOEncoder(TIOWrappedWriter):
33
+ default : _t.Callable[[_t.Any, _t.Any], None]
34
+
35
+ def __init__(self,
36
+ fobj : _t.Any,
37
+ eol : bytes = b"\n",
38
+ encoding : str = _sys.getdefaultencoding(),
39
+ encoders : dict[type[_t.Any], _t.Callable[[_t.Any, _t.Any], None]] = {},
40
+ default : _t.Callable[[_t.Any, _t.Any], None] | None = None) -> None:
41
+ super().__init__(fobj, eol, encoding)
42
+ self.encoders = encoders.copy()
43
+ if default is None:
44
+ self.default = TIOEncoder.not_implemented
45
+ else:
46
+ self.default = default
47
+
48
+ def not_implemented(self, obj : _t.Any) -> None:
49
+ raise NotImplementedError("don't know how to encode %s", type(obj))
50
+
51
+ def _find_encoder(self, obj_type : _t.Any) -> _t.Any:
52
+ for typ, enc in self.encoders.items():
53
+ if issubclass(obj_type, typ):
54
+ return enc
55
+ return self.default
56
+
57
+ def encode(self, obj : _t.Any) -> None:
58
+ typ = type(obj)
59
+ try:
60
+ enc = self.encoders[typ]
61
+ except KeyError:
62
+ enc = self._find_encoder(typ)
63
+ self.encoders[typ] = enc
64
+ enc(self, obj)
65
+
66
+ tio_default_encoders : dict[type[_t.Any], _t.Callable[[TIOWrappedWriter, _t.Any], None]] = {
67
+ bool: TIOEncoder.write_strable,
68
+ int: TIOEncoder.write_strable,
69
+ float: TIOEncoder.write_strable,
70
+ str: TIOEncoder.write_str,
71
+ bytes: TIOEncoder.write_bytes,
72
+ }
73
+
74
+ tio_default_encoders_ln : dict[type[_t.Any], _t.Callable[[TIOWrappedWriter, _t.Any], None]] = {
75
+ bool: TIOEncoder.write_strable_ln,
76
+ int: TIOEncoder.write_strable_ln,
77
+ float: TIOEncoder.write_strable_ln,
78
+ str: TIOEncoder.write_str_ln,
79
+ bytes: TIOEncoder.write_bytes_ln,
80
+ }
@@ -0,0 +1,152 @@
1
+ # Copyright (c) 2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ """cbor2-style encoder for Pythonic Object Representation (repr)
28
+ """
29
+
30
+ import io as _io
31
+ import typing as _t
32
+ import sys as _sys
33
+
34
+ from .base import TIOEncoder
35
+
36
+ class PyReprEncoder(TIOEncoder):
37
+ def __init__(self,
38
+ fobj : _io.BufferedIOBase,
39
+ indent : int = 2,
40
+ starting_indent : int = 0,
41
+ width : int | None = None,
42
+ encoding : str = _sys.getdefaultencoding(),
43
+ encoders : dict[type[_t.Any], _t.Callable[[_t.Any, _t.Any], None]] | None = None,
44
+ default : _t.Callable[[_t.Any, _t.Any], None] | None = None) -> None:
45
+ super().__init__(fobj, b"\n", encoding,
46
+ pyrepr_default_encoders if encoders is None else encoders, default)
47
+ self.indent = indent
48
+ self.current = starting_indent
49
+ self.width = width
50
+ self.linelen = 0
51
+ self.want_space = False
52
+ self.want_ln = False
53
+
54
+ def flush_line(self, force : bool = False) -> None:
55
+ if self.linelen != 0:
56
+ if force or self.want_ln or (self.width is not None and self.linelen > self.width):
57
+ self.write_str_ln("")
58
+ self.linelen = 0
59
+ self.want_ln = False
60
+ self.want_space = False
61
+
62
+ def lnlexeme(self, token : str) -> None:
63
+ token = " " * self.current + token
64
+ self.write_str(token)
65
+ self.linelen = len(token)
66
+
67
+ def lexeme(self, token : str) -> None:
68
+ self.flush_line()
69
+
70
+ if self.linelen == 0:
71
+ self.lnlexeme(token)
72
+ elif self.want_space:
73
+ if self.width is not None and self.linelen + len(token) + 1 > self.width:
74
+ self.flush_line(True)
75
+ self.lnlexeme(token)
76
+ else:
77
+ token = " " + token
78
+ self.write_str(token)
79
+ self.linelen += len(token)
80
+ else:
81
+ self.write_str(token)
82
+ self.linelen += len(token)
83
+ self.want_space = True
84
+
85
+ def comment(self, token : str) -> None:
86
+ self.lexeme("# " + token)
87
+ self.flush_line(True)
88
+
89
+ def start(self, token : str) -> None:
90
+ self.lexeme(token)
91
+ self.current += self.indent
92
+
93
+ def delim(self, token : str) -> None:
94
+ self.want_space = False
95
+ self.lexeme(token)
96
+
97
+ def stop(self, token : str) -> None:
98
+ self.current -= self.indent
99
+ self.lexeme(token)
100
+
101
+ def encode_plain(self, obj : _t.Any) -> None:
102
+ self.lexeme(str(obj))
103
+
104
+ def encode_repr(self, obj : _t.Any) -> None:
105
+ self.lexeme(repr(obj))
106
+
107
+ def encode_list(self, obj : list[_t.Any]) -> None:
108
+ large = len(obj) > 2
109
+ self.start("[")
110
+ self.want_ln = large
111
+ first = True
112
+ for i in range(0, len(obj)):
113
+ if not first:
114
+ self.delim(",")
115
+ self.want_ln = large
116
+ first = False
117
+ self.encode(obj[i])
118
+ self.want_ln = large
119
+ self.stop("]")
120
+
121
+ def encode_dict(self, obj : dict[_t.Any, _t.Any]) -> None:
122
+ large = len(obj) > 1
123
+ self.start("{")
124
+ self.want_ln = large
125
+ first = True
126
+ for k in obj:
127
+ if not first:
128
+ self.delim(",")
129
+ self.want_ln = large
130
+ first = False
131
+
132
+ self.lexeme(repr(k))
133
+ self.delim(":")
134
+ self.encode(obj[k])
135
+ self.want_ln = large
136
+ self.stop("}")
137
+
138
+ pyrepr_default_encoders : dict[type[_t.Any], _t.Callable[[PyReprEncoder, _t.Any], None]] = {
139
+ bool: PyReprEncoder.encode_plain,
140
+ int: PyReprEncoder.encode_plain,
141
+ float: PyReprEncoder.encode_plain,
142
+ str: PyReprEncoder.encode_repr,
143
+ bytes: PyReprEncoder.encode_repr,
144
+ type(None): PyReprEncoder.encode_repr,
145
+ list: PyReprEncoder.encode_list,
146
+ dict: PyReprEncoder.encode_dict,
147
+ }
148
+
149
+ def pyrepr_dumps(obj : _t.Any, *args : _t.Any, **kwargs : _t.Any) -> bytes:
150
+ encoder = PyReprEncoder(_io.BytesIO(), *args, **kwargs)
151
+ encoder.encode(obj)
152
+ return encoder.fobj.getvalue() # type: ignore
@@ -0,0 +1,123 @@
1
+ # Copyright (c) 2018-2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ import logging as _logging
28
+ import os as _os
29
+ import sys as _sys
30
+ import typing as _t
31
+
32
+ from .base import *
33
+
34
+ class MinimalIOWrapper(MinimalIO):
35
+ def __init__(self, fobj : _t.Any) -> None:
36
+ self.fobj = fobj
37
+ # _socket.socket's fileno() will return -1 after
38
+ # .close() and poll needs an actual value to unsubscribe
39
+ # properly so we have to keep a copy here
40
+ try:
41
+ self._fileno = fobj.fileno()
42
+ except OSError:
43
+ self._fileno = None
44
+ _logging.getLogger("kisstd").debug("init %s", self)
45
+
46
+ def __del__(self) -> None:
47
+ _logging.getLogger("kisstd").debug("del %s", self)
48
+
49
+ def __repr__(self) -> str:
50
+ if self._fileno is not None:
51
+ desc = "fd=" + str(self._fileno)
52
+ else:
53
+ desc = "obj=" + str(id(self.fobj))
54
+ return "<%s %s %s closed=%s>" % (self.__class__.__name__, hex(id(self)), desc, self.closed)
55
+
56
+ def close(self) -> None:
57
+ self.fobj.close()
58
+
59
+ @property
60
+ def closed(self) -> bool:
61
+ return self.fobj.closed # type: ignore
62
+
63
+ def shutdown(self, what : ShutdownState) -> None:
64
+ raise NotImplementedError("MinimalIOWrapper can't be shutdown")
65
+
66
+ @property
67
+ def shutdown_state(self) -> ShutdownState:
68
+ if self.closed:
69
+ return SHUT_BOTH
70
+ else:
71
+ return SHUT_NONE
72
+
73
+ def __enter__(self) -> _t.Any:
74
+ return self
75
+
76
+ def __exit__(self, exc_type : _t.Any, exc_value : _t.Any, exc_tb : _t.Any) -> None:
77
+ self.close()
78
+
79
+ class TIOWrapper(MinimalIOWrapper):
80
+ def __init__(self, fobj : _t.Any, eol : bytes = b"\n", encoding : str = _sys.getdefaultencoding()) -> None:
81
+ super().__init__(fobj)
82
+ self.encoding = encoding
83
+ self.eol = eol
84
+
85
+ class TIOWrappedReader(TIOWrapper, MinimalIOReader):
86
+ def read_some_bytes(self, size : int) -> bytes:
87
+ return self.fobj.read(size) # type: ignore
88
+
89
+ class TIOWrappedWriter(TIOWrapper, MinimalIOWriter):
90
+ def write_some_bytes(self, data : ByteString) -> int:
91
+ return self.fobj.write(data) # type: ignore
92
+
93
+ def flush(self) -> None:
94
+ self.fobj.flush()
95
+
96
+ def write_bytes_ln(self, data : ByteString) -> None:
97
+ self.write_bytes(data)
98
+ self.write_bytes(self.eol)
99
+
100
+ def write_str(self, data : str) -> None:
101
+ assert self.encoding is not None
102
+ self.write_bytes(data.encode(self.encoding))
103
+
104
+ def write_str_ln(self, data : str) -> None:
105
+ self.write_str(data)
106
+ self.write_bytes(self.eol)
107
+
108
+ def write_strable(self, data : _t.Any) -> None:
109
+ self.write_str(str(data))
110
+
111
+ def write_strable_ln(self, data : _t.Any) -> None:
112
+ self.write_strable(data)
113
+ self.write_bytes(self.eol)
114
+
115
+ def write(self, data : str | ByteString) -> None:
116
+ if isinstance(data, str):
117
+ self.write_str(data)
118
+ else:
119
+ self.write_bytes(data)
120
+
121
+ stdin = TIOWrappedReader(_os.fdopen(_sys.stdin.fileno(), "rb"))
122
+ stdout = TIOWrappedWriter(_os.fdopen(_sys.stdout.fileno(), "wb"))
123
+ stderr = TIOWrappedWriter(_os.fdopen(_sys.stderr.fileno(), "wb"))
@@ -0,0 +1,51 @@
1
+ # Copyright (c) 2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ import logging as _logging
28
+
29
+ class CounterHandler(_logging.NullHandler):
30
+ errors : int
31
+ warnings : int
32
+ infos : int
33
+ debugs : int
34
+
35
+ def __init__(self, level : int = _logging.DEBUG) -> None:
36
+ super().__init__(level)
37
+ self.errors = 0
38
+ self.warnings = 0
39
+ self.infos = 0
40
+ self.debugs = 0
41
+
42
+ def handle(self, record : _logging.LogRecord) -> bool:
43
+ if record.levelno >= _logging.ERROR:
44
+ self.errors += 1
45
+ elif record.levelno >= _logging.WARNING:
46
+ self.warnings += 1
47
+ elif record.levelno >= _logging.INFO:
48
+ self.infos += 1
49
+ elif record.levelno >= _logging.DEBUG:
50
+ self.debugs += 1
51
+ return True
@@ -0,0 +1,100 @@
1
+ # Copyright (c) 2018-2023 Jan Malakhovski <oxij@oxij.org>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in all
11
+ # copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ # SOFTWARE.
20
+ #
21
+ # This file is a part of kisstdlib project.
22
+ #
23
+ # This file can be distributed under the terms of the above MIT license or
24
+ # Python Software Foundation License version 2 (PSF-2.0) as published by Python
25
+ # Software Foundation.
26
+
27
+ import logging as _logging
28
+ import os as _os
29
+ import stat as _stat
30
+ import typing as _t
31
+
32
+ def walk_orderly(path : _t.AnyStr,
33
+ include_directories : bool = True,
34
+ follow_symlinks : bool = True,
35
+ handle_error : _t.Callable[..., None] | None = _logging.error) -> _t.Iterable[_t.AnyStr]:
36
+ """Similar to os.walk, but produces an iterator over plain file paths, allows
37
+ non-directories as input (which will just output a single element), and
38
+ the output is guaranteed to be ordered.
39
+ """
40
+
41
+ try:
42
+ fstat = _os.stat(path, follow_symlinks = follow_symlinks)
43
+ except OSError:
44
+ if handle_error is not None:
45
+ handle_error("failed to stat: %s", path)
46
+ return
47
+ raise
48
+
49
+ if not _stat.S_ISDIR(fstat.st_mode):
50
+ yield path
51
+ return
52
+
53
+ try:
54
+ scandir_it = _os.scandir(path)
55
+ except OSError:
56
+ if handle_error is not None:
57
+ handle_error("failed to scandir: %s", path)
58
+ return
59
+ raise
60
+
61
+ elements : list[_t.AnyStr] = []
62
+
63
+ with scandir_it:
64
+ while True:
65
+ try:
66
+ entry : _t.Any = next(scandir_it)
67
+ except StopIteration:
68
+ break
69
+ except OSError:
70
+ if handle_error is not None:
71
+ handle_error("failed in scandir: %s", path)
72
+ return
73
+ raise
74
+ else:
75
+ try:
76
+ is_dir = entry.is_dir(follow_symlinks = follow_symlinks)
77
+ except OSError:
78
+ if handle_error is not None:
79
+ handle_error("failed to stat: %s", entry.path)
80
+ return
81
+ raise
82
+
83
+ if is_dir:
84
+ if isinstance(entry.path, bytes):
85
+ elements.append(entry.path + b"/") # type: ignore
86
+ else:
87
+ elements.append(entry.path + "/")
88
+ else:
89
+ elements.append(entry.path)
90
+
91
+ elements.sort()
92
+
93
+ for path in elements:
94
+ lchar : _t.AnyStr = path[-1:]
95
+ if lchar == "/" or lchar == b"/":
96
+ if include_directories:
97
+ yield path
98
+ yield from walk_orderly(path, include_directories, follow_symlinks, handle_error)
99
+ else:
100
+ yield path
File without changes
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 2.1
2
+ Name: kisstdlib
3
+ Version: 0.0.1
4
+ Summary: Keep It Simple STandarD LIBraries set for Python
5
+ Author-email: Jan Malakhovski <oxij@oxij.org>
6
+ Keywords: sys,stdlib
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: License :: OSI Approved :: Python Software Foundation License
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+
14
+ # What?
15
+
16
+ Keep It Simple STandarD LIBraries set for Python.
17
+
18
+ A very alpha Work In Progress kind of thing ATM.
@@ -0,0 +1,20 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ kisstdlib/__init__.py
5
+ kisstdlib/exceptions.py
6
+ kisstdlib/logging.py
7
+ kisstdlib/path.py
8
+ kisstdlib/py.typed
9
+ kisstdlib.egg-info/PKG-INFO
10
+ kisstdlib.egg-info/SOURCES.txt
11
+ kisstdlib.egg-info/dependency_links.txt
12
+ kisstdlib.egg-info/top_level.txt
13
+ kisstdlib/argparse/__init__.py
14
+ kisstdlib/argparse/better.py
15
+ kisstdlib/io/__init__.py
16
+ kisstdlib/io/base.py
17
+ kisstdlib/io/wrapper.py
18
+ kisstdlib/io/encoder/__init__.py
19
+ kisstdlib/io/encoder/base.py
20
+ kisstdlib/io/encoder/pyrepr.py
@@ -0,0 +1 @@
1
+ kisstdlib
@@ -0,0 +1,26 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
4
+ [project]
5
+ name = "kisstdlib"
6
+ version = "0.0.1"
7
+ authors = [{ name = "Jan Malakhovski", email = "oxij@oxij.org" }]
8
+ description = "Keep It Simple STandarD LIBraries set for Python"
9
+ readme = "README.md"
10
+ classifiers = [
11
+ "Development Status :: 4 - Beta",
12
+ "Programming Language :: Python :: 3",
13
+ "License :: OSI Approved :: MIT License",
14
+ "License :: OSI Approved :: Python Software Foundation License",
15
+ ]
16
+ keywords = [
17
+ "sys",
18
+ "stdlib",
19
+ ]
20
+ requires-python = ">=3.10"
21
+ [tool.setuptools.packages.find]
22
+ where = ["."]
23
+ include = ["kisstdlib*"]
24
+ namespaces = true
25
+ [tool.setuptools.package-data]
26
+ "kisstdlib" = ["py.typed"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env python3
2
+ from setuptools import setup
3
+ setup()