-
Notifications
You must be signed in to change notification settings - Fork 5
/
labelprinter.py
131 lines (109 loc) · 3.99 KB
/
labelprinter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import argparse
import csv
import codecs
import xml.etree.ElementTree as ET
import os
import subprocess
import time
import win32api
import win32print
from SvgTemplate import SvgTemplate, TextFilter, ShowFilter, BarcodeFilter, StyleFilter, SvgFilter
from SvgTemplate import strip_tag
if __name__ == '__main__':
parser = argparse.ArgumentParser(description="Prints labels from changed rows in a .csv file")
parser.add_argument('template', type=str,
help="SVG label template")
parser.add_argument('data', type=str,
help="CSV data")
parser.add_argument('output', type=str,
help="SVG generated temporary prefix")
parser.add_argument('--printer', type=str,
help="printer name, leave blank to only generate PDFs", default=None)
parser.add_argument('--copies', type=int, default=1,
help="number of copies to print for each label")
parser.add_argument('--only', type=str, default=None,
help="only process rows which have this key nonempty")
parser.add_argument('--data_fresh', action='store_true',
help="ignore the initial state of data (print all rows)")
args = parser.parse_args()
ET.register_namespace('', "http://www.w3.org/2000/svg")
if args.only:
if '=' in args.only:
split = args.only.split('=')
assert len(split) == 2
only_parse_key = split[0]
only_parse_val = split[1]
else:
only_parse_key = args.only
only_parse_val = None
else:
only_parse_key = None
# TODO: deduplicate standard filter transforms w/ labelmaker
template = SvgTemplate(args.template, [
TextFilter(),
ShowFilter(),
BarcodeFilter(),
StyleFilter(),
SvgFilter(),
])
# Get the filename without the SVG extension so the page number can be added
if args.output[-4:].lower() == '.svg'.lower():
output_name = args.output[:-4]
else:
output_name = args.output
def canonicalize_row_dict(row_dict):
return tuple(sorted([(k, v) for (k, v) in row_dict.items() if v]))
def traverse(file_name, row_dict_fn):
data_file = codecs.open(file_name, encoding='utf-8')
data_reader = csv.DictReader(data_file)
seen_set = set()
for row_dict in data_reader:
seen_set.add(canonicalize_row_dict(row_dict))
row_dict_fn(row_dict)
data_file.close()
return seen_set
def print_fn(seen_set):
def actual_fn(row_dict):
if (only_parse_key and
((only_parse_val is None and not row[only_parse_key]) or
(only_parse_val is not None and row[only_parse_key] != only_parse_val))):
return
canonical_row_dict = canonicalize_row_dict(row_dict)
if canonical_row_dict in seen_set:
return
print(canonical_row_dict)
output = template.clone_base()
svg_elt = output.getroot()
assert strip_tag(svg_elt.tag) == 'svg'
for elt in template.generate(row_dict):
svg_elt.append(elt)
output.write(output_name + ".svg")
subprocess.Popen([
'inkscape', output_name + '.svg' ,
'--export-filename=' + output_name + '.pdf'
]).communicate()
if args.printer is not None:
for i in range(args.copies):
win32api.ShellExecute(0,
"print", output_name + '.pdf',
'/d:"%s"' % args.printer, ".", 0)
return actual_fn
# Read in the current rows and ignore those
if args.data_fresh:
last_mod_time = None
seen_set = set()
else:
last_mod_time = os.path.getmtime(args.data)
seen_set = traverse(args.data, lambda x: x)
print(f"Ready, ignored initial {len(seen_set)} rows")
while True:
if os.path.isfile(args.data):
mod_time = os.path.getmtime(args.data)
if last_mod_time is None or mod_time != last_mod_time:
print("File modification detected")
seen_set = traverse(args.data, print_fn(seen_set))
print("Done")
last_mod_time = mod_time
else:
print("Warning: file not found")
time.sleep(0.25)