fspachinko 0.0.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.
Files changed (55) hide show
  1. fspachinko-0.0.2/LICENSE +21 -0
  2. fspachinko-0.0.2/PKG-INFO +322 -0
  3. fspachinko-0.0.2/README.md +304 -0
  4. fspachinko-0.0.2/pyproject.toml +48 -0
  5. fspachinko-0.0.2/src/fspachinko/__init__.py +6 -0
  6. fspachinko-0.0.2/src/fspachinko/_data/configs/fspachinko.json +60 -0
  7. fspachinko-0.0.2/src/fspachinko/_data/configs/logging.json +36 -0
  8. fspachinko-0.0.2/src/fspachinko/_data/icons/add_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  9. fspachinko-0.0.2/src/fspachinko/_data/icons/close_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  10. fspachinko-0.0.2/src/fspachinko/_data/icons/file_open_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  11. fspachinko-0.0.2/src/fspachinko/_data/icons/folder_open_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  12. fspachinko-0.0.2/src/fspachinko/_data/icons/icon.icns +0 -0
  13. fspachinko-0.0.2/src/fspachinko/_data/icons/icon.ico +0 -0
  14. fspachinko-0.0.2/src/fspachinko/_data/icons/play_arrow_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  15. fspachinko-0.0.2/src/fspachinko/_data/icons/remove_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  16. fspachinko-0.0.2/src/fspachinko/_data/icons/save_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  17. fspachinko-0.0.2/src/fspachinko/_data/icons/save_as_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  18. fspachinko-0.0.2/src/fspachinko/_data/icons/stop_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  19. fspachinko-0.0.2/src/fspachinko/_data/icons/sync_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  20. fspachinko-0.0.2/src/fspachinko/_data/icons/windowIcon.png +0 -0
  21. fspachinko-0.0.2/src/fspachinko/cli/__init__.py +1 -0
  22. fspachinko-0.0.2/src/fspachinko/cli/__main__.py +19 -0
  23. fspachinko-0.0.2/src/fspachinko/cli/app.py +62 -0
  24. fspachinko-0.0.2/src/fspachinko/cli/observer.py +37 -0
  25. fspachinko-0.0.2/src/fspachinko/config/__init__.py +39 -0
  26. fspachinko-0.0.2/src/fspachinko/config/config.py +213 -0
  27. fspachinko-0.0.2/src/fspachinko/config/converter.py +163 -0
  28. fspachinko-0.0.2/src/fspachinko/config/schemas.py +96 -0
  29. fspachinko-0.0.2/src/fspachinko/core/__init__.py +20 -0
  30. fspachinko-0.0.2/src/fspachinko/core/builder.py +92 -0
  31. fspachinko-0.0.2/src/fspachinko/core/engine.py +129 -0
  32. fspachinko-0.0.2/src/fspachinko/core/quota.py +46 -0
  33. fspachinko-0.0.2/src/fspachinko/core/reporter.py +55 -0
  34. fspachinko-0.0.2/src/fspachinko/core/state.py +300 -0
  35. fspachinko-0.0.2/src/fspachinko/core/transfer.py +100 -0
  36. fspachinko-0.0.2/src/fspachinko/core/validator.py +70 -0
  37. fspachinko-0.0.2/src/fspachinko/core/walker.py +184 -0
  38. fspachinko-0.0.2/src/fspachinko/gui/__init__.py +1 -0
  39. fspachinko-0.0.2/src/fspachinko/gui/__main__.py +43 -0
  40. fspachinko-0.0.2/src/fspachinko/gui/actions.py +68 -0
  41. fspachinko-0.0.2/src/fspachinko/gui/centralwidget.py +70 -0
  42. fspachinko-0.0.2/src/fspachinko/gui/components.py +581 -0
  43. fspachinko-0.0.2/src/fspachinko/gui/mainwindow.py +153 -0
  44. fspachinko-0.0.2/src/fspachinko/gui/observer.py +54 -0
  45. fspachinko-0.0.2/src/fspachinko/gui/qthelpers.py +102 -0
  46. fspachinko-0.0.2/src/fspachinko/gui/settings.py +53 -0
  47. fspachinko-0.0.2/src/fspachinko/gui/uibuilder.py +127 -0
  48. fspachinko-0.0.2/src/fspachinko/gui/workers.py +56 -0
  49. fspachinko-0.0.2/src/fspachinko/utils/__init__.py +89 -0
  50. fspachinko-0.0.2/src/fspachinko/utils/constants.py +212 -0
  51. fspachinko-0.0.2/src/fspachinko/utils/helpers.py +143 -0
  52. fspachinko-0.0.2/src/fspachinko/utils/interfaces.py +35 -0
  53. fspachinko-0.0.2/src/fspachinko/utils/loggers.py +16 -0
  54. fspachinko-0.0.2/src/fspachinko/utils/paths.py +33 -0
  55. fspachinko-0.0.2/src/fspachinko/utils/timestamp.py +29 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Wonyoung Jang
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,322 @@
1
+ Metadata-Version: 2.4
2
+ Name: fspachinko
3
+ Version: 0.0.2
4
+ Summary: Transfer random files from directory A to directory B.
5
+ Author: Wonyoung Jang
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Requires-Dist: cyclopts>=4.4.5
9
+ Requires-Dist: pydantic>=2.12.5
10
+ Requires-Dist: pyinstaller>=6.18.0
11
+ Requires-Dist: pyside6>=6.10.1
12
+ Requires-Dist: qt-material>=2.17
13
+ Requires-Python: >=3.14
14
+ Project-URL: Documentation, https://wonyoung-jang.github.io/fspachinko/
15
+ Project-URL: Repository, https://github.com/wonyoung-jang/fspachinko
16
+ Project-URL: Issues, https://github.com/wonyoung-jang/fspachinko/issues
17
+ Description-Content-Type: text/markdown
18
+
19
+ # fspachinko
20
+
21
+ Transfer random files from point A to point B. Customize what and how to transfer with various filters. Supports copy, move, symlink (shortcut), and hardlink transfer operations.
22
+
23
+ ## Installation (uv)
24
+
25
+ ```bash
26
+ uv add fspachinko
27
+ ```
28
+
29
+ or
30
+
31
+ ```bash
32
+ uv tool install fspachinko
33
+ ```
34
+
35
+ ![Setup](resources/images/tab_output.png)
36
+ ![Filter](resources/images/tab_filters.png)
37
+ ![Options](resources/images/tab_options.png)
38
+
39
+ ## Usage
40
+
41
+ fspachinko can be used via command-line interface (CLI) or graphical user interface (GUI).
42
+
43
+ ## Command Line Interface
44
+
45
+ ### Basic Usage
46
+
47
+ ```bash
48
+ # Use configuration file
49
+ fspachinko-cli --config your-fspachinko.json
50
+ ```
51
+
52
+ ## Graphical User Interface
53
+
54
+ ### Launch GUI
55
+
56
+ ```bash
57
+ fspachinko-gui
58
+ ```
59
+
60
+ Or simply:
61
+
62
+ ```bash
63
+ fspachinko
64
+ ```
65
+
66
+ ### GUI Profiles
67
+
68
+ Save frequently used configurations as profiles:
69
+
70
+ 1. Configure settings in the GUI
71
+ 2. Click **File → Save Profile As**
72
+ 3. Name your profile (e.g., "music_copy")
73
+ 4. Load later with **File → Load Profile**
74
+
75
+ ## Configuration File
76
+
77
+ Create a `fspachinko.json` file for reusable configurations. Pass this to the CLI after the `--config` flag. The default (for Windows) is shown below:
78
+
79
+ ```json
80
+ {
81
+ "root": "C:/",
82
+ "dest": "fspachinko_output/",
83
+ "filecount": {
84
+ "count": 20,
85
+ "is_rand_enabled": false,
86
+ "rand_min": 1,
87
+ "rand_max": 12
88
+ },
89
+ "folder": {
90
+ "should_create": true,
91
+ "is_unique": true,
92
+ "name": "test_folder_output",
93
+ "count": 10
94
+ },
95
+ "filename": {
96
+ "template": "{original}"
97
+ },
98
+ "transfermode": {
99
+ "transfer_mode": "Symlink",
100
+ "trash_empty_folder_enabled": false
101
+ },
102
+ "keyword": {
103
+ "is_enabled": true,
104
+ "should_include": true,
105
+ "text": ""
106
+ },
107
+ "extension": {
108
+ "is_enabled": true,
109
+ "should_include": true,
110
+ "text": "wav"
111
+ },
112
+ "filesize": {
113
+ "is_enabled": false,
114
+ "minimum": 0.0,
115
+ "maximum": 0.0
116
+ },
117
+ "duration": {
118
+ "is_enabled": false,
119
+ "minimum": 0.0,
120
+ "maximum": 0.0
121
+ },
122
+ "folder_size_limit": {
123
+ "is_enabled": false,
124
+ "size_limit": 500.0
125
+ },
126
+ "total_size_limit": {
127
+ "is_enabled": false,
128
+ "size_limit": 500.0
129
+ },
130
+ "options": {
131
+ "max_per_folder": 3,
132
+ "should_follow_symlink": false,
133
+ "is_dry_run": true
134
+ }
135
+ }
136
+ ```
137
+
138
+ ## Example Configurations
139
+
140
+ ### Random Music Playlist
141
+
142
+ ```json
143
+ {
144
+ "root": "~/Music",
145
+ "dest": "~/Playlists/Random",
146
+ "filecount": {
147
+ "count": 50,
148
+ ...
149
+ },
150
+ ...
151
+ "extension": {
152
+ "is_enabled": true,
153
+ "should_include": true,
154
+ "text": "wav,flac,m4a"
155
+ },
156
+ ...
157
+ "options": {
158
+ "max_per_folder": 2,
159
+ ...
160
+ }
161
+ }
162
+ ```
163
+
164
+ ### Photo Gallery Selection
165
+
166
+ ```json
167
+ {
168
+ "root": "~/Photos",
169
+ "dest": "~/Gallery",
170
+ "filecount": {
171
+ "count": 20,
172
+ ...
173
+ },
174
+ ...
175
+ "extension": {
176
+ "is_enabled": true,
177
+ "should_include": true,
178
+ "text": "jpg,png"
179
+ },
180
+ "filesize": {
181
+ "is_enabled": true,
182
+ "is_enabled": true,
183
+ "minimum": 1.0,
184
+ ...
185
+ },
186
+ "keyword": {
187
+ "should_include": false,
188
+ "text": "thumbnail,draft"
189
+ },
190
+ ...
191
+ }
192
+ ```
193
+
194
+ ### Video Highlights
195
+
196
+ ```json
197
+ {
198
+ "root": "~/Videos",
199
+ "dest": "~/Highlights",
200
+ "filecount": {
201
+ "count": 10,
202
+ ...
203
+ },
204
+ ...
205
+ "extension": {
206
+ "is_enabled": true,
207
+ "should_include": true,
208
+ "text": "mp4"
209
+ },
210
+ "duration": {
211
+ "is_enabled": true,
212
+ "minimum": 30.0,
213
+ "maximum": 600.0
214
+ },
215
+ ...
216
+ }
217
+ ```
218
+
219
+ ### Safe Preview (Dry Run)
220
+
221
+ ```json
222
+ {
223
+ "root": "/important/files",
224
+ "dest": "/backup",
225
+ "filecount": {
226
+ "count": 100,
227
+ ...
228
+ },
229
+ ...
230
+ "options": {
231
+ ...
232
+ "is_dry_run": true
233
+ }
234
+ }
235
+ ```
236
+
237
+ ## Advanced Features
238
+
239
+ ### Output Filename Templates
240
+
241
+ Use template variables in filenames:
242
+
243
+ - `{original}`: Original filename
244
+ - `{index}`: Sequential number
245
+ - `{date}`: Current date (YYYY-MM-DD)
246
+ - `{time}`: Current time (HH-MM-SS)
247
+ - `{datetime}`: Combined date and time
248
+ - `{parent}`: Parent folder name
249
+ - `{parentstoroot}`: Full parent path separated by `-`
250
+
251
+ Example: `{index}_{original}_{date}`: `photo.jpg` -> `1_photo_2026-01-25.jpg`
252
+
253
+ ### Logging
254
+
255
+ Configure logging in a `json` file. Here is the default `fspachinko_configs/logging.json` provided:
256
+
257
+ ```json
258
+ {
259
+ "version": 1,
260
+ "disable_existing_loggers": false,
261
+ "formatters": {
262
+ "file": {
263
+ "format": "[%(asctime)s] %(levelname)s[%(module)s] %(message)s"
264
+ },
265
+ "console": {
266
+ "format": "[%(asctime)s] %(levelname)s[%(module)s] %(message)s"
267
+ }
268
+ },
269
+ "handlers": {
270
+ "console": {
271
+ "class": "logging.StreamHandler",
272
+ "formatter": "console",
273
+ "level": "INFO",
274
+ "stream": "ext://sys.stdout"
275
+ },
276
+ "file": {
277
+ "class": "logging.FileHandler",
278
+ "formatter": "file",
279
+ "level": "DEBUG",
280
+ "filename": "fspachinko.log",
281
+ "mode": "w",
282
+ "encoding": "utf-8",
283
+ "delay": true
284
+ }
285
+ },
286
+ "root": {
287
+ "level": "DEBUG",
288
+ "handlers": [
289
+ "console",
290
+ "file"
291
+ ]
292
+ }
293
+ }
294
+ ```
295
+
296
+ ## Troubleshooting
297
+
298
+ ### Common Issues
299
+
300
+ **No files found:**
301
+
302
+ - Check your filters (extension, keyword, size)
303
+ - Verify source path exists and contains matching files
304
+ - Try `--dry-run` to see what would be selected
305
+
306
+ **Permission errors:**
307
+
308
+ - Ensure read access to source directory
309
+ - Ensure write access to destination directory
310
+ - Try running with appropriate permissions
311
+
312
+ **Hardlink errors:**
313
+
314
+ - Source and destination must be on same filesystem
315
+ - Not supported on all filesystems (e.g., FAT32)
316
+ - Falls back to symlink automatically
317
+
318
+ **Duration filter not working:**
319
+
320
+ - Requires ffmpeg installed on system
321
+ - Only works with media files (video/audio)
322
+ - Check file format is supported by ffmpeg
@@ -0,0 +1,304 @@
1
+ # fspachinko
2
+
3
+ Transfer random files from point A to point B. Customize what and how to transfer with various filters. Supports copy, move, symlink (shortcut), and hardlink transfer operations.
4
+
5
+ ## Installation (uv)
6
+
7
+ ```bash
8
+ uv add fspachinko
9
+ ```
10
+
11
+ or
12
+
13
+ ```bash
14
+ uv tool install fspachinko
15
+ ```
16
+
17
+ ![Setup](resources/images/tab_output.png)
18
+ ![Filter](resources/images/tab_filters.png)
19
+ ![Options](resources/images/tab_options.png)
20
+
21
+ ## Usage
22
+
23
+ fspachinko can be used via command-line interface (CLI) or graphical user interface (GUI).
24
+
25
+ ## Command Line Interface
26
+
27
+ ### Basic Usage
28
+
29
+ ```bash
30
+ # Use configuration file
31
+ fspachinko-cli --config your-fspachinko.json
32
+ ```
33
+
34
+ ## Graphical User Interface
35
+
36
+ ### Launch GUI
37
+
38
+ ```bash
39
+ fspachinko-gui
40
+ ```
41
+
42
+ Or simply:
43
+
44
+ ```bash
45
+ fspachinko
46
+ ```
47
+
48
+ ### GUI Profiles
49
+
50
+ Save frequently used configurations as profiles:
51
+
52
+ 1. Configure settings in the GUI
53
+ 2. Click **File → Save Profile As**
54
+ 3. Name your profile (e.g., "music_copy")
55
+ 4. Load later with **File → Load Profile**
56
+
57
+ ## Configuration File
58
+
59
+ Create a `fspachinko.json` file for reusable configurations. Pass this to the CLI after the `--config` flag. The default (for Windows) is shown below:
60
+
61
+ ```json
62
+ {
63
+ "root": "C:/",
64
+ "dest": "fspachinko_output/",
65
+ "filecount": {
66
+ "count": 20,
67
+ "is_rand_enabled": false,
68
+ "rand_min": 1,
69
+ "rand_max": 12
70
+ },
71
+ "folder": {
72
+ "should_create": true,
73
+ "is_unique": true,
74
+ "name": "test_folder_output",
75
+ "count": 10
76
+ },
77
+ "filename": {
78
+ "template": "{original}"
79
+ },
80
+ "transfermode": {
81
+ "transfer_mode": "Symlink",
82
+ "trash_empty_folder_enabled": false
83
+ },
84
+ "keyword": {
85
+ "is_enabled": true,
86
+ "should_include": true,
87
+ "text": ""
88
+ },
89
+ "extension": {
90
+ "is_enabled": true,
91
+ "should_include": true,
92
+ "text": "wav"
93
+ },
94
+ "filesize": {
95
+ "is_enabled": false,
96
+ "minimum": 0.0,
97
+ "maximum": 0.0
98
+ },
99
+ "duration": {
100
+ "is_enabled": false,
101
+ "minimum": 0.0,
102
+ "maximum": 0.0
103
+ },
104
+ "folder_size_limit": {
105
+ "is_enabled": false,
106
+ "size_limit": 500.0
107
+ },
108
+ "total_size_limit": {
109
+ "is_enabled": false,
110
+ "size_limit": 500.0
111
+ },
112
+ "options": {
113
+ "max_per_folder": 3,
114
+ "should_follow_symlink": false,
115
+ "is_dry_run": true
116
+ }
117
+ }
118
+ ```
119
+
120
+ ## Example Configurations
121
+
122
+ ### Random Music Playlist
123
+
124
+ ```json
125
+ {
126
+ "root": "~/Music",
127
+ "dest": "~/Playlists/Random",
128
+ "filecount": {
129
+ "count": 50,
130
+ ...
131
+ },
132
+ ...
133
+ "extension": {
134
+ "is_enabled": true,
135
+ "should_include": true,
136
+ "text": "wav,flac,m4a"
137
+ },
138
+ ...
139
+ "options": {
140
+ "max_per_folder": 2,
141
+ ...
142
+ }
143
+ }
144
+ ```
145
+
146
+ ### Photo Gallery Selection
147
+
148
+ ```json
149
+ {
150
+ "root": "~/Photos",
151
+ "dest": "~/Gallery",
152
+ "filecount": {
153
+ "count": 20,
154
+ ...
155
+ },
156
+ ...
157
+ "extension": {
158
+ "is_enabled": true,
159
+ "should_include": true,
160
+ "text": "jpg,png"
161
+ },
162
+ "filesize": {
163
+ "is_enabled": true,
164
+ "is_enabled": true,
165
+ "minimum": 1.0,
166
+ ...
167
+ },
168
+ "keyword": {
169
+ "should_include": false,
170
+ "text": "thumbnail,draft"
171
+ },
172
+ ...
173
+ }
174
+ ```
175
+
176
+ ### Video Highlights
177
+
178
+ ```json
179
+ {
180
+ "root": "~/Videos",
181
+ "dest": "~/Highlights",
182
+ "filecount": {
183
+ "count": 10,
184
+ ...
185
+ },
186
+ ...
187
+ "extension": {
188
+ "is_enabled": true,
189
+ "should_include": true,
190
+ "text": "mp4"
191
+ },
192
+ "duration": {
193
+ "is_enabled": true,
194
+ "minimum": 30.0,
195
+ "maximum": 600.0
196
+ },
197
+ ...
198
+ }
199
+ ```
200
+
201
+ ### Safe Preview (Dry Run)
202
+
203
+ ```json
204
+ {
205
+ "root": "/important/files",
206
+ "dest": "/backup",
207
+ "filecount": {
208
+ "count": 100,
209
+ ...
210
+ },
211
+ ...
212
+ "options": {
213
+ ...
214
+ "is_dry_run": true
215
+ }
216
+ }
217
+ ```
218
+
219
+ ## Advanced Features
220
+
221
+ ### Output Filename Templates
222
+
223
+ Use template variables in filenames:
224
+
225
+ - `{original}`: Original filename
226
+ - `{index}`: Sequential number
227
+ - `{date}`: Current date (YYYY-MM-DD)
228
+ - `{time}`: Current time (HH-MM-SS)
229
+ - `{datetime}`: Combined date and time
230
+ - `{parent}`: Parent folder name
231
+ - `{parentstoroot}`: Full parent path separated by `-`
232
+
233
+ Example: `{index}_{original}_{date}`: `photo.jpg` -> `1_photo_2026-01-25.jpg`
234
+
235
+ ### Logging
236
+
237
+ Configure logging in a `json` file. Here is the default `fspachinko_configs/logging.json` provided:
238
+
239
+ ```json
240
+ {
241
+ "version": 1,
242
+ "disable_existing_loggers": false,
243
+ "formatters": {
244
+ "file": {
245
+ "format": "[%(asctime)s] %(levelname)s[%(module)s] %(message)s"
246
+ },
247
+ "console": {
248
+ "format": "[%(asctime)s] %(levelname)s[%(module)s] %(message)s"
249
+ }
250
+ },
251
+ "handlers": {
252
+ "console": {
253
+ "class": "logging.StreamHandler",
254
+ "formatter": "console",
255
+ "level": "INFO",
256
+ "stream": "ext://sys.stdout"
257
+ },
258
+ "file": {
259
+ "class": "logging.FileHandler",
260
+ "formatter": "file",
261
+ "level": "DEBUG",
262
+ "filename": "fspachinko.log",
263
+ "mode": "w",
264
+ "encoding": "utf-8",
265
+ "delay": true
266
+ }
267
+ },
268
+ "root": {
269
+ "level": "DEBUG",
270
+ "handlers": [
271
+ "console",
272
+ "file"
273
+ ]
274
+ }
275
+ }
276
+ ```
277
+
278
+ ## Troubleshooting
279
+
280
+ ### Common Issues
281
+
282
+ **No files found:**
283
+
284
+ - Check your filters (extension, keyword, size)
285
+ - Verify source path exists and contains matching files
286
+ - Try `--dry-run` to see what would be selected
287
+
288
+ **Permission errors:**
289
+
290
+ - Ensure read access to source directory
291
+ - Ensure write access to destination directory
292
+ - Try running with appropriate permissions
293
+
294
+ **Hardlink errors:**
295
+
296
+ - Source and destination must be on same filesystem
297
+ - Not supported on all filesystems (e.g., FAT32)
298
+ - Falls back to symlink automatically
299
+
300
+ **Duration filter not working:**
301
+
302
+ - Requires ffmpeg installed on system
303
+ - Only works with media files (video/audio)
304
+ - Check file format is supported by ffmpeg
@@ -0,0 +1,48 @@
1
+ [project]
2
+ name = "fspachinko"
3
+ version = "0.0.2"
4
+ description = "Transfer random files from directory A to directory B."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICEN[CS]E*"]
8
+ requires-python = ">=3.14"
9
+ dependencies = [
10
+ "cyclopts>=4.4.5",
11
+ "pydantic>=2.12.5",
12
+ "pyinstaller>=6.18.0",
13
+ "pyside6>=6.10.1",
14
+ "qt-material>=2.17",
15
+ ]
16
+ authors = [
17
+ {name = "Wonyoung Jang"},
18
+ ]
19
+
20
+ [project.urls]
21
+ Documentation = "https://wonyoung-jang.github.io/fspachinko/"
22
+ Repository = "https://github.com/wonyoung-jang/fspachinko"
23
+ Issues = "https://github.com/wonyoung-jang/fspachinko/issues"
24
+
25
+ [project.scripts]
26
+ fspachinko = "fspachinko.gui.__main__:main"
27
+ fspachinko-gui = "fspachinko.gui.__main__:main"
28
+ fspachinko-cli = "fspachinko.cli.__main__:main"
29
+
30
+ [build-system]
31
+ requires = ["uv_build>=0.9.27,<0.10.0"]
32
+ build-backend = "uv_build"
33
+
34
+ [tool.vulture]
35
+ paths = ["./src/fspachinko", "whitelist.py"]
36
+ ignore_decorators = ["@app.*"]
37
+ min_confidence = 40
38
+ verbose = false
39
+
40
+ [dependency-groups]
41
+ dev = [
42
+ "line-profiler>=5.0.0",
43
+ "tprof>=1.1.0",
44
+ ]
45
+ docs = [
46
+ "mkdocstrings-python>=2.0.1",
47
+ "zensical>=0.0.19",
48
+ ]
@@ -0,0 +1,6 @@
1
+ """Main package."""
2
+
3
+
4
+ def hello(n: int) -> str:
5
+ """Return a hello message with the sum of numbers from 1 to n."""
6
+ return f"Hello {n}!"