import json import os import sys import lxml.etree as etree from nitpo import Nitpo import filing import uuid import subprocess class Sheets(Nitpo): def __init__(self, do_verbose=False): super().__init__() # # complied stylesheets, done once self.sheets = {} if not self.has_conf('folders', 'style'): print("sheets need a folder to continue.") sys.exit() self.do_verbose = do_verbose return None def load_sheet(self, shena): sheet_fufi = self.get_sheet_fufi(shena) sheet_doc = etree.parse(sheet_fufi) sheet = etree.XSLT(sheet_doc) sheet.set_global_max_depth(1000000) self.sheets[shena] = sheet return sheet def return_sheet(self, shena): sheet_fufi = self.get_sheet_fufi(shena) if self.do_verbose: print(f"sheets chooses fufi {sheet_fufi}") sheet_doc = etree.parse(sheet_fufi) sheet = etree.XSLT(sheet_doc) #sheet.set_global_max_depth(1000000) return sheet def get_result(self, shena, in_doc, params=None): """uses a sheet name""" if shena not in self.sheets: # print(f"sheets loads {shena}", file=sys.stderr) self.load_sheet(shena) this_sheet = self.sheets[shena] if params is None: result = this_sheet(in_doc) else: # # don't know what the ** means here result = this_sheet(in_doc, **params) return result def get_sheet_fufi(self, shena): """get a sheet, in many ways""" if os.path.isfile(shena): return shena if self.has_conf('sheets', shena): sheet_fufi = self.conf['sheets'][shena] return sheet_fufi bana = shena + self.const['xslt_ext'] if self.has_conf('folders', 'empros'): empro_dir = self.conf['folders']['empros'] test_fufi = empro_dir + '/' + bana if os.path.isfile(test_fufi): return test_fufi if self.has_conf('folders', 'xslt'): sheet_fufi = self.conf['folders']['xslt'] + '/' + bana # print(sheet_fufi) if os.path.isfile(sheet_fufi): return sheet_fufi sheet_fufi = self.conf['folders']['style'] + '/' + bana if os.path.isfile(sheet_fufi): return sheet_fufi raise Exception(f"I don't see a sheet file for {shena}") def fufi_to_fufi(self, shena, in_fufi, out_fufi, params=None): sheet_fufi = self.get_sheet_fufi(shena) if not filing.donere(out_fufi, [sheet_fufi, in_fufi]): return False in_doc = etree.parse(in_fufi) out_doc = self.get_result(shena, in_doc) out_bytes = bytes(out_doc) out_string = out_bytes.decode('utf-8') filing.prepare(out_fufi) filing.srite(out_fufi, out_string) return out_string def fufi_to_docu(self, shena, in_fufi, out_fufi, params=None): sheet_fufi = self.get_sheet_fufi(shena) if not filing.donere(out_fufi, [sheet_fufi, in_fufi]): return False in_doc = etree.parse(in_fufi) out_doc = self.get_result(shena, in_doc) out_bytes = bytes(out_doc) out_string = out_bytes.decode('utf-8') filing.prepare(out_fufi) filing.srite(out_fufi, out_string) return out_string def fufi_to_string(self, shena, in_fufi, params=None): sheet_fufi = self.get_sheet_fufi(shena) in_doc = etree.parse(in_fufi) out_doc = self.get_result(shena, in_doc) out_bytes = bytes(out_doc) out_string = out_bytes.decode('utf-8') return out_string def via_system(self, shena, in_doc): """for papers screen transformation because so maxvars in lxml""" sheet_fufi = self.get_sheet_fufi(shena) randna = '/tmp/' + str(uuid.uuid4())[:8] out_fufi = randna + '_out.xml' in_fufi = randna + '_in.xml' in_doc.write(in_fufi, pretty_print=True) err_fufi = randna + '.err' args = '--maxvars 1000000 --maxdepth 1000000' s = f"/usr/bin/xsltproc {args} {sheet_fufi} {in_fufi}" s += f" > {out_fufi} 2> {err_fufi}" try: subprocess.run(s, check=True, shell=True) except subprocess.CalledProcessError: err_file = open(err_fufi, 'r') err = err_file.read() print(err, file=sys.stderr) return None ## try read as XML, if that fails, it's text try: doc = etree.parse(out_fufi) except etree.XMLSyntaxError: out_file = open(out_fufi, 'r') doc = out_file.read() for fufi in [in_fufi, out_fufi, err_fufi]: if os.path.isfile(fufi): os.remove(fufi) return doc