simplesyntax 0.1.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.
@@ -0,0 +1,870 @@
1
+ Metadata-Version: 2.4
2
+ Name: simplesyntax
3
+ Version: 0.1.0
4
+ Summary: Simple CSS-inspired Python media task library
5
+ Requires-Python: >=3.9
6
+ Description-Content-Type: text/markdown
7
+ Requires-Dist: yt-dlp
8
+ Requires-Dist: gallery-dl
9
+
10
+ # EasyTasks
11
+
12
+ EasyTasks is a simple CSS-inspired Python media library built around:
13
+
14
+ - yt-dlp
15
+ - FFmpeg
16
+ - gallery-dl
17
+
18
+ Its main goal is to provide a simple API for downloading media and extracting metadata without requiring complicated downloader classes or configuration objects.
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install easytasks
24
+
25
+ EasyTasks uses:
26
+
27
+ yt-dlp for video and supported metadata operations
28
+
29
+ gallery-dl for images and galleries
30
+
31
+ FFmpeg when media streams need to be merged
32
+
33
+
34
+
35
+ ---
36
+
37
+ Main API
38
+
39
+ The main API is:
40
+
41
+ from easytasks import rz
42
+
43
+ rz({...}, url)
44
+
45
+ The value on the right side of every selector is a user-defined Python variable name.
46
+
47
+ Example:
48
+
49
+ from easytasks import rz
50
+
51
+ rz({
52
+ "media[4]": "M"
53
+ }, "https://example.com/media")
54
+
55
+ print(M)
56
+
57
+ Here:
58
+
59
+ "media[4]" → M
60
+
61
+ means the downloaded media is made available through the variable M.
62
+
63
+ Another example:
64
+
65
+ from easytasks import rz
66
+
67
+ rz({
68
+ "media[4]": "V",
69
+ "title": "T",
70
+ "creator": "C"
71
+ }, url)
72
+
73
+ print(V)
74
+ print(T)
75
+ print(C)
76
+
77
+ The user chooses the variable names.
78
+
79
+ EasyTasks does not force names such as:
80
+
81
+ video
82
+ title
83
+ creator
84
+ views
85
+
86
+ The right-side names can be different valid Python variable names.
87
+
88
+
89
+ ---
90
+
91
+ Dictionary Order
92
+
93
+ The order of selectors inside the dictionary does not matter.
94
+
95
+ These are equivalent:
96
+
97
+ rz({
98
+ "media[4]": "M",
99
+ "title": "T",
100
+ "creator": "C"
101
+ }, url)
102
+
103
+ and:
104
+
105
+ rz({
106
+ "creator": "C",
107
+ "media[4]": "M",
108
+ "title": "T"
109
+ }, url)
110
+
111
+ EasyTasks identifies each operation from its selector.
112
+
113
+
114
+ ---
115
+
116
+ Variable Assignment
117
+
118
+ EasyTasks uses the right side of each selector as the variable name exposed to the caller.
119
+
120
+ For example:
121
+
122
+ rz({
123
+ "media[4]": "M"
124
+ }, url)
125
+
126
+ print(M)
127
+
128
+ The selector:
129
+
130
+ media[4]
131
+
132
+ defines what EasyTasks should retrieve.
133
+
134
+ The value:
135
+
136
+ M
137
+
138
+ defines the variable name that the user will use.
139
+
140
+ Multiple values can be requested together:
141
+
142
+ rz({
143
+ "media[4]": "VIDEO",
144
+ "title": "TITLE",
145
+ "creator": "AUTHOR",
146
+ "views": "VIEW_COUNT"
147
+ }, url)
148
+
149
+ print(VIDEO)
150
+ print(TITLE)
151
+ print(AUTHOR)
152
+ print(VIEW_COUNT)
153
+
154
+ No separate result dictionary is required for normal usage.
155
+
156
+
157
+ ---
158
+
159
+ Video Selectors
160
+
161
+ video[N] explicitly selects a video/yt-dlp operation.
162
+
163
+ The quality mapping is fixed:
164
+
165
+ Selector Meaning
166
+
167
+ video[0] Best available audio
168
+ video[1] 360p
169
+ video[2] 480p
170
+ video[3] 720p
171
+ video[4] 1080p
172
+ video[5] 1440p
173
+ video[6] Best available
174
+
175
+
176
+ Example:
177
+
178
+ from easytasks import rz
179
+
180
+ rz({
181
+ "video[4]": "V"
182
+ }, url)
183
+
184
+ print(V)
185
+
186
+ video without [N] is invalid.
187
+
188
+
189
+ ---
190
+
191
+ Video Quality Fallback
192
+
193
+ If the requested quality is unavailable, EasyTasks automatically tries the next lower available quality.
194
+
195
+ For example:
196
+
197
+ 1080p
198
+
199
+ 720p
200
+
201
+ 480p
202
+
203
+ 360p
204
+
205
+ The operation should not fail merely because the requested quality is unavailable.
206
+
207
+
208
+ ---
209
+
210
+ Media Selectors
211
+
212
+ media[N] automatically determines which media downloader should be used.
213
+
214
+ media[N]
215
+
216
+ detect media type
217
+ ├── VIDEO → yt-dlp
218
+ └── IMAGE → gallery-dl
219
+
220
+ The quality mapping is:
221
+
222
+ Selector Meaning
223
+
224
+ media[0] Best available audio
225
+ media[1] 360p
226
+ media[2] 480p
227
+ media[3] 720p
228
+ media[4] 1080p
229
+ media[5] 1440p
230
+ media[6] Best available
231
+
232
+
233
+ Example:
234
+
235
+ from easytasks import rz
236
+
237
+ rz({
238
+ "media[4]": "M"
239
+ }, "https://example.com/media")
240
+
241
+ print(M)
242
+
243
+ For a video, [N] controls the requested video quality.
244
+
245
+ For an image, [N] does not resize or convert the image. gallery-dl downloads the original/available image quality.
246
+
247
+ media[N] does not mean downloading both a video and an image.
248
+
249
+
250
+ ---
251
+
252
+ Media Fallback
253
+
254
+ media[N] uses automatic media detection.
255
+
256
+ The video path is attempted through yt-dlp first.
257
+
258
+ If the video operation fails, EasyTasks attempts the image/gallery operation through gallery-dl.
259
+
260
+ media[N]
261
+
262
+ yt-dlp
263
+
264
+ success?
265
+ ├── YES → done
266
+ └── NO
267
+
268
+ gallery-dl
269
+
270
+ success?
271
+ ├── YES → done
272
+ └── NO → failure
273
+
274
+ Cookie fallback is applied to both downloader types.
275
+
276
+
277
+ ---
278
+
279
+ Image Selector
280
+
281
+ For direct image operations, use:
282
+
283
+ from easytasks import rz
284
+
285
+ rz({
286
+ "image": "IMG"
287
+ }, "https://example.com/image")
288
+
289
+ print(IMG)
290
+
291
+ The image selector uses gallery-dl directly.
292
+
293
+ image[N] is invalid.
294
+
295
+
296
+ ---
297
+
298
+ Metadata
299
+
300
+ EasyTasks supports the following metadata selectors:
301
+
302
+ Selector Meaning
303
+
304
+ title Title
305
+ creator Creator/uploader/author
306
+ url Page/video URL
307
+ views View count
308
+ likes Like count
309
+ comments Comment count
310
+ duration Duration
311
+ thumbnail Thumbnail URL
312
+
313
+
314
+ Example:
315
+
316
+ from easytasks import rz
317
+
318
+ rz({
319
+ "title": "T",
320
+ "creator": "C",
321
+ "url": "U",
322
+ "views": "V",
323
+ "likes": "L",
324
+ "comments": "CM",
325
+ "duration": "D",
326
+ "thumbnail": "TH"
327
+ }, url)
328
+
329
+ print(T)
330
+ print(C)
331
+ print(U)
332
+ print(V)
333
+ print(L)
334
+ print(CM)
335
+ print(D)
336
+ print(TH)
337
+
338
+ The right-side names are completely user-defined.
339
+
340
+
341
+ ---
342
+
343
+ Media and Metadata Together
344
+
345
+ Media and metadata can be requested in the same rz() call.
346
+
347
+ from easytasks import rz
348
+
349
+ rz({
350
+ "media[4]": "M",
351
+ "title": "T",
352
+ "creator": "C",
353
+ "url": "U",
354
+ "views": "V",
355
+ "likes": "L",
356
+ "comments": "CM",
357
+ "duration": "D",
358
+ "thumbnail": "TH"
359
+ }, url)
360
+
361
+ print(M)
362
+ print(T)
363
+ print(C)
364
+ print(U)
365
+ print(V)
366
+ print(L)
367
+ print(CM)
368
+ print(D)
369
+ print(TH)
370
+
371
+
372
+ ---
373
+
374
+ Cookies
375
+
376
+ EasyTasks uses the variable:
377
+
378
+ ReiZyuki
379
+
380
+ Example:
381
+
382
+ ReiZyuki = [
383
+ "/storage/emulated/0/Download/youtube.txt",
384
+ "/storage/emulated/0/Download/instagram.txt",
385
+ "/storage/emulated/0/Download/reddit.txt"
386
+ ]
387
+
388
+ The user does not pass cookies as an argument to rz().
389
+
390
+ Correct:
391
+
392
+ from easytasks import rz
393
+
394
+ ReiZyuki = [
395
+ "/storage/emulated/0/Download/instagram.txt"
396
+ ]
397
+
398
+ rz({
399
+ "image": "IMG"
400
+ }, url)
401
+
402
+ print(IMG)
403
+
404
+ There is no need for:
405
+
406
+ rz({...}, url, cookies=ReiZyuki)
407
+
408
+
409
+ ---
410
+
411
+ Cookie Fallback
412
+
413
+ EasyTasks always attempts the operation without cookies first.
414
+
415
+ Request
416
+
417
+ No-cookie attempt
418
+
419
+ Success?
420
+ ┌───────┴───────┐
421
+ YES NO
422
+ ↓ ↓
423
+ DONE ReiZyuki
424
+
425
+ cookie #1
426
+
427
+ works?
428
+ / \
429
+ YES NO
430
+ ↓ ↓
431
+ DONE cookie #2
432
+
433
+ ...
434
+
435
+ Rules:
436
+
437
+ 1. Try without cookies first.
438
+
439
+
440
+ 2. If successful, stop immediately.
441
+
442
+
443
+ 3. If it fails, use the supplied ReiZyuki paths.
444
+
445
+
446
+ 4. Test cookie files one-by-one.
447
+
448
+
449
+ 5. The first working cookie is selected.
450
+
451
+
452
+ 6. If all cookies fail, raise the original no-cookie error.
453
+
454
+
455
+
456
+ This applies to:
457
+
458
+ video downloads
459
+
460
+ image downloads
461
+
462
+ media operations
463
+
464
+ playlists
465
+
466
+ metadata extraction
467
+
468
+ supported yt-dlp operations
469
+
470
+ supported gallery-dl operations
471
+
472
+
473
+ EasyTasks does not:
474
+
475
+ scan random directories
476
+
477
+ invent cookie files
478
+
479
+ require specific cookie filenames
480
+
481
+ automatically search for cookies
482
+
483
+ hardcode website-specific cookie filenames
484
+
485
+
486
+ Only paths supplied by the user through ReiZyuki are candidates.
487
+
488
+
489
+ ---
490
+
491
+ Observer
492
+
493
+ EasyTasks includes an Observer for ranking supplied cookie paths.
494
+
495
+ Observer can consider:
496
+
497
+ URL relevance
498
+
499
+ cookie filename relevance
500
+
501
+ previous successful cookie history
502
+
503
+
504
+ The Observer score is a ranking/relevance score.
505
+
506
+ It does not mean that a cookie is partially valid.
507
+
508
+ A cookie must still be tested by the actual downloader.
509
+
510
+ Example:
511
+
512
+ [Observer]
513
+
514
+ instagram.txt -> 78.85% match
515
+ youtube.txt -> 21.25% match
516
+ reddit.txt -> 20.00% match
517
+
518
+ Selected order:
519
+
520
+ 1. instagram.txt
521
+ 2. youtube.txt
522
+ 3. reddit.txt
523
+
524
+ The highest-ranked cookie is tested first.
525
+
526
+
527
+ ---
528
+
529
+ Playlist
530
+
531
+ Playlist syntax is fixed:
532
+
533
+ from easytasks import rz
534
+
535
+ rz({
536
+ "playlist": "QUALITY:SKIP:COUNT"
537
+ }, playlist_url)
538
+
539
+ The quality mapping is:
540
+
541
+ Value Meaning
542
+
543
+ 0 Best available audio
544
+ 1 360p
545
+ 2 480p
546
+ 3 720p
547
+ 4 1080p
548
+ 5 1440p
549
+ 6 Best available
550
+
551
+
552
+ Example:
553
+
554
+ rz({
555
+ "playlist": "4:5:10"
556
+ }, playlist_url)
557
+
558
+ This means:
559
+
560
+ 4 → 1080p
561
+ 5 → skip first 5 items
562
+ 10 → download next 10 items
563
+
564
+ Therefore:
565
+
566
+ Items 1–5 → skipped
567
+ Items 6–15 → downloaded
568
+
569
+ Quality fallback also applies to playlist downloads.
570
+
571
+
572
+ ---
573
+
574
+ Playlist + Media + Metadata
575
+
576
+ Playlist processing can be combined with media and metadata selectors.
577
+
578
+ from easytasks import rz
579
+
580
+ rz({
581
+ "playlist": "4:5:10",
582
+ "media[4]": "M",
583
+ "title": "T",
584
+ "creator": "C",
585
+ "url": "U",
586
+ "views": "V",
587
+ "likes": "L",
588
+ "comments": "CM",
589
+ "duration": "D",
590
+ "thumbnail": "TH"
591
+ }, playlist_url)
592
+
593
+ print(M)
594
+ print(T)
595
+ print(C)
596
+
597
+
598
+ ---
599
+
600
+ FFmpeg
601
+
602
+ FFmpeg is used when required to merge separate video and audio streams.
603
+
604
+ EasyTasks avoids unnecessary re-encoding.
605
+
606
+ When compatible source streams are available, the downloader prefers:
607
+
608
+ H.264 / AVC video
609
+ AAC / M4A audio
610
+
611
+ and produces MP4 output when merging is required.
612
+
613
+ The goal is to preserve source quality while producing compatible media.
614
+
615
+
616
+ ---
617
+
618
+ yt-dlp
619
+
620
+ yt-dlp handles video-based operations such as:
621
+
622
+ video[N]
623
+
624
+ video detection through media[N]
625
+
626
+ playlist downloads
627
+
628
+ supported metadata extraction
629
+
630
+
631
+
632
+ ---
633
+
634
+ gallery-dl
635
+
636
+ gallery-dl handles:
637
+
638
+ image
639
+
640
+ image/gallery detection through media[N]
641
+
642
+
643
+ The user does not need to manually call gallery-dl when using media[N].
644
+
645
+
646
+ ---
647
+
648
+ Default Download Directory
649
+
650
+ Downloaded media is stored by default in:
651
+
652
+ /storage/emulated/0/Download/ReiDownloader/
653
+
654
+
655
+ ---
656
+
657
+ Complete Examples
658
+
659
+ Video Download
660
+
661
+ from easytasks import rz
662
+
663
+ rz({
664
+ "video[4]": "V"
665
+ }, "https://example.com/video")
666
+
667
+ print(V)
668
+
669
+ Audio
670
+
671
+ from easytasks import rz
672
+
673
+ rz({
674
+ "video[0]": "A"
675
+ }, "https://example.com/video")
676
+
677
+ print(A)
678
+
679
+ Automatic Media
680
+
681
+ from easytasks import rz
682
+
683
+ rz({
684
+ "media[4]": "M"
685
+ }, "https://example.com/media")
686
+
687
+ print(M)
688
+
689
+ Image
690
+
691
+ from easytasks import rz
692
+
693
+ rz({
694
+ "image": "IMG"
695
+ }, "https://example.com/image")
696
+
697
+ print(IMG)
698
+
699
+ Metadata
700
+
701
+ from easytasks import rz
702
+
703
+ rz({
704
+ "title": "T",
705
+ "creator": "C",
706
+ "views": "V"
707
+ }, url)
708
+
709
+ print(T)
710
+ print(C)
711
+ print(V)
712
+
713
+ Cookies
714
+
715
+ from easytasks import rz
716
+
717
+ ReiZyuki = [
718
+ "/storage/emulated/0/Download/instagram.txt"
719
+ ]
720
+
721
+ rz({
722
+ "image": "IMG"
723
+ }, "https://www.instagram.com/example/")
724
+
725
+ print(IMG)
726
+
727
+ Playlist
728
+
729
+ from easytasks import rz
730
+
731
+ rz({
732
+ "playlist": "4:5:10"
733
+ }, "https://example.com/playlist")
734
+
735
+
736
+ ---
737
+
738
+ Invalid Syntax
739
+
740
+ Invalid Video Selector
741
+
742
+ This is invalid:
743
+
744
+ rz({
745
+ "video": "V"
746
+ }, url)
747
+
748
+ Use a quality selector:
749
+
750
+ rz({
751
+ "video[4]": "V"
752
+ }, url)
753
+
754
+
755
+ ---
756
+
757
+ Invalid Image Quality Selector
758
+
759
+ This is invalid:
760
+
761
+ rz({
762
+ "image[4]": "IMG"
763
+ }, url)
764
+
765
+ Use:
766
+
767
+ rz({
768
+ "image": "IMG"
769
+ }, url)
770
+
771
+
772
+ ---
773
+
774
+ Invalid Quality
775
+
776
+ Quality values outside 0–6 are invalid.
777
+
778
+ For example:
779
+
780
+ rz({
781
+ "video[10]": "V"
782
+ }, url)
783
+
784
+ is invalid.
785
+
786
+
787
+ ---
788
+
789
+ Invalid Playlist Format
790
+
791
+ This is invalid:
792
+
793
+ rz({
794
+ "playlist": "1080p:5:10"
795
+ }, url)
796
+
797
+ Use the numeric quality format:
798
+
799
+ rz({
800
+ "playlist": "4:5:10"
801
+ }, url)
802
+
803
+
804
+ ---
805
+
806
+ Quick Reference
807
+
808
+ Main API
809
+
810
+ from easytasks import rz
811
+
812
+ rz({...}, url)
813
+
814
+ Video
815
+
816
+ video[0] → audio
817
+ video[1] → 360p
818
+ video[2] → 480p
819
+ video[3] → 720p
820
+ video[4] → 1080p
821
+ video[5] → 1440p
822
+ video[6] → best
823
+
824
+ Media
825
+
826
+ media[0] → audio
827
+ media[1] → 360p
828
+ media[2] → 480p
829
+ media[3] → 720p
830
+ media[4] → 1080p
831
+ media[5] → 1440p
832
+ media[6] → best
833
+
834
+ Image
835
+
836
+ image
837
+
838
+ Metadata
839
+
840
+ title
841
+ creator
842
+ url
843
+ views
844
+ likes
845
+ comments
846
+ duration
847
+ thumbnail
848
+
849
+ Playlist
850
+
851
+ playlist = "QUALITY:SKIP:COUNT"
852
+
853
+ Cookies
854
+
855
+ ReiZyuki = [...]
856
+
857
+ Default Directory
858
+
859
+ /storage/emulated/0/Download/ReiDownloader/
860
+
861
+
862
+ ---
863
+
864
+ Public API Principle
865
+
866
+ EasyTasks is designed around a small CSS-inspired API:
867
+
868
+ rz({...}, url)
869
+
870
+ Selectors describe what EasyTasks should do, while the right-side values define the variable names through which the requested values are made available to the caller.