Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
mikf
GitHub Repository: mikf/gallery-dl
Path: blob/master/scripts/generate_test_result.py
5457 views
1
#!/usr/bin/env python3
2
# -*- coding: utf-8 -*-
3
4
# Copyright 2025 Mike Fährmann
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License version 2 as
8
# published by the Free Software Foundation.
9
10
"""Generate test result data"""
11
12
import logging
13
import argparse
14
import json
15
import util
16
from pyprint import pyprint
17
from gallery_dl import extractor, job, config
18
19
LOG = logging.getLogger("gen-test")
20
21
22
def module_name(opts):
23
category = opts["category"]
24
if category[0].isdecimal():
25
return f"_{category}"
26
return category
27
28
29
def generate_test_result(args):
30
head = generate_head(args)
31
32
if args.only_matching:
33
opts = meta = None
34
else:
35
if args.options:
36
args.options_parsed = options = {}
37
for opt in args.options:
38
key, _, value = opt.partition("=")
39
try:
40
value = json.loads(value)
41
except ValueError:
42
pass
43
options[key] = value
44
config.set((), key, value)
45
if args.range:
46
config.set((), "image-range" , args.range)
47
config.set((), "chapter-range", args.range)
48
49
djob = job.DataJob(args.extr, file=None)
50
djob.filter = dict.copy
51
djob.run()
52
53
opts = generate_opts(args, djob.data_urls, djob.exception)
54
ool = (len(opts) > 1 or "#options" in opts)
55
56
if args.metadata:
57
meta = generate_meta(args, djob.data_meta)
58
else:
59
meta = None
60
61
result = pyprint(head, oneline=False, lmin=9)
62
if opts:
63
result = result[:-2] + pyprint(opts, oneline=ool, lmin=9)[1:]
64
if meta:
65
result = result[:-1] + pyprint(meta, sort=sort_key)[1:]
66
return result + ",\n\n"
67
68
69
def generate_head(args):
70
head = {}
71
cls = args.cls
72
73
head["#url"] = args.extr.url
74
if args.comment is not None:
75
head["#comment"] = args.comment
76
if args.base or args.cat != cls.category or args.sub != cls.subcategory:
77
head["#category"] = (args.base, args.cat, args.sub)
78
head["#class"] = args.cls
79
80
return head
81
82
83
def generate_opts(args, urls, exc=None):
84
opts = {}
85
86
if args.options:
87
opts["#options"] = args.options_parsed
88
89
if args.range:
90
opts["#range"] = args.range
91
92
if exc:
93
opts["#exception"] = exc.__class__
94
elif not urls:
95
opts["#count"] = 0
96
elif len(urls) == 1:
97
opts["#results"] = urls[0]
98
elif len(urls) < args.limit_urls:
99
opts["#results"] = tuple(urls)
100
else:
101
import re
102
opts["#pattern"] = re.escape(urls[0])
103
opts["#count"] = len(urls)
104
105
return opts
106
107
108
def generate_meta(args, data):
109
if not data:
110
return {}
111
112
for kwdict in data:
113
delete = ["category", "subcategory"]
114
for key in kwdict:
115
if not key or key[0] == "_":
116
delete.append(key)
117
for key in delete:
118
del kwdict[key]
119
120
return data[0]
121
122
123
def sort_key(key, value):
124
if not value:
125
return 0
126
if isinstance(value, str) and "\n" in value:
127
return 7000
128
if isinstance(value, list) and len(value) > 1:
129
return 8000
130
if isinstance(value, dict):
131
return 9000
132
return 0
133
134
135
def insert_test_result(args, result, lines):
136
idx_block = None
137
flag = False
138
139
for idx, line in enumerate(lines):
140
line = line.lstrip()
141
if not line:
142
continue
143
elif line[0] == "{":
144
idx_block = idx
145
elif line.startswith('"#class"'):
146
if args.cls.__name__ in line:
147
flag = True
148
elif flag:
149
flag = None
150
break
151
152
if idx_block is None or flag is not None:
153
lines.insert(-1, result)
154
else:
155
lines.insert(idx_block, result)
156
157
158
def parse_args(args=None):
159
parser = argparse.ArgumentParser(args)
160
parser.add_argument("-c", "--comment", default=None)
161
parser.add_argument("-C", dest="comment", action="store_const", const="")
162
parser.add_argument("-g", "--git", action="store_true")
163
parser.add_argument("-l", "--limit_urls", type=int, default=10)
164
parser.add_argument("-m", "--metadata", action="store_true")
165
parser.add_argument("-o", "--option", dest="options", action="append")
166
parser.add_argument("-O", "--only-matching", action="store_true")
167
parser.add_argument("-r", "--range")
168
parser.add_argument("URL")
169
170
return parser.parse_args()
171
172
173
def main():
174
args = parse_args()
175
args.url = args.URL
176
177
extr = extractor.find(args.url)
178
if extr is None:
179
LOG.error("Unsupported URL '%s'", args.url)
180
raise SystemExit(1)
181
182
args.extr = extr
183
args.cls = extr.__class__
184
args.cat = extr.category
185
args.sub = extr.subcategory
186
args.base = extr.basecategory
187
188
LOG.info("Collecting data for '%s'", args.url)
189
result = generate_test_result(args)
190
191
path = util.path("test", "results", f"{args.cat}.py")
192
path_tr = util.trim(path)
193
LOG.info("Writing '%s' results to '%s'", args.url, path_tr)
194
with util.lines(path) as lines:
195
insert_test_result(args, result, lines)
196
197
if args.git:
198
LOG.info("git add %s", path_tr)
199
util.git("add", "--", path_tr)
200
201
202
if __name__ == "__main__":
203
logging.basicConfig(
204
level=logging.DEBUG,
205
format="[%(levelname)s] %(message)s",
206
)
207
main()
208
209