yd-cli 0.3__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.
- yd_cli-0.3/LICENSES/MIT.txt +9 -0
- yd_cli-0.3/PKG-INFO +132 -0
- yd_cli-0.3/README.md +109 -0
- yd_cli-0.3/pyproject.toml +198 -0
- yd_cli-0.3/src/yd/__init__.py +30 -0
- yd_cli-0.3/src/yd/__main__.py +11 -0
- yd_cli-0.3/src/yd/cli.py +484 -0
- yd_cli-0.3/src/yd/commands.py +255 -0
- yd_cli-0.3/src/yd/execution.py +153 -0
- yd_cli-0.3/src/yd/io.py +200 -0
- yd_cli-0.3/src/yd/py.typed +0 -0
- yd_cli-0.3/src/yd/types.py +159 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright 2026 Christian Heinze
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
yd_cli-0.3/PKG-INFO
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: yd-cli
|
|
3
|
+
Version: 0.3
|
|
4
|
+
Summary: CLI tool to synchronize directories using rsync.
|
|
5
|
+
Author: Christian Heinze
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSES/MIT.txt
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
14
|
+
Classifier: Topic :: System :: Archiving
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Classifier: Typing :: Typed
|
|
17
|
+
Requires-Dist: msgspec>=0.20
|
|
18
|
+
Requires-Dist: rich>=14.3
|
|
19
|
+
Requires-Dist: typer>=0.24
|
|
20
|
+
Requires-Python: >=3.14
|
|
21
|
+
Project-URL: Repository, https://codeberg.org/christianheinze/syf
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Directory synchronization tool `yd`
|
|
25
|
+
|
|
26
|
+
Build and execute `rsync` commands from *TOML* configuration files.
|
|
27
|
+
|
|
28
|
+
## Create a config
|
|
29
|
+
|
|
30
|
+
Create a new configuration called `photos` with:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
yd edit --new photos
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This command
|
|
37
|
+
|
|
38
|
+
- creates `~/.config/yd/photos.toml` (or under `$XDG_CONFIG_HOME/yd` if set; relative paths are resolved from your home directory), and
|
|
39
|
+
- opens it in the editor selected via `EDITOR`.
|
|
40
|
+
|
|
41
|
+
Reopen an existing configuration with:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
yd edit photos
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Configuration format
|
|
48
|
+
|
|
49
|
+
### Example
|
|
50
|
+
|
|
51
|
+
```toml
|
|
52
|
+
# Phone backup
|
|
53
|
+
src_home = "/home/alice"
|
|
54
|
+
target_home = "/mnt/backup"
|
|
55
|
+
backup = "deleted/%Y-%m-%d"
|
|
56
|
+
exclude = [".venv/", "__pycache__/"]
|
|
57
|
+
|
|
58
|
+
[[commands]]
|
|
59
|
+
src = "Documents"
|
|
60
|
+
exclude = ["*.log"]
|
|
61
|
+
|
|
62
|
+
[[commands]]
|
|
63
|
+
src = "Pictures"
|
|
64
|
+
target = "pics-%Y-%m-%d"
|
|
65
|
+
delete_extra = false
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Leading comment lines directly at the top of the file are treated as the configuration description and are shown by `yd ls`.
|
|
69
|
+
|
|
70
|
+
### Top-level options
|
|
71
|
+
|
|
72
|
+
| Key | Meaning |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `src_home` | Base directory for all `src` paths. Relative paths are resolved from your home directory. |
|
|
75
|
+
| `target_home` | Base directory for all target paths. Relative paths are resolved from your home directory. `strftime` placeholders such as `%Y-%m-%d` are supported. |
|
|
76
|
+
| `mtp_target` | Use in-place syncing for MTP targets. |
|
|
77
|
+
| `backup` | Backup directory for replaced or deleted files. Relative paths are resolved from `target_home`. `strftime` placeholders are supported. |
|
|
78
|
+
| `exclude` | Exclude patterns applied to every command. |
|
|
79
|
+
|
|
80
|
+
`mtp_target` matters because `rsync` normally copies to a temporary file and renames it afterward, but that is not possible when syncing via *MTP*.
|
|
81
|
+
|
|
82
|
+
### Command options
|
|
83
|
+
|
|
84
|
+
| Key | Meaning |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `src` | Relative source directory below `src_home`. |
|
|
87
|
+
| `target` | Relative target directory below `target_home`; defaults to `src`. `strftime` placeholders are supported. |
|
|
88
|
+
| `delete_extra` | Delete files in the target that do not exist in the source. Defaults to `true`. |
|
|
89
|
+
| `exclude` | Extra exclude patterns for this command only. |
|
|
90
|
+
|
|
91
|
+
### Notes
|
|
92
|
+
|
|
93
|
+
- `src` and `target` must stay within `src_home` and `target_home` after path resolution.
|
|
94
|
+
- `src_home` or `target_home` may be omitted from the configuration, but every missing value must then be supplied when running (via CLI parameters).
|
|
95
|
+
- Exactly one of `--src-home -` and `--target-home -` may read from standard input in a single run.
|
|
96
|
+
- If `backup` is omitted, `yd` creates a timestamped backup directory automatically unless `--no-backup` is specified.
|
|
97
|
+
- If a configured source directory exists but is empty, `yd` reports that no synchronization was performed for that command. E.g., forgetting to mount an external drive does not delete all corresponding copies on harddrive).
|
|
98
|
+
|
|
99
|
+
## Run a config
|
|
100
|
+
|
|
101
|
+
Run a saved configuration by name:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
yd run photos
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Options
|
|
108
|
+
|
|
109
|
+
| Option | Meaning |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| `--dry-run` | Show what would happen without changing files. |
|
|
112
|
+
| `--no-backup` | Disable backup handling for this run. |
|
|
113
|
+
| `--keep-newer` | Skip updates when the target file is newer. |
|
|
114
|
+
| `--rename-speedup` | Enable `rsync` options tuned for rename-heavy targets. This may require more disk space on the target. |
|
|
115
|
+
| `--src-home PATH` | Override `src_home` from the config. Use `-` to read the value from standard input. |
|
|
116
|
+
| `--target-home PATH` | Override `target_home` from the config. Use `-` to read the value from standard input. |
|
|
117
|
+
|
|
118
|
+
## List configs
|
|
119
|
+
|
|
120
|
+
List available configurations with:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
yd ls
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
This shows the configuration name together with the optional leading-comment description.
|
|
127
|
+
|
|
128
|
+
## Why `yd`?
|
|
129
|
+
|
|
130
|
+
- Has one character from `synchronize` and one from `directory`.
|
|
131
|
+
- Easy to type with both *QWERTZ* and *QUERTY* keyboards.
|
|
132
|
+
- Name was still available on *PyPI*.
|
yd_cli-0.3/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Directory synchronization tool `yd`
|
|
2
|
+
|
|
3
|
+
Build and execute `rsync` commands from *TOML* configuration files.
|
|
4
|
+
|
|
5
|
+
## Create a config
|
|
6
|
+
|
|
7
|
+
Create a new configuration called `photos` with:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
yd edit --new photos
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This command
|
|
14
|
+
|
|
15
|
+
- creates `~/.config/yd/photos.toml` (or under `$XDG_CONFIG_HOME/yd` if set; relative paths are resolved from your home directory), and
|
|
16
|
+
- opens it in the editor selected via `EDITOR`.
|
|
17
|
+
|
|
18
|
+
Reopen an existing configuration with:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
yd edit photos
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Configuration format
|
|
25
|
+
|
|
26
|
+
### Example
|
|
27
|
+
|
|
28
|
+
```toml
|
|
29
|
+
# Phone backup
|
|
30
|
+
src_home = "/home/alice"
|
|
31
|
+
target_home = "/mnt/backup"
|
|
32
|
+
backup = "deleted/%Y-%m-%d"
|
|
33
|
+
exclude = [".venv/", "__pycache__/"]
|
|
34
|
+
|
|
35
|
+
[[commands]]
|
|
36
|
+
src = "Documents"
|
|
37
|
+
exclude = ["*.log"]
|
|
38
|
+
|
|
39
|
+
[[commands]]
|
|
40
|
+
src = "Pictures"
|
|
41
|
+
target = "pics-%Y-%m-%d"
|
|
42
|
+
delete_extra = false
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Leading comment lines directly at the top of the file are treated as the configuration description and are shown by `yd ls`.
|
|
46
|
+
|
|
47
|
+
### Top-level options
|
|
48
|
+
|
|
49
|
+
| Key | Meaning |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| `src_home` | Base directory for all `src` paths. Relative paths are resolved from your home directory. |
|
|
52
|
+
| `target_home` | Base directory for all target paths. Relative paths are resolved from your home directory. `strftime` placeholders such as `%Y-%m-%d` are supported. |
|
|
53
|
+
| `mtp_target` | Use in-place syncing for MTP targets. |
|
|
54
|
+
| `backup` | Backup directory for replaced or deleted files. Relative paths are resolved from `target_home`. `strftime` placeholders are supported. |
|
|
55
|
+
| `exclude` | Exclude patterns applied to every command. |
|
|
56
|
+
|
|
57
|
+
`mtp_target` matters because `rsync` normally copies to a temporary file and renames it afterward, but that is not possible when syncing via *MTP*.
|
|
58
|
+
|
|
59
|
+
### Command options
|
|
60
|
+
|
|
61
|
+
| Key | Meaning |
|
|
62
|
+
| --- | --- |
|
|
63
|
+
| `src` | Relative source directory below `src_home`. |
|
|
64
|
+
| `target` | Relative target directory below `target_home`; defaults to `src`. `strftime` placeholders are supported. |
|
|
65
|
+
| `delete_extra` | Delete files in the target that do not exist in the source. Defaults to `true`. |
|
|
66
|
+
| `exclude` | Extra exclude patterns for this command only. |
|
|
67
|
+
|
|
68
|
+
### Notes
|
|
69
|
+
|
|
70
|
+
- `src` and `target` must stay within `src_home` and `target_home` after path resolution.
|
|
71
|
+
- `src_home` or `target_home` may be omitted from the configuration, but every missing value must then be supplied when running (via CLI parameters).
|
|
72
|
+
- Exactly one of `--src-home -` and `--target-home -` may read from standard input in a single run.
|
|
73
|
+
- If `backup` is omitted, `yd` creates a timestamped backup directory automatically unless `--no-backup` is specified.
|
|
74
|
+
- If a configured source directory exists but is empty, `yd` reports that no synchronization was performed for that command. E.g., forgetting to mount an external drive does not delete all corresponding copies on harddrive).
|
|
75
|
+
|
|
76
|
+
## Run a config
|
|
77
|
+
|
|
78
|
+
Run a saved configuration by name:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
yd run photos
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Options
|
|
85
|
+
|
|
86
|
+
| Option | Meaning |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| `--dry-run` | Show what would happen without changing files. |
|
|
89
|
+
| `--no-backup` | Disable backup handling for this run. |
|
|
90
|
+
| `--keep-newer` | Skip updates when the target file is newer. |
|
|
91
|
+
| `--rename-speedup` | Enable `rsync` options tuned for rename-heavy targets. This may require more disk space on the target. |
|
|
92
|
+
| `--src-home PATH` | Override `src_home` from the config. Use `-` to read the value from standard input. |
|
|
93
|
+
| `--target-home PATH` | Override `target_home` from the config. Use `-` to read the value from standard input. |
|
|
94
|
+
|
|
95
|
+
## List configs
|
|
96
|
+
|
|
97
|
+
List available configurations with:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
yd ls
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
This shows the configuration name together with the optional leading-comment description.
|
|
104
|
+
|
|
105
|
+
## Why `yd`?
|
|
106
|
+
|
|
107
|
+
- Has one character from `synchronize` and one from `directory`.
|
|
108
|
+
- Easy to type with both *QWERTZ* and *QUERTY* keyboards.
|
|
109
|
+
- Name was still available on *PyPI*.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
build-backend = "uv_build"
|
|
3
|
+
requires = [ "uv-build>=0.10,<0.12" ]
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "yd-cli"
|
|
7
|
+
version = "0.3"
|
|
8
|
+
description = "CLI tool to synchronize directories using rsync."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = [ "LICENSES/MIT.txt" ]
|
|
12
|
+
authors = [ { name = "Christian Heinze" } ]
|
|
13
|
+
requires-python = ">=3.14"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Environment :: Console",
|
|
17
|
+
"Intended Audience :: End Users/Desktop",
|
|
18
|
+
"Operating System :: POSIX :: Linux",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Programming Language :: Python :: 3.14",
|
|
21
|
+
"Topic :: System :: Archiving",
|
|
22
|
+
"Topic :: Utilities",
|
|
23
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"msgspec>=0.20",
|
|
27
|
+
"rich>=14.3",
|
|
28
|
+
"typer>=0.24",
|
|
29
|
+
]
|
|
30
|
+
urls.Repository = "https://codeberg.org/christianheinze/syf"
|
|
31
|
+
scripts.yd = "yd.cli:app"
|
|
32
|
+
|
|
33
|
+
[dependency-groups]
|
|
34
|
+
dev = [
|
|
35
|
+
"ipython>9",
|
|
36
|
+
{ include-group = "format" },
|
|
37
|
+
{ include-group = "lint" },
|
|
38
|
+
{ include-group = "test" },
|
|
39
|
+
]
|
|
40
|
+
test = [
|
|
41
|
+
# pytest-asyncio does not support pytest>=9 yet.
|
|
42
|
+
"pytest>=9",
|
|
43
|
+
"pytest-asyncio>=1.3",
|
|
44
|
+
"pytest-cov>=7",
|
|
45
|
+
"pytest-randomly>=4",
|
|
46
|
+
]
|
|
47
|
+
format = [
|
|
48
|
+
"mdformat>=1",
|
|
49
|
+
"mdformat-ruff>=0.1.3",
|
|
50
|
+
"pyproject-fmt>=2.11",
|
|
51
|
+
"ruff>=0.15.8",
|
|
52
|
+
]
|
|
53
|
+
lint = [
|
|
54
|
+
"ruff>=0.15.8",
|
|
55
|
+
"ty>=0.0.27",
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
[tool.uv]
|
|
59
|
+
# Suggestion from https://mkennedy.codes/posts/python-supply-chain-security-made-easy/
|
|
60
|
+
build-backend.exclude-newer = "72 hours"
|
|
61
|
+
build-backend.module-name = "yd"
|
|
62
|
+
|
|
63
|
+
[[tool.uv.index]]
|
|
64
|
+
name = "testpypi"
|
|
65
|
+
url = "https://test.pypi.org/simple/"
|
|
66
|
+
publish-url = "https://test.pypi.org/legacy/"
|
|
67
|
+
explicit = true
|
|
68
|
+
|
|
69
|
+
[tool.ruff]
|
|
70
|
+
respect-gitignore = false
|
|
71
|
+
fix = false
|
|
72
|
+
unsafe-fixes = false
|
|
73
|
+
format.line-ending = "lf"
|
|
74
|
+
lint.select = [
|
|
75
|
+
"A", # Builtin shadowing
|
|
76
|
+
"ANN", # Type annotations
|
|
77
|
+
"ARG", # Unused arguments
|
|
78
|
+
"ASYNC", # Async
|
|
79
|
+
"B", # Common sources of bugs
|
|
80
|
+
"C4", # Comprehensions
|
|
81
|
+
"COM", # Trailing comma issues
|
|
82
|
+
"D", # Docstrings
|
|
83
|
+
"E", # pycodestyle
|
|
84
|
+
"ERA", # Commented-out code
|
|
85
|
+
"F", # pyflakes
|
|
86
|
+
"FURB", # General stylistic improvements
|
|
87
|
+
"G", # Logging string format
|
|
88
|
+
"I", # Imports
|
|
89
|
+
"ICN", # Import conventions
|
|
90
|
+
"INP", # No namespace packages
|
|
91
|
+
"LOG", # Logging
|
|
92
|
+
"N", # PEP8 naming
|
|
93
|
+
"PERF", # Performance issues.
|
|
94
|
+
"PGH", # Too unspecific checking excludes
|
|
95
|
+
"PIE",
|
|
96
|
+
"PL", # pylint
|
|
97
|
+
"PT", # pytest
|
|
98
|
+
"PTH", # Enfore pathlib use
|
|
99
|
+
"PYI",
|
|
100
|
+
"Q", # Quotes
|
|
101
|
+
"RET", # Return values
|
|
102
|
+
"RSE", # Exception style
|
|
103
|
+
"RUF", # Ruff-specific rules
|
|
104
|
+
"S", # Security
|
|
105
|
+
"SIM", # Simplifications
|
|
106
|
+
"SLF", # Private member access
|
|
107
|
+
"SLOT", # Slots requirements
|
|
108
|
+
"T10", # Debugger used
|
|
109
|
+
"TC", # Typing
|
|
110
|
+
"TCH", # TYPE_CHECKING sections
|
|
111
|
+
"TID", # Good import practices
|
|
112
|
+
"UP", # pyupgrade
|
|
113
|
+
"W",
|
|
114
|
+
"YTT",
|
|
115
|
+
]
|
|
116
|
+
lint.ignore = [
|
|
117
|
+
# Any allowed.
|
|
118
|
+
"ANN401",
|
|
119
|
+
"COM812",
|
|
120
|
+
"COM819",
|
|
121
|
+
# Missing documentation allowed.
|
|
122
|
+
"D100",
|
|
123
|
+
"D101",
|
|
124
|
+
"D102",
|
|
125
|
+
"D103",
|
|
126
|
+
"D104",
|
|
127
|
+
"D105",
|
|
128
|
+
"D106",
|
|
129
|
+
"D107",
|
|
130
|
+
# No empty lines before docstrings.
|
|
131
|
+
"D203",
|
|
132
|
+
"D206",
|
|
133
|
+
"D213",
|
|
134
|
+
"D300",
|
|
135
|
+
# No empty line after final section of docstring.
|
|
136
|
+
"D413",
|
|
137
|
+
# Undocumented parameters allowed.
|
|
138
|
+
"D417",
|
|
139
|
+
"E111",
|
|
140
|
+
"E114",
|
|
141
|
+
"E117",
|
|
142
|
+
"ISC001",
|
|
143
|
+
"ISC002",
|
|
144
|
+
# Complex code allowed.
|
|
145
|
+
"PLR0911",
|
|
146
|
+
"PLR0912",
|
|
147
|
+
"PLR0913",
|
|
148
|
+
# Comparison with hardcoded literals allowed.
|
|
149
|
+
"PLR2004",
|
|
150
|
+
"Q000",
|
|
151
|
+
"Q001",
|
|
152
|
+
"Q002",
|
|
153
|
+
"Q003",
|
|
154
|
+
# `__all__` needs not be sorted.
|
|
155
|
+
"RUF022",
|
|
156
|
+
# assert statements allowed.
|
|
157
|
+
"S101",
|
|
158
|
+
# pseudo random number warning.
|
|
159
|
+
"S311",
|
|
160
|
+
# shell parameter not required in subprocess calls.
|
|
161
|
+
"S603",
|
|
162
|
+
"S604",
|
|
163
|
+
# Should not be using when using ruff formatter
|
|
164
|
+
"W191",
|
|
165
|
+
]
|
|
166
|
+
lint.flake8-tidy-imports.ban-relative-imports = "all"
|
|
167
|
+
lint.flake8-type-checking.runtime-evaluated-base-classes = [
|
|
168
|
+
"pydantic.BaseModel",
|
|
169
|
+
]
|
|
170
|
+
lint.flake8-type-checking.runtime-evaluated-decorators = [
|
|
171
|
+
"pydantic.validate_call",
|
|
172
|
+
]
|
|
173
|
+
lint.flake8-unused-arguments.ignore-variadic-names = true
|
|
174
|
+
lint.isort.required-imports = [ "from __future__ import annotations" ]
|
|
175
|
+
|
|
176
|
+
[tool.pyproject-fmt]
|
|
177
|
+
column_width = 88
|
|
178
|
+
indent = 4
|
|
179
|
+
max_supported_python = "3.14"
|
|
180
|
+
|
|
181
|
+
[tool.ty]
|
|
182
|
+
environment.python-platform = "linux"
|
|
183
|
+
environment.root = [ "src/" ]
|
|
184
|
+
src.include = [ "src/", "tests/" ]
|
|
185
|
+
src.respect-ignore-files = false
|
|
186
|
+
|
|
187
|
+
[tool.pytest]
|
|
188
|
+
minversion = "9.0"
|
|
189
|
+
addopts = [
|
|
190
|
+
"--import-mode=importlib",
|
|
191
|
+
"--strict-markers",
|
|
192
|
+
"--cov=yd",
|
|
193
|
+
"--cov=tests",
|
|
194
|
+
]
|
|
195
|
+
testpaths = [ "tests" ]
|
|
196
|
+
python_files = [ "test_*.py" ]
|
|
197
|
+
filterwarnings = [ "error" ]
|
|
198
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: Christian Heinze
|
|
2
|
+
#
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""The yd synchronization tool.
|
|
5
|
+
|
|
6
|
+
Do not directly import items from this module (e.g. `from yd import io`) which
|
|
7
|
+
triggers `__getattr__` and thereby eager importing of the module. Instead, import
|
|
8
|
+
`yd` and use attribute access.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import importlib
|
|
14
|
+
import importlib.metadata
|
|
15
|
+
|
|
16
|
+
TYPE_CHECKING = False
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from types import ModuleType
|
|
19
|
+
|
|
20
|
+
from yd import commands, execution, io, types
|
|
21
|
+
else:
|
|
22
|
+
|
|
23
|
+
def __getattr__(key: str, /) -> ModuleType:
|
|
24
|
+
if key in __all__:
|
|
25
|
+
return importlib.import_module(f"{__package__}.{key}", package=__package__)
|
|
26
|
+
raise AttributeError(f"module `{__name__}` has not attribute `{key}`")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
__version__ = importlib.metadata.version("yd-cli")
|
|
30
|
+
__all__ = ["__version__", "commands", "io", "execution", "types"]
|