flinventory 0.5.0__tar.gz → 0.6.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.
- {flinventory-0.5.0 → flinventory-0.6.0}/PKG-INFO +1 -1
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/generate_labels.py +59 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/location.py +6 -3
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/signprinter_latex.py +166 -56
- {flinventory-0.5.0 → flinventory-0.6.0}/pyproject.toml +1 -1
- {flinventory-0.5.0 → flinventory-0.6.0}/LICENSE +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/README.md +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/__init__.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/__main__.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/box.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/constant.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/datacleanup.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/defaulted_data.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/inventory_io.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/sign.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/thing.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/thingtemplate_latex/.gitignore +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/thingtemplate_latex/dummyImage.jpg +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/thingtemplate_latex/sign.tex +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/thingtemplate_latex/signlist-footer.tex +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/thingtemplate_latex/signlist-header.tex +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/flinventory/thingtemplate_latex/signs-example.tex +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/tests/__init__.py +0 -0
- {flinventory-0.5.0 → flinventory-0.6.0}/tests/test_defaulted_data.py +0 -0
@@ -1,6 +1,7 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
"""Create a list of things to hang in the place with all the stuff (e.g. a bike shed)."""
|
3
3
|
import logging
|
4
|
+
|
4
5
|
import pypandoc
|
5
6
|
|
6
7
|
import argparse
|
@@ -70,6 +71,16 @@ def add_arg_parsers(subparsers):
|
|
70
71
|
|
71
72
|
parser.set_defaults(func=generate_labels)
|
72
73
|
|
74
|
+
parser_single_sign = subparsers.add_parser(
|
75
|
+
"single_sign", description="Create a single sign as svg."
|
76
|
+
)
|
77
|
+
parser_single_sign.add_argument(
|
78
|
+
"thing_id",
|
79
|
+
help="Thing id of the thing the sign is for. "
|
80
|
+
"This is the directory name of the thing.",
|
81
|
+
)
|
82
|
+
parser_single_sign.set_defaults(func=generate_single_sign_svg)
|
83
|
+
|
73
84
|
|
74
85
|
def get_markdown_list(things):
|
75
86
|
"""Get markdown representation of thing list."""
|
@@ -212,3 +223,51 @@ def generate_labels(options: argparse.Namespace):
|
|
212
223
|
sign_printer_latex.create_signs_pdf(all_things)
|
213
224
|
else:
|
214
225
|
sign_printer_latex.save_signs_latex(all_things)
|
226
|
+
|
227
|
+
|
228
|
+
def generate_single_sign_svg(options: argparse.Namespace):
|
229
|
+
"""Generate sign for a single thing, given by options.thing_id.
|
230
|
+
|
231
|
+
Args:
|
232
|
+
options: command line options given
|
233
|
+
"""
|
234
|
+
try:
|
235
|
+
os.mkdir(options.output_dir)
|
236
|
+
except FileExistsError:
|
237
|
+
pass # everything fine
|
238
|
+
logging.basicConfig(
|
239
|
+
filename=os.path.join(options.output_dir, options.logfile),
|
240
|
+
level=logging.DEBUG,
|
241
|
+
filemode="w",
|
242
|
+
)
|
243
|
+
logging.info("Create thing sign")
|
244
|
+
all_things = inventory_io.Inventory.from_json_files(options.dataDirectory)
|
245
|
+
logging.info("Start creating sign svg.")
|
246
|
+
try:
|
247
|
+
thing = all_things.get_by_id(options.thing_id)
|
248
|
+
except KeyError as id_not_found:
|
249
|
+
print("key error:")
|
250
|
+
print(id_not_found)
|
251
|
+
possible_things = list(all_things.get_by_best("name", options.thing_id))
|
252
|
+
if len(possible_things) == 1:
|
253
|
+
thing = possible_things[0]
|
254
|
+
else:
|
255
|
+
error_message = (
|
256
|
+
f"No thing with the id {options.thing_id} and 0 or >1 thing "
|
257
|
+
f"with this name. Do not do anything."
|
258
|
+
)
|
259
|
+
logging.error(error_message)
|
260
|
+
print(error_message)
|
261
|
+
return
|
262
|
+
sign_printer_latex = SignPrinterLaTeX(options)
|
263
|
+
svg_path = sign_printer_latex.create_sign_svg(thing)
|
264
|
+
if svg_path:
|
265
|
+
print(
|
266
|
+
f"sign svg created for {thing.best('name', backup="?")} "
|
267
|
+
f"({options.thing_id}): find it at {svg_path}"
|
268
|
+
)
|
269
|
+
else:
|
270
|
+
print(
|
271
|
+
f"Error at creating sign for {thing.best('name', backup="?")} "
|
272
|
+
f"({options.thing_id})."
|
273
|
+
)
|
@@ -283,6 +283,9 @@ class Location(dict[str, Value]):
|
|
283
283
|
options: global options including the seperator
|
284
284
|
"""
|
285
285
|
|
286
|
+
EMPTY: list[Any] = [None, "", [], {}]
|
287
|
+
"""Values that are considered empty and mean that nothing should be saved."""
|
288
|
+
|
286
289
|
def __init__(
|
287
290
|
self,
|
288
291
|
schema: Schema,
|
@@ -356,11 +359,11 @@ class Location(dict[str, Value]):
|
|
356
359
|
def __setitem__(self, level: str, value: Value) -> None:
|
357
360
|
"""Set one level info.
|
358
361
|
|
359
|
-
Or deletes it if it's None or "" or [] or {}
|
362
|
+
Or deletes it if it's None or "" or [] or {} (see EMPTY)
|
360
363
|
|
361
364
|
Update internal info.
|
362
365
|
"""
|
363
|
-
if value in
|
366
|
+
if value in self.EMPTY:
|
364
367
|
if level in self:
|
365
368
|
del self[level]
|
366
369
|
else:
|
@@ -406,7 +409,7 @@ class Location(dict[str, Value]):
|
|
406
409
|
Sorts by schema hierarchy.
|
407
410
|
"""
|
408
411
|
self._levels = self.schema.get_schema_hierarchy(self)
|
409
|
-
as_dict = {
|
412
|
+
as_dict: dict[str, Value] = {
|
410
413
|
level.levelname: self._levels[index + 1].name
|
411
414
|
for index, level in list(enumerate(self._levels))[:-1]
|
412
415
|
}
|
@@ -9,7 +9,7 @@ import importlib.resources
|
|
9
9
|
import os.path
|
10
10
|
import logging
|
11
11
|
import subprocess
|
12
|
-
from typing import Union, Iterable
|
12
|
+
from typing import Union, Iterable, Optional
|
13
13
|
|
14
14
|
from .box import BoxedThing
|
15
15
|
from .sign import Sign
|
@@ -18,7 +18,7 @@ from . import thingtemplate_latex
|
|
18
18
|
|
19
19
|
TEMPLATE_PACKAGE = thingtemplate_latex
|
20
20
|
TEMPLATE_PRE = "signlist-header.tex"
|
21
|
-
|
21
|
+
# importlib.resources.read_text("flinventory", "signlist-header.tex"))
|
22
22
|
TEMPLATE_POST = "signlist-footer.tex"
|
23
23
|
TEMPLATE_SIGN = "sign.tex"
|
24
24
|
DUMMY_IMAGE = "dummyImage.jpg"
|
@@ -59,6 +59,7 @@ MAX_WIDTH = 18 # otherwise too wide for A4 page
|
|
59
59
|
MAX_HEIGHT = 28 # otherwise too long for A4 page
|
60
60
|
# maximum height for a sign [cm]
|
61
61
|
|
62
|
+
|
62
63
|
def sanitize_latex_code(latex: Union[str, int, float]):
|
63
64
|
"""Make a string insertable into LaTeX code.
|
64
65
|
|
@@ -113,11 +114,14 @@ class SignPrinterLaTeX:
|
|
113
114
|
# todo remove function by using importlib, which gives directly the text
|
114
115
|
file_contents = []
|
115
116
|
for filename in [TEMPLATE_PRE, TEMPLATE_SIGN, TEMPLATE_POST]:
|
116
|
-
file_contents.append(
|
117
|
+
file_contents.append(
|
118
|
+
importlib.resources.read_text(TEMPLATE_PACKAGE, filename)
|
119
|
+
)
|
117
120
|
return file_contents
|
118
121
|
|
119
|
-
def controlled_length(
|
120
|
-
|
122
|
+
def controlled_length(
|
123
|
+
self, sign: Sign, key: str, backup: Union[int, float], max: Union[int, float]
|
124
|
+
):
|
121
125
|
"""Get the value for the key if it exists and is a number and < max, otherwise backup."""
|
122
126
|
value = sign.get(key, backup)
|
123
127
|
try:
|
@@ -126,8 +130,10 @@ class SignPrinterLaTeX:
|
|
126
130
|
self.logger(f"{key} {value} is not a number. Use {backup} {UNIT} instead.")
|
127
131
|
return backup
|
128
132
|
if value <= 0:
|
129
|
-
self.logger(
|
130
|
-
|
133
|
+
self.logger(
|
134
|
+
f"{key} {value} is non-positive and therefore not a valid sign {key}. "
|
135
|
+
f"Use {backup} {UNIT} instead."
|
136
|
+
)
|
131
137
|
return backup
|
132
138
|
if value == int(value):
|
133
139
|
return min(int(value), max)
|
@@ -138,11 +144,15 @@ class SignPrinterLaTeX:
|
|
138
144
|
|
139
145
|
In UNIT.
|
140
146
|
"""
|
141
|
-
return self.controlled_length(
|
147
|
+
return self.controlled_length(
|
148
|
+
thing.sign, key="width", backup=STANDARD_WIDTH, max=MAX_WIDTH
|
149
|
+
)
|
142
150
|
|
143
151
|
def height(self, thing: BoxedThing) -> Union[int, float]:
|
144
152
|
"""Get the height of the sign of a boxed thing, using backup and max size."""
|
145
|
-
return self.controlled_length(
|
153
|
+
return self.controlled_length(
|
154
|
+
thing.sign, key="height", backup=STANDARD_HEIGHT, max=MAX_HEIGHT
|
155
|
+
)
|
146
156
|
|
147
157
|
def if_use_landscape_template(self, thing: BoxedThing):
|
148
158
|
"""Return if we want to use the landscape template for this thing.
|
@@ -152,7 +162,7 @@ class SignPrinterLaTeX:
|
|
152
162
|
than high.
|
153
163
|
"""
|
154
164
|
try:
|
155
|
-
return thing.sign.get(
|
165
|
+
return thing.sign.get("landscape")
|
156
166
|
except KeyError:
|
157
167
|
try:
|
158
168
|
return self.width(thing) >= self.width(thing) * LANDSCAPE_MIN_RATIO
|
@@ -180,11 +190,11 @@ class SignPrinterLaTeX:
|
|
180
190
|
width = self.width(thing)
|
181
191
|
height = self.height(thing)
|
182
192
|
used_width = width - height # that is approximately the part the image uses
|
183
|
-
german = thing.sign.get((
|
184
|
-
english = thing.sign.get((
|
193
|
+
german = thing.sign.get(("name", 0), "")
|
194
|
+
english = thing.sign.get(("name", 1), "")
|
185
195
|
german_expected_width_at_standard = len(german) * STANDARD_LETTER_LENGTH
|
186
196
|
german_max_by_width = (
|
187
|
-
|
197
|
+
STANDARD_FONT_SIZE_GERMAN * used_width / german_expected_width_at_standard
|
188
198
|
)
|
189
199
|
german_max_by_height = (
|
190
200
|
height
|
@@ -193,10 +203,10 @@ class SignPrinterLaTeX:
|
|
193
203
|
* GERMAN_TO_ENGLISH_SHARE
|
194
204
|
)
|
195
205
|
english_expected_width_at_standard = (
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
206
|
+
len(english)
|
207
|
+
* STANDARD_LETTER_LENGTH
|
208
|
+
* STANDARD_FONTSIZE_ENGLISH
|
209
|
+
/ STANDARD_FONT_SIZE_GERMAN
|
200
210
|
)
|
201
211
|
english_max_by_width = (
|
202
212
|
STANDARD_FONTSIZE_ENGLISH * used_width / english_expected_width_at_standard
|
@@ -218,8 +228,8 @@ class SignPrinterLaTeX:
|
|
218
228
|
"""
|
219
229
|
# use german and english as aliases for primary and secondary language
|
220
230
|
# because it's easier to read
|
221
|
-
german = thing.get((
|
222
|
-
english = thing.get((
|
231
|
+
german = thing.get(("name", 0), "")
|
232
|
+
english = thing.get(("name", 1), "")
|
223
233
|
german_words = german.replace("-", "- ").split() or [" "]
|
224
234
|
english_words = english.replace("-", " ").split() or [" "]
|
225
235
|
# ignore cases with more than 2 lines, should be considered by hand
|
@@ -257,23 +267,23 @@ class SignPrinterLaTeX:
|
|
257
267
|
)
|
258
268
|
german_expected_width_at_standard = german_length * STANDARD_LETTER_LENGTH
|
259
269
|
german_max_by_width = (
|
260
|
-
|
270
|
+
STANDARD_FONT_SIZE_GERMAN * width / german_expected_width_at_standard
|
261
271
|
)
|
262
272
|
text_height = height * (
|
263
273
|
1 if height < MINIMAL_HEIGHT_FOR_IMAGE else IMAGE_SHARE
|
264
274
|
)
|
265
275
|
german_max_by_height = (
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
276
|
+
STANDARD_FONT_SIZE_GERMAN
|
277
|
+
* text_height
|
278
|
+
/ STANDARD_LETTER_HEIGHT
|
279
|
+
/ (german_number_lines * GERMAN_TO_ENGLISH_SHARE + english_number_lines)
|
280
|
+
* GERMAN_TO_ENGLISH_SHARE
|
271
281
|
)
|
272
282
|
english_expected_width_at_standard = (
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
283
|
+
english_length
|
284
|
+
* STANDARD_LETTER_LENGTH
|
285
|
+
* STANDARD_FONTSIZE_ENGLISH
|
286
|
+
/ STANDARD_FONT_SIZE_GERMAN
|
277
287
|
)
|
278
288
|
# in factor size compared to normal size
|
279
289
|
english_max_by_width = (
|
@@ -324,19 +334,34 @@ class SignPrinterLaTeX:
|
|
324
334
|
Returns:
|
325
335
|
(german font size, english font size)
|
326
336
|
"""
|
327
|
-
default_german_font_size, default_english_font_size = self.guess_font_size(
|
328
|
-
|
329
|
-
|
337
|
+
default_german_font_size, default_english_font_size = self.guess_font_size(
|
338
|
+
thing
|
339
|
+
)
|
340
|
+
german_font_size = thing.sign.get(("fontsize", 0), default_german_font_size)
|
341
|
+
english_font_size = thing.sign.get(("fontsize", 1), default_english_font_size)
|
330
342
|
logging.info(
|
331
343
|
f"{thing.best('name')} font factor: (de) {german_font_size} (en) {english_font_size}"
|
332
344
|
)
|
333
345
|
return german_font_size, english_font_size
|
334
346
|
|
335
|
-
def
|
347
|
+
def create_latex_single_sign(self, thing: BoxedThing) -> str:
|
348
|
+
"""Create latex code (as str) that shows one sign in a minimal document."""
|
349
|
+
return "\n".join(
|
350
|
+
(
|
351
|
+
r"\documentclass{standalone}",
|
352
|
+
*(self.pre.splitlines()[2:]),
|
353
|
+
self.create_sign(thing),
|
354
|
+
self.post,
|
355
|
+
)
|
356
|
+
)
|
357
|
+
|
358
|
+
def create_latex(self, things: Iterable[BoxedThing]) -> str:
|
336
359
|
"""Create latex code (as str) that shows all signs.
|
337
360
|
|
338
361
|
Arguments:
|
339
362
|
things: list of things to be described
|
363
|
+
Return:
|
364
|
+
latex code with document with all signs that should be printed
|
340
365
|
"""
|
341
366
|
content_latex = [self.pre]
|
342
367
|
current_line_filled_width = 0
|
@@ -367,8 +392,8 @@ class SignPrinterLaTeX:
|
|
367
392
|
imageheight
|
368
393
|
location
|
369
394
|
"""
|
370
|
-
german = thing.sign.get((
|
371
|
-
english = thing.sign.get((
|
395
|
+
german = thing.sign.get(("name", 0), "")
|
396
|
+
english = thing.sign.get(("name", 1), "")
|
372
397
|
|
373
398
|
width = self.width(thing)
|
374
399
|
height = self.height(thing)
|
@@ -382,9 +407,7 @@ class SignPrinterLaTeX:
|
|
382
407
|
}
|
383
408
|
|
384
409
|
if not insertions["location"]: # empty string
|
385
|
-
logging.warning(
|
386
|
-
f"Print sign for {german} ({english}) without location."
|
387
|
-
)
|
410
|
+
logging.warning(f"Print sign for {german} ({english}) without location.")
|
388
411
|
|
389
412
|
# todo: make image height configurable
|
390
413
|
if height < MINIMAL_HEIGHT_FOR_IMAGE:
|
@@ -397,10 +420,7 @@ class SignPrinterLaTeX:
|
|
397
420
|
# at first only portrait sign, landscape sign can be implemented later
|
398
421
|
# if self.if_use_landscape_template(thing): # would need different condition
|
399
422
|
if image_path := thing.thing.image_path(): # not None or ""
|
400
|
-
rel_path_to_image = os.path.relpath(
|
401
|
-
image_path,
|
402
|
-
self.output_dir
|
403
|
-
)
|
423
|
+
rel_path_to_image = os.path.relpath(image_path, self.output_dir)
|
404
424
|
insertions["imagepath"] = rel_path_to_image
|
405
425
|
else:
|
406
426
|
if insertions["imageheight"] > 0:
|
@@ -414,15 +434,18 @@ class SignPrinterLaTeX:
|
|
414
434
|
except FileExistsError:
|
415
435
|
pass
|
416
436
|
else:
|
417
|
-
dummy_image = importlib.resources.read_binary(
|
437
|
+
dummy_image = importlib.resources.read_binary(
|
438
|
+
TEMPLATE_PACKAGE, DUMMY_IMAGE
|
439
|
+
)
|
418
440
|
with image_file:
|
419
441
|
image_file.write(dummy_image)
|
420
442
|
font_sizes = self.get_font_size(thing)
|
421
443
|
insertions["textscalePrimary"] = font_sizes[0] # /12
|
422
444
|
insertions["textscaleSecondary"] = font_sizes[1] # /12
|
423
445
|
|
424
|
-
insertions["locationShiftDown"] = thing.sign.get(
|
425
|
-
|
446
|
+
insertions["locationShiftDown"] = thing.sign.get(
|
447
|
+
"location_shift_down", STANDARD_LOCATION_SHIFT_DOWN
|
448
|
+
)
|
426
449
|
return insertions
|
427
450
|
|
428
451
|
def create_sign(self, thing):
|
@@ -444,7 +467,7 @@ class SignPrinterLaTeX:
|
|
444
467
|
Arguments:
|
445
468
|
things: list of things to visualize
|
446
469
|
Returns:
|
447
|
-
path to created file
|
470
|
+
path to created file. None in case of error.
|
448
471
|
"""
|
449
472
|
things.sort(key=lambda t: self.height(t))
|
450
473
|
file_signs = os.path.join(self.output_dir, self.signs_file)
|
@@ -456,16 +479,103 @@ class SignPrinterLaTeX:
|
|
456
479
|
def create_signs_pdf(self, things: list[BoxedThing]):
|
457
480
|
"""Create a pdf and latex files with signs."""
|
458
481
|
self.save_signs_latex(things)
|
459
|
-
latex = subprocess.run(
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
with open(
|
482
|
+
latex = subprocess.run(
|
483
|
+
["latexmk", self.signs_file, f"-aux-directory={AUX_DIR}", "-pdf"],
|
484
|
+
cwd=self.output_dir,
|
485
|
+
capture_output=True,
|
486
|
+
text=True,
|
487
|
+
) # text=True makes output a str instead of bytes
|
488
|
+
with open(
|
489
|
+
os.path.join(self.output_dir, AUX_DIR, "latex_output.txt"), mode="w"
|
490
|
+
) as stdout_file:
|
491
|
+
stdout_file.write(latex.stdout)
|
492
|
+
with open(
|
493
|
+
os.path.join(self.output_dir, AUX_DIR, "latex_error.txt"), mode="w"
|
494
|
+
) as stderr_file:
|
495
|
+
stderr_file.write(latex.stderr)
|
496
|
+
if latex.returncode != 0:
|
497
|
+
print(
|
498
|
+
f"Latex finished with returncode {latex.returncode}."
|
499
|
+
f"Check in {os.path.join(self.output_dir, AUX_DIR)} for details."
|
500
|
+
)
|
501
|
+
|
502
|
+
def create_sign_svg(self, thing: BoxedThing) -> Optional[str]:
|
503
|
+
"""Create a svg from a pdf with a sign for this thing.
|
504
|
+
|
505
|
+
Args:
|
506
|
+
thing: the thing which sign should be created
|
507
|
+
Returns:
|
508
|
+
path of the created svg file. None if error
|
509
|
+
"""
|
510
|
+
tex = self.create_latex_single_sign(thing)
|
511
|
+
tex_hash = str(abs(hash(tex)))
|
512
|
+
file_tex = tex_hash + ".tex"
|
513
|
+
path_tex = os.path.join(self.output_dir, tex_hash + ".tex")
|
514
|
+
file_pdf = tex_hash + ".pdf"
|
515
|
+
path_pdf = os.path.join(self.output_dir, file_pdf)
|
516
|
+
file_svg = tex_hash + ".svg"
|
517
|
+
path_svg = os.path.join(self.output_dir, file_svg)
|
518
|
+
if os.path.isfile(path_tex) and os.path.isfile(path_svg):
|
519
|
+
self.logger(f"Do not regenerate {tex_hash}.")
|
520
|
+
return file_svg
|
521
|
+
with open(path_tex, mode="w") as file_tex_f:
|
522
|
+
file_tex_f.write(tex)
|
523
|
+
latex = subprocess.run(
|
524
|
+
["latexmk", file_tex, f"-aux-directory={AUX_DIR}", "-pdf"],
|
525
|
+
cwd=self.output_dir,
|
526
|
+
capture_output=True,
|
527
|
+
text=True,
|
528
|
+
) # text=True makes output a str instead of bytes
|
529
|
+
with open(
|
530
|
+
os.path.join(self.output_dir, AUX_DIR, f"latex_output_{tex_hash}.txt"),
|
531
|
+
mode="w",
|
532
|
+
) as stdout_file:
|
466
533
|
stdout_file.write(latex.stdout)
|
467
|
-
with open(
|
534
|
+
with open(
|
535
|
+
os.path.join(self.output_dir, AUX_DIR, f"latex_error.{tex_hash}.txt"),
|
536
|
+
mode="w",
|
537
|
+
) as stderr_file:
|
468
538
|
stderr_file.write(latex.stderr)
|
469
539
|
if latex.returncode != 0:
|
470
|
-
|
471
|
-
|
540
|
+
error_message = (
|
541
|
+
f"Latex for {thing.best('name', backup=tex_hash)} "
|
542
|
+
f"finished with returncode {latex.returncode}."
|
543
|
+
f"Check in {os.path.join(self.output_dir, AUX_DIR)} ({tex_hash}) for details."
|
544
|
+
)
|
545
|
+
self.logger.error(error_message)
|
546
|
+
print(error_message)
|
547
|
+
return None
|
548
|
+
svg = subprocess.run(
|
549
|
+
["pdf2svg", path_pdf, path_svg],
|
550
|
+
capture_output=True,
|
551
|
+
text=True,
|
552
|
+
) # text=True makes output a str instead of bytes
|
553
|
+
with open(
|
554
|
+
os.path.join(self.output_dir, AUX_DIR, f"svg_output_{tex_hash}.txt"),
|
555
|
+
mode="w",
|
556
|
+
) as stdout_file:
|
557
|
+
stdout_file.write(svg.stdout)
|
558
|
+
with open(
|
559
|
+
os.path.join(self.output_dir, AUX_DIR, f"svg_error.{tex_hash}.txt"),
|
560
|
+
mode="w",
|
561
|
+
) as stderr_file:
|
562
|
+
stderr_file.write(svg.stderr)
|
563
|
+
if svg.returncode != 0:
|
564
|
+
error_message = (
|
565
|
+
f"svg for {thing.best('name', backup=tex_hash)} "
|
566
|
+
f"finished with returncode {svg.returncode}."
|
567
|
+
f"Check in {os.path.join(self.output_dir, tex_hash)}* for details."
|
568
|
+
)
|
569
|
+
self.logger.error(error_message)
|
570
|
+
print(error_message)
|
571
|
+
return None
|
572
|
+
if os.path.isfile(path_svg):
|
573
|
+
return path_svg
|
574
|
+
error_message = (
|
575
|
+
f"svg for {thing.best('name', backup=tex_hash)} "
|
576
|
+
f"finished with returncode 0 but the svg was not created. "
|
577
|
+
f"Check in {os.path.join(self.output_dir, tex_hash)}* for details."
|
578
|
+
)
|
579
|
+
self.logger.error(error_message)
|
580
|
+
print(error_message)
|
581
|
+
return None
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|