-
Notifications
You must be signed in to change notification settings - Fork 0
/
product_catalog.py
107 lines (92 loc) · 3.56 KB
/
product_catalog.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
from __future__ import print_function
import os, base64, preppy
from xml.sax.saxutils import escape, unescape
from rlextra.radxml.xmlutils import TagWrapper
from rlextra.radxml.html_cleaner import cleanInline
from rlextra.rml2pdf import rml2pdf
import pyRXPU
#required for python 2.7 & >=3.3
from reportlab.lib.utils import getBytesIO, isUnicode, asUnicode, asNative, asBytes, isPy3, unicodeT
DATA_DIR = 'data'
class Product(object):
"Empty class to hold parsed product attributes"
pass
def fix(tag):
"Apply fixes to their descriptive markup"
src = unicodeT(tag) #required for python 2.7 & >=3.3
step1 = src.replace(u'\x82',u'é')
step2 = unescape(step1)
step3 = step2.encode('utf-8')
return step3
def parse_catalog(filename):
"""Validate and parse XML. This will complain if invalid
We fully parse the XML and turn into Python variables, so that any encoding
issues are confronted here rather than in the template
"""
xml = open(filename).read()
if isUnicode(xml): xml = xml.encode('utf8') #required for python 2.7 & >=3.3
p = pyRXPU.Parser()
tree = p.parse(xml)
tagTree = TagWrapper(tree)
request_a_quote = [109,110,4121,4122,4123]
# we now need to de-duplicate; the query returns multiple rows with different images
# in them. if id is same, assume it's the same product.
ids_seen = set()
products = []
for prodTag in tagTree:
id = int(str(prodTag.ProductId1)) #extract tag content
if id in ids_seen:
continue
else:
ids_seen.add(id)
prod = Product()
prod.id = id
prod.modelNumber = int(str(prodTag.ModelNumber))
prod.archived = (str(prodTag.Archived) == 'true')
prod.name = fix(prodTag.ModelName)
prod.summary= fix(prodTag.Summary)
prod.description= fix(prodTag.Description)
#originally the images came from a remote site. We have stashed them in
#the img/ subdirectory, so just chop off the final part of the path.
#asNative required for python 2.7 & >=3.3
prod.image = os.path.split(asNative(fix(prodTag.ImageUrl)))[-1].replace(' ','')
if prod.modelNumber in request_a_quote:
prod.price = "Call us on 01635 246830 for a quote"
else:
prod.price = '£' + str(prodTag.UnitCost)[0:len(str(prodTag.UnitCost))-2]
if prod.archived:
pass
else:
products.append(prod)
products.sort(key=lambda x: x.modelNumber)
return products
def create_pdf(catalog, template):
"""Creates PDF as a binary stream in memory, and returns it
This can then be used to write to disk from management commands or crons,
or returned to caller via Django views.
"""
RML_DIR = 'rml'
templateName = os.path.join(RML_DIR, template)
template = preppy.getModule(templateName)
namespace = {
'products':catalog,
'RML_DIR': RML_DIR,
'IMG_DIR': 'img'
}
rml = template.getOutput(namespace)
open(os.path.join(DATA_DIR,'latest.rml'), 'w').write(rml)
buf = getBytesIO()
rml2pdf.go(asBytes(rml), outputFileName=buf)
return buf.getvalue()
def main():
filename = os.path.join(DATA_DIR, 'products.xml')
print('\n'+'#'*20)
print('\nabout to parse file: ', filename)
products = parse_catalog(filename)
print('file parsed OK \n')
pdf = create_pdf(products, 'flyer_template.prep')
filename ='output/harwood_flyer.pdf'
open(filename,'wb').write(pdf)
print('Created %s' % filename)
if __name__ == '__main__':
main()