Skip to content

Commit

Permalink
Merge branch 'release/0.1.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
lb803 committed Feb 3, 2021
2 parents 4411858 + fa4b2ed commit 70c7147
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 103 deletions.
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

class AccessAidePlugin(EditBookToolPlugin):
name = 'Access Aide'
version = (0, 1, 2)
version = (0, 1, 3)
author = 'Luca Baffa'
supported_platforms = ['windows', 'osx', 'linux']
description = 'Access Aide plugin for Calibre'
Expand Down
1 change: 1 addition & 0 deletions lib/stats.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/python3


class Stats:
'''
Simple class to manage stats.
Expand Down
167 changes: 65 additions & 102 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@
# My modules
from lib.stats import Stats


class AccessAide(Tool):
name = 'access-aide'
allowed_in_toolbar = True
allowed_in_menu = True

def __init__(self):

# init stat counters
self.lang_tag = Stats()
self.aria_match = Stats()
self.meta_decl = Stats()
self.lang_stat = Stats() # language tags
self.aria_stat = Stats() # aria roles matches
self.meta_stat = Stats() # metadata declarations

def create_action(self, for_toolbar=True):
ac = QAction(get_icons('icon/icon.png'), 'Access Aide', self.gui)
Expand All @@ -46,7 +48,13 @@ def main(self):
'Need to have a book open first', show=True)

# get book main language
lang = self.get_lang(container)
try:
lang = container.opf_xpath('//dc:language/text()')[0]
except IndexError:
error_dialog(self.gui, 'Access Aide',
'The OPF file does not report language info.',
show=True)
raise

self.add_metadata(container)

Expand All @@ -55,45 +63,19 @@ def main(self):
# iterate over book files
for name, media_type in container.mime_map.items():

if media_type in OEB_DOCS and \
name not in blacklist:
if media_type in OEB_DOCS \
and name not in blacklist:

self.add_lang(container.parsed(name), lang)
self.add_aria(container.parsed(name))

container.dirty(name)

self.display_info()

self.lang_tag.reset()
self.aria_match.reset()
self.meta_decl.reset()

def load_json(self, path):
'''Load a JSON file.
This method loads a json file stored inside the plugin
given its relative path. The method returns a python object.
'''

return json.loads(get_resources(path))

def get_lang(self, container):
'''Retrieve book main language.
This method parses the OPF file, gets a list of the declared
languages and returns the first one (which we trust to be the
main language of the book).
'''

languages = container.opf_xpath('//dc:language/text()')
info_dialog(self.gui, 'Access Aide', self.stats_report(), show=True)

if not languages:
return error_dialog(self.gui, 'Access Aide',
'The OPF file does not report language info.',
show=True)

return languages[0]
self.lang_stat.reset()
self.aria_stat.reset()
self.meta_stat.reset()

def add_lang(self, root, lang):
'''Add language attributes to <html> tags.
Expand All @@ -106,15 +88,11 @@ def add_lang(self, root, lang):
html = root.xpath('//*[local-name()="html"]')[0]

# set lang for 'lang' attribute
if self.write_attrib(html, 'lang', lang):

self.lang_tag.increase()
self.write_attrib(html, 'lang', lang, self.lang_stat)

# set lang for 'xml:lang' attribute
if self.write_attrib(html,
'{http://www.w3.org/XML/1998/namespace}lang', lang):

self.lang_tag.increase()
self.write_attrib(html, '{http://www.w3.org/XML/1998/namespace}lang',
lang, self.lang_stat)

def add_aria(self, root):
'''Add aria roles.
Expand All @@ -127,67 +105,58 @@ def add_aria(self, root):
'''

# load maps
epubtype_aria_map = self.load_json('assets/epubtype-aria-map.json')
extra_tags = self.load_json('assets/extra-tags.json')
epubtype_aria_map = json.loads(
get_resources('assets/epubtype-aria-map.json'))
extra_tags = json.loads(get_resources('assets/extra-tags.json'))

