fspachinko 0.0.2__py3-none-any.whl

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 (56) hide show
  1. fspachinko/__init__.py +6 -0
  2. fspachinko/_data/configs/fspachinko.json +60 -0
  3. fspachinko/_data/configs/logging.json +36 -0
  4. fspachinko/_data/icons/add_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  5. fspachinko/_data/icons/close_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  6. fspachinko/_data/icons/file_open_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  7. fspachinko/_data/icons/folder_open_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  8. fspachinko/_data/icons/icon.icns +0 -0
  9. fspachinko/_data/icons/icon.ico +0 -0
  10. fspachinko/_data/icons/play_arrow_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  11. fspachinko/_data/icons/remove_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  12. fspachinko/_data/icons/save_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  13. fspachinko/_data/icons/save_as_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  14. fspachinko/_data/icons/stop_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  15. fspachinko/_data/icons/sync_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg +1 -0
  16. fspachinko/_data/icons/windowIcon.png +0 -0
  17. fspachinko/cli/__init__.py +1 -0
  18. fspachinko/cli/__main__.py +19 -0
  19. fspachinko/cli/app.py +62 -0
  20. fspachinko/cli/observer.py +37 -0
  21. fspachinko/config/__init__.py +39 -0
  22. fspachinko/config/config.py +213 -0
  23. fspachinko/config/converter.py +163 -0
  24. fspachinko/config/schemas.py +96 -0
  25. fspachinko/core/__init__.py +20 -0
  26. fspachinko/core/builder.py +92 -0
  27. fspachinko/core/engine.py +129 -0
  28. fspachinko/core/quota.py +46 -0
  29. fspachinko/core/reporter.py +55 -0
  30. fspachinko/core/state.py +300 -0
  31. fspachinko/core/transfer.py +100 -0
  32. fspachinko/core/validator.py +70 -0
  33. fspachinko/core/walker.py +184 -0
  34. fspachinko/gui/__init__.py +1 -0
  35. fspachinko/gui/__main__.py +43 -0
  36. fspachinko/gui/actions.py +68 -0
  37. fspachinko/gui/centralwidget.py +70 -0
  38. fspachinko/gui/components.py +581 -0
  39. fspachinko/gui/mainwindow.py +153 -0
  40. fspachinko/gui/observer.py +54 -0
  41. fspachinko/gui/qthelpers.py +102 -0
  42. fspachinko/gui/settings.py +53 -0
  43. fspachinko/gui/uibuilder.py +127 -0
  44. fspachinko/gui/workers.py +56 -0
  45. fspachinko/utils/__init__.py +89 -0
  46. fspachinko/utils/constants.py +212 -0
  47. fspachinko/utils/helpers.py +143 -0
  48. fspachinko/utils/interfaces.py +35 -0
  49. fspachinko/utils/loggers.py +16 -0
  50. fspachinko/utils/paths.py +33 -0
  51. fspachinko/utils/timestamp.py +29 -0
  52. fspachinko-0.0.2.dist-info/METADATA +322 -0
  53. fspachinko-0.0.2.dist-info/RECORD +56 -0
  54. fspachinko-0.0.2.dist-info/WHEEL +4 -0
  55. fspachinko-0.0.2.dist-info/entry_points.txt +5 -0
  56. fspachinko-0.0.2.dist-info/licenses/LICENSE +21 -0
