From 0360b5a774f3a0edd01c8850c491a66c82ea2f91 Mon Sep 17 00:00:00 2001 From: Mauricio Baeza Date: Sun, 11 Oct 2020 19:48:57 -0500 Subject: [PATCH] Update libraries --- CHANGELOG | 5 + README.md | 6 +- VERSION | 3 +- conf.py | 265 ++---------- easymacro.py | 94 ++++- ...rCode_v0.6.0.oxt => ZAZBarCode_v0.7.0.oxt} | Bin 297137 -> 297705 bytes files/zazbarcode.update.xml | 25 +- source/Addons.xcu | 399 +++++++++--------- source/Office/Accelerators.xcu | 8 +- source/description.xml | 24 +- source/pythonpath/barcode/__init__.py | 123 ++++-- source/pythonpath/barcode/base.py | 51 +-- source/pythonpath/barcode/charsets/code128.py | 251 +++++++++-- source/pythonpath/barcode/charsets/code39.py | 77 ++-- source/pythonpath/barcode/charsets/ean.py | 65 ++- source/pythonpath/barcode/charsets/itf.py | 21 +- source/pythonpath/barcode/charsets/upc.py | 37 +- source/pythonpath/barcode/codex.py | 147 +++---- source/pythonpath/barcode/ean.py | 95 +++-- source/pythonpath/barcode/errors.py | 9 +- .../barcode/{ => fonts}/DejaVuSansMono.ttf | Bin source/pythonpath/barcode/isxn.py | 73 ++-- source/pythonpath/barcode/itf.py | 49 +-- source/pythonpath/barcode/pybarcode.py | 132 +++--- source/pythonpath/barcode/upc.py | 86 ++-- source/pythonpath/barcode/version.py | 7 +- source/pythonpath/barcode/writer.py | 232 ++++++---- source/pythonpath/easymacro.py | 94 ++++- source/pythonpath/qrcode/main.py | 22 +- source/pythonpath/qrcode/util.py | 51 ++- zaz.py | 317 ++++++++++++-- 31 files changed, 1617 insertions(+), 1151 deletions(-) rename files/{ZAZBarCode_v0.6.0.oxt => ZAZBarCode_v0.7.0.oxt} (77%) mode change 100644 => 100755 source/pythonpath/barcode/__init__.py mode change 100644 => 100755 source/pythonpath/barcode/base.py mode change 100644 => 100755 source/pythonpath/barcode/codex.py mode change 100644 => 100755 source/pythonpath/barcode/ean.py mode change 100644 => 100755 source/pythonpath/barcode/errors.py rename source/pythonpath/barcode/{ => fonts}/DejaVuSansMono.ttf (100%) mode change 100644 => 100755 source/pythonpath/barcode/isxn.py mode change 100644 => 100755 source/pythonpath/barcode/upc.py mode change 100644 => 100755 source/pythonpath/barcode/writer.py diff --git a/CHANGELOG b/CHANGELOG index 0264444..5dd4347 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,8 @@ +v 0.7.0 [-oct-2020] +--------------------- + - Update libraries + + v 0.6.0 [15-nov-2019] --------------------- - Call by code diff --git a/README.md b/README.md index d1e7d64..51892ef 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ Extension for insert barcode in LibreOffice documents, with Python, of course. Barcodes provided +* qrcode * code39 * code128 * ean @@ -19,7 +20,6 @@ Barcodes provided * pzn * upc * upca -* qrcode Requirements: @@ -45,6 +45,10 @@ BCH: `qztd3l00xle5tffdqvh2snvadkuau2ml0uqm4n875d` BTC: `3FhiXcXmAesmQzrNEngjHFnvaJRhU1AGWV` +ETH: `0x61a4f614a30ff686445751ed8328b82b77ecfc69` + +LTC: `MBcgQ3LQJA4W2wsXknTdm2fxRSysLaBJHS` + * [Look the wiki](https://gitlab.com/mauriciobaeza/zaz-barcode/wikis/home) * [Mira la wiki](https://gitlab.com/mauriciobaeza/zaz-barcode/wikis/home_es) diff --git a/VERSION b/VERSION index 009695b..bcaffe1 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1 @@ -0.6.0 - +0.7.0 \ No newline at end of file diff --git a/conf.py b/conf.py index 9a4b900..ff2f0fd 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ import logging TYPE_EXTENSION = 1 # ~ https://semver.org/ -VERSION = '0.6.0' +VERSION = '0.7.0' # ~ Your great extension name, not used spaces NAME = 'ZAZBarCode' @@ -41,8 +41,7 @@ ID = 'net.elmau.zaz.BarCode' USE_LOCALES = True DOMAIN = 'base' PATH_LOCALES = 'locales' -# ~ locate pygettext.py -PATH_PYGETTEXT = '/usr/lib/python3.7/Tools/i18n/pygettext.py' +PATH_PYGETTEXT = '/usr/lib/python3.8/Tools/i18n/pygettext.py' PATH_MSGMERGE = 'msgmerge' @@ -93,17 +92,6 @@ INFO = { } -CONTEXT = { - 'calc': 'com.sun.star.sheet.SpreadsheetDocument', - 'writer': 'com.sun.star.text.TextDocument', - 'impress': 'com.sun.star.presentation.PresentationDocument', - 'draw': 'com.sun.star.drawing.DrawingDocument', - 'base': 'com.sun.star.sdb.OfficeDatabaseDocument', - 'math': 'com.sun.star.formula.FormulaProperties', - 'basic': 'com.sun.star.script.BasicIDE', -} - - # ~ Menus, only for TYPE_EXTENSION = 1 # ~ Parent can be: AddonMenu or OfficeMenuBar # ~ For icons con name: NAME_16.bmp, used only NAME @@ -372,7 +360,7 @@ elif TYPE_EXTENSION == 3: METHODS = _methods() -FILE_PY = f"""import uno +DATA_PY = f"""import uno import unohelper {SRV_IMPORT} @@ -392,177 +380,6 @@ g_ImplementationHelper = unohelper.ImplementationHelper() g_ImplementationHelper.addImplementation({NAME}, ID_EXTENSION, SERVICE) """ - -tmp = ' {}' -node = [tmp.format(k, v['display_name']) for k, v in INFO.items()] -NODE_DISPLAY_NAME = '\n'.join(node) - -tmp = ' ' -node = [tmp.format(k) for k, v in INFO.items()] -NODE_EXTENSION_DESCRIPTION = '\n'.join(node) - -NODE_ICON = '' -if ICON: - NODE_ICON = f' ' - -NODE_PUBLISHER = '' -if PUBLISHER: - tmp = ' {}' - node = [tmp.format(v['link'], k, v['text']) for k, v in PUBLISHER.items()] - NODE_PUBLISHER = '\n'.join(node) - -NODE_DEPENDENCIES_MINIMAL = '' -if DEPENDENCIES_MINIMAL: - NODE_DEPENDENCIES_MINIMAL = f"""\n - - """ - -tmp = ' ' -node = [tmp.format(DIRS['registration'], k) for k in INFO.keys()] -NODE_LICENSE = '\n'.join(node) - -NODE_UPDATE = '' -if URL_XML_UPDATE: - NODE_UPDATE = f""" - - - """ - -FILE_DESCRIPTION = f""" - - - - -{NODE_DISPLAY_NAME} - - -{NODE_EXTENSION_DESCRIPTION} - - -{NODE_ICON} - - -{NODE_PUBLISHER} - - - -{NODE_LICENSE} - - {NODE_DEPENDENCIES_MINIMAL}{NODE_UPDATE} - -""" - -NODE_MENU = """ - -{titles} - - - service:{id}?{argument} - - - _self - - - {context} - - - %origin%/{folder}/{icon} - - """ - -opt = 'fuse' -if PARENT == 'OfficeMenuBar': - opt = 'replace' - - -def _get_context(args): - if not args: - return '' - c = [] - for v in args.split(','): - c.append(CONTEXT[v]) - return ','.join(c) - - -menus = [] -toolbar = [] -tmp = ' {}' -for i, m in enumerate(MENUS): - titles = [tmp.format(k, v) for k, v in m['title'].items()] - values = { - 'id': ID, - 'index': i+101, - 'opt': opt, - 'titles': '\n'.join(titles), - 'argument': m['argument'], - 'context': _get_context(m['context']), - 'folder': DIRS['images'], - 'icon': m['icon'], - } - menus.append(NODE_MENU.format(**values)) - if m['toolbar']: - values['index'] = f't{i+1}' - toolbar.append(NODE_MENU.format(**values)) - -NODE_TOOLBAR = '' -NODE_MENUS = '' -if TYPE_EXTENSION == 1: - if PARENT == 'AddonMenu': - NODE_MENUS = '\n'.join(menus) - elif PARENT == 'OfficeMenuBar': - tmp = ' {}' - titles = '\n'.join([tmp.format(k, v) for k, v in MENU_MAIN.items()]) - SUBMENUS = '\n ' + '\n'.join(menus) + '\n ' - NODE_MENUS = f""" - - {titles} - - - _self - - {SUBMENUS} - """ - - if toolbar: - node_toolbars = '\n'.join(toolbar) - NODE_TOOLBAR = f""" - - {node_toolbars} - - """ - -FILE_ADDONS = f""" - - - -{NODE_MENUS} - -{NODE_TOOLBAR} - - -""" - - -FILE_UPDATE = '' -if URL_XML_UPDATE: - FILE_UPDATE = f""" - - - - - - - - - - - -""" - - def _functions(): a = '[in] any {}' t = ' any {}({});' @@ -679,72 +496,42 @@ FILE_ADDIN = f""" """ -NODE_SHORTCUT = """ {0} - {0} - {0}service:{2}?{3} - {0} - {0} -""" - -NODE_SHORTCUTS = '' -if TYPE_EXTENSION == 1: - node_global = [] - node_module = {} - for m in MENUS: - if not m.get('shortcut', ''): - continue - if m['context']: - for c in m['context'].split(','): - if not c in node_module: - node_module[c] = [] - node = NODE_SHORTCUT.format(' ', m['shortcut'], ID, m['argument']) - node_module[c].append(node) - continue - node = NODE_SHORTCUT.format('', m['shortcut'], ID, m['argument']) - node_global.append(node) - if node_global: - NODE_SHORTCUTS = ' \n' - NODE_SHORTCUTS += '\n'.join(node_global) - NODE_SHORTCUTS += ' ' - if node_module: - NODE_SHORTCUTS += ' \n' - for c, n in node_module.items(): - NODE_SHORTCUTS += ' \n'.format(CONTEXT[c]) - NODE_SHORTCUTS += '\n'.join(n) - NODE_SHORTCUTS += ' \n' - NODE_SHORTCUTS += ' ' - -FILE_SHORTCUTS = f""" - - -{NODE_SHORTCUTS} - - -""" - - DATA_MANIFEST = [FILES['py'], f"Office/{FILES['shortcut']}", 'Addons.xcu'] if TYPE_EXTENSION > 1: DATA_MANIFEST.append(FILES['rdb']) if TYPE_EXTENSION == 3: DATA_MANIFEST.append('CalcAddIn.xcu') +DATA_DESCRIPTION = { + 'identifier': {'value': ID}, + 'version': {'value': VERSION}, + 'display-name': {k: v['display_name'] for k, v in INFO.items()}, + 'icon': ICON_EXT, + 'publisher': PUBLISHER, + 'update': URL_XML_UPDATE, +} + +DATA_ADDONS = { + 'parent': PARENT, + 'images': DIRS['images'], + 'main': MENU_MAIN, + 'menus': MENUS, +} DATA = { - 'py': FILE_PY, + 'py': DATA_PY, 'manifest': DATA_MANIFEST, - 'description': FILE_DESCRIPTION, - 'addons': FILE_ADDONS, - 'update': FILE_UPDATE, + 'description': DATA_DESCRIPTION, + 'addons': DATA_ADDONS, + 'update': URL_OXT, 'idl': FILE_IDL, 'addin': FILE_ADDIN, - 'shortcut': FILE_SHORTCUTS, } +with open('VERSION', 'w') as f: + f.write(VERSION) + + # ~ LICENSE_ACCEPT_BY = 'user' # or admin # ~ LICENSE_SUPPRESS_ON_UPDATE = True diff --git a/easymacro.py b/easymacro.py index 30e717e..5a75695 100644 --- a/easymacro.py +++ b/easymacro.py @@ -499,6 +499,11 @@ def dict_to_property(values, uno_any=False): return ps +def dict_to_named(values): + ps = tuple([NamedValue(n, v) for n, v in values.items()]) + return ps + + def property_to_dict(values): d = {i.Name: i.Value for i in values} return d @@ -1837,6 +1842,33 @@ class LOCellRange(object): self.sheet.obj.copyRange(self.address, source.range_address) return + def transpose(self, formula=False): + data = self.data + if formula: + data = self.formula + data = tuple(zip(*data)) + self.clear(1023) + self[0,0].copy_from(data, formula=formula) + return + + def transpose2(self): + # ~ 'Flags': 'A', + # ~ 'FormulaCommand': 0, + # ~ 'SkipEmptyCells': False, + # ~ 'AsLink': False, + # ~ 'MoveMode': 4, + args = { + 'Transpose': True, + } + args = dict_to_property(args) + self.select() + copy() + self.clear(1023) + self[0,0].select() + call_dispatch('.uno:InsertContents', args) + set_clipboard('') + return + def offset(self, row=1, col=0): ra = self.obj.getRangeAddress() col = ra.EndColumn + col @@ -1939,6 +1971,10 @@ class LOCellRange(object): def auto_format(self, value): self.obj.autoFormat(value) + def auto_width(self): + self.obj.Columns.OptimalWidth = True + return + def insert_image(self, path, **kwargs): s = self.obj.Size w = kwargs.get('width', s.Width) @@ -2060,6 +2096,22 @@ class LOCellRange(object): found = self.obj.replaceAll(descriptor) return found + @property + def validation(self): + return self.obj.Validation + @validation.setter + def validation(self, values): + is_list = False + current = self.validation + for k, v in values.items(): + if k == 'Type' and v == 6: + is_list = True + if k == 'Formula1' and is_list: + if isinstance(v, (tuple, list)): + v = ';'.join(['"{}"'.format(i) for i in v]) + setattr(current, k, v) + self.obj.Validation = current + class EventsListenerBase(unohelper.Base, XEventListener): @@ -2454,23 +2506,39 @@ class UnoBaseObject(object): return self._model.Width @width.setter def width(self, value): - if hasattr(self.model, 'Width'): - self.model.Width = value - elif hasattr(self.obj, 'PosSize'): - self._set_possize('Width', value) + self.model.Width = value + + @property + def ps_width(self): + return self._get_possize('Width') + @ps_width.setter + def ps_width(self, value): + self._set_possize('Width', value) @property def height(self): - if hasattr(self.model, 'Height'): - return self.model.Height - ps = self.obj.getPosSize() - return ps.Height + return self.model.Height @height.setter def height(self, value): - if hasattr(self.model, 'Height'): - self.model.Height = value - elif hasattr(self.obj, 'PosSize'): - self._set_possize('Height', value) + self.model.Height = value + + @property + def ps_height(self): + return self._get_possize('Height') + @ps_height.setter + def ps_height(self, value): + self._set_possize('Height', value) + + @property + def size(self): + ps = self.obj.getPosSize() + return (ps.Width, ps.Height) + @size.setter + def size(self, value): + ps = self.obj.getPosSize() + ps.Width = value[0] + ps.Height = value[1] + self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, SIZE) @property def tag(self): @@ -4493,7 +4561,7 @@ def _zippwd(source, target, pwd): # ~ Export ok -def zip(source, target='', mode='w', pwd=''): +def zip_files(source, target='', mode='w', pwd=''): if pwd: return _zippwd(source, target, pwd) diff --git a/files/ZAZBarCode_v0.6.0.oxt b/files/ZAZBarCode_v0.7.0.oxt similarity index 77% rename from files/ZAZBarCode_v0.6.0.oxt rename to files/ZAZBarCode_v0.7.0.oxt index 3ca74953c21a4648d57bd8a9c4ad5c4a1f43d855..36d10f2b97ccdb4e4cdde2fab2a7dc752e840f5f 100644 GIT binary patch delta 61933 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 n|9)6s5R0RRX#@G)&ZpAroZ)xIC~I3 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

+EXr;cQe2V`*TpzZMyEAE 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%0D(xeET5y{0dt(B? ziZY;JXh1+fP(U`SGD^_jLYtxpKtMbkskc@#?F zciB|6i&5F@50?s>f4v+yn3qCIDY>uv0#O*Mq+=t54R|4XBoxU!+h7#A^c^}Un}bKq zlQMWJ9|EIhN>;)^g96jQViC}4-v;R3>oBF=b*8^zZ`U|J?&e{S9f?n+kLikv!I%1l z)M=tYLINON>I`N47&^HaUSCI8k%4{g5B;VZHZ}oHy}NI0CMM4hPdJ(@HvDP^5Wo2m zov5cY3eqXZY5U^BIZ2iIdbDYxuSH!6rsw6-CU%0u0Of9nfn$Y=B$v*Uq1I`N&V(6X znIlD>nPyhUYzDVnoznadn$uW@W}MkxHaQI=gMdMFTlGmTIMt|VbPrx5k)L=za>1x_ zvYDF!bOx9NvYhXNB1Hl-W{Xj#82NQ?_{_rIN8R}d@qR(fU3FidAdZct=`SJ(b%yON zlKjDJbpK(}9gjr7SSan(WL@gzTF~0JJOxFM%mijE5Eyen1a#J$ORiT-Z_o%=f|(*% zG$776=cLK7s6n9?dKZdL$O2_t6vOEBh*%%&vSHL&5rQlq0`C#3kRf`W7L*lg#d7{1 zh2`nv;&$re;-baDzTYEutcf*NVgSg`)FmNi2G5and@oQ!EW_@Da;`;+ah+*n-k|3d z9?afd@d|yh+V21wuSVmmdG~5+KoqPw3{a)@w2$tZnj&!tDv2@i#$MB!pUupmN$aU! zE2eEeDwNRBloj-rmJEL2lvTZ_QcQF(mf~gX$kXf8JU;J*HFk)xZRo`x1wINQa*^@@ znyIYaS&RzM^kFjfw9N{Dw!|eeUIcLDSw_MM&bls|t8Cl>BV%Bdd+AS0=JA;r17_FF zqV}O$Q~zoWCiH-EsQX)NNcI>-ItDuEV1*3VYN0dxTE@eEwh%b<%HotnlmTy0R@X(% z8g~joRhKkd+3num)_V0|2okNDHR5n4kHG1T^+H!pV}nsZSm7){O-U~rNwFEFt?`h-C5 zjfYseZ5_J|e*|BfqD>a-expx-yd~C~Vf}Ij=SJB|9`lW*ypRgzB_=V#n!i{}p)+Nc zz!QP9f@oMcqDCcb*p*dW&}_G4!?I$HA0lp}yN0*~%~2fZ_rvx33}^Us0l;jRY7@-4 z%zM71|D|t|SG+?wNbj3jY1P_Uq#jzhs^3tmh8r6nU!BZW*CmRkn^=k1i zRaJmcYoG`YVG^tzN-KWK;ndPJ+^=YN3FDMu)aa%HnmD8p0(4xf-vZ6w#D{ zX84`eU}WQoFuS+9FJiJsyW0512cZPd5*BNDeuu2;E4&g(O28>l4N#)r>kRBNSP}z8 z^PzXOjGD&dd#e59 zt%QA}6{n?OF$TSxrd~e6=zWKD#$-Pfrulr?YYOvP>x^FgZwAgo4^*ENC4oayMfhUy z_sE)r_IVDG3=Oyl1_004lm7lL12eKeTm_FFW@y_21?7SQyNz0Ok-QL+_^?j!;aYw` z{54&uJ1r`%iRa1MuvRk=YNz&|2(1rwbg)&ggpAn=dfi)ppMC1OG>o`@FW;Qke}f(e z1kNNVv=W@IT7~}kN2xbwqa8e2*bYo+812I}7-ETt;9Ae6m zq7s$l;?39OnEQcH5FBThb}Ko`Nn|rC_&4f$(p7>Ov0vi4G$#L3D6#g3zT>KgoUxn)XZDiSWxEEmdzcuZCtn@iZ>_57n%fp�L<&8djj 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 M05I+WRR-|?0rvPHr2qf` diff --git a/files/zazbarcode.update.xml b/files/zazbarcode.update.xml index 0893f42..f68a62c 100644 --- a/files/zazbarcode.update.xml +++ b/files/zazbarcode.update.xml @@ -1,16 +1,9 @@ - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + diff --git a/source/Addons.xcu b/source/Addons.xcu index 5d68361..1208786 100644 --- a/source/Addons.xcu +++ b/source/Addons.xcu @@ -1,325 +1,324 @@ - - - + + + - - ZAZ BarCode + + ZAZ BarCode ZAZ BarCode + + + _self + + + + + Insert BarCode + Insertar Código + + + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument,com.sun.star.presentation.PresentationDocument,com.sun.star.drawing.DrawingDocument + + + service:net.elmau.zaz.BarCode?ask _self - - - - Insert BarCode - Insertar Código - - - service:net.elmau.zaz.BarCode?ask - - - _self - - - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument,com.sun.star.presentation.PresentationDocument,com.sun.star.drawing.DrawingDocument - - %origin%/images/barcode + %origin%/images/barcode - + - Insert CODE39 - Insertar CODE39 - - - service:net.elmau.zaz.BarCode?code39 - - - _self + Insert CODE39 + Insertar CODE39 - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?code39 + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert CODE128 - Insertar CODE128 - - - service:net.elmau.zaz.BarCode?code128 - - - _self + Insert CODE128 + Insertar CODE128 - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?code128 + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert EAN - Insertar EAN - - - service:net.elmau.zaz.BarCode?ean - - - _self + Insert EAN + Insertar EAN - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?ean + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert EAN8 - Insertar EAN8 - - - service:net.elmau.zaz.BarCode?ean8 - - - _self + Insert EAN8 + Insertar EAN8 - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?ean8 + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert EAN13 - Insertar EAN13 - - - service:net.elmau.zaz.BarCode?ean13 - - - _self + Insert EAN13 + Insertar EAN13 - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?ean13 + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert GS1 - Insertar GS1 - - - service:net.elmau.zaz.BarCode?gs1 - - - _self + Insert GS1 + Insertar GS1 - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?gs1 + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert GTIN - Insertar GTIN - - - service:net.elmau.zaz.BarCode?gtin - - - _self + Insert GTIN + Insertar GTIN - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?gtin + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert ISBN - Insertar ISBN - - - service:net.elmau.zaz.BarCode?isbn - - - _self + Insert ISBN + Insertar ISBN - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?isbn + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert ISBN10 - Insertar ISBN10 - - - service:net.elmau.zaz.BarCode?isbn10 - - - _self + Insert ISBN10 + Insertar ISBN10 - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?isbn10 + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert ISBN13 - Insertar ISBN13 - - - service:net.elmau.zaz.BarCode?isbn13 - - - _self + Insert ISBN13 + Insertar ISBN13 - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?isbn13 + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert ISSN - Insertar ISSN - - - service:net.elmau.zaz.BarCode?issn - - - _self + Insert ISSN + Insertar ISSN - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?issn + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert JAN - Insertar JAN - - - service:net.elmau.zaz.BarCode?jan - - - _self + Insert JAN + Insertar JAN - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?jan + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert PZN - Insertar PZN - - - service:net.elmau.zaz.BarCode?pzn - - - _self + Insert PZN + Insertar PZN - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?pzn + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert UPC - Insertar UPC - - - service:net.elmau.zaz.BarCode?upc - - - _self + Insert UPC + Insertar UPC - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?upc + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert UPCA - Insertar UPCA - - - service:net.elmau.zaz.BarCode?upca - - - _self + Insert UPCA + Insertar UPCA - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?upca + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - Insert QRCODE - Insertar QRCODE - - - service:net.elmau.zaz.BarCode?qrcode - - - _self + Insert QRCODE + Insertar QRCODE - com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument + + + service:net.elmau.zaz.BarCode?qrcode + + + _self - %origin%/images/barcode + %origin%/images/barcode - + - - + diff --git a/source/Office/Accelerators.xcu b/source/Office/Accelerators.xcu index d290b14..3db9b03 100644 --- a/source/Office/Accelerators.xcu +++ b/source/Office/Accelerators.xcu @@ -1,9 +1,5 @@ - - + + diff --git a/source/description.xml b/source/description.xml index 6d95b82..0195747 100644 --- a/source/description.xml +++ b/source/description.xml @@ -1,29 +1,29 @@ - + - - + + ZAZ Bar Code ZAZ Códigos de Barras - - + + - + El Mau El Mau - - - + + + - - - + + + diff --git a/source/pythonpath/barcode/__init__.py b/source/pythonpath/barcode/__init__.py old mode 100644 new mode 100755 index 427d094..571fdea --- a/source/pythonpath/barcode/__init__.py +++ b/source/pythonpath/barcode/__init__.py @@ -1,57 +1,73 @@ -# -*- coding: utf-8 -*- - -""" - -pyBarcode -========= - -This package provides a simple way to create standard barcodes. +"""This package provides a simple way to create standard barcodes. It needs no external packages to be installed, the barcodes are created as SVG objects. If Pillow is installed, the barcodes can also be rendered as images (all formats supported by Pillow). """ +import os +from typing import BinaryIO +from typing import Dict +from typing import Union +from barcode.codex import Code128 +from barcode.codex import Code39 +from barcode.codex import Gs1_128 +from barcode.codex import PZN +from barcode.ean import EAN13 +from barcode.ean import EAN14 +from barcode.ean import EAN8 +from barcode.ean import JAN from barcode.errors import BarcodeNotFoundError -from barcode.codex import Code39, PZN, Code128, Gs1_128 -from barcode.ean import EAN8, EAN13, EAN14, JAN -from barcode.isxn import ISBN10, ISBN13, ISSN -from barcode.upc import UPCA +from barcode.isxn import ISBN10 +from barcode.isxn import ISBN13 +from barcode.isxn import ISSN from barcode.itf import ITF +from barcode.upc import UPCA from barcode.version import version # noqa: F401 - -__BARCODE_MAP = dict( - ean8=EAN8, - ean13=EAN13, - ean=EAN13, - gtin=EAN14, - ean14=EAN14, - jan=JAN, - upc=UPCA, - upca=UPCA, - isbn=ISBN13, - isbn13=ISBN13, - gs1=ISBN13, - isbn10=ISBN10, - issn=ISSN, - code39=Code39, - pzn=PZN, - code128=Code128, - itf=ITF, - gs1_128=Gs1_128, -) +__BARCODE_MAP = { + "ean8": EAN8, + "ean13": EAN13, + "ean": EAN13, + "gtin": EAN14, + "ean14": EAN14, + "jan": JAN, + "upc": UPCA, + "upca": UPCA, + "isbn": ISBN13, + "isbn13": ISBN13, + "gs1": ISBN13, + "isbn10": ISBN10, + "issn": ISSN, + "code39": Code39, + "pzn": PZN, + "code128": Code128, + "itf": ITF, + "gs1_128": Gs1_128, +} PROVIDED_BARCODES = list(__BARCODE_MAP) PROVIDED_BARCODES.sort() def get(name, code=None, writer=None, options=None): + """Helper method for getting a generator or even a generated code. + + :param str name: The name of the type of barcode desired. + :param str code: The actual information to encode. If this parameter is + provided, a generated barcode is returned. Otherwise, the barcode class + is returned. + :param Writer writer: An alternative writer to use when generating the + barcode. + :param dict options: Additional options to be passed on to the barcode when + generating. + """ options = options or {} try: barcode = __BARCODE_MAP[name.lower()] except KeyError: - raise BarcodeNotFoundError('The barcode {0!r} you requested is not ' - 'known.'.format(name)) + raise BarcodeNotFoundError( + "The barcode {!r} you requested is not known.".format(name) + ) if code is not None: return barcode(code, writer, **options) else: @@ -62,17 +78,38 @@ def get_class(name): return get_barcode(name) -def generate(name, code, writer=None, output=None, writer_options=None, - text=None, pil=False): - options = writer_options or {} - barcode = get(name, code, writer, options) - if pil: - return barcode.render(writer_options, text) +def generate( + name: str, + code: str, + writer=None, + output: Union[str, os.PathLike, BinaryIO] = None, + writer_options: Dict = None, + text: str = None, +): + """Shortcut to generate a barcode in one line. + + :param name: Name of the type of barcode to use. + :param code: Data to encode into the barcode. + :param writer: A writer to use (e.g.: ImageWriter or SVGWriter). + :param output: Destination file-like or path-like where to save the generated + barcode. + :param writer_options: Options to pass on to the writer instance. + :param text: Text to render under the barcode. + """ + from barcode.base import Barcode + + writer = writer or Barcode.default_writer() + writer.set_options(writer_options or {}) + + barcode = get(name, code, writer) + if isinstance(output, str): - fullname = barcode.save(output, options, text) + fullname = barcode.save(output, writer_options, text) return fullname + elif output: + barcode.write(output, writer_options, text) else: - barcode.write(output, options, text) + raise TypeError("'output' cannot be None") get_barcode = get diff --git a/source/pythonpath/barcode/base.py b/source/pythonpath/barcode/base.py old mode 100644 new mode 100755 index 6a42bf5..7b7b0fe --- a/source/pythonpath/barcode/base.py +++ b/source/pythonpath/barcode/base.py @@ -1,43 +1,37 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - """barcode.base """ - from barcode.writer import SVGWriter -class Barcode(object): +class Barcode: - name = '' + name = "" digits = 0 default_writer = SVGWriter default_writer_options = { - 'module_width': 0.2, - 'module_height': 15.0, - 'quiet_zone': 6.5, - 'font_size': 10, - 'text_distance': 5.0, - 'background': 'white', - 'foreground': 'black', - 'write_text': True, - 'text': '', + "module_width": 0.2, + "module_height": 15.0, + "quiet_zone": 6.5, + "font_size": 10, + "text_distance": 5.0, + "background": "white", + "foreground": "black", + "write_text": True, + "text": "", } def to_ascii(self): code = self.build() for i, line in enumerate(code): - code[i] = line.replace('1', 'X').replace('0', ' ') - return '\n'.join(code) + code[i] = line.replace("1", "X").replace("0", " ") + return "\n".join(code) def __repr__(self): - return '<{0}({1!r})>'.format(self.__class__.__name__, - self.get_fullcode()) + return "<{}({!r})>".format(self.__class__.__name__, self.get_fullcode()) def build(self): raise NotImplementedError @@ -59,7 +53,7 @@ class Barcode(object): extension). options : Dict The same as in `self.render`. - text : str (unicode on Python 2) + text : str Text to render under the barcode. :returns: The full filename with extension. @@ -82,14 +76,11 @@ class Barcode(object): Object to write the raw data in. options : Dict The same as in `self.render`. - text : str (unicode on Python 2) + text : str Text to render under the barcode. """ output = self.render(options, text) - if hasattr(output, 'tostring'): - output.save(fp, format=self.writer.format) - else: - fp.write(output) + self.writer.write(output, fp) def render(self, writer_options=None, text=None): """Renders the barcode using `self.writer`. @@ -97,18 +88,18 @@ class Barcode(object): :parameters: writer_options : Dict Options for `self.writer`, see writer docs for details. - text : str (unicode on Python 2) + text : str Text to render under the barcode. :returns: Output of the writers render method. """ options = Barcode.default_writer_options.copy() options.update(writer_options or {}) - if options['write_text'] or text is not None: + if options["write_text"] or text is not None: if text is not None: - options['text'] = text + options["text"] = text else: - options['text'] = self.get_fullcode() + options["text"] = self.get_fullcode() self.writer.set_options(options) code = self.build() raw = self.writer.render(code) diff --git a/source/pythonpath/barcode/charsets/code128.py b/source/pythonpath/barcode/charsets/code128.py index 5132e29..4941aa2 100644 --- a/source/pythonpath/barcode/charsets/code128.py +++ b/source/pythonpath/barcode/charsets/code128.py @@ -1,64 +1,223 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - import string # Charsets for code 128 _common = ( - ' ', '!', '"', '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', - '-', '.', '/', -) + tuple(string.digits) + ( - ':', ';', '<', '=', '>', '?', '@', -) + tuple(string.ascii_uppercase) + ( - '[', '\\', ']', '^', '_', + ( + " ", + "!", + '"', + "#", + "$", + "%", + "&", + "'", + "(", + ")", + "*", + "+", + ",", + "-", + ".", + "/", + ) + + tuple(string.digits) + + ( + ":", + ";", + "<", + "=", + ">", + "?", + "@", + ) + + tuple(string.ascii_uppercase) + + ( + "[", + "\\", + "]", + "^", + "_", + ) ) _charset_a = _common + ( - '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', '\x08', - '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', '\x10', '\x11', - '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', - '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', '\xf3', '\xf2', 'SHIFT', 'TO_C', - 'TO_B', '\xf4', '\xf1', + "\x00", + "\x01", + "\x02", + "\x03", + "\x04", + "\x05", + "\x06", + "\x07", + "\x08", + "\x09", + "\x0a", + "\x0b", + "\x0c", + "\x0d", + "\x0e", + "\x0f", + "\x10", + "\x11", + "\x12", + "\x13", + "\x14", + "\x15", + "\x16", + "\x17", + "\x18", + "\x19", + "\x1a", + "\x1b", + "\x1c", + "\x1d", + "\x1e", + "\x1f", + "\xf3", + "\xf2", + "SHIFT", + "TO_C", + "TO_B", + "\xf4", + "\xf1", ) -_charset_b = _common + ('`',) + tuple(string.ascii_lowercase) + ( - '{', '|', '}', '~', '\x7f', '\xf3', '\xf2', 'SHIFT', 'TO_C', '\xf4', - 'TO_A', '\xf1', +_charset_b = ( + _common + + ("`",) + + tuple(string.ascii_lowercase) + + ( + "{", + "|", + "}", + "~", + "\x7f", + "\xf3", + "\xf2", + "SHIFT", + "TO_C", + "\xf4", + "TO_A", + "\xf1", + ) ) ALL = set(_common + _charset_a + _charset_b) -A = dict(((c, i) for i, c in enumerate(_charset_a))) -B = dict(((c, i) for i, c in enumerate(_charset_b))) -C = {'TO_B': 100, 'TO_A': 101, '\xf1': 102} +A = {c: i for i, c in enumerate(_charset_a)} +B = {c: i for i, c in enumerate(_charset_b)} +C = {"TO_B": 100, "TO_A": 101, "\xf1": 102} CODES = ( - '11011001100', '11001101100', '11001100110', '10010011000', '10010001100', - '10001001100', '10011001000', '10011000100', '10001100100', '11001001000', - '11001000100', '11000100100', '10110011100', '10011011100', '10011001110', - '10111001100', '10011101100', '10011100110', '11001110010', '11001011100', - '11001001110', '11011100100', '11001110100', '11101101110', '11101001100', - '11100101100', '11100100110', '11101100100', '11100110100', '11100110010', - '11011011000', '11011000110', '11000110110', '10100011000', '10001011000', - '10001000110', '10110001000', '10001101000', '10001100010', '11010001000', - '11000101000', '11000100010', '10110111000', '10110001110', '10001101110', - '10111011000', '10111000110', '10001110110', '11101110110', '11010001110', - '11000101110', '11011101000', '11011100010', '11011101110', '11101011000', - '11101000110', '11100010110', '11101101000', '11101100010', '11100011010', - '11101111010', '11001000010', '11110001010', '10100110000', '10100001100', - '10010110000', '10010000110', '10000101100', '10000100110', '10110010000', - '10110000100', '10011010000', '10011000010', '10000110100', '10000110010', - '11000010010', '11001010000', '11110111010', '11000010100', '10001111010', - '10100111100', '10010111100', '10010011110', '10111100100', '10011110100', - '10011110010', '11110100100', '11110010100', '11110010010', '11011011110', - '11011110110', '11110110110', '10101111000', '10100011110', '10001011110', - '10111101000', '10111100010', '11110101000', '11110100010', '10111011110', - '10111101110', '11101011110', '11110101110', '11010000100', '11010010000', - '11010011100', + "11011001100", + "11001101100", + "11001100110", + "10010011000", + "10010001100", + "10001001100", + "10011001000", + "10011000100", + "10001100100", + "11001001000", + "11001000100", + "11000100100", + "10110011100", + "10011011100", + "10011001110", + "10111001100", + "10011101100", + "10011100110", + "11001110010", + "11001011100", + "11001001110", + "11011100100", + "11001110100", + "11101101110", + "11101001100", + "11100101100", + "11100100110", + "11101100100", + "11100110100", + "11100110010", + "11011011000", + "11011000110", + "11000110110", + "10100011000", + "10001011000", + "10001000110", + "10110001000", + "10001101000", + "10001100010", + "11010001000", + "11000101000", + "11000100010", + "10110111000", + "10110001110", + "10001101110", + "10111011000", + "10111000110", + "10001110110", + "11101110110", + "11010001110", + "11000101110", + "11011101000", + "11011100010", + "11011101110", + "11101011000", + "11101000110", + "11100010110", + "11101101000", + "11101100010", + "11100011010", + "11101111010", + "11001000010", + "11110001010", + "10100110000", + "10100001100", + "10010110000", + "10010000110", + "10000101100", + "10000100110", + "10110010000", + "10110000100", + "10011010000", + "10011000010", + "10000110100", + "10000110010", + "11000010010", + "11001010000", + "11110111010", + "11000010100", + "10001111010", + "10100111100", + "10010111100", + "10010011110", + "10111100100", + "10011110100", + "10011110010", + "11110100100", + "11110010100", + "11110010010", + "11011011110", + "11011110110", + "11110110110", + "10101111000", + "10100011110", + "10001011110", + "10111101000", + "10111100010", + "11110101000", + "11110100010", + "10111011110", + "10111101110", + "11101011110", + "11110101110", + "11010000100", + "11010010000", + "11010011100", ) -STOP = '11000111010' +STOP = "11000111010" -START_CODES = {'A': 103, 'B': 104, 'C': 105} -TO = {101: START_CODES['A'], 100: START_CODES['B'], 99: START_CODES['C']} +START_CODES = {"A": 103, "B": 104, "C": 105} +TO = {101: START_CODES["A"], 100: START_CODES["B"], 99: START_CODES["C"]} diff --git a/source/pythonpath/barcode/charsets/code39.py b/source/pythonpath/barcode/charsets/code39.py index 4031f65..d9f679d 100644 --- a/source/pythonpath/barcode/charsets/code39.py +++ b/source/pythonpath/barcode/charsets/code39.py @@ -1,34 +1,61 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - import string # Charsets for code 39 -REF = (tuple(string.digits) + tuple(string.ascii_uppercase) + - ('-', '.', ' ', '$', '/', '+', '%')) -B = '1' -E = '0' +REF = ( + tuple(string.digits) + + tuple(string.ascii_uppercase) + + ("-", ".", " ", "$", "/", "+", "%") +) +B = "1" +E = "0" CODES = ( - '101000111011101', '111010001010111', '101110001010111', - '111011100010101', '101000111010111', '111010001110101', - '101110001110101', '101000101110111', '111010001011101', - '101110001011101', '111010100010111', '101110100010111', - '111011101000101', '101011100010111', '111010111000101', - '101110111000101', '101010001110111', '111010100011101', - '101110100011101', '101011100011101', '111010101000111', - '101110101000111', '111011101010001', '101011101000111', - '111010111010001', '101110111010001', '101010111000111', - '111010101110001', '101110101110001', '101011101110001', - '111000101010111', '100011101010111', '111000111010101', - '100010111010111', '111000101110101', '100011101110101', - '100010101110111', '111000101011101', '100011101011101', - '100010001000101', '100010001010001', '100010100010001', - '101000100010001', + "101000111011101", + "111010001010111", + "101110001010111", + "111011100010101", + "101000111010111", + "111010001110101", + "101110001110101", + "101000101110111", + "111010001011101", + "101110001011101", + "111010100010111", + "101110100010111", + "111011101000101", + "101011100010111", + "111010111000101", + "101110111000101", + "101010001110111", + "111010100011101", + "101110100011101", + "101011100011101", + "111010101000111", + "101110101000111", + "111011101010001", + "101011101000111", + "111010111010001", + "101110111010001", + "101010111000111", + "111010101110001", + "101110101110001", + "101011101110001", + "111000101010111", + "100011101010111", + "111000111010101", + "100010111010111", + "111000101110101", + "100011101110101", + "100010101110111", + "111000101011101", + "100011101011101", + "100010001000101", + "100010001010001", + "100010100010001", + "101000100010001", ) -EDGE = '100010111011101' -MIDDLE = '0' +EDGE = "100010111011101" +MIDDLE = "0" # MAP for assigning every symbol (REF) to (reference number, barcode) MAP = dict(zip(REF, enumerate(CODES))) diff --git a/source/pythonpath/barcode/charsets/ean.py b/source/pythonpath/barcode/charsets/ean.py index 951028a..199142d 100644 --- a/source/pythonpath/barcode/charsets/ean.py +++ b/source/pythonpath/barcode/charsets/ean.py @@ -1,17 +1,52 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - - -EDGE = '101' -MIDDLE = '01010' +EDGE = "101" +MIDDLE = "01010" CODES = { - 'A': ('0001101', '0011001', '0010011', '0111101', '0100011', - '0110001', '0101111', '0111011', '0110111', '0001011'), - 'B': ('0100111', '0110011', '0011011', '0100001', '0011101', - '0111001', '0000101', '0010001', '0001001', '0010111'), - 'C': ('1110010', '1100110', '1101100', '1000010', '1011100', - '1001110', '1010000', '1000100', '1001000', '1110100'), + "A": ( + "0001101", + "0011001", + "0010011", + "0111101", + "0100011", + "0110001", + "0101111", + "0111011", + "0110111", + "0001011", + ), + "B": ( + "0100111", + "0110011", + "0011011", + "0100001", + "0011101", + "0111001", + "0000101", + "0010001", + "0001001", + "0010111", + ), + "C": ( + "1110010", + "1100110", + "1101100", + "1000010", + "1011100", + "1001110", + "1010000", + "1000100", + "1001000", + "1110100", + ), } -LEFT_PATTERN = ('AAAAAA', 'AABABB', 'AABBAB', 'AABBBA', 'ABAABB', - 'ABBAAB', 'ABBBAA', 'ABABAB', 'ABABBA', 'ABBABA') +LEFT_PATTERN = ( + "AAAAAA", + "AABABB", + "AABBAB", + "AABBBA", + "ABAABB", + "ABBAAB", + "ABBBAA", + "ABABAB", + "ABABBA", + "ABBABA", +) diff --git a/source/pythonpath/barcode/charsets/itf.py b/source/pythonpath/barcode/charsets/itf.py index 988db00..24eb02f 100644 --- a/source/pythonpath/barcode/charsets/itf.py +++ b/source/pythonpath/barcode/charsets/itf.py @@ -1,12 +1,19 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - # W = Wide bar # w = wide space # N = Narrow bar # n = narrow space -START = 'NnNn' -STOP = 'WnN' -CODES = ('NNWWN', 'WNNNW', 'NWNNW', 'WWNNN', 'NNWNW', 'WNWNN', 'NWWNN', 'NNNWW', 'WNNWN', 'NWNWN') +START = "NnNn" +STOP = "WnN" +CODES = ( + "NNWWN", + "WNNNW", + "NWNNW", + "WWNNN", + "NNWNW", + "WNWNN", + "NWWNN", + "NNNWW", + "WNNWN", + "NWNWN", +) diff --git a/source/pythonpath/barcode/charsets/upc.py b/source/pythonpath/barcode/charsets/upc.py index 9b625c7..df90deb 100644 --- a/source/pythonpath/barcode/charsets/upc.py +++ b/source/pythonpath/barcode/charsets/upc.py @@ -1,13 +1,28 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - - -EDGE = '101' -MIDDLE = '01010' +EDGE = "101" +MIDDLE = "01010" CODES = { - 'L': ('0001101', '0011001', '0010011', '0111101', '0100011', - '0110001', '0101111', '0111011', '0110111', '0001011'), - 'R': ('1110010', '1100110', '1101100', '1000010', '1011100', - '1001110', '1010000', '1000100', '1001000', '1110100') + "L": ( + "0001101", + "0011001", + "0010011", + "0111101", + "0100011", + "0110001", + "0101111", + "0111011", + "0110111", + "0001011", + ), + "R": ( + "1110010", + "1100110", + "1101100", + "1000010", + "1011100", + "1001110", + "1010000", + "1000100", + "1001000", + "1110100", + ), } diff --git a/source/pythonpath/barcode/codex.py b/source/pythonpath/barcode/codex.py old mode 100644 new mode 100755 index c747175..870c8c2 --- a/source/pythonpath/barcode/codex.py +++ b/source/pythonpath/barcode/codex.py @@ -1,17 +1,15 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - -from barcode.base import Barcode -from barcode.charsets import code128, code39 -from barcode.errors import * - """Module: barcode.codex :Provided barcodes: Code 39, Code 128, PZN """ -__docformat__ = 'restructuredtext en' +from barcode.base import Barcode +from barcode.charsets import code128 +from barcode.charsets import code39 +from barcode.errors import BarcodeError +from barcode.errors import IllegalCharacterError +from barcode.errors import NumberOfDigitsError +__docformat__ = "restructuredtext en" # Sizes MIN_SIZE = 0.2 @@ -25,43 +23,40 @@ def check_code(code, name, allowed): wrong.append(char) if wrong: raise IllegalCharacterError( - 'The following characters are not valid for ' - '{name}: {wrong}'.format(name=name, wrong=', '.join(wrong)) + "The following characters are not valid for {name}: {wrong}".format( + name=name, wrong=", ".join(wrong) + ) ) class Code39(Barcode): - """Initializes a new Code39 instance. + """A Code39 barcode implementation""" - :parameters: - code : String - Code 39 string without \* and checksum (added automatically if - `add_checksum` is True). - writer : barcode.writer Instance - The writer to render the barcode (default: SVGWriter). - add_checksum : Boolean - Add the checksum to code or not (default: True). - """ + name = "Code 39" - name = 'Code 39' + def __init__(self, code: str, writer=None, add_checksum: bool = True): + r""" + :param code: Code 39 string without \* and without checksum. + :param writer: A ``barcode.writer`` instance used to render the barcode + (default: SVGWriter). + :param add_checksum: Add the checksum to code or not + """ - def __init__(self, code, writer=None, add_checksum=True): self.code = code.upper() if add_checksum: self.code += self.calculate_checksum() self.writer = writer or Barcode.default_writer() check_code(self.code, self.name, code39.REF) - def __unicode__(self): + def __str__(self): return self.code - __str__ = __unicode__ - - def get_fullcode(self): + def get_fullcode(self) -> str: + """:returns: The full code as it will be encoded.""" return self.code def calculate_checksum(self): - check = sum([code39.MAP[x][0] for x in self.code]) % 43 + check = sum(code39.MAP[x][0] for x in self.code) % 43 for k, v in code39.MAP.items(): if check == v[0]: return k @@ -74,7 +69,7 @@ class Code39(Barcode): return [code39.MIDDLE.join(chars)] def render(self, writer_options=None, text=None): - options = dict(module_width=MIN_SIZE, quiet_zone=MIN_QUIET_ZONE) + options = {"module_width": MIN_SIZE, "quiet_zone": MIN_QUIET_ZONE} options.update(writer_options or {}) return Barcode.render(self, options, text) @@ -89,30 +84,30 @@ class PZN7(Code39): The writer to render the barcode (default: SVGWriter). """ - name = 'Pharmazentralnummer' + name = "Pharmazentralnummer" digits = 6 def __init__(self, pzn, writer=None): - pzn = pzn[:self.digits] + pzn = pzn[: self.digits] if not pzn.isdigit(): - raise IllegalCharacterError('PZN can only contain numbers.') + raise IllegalCharacterError("PZN can only contain numbers.") if len(pzn) != self.digits: - raise NumberOfDigitsError('PZN must have {0} digits, not ' - '{1}.'.format(self.digits, len(pzn))) + raise NumberOfDigitsError( + "PZN must have {} digits, not {}.".format(self.digits, len(pzn)) + ) self.pzn = pzn - self.pzn = '{0}{1}'.format(pzn, self.calculate_checksum()) - Code39.__init__(self, 'PZN-{0}'.format(self.pzn), writer, - add_checksum=False) + self.pzn = "{}{}".format(pzn, self.calculate_checksum()) + Code39.__init__(self, "PZN-{}".format(self.pzn), writer, add_checksum=False) def get_fullcode(self): - return 'PZN-{0}'.format(self.pzn) + return "PZN-{}".format(self.pzn) def calculate_checksum(self): - sum_ = sum([int(x) * int(y) for x, y in enumerate(self.pzn, start=2)]) + sum_ = sum(int(x) * int(y) for x, y in enumerate(self.pzn, start=2)) checksum = sum_ % 11 if checksum == 10: - raise BarcodeError('Checksum can not be 10 for PZN.') + raise BarcodeError("Checksum can not be 10 for PZN.") else: return checksum @@ -134,20 +129,18 @@ class Code128(Barcode): The writer to render the barcode (default: SVGWriter). """ - name = 'Code 128' + name = "Code 128" def __init__(self, code, writer=None): self.code = code self.writer = writer or Barcode.default_writer() - self._charset = 'B' - self._buffer = '' + self._charset = "B" + self._buffer = "" check_code(self.code, self.name, code128.ALL) - def __unicode__(self): + def __str__(self): return self.code - __str__ = __unicode__ - @property def encoded(self): return self._build() @@ -156,18 +149,18 @@ class Code128(Barcode): return self.code def _new_charset(self, which): - if which == 'A': - code = self._convert('TO_A') - elif which == 'B': - code = self._convert('TO_B') - elif which == 'C': - code = self._convert('TO_C') + if which == "A": + code = self._convert("TO_A") + elif which == "B": + code = self._convert("TO_B") + elif which == "C": + code = self._convert("TO_C") self._charset = which return [code] def _maybe_switch_charset(self, pos): char = self.code[pos] - next_ = self.code[pos:pos + 10] + next_ = self.code[pos : pos + 10] def look_next(): digits = 0 @@ -176,44 +169,44 @@ class Code128(Barcode): digits += 1 else: break - return digits > 3 + return digits > 3 and (digits % 2) == 0 codes = [] - if self._charset == 'C' and not char.isdigit(): + if self._charset == "C" and not char.isdigit(): if char in code128.B: - codes = self._new_charset('B') + codes = self._new_charset("B") elif char in code128.A: - codes = self._new_charset('A') + codes = self._new_charset("A") if len(self._buffer) == 1: codes.append(self._convert(self._buffer[0])) - self._buffer = '' - elif self._charset == 'B': + self._buffer = "" + elif self._charset == "B": if look_next(): - codes = self._new_charset('C') + codes = self._new_charset("C") elif char not in code128.B: if char in code128.A: - codes = self._new_charset('A') - elif self._charset == 'A': + codes = self._new_charset("A") + elif self._charset == "A": if look_next(): - codes = self._new_charset('C') + codes = self._new_charset("C") elif char not in code128.A: if char in code128.B: - codes = self._new_charset('B') + codes = self._new_charset("B") return codes def _convert(self, char): - if self._charset == 'A': + if self._charset == "A": return code128.A[char] - elif self._charset == 'B': + elif self._charset == "B": return code128.B[char] - elif self._charset == 'C': + elif self._charset == "C": if char in code128.C: return code128.C[char] elif char.isdigit(): self._buffer += char if len(self._buffer) == 2: value = int(self._buffer) - self._buffer = '' + self._buffer = "" return value def _try_to_optimize(self, encoded): @@ -236,24 +229,24 @@ class Code128(Barcode): encoded.append(code_num) # Finally look in the buffer if len(self._buffer) == 1: - encoded.extend(self._new_charset('B')) + encoded.extend(self._new_charset("B")) encoded.append(self._convert(self._buffer[0])) - self._buffer = '' + self._buffer = "" encoded = self._try_to_optimize(encoded) return encoded def build(self): encoded = self._build() encoded.append(self._calculate_checksum(encoded)) - code = '' + code = "" for code_num in encoded: code += code128.CODES[code_num] code += code128.STOP - code += '11' + code += "11" return [code] def render(self, writer_options=None, text=None): - options = dict(module_width=MIN_SIZE, quiet_zone=MIN_QUIET_ZONE) + options = {"module_width": MIN_SIZE, "quiet_zone": MIN_QUIET_ZONE} options.update(writer_options or {}) return Barcode.render(self, options, text) @@ -266,16 +259,16 @@ class Gs1_128(Code128): https://www.gs1-128.info/ """ - name = 'GS1-128' + name = "GS1-128" - FNC1_CHAR = '\xf1' + FNC1_CHAR = "\xf1" def __init__(self, code, writer=None): code = self.FNC1_CHAR + code - super(Gs1_128, self).__init__(code, writer) + super().__init__(code, writer) def get_fullcode(self): - return super(Gs1_128, self).get_fullcode()[1:] + return super().get_fullcode()[1:] # For pre 0.8 compatibility diff --git a/source/pythonpath/barcode/ean.py b/source/pythonpath/barcode/ean.py old mode 100644 new mode 100755 index f3a447c..0b4ab5b --- a/source/pythonpath/barcode/ean.py +++ b/source/pythonpath/barcode/ean.py @@ -1,27 +1,32 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - -from barcode.base import Barcode -from barcode.charsets import ean as _ean -from barcode.errors import * - """Module: barcode.ean :Provided barcodes: EAN-14, EAN-13, EAN-8, JAN """ -__docformat__ = 'restructuredtext en' +__docformat__ = "restructuredtext en" -# Python 3 -try: - reduce -except NameError: - from functools import reduce +from functools import reduce +from barcode.base import Barcode +from barcode.charsets import ean as _ean +from barcode.errors import ( + IllegalCharacterError, + NumberOfDigitsError, + WrongCountryCodeError, +) # EAN13 Specs (all sizes in mm) -SIZES = dict(SC0=0.27, SC1=0.297, SC2=0.33, SC3=0.363, SC4=0.396, SC5=0.445, - SC6=0.495, SC7=0.544, SC8=0.61, SC9=0.66) +SIZES = { + "SC0": 0.27, + "SC1": 0.297, + "SC2": 0.33, + "SC3": 0.363, + "SC4": 0.396, + "SC5": 0.445, + "SC6": 0.495, + "SC7": 0.544, + "SC8": 0.61, + "SC9": 0.66, +} class EuropeanArticleNumber13(Barcode): @@ -34,37 +39,36 @@ class EuropeanArticleNumber13(Barcode): The writer to render the barcode (default: SVGWriter). """ - name = 'EAN-13' + name = "EAN-13" digits = 12 - def __init__(self, ean, writer=None, **kwargs): - no_checksum = False - if "no_checksum" in kwargs.keys(): - no_checksum = kwargs["no_checksum"] - ean = ean[:self.digits] + def __init__(self, ean, writer=None, no_checksum=False): + ean = ean[: self.digits] if not ean.isdigit(): - raise IllegalCharacterError('EAN code can only contain numbers.') + raise IllegalCharacterError("EAN code can only contain numbers.") if len(ean) != self.digits: - raise NumberOfDigitsError('EAN must have {0} digits, not ' - '{1}.'.format(self.digits, len(ean))) + raise NumberOfDigitsError( + "EAN must have {} digits, not {}.".format( + self.digits, + len(ean), + ) + ) self.ean = ean # If no checksum if no_checksum: # Add a thirteen char if given in parameter, # otherwise pad with zero - self.ean = '{0}{1}'.format( + self.ean = "{}{}".format( ean, ean[self.digits] if len(ean) > self.digits else 0 ) else: - self.ean = '{0}{1}'.format(ean, self.calculate_checksum()) + self.ean = "{}{}".format(ean, self.calculate_checksum()) self.writer = writer or Barcode.default_writer() - def __unicode__(self): + def __str__(self): return self.ean - __str__ = __unicode__ - def get_fullcode(self): return self.ean @@ -74,7 +78,10 @@ class EuropeanArticleNumber13(Barcode): :returns: The checksum for `self.ean`. :rtype: Integer """ - def sum_(x, y): return int(x) + int(y) + + def sum_(x, y): + return int(x) + int(y) + evensum = reduce(sum_, self.ean[-2::-2]) oddsum = reduce(sum_, self.ean[-1::-2]) return (10 - ((evensum + oddsum * 3) % 10)) % 10 @@ -91,7 +98,7 @@ class EuropeanArticleNumber13(Barcode): code += _ean.CODES[pattern[i]][int(number)] code += _ean.MIDDLE for number in self.ean[7:]: - code += _ean.CODES['C'][int(number)] + code += _ean.CODES["C"][int(number)] code += _ean.EDGE return [code] @@ -102,11 +109,11 @@ class EuropeanArticleNumber13(Barcode): """ code = self.build() for i, line in enumerate(code): - code[i] = line.replace('1', '|').replace('0', ' ') - return '\n'.join(code) + code[i] = line.replace("1", "|").replace("0", " ") + return "\n".join(code) def render(self, writer_options=None, text=None): - options = dict(module_width=SIZES['SC2']) + options = {"module_width": SIZES["SC2"]} options.update(writer_options or {}) return Barcode.render(self, options, text) @@ -121,14 +128,15 @@ class JapanArticleNumber(EuropeanArticleNumber13): The writer to render the barcode (default: SVGWriter). """ - name = 'JAN' + name = "JAN" valid_country_codes = list(range(450, 460)) + list(range(490, 500)) def __init__(self, jan, writer=None): if int(jan[:3]) not in JapanArticleNumber.valid_country_codes: - raise WrongCountryCodeError("Country code isn't between 450-460 " - "or 490-500.") + raise WrongCountryCodeError( + "Country code isn't between 450-460 or 490-500." + ) EuropeanArticleNumber13.__init__(self, jan, writer) @@ -142,7 +150,7 @@ class EuropeanArticleNumber8(EuropeanArticleNumber13): The writer to render the barcode (default: SVGWriter). """ - name = 'EAN-8' + name = "EAN-8" digits = 7 @@ -157,10 +165,10 @@ class EuropeanArticleNumber8(EuropeanArticleNumber13): """ code = _ean.EDGE[:] for number in self.ean[:4]: - code += _ean.CODES['A'][int(number)] + code += _ean.CODES["A"][int(number)] code += _ean.MIDDLE for number in self.ean[4:]: - code += _ean.CODES['C'][int(number)] + code += _ean.CODES["C"][int(number)] code += _ean.EDGE return [code] @@ -175,7 +183,7 @@ class EuropeanArticleNumber14(EuropeanArticleNumber13): The writer to render the barcode (default: SVGWriter). """ - name = 'EAN-14' + name = "EAN-14" digits = 13 def calculate_checksum(self): @@ -185,7 +193,8 @@ class EuropeanArticleNumber14(EuropeanArticleNumber13): :rtype: Integer """ - def sum_(x, y): return int(x) + int(y) + def sum_(x, y): + return int(x) + int(y) evensum = reduce(sum_, self.ean[::2]) oddsum = reduce(sum_, self.ean[1::2]) diff --git a/source/pythonpath/barcode/errors.py b/source/pythonpath/barcode/errors.py old mode 100644 new mode 100755 index 20f9459..7fb448f --- a/source/pythonpath/barcode/errors.py +++ b/source/pythonpath/barcode/errors.py @@ -1,10 +1,5 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - -"""barcode.errors -""" -__docformat__ = 'restructuredtext en' +"""barcode.errors""" +__docformat__ = "restructuredtext en" class BarcodeError(Exception): diff --git a/source/pythonpath/barcode/DejaVuSansMono.ttf b/source/pythonpath/barcode/fonts/DejaVuSansMono.ttf similarity index 100% rename from source/pythonpath/barcode/DejaVuSansMono.ttf rename to source/pythonpath/barcode/fonts/DejaVuSansMono.ttf diff --git a/source/pythonpath/barcode/isxn.py b/source/pythonpath/barcode/isxn.py old mode 100644 new mode 100755 index c5911ff..3d73ce1 --- a/source/pythonpath/barcode/isxn.py +++ b/source/pythonpath/barcode/isxn.py @@ -1,10 +1,3 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - -from barcode.ean import EuropeanArticleNumber13 -from barcode.errors import * - """Module: barcode.isxn :Provided barcodes: ISBN-13, ISBN-10, ISSN @@ -18,17 +11,21 @@ Example:: >>> from barcode import get_barcode >>> ISBN = get_barcode('isbn10') >>> isbn = ISBN('0132354187') - >>> unicode(isbn) + >>> isbn '0132354187' >>> isbn.get_fullcode() '9780132354189' >>> # Test with wrong checksum >>> isbn = ISBN('0132354180') - >>> unicode(isbn) + >>> isbn '0132354187' """ -__docformat__ = 'restructuredtext en' +from barcode.ean import EuropeanArticleNumber13 +from barcode.errors import BarcodeError +from barcode.errors import WrongCountryCodeError + +__docformat__ = "restructuredtext en" class InternationalStandardBookNumber13(EuropeanArticleNumber13): @@ -41,16 +38,16 @@ class InternationalStandardBookNumber13(EuropeanArticleNumber13): The writer to render the barcode (default: SVGWriter). """ - name = 'ISBN-13' + name = "ISBN-13" def __init__(self, isbn, writer=None): - isbn = isbn.replace('-', '') + isbn = isbn.replace("-", "") self.isbn13 = isbn - if isbn[:3] not in ('978', '979'): - raise WrongCountryCodeError('ISBN must start with 978 or 979.') - if isbn[:3] == '979': - if isbn[3:5] not in ('10', '11'): - raise BarcodeError('ISBN must start with 97910 or 97911.') + if isbn[:3] not in ("978", "979"): + raise WrongCountryCodeError("ISBN must start with 978 or 979.") + if isbn[:3] == "979": + if isbn[3:5] not in ("10", "11"): + raise BarcodeError("ISBN must start with 97910 or 97911.") EuropeanArticleNumber13.__init__(self, isbn, writer) @@ -65,30 +62,27 @@ class InternationalStandardBookNumber10(InternationalStandardBookNumber13): The writer to render the barcode (default: SVGWriter). """ - name = 'ISBN-10' + name = "ISBN-10" digits = 9 def __init__(self, isbn, writer=None): - isbn = isbn.replace('-', '') - isbn = isbn[:self.digits] + isbn = isbn.replace("-", "") + isbn = isbn[: self.digits] self.isbn10 = isbn - self.isbn10 = '{0}{1}'.format(isbn, self._calculate_checksum()) - InternationalStandardBookNumber13.__init__(self, '978' + isbn, writer) + self.isbn10 = "{}{}".format(isbn, self._calculate_checksum()) + InternationalStandardBookNumber13.__init__(self, "978" + isbn, writer) def _calculate_checksum(self): - tmp = sum([x * int(y) for x, y in enumerate(self.isbn10[:9], - start=1)]) % 11 + tmp = sum(x * int(y) for x, y in enumerate(self.isbn10[:9], start=1)) % 11 if tmp == 10: - return 'X' + return "X" else: return tmp - def __unicode__(self): + def __str__(self): return self.isbn10 - __str__ = __unicode__ - class InternationalStandardSerialNumber(EuropeanArticleNumber13): """Initializes new ISSN barcode. This code is rendered as EAN-13 @@ -101,33 +95,34 @@ class InternationalStandardSerialNumber(EuropeanArticleNumber13): The writer to render the barcode (default: SVGWriter). """ - name = 'ISSN' + name = "ISSN" digits = 7 def __init__(self, issn, writer=None): - issn = issn.replace('-', '') - issn = issn[:self.digits] + issn = issn.replace("-", "") + issn = issn[: self.digits] self.issn = issn - self.issn = '{0}{1}'.format(issn, self._calculate_checksum()) + self.issn = "{}{}".format(issn, self._calculate_checksum()) EuropeanArticleNumber13.__init__(self, self.make_ean(), writer) def _calculate_checksum(self): - tmp = 11 - sum([x * int(y) for x, y in - enumerate(reversed(self.issn[:7]), start=2)]) % 11 + tmp = ( + 11 + - sum(x * int(y) for x, y in enumerate(reversed(self.issn[:7]), start=2)) + % 11 + ) if tmp == 10: - return 'X' + return "X" else: return tmp def make_ean(self): - return '977{0}00{1}'.format(self.issn[:7], self._calculate_checksum()) + return "977{}00{}".format(self.issn[:7], self._calculate_checksum()) - def __unicode__(self): + def __str__(self): return self.issn - __str__ = __unicode__ - # Shortcuts ISBN13 = InternationalStandardBookNumber13 diff --git a/source/pythonpath/barcode/itf.py b/source/pythonpath/barcode/itf.py index c307255..4978dcd 100644 --- a/source/pythonpath/barcode/itf.py +++ b/source/pythonpath/barcode/itf.py @@ -1,17 +1,12 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - -from barcode.base import Barcode -from barcode.charsets import itf -from barcode.errors import * - """Module: barcode.itf :Provided barcodes: Interleaved 2 of 5 """ -__docformat__ = 'restructuredtext en' +__docformat__ = "restructuredtext en" +from barcode.base import Barcode +from barcode.charsets import itf +from barcode.errors import IllegalCharacterError MIN_SIZE = 0.2 MIN_QUIET_ZONE = 6.4 @@ -32,24 +27,22 @@ class ITF(Barcode): wide/narrow must be in the range 2..3 """ - name = 'ITF' + name = "ITF" def __init__(self, code, writer=None, narrow=2, wide=5): if not code.isdigit(): - raise IllegalCharacterError('ITF code can only contain numbers.') + raise IllegalCharacterError("ITF code can only contain numbers.") # Length must be even, prepend 0 if necessary if len(code) % 2 != 0: - code = '0' + code + code = "0" + code self.code = code self.writer = writer or Barcode.default_writer() self.narrow = narrow self.wide = wide - def __unicode__(self): + def __str__(self): return self.code - __str__ = __unicode__ - def get_fullcode(self): return self.code @@ -57,25 +50,27 @@ class ITF(Barcode): data = itf.START for i in range(0, len(self.code), 2): bars_digit = int(self.code[i]) - spaces_digit = int(self.code[i+1]) + spaces_digit = int(self.code[i + 1]) for j in range(5): data += itf.CODES[bars_digit][j].upper() data += itf.CODES[spaces_digit][j].lower() data += itf.STOP - raw = '' + raw = "" for e in data: - if e == 'W': - raw += '1' * self.wide - if e == 'w': - raw += '0' * self.wide - if e == 'N': - raw += '1' * self.narrow - if e == 'n': - raw += '0' * self.narrow + if e == "W": + raw += "1" * self.wide + if e == "w": + raw += "0" * self.wide + if e == "N": + raw += "1" * self.narrow + if e == "n": + raw += "0" * self.narrow return [raw] def render(self, writer_options, text=None): - options = dict(module_width=MIN_SIZE/self.narrow, - quiet_zone=MIN_QUIET_ZONE) + options = { + "module_width": MIN_SIZE / self.narrow, + "quiet_zone": MIN_QUIET_ZONE, + } options.update(writer_options or {}) return Barcode.render(self, options, text) diff --git a/source/pythonpath/barcode/pybarcode.py b/source/pythonpath/barcode/pybarcode.py index c1938fa..c44723c 100644 --- a/source/pythonpath/barcode/pybarcode.py +++ b/source/pythonpath/barcode/pybarcode.py @@ -1,115 +1,97 @@ -# -*- coding: utf-8 -*- - -from __future__ import print_function - import os - -import barcode - from argparse import ArgumentParser -from barcode.writer import ImageWriter, SVGWriter +import barcode from barcode.version import version +from barcode.writer import ImageWriter +from barcode.writer import SVGWriter -# Optional PyQt4 GUI -try: - from PyQt4 import QtCore -except ImportError: - QtCore = None # lint:ok - -# No GUI available yet -QtCore = None -IMG_FORMATS = ('BMP', 'GIF', 'JPEG', 'MSP', 'PCX', 'PNG', 'TIFF', 'XBM') - - -def open_gui(args, parser=None): - pass +IMG_FORMATS = ("BMP", "GIF", "JPEG", "MSP", "PCX", "PNG", "TIFF", "XBM") def list_types(args, parser=None): - print('\npyBarcode available barcode formats:') - print(', '.join(barcode.PROVIDED_BARCODES)) - print('\n') - print('Available image formats') - print('Standard: svg') + print("\npython-barcode available barcode formats:") + print(", ".join(barcode.PROVIDED_BARCODES)) + print("\n") + print("Available image formats") + print("Standard: svg") if ImageWriter is not None: - print('Pillow:', ', '.join(IMG_FORMATS)) + print("Pillow:", ", ".join(IMG_FORMATS)) else: - print('Pillow: disabled') - print('\n') + print("Pillow: disabled") + print("\n") def create_barcode(args, parser): args.type = args.type.upper() - if args.type != 'SVG' and args.type not in IMG_FORMATS: + if args.type != "SVG" and args.type not in IMG_FORMATS: parser.error( - 'Unknown type {type}. Try list action for available ' - 'types.'.format(type=args.type) + "Unknown type {type}. Try list action for available types.".format( + type=args.type + ) ) args.barcode = args.barcode.lower() if args.barcode not in barcode.PROVIDED_BARCODES: parser.error( - 'Unknown barcode {bc}. Try list action for available ' - 'barcodes.'.format(bc=args.barcode) + "Unknown barcode {bc}. Try list action for available barcodes.".format( + bc=args.barcode + ) ) - if args.type != 'SVG': - opts = dict(format=args.type) + if args.type != "SVG": + opts = {"format": args.type} writer = ImageWriter() else: - opts = dict(compress=args.compress) + opts = {"compress": args.compress} writer = SVGWriter() out = os.path.normpath(os.path.abspath(args.output)) - name = barcode.generate(args.barcode, args.code, writer, out, opts, - args.text) - print('New barcode saved as {0}.'.format(name)) + name = barcode.generate(args.barcode, args.code, writer, out, opts, args.text) + print("New barcode saved as {}.".format(name)) def main(): msg = [] if ImageWriter is None: - msg.append( - 'Image output disabled (Pillow not found), --type option disabled.' - ) + msg.append("Image output disabled (Pillow not found), --type option disabled.") else: msg.append( - 'Image output enabled, use --type option to give image ' - 'format (png, jpeg, ...).' + "Image output enabled, use --type option to give image " + "format (png, jpeg, ...)." ) - if QtCore is None: - msg.append('PyQt not found, gui action disabled.') - else: - msg.append('PyQt found. Use gui action to get a simple GUI.') parser = ArgumentParser( - description='Create standard barcodes via cli.', epilog=' '.join(msg) + description="Create standard barcodes via cli.", epilog=" ".join(msg) ) - parser.add_argument('-v', '--version', action='version', - version='%(prog)s ' + version) - subparsers = parser.add_subparsers(title='Actions') - create_parser = subparsers.add_parser('create', help='Create a barcode ' - 'with the given options.') - create_parser.add_argument('code', help='Code to render as barcode.') - create_parser.add_argument('output', help='Filename for output ' - 'without extension, e. g. mybarcode.') + parser.add_argument( + "-v", "--version", action="version", version="%(prog)s " + version + ) + subparsers = parser.add_subparsers(title="Actions") + create_parser = subparsers.add_parser( + "create", help="Create a barcode with the given options." + ) + create_parser.add_argument("code", help="Code to render as barcode.") create_parser.add_argument( - '-c', '--compress', action='store_true', - help='Compress output, only recognized if type is svg.' + "output", help="Filename for output without extension, e. g. mybarcode." ) - create_parser.add_argument('-b', '--barcode', help='Barcode to use ' - '[default: %(default)s].') - create_parser.add_argument('--text', help='Text to show under the ' - 'barcode.') + create_parser.add_argument( + "-c", + "--compress", + action="store_true", + help="Compress output, only recognized if type is svg.", + ) + create_parser.add_argument( + "-b", "--barcode", help="Barcode to use [default: %(default)s]." + ) + create_parser.add_argument("--text", help="Text to show under the barcode.") if ImageWriter is not None: - create_parser.add_argument('-t', '--type', help='Type of output ' - '[default: %(default)s].') - list_parser = subparsers.add_parser('list', help='List available ' - 'image and code types.') + create_parser.add_argument( + "-t", "--type", help="Type of output [default: %(default)s]." + ) + list_parser = subparsers.add_parser( + "list", help="List available image and code types." + ) list_parser.set_defaults(func=list_types) - if QtCore is not None: - gui_parser = subparsers.add_parser('gui', help='Opens a simple ' - 'PyQt GUI to create barcodes.') - gui_parser.set_defaults(func=open_gui) - create_parser.set_defaults(type='svg', compress=False, func=create_barcode, - barcode='code39', text=None) + create_parser.set_defaults( + type="svg", compress=False, func=create_barcode, barcode="code39", text=None + ) args = parser.parse_args() try: func = args.func @@ -119,5 +101,5 @@ def main(): func(args, parser) -if __name__ == '__main__': +if __name__ == "__main__": main() diff --git a/source/pythonpath/barcode/upc.py b/source/pythonpath/barcode/upc.py old mode 100644 new mode 100755 index cd68259..c3ad3c8 --- a/source/pythonpath/barcode/upc.py +++ b/source/pythonpath/barcode/upc.py @@ -1,61 +1,57 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - -from barcode.base import Barcode -from barcode.charsets import upc as _upc -from barcode.errors import * - -try: - reduce -except NameError: - from functools import reduce - """Module: barcode.upc :Provided barcodes: UPC-A """ -__docformat__ = 'restructuredtext en' +__docformat__ = "restructuredtext en" + +from functools import reduce + +from barcode.base import Barcode +from barcode.charsets import upc as _upc +from barcode.errors import IllegalCharacterError, NumberOfDigitsError class UniversalProductCodeA(Barcode): - """Initializes new UPC-A barcode. + """Universal Product Code (UPC) barcode. - :parameters: - upc : String - The upc number as string. - writer : barcode.writer Instance - The writer to render the barcode (default: SVGWriter). - make_ean: boolean + UPC-A consists of 12 numeric digits. """ - name = 'UPC-A' + name = "UPC-A" digits = 11 def __init__(self, upc, writer=None, make_ean=False): + """Initializes new UPC-A barcode. + + :param str upc: The upc number as string. + :param writer: barcode.writer instance. The writer to render the + barcode (default: SVGWriter). + :param bool make_ean: Indicates if a leading zero should be added to + the barcode. This converts the UPC into a valid European Article + Number (EAN). + """ self.ean = make_ean - upc = upc[:self.digits] + upc = upc[: self.digits] if not upc.isdigit(): - raise IllegalCharacterError('UPC code can only contain numbers.') + raise IllegalCharacterError("UPC code can only contain numbers.") if len(upc) != self.digits: - raise NumberOfDigitsError('UPC must have {0} digits, not ' - '{1}.'.format(self.digits, len(upc))) + raise NumberOfDigitsError( + "UPC must have {} digits, not {}.".format(self.digits, len(upc)) + ) self.upc = upc - self.upc = '{}{}'.format(upc, self.calculate_checksum()) + self.upc = "{}{}".format(upc, self.calculate_checksum()) self.writer = writer or Barcode.default_writer() - def __unicode__(self): + def __str__(self): if self.ean: - return '0' + self.upc + return "0" + self.upc else: return self.upc - __str__ = __unicode__ - def get_fullcode(self): if self.ean: - return '0' + self.upc + return "0" + self.upc else: return self.upc @@ -63,10 +59,13 @@ class UniversalProductCodeA(Barcode): """Calculates the checksum for UPCA/UPC codes :return: The checksum for 'self.upc' - :rtype: Integer + :rtype: int """ - def sum_(x, y): return int(x) + int(y) - upc = self.upc[0:self.digits] + + def sum_(x, y): + return int(x) + int(y) + + upc = self.upc[0 : self.digits] oddsum = reduce(sum_, upc[::2]) evensum = reduce(sum_, upc[1::2]) check = (evensum + oddsum * 3) % 10 @@ -79,17 +78,17 @@ class UniversalProductCodeA(Barcode): """Builds the barcode pattern from 'self.upc' :return: The pattern as string - :rtype: String + :rtype: str """ code = _upc.EDGE[:] - for i, number in enumerate(self.upc[0:6]): - code += _upc.CODES['L'][int(number)] + for _i, number in enumerate(self.upc[0:6]): + code += _upc.CODES["L"][int(number)] code += _upc.MIDDLE for number in self.upc[6:]: - code += _upc.CODES['R'][int(number)] + code += _upc.CODES["R"][int(number)] code += _upc.EDGE @@ -98,17 +97,18 @@ class UniversalProductCodeA(Barcode): def to_ascii(self): """Returns an ascii representation of the barcode. - :rtype: String + :rtype: str """ code = self.build() for i, line in enumerate(code): - code[i] = line.replace('1', '|').replace('0', '_') - return '\n'.join(code) + code[i] = line.replace("1", "|").replace("0", "_") + return "\n".join(code) def render(self, writer_options=None, text=None): - options = dict(module_width=0.33) + options = {"module_width": 0.33} options.update(writer_options or {}) return Barcode.render(self, options, text) + UPCA = UniversalProductCodeA diff --git a/source/pythonpath/barcode/version.py b/source/pythonpath/barcode/version.py index f9f5476..8d5a1c7 100644 --- a/source/pythonpath/barcode/version.py +++ b/source/pythonpath/barcode/version.py @@ -1,4 +1,3 @@ -# coding: utf-8 -# file generated by setuptools_scm -# don't change, don't track in version control -version = '0.10.0' +#!/usr/bin/env python3 + +version = '0.0.0' diff --git a/source/pythonpath/barcode/writer.py b/source/pythonpath/barcode/writer.py old mode 100644 new mode 100755 index 415f26f..e3fbbff --- a/source/pythonpath/barcode/writer.py +++ b/source/pythonpath/barcode/writer.py @@ -1,10 +1,7 @@ -# -*- coding: utf-8 -*- - -from __future__ import unicode_literals - import gzip import os import xml.dom +from typing import BinaryIO from barcode.version import version @@ -17,8 +14,9 @@ except ImportError: from PIL import Image, ImageDraw, ImageFont # lint:ok except ImportError: import logging - log = logging.getLogger('pyBarcode') - log.info('Pillow not found. Image output disabled') + + log = logging.getLogger("pyBarcode") + log.info("Pillow not found. Image output disabled") Image = ImageDraw = ImageFont = None # lint:ok @@ -35,26 +33,26 @@ def _set_attributes(element, **attributes): element.setAttribute(key, value) -def create_svg_object(): +def create_svg_object(with_doctype=False): imp = xml.dom.getDOMImplementation() doctype = imp.createDocumentType( - 'svg', - '-//W3C//DTD SVG 1.1//EN', - 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' + "svg", + "-//W3C//DTD SVG 1.1//EN", + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd", + ) + document = imp.createDocument(None, "svg", doctype if with_doctype else None) + _set_attributes( + document.documentElement, version="1.1", xmlns="http://www.w3.org/2000/svg" ) - document = imp.createDocument(None, 'svg', doctype) - _set_attributes(document.documentElement, version='1.1', - xmlns='http://www.w3.org/2000/svg') return document -SIZE = '{0:.3f}mm' -COMMENT = 'Autogenerated with python-barcode {0}'.format(version) +SIZE = "{0:.3f}mm" +COMMENT = "Autogenerated with python-barcode {}".format(version) PATH = os.path.dirname(os.path.abspath(__file__)) -FONT = os.path.join(PATH, 'DejaVuSansMono.ttf') -class BaseWriter(object): +class BaseWriter: """Baseclass for all writers. Initializes the basic writer options. Childclasses can add more @@ -79,21 +77,26 @@ class BaseWriter(object): rendered output. """ - def __init__(self, initialize=None, paint_module=None, paint_text=None, - finish=None): - self._callbacks = dict( - initialize=initialize, paint_module=paint_module, - paint_text=paint_text, finish=finish - ) + def __init__( + self, initialize=None, paint_module=None, paint_text=None, finish=None + ): + self._callbacks = { + "initialize": initialize, + "paint_module": paint_module, + "paint_text": paint_text, + "finish": finish, + } self.module_width = 10 self.module_height = 10 + self.font_path = os.path.join(PATH, "fonts", "DejaVuSansMono.ttf") self.font_size = 10 self.quiet_zone = 6.5 - self.background = 'white' - self.foreground = 'black' - self.text = '' - self.human = '' # human readable text + self.background = "white" + self.foreground = "black" + self.text = "" + self.human = "" # human readable text self.text_distance = 5 + self.text_line_distance = 1 self.center_text = True def calculate_size(self, modules_per_line, number_of_lines, dpi=300): @@ -112,8 +115,12 @@ class BaseWriter(object): """ width = 2 * self.quiet_zone + modules_per_line * self.module_width height = 2.0 + self.module_height * number_of_lines + number_of_text_lines = len(self.text.splitlines()) if self.font_size and self.text: - height += pt2mm(self.font_size) / 2 + self.text_distance + height += ( + pt2mm(self.font_size) / 2 * number_of_text_lines + self.text_distance + ) + height += self.text_line_distance * (number_of_text_lines - 1) return int(mm2px(width, dpi)), int(mm2px(height, dpi)) def save(self, filename, output): @@ -154,7 +161,7 @@ class BaseWriter(object): :rtype: None """ for key, val in options.items(): - key = key.lstrip('_') + key = key.lstrip("_") if hasattr(self, key): setattr(self, key, val) @@ -167,8 +174,8 @@ class BaseWriter(object): List of strings matching the writer spec (only contain 0 or 1). """ - if self._callbacks['initialize'] is not None: - self._callbacks['initialize'](code) + if self._callbacks["initialize"] is not None: + self._callbacks["initialize"](code) ypos = 1.0 for cc, line in enumerate(code): """ @@ -176,11 +183,11 @@ class BaseWriter(object): result in aliasing gaps '11010111' -> [2, -1, 1, -1, 3] """ - line += ' ' + line += " " c = 1 mlist = [] for i in range(0, len(line) - 1): - if line[i] == line[i+1]: + if line[i] == line[i + 1]: c += 1 else: if line[i] == "1": @@ -197,141 +204,194 @@ class BaseWriter(object): else: color = self.foreground # remove painting for background colored tiles? - self._callbacks['paint_module']( + self._callbacks["paint_module"]( xpos, ypos, self.module_width * abs(mod), color ) xpos += self.module_width * abs(mod) bxe = xpos # Add right quiet zone to every line, except last line, # quiet zone already provided with background, - # should it be removed complety? + # should it be removed completely? if (cc + 1) != len(code): - self._callbacks['paint_module']( + self._callbacks["paint_module"]( xpos, ypos, self.quiet_zone, self.background ) ypos += self.module_height - if self.text and self._callbacks['paint_text'] is not None: + if self.text and self._callbacks["paint_text"] is not None: ypos += self.text_distance if self.center_text: # better center position for text xpos = bxs + ((bxe - bxs) / 2.0) else: xpos = bxs - self._callbacks['paint_text'](xpos, ypos) - return self._callbacks['finish']() + self._callbacks["paint_text"](xpos, ypos) + return self._callbacks["finish"]() class SVGWriter(BaseWriter): - def __init__(self): - BaseWriter.__init__(self, self._init, self._create_module, - self._create_text, self._finish) + BaseWriter.__init__( + self, self._init, self._create_module, self._create_text, self._finish + ) self.compress = False self.dpi = 25.4 + self.with_doctype = True self._document = None self._root = None self._group = None def _init(self, code): width, height = self.calculate_size(len(code[0]), len(code), self.dpi) - self._document = create_svg_object() + self._document = create_svg_object(self.with_doctype) self._root = self._document.documentElement - attributes = dict(width=SIZE.format(width), height=SIZE.format(height)) + attributes = { + "width": SIZE.format(width), + "height": SIZE.format(height), + } _set_attributes(self._root, **attributes) self._root.appendChild(self._document.createComment(COMMENT)) # create group for easier handling in 3rd party software # like corel draw, inkscape, ... - group = self._document.createElement('g') - attributes = dict(id='barcode_group') + group = self._document.createElement("g") + attributes = {"id": "barcode_group"} _set_attributes(group, **attributes) self._group = self._root.appendChild(group) - background = self._document.createElement('rect') - attributes = dict(width='100%', height='100%', - style='fill:{0}'.format(self.background)) + background = self._document.createElement("rect") + attributes = { + "width": "100%", + "height": "100%", + "style": "fill:{}".format(self.background), + } _set_attributes(background, **attributes) self._group.appendChild(background) def _create_module(self, xpos, ypos, width, color): - element = self._document.createElement('rect') - attributes = dict(x=SIZE.format(xpos), y=SIZE.format(ypos), - width=SIZE.format(width), - height=SIZE.format(self.module_height), - style='fill:{0};'.format(color)) + element = self._document.createElement("rect") + attributes = { + "x": SIZE.format(xpos), + "y": SIZE.format(ypos), + "width": SIZE.format(width), + "height": SIZE.format(self.module_height), + "style": "fill:{};".format(color), + } _set_attributes(element, **attributes) self._group.appendChild(element) def _create_text(self, xpos, ypos): - element = self._document.createElement('text') - attributes = dict(x=SIZE.format(xpos), y=SIZE.format(ypos), - style='fill:{0};font-size:{1}pt;text-anchor:' - 'middle;'.format(self.foreground, - self.font_size)) - _set_attributes(element, **attributes) # check option to override self.text with self.human (barcode as # human readable data, can be used to print own formats) - if self.human != '': + if self.human != "": barcodetext = self.human else: barcodetext = self.text - text_element = self._document.createTextNode(barcodetext) - element.appendChild(text_element) - self._group.appendChild(element) + for subtext in barcodetext.split("\n"): + element = self._document.createElement("text") + attributes = { + "x": SIZE.format(xpos), + "y": SIZE.format(ypos), + "style": "fill:{};font-size:{}pt;text-anchor:middle;".format( + self.foreground, + self.font_size, + ), + } + _set_attributes(element, **attributes) + text_element = self._document.createTextNode(subtext) + element.appendChild(text_element) + self._group.appendChild(element) + ypos += pt2mm(self.font_size) + self.text_line_distance def _finish(self): if self.compress: - return self._document.toxml(encoding='UTF-8') + return self._document.toxml(encoding="UTF-8") else: - return self._document.toprettyxml(indent=4 * ' ', newl=os.linesep, - encoding='UTF-8') + return self._document.toprettyxml( + indent=4 * " ", newl=os.linesep, encoding="UTF-8" + ) def save(self, filename, output): if self.compress: - _filename = '{0}.svgz'.format(filename) - f = gzip.open(_filename, 'wb') + _filename = "{}.svgz".format(filename) + f = gzip.open(_filename, "wb") f.write(output) f.close() else: - _filename = '{0}.svg'.format(filename) - with open(_filename, 'wb') as f: + _filename = "{}.svg".format(filename) + with open(_filename, "wb") as f: f.write(output) return _filename + def write(self, content, fp: BinaryIO): + """Write `content` into a file-like object. + + Content should be a barcode rendered by this writer. + """ + fp.write(content) + if Image is None: ImageWriter = None else: - class ImageWriter(BaseWriter): - def __init__(self): - BaseWriter.__init__(self, self._init, self._paint_module, - self._paint_text, self._finish) - self.format = 'PNG' + class ImageWriter(BaseWriter): # type: ignore + format: str + mode: str + dpi: int + + def __init__(self, format="PNG", mode="RGB"): + """Initialise a new write instance. + + :params format: The file format for the generated image. This parameter can + take any value that Pillow accepts. + :params mode: The colour-mode for the generated image. Set this to RGBA if + you wish to use colours with transparency. + """ + BaseWriter.__init__( + self, self._init, self._paint_module, self._paint_text, self._finish + ) + self.format = format + self.mode = mode self.dpi = 300 self._image = None self._draw = None def _init(self, code): size = self.calculate_size(len(code[0]), len(code), self.dpi) - self._image = Image.new('RGB', size, self.background) + self._image = Image.new(self.mode, size, self.background) self._draw = ImageDraw.Draw(self._image) def _paint_module(self, xpos, ypos, width, color): - size = [(mm2px(xpos, self.dpi), mm2px(ypos, self.dpi)), - (mm2px(xpos + width, self.dpi), - mm2px(ypos + self.module_height, self.dpi))] + size = [ + (mm2px(xpos, self.dpi), mm2px(ypos, self.dpi)), + ( + mm2px(xpos + width, self.dpi), + mm2px(ypos + self.module_height, self.dpi), + ), + ] self._draw.rectangle(size, outline=color, fill=color) def _paint_text(self, xpos, ypos): - font = ImageFont.truetype(FONT, self.font_size * 2) - width, height = font.getsize(self.text) - pos = (mm2px(xpos, self.dpi) - width // 2, - mm2px(ypos, self.dpi) - height // 4) - self._draw.text(pos, self.text, font=font, fill=self.foreground) + font = ImageFont.truetype(self.font_path, self.font_size * 2) + for subtext in self.text.split("\n"): + width, height = font.getsize(subtext) + # determine the maximum width of each line + pos = ( + mm2px(xpos, self.dpi) - width // 2, + mm2px(ypos, self.dpi) - height // 4, + ) + self._draw.text(pos, subtext, font=font, fill=self.foreground) + ypos += pt2mm(self.font_size) / 2 + self.text_line_distance def _finish(self): return self._image def save(self, filename, output): - filename = '{0}.{1}'.format(filename, self.format.lower()) + filename = "{}.{}".format(filename, self.format.lower()) output.save(filename, self.format.upper()) return filename + + def write(self, content, fp: BinaryIO): + """Write `content` into a file-like object. + + Content should be a barcode rendered by this writer. + """ + content.save(fp, format=self.format) diff --git a/source/pythonpath/easymacro.py b/source/pythonpath/easymacro.py index 30e717e..5a75695 100644 --- a/source/pythonpath/easymacro.py +++ b/source/pythonpath/easymacro.py @@ -499,6 +499,11 @@ def dict_to_property(values, uno_any=False): return ps +def dict_to_named(values): + ps = tuple([NamedValue(n, v) for n, v in values.items()]) + return ps + + def property_to_dict(values): d = {i.Name: i.Value for i in values} return d @@ -1837,6 +1842,33 @@ class LOCellRange(object): self.sheet.obj.copyRange(self.address, source.range_address) return + def transpose(self, formula=False): + data = self.data + if formula: + data = self.formula + data = tuple(zip(*data)) + self.clear(1023) + self[0,0].copy_from(data, formula=formula) + return + + def transpose2(self): + # ~ 'Flags': 'A', + # ~ 'FormulaCommand': 0, + # ~ 'SkipEmptyCells': False, + # ~ 'AsLink': False, + # ~ 'MoveMode': 4, + args = { + 'Transpose': True, + } + args = dict_to_property(args) + self.select() + copy() + self.clear(1023) + self[0,0].select() + call_dispatch('.uno:InsertContents', args) + set_clipboard('') + return + def offset(self, row=1, col=0): ra = self.obj.getRangeAddress() col = ra.EndColumn + col @@ -1939,6 +1971,10 @@ class LOCellRange(object): def auto_format(self, value): self.obj.autoFormat(value) + def auto_width(self): + self.obj.Columns.OptimalWidth = True + return + def insert_image(self, path, **kwargs): s = self.obj.Size w = kwargs.get('width', s.Width) @@ -2060,6 +2096,22 @@ class LOCellRange(object): found = self.obj.replaceAll(descriptor) return found + @property + def validation(self): + return self.obj.Validation + @validation.setter + def validation(self, values): + is_list = False + current = self.validation + for k, v in values.items(): + if k == 'Type' and v == 6: + is_list = True + if k == 'Formula1' and is_list: + if isinstance(v, (tuple, list)): + v = ';'.join(['"{}"'.format(i) for i in v]) + setattr(current, k, v) + self.obj.Validation = current + class EventsListenerBase(unohelper.Base, XEventListener): @@ -2454,23 +2506,39 @@ class UnoBaseObject(object): return self._model.Width @width.setter def width(self, value): - if hasattr(self.model, 'Width'): - self.model.Width = value - elif hasattr(self.obj, 'PosSize'): - self._set_possize('Width', value) + self.model.Width = value + + @property + def ps_width(self): + return self._get_possize('Width') + @ps_width.setter + def ps_width(self, value): + self._set_possize('Width', value) @property def height(self): - if hasattr(self.model, 'Height'): - return self.model.Height - ps = self.obj.getPosSize() - return ps.Height + return self.model.Height @height.setter def height(self, value): - if hasattr(self.model, 'Height'): - self.model.Height = value - elif hasattr(self.obj, 'PosSize'): - self._set_possize('Height', value) + self.model.Height = value + + @property + def ps_height(self): + return self._get_possize('Height') + @ps_height.setter + def ps_height(self, value): + self._set_possize('Height', value) + + @property + def size(self): + ps = self.obj.getPosSize() + return (ps.Width, ps.Height) + @size.setter + def size(self, value): + ps = self.obj.getPosSize() + ps.Width = value[0] + ps.Height = value[1] + self.obj.setPosSize(ps.X, ps.Y, ps.Width, ps.Height, SIZE) @property def tag(self): @@ -4493,7 +4561,7 @@ def _zippwd(source, target, pwd): # ~ Export ok -def zip(source, target='', mode='w', pwd=''): +def zip_files(source, target='', mode='w', pwd=''): if pwd: return _zippwd(source, target, pwd) diff --git a/source/pythonpath/qrcode/main.py b/source/pythonpath/qrcode/main.py index 5cbc2a8..55999e9 100644 --- a/source/pythonpath/qrcode/main.py +++ b/source/pythonpath/qrcode/main.py @@ -1,12 +1,8 @@ -import struct -from bisect import bisect_left - from qrcode import constants, exceptions, util from qrcode.image.base import BaseImage - -def int2byte(value): - return struct.Struct('>B').pack(value) +import six +from bisect import bisect_left def make(data=None, **kwargs): @@ -46,13 +42,21 @@ class QRCode(object): # Spec says border should be at least four boxes wide, but allow for # any (e.g. for producing printable QR codes). self.border = int(border) - _check_mask_pattern(mask_pattern) self.mask_pattern = mask_pattern self.image_factory = image_factory if image_factory is not None: assert issubclass(image_factory, BaseImage) self.clear() + @property + def mask_pattern(self): + return self._mask_pattern + + @mask_pattern.setter + def mask_pattern(self, pattern): + _check_mask_pattern(pattern) + self._mask_pattern = pattern + def clear(self): """ Reset the internal data. @@ -240,7 +244,7 @@ class QRCode(object): self.make() modcount = self.modules_count - codes = [int2byte(code).decode('cp437') + codes = [six.int2byte(code).decode('cp437') for code in (255, 223, 220, 219)] if tty: invert = True @@ -381,7 +385,7 @@ class QRCode(object): data_len = len(data) - for col in range(self.modules_count - 1, 0, -2): + for col in six.moves.xrange(self.modules_count - 1, 0, -2): if col <= 6: col -= 1 diff --git a/source/pythonpath/qrcode/util.py b/source/pythonpath/qrcode/util.py index 74ab39f..58f3d21 100644 --- a/source/pythonpath/qrcode/util.py +++ b/source/pythonpath/qrcode/util.py @@ -1,8 +1,8 @@ import re import math -# ~ import six -# ~ from six.moves import xrange +import six +from six.moves import xrange from qrcode import base, exceptions, LUT @@ -32,10 +32,8 @@ MODE_SIZE_LARGE = { MODE_KANJI: 12, } - -ALPHA_NUM = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:'.encode("latin-1") -RE_ALPHA_NUM = re.compile('^['.encode("latin-1") + re.escape(ALPHA_NUM) + r']*\Z'.encode("latin-1")) - +ALPHA_NUM = six.b('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:') +RE_ALPHA_NUM = re.compile(six.b('^[') + re.escape(ALPHA_NUM) + six.b(r']*\Z')) # The number of bits for numeric delimited data lengths. NUMBER_LENGTH = {3: 10, 2: 7, 1: 4} @@ -98,8 +96,8 @@ PAD1 = 0x11 _data_count = lambda block: block.data_count BIT_LIMIT_TABLE = [ [0] + [8*sum(map(_data_count, base.rs_blocks(version, error_correction))) - for version in range(1, 41)] - for error_correction in range(4) + for version in xrange(1, 41)] + for error_correction in xrange(4) ] @@ -194,7 +192,7 @@ def lost_point(modules): def _lost_point_level1(modules, modules_count): lost_point = 0 - modules_range = range(modules_count) + modules_range = xrange(modules_count) container = [0] * (modules_count + 1) for row in modules_range: @@ -227,7 +225,7 @@ def _lost_point_level1(modules, modules_count): container[length] += 1 lost_point += sum(container[each_length] * (each_length - 2) - for each_length in range(5, modules_count + 1)) + for each_length in xrange(5, modules_count + 1)) return lost_point @@ -235,7 +233,7 @@ def _lost_point_level1(modules, modules_count): def _lost_point_level2(modules, modules_count): lost_point = 0 - modules_range = range(modules_count - 1) + modules_range = xrange(modules_count - 1) for row in modules_range: this_row = modules[row] next_row = modules[row + 1] @@ -264,8 +262,8 @@ def _lost_point_level3(modules, modules_count): # row/column, preceded or followed by light area 4 modules wide. From ISOIEC. # pattern1: 10111010000 # pattern2: 00001011101 - modules_range = range(modules_count) - modules_range_short = range(modules_count-10) + modules_range = xrange(modules_count) + modules_range_short = xrange(modules_count-10) lost_point = 0 for row in modules_range: @@ -350,14 +348,14 @@ def optimal_data_chunks(data, minimum=4): :param minimum: The minimum number of bytes in a row to split as a chunk. """ data = to_bytestring(data) - num_pattern = r'\d'.encode("latin-1") - alpha_pattern = '['.encode("latin-1") + re.escape(ALPHA_NUM) + ']'.encode("latin-1") + num_pattern = six.b(r'\d') + alpha_pattern = six.b('[') + re.escape(ALPHA_NUM) + six.b(']') if len(data) <= minimum: - num_pattern = re.compile('^'.encode("latin-1") + num_pattern + '+$'.encode("latin-1")) - alpha_pattern = re.compile('^'.encode("latin-1") + alpha_pattern + '+$'.encode("latin-1")) + num_pattern = re.compile(six.b('^') + num_pattern + six.b('+$')) + alpha_pattern = re.compile(six.b('^') + alpha_pattern + six.b('+$')) else: re_repeat = ( - '{'.encode("latin-1") + str(minimum).encode('ascii') + ',}'.encode("latin-1")) + six.b('{') + six.text_type(minimum).encode('ascii') + six.b(',}')) num_pattern = re.compile(num_pattern + re_repeat) alpha_pattern = re.compile(alpha_pattern + re_repeat) num_bits = _optimal_split(data, num_pattern) @@ -392,8 +390,8 @@ def to_bytestring(data): Convert data to a (utf-8 encoded) byte-string if it isn't a byte-string already. """ - if not isinstance(data, bytes): - data = str(data).encode('utf-8') + if not isinstance(data, six.binary_type): + data = six.text_type(data).encode('utf-8') return data @@ -441,12 +439,12 @@ class QRData(object): def write(self, buffer): if self.mode == MODE_NUMBER: - for i in range(0, len(self.data), 3): + for i in xrange(0, len(self.data), 3): chars = self.data[i:i + 3] bit_length = NUMBER_LENGTH[len(chars)] buffer.put(int(chars), bit_length) elif self.mode == MODE_ALPHA_NUM: - for i in range(0, len(self.data), 2): + for i in xrange(0, len(self.data), 2): chars = self.data[i:i + 2] if len(chars) > 1: buffer.put( @@ -455,13 +453,12 @@ class QRData(object): else: buffer.put(ALPHA_NUM.find(chars), 6) else: - # ~ if six.PY3: + if six.PY3: # Iterating a bytestring in Python 3 returns an integer, # no need to ord(). - # ~ data = self.data - # ~ else: - # ~ data = [ord(c) for c in self.data] - data = self.data + data = self.data + else: + data = [ord(c) for c in self.data] for c in data: buffer.put(c, 8) diff --git a/zaz.py b/zaz.py index 9cad0c8..d08a269 100644 --- a/zaz.py +++ b/zaz.py @@ -19,6 +19,7 @@ import argparse import os +import py_compile import re import sys import zipfile @@ -44,8 +45,18 @@ from conf import ( class LiboXML(object): + CONTEXT = { + 'calc': 'com.sun.star.sheet.SpreadsheetDocument', + 'writer': 'com.sun.star.text.TextDocument', + 'impress': 'com.sun.star.presentation.PresentationDocument', + 'draw': 'com.sun.star.drawing.DrawingDocument', + 'base': 'com.sun.star.sdb.OfficeDatabaseDocument', + 'math': 'com.sun.star.formula.FormulaProperties', + 'basic': 'com.sun.star.script.BasicIDE', + } TYPES = { 'py': 'application/vnd.sun.star.uno-component;type=Python', + 'pyc': 'application/binary', 'zip': 'application/binary', 'xcu': 'application/vnd.sun.star.configuration-data', 'rdb': 'application/vnd.sun.star.uno-typelibrary;type=RDB', @@ -53,18 +64,34 @@ class LiboXML(object): 'help': 'application/vnd.sun.star.help', 'component': 'application/vnd.sun.star.uno-components', } - NAME_SPACES = { + NS_MANIFEST = { 'manifest_version': '1.2', 'manifest': 'urn:oasis:names:tc:opendocument:xmlns:manifest:1.0', 'xmlns:loext': 'urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0', } + NS_DESCRIPTION = { + 'xmlns': 'http://openoffice.org/extensions/description/2006', + 'xmlns:xlink': 'http://www.w3.org/1999/xlink', + 'xmlns:d': 'http://openoffice.org/extensions/description/2006', + } + NS_ADDONS = { + 'xmlns:xs': 'http://www.w3.org/2001/XMLSchema', + 'xmlns:oor': 'http://openoffice.org/2001/registry', + } + NS_UPDATE = { + 'xmlns': 'http://openoffice.org/extensions/update/2006', + 'xmlns:d': 'http://openoffice.org/extensions/description/2006', + 'xmlns:xlink': 'http://www.w3.org/1999/xlink', + } def __init__(self): self._manifest = None self._paths = [] + self._path_images = '' + self._toolbars = [] def _save_path(self, attr): - self._paths.append(attr['{{{}}}full-path'.format(self.NAME_SPACES['manifest'])]) + self._paths.append(attr['{{{}}}full-path'.format(self.NS_MANIFEST['manifest'])]) return def _clean(self, name, nodes): @@ -86,18 +113,18 @@ class LiboXML(object): def new_manifest(self, data): attr = { - 'manifest:version': self.NAME_SPACES['manifest_version'], - 'xmlns:manifest': self.NAME_SPACES['manifest'], - 'xmlns:loext': self.NAME_SPACES['xmlns:loext'], + 'manifest:version': self.NS_MANIFEST['manifest_version'], + 'xmlns:manifest': self.NS_MANIFEST['manifest'], + 'xmlns:loext': self.NS_MANIFEST['xmlns:loext'], } self._manifest = ET.Element('manifest:manifest', attr) return self.add_data_manifest(data) def parse_manifest(self, data): - ET.register_namespace('manifest', self.NAME_SPACES['manifest']) + ET.register_namespace('manifest', self.NS_MANIFEST['manifest']) self._manifest = ET.fromstring(data) - data = {'xmlns:loext': self.NAME_SPACES['xmlns:loext']} - self._manifest.attrib.update(**data) + attr = {'xmlns:loext': self.NS_MANIFEST['xmlns:loext']} + self._manifest.attrib.update(**attr) self._clean('manifest', self._manifest) return @@ -116,6 +143,217 @@ class LiboXML(object): ET.SubElement(self._manifest, node_name, attr) return self._get_xml(self._manifest) + def new_description(self, data): + doc = ET.Element('description', self.NS_DESCRIPTION) + + key = 'identifier' + ET.SubElement(doc, key, data[key]) + + key = 'version' + ET.SubElement(doc, key, data[key]) + + key = 'display-name' + node = ET.SubElement(doc, key) + for k, v in data[key].items(): + sn = ET.SubElement(node, 'name', {'lang': k}) + sn.text = v + + node = ET.SubElement(doc, 'extension-description') + for k in data[key].keys(): + attr = { + 'lang': k, + 'xlink:href': f'description/desc_{k}.txt', + } + ET.SubElement(node, 'src', attr) + + key = 'icon' + node = ET.SubElement(doc, key) + attr = {'xlink:href': f"images/{data[key]}"} + ET.SubElement(node, 'default', attr) + + key = 'publisher' + node = ET.SubElement(doc, key) + for k, v in data[key].items(): + attr = { + 'xlink:href': v['link'], + 'lang': k, + } + sn = ET.SubElement(node, 'name', attr) + sn.text = v['text'] + + key = 'display-name' + node = ET.SubElement(doc, 'registration') + attr = { + 'accept-by': 'user', + 'suppress-on-update': 'true', + } + node = ET.SubElement(node, 'simple-license', attr) + for k in data[key].keys(): + attr = { + 'xlink:href': f"{DIRS['registration']}/license_{k}.txt", + 'lang': k + } + ET.SubElement(node, 'license-text', attr) + + if data['update']: + node = ET.SubElement(doc, 'update-information') + ET.SubElement(node, 'src', {'xlink:href': data['update']}) + + return self._get_xml(doc) + + def _get_context(self, args): + if not args: + return '' + context = ','.join([self.CONTEXT[v] for v in args.split(',')]) + return context + + def _add_node_value(self, node, name, value='_self'): + attr = {'oor:name': name, 'oor:type': 'xs:string'} + sn = ET.SubElement(node, 'prop', attr) + sn = ET.SubElement(sn, 'value') + sn.text = value + return + + def _add_menu(self, id_extension, node, index, menu, in_menu_bar=True): + if in_menu_bar: + attr = { + 'oor:name': index, + 'oor:op': 'replace', + } + subnode = ET.SubElement(node, 'node', attr) + else: + subnode = node + + attr = {'oor:name': 'Title', 'oor:type': 'xs:string'} + sn1 = ET.SubElement(subnode, 'prop', attr) + for k, v in menu['title'].items(): + sn2 = ET.SubElement(sn1, 'value', {'xml:lang': k}) + sn2.text = v + value = self._get_context(menu['context']) + self._add_node_value(subnode, 'Context', value) + + if 'submenu' in menu: + sn = ET.SubElement(subnode, 'node', {'oor:name': 'Submenu'}) + for i, m in enumerate(menu['submenu']): + self._add_menu(id_extension, sn, f'{index}.s{i}', m) + if m.get('toolbar', False): + self._toolbars.append(m) + return + + value = f"service:{id_extension}?{menu['argument']}" + self._add_node_value(subnode, 'URL', value) + self._add_node_value(subnode, 'Target') + value = f"%origin%/{self._path_images}/{menu['icon']}" + self._add_node_value(subnode, 'ImageIdentifier', value) + return + + def new_addons(self, id_extension, data): + in_menu_bar = data['parent'] == 'OfficeMenuBar' + self._path_images = data['images'] + attr = { + 'oor:name': 'Addons', + 'oor:package': 'org.openoffice.Office', + } + attr.update(self.NS_ADDONS) + doc = ET.Element('oor:component-data', attr) + parent = ET.SubElement(doc, 'node', {'oor:name': 'AddonUI'}) + node = ET.SubElement(parent, 'node', {'oor:name': data['parent']}) + + op = 'fuse' + if in_menu_bar: + op = 'replace' + + attr = {'oor:name': id_extension, 'oor:op': op} + node = ET.SubElement(node, 'node', attr) + + if in_menu_bar: + attr = {'oor:name': 'Title', 'oor:type': 'xs:string'} + subnode = ET.SubElement(node, 'prop', attr) + for k, v in data['main'].items(): + sn = ET.SubElement(subnode, 'value', {'xml:lang': k}) + sn.text = v + + self._add_node_value(node, 'Target') + node = ET.SubElement(node, 'node', {'oor:name': 'Submenu'}) + + for i, menu in enumerate(data['menus']): + self._add_menu(id_extension, node, f'm{i}', menu, in_menu_bar) + if menu.get('toolbar', False): + self._toolbars.append(menu) + + if self._toolbars: + attr = {'oor:name': 'OfficeToolBar'} + toolbar = ET.SubElement(parent, 'node', attr) + attr = {'oor:name': id_extension, 'oor:op': 'replace'} + toolbar = ET.SubElement(toolbar, 'node', attr) + for t, menu in enumerate(self._toolbars): + self._add_menu(id_extension, toolbar, f't{t}', menu) + + return self._get_xml(doc) + + def _add_shortcut(self, node, key, id_extension, arg): + attr = {'oor:name': key, 'oor:op': 'fuse'} + subnode = ET.SubElement(node, 'node', attr) + subnode = ET.SubElement(subnode, 'prop', {'oor:name': 'Command'}) + subnode = ET.SubElement(subnode, 'value', {'xml:lang': 'en-US'}) + subnode.text = f"service:{id_extension}?{arg}" + return + + def _get_acceleartors(self, menu): + if 'submenu' in menu: + for m in menu['submenu']: + return self._get_acceleartors(m) + + if not menu.get('shortcut', ''): + return '' + + return menu + + def new_accelerators(self, id_extension, menus): + attr = { + 'oor:name': 'Accelerators', + 'oor:package': 'org.openoffice.Office', + } + attr.update(self.NS_ADDONS) + doc = ET.Element('oor:component-data', attr) + parent = ET.SubElement(doc, 'node', {'oor:name': 'PrimaryKeys'}) + + data = [] + for m in menus: + info = self._get_acceleartors(m) + if info: + data.append(info) + + node_global = None + node_modules = None + for m in data: + if m['context']: + if node_modules is None: + node_modules = ET.SubElement( + parent, 'node', {'oor:name': 'Modules'}) + for app in m['context'].split(','): + node = ET.SubElement( + node_modules, 'node', {'oor:name': self.CONTEXT[app]}) + self._add_shortcut( + node, m['shortcut'], id_extension, m['argument']) + else: + if node_global is None: + node_global = ET.SubElement( + parent, 'node', {'oor:name': 'Global'}) + self._add_shortcut( + node_global, m['shortcut'], id_extension, m['argument']) + + return self._get_xml(doc) + + def new_update(self, extension, url_oxt): + doc = ET.Element('description', self.NS_UPDATE) + ET.SubElement(doc, 'identifier', {'value': extension['id']}) + ET.SubElement(doc, 'version', {'value': extension['version']}) + node = ET.SubElement(doc, 'update-download') + ET.SubElement(node, 'src', {'xlink:href': url_oxt}) + node = ET.SubElement(doc, 'release-notes') + return self._get_xml(doc) + def _get_xml(self, doc): xml = parseString(ET.tostring(doc, encoding='utf-8')) return xml.toprettyxml(indent=' ', encoding='utf-8').decode('utf-8') @@ -155,11 +393,7 @@ def _get_files(path, filters=''): def _compress_oxt(): log.info('Compress OXT extension...') - path = DIRS['files'] - if not _exists(path): - _mkdir(path) - - path_oxt = _join(path, FILES['oxt']) + path_oxt = _join(DIRS['files'], FILES['oxt']) z = zipfile.ZipFile(path_oxt, 'w', compression=zipfile.ZIP_DEFLATED) root_len = len(os.path.abspath(DIRS['source'])) @@ -173,10 +407,6 @@ def _compress_oxt(): z.write(fullpath, file_name, zipfile.ZIP_DEFLATED) z.close() - if DATA['update']: - path_xml = _join(path, FILES['update']) - _save(path_xml, DATA['update']) - log.info('Extension OXT created sucesfully...') return @@ -294,6 +524,10 @@ def _compile_idl(): def _update_files(): + path_files = DIRS['files'] + if not _exists(path_files): + _mkdir(path_files) + path_source = DIRS['source'] for k, v in INFO.items(): @@ -325,16 +559,21 @@ def _update_files(): data = xml.new_manifest(DATA['manifest']) _save(path, data) - path = _join(path_source, DIRS['office']) - _mkdir(path) - path = _join(path_source, DIRS['office'], FILES['shortcut']) - _save(path, DATA['shortcut']) - - path = _join(path_source, FILES['addons']) - _save(path, DATA['addons']) - path = _join(path_source, FILES['description']) - _save(path, DATA['description']) + data = xml.new_description(DATA['description']) + _save(path, data) + + if TYPE_EXTENSION == 1: + path = _join(path_source, FILES['addons']) + data = xml.new_addons(EXTENSION['id'], DATA['addons']) + _save(path, data) + + path = _join(path_source, DIRS['office']) + _mkdir(path) + path = _join(path_source, DIRS['office'], FILES['shortcut']) + data = xml.new_accelerators(EXTENSION['id'], DATA['addons']['menus']) + _save(path, data) + if TYPE_EXTENSION == 3: path = _join(path_source, FILES['addin']) @@ -342,10 +581,15 @@ def _update_files(): if USE_LOCALES: msg = "Don't forget generate DOMAIN.pot for locales" - log.info(msg) for lang in EXTENSION['languages']: path = _join(path_source, DIRS['locales'], lang, 'LC_MESSAGES') Path(path).mkdir(parents=True, exist_ok=True) + log.info(msg) + + if DATA['update']: + path_xml = _join(path_files, FILES['update']) + data = xml.new_update(EXTENSION, DATA['update']) + _save(path_xml, data) _compile_idl() return @@ -373,7 +617,8 @@ def _get_info_path(path): def _zip_embed(source, files): PATH = 'Scripts/python/' - EASYMACRO = 'easymacro.' + EASYMACRO = 'easymacro2.py' + FILE_PYC = 'easymacro.pyc' p, f, name, e = _get_info_path(source) now = datetime.now().strftime('_%Y%m%d_%H%M%S') @@ -381,12 +626,10 @@ def _zip_embed(source, files): copyfile(source, path_source) target = source - with zipfile.PyZipFile(EASYMACRO + 'zip', mode='w') as zf: - zf.writepy(EASYMACRO + 'py') - + py_compile.compile(EASYMACRO, FILE_PYC) xml = LiboXML() - path_easymacro = PATH + EASYMACRO + 'zip' + path_easymacro = PATH + FILE_PYC names = [f[1] for f in files] + [path_easymacro] nodes = [] with zipfile.ZipFile(target, 'w', compression=zipfile.ZIP_DEFLATED) as zt: @@ -405,14 +648,14 @@ def _zip_embed(source, files): data.append(name) zt.write(path, name) - zt.write(EASYMACRO + 'zip', path_easymacro) + zt.write(FILE_PYC, path_easymacro) data.append(path_easymacro) xml.parse_manifest(xml_manifest) xml_manifest = xml.add_data_manifest(data) zt.writestr(path_manifest, xml_manifest) - os.unlink(EASYMACRO + 'zip') + os.unlink(FILE_PYC) return @@ -504,7 +747,9 @@ def main(args): if not _validate_update(): return - _update_files() + if not args.only_compress: + _update_files() + _compress_oxt() if args.install: @@ -529,6 +774,8 @@ def _process_command_line_arguments(): default=False, required=False) parser.add_argument('-u', '--update', dest='update', action='store_true', default=False, required=False) + parser.add_argument('-oc', '--only_compress', dest='only_compress', + action='store_true', default=False, required=False) return parser.parse_args()