Compare commits

...

11 Commits

Author SHA1 Message Date
Mauricio Baeza 5f1207836a Remove set image in column 2020-12-26 21:59:07 -06:00
Mauricio Baeza 35d356a698 Update zaz 2020-12-24 21:07:33 -06:00
Mauricio Baeza b3d8674a9e Remove insert in draw and impress 2020-12-23 22:35:47 -06:00
Mauricio Baeza 490975b268 Refactorice make code 2020-12-22 21:59:31 -06:00
Mauricio Baeza 86c7224b5b Move create with dialog 2020-12-22 21:49:51 -06:00
Mauricio Baeza 8714c7b75c Refactory insert barcode in Writer 2020-12-21 22:32:36 -06:00
Mauricio Baeza 91a5ce7861 Validate data 2020-12-21 22:19:44 -06:00
Mauricio Baeza e5b37216ba Refactory insert barcode in Calc 2020-12-21 22:17:17 -06:00
Mauricio Baeza f410bf3d19 Separate main 2020-12-20 22:00:38 -06:00
Mauricio Baeza 04aa7eea7c Update easymacro.py 2020-12-20 21:50:17 -06:00
Mauricio Baeza 0360b5a774 Update libraries 2020-10-11 19:48:57 -05:00
33 changed files with 11377 additions and 8692 deletions

View File

@ -1,3 +1,8 @@
v 0.7.0 [-oct-2020]
---------------------
- Update libraries
v 0.6.0 [15-nov-2019]
---------------------
- Call by code

View File

@ -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)

View File

@ -1,2 +1 @@
0.6.0
0.7.0

282
conf.py
View File