@@ -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,56 @@
1
+ fspachinko/__init__.py,sha256=y70y6RtQXs-1isj4yhUZ5Cpx_NDXy09j9mmqeYmDaxo,149
2
+ fspachinko/_data/configs/fspachinko.json,sha256=58Bee1oNAFoUWkhCAUpqaIhCRbLJy8pmCHtq9O3zmKE,1345
3
+ fspachinko/_data/configs/logging.json,sha256=8qpFJUh4JKZieaXtvzygYZpgxGcjGu_rhvNxAm0yyr0,924
4
+ fspachinko/_data/icons/add_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=nOgT_oGW2anAKuDsUyTDOENHo5SIMQqJh8ZEpIEZtLM,182
5
+ fspachinko/_data/icons/close_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=hm9fnCle5muBGKgnpA_j-mW_59SLpG0KzmWroUwMNx4,222
6
+ fspachinko/_data/icons/file_open_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=vwa_l1960SRIYaCnbd9bUcZsZJDFFPQbHYz9_5bKjkM,309
7
+ fspachinko/_data/icons/folder_open_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=72ZHCcc-KFoKmz9zAIj5qb-RiCqhwDMO4PR_Xbd0eDg,353
8
+ fspachinko/_data/icons/icon.icns,sha256=7oCQiX8t71yRLpxj8Bb0rg_jvpO2mxPA-xNxk2tLedE,40748
9
+ fspachinko/_data/icons/icon.ico,sha256=wON-KKyX6VZP8JjtkudDy4GsHHnyq1fiBOEg1cWZVAY,74814
10
+ fspachinko/_data/icons/play_arrow_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=wfcPR-6XCE5ZVjIqiZudbWHpxbqiQV50C0bGzHLLIo4,190
11
+ fspachinko/_data/icons/remove_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=E21NyskQ_zG4Dxk-qeif5hqqwqGOzRu0_dgeEV9gAWs,149
12
+ fspachinko/_data/icons/save_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=SaS4uoFP4F0d69MWBoZNIyoLHsRC6OHBZmdvTfajfIk,388
13
+ fspachinko/_data/icons/save_as_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=b-MHohaDYZpUVm0kYMIu-a1K-6-toIqLGLYG_NC4Gw8,578
14
+ fspachinko/_data/icons/stop_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=T8H9WTg95TcqQxmkLwjgm03EiNx7mfdJGvMAeMqasSg,192
15
+ fspachinko/_data/icons/sync_24dp_E3E3E3_FILL0_wght400_GRAD0_opsz24.svg,sha256=iidUlXTe9JerwNGTiTfKr8ZJH9mszfy3rv_BQyXQ4R8,407
16
+ fspachinko/_data/icons/windowIcon.png,sha256=2ZEQYqXCwbPBRWkGe3M3Sucu92MX25UaJuuFO1chl3c,54159
17
+ fspachinko/cli/__init__.py,sha256=SCk8yOKuiusfPBi_7bioX9S4e7aC9Gb8CHQCJiJCJQk,35
18
+ fspachinko/cli/__main__.py,sha256=c_bV8_7GU5AWk9fI5YgNY4xZShX5RW19baZQACmGYAA,325
19
+ fspachinko/cli/app.py,sha256=pwlBtOBj72qSr4BN-MvYY8RlJcYq9QhknnndemJI2os,1651
20
+ fspachinko/cli/observer.py,sha256=3bxSf1CszusEVPEcUx67rtKKJOZNW0RcZEWHj3JYg4Y,1095
21
+ fspachinko/config/__init__.py,sha256=Ysjw8gyZv8hHwqNxL6Y2WmYGVtThWP6eiy8oMKXipQw,706
22
+ fspachinko/config/config.py,sha256=DI4yzQdocFdQ8i_vJVjU3NRRqnFpLpE9KSmXeJHmJFo,6699
23
+ fspachinko/config/converter.py,sha256=p4lS24h4iKfZQiYMRRQ0pDYbT60s_75g_LuImX-pyzQ,7568
24
+ fspachinko/config/schemas.py,sha256=0BGEdKUWv6By03OglzqDb9Ruw5LEg8XvHaOl5LZv80I,2171
25
+ fspachinko/core/__init__.py,sha256=z9JPaP4G22crswwVZqhLuCcC_65nV5ElboPrmFQpgf8,508
26
+ fspachinko/core/builder.py,sha256=CDGwOfpzwzj3wL0x5ORN5e12ZlENS-NM9hxoAH1_7mo,3031
27
+ fspachinko/core/engine.py,sha256=9eFjT-O8MPeMfrbOrfNkjwRsqRd-TlqhNRNhBkbKQOY,4223
28
+ fspachinko/core/quota.py,sha256=M-Juyk3Rynfw7Eo61XzCqDLUGe2OrJmQA1QwidbUJb8,1451
29
+ fspachinko/core/reporter.py,sha256=DXuZgQXsFYlab33KT4MidKylrSo2jtFQMHDaS6WvMig,2229
30
+ fspachinko/core/state.py,sha256=491Nbd6PvoHiCtyTfWZQhku4Kkehj7tfFZAWkQFk3-Q,9551
31
+ fspachinko/core/transfer.py,sha256=2X5OPe8lpsUAvgZVRaqycyVG4D-oISIRbVZ6vyHyHaI,3294
32
+ fspachinko/core/validator.py,sha256=fnIGyWs5eyfQkaQQ9aQDte6McoUsxMkZBWnoTSlzWFQ,2240
33
+ fspachinko/core/walker.py,sha256=gfIu0C3dLFFrPbYp6RoOSbjnxY3QkjHrBhuUNW-g_lk,5769
34
+ fspachinko/gui/__init__.py,sha256=KDO53ikj1SljEnSNow9dDWScyExXadyQMIpqV_fl63U,20
35
+ fspachinko/gui/__main__.py,sha256=9eAkAMjufR6u7d4B5vA4odF515EdG-QvqtZ-j547Km8,1200
36
+ fspachinko/gui/actions.py,sha256=02r5SduGr1ZJLtV4z3jOn3RMcJE18QQVRuUob57P1nI,2427
37
+ fspachinko/gui/centralwidget.py,sha256=R_sPDbTAjFUv88AVCwt65YssO_F1IrAQQu2SawUYl8c,2447
38
+ fspachinko/gui/components.py,sha256=-qsPLoGbrEBqS0Zw97qDsKBMmHa8X6Y1UDYJ49G4g1c,22132
39
+ fspachinko/gui/mainwindow.py,sha256=JaAIOlYHzeeEnt4JyJMmbrYXHm1dTbm6qKwCoG1duhA,5716
40
+ fspachinko/gui/observer.py,sha256=ut3NGx2bEvzNfulJ7jpq_LoG3pYJUe_KfH7FtyyVRas,1380
41
+ fspachinko/gui/qthelpers.py,sha256=xJRg9PhOPIhMelhISTljJ_zHkQeCbauh4iBkwrVL46A,2870
42
+ fspachinko/gui/settings.py,sha256=-LW0d7PKh0WMr0zoV3ilynZZQ6I7fsqrOc_580-j4dk,1865
43
+ fspachinko/gui/uibuilder.py,sha256=T9DTAgJCJg31Y8ag6Fzu6ypBxywTrIa4dzdTJ-izQk0,4950
44
+ fspachinko/gui/workers.py,sha256=OoLOc9A3jRBXZ3ct39AE-rqGL0S79DqdlWnF4gpu1bE,1386
45
+ fspachinko/utils/__init__.py,sha256=eT1vizibScj8srVkmCSaBZzVo3Kt2Pi9Ph4dWTNpSJo,1823
46
+ fspachinko/utils/constants.py,sha256=haQIYWQ7lN-jYlfHm1kFgz4ntKoQvGAbLhBLZKpV88U,5193
47
+ fspachinko/utils/helpers.py,sha256=CaBAt9pArvj0WYfPwHEZZLr8SZH4xaeKyo6twa92hyY,4293
48
+ fspachinko/utils/interfaces.py,sha256=QTN8-LYUsClLrWRe-uRf9HClZd92lS5xx3VInlXzMkE,963
49
+ fspachinko/utils/loggers.py,sha256=rCi7_zgEPS1RJRD2jN9gZnUsqv-dphKzNZ7kjs2Jg04,403
50
+ fspachinko/utils/paths.py,sha256=kULkQImy0BUYHHdLUMhPgwmm744vbLcSGLhlUxQB8co,1004
51
+ fspachinko/utils/timestamp.py,sha256=hFuis7cqFseMNoc6ACQUtuIkdh0PsA3WG6z9OA2mEFk,893
52
+ fspachinko-0.0.2.dist-info/licenses/LICENSE,sha256=F1FWVuT7zcubFaT9Ht6LSJibItfcN4lRb3jZJYFUlRQ,1091
53
+ fspachinko-0.0.2.dist-info/WHEEL,sha256=iHtWm8nRfs0VRdCYVXocAWFW8ppjHL-uTJkAdZJKOBM,80
54
+ fspachinko-0.0.2.dist-info/entry_points.txt,sha256=18_kvn_YIWGCFdLaKAO4kb4FabHnNj8Kb7ZyiBPKB7M,153
55
+ fspachinko-0.0.2.dist-info/METADATA,sha256=ER704Gq053PEECGtn91gmuGNZaecFlRoBg17xHrg6Fo,6630
56
+ fspachinko-0.0.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.9.30
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,5 @@
1
+ [console_scripts]
2
+ fspachinko = fspachinko.gui.__main__:main
3
+ fspachinko-cli = fspachinko.cli.__main__:main
4
+ fspachinko-gui = fspachinko.gui.__main__:main
5
+
@@ -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.