| |
| from __future__ import with_statement |
| import logging |
|
|
|
|
| logger = logging.getLogger(__name__) |
|
|
|
|
| NS_URI = 'http://openoffice.org/extensions/description/2006' |
| NS_URI_DEP = 'http://openoffice.org/extensions/description/2006' |
| NS_URI_XLINK = 'http://www.w3.org/1999/xlink' |
|
|
| NS = '{' + NS_URI + '}' |
| NS_DEP = '{' + NS_URI_DEP + '}' |
| NS_XLINK = '{' + NS_URI_XLINK + '}' |
|
|
|
|
| def as_dict(f): |
| def wrapper(*args, **kwargs): |
| return dict(f(*args, **kwargs)) |
| wrapper.items = f |
| return wrapper |
|
|
|
|
| @as_dict |
| def get_display_name(doc): |
| root = doc.getroot() |
| for elt in root.findall(NS + 'display-name/' + NS + 'name'): |
| yield elt.get('lang'), elt.text |
|
|
|
|
| def set_display_name(doc, display_name): |
| import xml.etree.ElementTree as ET |
| root = doc.getroot() |
| dispname = ET.SubElement(root, 'display-name') |
| for lang, name in display_name.items(): |
| elt = ET.SubElement(dispname, 'name') |
| elt.set('lang', lang) |
| elt.text = name |
|
|
|
|
| @as_dict |
| def get_extension_description(doc): |
| root = doc.getroot() |
| for elt in root.findall(NS + 'extension-description/' + NS + 'src'): |
| yield elt.get('lang'), elt.get(NS_XLINK + 'href') |
|
|
|
|
| def set_extension_description(doc, description): |
| import xml.etree.ElementTree as ET |
| root = doc.getroot() |
| desc = ET.SubElement(root, 'extension-description') |
| for lang, url in description.items(): |
| elt = ET.SubElement(desc, 'src') |
| elt.set('lang', lang) |
| elt.set('xlink:href', url) |
|
|
|
|
| @as_dict |
| def get_publisher(doc): |
| root = doc.getroot() |
| for elt in root.findall(NS + 'publisher/' + NS + 'name'): |
| yield elt.get('lang'), dict(name=elt.text, |
| url=elt.get(NS_XLINK + 'href')) |
|
|
|
|
| def set_publisher(doc, publisher): |
| import xml.etree.ElementTree as ET |
| root = doc.getroot() |
| pub = ET.SubElement(root, 'publisher') |
| for lang, dct in publisher.items(): |
| elt = ET.SubElement(pub, 'name') |
| elt.set('lang', lang) |
| elt.set('xlink:href', dct['url']) |
| elt.text = dct['name'] |
|
|
|
|
| def get_license_accept_by(doc): |
| root = doc.getroot() |
| for elt in root.findall(NS + 'registration/' + NS + 'simple-license'): |
| accept_by = elt.get('accept-by') |
| if accept_by: |
| return accept_by |
|
|
|
|
| def get_license(doc): |
| root = doc.getroot() |
| for elt in root.findall(NS + 'registration/' + NS + 'simple-license'): |
| return dict((elt.get('lang'), elt.get(NS_XLINK + 'href')) |
| for elt in elt.findall(NS + 'license-text')) |
| return dict() |
|
|
|
|
| def get_oo_min_version(doc): |
| root = doc.getroot() |
| for dep in root.findall(NS + 'dependencies'): |
| for elt in dep.findall(NS + 'OpenOffice.org-minimal-version'): |
| return elt.get('value') |
|
|
|
|
| class Description(object): |
|
|
| @classmethod |
| def parse(cls, f): |
| import xml.etree.ElementTree as ET |
|
|
| doc = ET.parse(f) |
| root = doc.getroot() |
|
|
| def getvalue(xpath, default=None): |
| for elt in root.findall(xpath): |
| value = elt.get('value', default) |
| if value: |
| return value |
| return default |
|
|
| return cls(identifier=getvalue(NS + 'identifier'), |
| version=getvalue(NS + 'version'), |
| platform=getvalue(NS + 'platform', 'all'), |
| display_name=get_display_name(doc), |
| description=get_extension_description(doc), |
| publisher=get_publisher(doc), |
| license_accept_by=get_license_accept_by(doc), |
| license=get_license(doc), |
| oo_min_version=get_oo_min_version(doc)) |
|
|
| def __init__(self, |
| identifier='noname', |
| version='0.0', |
| platform='all', |
| display_name=dict(), |
| description=dict(), |
| publisher=dict(), |
| license_accept_by='admin', |
| license=dict(), |
| oo_min_version=None): |
| ''' Generate description.xml |
| |
| :param f: output file |
| :param identifier: extension identifier |
| :param version: extension version |
| :param platform: target platform |
| :param display_name: localizations of display name |
| :param description: localizations of extension description |
| :param publisher: localizations of publisher |
| :param license_accept_by: who is supposed to accept the license |
| :param license: localization of license |
| :param oo_min_version: minimal version of LibreOffice |
| |
| Each localization parameters are dicts, whose keys are language identifiers |
| defined in RFC 3066. |
| |
| ``identifier`` specifies `Extension Identifier |
| <http://wiki.openoffice.org/wiki/Documentation/DevGuide/Extensions/Extension_Identifiers>`_. |
| |
| ``version`` specifies `Extension Version |
| <http://wiki.openoffice.org/wiki/Documentation/DevGuide/Extensions/Extension_Versions>`_. |
| |
| ``platform`` specifies supposed `Target Platform |
| <http://wiki.openoffice.org/wiki/Documentation/DevGuide/Extensions/Target_Platform>`_ on which this extension |
| runs. Default value is ``all``. |
| |
| ``display_name`` specifies localized `Display Names |
| <http://wiki.openoffice.org/wiki/Documentation/DevGuide/Extensions/Display_Name>`_. |
| It's a localization dict whose values are localized unicode strings, e.g.:: |
| |
| display_name = { |
| 'en': 'Example Filter', |
| 'ko': u'예제 필터' |
| } |
| |
| Values of ``description`` is a URL of description file, e.g.:: |
| |
| description = { |
| 'en': 'description/en.txt', |
| 'ko': 'description/ko.txt' |
| } |
| |
| ``publisher`` specifies `Publisher Information |
| <http://wiki.openoffice.org/wiki/Documentation/DevGuide/Extensions/Publisher_Information>`_. |
| It's a localization dict whose values are dicts themselves, which have |
| ``name`` and ``url``. ``name`` is a localized name of the publisher and |
| ``url`` is a URL of the publisher. For example:: |
| |
| publisher = { |
| 'en': { |
| 'name': 'John Doe', |
| 'url': 'http://example.tld' |
| }, |
| 'ko': { |
| 'name': u'홍길동', |
| 'url': 'http://example.tld' |
| } |
| } |
| |
| Optional ``license_accept_by`` specifies who is supposed to accept the |
| license. ``admin`` or ``user``. Default value is 'admin'. |
| |
| Optional ``license`` is a localization dict whose values are an URL of |
| license file. For example:: |
| |
| license = { |
| 'en': 'registration/COPYING' |
| } |
| |
| See `Simple License |
| <http://wiki.openoffice.org/wiki/Documentation/DevGuide/Extensions/Simple_License>`_. |
| ''' |
| self.identifier = identifier |
| self.version = version |
| self.platform = platform |
| self.display_name = display_name |
| self.description = description |
| self.publisher = publisher |
| self.license_accept_by = license_accept_by |
| self.license = license |
| self.oo_min_version = oo_min_version |
|
|
| def write(self, f): |
|
|
| |
|
|
| import xml.etree.ElementTree as ET |
|
|
| root = ET.Element('description', {'xmlns': NS_URI, |
| 'xmlns:dep': NS_URI_DEP, |
| 'xmlns:xlink': NS_URI_XLINK}) |
| doc = ET.ElementTree(root) |
|
|
| ET.SubElement(root, 'identifier').set('value', self.identifier) |
| ET.SubElement(root, 'version').set('value', self.version) |
| ET.SubElement(root, 'platform').set('value', self.platform) |
|
|
| set_display_name(doc, self.display_name) |
|
|
| set_extension_description(doc, self.description) |
|
|
| set_publisher(doc, self.publisher) |
|
|
| if self.license: |
| reg = ET.SubElement(root, 'registration') |
| lic = ET.SubElement(reg, 'simple-license') |
| lic.set('accept-by', self.license_accept_by) |
| for lang, url in self.license.items(): |
| elt = ET.SubElement(lic, 'license-text') |
| elt.set('lang', lang) |
| elt.set('xlink:href', url) |
|
|
| if self.oo_min_version is not None: |
| dep = ET.SubElement(root, 'dependencies') |
| minver = ET.SubElement(dep, 'OpenOffice.org-minimal-version') |
| minver.set('dep:name', 'LibreOffice ' + self.oo_min_version) |
| minver.set('value', self.oo_min_version) |
|
|
| f.write('<?xml version="1.0" encoding="utf-8"?>') |
| doc.write(f, encoding='utf-8') |
|
|
| def required_files(self): |
| for url in self.description.values(): |
| yield url |
| for url in self.license.values(): |
| yield url |
|
|
|
|
| def print_human_readable(desc, root_stg=None): |
| ''' Print summary in human readable form. |
| |
| :param desc: an instance of Description |
| :param root_stg: root storage of description.xml |
| ''' |
| from storage import resolve_path |
| print 'identifier:', desc.identifier |
| print 'version:', desc.version |
| print 'platform:', desc.platform |
|
|
| print 'display-name:' |
| for lang, name in desc.display_name.items(): |
| print ' [%s] %s' % (lang, name) |
|
|
| print 'extension-description:' |
| for lang, url in desc.description.items(): |
| if not root_stg or resolve_path(root_stg, url): |
| state = '' |
| else: |
| state = ' -- MISSING' |
| print ' [%s] %s%s' % (lang, url, state) |
|
|
| print 'publisher:' |
| for lang, publisher in desc.publisher.items(): |
| print ' [%s] %s (%s)' % (lang, |
| publisher['name'], |
| publisher['url']) |
| if desc.license: |
| print 'license: accept-by', desc.license_accept_by |
| for lang, url in desc.license.items(): |
| if not root_stg or resolve_path(root_stg, url): |
| state = '' |
| else: |
| state = ' -- MISSING' |
| print ' [%s] %s%s' % (lang, url, state) |
|
|
| if desc.oo_min_version: |
| print 'dependencies:' |
| print ' LibreOffice minimal version:', desc.oo_min_version |
|
|
|
|
| def init_main(): |
| doc = '''Usage: oxt-desc-init [options] <desc-file> |
| |
| --help Print this screen. |
| ''' |
|
|
| from docopt import docopt |
| args = docopt(doc) |
| logging.basicConfig(level=logging.INFO) |
|
|
| description = Description(identifier='tld.example', |
| version='0.1', |
| display_name=dict(en='Example extension'), |
| publisher=dict(en=dict(name='Publisher Name', |
| url='http://example.tld')), |
| license=dict(url=dict(en='COPYING')), |
| description=dict(en='description/en.txt')) |
| with file(args['<desc-file>'], 'w') as f: |
| description.write(f) |
|
|
|
|
| def show_main(): |
| doc = '''Usage: oxt-desc-show [options] <desc-file> |
| |
| --help Show this screen. |
| ''' |
| from docopt import docopt |
| args = docopt(doc) |
| logging.basicConfig(level=logging.INFO) |
|
|
| with file(args['<desc-file>']) as f: |
| desc = Description.parse(f) |
|
|
| print_human_readable(desc) |
|
|
|
|
| def version_main(): |
| doc = '''Usage: oxt-desc-version [options] <desc-file> [<new-version>] |
| |
| --help Show this screen. |
| ''' |
| from docopt import docopt |
| args = docopt(doc) |
| logging.basicConfig(level=logging.INFO) |
|
|
| with file(args['<desc-file>'], 'r') as f: |
| desc = Description.parse(f) |
|
|
| new_version = args['<new-version>'] |
| if new_version is not None: |
| logger.info('old: %s', desc.version) |
| desc.version = new_version |
| logger.info('new: %s', desc.version) |
| with file(args['<desc-file>'], 'w') as f: |
| desc.write(f) |
| else: |
| print desc.version |
|
|
|
|
| def ls_main(): |
| doc = '''Usage: oxt-desc-ls [options] <desc-file> |
| |
| --help Show this screen. |
| ''' |
| from docopt import docopt |
| args = docopt(doc) |
| logging.basicConfig(level=logging.INFO) |
|
|
| with file(args['<desc-file>']) as f: |
| desc = Description.parse(f) |
|
|
| for path in desc.required_files(): |
| print path |
|
|