from __future__ import print_function, unicode_literals
import os
from six import iteritems
from glob import glob
from datetime import datetime
from door43_tools.bible_books import BOOK_NAMES, BOOK_NUMBERS
from door43_tools.language_handler import Language
from general_tools.file_utils import load_json_object, get_files, get_subdirs
[docs]class Manifest(object):
LATEST_VERSION = 6
def __init__(self, file_name=None, meta=None, repo_name=None, files_path=None):
"""
Class constructor. Optionally accepts the name of a file to deserialize.
:param str file_name: The name of a file to deserialize into a Manifest object
"""
# Defaults
self.package_version = Manifest.LATEST_VERSION
self.format = ""
self.generator = {
"name": "",
"build": ""
}
self.target_language = {
"id": "",
"name": "",
"direction": "ltr"
}
self.project = {
"id": "",
"name": ""
}
self.type = {
"id": "text",
"name": "Text"
}
self.resource = {
"id": "",
"name": ""
}
self.source_translations = []
self.parent_draft = {}
self.translators = []
self.finished_chunks = []
# deserialize
if file_name:
if os.path.isfile(file_name):
manifest_json = load_json_object(file_name)
manifest_json = Manifest.standardize_manifest_json(manifest_json)
self.__dict__.update(manifest_json)
else:
raise IOError('The file {0} was not found.'.format(file_name))
if meta:
self.update_from_meta(meta)
if files_path:
self.update_from_files(files_path)
if repo_name:
self.update_from_repo_name(repo_name)
if not self.resource['id'] and (self.format == 'usfm' or (self.project['id'] and self.project['id'].lower() in BOOK_NAMES)):
self.resource['id'] = 'bible'
self.resource['name'] = 'Bible'
[docs] def update_from_repo_name(self, repo_name):
if '_' in repo_name:
parts = repo_name.split('_')
else:
parts = repo_name.split('-')
if not self.target_language['id']:
languages = Language.load_languages()
for i, part in enumerate(parts):
found = [x for x in languages if x.lc == part]
if len(found):
lang = found[0]
self.target_language['id'] = lang.lc
self.target_language['name'] = lang.ln
self.target_language['direction'] = lang.ld
del parts[i]
break
for part in parts:
if not self.resource['id']:
if part.lower() == 'obs':
self.resource['id'] = 'obs'
elif part.lower() == 'ulb':
self.resource['id'] = 'ulb'
elif part.lower() == 'udb':
self.resource['id'] = 'udb'
elif part.lower() == 'bible':
self.resource['id'] = 'bible'
self.resource['name'] = Manifest.get_resource_name(self.resource['id'])
if not self.format:
if part.lower() == 'obs':
self.format = 'markdown'
if part.lower() == 'ulb' or part.lower() == 'udb' or part.lower() == 'bible':
self.format = 'usfm'
if not self.project['id'] and part.lower() in BOOK_NAMES:
self.project['id'] = part.lower()
self.project['name'] = BOOK_NAMES[part.lower()]
if not self.format:
self.format = 'usfm'
if not self.resource['id']:
self.resource['id'] = 'bible'
self.resource['name'] = 'Bible'
if not self.resource['id']:
self.resource['id'] = repo_name
self.resource['name'] = repo_name
if not self.target_language['id']:
self.target_language['id'] = 'en'
self.target_language['name'] = 'English'
[docs] def update_from_files(self, path):
path = path.rstrip('/')
found_markdown = False
found_usfm = False
found_html = False
found_text_in_numbered_dir = False
if not self.format:
for f in get_files(path):
if f.endswith('usfm'):
found_usfm = True
elif f.endswith('.md'):
found_markdown = True
elif f.endswith('.html'):
found_html = True
elif f.endswith('.txt'):
try:
if int(os.path.basename(os.path.dirname(f))):
found_text_in_numbered_dir = True
except Exception:
pass
if found_usfm:
if not self.format:
self.format = 'usfm'
if not self.resource['id']:
self.resource['id'] = 'bible'
self.resource['name'] = 'Bible'
elif found_markdown:
if not self.format:
self.format = 'markdown'
elif found_html:
if not self.format:
self.format = 'html'
if not self.generator['name']:
for subdir in glob(os.path.join(path, '*')):
if os.path.isdir(subdir):
dir_name = subdir[len(path)+1:]
try:
if int(dir_name) and len(glob(os.path.join(subdir, '*.txt'))) > 0:
self.generator['name'] = 'ts'
break
except Exception:
continue
@staticmethod
[docs] def standardize_manifest_json(manifest):
translators = []
if 'translators' in manifest:
for translator in manifest['translators']:
if isinstance(translator, dict) and 'name' in translator:
translators.append(translator['name'])
elif isinstance(translator, basestring):
translators.append(translator)
manifest['translators'] = translators
source_translations = []
if 'source_translations' in manifest:
if isinstance(manifest['source_translations'], dict):
for key in manifest['source_translations'].keys():
source = manifest['source_translations'][key]
prod, lang, resource = key.split('-')
source['language_id'] = lang
source['resource_id'] = resource
source_translations.append(source)
if 'resource' not in manifest:
manifest['resource'] = {'id': resource, 'name': ""}
if 'format' not in manifest:
if resource == 'ulb' or resource == 'udb' or resource == 'bible':
manifest['format'] = 'usfm'
elif resource == 'obs':
manifest['format'] = 'markdown'
manifest['source_translations'] = source_translations
if 'sources' in manifest:
manifest['source_translations'] = manifest['sources']
del manifest['sources']
if 'target_language' not in manifest:
manifest['target_language'] = {'id': "", 'name': "", 'direction': "l2r"}
if 'language' in manifest and isinstance(manifest['language'], dict):
if 'lc' in manifest['language']:
manifest['target_language']['id'] = manifest['language']['lc']
elif 'slug' in manifest['language']:
manifest['target_language']['id'] = manifest['language']['slug']
if 'ln' in manifest['language']:
manifest['target_language']['name'] = manifest['language']['ln']
elif 'name' in manifest['language']:
manifest['target_language']['name'] = manifest['language']['name']
if 'direction' in manifest['language']:
manifest['target_language']['direction'] = manifest['language']['direction']
elif 'dir' in manifest['language']:
manifest['target_language']['direction'] = manifest['language']['dir']
del manifest['language']
if 'project' not in manifest:
manifest['project'] = {'id': "", 'name': ""}
if 'project_id' in manifest:
manifest['project']['id'] = manifest['project_id']
if 'format' in manifest and manifest['format'] == 'usfm':
manifest['project']['name'] = BOOK_NAMES[manifest['project_id']]
del manifest['project_id']
elif 'slug' in manifest['project']:
manifest['project']['id'] = manifest['project']['slug'].lower()
manifest['project']['name'] = BOOK_NAMES[manifest['project']['slug'].lower()]
del manifest['project']['slug']
if 'project' in manifest and 'id' in manifest['project']:
if manifest['project']['id'] in BOOK_NAMES:
if 'resource' not in manifest or 'id' not in manifest['resource']:
manifest['resource'] = {
'id': 'bible',
'name': 'Bible'
}
if 'format' not in manifest:
manifest['format'] = 'usfm'
elif manifest['project']['id'] == 'obs':
if 'resource' not in manifest or 'id' not in manifest['resource']:
manifest['resource'] = {
'id': 'obs',
'name': 'Open Bible Stories'
}
if 'format' not in manifest:
manifest['format'] = 'markdown'
else:
if 'format' not in manifest:
manifest['format'] = 'markdown'
if 'parent_drafts' not in manifest:
manifest['parent_drafts'] = {}
if 'finished_frames' in manifest:
manifest['finished_chunks'] = manifest['finished_frames']
del manifest['finished_frames']
if 'type' not in manifest:
manifest['type'] = {'id': 'text', 'name': 'Text'}
if 'resource' not in manifest:
manifest['resource'] = {'id': "", 'name': ""}
elif 'id' in manifest['resource'] and manifest['resource']['id'] and ('name' not in manifest['resource'] or not manifest['resource']['name']):
manifest['resource']['name'] = Manifest.get_resource_name(manifest['resource']['id'])
if 'slug' in manifest:
if not manifest['resource']['id']:
manifest['resource']['id'] = manifest['slug']
del manifest['slug']
if 'name' in manifest:
if not manifest['resource']['name']:
manifest['resource']['name'] = manifest['name']
del manifest['name']
if manifest['format'] == 'usfm' and manifest['resource']['id'] not in ['ulb', 'udb', 'bible']:
manifest['resource']['id'] = 'bible'
if not manifest['resource']['name']:
manifest['resource']['name'] = Manifest.get_resource_name(manifest['resource']['id'])
manifest['package_version'] = Manifest.LATEST_VERSION
return manifest
@staticmethod
[docs] def get_resource_name(resource_id):
resource_id = resource_id.lower()
if resource_id == 'ulb':
return 'Unlocked Literal Bible'
elif resource_id == 'udb':
return 'Unlocked Dynamic Bible'
elif resource_id == 'bible':
return 'Bible'
elif resource_id == 'obs':
return 'Open Bible Stories'
elif resource_id == 'tn':
return 'translationNotes'
elif resource_id == 'tw':
return 'translationWords'
elif resource_id == 'tq':
return 'translationQuestions'
elif resource_id == 'ta':
return 'translationAcademy'
return ''