# find nodes with an 'epub:type' attribute
nodes = root.xpath('//*[@epub:type]',
namespaces={'epub':'http://www.idpf.org/2007/ops'})
namespaces={'epub': 'http://www.idpf.org/2007/ops'})

for node in nodes:

tag = lxml.etree.QName(node).localname
value = node.attrib['{http://www.idpf.org/2007/ops}type']

# get map for the 'value' key
map = epubtype_aria_map.get(value, None)

# skip if the epub type is not mapped
if map == None:

continue

# if the tag on 'node' is allowed
if tag in map['tag'] or tag in extra_tags:
# get map for the 'value' key (if present)
map = epubtype_aria_map.get(value, False)

if self.write_attrib(node, 'role', map['aria']):
if map and (tag in map['tag'] or tag in extra_tags):

self.aria_match.increase()
self.write_attrib(node, 'role', map['aria'], self.aria_stat)

def write_attrib(self, node, attribute, value):
def write_attrib(self, node, attribute, value, stat):
'''Write attributes to nodes.
A preliminary check is performed, in the spirit of keeping
changes to the original document to a minimum.
Attributes are written if config has 'force_override' set
or if node is not present.
'''

# skip if force_override is not set and attribute is already set
if prefs['force_override'] == False \
and attribute in node.attrib:
if prefs['force_override'] \
or attribute not in node.attrib:

return False
node.attrib[attribute] = value
stat.increase()

node.attrib[attribute] = value
return

return True
def stats_report(self):
'''Compose a short report on stats.
def display_info(self):
'''Display an info dialogue.
This method composes and shows an info dialogue to display at the end of
This method returns a string to display at the end of
runtime along with some statistics.
'''

message = ('<h3>Routine completed</h3>'
'<p>Language attributes added: {lang_tag}<br>'
'Aria roles added: {aria_match}<br>'
'Metadata declarations added: {meta_decl}</p>') \
.format(**{'lang_tag': self.lang_tag.get(),
'aria_match': self.aria_match.get(),
'meta_decl': self.meta_decl.get()})
template = ('<h3>Routine completed</h3>'
'<p>Language attributes added: {lang_stat}<br>'
'Aria roles added: {aria_stat}<br>'
'Metadata declarations added: {meta_stat}</p>')

data = {'lang_stat': self.lang_stat.get(),
'aria_stat': self.aria_stat.get(),
'meta_stat': self.meta_stat.get()}

info_dialog(self.gui, 'Access Aide',
message, show=True)
return template.format(**data)

def add_metadata(self, container):
''' Add metadata to OPF file.
Expand All @@ -208,38 +177,32 @@ def add_metadata(self, container):
if '3.' in container.opf_version:

# prevent overriding
if prefs['force_override'] == False \
and container.opf_xpath('//*[contains(@property, "{}")]'\
.format(value)):
if prefs['force_override'] \
or not container.opf_xpath(
'//*[contains(@property, "{}")]'.format(value)):

continue
element = lxml.etree.Element('meta')
element.set('property', ('schema:' + value))
element.text = text

element = lxml.etree.Element('meta')
element.set('property', ('schema:' + value))
element.text = text
container.insert_into_xml(metadata, element)

self.meta_decl.increase()
self.meta_stat.increase()

# if epub2
elif '2.' in container.opf_version:

# prevent overriding
if prefs['force_override'] == False \
and container.opf_xpath('//*[contains(@name, "{}")]' \
.format(value)):

continue

element = lxml.etree.Element('meta')
element.set('name', ('schema:' + value))
element.set('content', text)

self.meta_decl.increase()
if prefs['force_override'] \
or not container.opf_xpath(
'//*[contains(@name, "{}")]'.format(value)):

else:
element = lxml.etree.Element('meta')
element.set('name', ('schema:' + value))
element.set('content', text)

return
container.insert_into_xml(metadata, element)

container.insert_into_xml(metadata, element)
self.meta_stat.increase()

container.dirty(container.opf_name)

0 comments on commit 70c7147

Please sign in to comment.