utilo 2.112.0__tar.gz → 2.112.2__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.
- {utilo-2.112.0/utilo.egg-info → utilo-2.112.2}/PKG-INFO +3 -3
- {utilo-2.112.0 → utilo-2.112.2}/pyproject.toml +6 -7
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_file.py +26 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/cacher.py +6 -2
- {utilo-2.112.0 → utilo-2.112.2}/utilo/file/__init__.py +29 -11
- {utilo-2.112.0 → utilo-2.112.2}/utilo/string/__init__.py +2 -0
- {utilo-2.112.0 → utilo-2.112.2/utilo.egg-info}/PKG-INFO +3 -3
- {utilo-2.112.0 → utilo-2.112.2}/utilo.egg-info/requires.txt +2 -2
- {utilo-2.112.0 → utilo-2.112.2}/LICENSE +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/README +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/setup.cfg +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_collection.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_convert.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_datetime.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_decorators.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_error.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_likelihood.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_logger.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_math.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_pages.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_process.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_quick.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_regex.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_string.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_todo.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_typechecker.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_utils.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/tests/test_yaml.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/__init__.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/__todo__.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/alpha.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/baw.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/classes.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/classifier/__init__.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/classifier/base.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/classifier/public.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/classifier/strategy.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/cli/__init__.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/collection.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/color.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/config.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/convert.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/datetime.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/decorator.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/error.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/__init__.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/cache.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/collector.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/config.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/cprofile.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/description.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/outpath.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/pack.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/path.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/processor.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/userinput.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/feature/workplan.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/file/action.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/file/directory.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/file/hashed.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/file/info.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/file/loader.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/file/securewrapper.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/file/utils.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/group.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/hash.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/likelihood.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/logger.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/math/__init__.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/math/const.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/math/distance.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/math/func.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/math/line.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/math/near.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/math/number.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/math/rectangle.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/math/roman.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/optimizer.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/pages.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/process.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/quick.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/regex.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/secret.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/space.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/string/compare.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/string/display.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/string/modify.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/string/table.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/tuples.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/typechecker.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/utils.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/xyz/__init__.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/xyz/lock.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/xyz/table.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo/xyz/tidy.py +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo.egg-info/SOURCES.txt +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo.egg-info/dependency_links.txt +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo.egg-info/entry_points.txt +0 -0
- {utilo-2.112.0 → utilo-2.112.2}/utilo.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: utilo
|
|
3
|
-
Version: 2.112.
|
|
3
|
+
Version: 2.112.2
|
|
4
4
|
Author-email: Helmut Konrad Schewe <helmutus@outlook.com>
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/anaticulae/utilo
|
|
@@ -11,13 +11,13 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
11
11
|
Requires-Python: >=3.12
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
-
Requires-Dist: filelock<5.0.0,>=4.
|
|
14
|
+
Requires-Dist: filelock<5.0.0,>=4.2.10
|
|
15
15
|
Requires-Dist: utilosafe<2.0.0,>=1.0.0
|
|
16
16
|
Provides-Extra: dev
|
|
17
17
|
Requires-Dist: PyYAML<7.0.0,>=6.0.3; extra == "dev"
|
|
18
18
|
Requires-Dist: pytest-timeout<3.0.0,>=2.4.0; extra == "dev"
|
|
19
19
|
Requires-Dist: utilotest<2.0.0,>=1.1.1; extra == "dev"
|
|
20
|
-
Requires-Dist: iamraw<5.0.0,>=4.95.
|
|
20
|
+
Requires-Dist: iamraw<5.0.0,>=4.95.1; extra == "dev"
|
|
21
21
|
Dynamic: license-file
|
|
22
22
|
|
|
23
23
|
UTILA
|
|
@@ -7,14 +7,14 @@ build-backend = "setuptools.build_meta"
|
|
|
7
7
|
|
|
8
8
|
[project]
|
|
9
9
|
name = "utilo"
|
|
10
|
-
version = "2.112.
|
|
10
|
+
version = "2.112.2"
|
|
11
11
|
description = ""
|
|
12
12
|
requires-python = ">=3.12"
|
|
13
13
|
authors = [
|
|
14
14
|
{ name = "Helmut Konrad Schewe", email = "helmutus@outlook.com" },
|
|
15
15
|
]
|
|
16
16
|
dependencies = [
|
|
17
|
-
"filelock>=4.
|
|
17
|
+
"filelock>=4.2.10,<5.0.0",
|
|
18
18
|
"utilosafe>=1.0.0,<2.0.0",
|
|
19
19
|
]
|
|
20
20
|
keywords = []
|
|
@@ -43,7 +43,7 @@ dev = [
|
|
|
43
43
|
"PyYAML>=6.0.3,<7.0.0",
|
|
44
44
|
"pytest-timeout>=2.4.0,<3.0.0",
|
|
45
45
|
"utilotest>=1.1.1,<2.0.0",
|
|
46
|
-
"iamraw>=4.95.
|
|
46
|
+
"iamraw>=4.95.1,<5.0.0",
|
|
47
47
|
]
|
|
48
48
|
|
|
49
49
|
[project.urls]
|
|
@@ -63,21 +63,20 @@ output_format = "md"
|
|
|
63
63
|
changelog_file = "CHANGELOG"
|
|
64
64
|
|
|
65
65
|
[tool.semantic_release.commit_parser_options]
|
|
66
|
-
|
|
66
|
+
allowed_tags = [
|
|
67
67
|
"build",
|
|
68
68
|
"chore",
|
|
69
69
|
"ci",
|
|
70
70
|
"deps",
|
|
71
71
|
"docs",
|
|
72
|
+
"feat",
|
|
72
73
|
"fix",
|
|
73
74
|
"perf",
|
|
74
75
|
"refactor",
|
|
75
76
|
"style",
|
|
76
77
|
"test",
|
|
77
78
|
]
|
|
78
|
-
|
|
79
|
-
"feat",
|
|
80
|
-
]
|
|
79
|
+
default_bump_level = 2
|
|
81
80
|
|
|
82
81
|
[tool.setuptools.packages.find]
|
|
83
82
|
where = [
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
# be prosecuted under federal law. Its content is company confidential.
|
|
8
8
|
#==============================================================================
|
|
9
9
|
|
|
10
|
+
import multiprocessing
|
|
10
11
|
import os
|
|
11
12
|
|
|
12
13
|
import pytest
|
|
@@ -602,3 +603,28 @@ def test_file_create_owner(tmpdir):
|
|
|
602
603
|
# -rw-rw-r-- local
|
|
603
604
|
# -rw-r--r-- github
|
|
604
605
|
assert mode in {33204, 33188}
|
|
606
|
+
|
|
607
|
+
|
|
608
|
+
def test_file_replace_binary_overlap(tmpdir):
|
|
609
|
+
"""Verify that concurrent processes replace file correctly."""
|
|
610
|
+
expected = b'binary'
|
|
611
|
+
path = utilo.join(tmpdir, 'file.txt')
|
|
612
|
+
concurrent_run(
|
|
613
|
+
target=utilo.file_replace_binary,
|
|
614
|
+
args=(path, expected),
|
|
615
|
+
)
|
|
616
|
+
content = utilo.file_read_binary(path, lock=True)
|
|
617
|
+
assert content == expected
|
|
618
|
+
|
|
619
|
+
|
|
620
|
+
def concurrent_run(target, args, times: int = 100):
|
|
621
|
+
processes = [
|
|
622
|
+
multiprocessing.Process(
|
|
623
|
+
target=target,
|
|
624
|
+
args=args,
|
|
625
|
+
) for _ in range(times)
|
|
626
|
+
]
|
|
627
|
+
for p in processes:
|
|
628
|
+
p.start()
|
|
629
|
+
for p in processes:
|
|
630
|
+
p.join()
|
|
@@ -78,8 +78,12 @@ def safehash(item):
|
|
|
78
78
|
return hash(str(item))
|
|
79
79
|
|
|
80
80
|
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
try:
|
|
82
|
+
# python <= 3.12
|
|
83
|
+
functools._HashedSeq.__init__.__defaults__ = (safehash,)
|
|
84
|
+
except AttributeError:
|
|
85
|
+
pass
|
|
86
|
+
# python >= 3.13
|
|
83
87
|
# pylint:disable=all
|
|
84
88
|
|
|
85
89
|
################################################################################
|
|
@@ -85,12 +85,14 @@ def file_append(path: str, content: str, create: bool = False, private: bool = F
|
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
@contextlib.contextmanager
|
|
88
|
-
def lock_file(path: str, lock: bool = True):
|
|
89
|
-
if
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
def lock_file(path: str, lock: bool = True):
|
|
89
|
+
if lock:
|
|
90
|
+
lockdir = tmp('/utilo')
|
|
91
|
+
simple = utilo.simple(path, maxlength=255)
|
|
92
|
+
lockpath = utilo.join(lockdir, simple)
|
|
93
|
+
with filelock.FileLock(lockpath):
|
|
94
|
+
yield
|
|
95
|
+
else:
|
|
94
96
|
yield
|
|
95
97
|
|
|
96
98
|
|
|
@@ -211,8 +213,11 @@ def file_read_binary(
|
|
|
211
213
|
"""Read binary file content"""
|
|
212
214
|
with lock_file(path, lock=lock):
|
|
213
215
|
utilo.exists_assert(path)
|
|
214
|
-
with utilo.file.securewrapper.open(
|
|
215
|
-
|
|
216
|
+
with utilo.file.securewrapper.open(
|
|
217
|
+
path,
|
|
218
|
+
mode='rb',
|
|
219
|
+
private=private,
|
|
220
|
+
) as fp:
|
|
216
221
|
content = fp.read(size)
|
|
217
222
|
return content
|
|
218
223
|
|
|
@@ -252,7 +257,11 @@ def file_replace(
|
|
|
252
257
|
lock=False,
|
|
253
258
|
)
|
|
254
259
|
return
|
|
255
|
-
current_content = file_read(
|
|
260
|
+
current_content = file_read(
|
|
261
|
+
path,
|
|
262
|
+
private=private,
|
|
263
|
+
lock=False,
|
|
264
|
+
)
|
|
256
265
|
if current_content == content:
|
|
257
266
|
return
|
|
258
267
|
with utilo.file.securewrapper.open(
|
|
@@ -279,9 +288,18 @@ def file_replace_binary(path: str, content: bytes, private: bool = False):
|
|
|
279
288
|
"""
|
|
280
289
|
with lock_file(path, lock=True):
|
|
281
290
|
if not os.path.exists(path):
|
|
282
|
-
file_create_binary(
|
|
291
|
+
file_create_binary(
|
|
292
|
+
path,
|
|
293
|
+
content,
|
|
294
|
+
private=private,
|
|
295
|
+
lock=False,
|
|
296
|
+
)
|
|
283
297
|
return
|
|
284
|
-
current_content = file_read_binary(
|
|
298
|
+
current_content = file_read_binary(
|
|
299
|
+
path,
|
|
300
|
+
private=private,
|
|
301
|
+
lock=False,
|
|
302
|
+
)
|
|
285
303
|
if current_content == content:
|
|
286
304
|
return
|
|
287
305
|
with utilo.file.securewrapper.open(
|
|
@@ -386,6 +386,8 @@ def simple(item: str, maxlength: int = 25) -> str:
|
|
|
386
386
|
|
|
387
387
|
>>> simple('No spaces _+; 133')
|
|
388
388
|
'Nospaces133'
|
|
389
|
+
>>> simple('/c/windows/tmp/abc/test.txt')
|
|
390
|
+
'cwindowstmpabctesttxt'
|
|
389
391
|
"""
|
|
390
392
|
item = utilo.fix_encoding(item)
|
|
391
393
|
item = item.translate(SIMPLIFY)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: utilo
|
|
3
|
-
Version: 2.112.
|
|
3
|
+
Version: 2.112.2
|
|
4
4
|
Author-email: Helmut Konrad Schewe <helmutus@outlook.com>
|
|
5
5
|
License-Expression: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/anaticulae/utilo
|
|
@@ -11,13 +11,13 @@ Classifier: Programming Language :: Python :: 3.14
|
|
|
11
11
|
Requires-Python: >=3.12
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
License-File: LICENSE
|
|
14
|
-
Requires-Dist: filelock<5.0.0,>=4.
|
|
14
|
+
Requires-Dist: filelock<5.0.0,>=4.2.10
|
|
15
15
|
Requires-Dist: utilosafe<2.0.0,>=1.0.0
|
|
16
16
|
Provides-Extra: dev
|
|
17
17
|
Requires-Dist: PyYAML<7.0.0,>=6.0.3; extra == "dev"
|
|
18
18
|
Requires-Dist: pytest-timeout<3.0.0,>=2.4.0; extra == "dev"
|
|
19
19
|
Requires-Dist: utilotest<2.0.0,>=1.1.1; extra == "dev"
|
|
20
|
-
Requires-Dist: iamraw<5.0.0,>=4.95.
|
|
20
|
+
Requires-Dist: iamraw<5.0.0,>=4.95.1; extra == "dev"
|
|
21
21
|
Dynamic: license-file
|
|
22
22
|
|
|
23
23
|
UTILA
|
|
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
|
|
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
|
|
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
|
|
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
|