libdev 0.95__tar.gz → 0.97__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.
- libdev-0.97/PKG-INFO +94 -0
- {libdev-0.95 → libdev-0.97}/README.md +7 -0
- libdev-0.97/env/bin/jp.py +54 -0
- {libdev-0.95 → libdev-0.97}/libdev/__init__.py +1 -1
- {libdev-0.95 → libdev-0.97}/libdev/cfg.py +23 -4
- {libdev-0.95 → libdev-0.97}/libdev/check.py +1 -0
- libdev-0.97/libdev/dev.py +29 -0
- libdev-0.97/libdev/doc.py +29 -0
- {libdev-0.95 → libdev-0.97}/libdev/num.py +31 -10
- {libdev-0.95 → libdev-0.97}/libdev/req.py +14 -19
- {libdev-0.95 → libdev-0.97}/libdev/time.py +51 -12
- libdev-0.97/libdev.egg-info/PKG-INFO +94 -0
- {libdev-0.95 → libdev-0.97}/libdev.egg-info/SOURCES.txt +2 -0
- libdev-0.97/libdev.egg-info/requires.txt +13 -0
- libdev-0.97/libdev.egg-info/top_level.txt +4 -0
- libdev-0.97/pyproject.toml +75 -0
- {libdev-0.95 → libdev-0.97}/setup.py +21 -17
- {libdev-0.95 → libdev-0.97}/tests/test_num.py +1 -0
- {libdev-0.95 → libdev-0.97}/tests/test_time.py +7 -0
- libdev-0.95/PKG-INFO +0 -50
- libdev-0.95/libdev/dev.py +0 -21
- libdev-0.95/libdev/doc.py +0 -17
- libdev-0.95/libdev.egg-info/PKG-INFO +0 -50
- libdev-0.95/libdev.egg-info/requires.txt +0 -5
- libdev-0.95/libdev.egg-info/top_level.txt +0 -1
- {libdev-0.95 → libdev-0.97}/LICENSE +0 -0
- {libdev-0.95 → libdev-0.97}/libdev/codes.py +0 -0
- {libdev-0.95 → libdev-0.97}/libdev/crypt.py +0 -0
- {libdev-0.95 → libdev-0.97}/libdev/fin.py +0 -0
- {libdev-0.95 → libdev-0.97}/libdev/gen.py +0 -0
- {libdev-0.95 → libdev-0.97}/libdev/img.py +0 -0
- {libdev-0.95 → libdev-0.97}/libdev/lang.py +0 -0
- {libdev-0.95 → libdev-0.97}/libdev/log.py +0 -0
- {libdev-0.95 → libdev-0.97}/libdev/s3.py +0 -0
- {libdev-0.95 → libdev-0.97}/libdev.egg-info/dependency_links.txt +0 -0
- {libdev-0.95 → libdev-0.97}/setup.cfg +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_cfg.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_check.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_codes.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_crypt.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_dev.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_doc.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_gen.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_img.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_lang.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_log.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_req.py +0 -0
- {libdev-0.95 → libdev-0.97}/tests/test_s3.py +0 -0
libdev-0.97/PKG-INFO
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: libdev
|
|
3
|
+
Version: 0.97
|
|
4
|
+
Summary: Set of standard functions for development
|
|
5
|
+
Home-page: https://github.com/chilleco/lib
|
|
6
|
+
Author: Alex Poloz
|
|
7
|
+
Author-email: Alex Poloz <alexypoloz@gmail.com>
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2021 Alexey Poloz
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
|
|
30
|
+
Project-URL: Source, https://github.com/chilleco/lib
|
|
31
|
+
Keywords: standard,lib,dev,development,cfg,config,generate,codes,tokens,ids,passwords,generator,ciphers,time,formatter,nlp,natural language,aws,s3,upload file,file server
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Environment :: Console
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
36
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
43
|
+
Classifier: Operating System :: OS Independent
|
|
44
|
+
Requires-Python: >=3.10, <4
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
License-File: LICENSE
|
|
47
|
+
Requires-Dist: aiohttp>=3.13.2
|
|
48
|
+
Requires-Dist: python-dotenv>=1.2.1
|
|
49
|
+
Requires-Dist: boto3>=1.42.0
|
|
50
|
+
Requires-Dist: Pillow>=12.0.0
|
|
51
|
+
Requires-Dist: loguru>=0.7.3
|
|
52
|
+
Provides-Extra: dev
|
|
53
|
+
Requires-Dist: build>=1.3.0; extra == "dev"
|
|
54
|
+
Requires-Dist: setuptools>=80.9.0; extra == "dev"
|
|
55
|
+
Requires-Dist: twine>=6.2.0; extra == "dev"
|
|
56
|
+
Requires-Dist: pylint>=4.0.4; extra == "dev"
|
|
57
|
+
Requires-Dist: pytest>=9.0.1; extra == "dev"
|
|
58
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == "dev"
|
|
59
|
+
Dynamic: author
|
|
60
|
+
Dynamic: home-page
|
|
61
|
+
Dynamic: license-file
|
|
62
|
+
Dynamic: requires-python
|
|
63
|
+
|
|
64
|
+
# LibDev
|
|
65
|
+
Development library — Set of standard functions for development
|
|
66
|
+
|
|
67
|
+
[GitHub](https://github.com/chilleco/lib)
|
|
68
|
+
| [PyPI](https://pypi.org/project/libdev/)
|
|
69
|
+
|
|
70
|
+
## Requirements
|
|
71
|
+
- Python 3.10+ (dependencies are 3.14-ready)
|
|
72
|
+
|
|
73
|
+
## Installation
|
|
74
|
+
- Runtime: `pip install .`
|
|
75
|
+
- Dev / tests: `pip install .[dev]` or `make setup-dev`
|
|
76
|
+
|
|
77
|
+
## Submodules
|
|
78
|
+
Stream | Submodule | Description
|
|
79
|
+
---|---|---
|
|
80
|
+
System | ` libdev.cfg ` | Configuration getting
|
|
81
|
+
| ` libdev.req ` | AsyncIO requests (AIOHTTP wrapper)
|
|
82
|
+
| ` libdev.log ` | Logger (Loguru wrapper)
|
|
83
|
+
Data Format | ` libdev.num ` | Numeric conversions & handlers
|
|
84
|
+
| ` libdev.time ` | Time processing
|
|
85
|
+
Transforms | ` libdev.gen ` | Code & token generators
|
|
86
|
+
| ` libdev.codes ` | Ciphers: langs & flags / networks / user statuses
|
|
87
|
+
| ` libdev.check ` | Validation functions
|
|
88
|
+
| ` libdev.crypt ` | Encryption and decryption functions
|
|
89
|
+
Fields | ` libdev.dev ` | Development tools
|
|
90
|
+
| ` libdev.fin ` | Financial codes and tools
|
|
91
|
+
| ` libdev.lang ` | Natural language formatters
|
|
92
|
+
Files | ` libdev.doc ` | Base64 / JSON handlers
|
|
93
|
+
| ` libdev.s3 ` | S3 file server functions
|
|
94
|
+
| ` libdev.img ` | Image processing
|
|
@@ -4,6 +4,13 @@ Development library — Set of standard functions for development
|
|
|
4
4
|
[GitHub](https://github.com/chilleco/lib)
|
|
5
5
|
| [PyPI](https://pypi.org/project/libdev/)
|
|
6
6
|
|
|
7
|
+
## Requirements
|
|
8
|
+
- Python 3.10+ (dependencies are 3.14-ready)
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
- Runtime: `pip install .`
|
|
12
|
+
- Dev / tests: `pip install .[dev]` or `make setup-dev`
|
|
13
|
+
|
|
7
14
|
## Submodules
|
|
8
15
|
Stream | Submodule | Description
|
|
9
16
|
---|---|---
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/Users/kosyachniy/Desktop/chill/lib/env/bin/python
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import json
|
|
5
|
+
import argparse
|
|
6
|
+
from pprint import pformat
|
|
7
|
+
|
|
8
|
+
import jmespath
|
|
9
|
+
from jmespath import exceptions
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main():
|
|
13
|
+
parser = argparse.ArgumentParser()
|
|
14
|
+
parser.add_argument('expression')
|
|
15
|
+
parser.add_argument('-f', '--filename',
|
|
16
|
+
help=('The filename containing the input data. '
|
|
17
|
+
'If a filename is not given then data is '
|
|
18
|
+
'read from stdin.'))
|
|
19
|
+
parser.add_argument('--ast', action='store_true',
|
|
20
|
+
help=('Pretty print the AST, do not search the data.'))
|
|
21
|
+
args = parser.parse_args()
|
|
22
|
+
expression = args.expression
|
|
23
|
+
if args.ast:
|
|
24
|
+
# Only print the AST
|
|
25
|
+
expression = jmespath.compile(args.expression)
|
|
26
|
+
sys.stdout.write(pformat(expression.parsed))
|
|
27
|
+
sys.stdout.write('\n')
|
|
28
|
+
return 0
|
|
29
|
+
if args.filename:
|
|
30
|
+
with open(args.filename, 'r') as f:
|
|
31
|
+
data = json.load(f)
|
|
32
|
+
else:
|
|
33
|
+
data = sys.stdin.read()
|
|
34
|
+
data = json.loads(data)
|
|
35
|
+
try:
|
|
36
|
+
sys.stdout.write(json.dumps(
|
|
37
|
+
jmespath.search(expression, data), indent=4, ensure_ascii=False))
|
|
38
|
+
sys.stdout.write('\n')
|
|
39
|
+
except exceptions.ArityError as e:
|
|
40
|
+
sys.stderr.write("invalid-arity: %s\n" % e)
|
|
41
|
+
return 1
|
|
42
|
+
except exceptions.JMESPathTypeError as e:
|
|
43
|
+
sys.stderr.write("invalid-type: %s\n" % e)
|
|
44
|
+
return 1
|
|
45
|
+
except exceptions.UnknownFunctionError as e:
|
|
46
|
+
sys.stderr.write("unknown-function: %s\n" % e)
|
|
47
|
+
return 1
|
|
48
|
+
except exceptions.ParseError as e:
|
|
49
|
+
sys.stderr.write("syntax-error: %s\n" % e)
|
|
50
|
+
return 1
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == '__main__':
|
|
54
|
+
sys.exit(main())
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""Centralized configuration loader for LibDev consumers.
|
|
2
|
+
|
|
3
|
+
This module mirrors the behavior documented in `LIBDEV_DOCUMENTATION.md`:
|
|
4
|
+
it first ingests a project level ``sets.json`` file, then overlays values
|
|
5
|
+
from ``.env`` (via ``python-dotenv``) by translating dotted keys to
|
|
6
|
+
``UPPER_SNAKE_CASE`` environment variables. Use the helpers below instead of
|
|
7
|
+
calling ``os.getenv`` throughout the codebase so the hierarchy stays uniform.
|
|
3
8
|
"""
|
|
4
9
|
|
|
5
10
|
import os
|
|
@@ -19,7 +24,15 @@ if os.path.isfile(".env"):
|
|
|
19
24
|
|
|
20
25
|
|
|
21
26
|
def cfg(name, default=None):
|
|
22
|
-
"""
|
|
27
|
+
"""Return a config value stored in ``sets.json``/``.env``.
|
|
28
|
+
|
|
29
|
+
The lookup walks dotted paths inside the parsed JSON structure and, when a
|
|
30
|
+
key is missing, falls back to an environment variable where dots are
|
|
31
|
+
replaced with underscores and the string is upper-cased (``api.base`` →
|
|
32
|
+
``API_BASE``). Environment values are JSON-decoded automatically so booleans
|
|
33
|
+
and numeric strings turn into native Python types. ``default`` is returned
|
|
34
|
+
when a key is absent in both sources.
|
|
35
|
+
"""
|
|
23
36
|
|
|
24
37
|
keys = name.split(".")
|
|
25
38
|
data = sets
|
|
@@ -44,7 +57,13 @@ def cfg(name, default=None):
|
|
|
44
57
|
|
|
45
58
|
|
|
46
59
|
def set_cfg(name, value):
|
|
47
|
-
"""
|
|
60
|
+
"""Mutate the in-memory ``sets`` dictionary for tests or overrides.
|
|
61
|
+
|
|
62
|
+
Writes scoped dotted keys back into the ``sets`` mapping without touching
|
|
63
|
+
disk. This mirrors the behavior in consumer repos that temporarily adjust
|
|
64
|
+
configuration for integration tests or AI agents. Changes live only for the
|
|
65
|
+
current process and should be reset between tests.
|
|
66
|
+
"""
|
|
48
67
|
|
|
49
68
|
array_name = name.split(".")
|
|
50
69
|
dictionary = {}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Development-environment helpers tied to LibDev guidelines.
|
|
2
|
+
|
|
3
|
+
Currently exposes public IP validation logic that mirrors the rules documented
|
|
4
|
+
in ``LIBDEV_DOCUMENTATION.md`` for analytics and logging pipelines. Extend this
|
|
5
|
+
module instead of sprinkling regex checks throughout consumer projects.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import re
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def check_public_ip(ip):
|
|
12
|
+
"""Return ``ip`` if it is routable on the public internet.
|
|
13
|
+
|
|
14
|
+
Private (RFC1918), loopback, and carrier-grade NAT subnets are filtered
|
|
15
|
+
out, ensuring only analyzable public addresses pass downstream. ``None`` is
|
|
16
|
+
returned for empty inputs or addresses that match reserved ranges.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
if not ip:
|
|
20
|
+
return None
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
None
|
|
24
|
+
if re.match(
|
|
25
|
+
r"^(172\.(1[6-9]\.|2[0-9]\.|3[0-1]\.)|192\.168\.|10\.|127\.)",
|
|
26
|
+
ip,
|
|
27
|
+
)
|
|
28
|
+
else ip
|
|
29
|
+
)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Utility helpers for dealing with document/JSON serialization.
|
|
2
|
+
|
|
3
|
+
These functions are referenced by the integration guide to make sure assets
|
|
4
|
+
and structured logs look the same across repositories (e.g., ``log.json`` uses
|
|
5
|
+
``to_json`` under the hood).
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import base64
|
|
9
|
+
import json
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def to_base64(image, mime="image/jpg"):
|
|
13
|
+
"""Return a ``data:`` URL for the given file-like ``image``.
|
|
14
|
+
|
|
15
|
+
Reads the stream, base64-encodes the bytes, and prefixes it with the MIME
|
|
16
|
+
Type so downstream clients (frontends, bots) can embed the payload directly
|
|
17
|
+
without touching disk.
|
|
18
|
+
"""
|
|
19
|
+
data = base64.b64encode(image.read())
|
|
20
|
+
return f"data:{mime};base64,{data.decode('utf-8')}"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def to_json(data):
|
|
24
|
+
"""Serialize ``data`` to a UTF-8 friendly JSON string.
|
|
25
|
+
|
|
26
|
+
Uses tab indentation and ``ensure_ascii=False`` to preserve Cyrillic or
|
|
27
|
+
emoji content mentioned in ``LIBDEV_DOCUMENTATION.md``.
|
|
28
|
+
"""
|
|
29
|
+
return json.dumps(data, indent="\t", ensure_ascii=False)
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""Numeric normalization and presentation helpers used across LibDev.
|
|
2
|
+
|
|
3
|
+
Implements the opinionated formatting rules discussed in the integration
|
|
4
|
+
guide: deterministic rounding, removal of floating-point artifacts, thousands
|
|
5
|
+
separators, and zero-compression for compact analytical displays.
|
|
3
6
|
"""
|
|
4
7
|
|
|
5
8
|
import re
|
|
@@ -22,7 +25,7 @@ def is_float(value: str) -> bool:
|
|
|
22
25
|
|
|
23
26
|
|
|
24
27
|
def to_num(value) -> bool:
|
|
25
|
-
"""Convert
|
|
28
|
+
"""Convert an incoming scalar to ``int``/``float`` while preserving intent."""
|
|
26
29
|
|
|
27
30
|
if value is None:
|
|
28
31
|
return None
|
|
@@ -80,7 +83,11 @@ def get_whole(value):
|
|
|
80
83
|
|
|
81
84
|
|
|
82
85
|
def simplify_value(value, decimals=4):
|
|
83
|
-
"""
|
|
86
|
+
"""Return the significant digits of ``value`` capped by ``decimals``.
|
|
87
|
+
|
|
88
|
+
Used by analytics pipelines to produce short strings that still encode the
|
|
89
|
+
important portion of very large or tiny numbers.
|
|
90
|
+
"""
|
|
84
91
|
|
|
85
92
|
if value is None:
|
|
86
93
|
return None
|
|
@@ -126,7 +133,13 @@ def pretty(
|
|
|
126
133
|
zeros=4,
|
|
127
134
|
compress=None,
|
|
128
135
|
):
|
|
129
|
-
"""
|
|
136
|
+
"""Format ``value`` according to LibDev UI/metrics rules.
|
|
137
|
+
|
|
138
|
+
Supports optional rounding to a target precision, manual sign prefixing,
|
|
139
|
+
swapping the thousands separator symbol, and compressing leading/trailing
|
|
140
|
+
zeros (see ``compress_zeros``). This helper is the canonical way to build
|
|
141
|
+
user-facing number strings.
|
|
142
|
+
"""
|
|
130
143
|
|
|
131
144
|
if value is None:
|
|
132
145
|
return None
|
|
@@ -282,6 +295,8 @@ def to_step(value, step=1, side=False):
|
|
|
282
295
|
|
|
283
296
|
|
|
284
297
|
def to_plain(value) -> str:
|
|
298
|
+
"""Convert ``value`` to a normalized decimal string without notation."""
|
|
299
|
+
|
|
285
300
|
if value is None:
|
|
286
301
|
return None
|
|
287
302
|
try:
|
|
@@ -311,11 +326,17 @@ def _round_to_decimals(x, decimals):
|
|
|
311
326
|
|
|
312
327
|
|
|
313
328
|
def compress_zeros(x, zeros=2, round=None) -> str:
|
|
314
|
-
"""
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
329
|
+
"""Compress zero runs using the subscript notation referenced in the docs.
|
|
330
|
+
|
|
331
|
+
Examples::
|
|
332
|
+
|
|
333
|
+
0.000012 -> "0.0₄12"
|
|
334
|
+
1.000045 -> "1.0₄45"
|
|
335
|
+
|
|
336
|
+
``round`` controls how many digits remain after the compressed block, while
|
|
337
|
+
``zeros`` sets the minimum run length required before a compression occurs.
|
|
338
|
+
Returns a string that can be passed to ``pretty`` or directly displayed in
|
|
339
|
+
dashboards.
|
|
319
340
|
"""
|
|
320
341
|
|
|
321
342
|
if x is None:
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""Async HTTP gateway used across LibDev powered projects.
|
|
2
|
+
|
|
3
|
+
Centralizes ``aiohttp`` usage so upstream services benefit from the same request
|
|
4
|
+
construction (JSON vs form payloads, multipart file uploads) and response
|
|
5
|
+
parsing rules described in ``LIBDEV_DOCUMENTATION.md``. Always ``await`` the
|
|
6
|
+
helpers in this module to stay inside the async boundary.
|
|
3
7
|
"""
|
|
4
8
|
|
|
5
9
|
import aiohttp
|
|
@@ -14,24 +18,15 @@ async def fetch(
|
|
|
14
18
|
headers=None,
|
|
15
19
|
timeout=None,
|
|
16
20
|
):
|
|
17
|
-
"""
|
|
18
|
-
Fetch data from a URL using aiohttp.
|
|
19
|
-
|
|
20
|
-
Args:
|
|
21
|
-
url (str): The URL to fetch data from.
|
|
22
|
-
payload (dict, optional): The payload to send with the request.
|
|
23
|
-
Defaults to None.
|
|
24
|
-
type_req (str, optional): The type of request (e.g., 'post', 'put',
|
|
25
|
-
'delete', etc.). Defaults to 'post'.
|
|
26
|
-
type_data (str, optional): The type of data (e.g., 'json', 'data').
|
|
27
|
-
Defaults to 'json'.
|
|
28
|
-
headers (dict, optional): The headers to include with the request.
|
|
29
|
-
Defaults to None.
|
|
30
|
-
timeout (float, optional): The timeout for the request in seconds.
|
|
31
|
-
Defaults to None.
|
|
21
|
+
"""Perform an HTTP request and normalize the response payload.
|
|
32
22
|
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
Parameters mirror the rules from the integration guide: ``files`` may be a
|
|
24
|
+
mapping of field name to bytes/file-like objects (forcing multipart form
|
|
25
|
+
uploads), ``type_data`` controls whether the ``payload`` is supplied via the
|
|
26
|
+
``json`` or ``data`` keyword, and ``type_req`` is the lowercase HTTP verb. A
|
|
27
|
+
status code integer and the decoded response body (JSON dict, plain text, or
|
|
28
|
+
raw bytes) are returned. Callers are expected to provide their own retries
|
|
29
|
+
or circuit breaking logic.
|
|
35
30
|
"""
|
|
36
31
|
if payload is None:
|
|
37
32
|
payload = {}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
"""
|
|
2
|
-
|
|
1
|
+
"""Datetime parsing/formatting helpers aligned with LibDev localization rules.
|
|
2
|
+
|
|
3
|
+
The functions below implement the Russian month parsing, timezone handling, and
|
|
4
|
+
delta formatting conventions cited in ``LIBDEV_DOCUMENTATION.md`` so every
|
|
5
|
+
project surfaces dates the same way.
|
|
3
6
|
"""
|
|
4
7
|
|
|
5
8
|
# TODO: Учитывать летнее / зимнее время в прошлых датах, которого теперь нет
|
|
@@ -51,13 +54,15 @@ def to_tz(hours):
|
|
|
51
54
|
return datetime.timezone(datetime.timedelta(hours=hours))
|
|
52
55
|
|
|
53
56
|
|
|
54
|
-
def get_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=
|
|
57
|
+
def get_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=None):
|
|
55
58
|
"""Get time from timestamp"""
|
|
56
59
|
|
|
57
60
|
if data is None:
|
|
58
61
|
data = time.time()
|
|
59
62
|
if isinstance(data, str):
|
|
60
63
|
return data
|
|
64
|
+
if tz is None:
|
|
65
|
+
tz = 0
|
|
61
66
|
|
|
62
67
|
# TODO: smart TZ
|
|
63
68
|
|
|
@@ -67,18 +72,20 @@ def get_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=0):
|
|
|
67
72
|
return time.strftime(template, time.gmtime(data + tz * 3600))
|
|
68
73
|
|
|
69
74
|
|
|
70
|
-
def get_date(data=None, template="%d.%m.%Y", tz=
|
|
75
|
+
def get_date(data=None, template="%d.%m.%Y", tz=None):
|
|
71
76
|
"""Get date from timestamp"""
|
|
72
77
|
return get_time(data, template, tz)
|
|
73
78
|
|
|
74
79
|
|
|
75
|
-
def decode_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=
|
|
80
|
+
def decode_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=None):
|
|
76
81
|
"""Get timestamp from time"""
|
|
77
82
|
|
|
78
83
|
if not data:
|
|
79
84
|
return None
|
|
80
85
|
if isinstance(data, int):
|
|
81
86
|
return data
|
|
87
|
+
if tz is None:
|
|
88
|
+
tz = 0
|
|
82
89
|
|
|
83
90
|
try:
|
|
84
91
|
data = datetime.datetime.strptime(data, template)
|
|
@@ -90,17 +97,20 @@ def decode_time(data=None, template="%d.%m.%Y %H:%M:%S", tz=0):
|
|
|
90
97
|
return int(data.timestamp())
|
|
91
98
|
|
|
92
99
|
|
|
93
|
-
def decode_date(data=None, template="%d.%m.%Y", tz=
|
|
100
|
+
def decode_date(data=None, template="%d.%m.%Y", tz=None):
|
|
94
101
|
"""Get timestamp from date"""
|
|
95
102
|
return decode_time(data, template, tz)
|
|
96
103
|
|
|
97
104
|
|
|
98
105
|
# pylint: disable=too-many-branches,too-many-statements
|
|
99
|
-
def parse_time(data: str, tz=
|
|
106
|
+
def parse_time(data: str, tz=None):
|
|
100
107
|
"""Parse time"""
|
|
101
108
|
|
|
102
109
|
# TODO: 16 year -> 2016 year
|
|
103
110
|
|
|
111
|
+
if tz is None:
|
|
112
|
+
tz = 0
|
|
113
|
+
|
|
104
114
|
data = data.lower()
|
|
105
115
|
|
|
106
116
|
# Cut special characters
|
|
@@ -264,7 +274,7 @@ def format_delta(sec, short=False, locale="en"):
|
|
|
264
274
|
return delta
|
|
265
275
|
|
|
266
276
|
|
|
267
|
-
def get_midnight(timestamp=None, tz=
|
|
277
|
+
def get_midnight(timestamp=None, tz=None):
|
|
268
278
|
"""
|
|
269
279
|
Get the start of the day (midnight) for a given timestamp in a specified timezone.
|
|
270
280
|
|
|
@@ -275,14 +285,19 @@ def get_midnight(timestamp=None, tz=0):
|
|
|
275
285
|
Returns:
|
|
276
286
|
float: The timestamp for the start of the day (midnight) in the specified timezone.
|
|
277
287
|
"""
|
|
288
|
+
|
|
278
289
|
if timestamp is None:
|
|
279
290
|
timestamp = time.time()
|
|
291
|
+
if tz is None:
|
|
292
|
+
tz = 0
|
|
293
|
+
|
|
280
294
|
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
|
|
281
295
|
start_day = dt_local.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
296
|
+
|
|
282
297
|
return int(start_day.timestamp())
|
|
283
298
|
|
|
284
299
|
|
|
285
|
-
def get_month_start(timestamp=None, tz=
|
|
300
|
+
def get_month_start(timestamp=None, tz=None):
|
|
286
301
|
"""
|
|
287
302
|
Get the start of the month (midnight on the first day of the month) for a given timestamp in a specified timezone.
|
|
288
303
|
|
|
@@ -293,14 +308,25 @@ def get_month_start(timestamp=None, tz=0):
|
|
|
293
308
|
Returns:
|
|
294
309
|
float: The timestamp for the start of the month in the specified timezone.
|
|
295
310
|
"""
|
|
311
|
+
|
|
296
312
|
if timestamp is None:
|
|
297
313
|
timestamp = time.time()
|
|
314
|
+
if tz is None:
|
|
315
|
+
tz = 0
|
|
316
|
+
|
|
298
317
|
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
|
|
299
318
|
start_month = dt_local.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
|
|
319
|
+
|
|
300
320
|
return int(start_month.timestamp())
|
|
301
321
|
|
|
302
322
|
|
|
303
|
-
def
|
|
323
|
+
def get_previous_month(timestamp=None, tz=None):
|
|
324
|
+
current_period = get_month_start(timestamp, tz)
|
|
325
|
+
one_month_ago = get_month_start(current_period - 1, tz)
|
|
326
|
+
return one_month_ago
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def get_week_start(timestamp=None, tz=None):
|
|
304
330
|
"""
|
|
305
331
|
Get the start of the week (midnight on Monday) for a given timestamp in a specified timezone.
|
|
306
332
|
|
|
@@ -311,17 +337,23 @@ def get_week_start(timestamp=None, tz=0):
|
|
|
311
337
|
Returns:
|
|
312
338
|
float: The timestamp for the start of the week (Monday at midnight) in the specified timezone.
|
|
313
339
|
"""
|
|
340
|
+
|
|
314
341
|
if timestamp is None:
|
|
315
342
|
timestamp = time.time()
|
|
343
|
+
if tz is None:
|
|
344
|
+
tz = 0
|
|
345
|
+
|
|
316
346
|
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
|
|
317
347
|
# Calculate days to subtract to get to Monday (weekday() returns 0 for Monday, 6 for Sunday)
|
|
318
348
|
days_since_monday = dt_local.weekday()
|
|
349
|
+
|
|
319
350
|
start_week = dt_local - datetime.timedelta(days=days_since_monday)
|
|
320
351
|
start_week = start_week.replace(hour=0, minute=0, second=0, microsecond=0)
|
|
352
|
+
|
|
321
353
|
return int(start_week.timestamp())
|
|
322
354
|
|
|
323
355
|
|
|
324
|
-
def get_next_day(timestamp=None, tz=
|
|
356
|
+
def get_next_day(timestamp=None, tz=None):
|
|
325
357
|
"""
|
|
326
358
|
Get the start of the next day (midnight) for a given timestamp in a specified timezone.
|
|
327
359
|
|
|
@@ -332,17 +364,22 @@ def get_next_day(timestamp=None, tz=0):
|
|
|
332
364
|
Returns:
|
|
333
365
|
float: The timestamp for the start of the next day (midnight) in the specified timezone.
|
|
334
366
|
"""
|
|
367
|
+
|
|
335
368
|
if timestamp is None:
|
|
336
369
|
timestamp = time.time()
|
|
370
|
+
if tz is None:
|
|
371
|
+
tz = 0
|
|
372
|
+
|
|
337
373
|
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
|
|
338
374
|
next_day = (dt_local + datetime.timedelta(days=1)).replace(
|
|
339
375
|
hour=0, minute=0, second=0, microsecond=0
|
|
340
376
|
)
|
|
377
|
+
|
|
341
378
|
return int(next_day.timestamp())
|
|
342
379
|
|
|
343
380
|
|
|
344
381
|
# TODO: get previous month (params=-1 +1)
|
|
345
|
-
def get_next_month(timestamp=None, tz=
|
|
382
|
+
def get_next_month(timestamp=None, tz=None):
|
|
346
383
|
"""
|
|
347
384
|
Get the start of the next month (midnight on the first day of the next month) for a given timestamp in a specified timezone.
|
|
348
385
|
|
|
@@ -356,6 +393,8 @@ def get_next_month(timestamp=None, tz=0):
|
|
|
356
393
|
|
|
357
394
|
if timestamp is None:
|
|
358
395
|
timestamp = time.time()
|
|
396
|
+
if tz is None:
|
|
397
|
+
tz = 0
|
|
359
398
|
|
|
360
399
|
dt_local = datetime.datetime.fromtimestamp(timestamp, tz=to_tz(tz))
|
|
361
400
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: libdev
|
|
3
|
+
Version: 0.97
|
|
4
|
+
Summary: Set of standard functions for development
|
|
5
|
+
Home-page: https://github.com/chilleco/lib
|
|
6
|
+
Author: Alex Poloz
|
|
7
|
+
Author-email: Alex Poloz <alexypoloz@gmail.com>
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2021 Alexey Poloz
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
|
|
30
|
+
Project-URL: Source, https://github.com/chilleco/lib
|
|
31
|
+
Keywords: standard,lib,dev,development,cfg,config,generate,codes,tokens,ids,passwords,generator,ciphers,time,formatter,nlp,natural language,aws,s3,upload file,file server
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Environment :: Console
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
36
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
43
|
+
Classifier: Operating System :: OS Independent
|
|
44
|
+
Requires-Python: >=3.10, <4
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
License-File: LICENSE
|
|
47
|
+
Requires-Dist: aiohttp>=3.13.2
|
|
48
|
+
Requires-Dist: python-dotenv>=1.2.1
|
|
49
|
+
Requires-Dist: boto3>=1.42.0
|
|
50
|
+
Requires-Dist: Pillow>=12.0.0
|
|
51
|
+
Requires-Dist: loguru>=0.7.3
|
|
52
|
+
Provides-Extra: dev
|
|
53
|
+
Requires-Dist: build>=1.3.0; extra == "dev"
|
|
54
|
+
Requires-Dist: setuptools>=80.9.0; extra == "dev"
|
|
55
|
+
Requires-Dist: twine>=6.2.0; extra == "dev"
|
|
56
|
+
Requires-Dist: pylint>=4.0.4; extra == "dev"
|
|
57
|
+
Requires-Dist: pytest>=9.0.1; extra == "dev"
|
|
58
|
+
Requires-Dist: pytest-asyncio>=1.3.0; extra == "dev"
|
|
59
|
+
Dynamic: author
|
|
60
|
+
Dynamic: home-page
|
|
61
|
+
Dynamic: license-file
|
|
62
|
+
Dynamic: requires-python
|
|
63
|
+
|
|
64
|
+
# LibDev
|
|
65
|
+
Development library — Set of standard functions for development
|
|
66
|
+
|
|
67
|
+
[GitHub](https://github.com/chilleco/lib)
|
|
68
|
+
| [PyPI](https://pypi.org/project/libdev/)
|
|
69
|
+
|
|
70
|
+
## Requirements
|
|
71
|
+
- Python 3.10+ (dependencies are 3.14-ready)
|
|
72
|
+
|
|
73
|
+
## Installation
|
|
74
|
+
- Runtime: `pip install .`
|
|
75
|
+
- Dev / tests: `pip install .[dev]` or `make setup-dev`
|
|
76
|
+
|
|
77
|
+
## Submodules
|
|
78
|
+
Stream | Submodule | Description
|
|
79
|
+
---|---|---
|
|
80
|
+
System | ` libdev.cfg ` | Configuration getting
|
|
81
|
+
| ` libdev.req ` | AsyncIO requests (AIOHTTP wrapper)
|
|
82
|
+
| ` libdev.log ` | Logger (Loguru wrapper)
|
|
83
|
+
Data Format | ` libdev.num ` | Numeric conversions & handlers
|
|
84
|
+
| ` libdev.time ` | Time processing
|
|
85
|
+
Transforms | ` libdev.gen ` | Code & token generators
|
|
86
|
+
| ` libdev.codes ` | Ciphers: langs & flags / networks / user statuses
|
|
87
|
+
| ` libdev.check ` | Validation functions
|
|
88
|
+
| ` libdev.crypt ` | Encryption and decryption functions
|
|
89
|
+
Fields | ` libdev.dev ` | Development tools
|
|
90
|
+
| ` libdev.fin ` | Financial codes and tools
|
|
91
|
+
| ` libdev.lang ` | Natural language formatters
|
|
92
|
+
Files | ` libdev.doc ` | Base64 / JSON handlers
|
|
93
|
+
| ` libdev.s3 ` | S3 file server functions
|
|
94
|
+
| ` libdev.img ` | Image processing
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=80.9", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "libdev"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Set of standard functions for development"
|
|
9
|
+
readme = { file = "README.md", content-type = "text/markdown" }
|
|
10
|
+
requires-python = ">=3.10, <4"
|
|
11
|
+
license = { file = "LICENSE" }
|
|
12
|
+
authors = [{ name = "Alex Poloz", email = "alexypoloz@gmail.com" }]
|
|
13
|
+
keywords = [
|
|
14
|
+
"standard",
|
|
15
|
+
"lib",
|
|
16
|
+
"dev",
|
|
17
|
+
"development",
|
|
18
|
+
"cfg",
|
|
19
|
+
"config",
|
|
20
|
+
"generate",
|
|
21
|
+
"codes",
|
|
22
|
+
"tokens",
|
|
23
|
+
"ids",
|
|
24
|
+
"passwords",
|
|
25
|
+
"generator",
|
|
26
|
+
"ciphers",
|
|
27
|
+
"time",
|
|
28
|
+
"formatter",
|
|
29
|
+
"nlp",
|
|
30
|
+
"natural language",
|
|
31
|
+
"aws",
|
|
32
|
+
"s3",
|
|
33
|
+
"upload file",
|
|
34
|
+
"file server",
|
|
35
|
+
]
|
|
36
|
+
classifiers = [
|
|
37
|
+
"Development Status :: 4 - Beta",
|
|
38
|
+
"Environment :: Console",
|
|
39
|
+
"Intended Audience :: Developers",
|
|
40
|
+
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
41
|
+
"License :: OSI Approved :: MIT License",
|
|
42
|
+
"Programming Language :: Python :: 3",
|
|
43
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
44
|
+
"Programming Language :: Python :: 3.10",
|
|
45
|
+
"Programming Language :: Python :: 3.11",
|
|
46
|
+
"Programming Language :: Python :: 3.12",
|
|
47
|
+
"Programming Language :: Python :: 3.13",
|
|
48
|
+
"Operating System :: OS Independent",
|
|
49
|
+
]
|
|
50
|
+
dependencies = [
|
|
51
|
+
"aiohttp>=3.13.2",
|
|
52
|
+
"python-dotenv>=1.2.1",
|
|
53
|
+
"boto3>=1.42.0",
|
|
54
|
+
"Pillow>=12.0.0",
|
|
55
|
+
"loguru>=0.7.3",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[project.optional-dependencies]
|
|
59
|
+
dev = [
|
|
60
|
+
"build>=1.3.0",
|
|
61
|
+
"setuptools>=80.9.0",
|
|
62
|
+
"twine>=6.2.0",
|
|
63
|
+
"pylint>=4.0.4",
|
|
64
|
+
"pytest>=9.0.1",
|
|
65
|
+
"pytest-asyncio>=1.3.0",
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
[project.urls]
|
|
69
|
+
Source = "https://github.com/chilleco/lib"
|
|
70
|
+
|
|
71
|
+
[tool.setuptools.dynamic]
|
|
72
|
+
version = { attr = "libdev.__version__" }
|
|
73
|
+
|
|
74
|
+
[tool.setuptools.packages.find]
|
|
75
|
+
exclude = ["tests", "tests.*"]
|
|
@@ -4,31 +4,31 @@ Setup the Python package
|
|
|
4
4
|
|
|
5
5
|
import pathlib
|
|
6
6
|
import re
|
|
7
|
-
from setuptools import setup, find_packages
|
|
8
7
|
|
|
8
|
+
from setuptools import find_packages, setup
|
|
9
9
|
|
|
10
|
-
with open("README.md", "r", encoding="utf-8") as file:
|
|
11
|
-
long_description = file.read()
|
|
12
10
|
|
|
13
11
|
WORK_DIR = pathlib.Path(__file__).parent
|
|
14
12
|
|
|
13
|
+
with open(WORK_DIR / "README.md", "r", encoding="utf-8") as file:
|
|
14
|
+
LONG_DESCRIPTION = file.read()
|
|
15
|
+
|
|
15
16
|
|
|
16
17
|
def get_version():
|
|
17
|
-
"""
|
|
18
|
+
"""Extract version from package init."""
|
|
18
19
|
|
|
19
20
|
txt = (WORK_DIR / "libdev" / "__init__.py").read_text("utf-8")
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
raise RuntimeError("Unable to determine version") from e
|
|
21
|
+
match = re.search(r'^__version__ = "([^"]+)"', txt, re.M)
|
|
22
|
+
if not match:
|
|
23
|
+
raise RuntimeError("Unable to determine version")
|
|
24
|
+
return match.group(1)
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
setup(
|
|
28
28
|
name="libdev",
|
|
29
29
|
version=get_version(),
|
|
30
30
|
description="Set of standard functions for development",
|
|
31
|
-
long_description=
|
|
31
|
+
long_description=LONG_DESCRIPTION,
|
|
32
32
|
long_description_content_type="text/markdown",
|
|
33
33
|
url="https://github.com/chilleco/lib",
|
|
34
34
|
author="Alex Poloz",
|
|
@@ -40,6 +40,11 @@ setup(
|
|
|
40
40
|
"Topic :: Software Development :: Libraries :: Application Frameworks",
|
|
41
41
|
"License :: OSI Approved :: MIT License",
|
|
42
42
|
"Programming Language :: Python :: 3",
|
|
43
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
44
|
+
"Programming Language :: Python :: 3.10",
|
|
45
|
+
"Programming Language :: Python :: 3.11",
|
|
46
|
+
"Programming Language :: Python :: 3.12",
|
|
47
|
+
"Programming Language :: Python :: 3.13",
|
|
43
48
|
"Operating System :: OS Independent",
|
|
44
49
|
],
|
|
45
50
|
keywords=(
|
|
@@ -48,14 +53,13 @@ setup(
|
|
|
48
53
|
"natural language, aws, s3, upload file, file server"
|
|
49
54
|
),
|
|
50
55
|
packages=find_packages(exclude=("tests",)),
|
|
51
|
-
python_requires=">=3.
|
|
56
|
+
python_requires=">=3.10, <4",
|
|
52
57
|
install_requires=[
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"loguru",
|
|
58
|
+
"aiohttp>=3.13.2",
|
|
59
|
+
"python-dotenv>=1.2.1",
|
|
60
|
+
"boto3>=1.42.0",
|
|
61
|
+
"Pillow>=12.0.0",
|
|
62
|
+
"loguru>=0.7.3",
|
|
59
63
|
],
|
|
60
64
|
project_urls={
|
|
61
65
|
"Source": "https://github.com/chilleco/lib",
|
|
@@ -157,6 +157,7 @@ def test_pretty():
|
|
|
157
157
|
assert pretty(123.456, 1) == "123"
|
|
158
158
|
assert pretty(123.456, 1, True) == "+123"
|
|
159
159
|
assert pretty(12345.6, 3, True) == "+12’346"
|
|
160
|
+
assert pretty(1046012.4859999998, 0) == "1’046’012"
|
|
160
161
|
assert pretty(-0.000000235235, zeros=None, compress=None) == "-0.000000235235"
|
|
161
162
|
assert pretty(-0.000000235235, zeros=4, compress=2) == "-0.0₆24"
|
|
162
163
|
|
|
@@ -13,6 +13,7 @@ from libdev.time import (
|
|
|
13
13
|
format_delta,
|
|
14
14
|
get_midnight,
|
|
15
15
|
get_month_start,
|
|
16
|
+
get_previous_month,
|
|
16
17
|
get_next_day,
|
|
17
18
|
get_next_month,
|
|
18
19
|
get_delta_days,
|
|
@@ -121,6 +122,12 @@ def test_get_month_start():
|
|
|
121
122
|
assert get_month_start(1704060061, tz=3) == 1704056400
|
|
122
123
|
|
|
123
124
|
|
|
125
|
+
def test_get_previous_month():
|
|
126
|
+
assert get_previous_month(1764497920.160952) == 1759276800
|
|
127
|
+
assert get_previous_month(1764497920, tz=3) == 1759266000
|
|
128
|
+
assert get_previous_month(1760648400, 1) == 1756681200
|
|
129
|
+
|
|
130
|
+
|
|
124
131
|
def test_get_next_day():
|
|
125
132
|
assert get_next_day(1704060061) == 1704067200
|
|
126
133
|
assert get_next_day(1704060061, tz=3) == 1704142800
|
libdev-0.95/PKG-INFO
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: libdev
|
|
3
|
-
Version: 0.95
|
|
4
|
-
Summary: Set of standard functions for development
|
|
5
|
-
Home-page: https://github.com/chilleco/lib
|
|
6
|
-
Author: Alex Poloz
|
|
7
|
-
Author-email: alexypoloz@gmail.com
|
|
8
|
-
License: MIT
|
|
9
|
-
Project-URL: Source, https://github.com/chilleco/lib
|
|
10
|
-
Keywords: standard,lib,dev,development,cfg,config,generate,codes,tokens,ids,passwords,generator,ciphers,time,formatter,nlp,natural language,aws,s3,upload file,file server
|
|
11
|
-
Classifier: Development Status :: 4 - Beta
|
|
12
|
-
Classifier: Environment :: Console
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
15
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
-
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Operating System :: OS Independent
|
|
18
|
-
Requires-Python: >=3.7, <4
|
|
19
|
-
Description-Content-Type: text/markdown
|
|
20
|
-
License-File: LICENSE
|
|
21
|
-
Requires-Dist: aiohttp
|
|
22
|
-
Requires-Dist: python-dotenv
|
|
23
|
-
Requires-Dist: boto3
|
|
24
|
-
Requires-Dist: Pillow
|
|
25
|
-
Requires-Dist: loguru
|
|
26
|
-
|
|
27
|
-
# LibDev
|
|
28
|
-
Development library — Set of standard functions for development
|
|
29
|
-
|
|
30
|
-
[GitHub](https://github.com/chilleco/lib)
|
|
31
|
-
| [PyPI](https://pypi.org/project/libdev/)
|
|
32
|
-
|
|
33
|
-
## Submodules
|
|
34
|
-
Stream | Submodule | Description
|
|
35
|
-
---|---|---
|
|
36
|
-
System | ` libdev.cfg ` | Configuration getting
|
|
37
|
-
| ` libdev.req ` | AsyncIO requests (AIOHTTP wrapper)
|
|
38
|
-
| ` libdev.log ` | Logger (Loguru wrapper)
|
|
39
|
-
Data Format | ` libdev.num ` | Numeric conversions & handlers
|
|
40
|
-
| ` libdev.time ` | Time processing
|
|
41
|
-
Transforms | ` libdev.gen ` | Code & token generators
|
|
42
|
-
| ` libdev.codes ` | Ciphers: langs & flags / networks / user statuses
|
|
43
|
-
| ` libdev.check ` | Validation functions
|
|
44
|
-
| ` libdev.crypt ` | Encryption and decryption functions
|
|
45
|
-
Fields | ` libdev.dev ` | Development tools
|
|
46
|
-
| ` libdev.fin ` | Financial codes and tools
|
|
47
|
-
| ` libdev.lang ` | Natural language formatters
|
|
48
|
-
Files | ` libdev.doc ` | Base64 / JSON handlers
|
|
49
|
-
| ` libdev.s3 ` | S3 file server functions
|
|
50
|
-
| ` libdev.img ` | Image processing
|
libdev-0.95/libdev/dev.py
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Development tools
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import re
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def check_public_ip(ip):
|
|
9
|
-
"""Check if the IP address is public"""
|
|
10
|
-
|
|
11
|
-
if not ip:
|
|
12
|
-
return None
|
|
13
|
-
|
|
14
|
-
return (
|
|
15
|
-
None
|
|
16
|
-
if re.match(
|
|
17
|
-
r"^(172\.(1[6-9]\.|2[0-9]\.|3[0-1]\.)|192\.168\.|10\.|127\.)",
|
|
18
|
-
ip,
|
|
19
|
-
)
|
|
20
|
-
else ip
|
|
21
|
-
)
|
libdev-0.95/libdev/doc.py
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Documents processing functionality
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import base64
|
|
6
|
-
import json
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def to_base64(image, mime="image/jpg"):
|
|
10
|
-
"""Convert image to base64"""
|
|
11
|
-
data = base64.b64encode(image.read())
|
|
12
|
-
return f"data:{mime};base64,{data.decode('utf-8')}"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def to_json(data):
|
|
16
|
-
"""Convert object to json"""
|
|
17
|
-
return json.dumps(data, indent="\t", ensure_ascii=False)
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: libdev
|
|
3
|
-
Version: 0.95
|
|
4
|
-
Summary: Set of standard functions for development
|
|
5
|
-
Home-page: https://github.com/chilleco/lib
|
|
6
|
-
Author: Alex Poloz
|
|
7
|
-
Author-email: alexypoloz@gmail.com
|
|
8
|
-
License: MIT
|
|
9
|
-
Project-URL: Source, https://github.com/chilleco/lib
|
|
10
|
-
Keywords: standard,lib,dev,development,cfg,config,generate,codes,tokens,ids,passwords,generator,ciphers,time,formatter,nlp,natural language,aws,s3,upload file,file server
|
|
11
|
-
Classifier: Development Status :: 4 - Beta
|
|
12
|
-
Classifier: Environment :: Console
|
|
13
|
-
Classifier: Intended Audience :: Developers
|
|
14
|
-
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
15
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
-
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Operating System :: OS Independent
|
|
18
|
-
Requires-Python: >=3.7, <4
|
|
19
|
-
Description-Content-Type: text/markdown
|
|
20
|
-
License-File: LICENSE
|
|
21
|
-
Requires-Dist: aiohttp
|
|
22
|
-
Requires-Dist: python-dotenv
|
|
23
|
-
Requires-Dist: boto3
|
|
24
|
-
Requires-Dist: Pillow
|
|
25
|
-
Requires-Dist: loguru
|
|
26
|
-
|
|
27
|
-
# LibDev
|
|
28
|
-
Development library — Set of standard functions for development
|
|
29
|
-
|
|
30
|
-
[GitHub](https://github.com/chilleco/lib)
|
|
31
|
-
| [PyPI](https://pypi.org/project/libdev/)
|
|
32
|
-
|
|
33
|
-
## Submodules
|
|
34
|
-
Stream | Submodule | Description
|
|
35
|
-
---|---|---
|
|
36
|
-
System | ` libdev.cfg ` | Configuration getting
|
|
37
|
-
| ` libdev.req ` | AsyncIO requests (AIOHTTP wrapper)
|
|
38
|
-
| ` libdev.log ` | Logger (Loguru wrapper)
|
|
39
|
-
Data Format | ` libdev.num ` | Numeric conversions & handlers
|
|
40
|
-
| ` libdev.time ` | Time processing
|
|
41
|
-
Transforms | ` libdev.gen ` | Code & token generators
|
|
42
|
-
| ` libdev.codes ` | Ciphers: langs & flags / networks / user statuses
|
|
43
|
-
| ` libdev.check ` | Validation functions
|
|
44
|
-
| ` libdev.crypt ` | Encryption and decryption functions
|
|
45
|
-
Fields | ` libdev.dev ` | Development tools
|
|
46
|
-
| ` libdev.fin ` | Financial codes and tools
|
|
47
|
-
| ` libdev.lang ` | Natural language formatters
|
|
48
|
-
Files | ` libdev.doc ` | Base64 / JSON handlers
|
|
49
|
-
| ` libdev.s3 ` | S3 file server functions
|
|
50
|
-
| ` libdev.img ` | Image processing
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
libdev
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|