@ -25,24 +25,24 @@ import logging
# ~ 3 = Calc addin
TYPE_EXTENSION = 1
# ~ https://semver.org/
VERSION = '0.6.0'
# ~ Your great extension name, not used spaces
NAME = 'ZAZBarCode'
# ~ https://semver.org/
VERSION = '0.7.0'
# ~ Should be unique, used URL inverse
ID = 'net.elmau.zaz.BarCode'
# ~ If you extension will be multilanguage set: True
# ~ This feature used gettext, set pythonpath and easymacro in True
# ~ Yu can used PoEdit for edit PO files and generate MO files.
# ~ You can used PoEdit for edit PO files and generate MO files.
# ~ https://poedit.net/
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'
# ~ You can use PoEdit for update locales too
PATH_MSGMERGE = 'msgmerge'
@ -57,9 +57,6 @@ ICON = 'images/logo.png'
# ~ Name inside extensions
ICON_EXT = f'{NAME.lower()}.png'
# ~ For example
# ~ DEPENDENCIES_MINIMAL = '6.0'
DEPENDENCIES_MINIMAL = ''
# ~ Change for you favorite license
LICENSE_EN = f"""This file is part of {NAME}.
@ -93,17 +90,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
@ -123,7 +109,7 @@ MENU_MAIN = {
MENUS = (
{
'title': {'en': 'Insert BarCode', 'es': 'Insertar Código'},
'argument': 'ask',
'argument': 'used_dialog',
'context': 'calc,writer,impress,draw',
'icon': 'barcode',
'toolbar': False,
@ -302,9 +288,8 @@ FILES = {
# ~ URLs for update for example
# ~ URL_XML_UPDATE = 'https://gitlab.com/USER/PROYECT/raw/BRANCH/FOLDERs/FILE_NAME'
URL_BASE = 'https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/'
URL_XML_UPDATE = URL_BASE + FILES['update']
URL_OXT = URL_BASE + FILES['oxt']
URL_XML_UPDATE = ''
URL_OXT = ''
# ~ Default program for test: --calc, --writer, --draw
@ -372,7 +357,7 @@ elif TYPE_EXTENSION == 3:
METHODS = _methods()
FILE_PY = f"""import uno
DATA_PY = f"""import uno
import unohelper
{SRV_IMPORT}
@ -392,177 +377,6 @@ g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation({NAME}, ID_EXTENSION, SERVICE)
"""
tmp = ' <name lang="{}">{}</name>'
node = [tmp.format(k, v['display_name']) for k, v in INFO.items()]
NODE_DISPLAY_NAME = '\n'.join(node)
tmp = ' <src lang="{0}" xlink:href="description/desc_{0}.txt" />'
node = [tmp.format(k) for k, v in INFO.items()]
NODE_EXTENSION_DESCRIPTION = '\n'.join(node)
NODE_ICON = ''
if ICON:
NODE_ICON = f' <default xlink:href="images/{ICON_EXT}" />'
NODE_PUBLISHER = ''
if PUBLISHER:
tmp = ' <name xlink:href="{}" lang="{}">{}</name>'
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 <dependencies>
<OpenOffice.org-minimal-version value="{DEPENDENCIES_MINIMAL}" d:name="LibreOffice {DEPENDENCIES_MINIMAL}"/>
</dependencies>"""
tmp = ' <license-text xlink:href="{0}/license_{1}.txt" lang="{1}" />'
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"""
<update-information>
<src xlink:href="{URL_XML_UPDATE}" />
</update-information>"""
FILE_DESCRIPTION = f"""<?xml version='1.0' encoding='UTF-8'?>
<description xmlns="http://openoffice.org/extensions/description/2006" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:d="http://openoffice.org/extensions/description/2006">
<identifier value="{ID}" />
<version value="{VERSION}" />
<display-name>
{NODE_DISPLAY_NAME}
</display-name>
<extension-description>
{NODE_EXTENSION_DESCRIPTION}
</extension-description>
<icon>
{NODE_ICON}
</icon>
<publisher>
{NODE_PUBLISHER}
</publisher>
<registration>
<simple-license accept-by="user" suppress-on-update="true" >
{NODE_LICENSE}
</simple-license>
</registration>{NODE_DEPENDENCIES_MINIMAL}{NODE_UPDATE}
</description>
"""
NODE_MENU = """ <node oor:name="{id}.{index}" oor:op="{opt}">
<prop oor:name="Title" oor:type="xs:string">
{titles}
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:{id}?{argument}</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>{context}</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/{folder}/{icon}</value>
</prop>
</node>"""
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 = ' <value xml:lang="{}">{}</value>'
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 = ' <value xml:lang="{}">{}</value>'
titles = '\n'.join([tmp.format(k, v) for k, v in MENU_MAIN.items()])
SUBMENUS = '<node oor:name="Submenu">\n ' + '\n'.join(menus) + '\n </node>'
NODE_MENUS = f""" <node oor:name="{ID}" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
{titles}
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
{SUBMENUS}
</node>"""
if toolbar:
node_toolbars = '\n'.join(toolbar)
NODE_TOOLBAR = f""" <node oor:name="OfficeToolBar">
<node oor:name="{ID}" oor:op="replace">
{node_toolbars}
</node>
</node>"""
FILE_ADDONS = f"""<?xml version='1.0' encoding='UTF-8'?>
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Addons" oor:package="org.openoffice.Office">
<node oor:name="AddonUI">
<node oor:name="{PARENT}">
{NODE_MENUS}
</node>
{NODE_TOOLBAR}
</node>
</oor:component-data>
"""
FILE_UPDATE = ''
if URL_XML_UPDATE:
FILE_UPDATE = f"""<?xml version="1.0" encoding="UTF-8"?>
<description
xmlns="http://openoffice.org/extensions/update/2006"
xmlns:d="http://openoffice.org/extensions/description/2006"
xmlns:xlink="http://www.w3.org/1999/xlink">
<identifier value="{ID}" />
<version value="{VERSION}" />
<update-download>
<src xlink:href="{URL_OXT}"/>
</update-download>
<release-notes>
</release-notes>
</description>"""
def _functions():
a = '[in] any {}'
t = ' any {}({});'
@ -679,72 +493,42 @@ FILE_ADDIN = f"""<?xml version="1.0" encoding="UTF-8"?>
</oor:component-data>"""
NODE_SHORTCUT = """ {0}<node oor:name="{1}" oor:op="fuse">
{0}<prop oor:name="Command">
{0}<value xml:lang="en-US">service:{2}?{3}</value>
{0}</prop>
{0}</node>
"""
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 = ' <node oor:name="Global">\n'
NODE_SHORTCUTS += '\n'.join(node_global)
NODE_SHORTCUTS += ' </node>'
if node_module:
NODE_SHORTCUTS += ' <node oor:name="Modules">\n'
for c, n in node_module.items():
NODE_SHORTCUTS += ' <node oor:name="{}">\n'.format(CONTEXT[c])
NODE_SHORTCUTS += '\n'.join(n)
NODE_SHORTCUTS += ' </node>\n'
NODE_SHORTCUTS += ' </node>'
FILE_SHORTCUTS = f"""<?xml version="1.0" encoding="UTF-8"?>
<oor:component-data
xmlns:oor="http://openoffice.org/2001/registry"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
oor:name="Accelerators"
oor:package="org.openoffice.Office">
<node oor:name="PrimaryKeys">
{NODE_SHORTCUTS}
</node>
</oor:component-data>
"""
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

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<description
xmlns="http://openoffice.org/extensions/update/2006"
xmlns:d="http://openoffice.org/extensions/description/2006"
xmlns:xlink="http://www.w3.org/1999/xlink">
<identifier value="net.elmau.zaz.BarCode" />
<version value="0.6.0" />
<update-download>
<src xlink:href="https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/ZAZBarCode_v0.6.0.oxt"/>
</update-download>
<release-notes>
</release-notes>
</description>
<?xml version="1.0" encoding="utf-8"?>
<description xmlns="http://openoffice.org/extensions/update/2006" xmlns:d="http://openoffice.org/extensions/description/2006" xmlns:xlink="http://www.w3.org/1999/xlink">
<identifier value="net.elmau.zaz.BarCode"/>
<version value="0.7.0"/>
<update-download>
<src xlink:href="https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/ZAZBarCode_v0.7.0.oxt"/>
</update-download>
<release-notes/>
</description>

View File

@ -1,325 +1,324 @@
<?xml version='1.0' encoding='UTF-8'?>
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" oor:name="Addons" oor:package="org.openoffice.Office">
<node oor:name="AddonUI">
<?xml version="1.0" encoding="utf-8"?>
<oor:component-data xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:oor="http://openoffice.org/2001/registry" oor:name="Addons" oor:package="org.openoffice.Office">
<node oor:name="AddonUI">
<node oor:name="OfficeMenuBar">
<node oor:name="net.elmau.zaz.BarCode" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">ZAZ BarCode</value>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">ZAZ BarCode</value>
<value xml:lang="es">ZAZ BarCode</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<node oor:name="Submenu">
<node oor:name="m0" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert BarCode</value>
<value xml:lang="es">Insertar Código</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument,com.sun.star.presentation.PresentationDocument,com.sun.star.drawing.DrawingDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?used_dialog</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<node oor:name="Submenu">
<node oor:name="net.elmau.zaz.BarCode.101" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert BarCode</value>
<value xml:lang="es">Insertar Código</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?ask</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument,com.sun.star.presentation.PresentationDocument,com.sun.star.drawing.DrawingDocument</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.102" oor:op="replace">
<node oor:name="m1" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert CODE39</value>
<value xml:lang="es">Insertar CODE39</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?code39</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert CODE39</value>
<value xml:lang="es">Insertar CODE39</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?code39</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.103" oor:op="replace">
<node oor:name="m2" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert CODE128</value>
<value xml:lang="es">Insertar CODE128</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?code128</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert CODE128</value>
<value xml:lang="es">Insertar CODE128</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?code128</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.104" oor:op="replace">
<node oor:name="m3" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert EAN</value>
<value xml:lang="es">Insertar EAN</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?ean</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert EAN</value>
<value xml:lang="es">Insertar EAN</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?ean</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.105" oor:op="replace">
<node oor:name="m4" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert EAN8</value>
<value xml:lang="es">Insertar EAN8</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?ean8</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert EAN8</value>
<value xml:lang="es">Insertar EAN8</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?ean8</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.106" oor:op="replace">
<node oor:name="m5" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert EAN13</value>
<value xml:lang="es">Insertar EAN13</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?ean13</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert EAN13</value>
<value xml:lang="es">Insertar EAN13</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?ean13</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.107" oor:op="replace">
<node oor:name="m6" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert GS1</value>
<value xml:lang="es">Insertar GS1</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?gs1</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert GS1</value>
<value xml:lang="es">Insertar GS1</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?gs1</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.108" oor:op="replace">
<node oor:name="m7" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert GTIN</value>
<value xml:lang="es">Insertar GTIN</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?gtin</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert GTIN</value>
<value xml:lang="es">Insertar GTIN</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?gtin</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.109" oor:op="replace">
<node oor:name="m8" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert ISBN</value>
<value xml:lang="es">Insertar ISBN</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?isbn</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert ISBN</value>
<value xml:lang="es">Insertar ISBN</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?isbn</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.110" oor:op="replace">
<node oor:name="m9" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert ISBN10</value>
<value xml:lang="es">Insertar ISBN10</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?isbn10</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert ISBN10</value>
<value xml:lang="es">Insertar ISBN10</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?isbn10</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.111" oor:op="replace">
<node oor:name="m10" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert ISBN13</value>
<value xml:lang="es">Insertar ISBN13</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?isbn13</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert ISBN13</value>
<value xml:lang="es">Insertar ISBN13</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?isbn13</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.112" oor:op="replace">
<node oor:name="m11" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert ISSN</value>
<value xml:lang="es">Insertar ISSN</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?issn</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert ISSN</value>
<value xml:lang="es">Insertar ISSN</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?issn</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.113" oor:op="replace">
<node oor:name="m12" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert JAN</value>
<value xml:lang="es">Insertar JAN</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?jan</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert JAN</value>
<value xml:lang="es">Insertar JAN</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?jan</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.114" oor:op="replace">
<node oor:name="m13" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert PZN</value>
<value xml:lang="es">Insertar PZN</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?pzn</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert PZN</value>
<value xml:lang="es">Insertar PZN</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?pzn</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.115" oor:op="replace">
<node oor:name="m14" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert UPC</value>
<value xml:lang="es">Insertar UPC</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?upc</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert UPC</value>
<value xml:lang="es">Insertar UPC</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?upc</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.116" oor:op="replace">
<node oor:name="m15" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert UPCA</value>
<value xml:lang="es">Insertar UPCA</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?upca</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert UPCA</value>
<value xml:lang="es">Insertar UPCA</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?upca</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
<node oor:name="net.elmau.zaz.BarCode.117" oor:op="replace">
<node oor:name="m16" oor:op="replace">
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Insert QRCODE</value>
<value xml:lang="es">Insertar QRCODE</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?qrcode</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
<value xml:lang="en">Insert QRCODE</value>
<value xml:lang="es">Insertar QRCODE</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
<value>com.sun.star.sheet.SpreadsheetDocument,com.sun.star.text.TextDocument</value>
</prop>
<prop oor:name="URL" oor:type="xs:string">
<value>service:net.elmau.zaz.BarCode?qrcode</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="ImageIdentifier" oor:type="xs:string">
<value>%origin%/images/barcode</value>
<value>%origin%/images/barcode</value>
</prop>
</node>
</node>
</node>
</node>
</node>
</node>
</node>
</oor:component-data>

View File

@ -1,36 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<oor:component-data
xmlns:oor="http://openoffice.org/2001/registry"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
oor:name="Accelerators"
oor:package="org.openoffice.Office">
<?xml version="1.0" encoding="utf-8"?>
<oor:component-data xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:oor="http://openoffice.org/2001/registry" oor:name="Accelerators" oor:package="org.openoffice.Office">
<node oor:name="PrimaryKeys">
<node oor:name="Modules">
<node oor:name="com.sun.star.sheet.SpreadsheetDocument">
<node oor:name="I_SHIFT_MOD1_MOD2" oor:op="fuse">
<prop oor:name="Command">
<value xml:lang="en-US">service:net.elmau.zaz.BarCode?ask</value>
<value xml:lang="en-US">service:net.elmau.zaz.BarCode?used_dialog</value>
</prop>
</node>
</node>
<node oor:name="com.sun.star.text.TextDocument">
<node oor:name="I_SHIFT_MOD1_MOD2" oor:op="fuse">
<prop oor:name="Command">
<value xml:lang="en-US">service:net.elmau.zaz.BarCode?ask</value>
<value xml:lang="en-US">service:net.elmau.zaz.BarCode?used_dialog</value>
</prop>
</node>
</node>
<node oor:name="com.sun.star.presentation.PresentationDocument">
<node oor:name="I_SHIFT_MOD1_MOD2" oor:op="fuse">
<prop oor:name="Command">
<value xml:lang="en-US">service:net.elmau.zaz.BarCode?ask</value>
<value xml:lang="en-US">service:net.elmau.zaz.BarCode?used_dialog</value>
</prop>
</node>
</node>
<node oor:name="com.sun.star.drawing.DrawingDocument">
<node oor:name="I_SHIFT_MOD1_MOD2" oor:op="fuse">
<prop oor:name="Command">
<value xml:lang="en-US">service:net.elmau.zaz.BarCode?ask</value>
<value xml:lang="en-US">service:net.elmau.zaz.BarCode?used_dialog</value>
</prop>
</node>
</node>

View File

@ -2,55 +2,17 @@ import gettext
import uno
import unohelper
from com.sun.star.task import XJobExecutor, XJob
import easymacro as app
import qrcode
import qrcode.image.svg as svg
from barcode import generate
import main
ID_EXTENSION = 'net.elmau.zaz.BarCode'
SERVICE = ('com.sun.star.task.Job',)
TITLE = 'ZAZ BarCode'
QR = 'qrcode'
_ = app.install_locales(__file__)
class Controllers(object):
def __init__(self, dlg):
self.d = dlg
def listbox_item_changed(self, event):
self.d.text.set_focus()
return
def button_action(self, event):
if not self.d.listbox.value:
self.d.listbox.set_focus()
msg = _('Select barcode type')
app.warning(msg, TITLE)
return
if not self.d.text.value.strip():
self.d.text.set_focus()
msg = _('Data field is mandatory')
app.warning(msg, TITLE)
return
self.d.close(1)
return
class ZAZBarCode(unohelper.Base, XJob, XJobExecutor):
def __init__(self, ctx):
self.ctx = ctx
self._data = ''
self._type = ''
self._ask = False
self._path = ''
def execute(self, args):
data = app.property_to_dict(args)
@ -72,178 +34,10 @@ class ZAZBarCode(unohelper.Base, XJob, XJobExecutor):
return self._path
def trigger(self, args):
self._type = args
if args == 'ask' and not self._get_values():
return
doc = app.get_document()
getattr(self, '_insert_in_{}'.format(doc.type))(doc)
app.kill(self._path)
main.ID_EXTENSION = ID_EXTENSION
main.run(args, __file__)
return
def _create_code(self, path=''):
if not path:
path = app.get_temp_file(True)
if self._type == QR:
factory = svg.SvgImage
img = qrcode.make(self._data, border=2, image_factory=factory)
img.save(path)
else:
try:
path = generate(self._type, self._data, output=path)
except Exception as e:
app.error(e)
return str(e)
if app.is_created(path):
self._path = path
return ''
return _('Not generated')
def _get_values(self):
self._type = ''
dlg = self._create_dialog()
if dlg.open():
self._data = dlg.text.value.strip()
self._type = dlg.listbox.value
self._ask = True
return True
return False
def _insert_in_calc(self, doc):
cell = doc.get_cell()
if not self._data:
self._data = cell.value
if not self._data:
msg = _('Select data')
self._show_error(msg)
return
result = self._create_code()
if result:
self._show_error(result)
return
if not self._ask:
cell = cell.offset(0, 1)
cell.insert_image(self._path)
return
def _insert_in_writer(self, doc):
doc = app.get_document()
if not self._data:
sel = app.get_selection()
self._data = sel.string
if not self._data:
msg = _('Select data')
self._show_error(msg)
return
result = self._create_code()
if result:
self._show_error(result)
return
doc.insert_image(self._path)
return
def _insert_in_draw(self, doc):
result = self._create_code()
if result:
self._show_error(result)
return
doc.insert_image(self._path)
return
def _insert_in_impress(self, doc):
self._insert_in_draw(doc)
return
def _show_error(self, error):
msg = _('Error in: {}\n\n{}').format(self._type, error)
app.error(error)
app.errorbox(msg, TITLE)
return
def _create_dialog(self):
args = {
'Name': 'dialog',
'Title': TITLE,
'Width': 160,
'Height': 160,
}
dlg = app.create_dialog(args)
dlg.events = Controllers(dlg)
dlg.id_extension = ID_EXTENSION
args = {
'Type': 'Label',
'Name': 'lbl_barcode',
'Label': _('~Select barcode type'),
'Width': 70,
'Height': 15,
'X': 10,
'Y': 10,
'VerticalAlign': 1,
}
dlg.add_control(args)
args = {
'Type': 'Label',
'Name': 'lbl_data',
'Label': _('~Capture data for barcode'),
'Width': 100,
'Height': 15,
'VerticalAlign': 1,
}
dlg.add_control(args)
args = {
'Type': 'ListBox',
'Name': 'listbox',
'Width': 65,
'Height': 15,
'Dropdown': True,
}
dlg.add_control(args)
data = ('code39', 'code128', 'ean', 'ean8', 'ean13', 'gs1', 'gtin',
'isbn', 'isbn10', 'isbn13', 'issn', 'jan', 'pzn', 'upc', 'upca',
'qrcode')
dlg.listbox.data = data
args = {
'Type': 'Text',
'Name': 'text',
'Width': 140,
'Height': 75,
'MultiLine': True,
'VScroll': True,
}
dlg.add_control(args)
args = {
'Type': 'Button',
'Name': 'button',
'Label': _('~Insert Barcode'),
'Width': 70,
'Height': 15,
'ImageURL': 'qr.png',
'ImagePosition': 1,
}
dlg.add_control(args)
dlg.listbox.move(dlg.lbl_barcode, 5, 0)
dlg.lbl_data.move(dlg.lbl_barcode)
dlg.text.move(dlg.lbl_data)
dlg.button.move(dlg.text, 0, 10)
dlg.button.center()
return dlg
g_ImplementationHelper = unohelper.ImplementationHelper()
g_ImplementationHelper.addImplementation(ZAZBarCode, ID_EXTENSION, SERVICE)

View File

@ -1,29 +1,29 @@
<?xml version='1.0' encoding='UTF-8'?>
<?xml version="1.0" encoding="utf-8"?>
<description xmlns="http://openoffice.org/extensions/description/2006" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:d="http://openoffice.org/extensions/description/2006">
<identifier value="net.elmau.zaz.BarCode" />
<version value="0.6.0" />
<identifier value="net.elmau.zaz.BarCode"/>
<version value="0.7.0"/>
<display-name>
<name lang="en">ZAZ Bar Code</name>
<name lang="es">ZAZ Códigos de Barras</name>
</display-name>
<extension-description>
<src lang="en" xlink:href="description/desc_en.txt" />
<src lang="es" xlink:href="description/desc_es.txt" />
<src lang="en" xlink:href="description/desc_en.txt"/>
<src lang="es" xlink:href="description/desc_es.txt"/>
</extension-description>
<icon>
<default xlink:href="images/zazbarcode.png" />
<default xlink:href="images/zazbarcode.png"/>
</icon>
<publisher>
<name xlink:href="https://gitlab.com/mauriciobaeza" lang="en">El Mau</name>
<name xlink:href="https://gitlab.com/mauriciobaeza" lang="es">El Mau</name>
</publisher>
<registration>
<simple-license accept-by="user" suppress-on-update="true" >
<license-text xlink:href="registration/license_en.txt" lang="en" />
<license-text xlink:href="registration/license_es.txt" lang="es" />
<simple-license accept-by="user" suppress-on-update="true">
<license-text xlink:href="registration/license_en.txt" lang="en"/>
<license-text xlink:href="registration/license_es.txt" lang="es"/>
</simple-license>
</registration>
<update-information>
<src xlink:href="https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/zazbarcode.update.xml" />
</update-information>
<update-information>
<src xlink:href="https://gitlab.com/mauriciobaeza/zaz-barcode/raw/master/files/zazbarcode.update.xml"/>
</update-information>
</description>

123
source/pythonpath/barcode/__init__.py Normal file → Executable file
View File

@ -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

51
source/pythonpath/barcode/base.py Normal file → Executable file
View File

@ -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)

View File

@ -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"]}

View File

@ -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)))

View File

@ -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",
)

View File

@ -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",
)

View File

@ -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",
),
}

147
source/pythonpath/barcode/codex.py Normal file → Executable file
View File

@ -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

95
source/pythonpath/barcode/ean.py Normal file → Executable file
View File

@ -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])

9
source/pythonpath/barcode/errors.py Normal file → Executable file
View File

@ -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):

73
source/pythonpath/barcode/isxn.py Normal file → Executable file
View File

@ -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

View File

@ -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)

View File

@ -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()

86
source/pythonpath/barcode/upc.py Normal file → Executable file
View File

@ -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

View File

@ -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'

232
source/pythonpath/barcode/writer.py Normal file → Executable file
View File

@ -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)

File diff suppressed because it is too large Load Diff

174
source/pythonpath/main.py Normal file
View File

@ -0,0 +1,174 @@
#!/usr/bin/env python3
import easymacro as app
import qrcode
import qrcode.image.svg as svg
from barcode import generate
ID_EXTENSION = ''
_ = None
TITLE = 'ZAZ BarCode'
QR = 'qrcode'
class Controllers(object):
def __init__(self, dlg):
self.d = dlg
def listbox_item_changed(self, event):
self.d.text.set_focus()
return
def button_action(self, event):
if not self.d.listbox.value:
self.d.listbox.set_focus()
msg = _('Select barcode type')
app.warning(msg, TITLE)
return
if not self.d.text.value.strip():
self.d.text.set_focus()
msg = _('Data field is mandatory')
app.warning(msg, TITLE)
return
self.d.close(1)
return
@app.catch_exception
def _use_dialog():
dlg = _create_dialog()
if not dlg.open():
return
data = dlg.text.value.strip()
type_code = dlg.listbox.value
path = _make_code(type_code, data)
app.selection.insert_image(path)
app.paths.kill(path)
return
def _make_code(type_code, data):
path = app.paths.tmp()
if type_code == QR:
factory = svg.SvgImage
img = qrcode.make(data, border=2, image_factory=factory)
img.save(path)
else:
try:
generate(type_code, data, output=open(path, 'wb'))
except Exception as e:
app.errorbox(e)
return ''
return path
def _create_dialog():
args = {
'Name': 'dialog',
'Title': TITLE,
'Width': 160,
'Height': 160,
}
dlg = app.create_dialog(args)
dlg.id = ID_EXTENSION
dlg.events = Controllers
args = {
'Type': 'Label',
'Name': 'lbl_barcode',
'Label': _('~Select barcode type'),
'Width': 70,
'Height': 15,
'X': 10,
'Y': 10,
'VerticalAlign': 1,
}
dlg.add_control(args)
args = {
'Type': 'Label',
'Name': 'lbl_data',
'Label': _('~Capture data for barcode'),
'Width': 100,
'Height': 15,
'VerticalAlign': 1,
}
dlg.add_control(args)
args = {
'Type': 'ListBox',
'Name': 'listbox',
'Width': 65,
'Height': 15,
'Dropdown': True,
}
dlg.add_control(args)
data = ('code39', 'code128', 'ean', 'ean8', 'ean13', 'gs1', 'gtin',
'isbn', 'isbn10', 'isbn13', 'issn', 'jan', 'pzn', 'upc', 'upca',
'qrcode')
dlg.listbox.data = data
args = {
'Type': 'Text',
'Name': 'text',
'Width': 140,
'Height': 75,
'MultiLine': True,
'VScroll': True,
}
dlg.add_control(args)
args = {
'Type': 'Button',
'Name': 'button',
'Label': _('~Insert Barcode'),
'Width': 70,
'Height': 15,
'ImageURL': 'qr.png',
'ImagePosition': 1,
}
dlg.add_control(args)
dlg.listbox.move(dlg.lbl_barcode, 5, 0)
dlg.lbl_data.move(dlg.lbl_barcode)
dlg.text.move(dlg.lbl_data)
dlg.button.move(dlg.text, 0, 10)
dlg.button.center()
return dlg
@app.catch_exception
def _insert_code(type_code):
sel = app.selection
data = sel.value
if not data:
msg = _('Select data')
app.errorbox(msg)
return
path = _make_code(type_code, data)
sel.offset().insert_image(path)
app.paths.kill(path)
return
def run(args, path_locales):
global _
_ = app.install_locales(path_locales)
if args == 'used_dialog':
_use_dialog()
else:
_insert_code(args)
return

View File

@ -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

View File

@ -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)

370
zaz.py Normal file → Executable file
View File

@ -4,6 +4,8 @@
# ~ This file is part of ZAZ.
# ~ https://git.elmau.net/elmau/zaz
# ~ ZAZ is free software: you can redistribute it and/or modify
# ~ it under the terms of the GNU General Public License as published by
# ~ the Free Software Foundation, either version 3 of the License, or
@ -19,6 +21,7 @@
import argparse
import os
import py_compile
import re
import sys
import zipfile
@ -43,9 +46,22 @@ from conf import (
log)
EASYMACRO = 'easymacro.py'
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 +69,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 +118,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 +148,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 +398,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 +412,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 +529,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():
@ -315,7 +554,7 @@ def _update_files():
copyfile(source, target)
if FILES['easymacro']:
source = 'easymacro.py'
source = EASYMACRO
target = _join(path_source, 'pythonpath', source)
copyfile(source, target)
@ -325,16 +564,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,16 +586,21 @@ 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
def _new():
def _create():
if not _validate_new():
return
@ -373,7 +622,7 @@ def _get_info_path(path):
def _zip_embed(source, files):
PATH = 'Scripts/python/'
EASYMACRO = 'easymacro.'
FILE_PYC = 'easymacro.pyc'
p, f, name, e = _get_info_path(source)
now = datetime.now().strftime('_%Y%m%d_%H%M%S')
@ -381,12 +630,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 +652,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
@ -450,8 +697,6 @@ def _embed(args):
def _locales(args):
EASYMACRO = 'easymacro.py'
if args.files:
files = args.files.split(',')
else:
@ -483,8 +728,39 @@ def _update():
return
def _new(args):
if not args.target:
msg = 'Add argument target: -t PATH_TARGET'
log.error(msg)
return
if not args.name:
msg = 'Add argument name: -n name-new-extension'
log.error(msg)
return
path = _join(args.target, args.name)
_mkdir(path)
_mkdir(_join(path, 'files'))
_mkdir(_join(path, 'images'))
path_logo = 'images/pymacros.png'
copyfile(path_logo, _join(path, 'images/logo.png'))
copyfile('zaz.py', _join(path, 'zaz.py'))
copyfile(EASYMACRO, _join(path, 'easymacro.py'))
copyfile('conf.py.example', _join(path, 'conf.py'))
msg = 'Folders and files copy successfully for new extension.'
log.info(msg)
msg = f'Change to folder: {path}'
log.info(msg)
return
def main(args):
if args.new:
_new(args)
return
if args.update:
_update()
return
@ -497,14 +773,16 @@ def main(args):
_embed(args)
return
if args.new:
_new()
if args.create:
_create()
return
if not _validate_update():
return
_update_files()
if not args.only_compress:
_update_files()
_compress_oxt()
if args.install:
@ -517,9 +795,13 @@ def main(args):
def _process_command_line_arguments():
parser = argparse.ArgumentParser(
description='Make LibreOffice extensions')
parser.add_argument('-i', '--install', dest='install', action='store_true',
parser.add_argument('-new', '--new', dest='new', action='store_true',
default=False, required=False)
parser.add_argument('-n', '--new', dest='new', action='store_true',
parser.add_argument('-t', '--target', dest='target', default='')
parser.add_argument('-n', '--name', dest='name', default='', required=False)
parser.add_argument('-c', '--create', dest='create', action='store_true',
default=False, required=False)
parser.add_argument('-i', '--install', dest='install', action='store_true',
default=False, required=False)
parser.add_argument('-e', '--embed', dest='embed', action='store_true',
default=False, required=False)
@ -529,6 +811,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()