justkitten 0.8.0__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.
- justkitten-0.8.0/.github/workflows/integration.yml +40 -0
- justkitten-0.8.0/.github/workflows/release.yml +40 -0
- justkitten-0.8.0/.github/workflows/tests.yml +13 -0
- justkitten-0.8.0/.gitignore +142 -0
- justkitten-0.8.0/CHANGELOG.md +408 -0
- justkitten-0.8.0/CLAUDE.md +41 -0
- justkitten-0.8.0/PKG-INFO +145 -0
- justkitten-0.8.0/README.md +97 -0
- justkitten-0.8.0/pyproject.toml +124 -0
- justkitten-0.8.0/src/justkitten/__init__.py +0 -0
- justkitten-0.8.0/src/justkitten/cd.py +19 -0
- justkitten-0.8.0/src/justkitten/cli.py +162 -0
- justkitten-0.8.0/src/justkitten/data.py +134 -0
- justkitten-0.8.0/src/justkitten/dictable.py +237 -0
- justkitten-0.8.0/src/justkitten/exif.py +124 -0
- justkitten-0.8.0/src/justkitten/filesystem.py +648 -0
- justkitten-0.8.0/src/justkitten/joins.py +62 -0
- justkitten-0.8.0/src/justkitten/json_migration.py +60 -0
- justkitten-0.8.0/src/justkitten/parts.py +216 -0
- justkitten-0.8.0/src/justkitten/py.typed +0 -0
- justkitten-0.8.0/src/justkitten/pylinq.py +182 -0
- justkitten-0.8.0/src/justkitten/singleton.py +22 -0
- justkitten-0.8.0/src/justkitten/sources.py +157 -0
- justkitten-0.8.0/src/justkitten/subfolder.py +25 -0
- justkitten-0.8.0/src/justkitten/testing.py +27 -0
- justkitten-0.8.0/src/justkitten/time_formatter.py +24 -0
- justkitten-0.8.0/src/justkitten/transfer.py +67 -0
- justkitten-0.8.0/src/justkitten/util.py +326 -0
- justkitten-0.8.0/tests/__init__.py +0 -0
- justkitten-0.8.0/tests/conftest.py +10 -0
- justkitten-0.8.0/tests/test_cd.py +44 -0
- justkitten-0.8.0/tests/test_cli.py +114 -0
- justkitten-0.8.0/tests/test_data.py +118 -0
- justkitten-0.8.0/tests/test_dictable.py +691 -0
- justkitten-0.8.0/tests/test_exif.py +171 -0
- justkitten-0.8.0/tests/test_filesystem.py +68 -0
- justkitten-0.8.0/tests/test_joins.py +48 -0
- justkitten-0.8.0/tests/test_json_migration.py +76 -0
- justkitten-0.8.0/tests/test_parts.py +184 -0
- justkitten-0.8.0/tests/test_pylinq.py +244 -0
- justkitten-0.8.0/tests/test_singleton.py +31 -0
- justkitten-0.8.0/tests/test_sources.py +151 -0
- justkitten-0.8.0/tests/test_subfolder.py +50 -0
- justkitten-0.8.0/tests/test_testing.py +69 -0
- justkitten-0.8.0/tests/test_time_formatter.py +33 -0
- justkitten-0.8.0/tests/test_transfer.py +30 -0
- justkitten-0.8.0/tests/test_util.py +36 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Integration
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
integration:
|
|
10
|
+
uses: djachenko/repokit/.github/workflows/python-integration.yml@0.9
|
|
11
|
+
secrets: inherit
|
|
12
|
+
|
|
13
|
+
publish:
|
|
14
|
+
needs: integration
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
permissions:
|
|
17
|
+
id-token: write
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/download-artifact@v8
|
|
21
|
+
with:
|
|
22
|
+
name: dist
|
|
23
|
+
path: dist/
|
|
24
|
+
|
|
25
|
+
- name: Publish to TestPyPI
|
|
26
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
27
|
+
with:
|
|
28
|
+
repository-url: https://test.pypi.org/legacy/
|
|
29
|
+
skip-existing: true
|
|
30
|
+
|
|
31
|
+
- name: Smoke test
|
|
32
|
+
run: |
|
|
33
|
+
PACKAGE=$(ls dist/*.whl | head -1 | xargs basename | sed 's/-[0-9].*//')
|
|
34
|
+
VERSION=$(ls dist/*.tar.gz | sed 's/.*-\(.*\)\.tar\.gz/\1/')
|
|
35
|
+
for i in {1..5}; do
|
|
36
|
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ $PACKAGE==$VERSION && break
|
|
37
|
+
echo "Attempt $i failed, retrying in 10s..."
|
|
38
|
+
sleep 10
|
|
39
|
+
done
|
|
40
|
+
python -c "import $PACKAGE"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- master
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
release:
|
|
10
|
+
uses: djachenko/repokit/.github/workflows/python-release.yml@0.9
|
|
11
|
+
secrets: inherit
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write
|
|
14
|
+
|
|
15
|
+
publish:
|
|
16
|
+
needs: release
|
|
17
|
+
if: needs.release.outputs.released == 'true'
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
permissions:
|
|
20
|
+
id-token: write
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/download-artifact@v8
|
|
24
|
+
with:
|
|
25
|
+
name: dist
|
|
26
|
+
path: dist/
|
|
27
|
+
|
|
28
|
+
- name: Publish to PyPI
|
|
29
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
30
|
+
|
|
31
|
+
- name: Smoke test
|
|
32
|
+
run: |
|
|
33
|
+
PACKAGE=$(ls dist/*.whl | head -1 | xargs basename | sed 's/-[0-9].*//')
|
|
34
|
+
VERSION=$(ls dist/*.tar.gz | sed 's/.*-\(.*\)\.tar\.gz/\1/')
|
|
35
|
+
for i in {1..5}; do
|
|
36
|
+
pip install $PACKAGE==$VERSION && break
|
|
37
|
+
echo "Attempt $i failed, retrying in 10s..."
|
|
38
|
+
sleep 10
|
|
39
|
+
done
|
|
40
|
+
python -c "import $PACKAGE"
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
pip-wheel-metadata/
|
|
24
|
+
share/python-wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
MANIFEST
|
|
29
|
+
|
|
30
|
+
# PyInstaller
|
|
31
|
+
# Usually these files are written by a python script from a template
|
|
32
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
33
|
+
*.manifest
|
|
34
|
+
*.spec
|
|
35
|
+
|
|
36
|
+
# Installer logs
|
|
37
|
+
pip-log.txt
|
|
38
|
+
pip-delete-this-directory.txt
|
|
39
|
+
|
|
40
|
+
# Unit test / coverage reports
|
|
41
|
+
htmlcov/
|
|
42
|
+
.tox/
|
|
43
|
+
.nox/
|
|
44
|
+
.coverage
|
|
45
|
+
.coverage.*
|
|
46
|
+
.cache
|
|
47
|
+
nosetests.xml
|
|
48
|
+
coverage.xml
|
|
49
|
+
*.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
|
|
53
|
+
# Translations
|
|
54
|
+
*.mo
|
|
55
|
+
*.pot
|
|
56
|
+
|
|
57
|
+
# Django stuff:
|
|
58
|
+
*.log
|
|
59
|
+
local_settings.py
|
|
60
|
+
db.sqlite3
|
|
61
|
+
db.sqlite3-journal
|
|
62
|
+
|
|
63
|
+
# Flask stuff:
|
|
64
|
+
instance/
|
|
65
|
+
.webassets-cache
|
|
66
|
+
|
|
67
|
+
# Scrapy stuff:
|
|
68
|
+
.scrapy
|
|
69
|
+
|
|
70
|
+
# Sphinx documentation
|
|
71
|
+
docs/_build/
|
|
72
|
+
|
|
73
|
+
# PyBuilder
|
|
74
|
+
target/
|
|
75
|
+
|
|
76
|
+
# Jupyter Notebook
|
|
77
|
+
.ipynb_checkpoints
|
|
78
|
+
|
|
79
|
+
# IPython
|
|
80
|
+
profile_default/
|
|
81
|
+
ipython_config.py
|
|
82
|
+
|
|
83
|
+
# pyenv
|
|
84
|
+
.python-version
|
|
85
|
+
|
|
86
|
+
# pipenv
|
|
87
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
88
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
89
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
90
|
+
# install all needed dependencies.
|
|
91
|
+
#Pipfile.lock
|
|
92
|
+
|
|
93
|
+
# celery beat schedule file
|
|
94
|
+
celerybeat-schedule
|
|
95
|
+
|
|
96
|
+
# SageMath parsed files
|
|
97
|
+
*.sage.py
|
|
98
|
+
|
|
99
|
+
# Environments
|
|
100
|
+
.env
|
|
101
|
+
.venv
|
|
102
|
+
env/
|
|
103
|
+
venv/
|
|
104
|
+
ENV/
|
|
105
|
+
env.bak/
|
|
106
|
+
venv.bak/
|
|
107
|
+
|
|
108
|
+
# Spyder project settings
|
|
109
|
+
.spyderproject
|
|
110
|
+
.spyproject
|
|
111
|
+
|
|
112
|
+
# Rope project settings
|
|
113
|
+
.ropeproject
|
|
114
|
+
|
|
115
|
+
# mkdocs documentation
|
|
116
|
+
/site
|
|
117
|
+
|
|
118
|
+
# mypy
|
|
119
|
+
.mypy_cache/
|
|
120
|
+
.dmypy.json
|
|
121
|
+
dmypy.json
|
|
122
|
+
|
|
123
|
+
# Pyre type checker
|
|
124
|
+
.pyre/
|
|
125
|
+
|
|
126
|
+
# Worktrees
|
|
127
|
+
_worktrees/
|
|
128
|
+
|
|
129
|
+
# Session memory
|
|
130
|
+
memory/
|
|
131
|
+
|
|
132
|
+
# IDE
|
|
133
|
+
.idea/
|
|
134
|
+
|
|
135
|
+
# Claude Code
|
|
136
|
+
.claude/
|
|
137
|
+
_claude
|
|
138
|
+
|
|
139
|
+
# Repo dump
|
|
140
|
+
justin_utils.txt
|
|
141
|
+
.repokit
|
|
142
|
+
CLAUDE.local.md
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# CHANGELOG
|
|
2
|
+
|
|
3
|
+
<!-- version list -->
|
|
4
|
+
|
|
5
|
+
## v0.8.0 (2026-10-20)
|
|
6
|
+
|
|
7
|
+
### Refactoring
|
|
8
|
+
|
|
9
|
+
- Rename justin_utils to justkitten
|
|
10
|
+
([`a8e47d6`](https://github.com/djachenko/justkitten-py/commit/a8e47d62781bf00794c6f9472ec8a7fca5c0cc47))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## v0.7.0 (2026-10-15)
|
|
14
|
+
|
|
15
|
+
### Features
|
|
16
|
+
|
|
17
|
+
- Follow Codable semantics in dictable
|
|
18
|
+
([`fb7df96`](https://github.com/djachenko/justin_utils/commit/fb7df9675ca34652b2a5dd3f2d1e8c9ec629ce8a))
|
|
19
|
+
|
|
20
|
+
### Testing
|
|
21
|
+
|
|
22
|
+
- Pin dictable behaviors uncovered by mutation sweep
|
|
23
|
+
([`68824cc`](https://github.com/djachenko/justin_utils/commit/68824ccd325f68ebd0fd5f52ea0e860c6ddd5cf5))
|
|
24
|
+
|
|
25
|
+
### Breaking Changes
|
|
26
|
+
|
|
27
|
+
- Dictable.rules() is removed; pass rules to fromdict or from_dict instead. from_dict takes a rules
|
|
28
|
+
argument: from_dict(cls, json_object, rules=None).
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## v0.6.2 (2026-10-14)
|
|
32
|
+
|
|
33
|
+
### Refactoring
|
|
34
|
+
|
|
35
|
+
- Name fixture files once per test via local file_name
|
|
36
|
+
([`b887d65`](https://github.com/djachenko/justin_utils/commit/b887d65d0acd6dffe2976319b528fecd80b7e237))
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
## v0.6.1 (2026-10-14)
|
|
40
|
+
|
|
41
|
+
### Bug Fixes
|
|
42
|
+
|
|
43
|
+
- Parse nested plain dataclasses recursively in fromdict
|
|
44
|
+
([`76e0038`](https://github.com/djachenko/justin_utils/commit/76e00387fbbc373914a0a260227596128a98f4b1))
|
|
45
|
+
|
|
46
|
+
### Chores
|
|
47
|
+
|
|
48
|
+
- Mark json_migration classes as deprecated
|
|
49
|
+
([`9534664`](https://github.com/djachenko/justin_utils/commit/95346643d98e3daa82ea6f6336a870dbec506568))
|
|
50
|
+
|
|
51
|
+
### Refactoring
|
|
52
|
+
|
|
53
|
+
- Fix mypy errors in json_migration
|
|
54
|
+
([`1b0fd30`](https://github.com/djachenko/justin_utils/commit/1b0fd30e0f3197d017e23278754a75a2bc958124))
|
|
55
|
+
|
|
56
|
+
- Group type-based branches in _convert under one isinstance check
|
|
57
|
+
([`751c8a7`](https://github.com/djachenko/justin_utils/commit/751c8a702eb5164c22103f1677019f0b1124de52))
|
|
58
|
+
|
|
59
|
+
### Testing
|
|
60
|
+
|
|
61
|
+
- Nested dataclass keeps its own from_dict
|
|
62
|
+
([`14b22ac`](https://github.com/djachenko/justin_utils/commit/14b22acc6e27701e93bc8ba567491bfe82b24866))
|
|
63
|
+
|
|
64
|
+
- Remove duplicate test_scalar_coercion
|
|
65
|
+
([`2546206`](https://github.com/djachenko/justin_utils/commit/2546206ffa0c3c5dea96e2b811edbeb5a007e145))
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
## v0.6.0 (2026-10-08)
|
|
69
|
+
|
|
70
|
+
### Features
|
|
71
|
+
|
|
72
|
+
- Add create_files pytest fixture as a shareable plugin
|
|
73
|
+
([`917fbff`](https://github.com/djachenko/justin_utils/commit/917fbff7ee02ca2e452ea695bee2d8fceccde7d2))
|
|
74
|
+
|
|
75
|
+
### Refactoring
|
|
76
|
+
|
|
77
|
+
- Load create_files from justin_utils.testing in own tests
|
|
78
|
+
([`60bb8fc`](https://github.com/djachenko/justin_utils/commit/60bb8fc7645fd45a86b2f33d58029b7703fd2b97))
|
|
79
|
+
|
|
80
|
+
- Return Self from pylinq methods and drop quoted annotations
|
|
81
|
+
([`895c260`](https://github.com/djachenko/justin_utils/commit/895c260af22471cfedbfc86f61060f75cf71adbd))
|
|
82
|
+
|
|
83
|
+
- Return Self from the constructing classmethods
|
|
84
|
+
([`228d5c6`](https://github.com/djachenko/justin_utils/commit/228d5c6a183707aeb0fb5f5b6547d747ecc9e94d))
|
|
85
|
+
|
|
86
|
+
- Type pylinq and drop its mypy exemption
|
|
87
|
+
([`6676c35`](https://github.com/djachenko/justin_utils/commit/6676c35320a31fdd2e89126f3d7f0f7c6c45f125))
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
## v0.5.0 (2026-09-05)
|
|
91
|
+
|
|
92
|
+
### Build System
|
|
93
|
+
|
|
94
|
+
- Add py.typed marker
|
|
95
|
+
([`9fdef21`](https://github.com/djachenko/justin_utils/commit/9fdef214f4291865eaa40800ffa2889fa4941cc8))
|
|
96
|
+
|
|
97
|
+
### Chores
|
|
98
|
+
|
|
99
|
+
- Ignore the _claude symlink
|
|
100
|
+
([`5eac279`](https://github.com/djachenko/justin_utils/commit/5eac2798c7399501165d805bf2ee9e74bc02ef9e))
|
|
101
|
+
|
|
102
|
+
### Code Style
|
|
103
|
+
|
|
104
|
+
- Collapse the parametrize decorator
|
|
105
|
+
([`1ba68c3`](https://github.com/djachenko/justin_utils/commit/1ba68c3aa1d9d3175528b13f1c981884b1525afc))
|
|
106
|
+
|
|
107
|
+
### Features
|
|
108
|
+
|
|
109
|
+
- Report deserialization failures with DictableError
|
|
110
|
+
([`e128ff4`](https://github.com/djachenko/justin_utils/commit/e128ff40e00ee732799d423c5fd4a3cc7d240265))
|
|
111
|
+
|
|
112
|
+
### Refactoring
|
|
113
|
+
|
|
114
|
+
- Replace lambda defaults with named callables in pylinq
|
|
115
|
+
([`cd2bc3f`](https://github.com/djachenko/justin_utils/commit/cd2bc3f40c0313dc84ac9d4487049afe29aae898))
|
|
116
|
+
|
|
117
|
+
- Stop assuming every Dictable is a dataclass
|
|
118
|
+
([`2e6366e`](https://github.com/djachenko/justin_utils/commit/2e6366ee6cb05502eaff1950f70330551dd284f4))
|
|
119
|
+
|
|
120
|
+
### Testing
|
|
121
|
+
|
|
122
|
+
- Accept the windows error for reading a directory
|
|
123
|
+
([`ef4bcf3`](https://github.com/djachenko/justin_utils/commit/ef4bcf3b3333e15d7f883022526f435b031eff1a))
|
|
124
|
+
|
|
125
|
+
- Support binary files in the conftest file tree
|
|
126
|
+
([`9d2f49f`](https://github.com/djachenko/justin_utils/commit/9d2f49f6a50ceec9db1805ab9a5444ef2c6ca989))
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
## v0.4.1 (2026-09-05)
|
|
130
|
+
|
|
131
|
+
### Bug Fixes
|
|
132
|
+
|
|
133
|
+
- Raise AssertionError instead of assert False
|
|
134
|
+
([`6e0dc14`](https://github.com/djachenko/justin_utils/commit/6e0dc148b1bab63baa1266f1ea7dccdc2208275b))
|
|
135
|
+
|
|
136
|
+
- Raise meaningful exceptions instead of AssertionError
|
|
137
|
+
([`c6a6cd8`](https://github.com/djachenko/justin_utils/commit/c6a6cd893b6406cfd9e00d894d688b5df42065c4))
|
|
138
|
+
|
|
139
|
+
- Return None for a RAF with a truncated header
|
|
140
|
+
([`d347f81`](https://github.com/djachenko/justin_utils/commit/d347f814259b4fef9834a2ddc25e6c2e249d20c4))
|
|
141
|
+
|
|
142
|
+
### Chores
|
|
143
|
+
|
|
144
|
+
- Configure ruff lint rules and line length
|
|
145
|
+
([`5bde5ef`](https://github.com/djachenko/justin_utils/commit/5bde5ef93df21a3f0289c7f5a8596b0dd9fdbc0e))
|
|
146
|
+
|
|
147
|
+
### Code Style
|
|
148
|
+
|
|
149
|
+
- Apply ruff format
|
|
150
|
+
([`80c5a39`](https://github.com/djachenko/justin_utils/commit/80c5a39f2058757fa1670606f0d32af1885d8876))
|
|
151
|
+
|
|
152
|
+
- Drop the formatter, keep the linter
|
|
153
|
+
([`642e030`](https://github.com/djachenko/justin_utils/commit/642e0301081a95b09219ef63df93c858cdafbd6b))
|
|
154
|
+
|
|
155
|
+
- Preserve author quote style and keep exploded call sites
|
|
156
|
+
([`0d0de99`](https://github.com/djachenko/justin_utils/commit/0d0de99e8aafb218386c49f2b55b0242e58fe2e5))
|
|
157
|
+
|
|
158
|
+
### Refactoring
|
|
159
|
+
|
|
160
|
+
- Call the classmethod on type(self), not the instance
|
|
161
|
+
([`21cce05`](https://github.com/djachenko/justin_utils/commit/21cce05fff1e29e2e32a2152aaae5a60bf7fcfd4))
|
|
162
|
+
|
|
163
|
+
- Drop the decorative ABC from Singleton
|
|
164
|
+
([`70d5acc`](https://github.com/djachenko/justin_utils/commit/70d5accb93c80771da6a8af97fcb9e6df34290de))
|
|
165
|
+
|
|
166
|
+
- Drop two noqa directives by fixing their cause
|
|
167
|
+
([`84f88ca`](https://github.com/djachenko/justin_utils/commit/84f88cade2c8210fb056b27d8bc111347d73bc33))
|
|
168
|
+
|
|
169
|
+
- Fix ruff lint findings
|
|
170
|
+
([`517c6a7`](https://github.com/djachenko/justin_utils/commit/517c6a7e7acf1c868190d6d8cb9d162038458afc))
|
|
171
|
+
|
|
172
|
+
- Remove the unused TypeVar from singleton
|
|
173
|
+
([`07cb39c`](https://github.com/djachenko/justin_utils/commit/07cb39ce74255f0911e19e87df30460143e030e6))
|
|
174
|
+
|
|
175
|
+
- Return Self from constructing classmethods
|
|
176
|
+
([`9b19301`](https://github.com/djachenko/justin_utils/commit/9b193013045dc74c78a6d8e21870ab29a3792969))
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
## v0.4.0 (2026-08-19)
|
|
180
|
+
|
|
181
|
+
### Features
|
|
182
|
+
|
|
183
|
+
- Rewrite exif parsing with container abstraction and RAF support
|
|
184
|
+
([`556ac3c`](https://github.com/djachenko/justin_utils/commit/556ac3c390d745ff238df2211777ba99f5ae153e))
|
|
185
|
+
|
|
186
|
+
### Refactoring
|
|
187
|
+
|
|
188
|
+
- Make RAF magic and header offset class constants
|
|
189
|
+
([`32edf21`](https://github.com/djachenko/justin_utils/commit/32edf2113f37308412d36e11aaf1d2b1941f4e68))
|
|
190
|
+
|
|
191
|
+
- Narrow ImageSource to Path | IO[bytes], drop private PIL import
|
|
192
|
+
([`ac12695`](https://github.com/djachenko/justin_utils/commit/ac12695b2c6d24d44be9d4f296e11dae980fd667))
|
|
193
|
+
|
|
194
|
+
- Pass path to containers instead of a shared file handle
|
|
195
|
+
([`5dbf072`](https://github.com/djachenko/justin_utils/commit/5dbf072c1919bdf7ba0a6b4fbdf7285dc1131eae))
|
|
196
|
+
|
|
197
|
+
### Testing
|
|
198
|
+
|
|
199
|
+
- Extract raf container builder to drop duplicated header assembly
|
|
200
|
+
([`623c954`](https://github.com/djachenko/justin_utils/commit/623c954d3187fa76358eff43ab4c55c61b3163f9))
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
## v0.3.0 (2026-07-29)
|
|
204
|
+
|
|
205
|
+
### Chores
|
|
206
|
+
|
|
207
|
+
- Ignore CLAUDE.local.md
|
|
208
|
+
([`c24bde6`](https://github.com/djachenko/justin_utils/commit/c24bde6b075f3094e703a006bde09d26dc2ed3d7))
|
|
209
|
+
|
|
210
|
+
### Documentation
|
|
211
|
+
|
|
212
|
+
- Remove stale status and backlog from CLAUDE.md
|
|
213
|
+
([`ce127dd`](https://github.com/djachenko/justin_utils/commit/ce127dd96b96c900182605d1ba01e33d8bcbad40))
|
|
214
|
+
|
|
215
|
+
- Reorder modules section alphabetically, promote CLI tools
|
|
216
|
+
([`de7f0fc`](https://github.com/djachenko/justin_utils/commit/de7f0fcd68bf7968caed2d21c5c03d6a04b62e64))
|
|
217
|
+
|
|
218
|
+
### Features
|
|
219
|
+
|
|
220
|
+
- Add dictable module
|
|
221
|
+
([`ae0ee7c`](https://github.com/djachenko/justin_utils/commit/ae0ee7c0ef960e819d92f5722afc7ab7de1ea00c))
|
|
222
|
+
|
|
223
|
+
### Refactoring
|
|
224
|
+
|
|
225
|
+
- Remove frozendict dependency from dictable
|
|
226
|
+
([`7d8fb50`](https://github.com/djachenko/justin_utils/commit/7d8fb50bbc40892a2e707918f37806af0f2821f5))
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
## v0.2.3 (2026-07-29)
|
|
230
|
+
|
|
231
|
+
### Bug Fixes
|
|
232
|
+
|
|
233
|
+
- Add return type annotations for mypy --strict compliance
|
|
234
|
+
([`88af0ca`](https://github.com/djachenko/justin_utils/commit/88af0ca2b38363ca06e65797d5ae90926b7cbe66))
|
|
235
|
+
|
|
236
|
+
- Resolve ruff 0.16 violations (RUF012/013, C41x, UP028, B008, BLE001, PLR1722, DTZ, noqa)
|
|
237
|
+
([`0f2d878`](https://github.com/djachenko/justin_utils/commit/0f2d878cc08ea1fcf88d8d30aa56d75d54f02d46))
|
|
238
|
+
|
|
239
|
+
### Chores
|
|
240
|
+
|
|
241
|
+
- Pin ruff to >= 0.16, < 0.17
|
|
242
|
+
([`04157f0`](https://github.com/djachenko/justin_utils/commit/04157f0ea62cc2d790c319a041c4efe343540014))
|
|
243
|
+
|
|
244
|
+
### Code Style
|
|
245
|
+
|
|
246
|
+
- Apply ruff 0.16 auto-fixes (UP006/UP035, I001, C41x, B009)
|
|
247
|
+
([`91bf2d1`](https://github.com/djachenko/justin_utils/commit/91bf2d1af497b1b251a176cc339fc1bb3bcb6e4a))
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
## v0.2.2 (2026-06-30)
|
|
251
|
+
|
|
252
|
+
### Bug Fixes
|
|
253
|
+
|
|
254
|
+
- Allow None for metadata in ExternalMetadataSource type hint
|
|
255
|
+
([`eac8d77`](https://github.com/djachenko/justin_utils/commit/eac8d77efc69eefe7ebede1df76ebfb1aaca7b52))
|
|
256
|
+
|
|
257
|
+
### Chores
|
|
258
|
+
|
|
259
|
+
- Mark cli.py public classes as deprecated
|
|
260
|
+
([`00d95a7`](https://github.com/djachenko/justin_utils/commit/00d95a70ff0e3c0c9d97e11784992b63de8cbb49))
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
## v0.2.1 (2026-06-30)
|
|
264
|
+
|
|
265
|
+
### Bug Fixes
|
|
266
|
+
|
|
267
|
+
- DataSize.Unit.for_value off-by-one at exact unit boundaries
|
|
268
|
+
([`051f730`](https://github.com/djachenko/justin_utils/commit/051f730e969643beb539e7c9f87497794658a629))
|
|
269
|
+
|
|
270
|
+
- Remove now-empty source folder after renumber single-part flatten
|
|
271
|
+
([`04ffb38`](https://github.com/djachenko/justin_utils/commit/04ffb38514a55b1db8bf1ec1f71c93abc601d8b0))
|
|
272
|
+
|
|
273
|
+
### Code Style
|
|
274
|
+
|
|
275
|
+
- Add type hints to _run() in test_subfolder.py
|
|
276
|
+
([`9710541`](https://github.com/djachenko/justin_utils/commit/97105418b511bfce410e14f31db77e39c4cfd3b2))
|
|
277
|
+
|
|
278
|
+
- Blank line after first statement in _RecordingAction.__init__
|
|
279
|
+
([`27a4a5d`](https://github.com/djachenko/justin_utils/commit/27a4a5d645e522d2dba5f75200faf7d79b31cd6e))
|
|
280
|
+
|
|
281
|
+
- Type the recursive file-tree structure instead of bare dict
|
|
282
|
+
([`54f2d83`](https://github.com/djachenko/justin_utils/commit/54f2d83b0d9d9f5785c5d957d53b645b1ed2035f))
|
|
283
|
+
|
|
284
|
+
- Unify exception-test naming to _raises suffix
|
|
285
|
+
([`39f0553`](https://github.com/djachenko/justin_utils/commit/39f055376574c436135e531dde26127a85a5a275))
|
|
286
|
+
|
|
287
|
+
- Use collections.abc.Iterable and lowercase list[] in test_cli.py
|
|
288
|
+
([`1a83dbe`](https://github.com/djachenko/justin_utils/commit/1a83dbed078ee8ead8d93735cfb7cb5fc4bea0e1))
|
|
289
|
+
|
|
290
|
+
### Testing
|
|
291
|
+
|
|
292
|
+
- Add coverage for subfolder.py, fix mypy typing in test_cli.py
|
|
293
|
+
([`0c59307`](https://github.com/djachenko/justin_utils/commit/0c5930766742d08bccf3f7332f7a309ad1af7f56))
|
|
294
|
+
|
|
295
|
+
- Assert correct behavior for unit boundaries and renumber cleanup (red)
|
|
296
|
+
([`a6d4d14`](https://github.com/djachenko/justin_utils/commit/a6d4d14c95f9119023a67da0ac44ab957d3b8cfa))
|
|
297
|
+
|
|
298
|
+
- Cover case-insensitive extension matching in parse_sources
|
|
299
|
+
([`2ec5538`](https://github.com/djachenko/justin_utils/commit/2ec55380dd862f8e10f07bc3f9076568fd2f47d5))
|
|
300
|
+
|
|
301
|
+
- Deduplicate repeated string literals into single source of truth
|
|
302
|
+
([`2de5092`](https://github.com/djachenko/justin_utils/commit/2de5092688b1343ef1131061b1dfea84617a6921))
|
|
303
|
+
|
|
304
|
+
- Fix DataSpeed.formatted boundary test missed in previous audit
|
|
305
|
+
([`271cbd1`](https://github.com/djachenko/justin_utils/commit/271cbd1b8517e3b938903d00d2aaa2cdb0bdc11e))
|
|
306
|
+
|
|
307
|
+
- Fold case-insensitivity into existing parse_sources parametrize instead of new tests
|
|
308
|
+
([`d2d5eef`](https://github.com/djachenko/justin_utils/commit/d2d5eef388b36cb5aaabf0e877d5253f5cbfacf2))
|
|
309
|
+
|
|
310
|
+
- Fold duplicate-shaped tests into parametrize across the suite
|
|
311
|
+
([`fb7fcf6`](https://github.com/djachenko/justin_utils/commit/fb7fcf6f3405e9184655909d3d1e52d6bb528bed))
|
|
312
|
+
|
|
313
|
+
- Refactor test_parts.py to class+parametrize style
|
|
314
|
+
([`a94bde9`](https://github.com/djachenko/justin_utils/commit/a94bde9543ffcd34ad916a3043e646939ac5cd17))
|
|
315
|
+
|
|
316
|
+
- Use cross-product parametrize for extension-case combinations
|
|
317
|
+
([`bf6139d`](https://github.com/djachenko/justin_utils/commit/bf6139d5680712d61eac1b3042e47c46a53b892e))
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
## v0.2.0 (2026-06-30)
|
|
321
|
+
|
|
322
|
+
### Bug Fixes
|
|
323
|
+
|
|
324
|
+
- Clean up leftover temp folder in dump_in_temp
|
|
325
|
+
([`4565292`](https://github.com/djachenko/justin_utils/commit/4565292cebbe4a227d464031fabeb22b6b8bd5cc))
|
|
326
|
+
|
|
327
|
+
### Features
|
|
328
|
+
|
|
329
|
+
- Migrate parts CLI from argparse to Typer
|
|
330
|
+
([`2a5cf62`](https://github.com/djachenko/justin_utils/commit/2a5cf626f902f38274f077fa8048ba54210cb8b5))
|
|
331
|
+
|
|
332
|
+
### Testing
|
|
333
|
+
|
|
334
|
+
- Add tests for parts.py Typer CLI
|
|
335
|
+
([`cf850f8`](https://github.com/djachenko/justin_utils/commit/cf850f8be5c41bca85ec564423df89d0405b8e9c))
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
## v0.1.2 (2026-06-30)
|
|
339
|
+
|
|
340
|
+
### Bug Fixes
|
|
341
|
+
|
|
342
|
+
- Add path setter on FolderBased and drop unused pytest imports
|
|
343
|
+
([`983609c`](https://github.com/djachenko/justin_utils/commit/983609cda8deff699e9300003f41359835a26ac2))
|
|
344
|
+
|
|
345
|
+
- Folder.merge_into path update and __get_by_path single-component lookup
|
|
346
|
+
([`8ea2d62`](https://github.com/djachenko/justin_utils/commit/8ea2d62127c728e945071d657b9a5ceea68d09a5))
|
|
347
|
+
|
|
348
|
+
- Support Linux in __get_mount
|
|
349
|
+
([`e9ad807`](https://github.com/djachenko/justin_utils/commit/e9ad807f3b6b2a09742b32c3bf4a819bbcc7e2e3))
|
|
350
|
+
|
|
351
|
+
### Chores
|
|
352
|
+
|
|
353
|
+
- Add _worktrees/ to gitignore
|
|
354
|
+
([`8abfe6e`](https://github.com/djachenko/justin_utils/commit/8abfe6eeed64e90c16c7df042a51a46f8d45a5a5))
|
|
355
|
+
|
|
356
|
+
- Mark FolderBased as deprecated
|
|
357
|
+
([`6ddb233`](https://github.com/djachenko/justin_utils/commit/6ddb2332e9564eb7dd7a1aadf6aafc727138c871))
|
|
358
|
+
|
|
359
|
+
### Testing
|
|
360
|
+
|
|
361
|
+
- Add pytest suite for backlog bugs
|
|
362
|
+
([`3255843`](https://github.com/djachenko/justin_utils/commit/325584380b18522e9c02b4bd72a9620f2781d2eb))
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
## v0.1.1 (2026-06-27)
|
|
366
|
+
|
|
367
|
+
### Bug Fixes
|
|
368
|
+
|
|
369
|
+
- Add assertions for mypy in TransferSpeedMeter
|
|
370
|
+
([`9abdfe2`](https://github.com/djachenko/justin_utils/commit/9abdfe22253af2e2ee4ae0d30cfd8db0d414c0f5))
|
|
371
|
+
|
|
372
|
+
- Copy() no longer removes source tree on cross-drive copy
|
|
373
|
+
([`92e2d89`](https://github.com/djachenko/justin_utils/commit/92e2d893814a4c7d3c2ab7605330a034322e8620))
|
|
374
|
+
|
|
375
|
+
- Correct null checks in joins
|
|
376
|
+
([`d7ab2f5`](https://github.com/djachenko/justin_utils/commit/d7ab2f52fb64f7f1462940003b8f45d31f7be74d))
|
|
377
|
+
|
|
378
|
+
- Correct parse_date year logic for 4-digit years
|
|
379
|
+
([`cf7e703`](https://github.com/djachenko/justin_utils/commit/cf7e703c376cd7233c0f729961cde2cc50d07086))
|
|
380
|
+
|
|
381
|
+
- Make Exif.from_path abstract, Action inherit ABC
|
|
382
|
+
([`34d8cdc`](https://github.com/djachenko/justin_utils/commit/34d8cdcf2b4ca665474f27d69fc887d832e3cfec))
|
|
383
|
+
|
|
384
|
+
- Replace @property @cache with @cached_property
|
|
385
|
+
([`b07b020`](https://github.com/djachenko/justin_utils/commit/b07b020a4e49033a7f314a3b4b9acb1038a3bcb9))
|
|
386
|
+
|
|
387
|
+
### Chores
|
|
388
|
+
|
|
389
|
+
- [repokit] update ci workflows
|
|
390
|
+
([`0f1b1e5`](https://github.com/djachenko/justin_utils/commit/0f1b1e5ffde4b03d140b724d5b5eae327a2208f2))
|
|
391
|
+
|
|
392
|
+
- Bump minimum Python to 3.11, drop typing_extensions
|
|
393
|
+
([`284ff9c`](https://github.com/djachenko/justin_utils/commit/284ff9c0a682d835df67d64ba4c38283ea015fa9))
|
|
394
|
+
|
|
395
|
+
### Documentation
|
|
396
|
+
|
|
397
|
+
- Rewrite README
|
|
398
|
+
([`d898e99`](https://github.com/djachenko/justin_utils/commit/d898e999d1f9b5dab6015e3c24fa907903e09df7))
|
|
399
|
+
|
|
400
|
+
### Refactoring
|
|
401
|
+
|
|
402
|
+
- Expand ternary operators
|
|
403
|
+
([`37dede3`](https://github.com/djachenko/justin_utils/commit/37dede3c36407b2602971198255eda117b5236c3))
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
## v0.1.0 (2026-06-25)
|
|
407
|
+
|
|
408
|
+
- Initial Release
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# justkitten — Project Guide
|
|
2
|
+
|
|
3
|
+
## Что это
|
|
4
|
+
|
|
5
|
+
Общие утилиты Python-экосистемы. Библиотека без зависимостей, которую можно установить отдельно и использовать в любом проекте экосистемы.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Место в экосистеме
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
justin ──→ justkitten
|
|
13
|
+
pyvko ──→ justkitten (планируется)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Цель: вобрать весь переиспользуемый код из `justin` и `pyvko`, чтобы шарить между проектами без лишних зависимостей.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Текущие модули
|
|
21
|
+
|
|
22
|
+
| Модуль | Содержимое |
|
|
23
|
+
|--------|------------|
|
|
24
|
+
| `filesystem.py` | `Folder`, `File` — обёртки над `Path` с удобным доступом к подпапкам |
|
|
25
|
+
| `parts.py` | CLI-утилита `parts` |
|
|
26
|
+
| `subfolder.py` | CLI-утилита `sf` |
|
|
27
|
+
| `transfer.py` | `TransferSpeedMeter`, `TransferTimeEstimator` |
|
|
28
|
+
| `time_formatter.py` | Форматирование времени |
|
|
29
|
+
| `data.py` | `DataSize` |
|
|
30
|
+
| `dictable.py` | `Dictable`, `DictableDataclass`, `fromdict` — десериализация JSON в датаклассы |
|
|
31
|
+
| `exif.py` | EXIF-утилиты |
|
|
32
|
+
| `singleton.py` | Singleton паттерн |
|
|
33
|
+
| `joins.py`, `pylinq.py` | LINQ-подобные операции над коллекциями |
|
|
34
|
+
| `json_migration.py` | Утилиты для JSON-миграций |
|
|
35
|
+
| `testing.py` | pytest-плагин с фикстурой `create_files`; подключается через `pytest_plugins`, extra `testing` |
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Git
|
|
40
|
+
|
|
41
|
+
Semantic commits: `feat:`, `fix:`, `refactor:`, `chore:`
|