Skip to content

Commit

Permalink
Merge branch 'feature/v2.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
caleb531 committed Mar 5, 2015
2 parents c60d073 + 7c3153b commit 2f43dec
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 96 deletions.
Binary file modified YouVersion Suggest.alfredworkflow
Binary file not shown.
2 changes: 1 addition & 1 deletion tests/test_compliance.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ def test_json():
validator = jsonschema.validate(data, schema)
yield nose.assert_is_none, validator
except jsonschema.exceptions.ValidationError as error:
assert False, error
yield nose.assert_true, False, error
9 changes: 4 additions & 5 deletions tests/test_filter_refs_book.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,10 @@ def test_numbered_partial():
nose.assert_equal(results[0]['title'], '1 Corinthians 1 (NIV)')


def test_numbered_whitespace():
"""should match numbered books irrespective of extra whitespace"""
results = yvs.get_result_list('1 cor', prefs={})
nose.assert_equal(len(results), 1)
nose.assert_equal(results[0]['title'], '1 Corinthians 1 (NIV)')
def test_number_only():
"""should match single number query"""
results = yvs.get_result_list('2', prefs={})
nose.assert_equal(len(results), 8)


def test_nonnumbered_partial():
Expand Down
8 changes: 5 additions & 3 deletions tests/test_filter_refs_chapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ def test_id():
def test_nonexistent():
"""should not match nonexistent chapters"""
results = yvs.get_result_list('psalm 160', prefs={})
nose.assert_equal(len(results), 0)
nose.assert_equal(len(results), 1)
nose.assert_equal(results[0]['title'], 'Psalm 150 (NIV)')


def test_zero_chapter():
"""should not match chapter zero"""
"""should interpret chapter zero as chapter one"""
results = yvs.get_result_list('psalm 0', prefs={})
nose.assert_equal(len(results), 0)
nose.assert_equal(len(results), 1)
nose.assert_equal(results[0]['title'], 'Psalm 1 (NIV)')
26 changes: 18 additions & 8 deletions tests/test_filter_refs_edge.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,36 @@


def test_whitespace():
"""should match references irrespective of surrounding whitespace"""
"""should ignore excessive whitespace"""
results = yvs.get_result_list(' romans 8 28 a ', prefs={})
nose.assert_equal(len(results), 1)
nose.assert_equal(results[0]['title'], 'Romans 8:28 (AMP)')


def test_littered():
"""should match reference literred with non-alphanumeric characters"""
results = yvs.get_result_list('1!co@13#4$7^e', prefs={})
"""should ignore non-alphanumeric characters"""
results = yvs.get_result_list('!1@co#13$4^7&e*', prefs={})
nose.assert_equal(len(results), 1)
nose.assert_equal(results[0]['title'], '1 Corinthians 13:4-7 (ESV)')


def test_trailing_alphanumeric():
"""should ignore trailing non-matching alphanumeric characters"""
results = yvs.get_result_list('2 co 3 x y z 1 2 3', prefs={})
nose.assert_equal(len(results), 1)
nose.assert_equal(results[0]['title'], '2 Corinthians 3 (NIV)')


def test_unicode_accented():
"""should recognize accented Unicode characters"""
results = yvs.get_result_list('é', prefs={})
nose.assert_equal(len(results), 0)
results = yvs.get_result_list('é 3', prefs={
'language': 'es'
})
nose.assert_equal(len(results), 1)
nose.assert_equal(results[0]['title'], 'Éxodo 3 (NVI)')


def test_unicode_obscure():
"""should recognize obscure Unicode characters"""
results = yvs.get_result_list('π', prefs={})
def test_unicode_normalization():
"""should normalize Unicode characters"""
results = yvs.get_result_list('e\u0301', prefs={})
nose.assert_equal(len(results), 0)
2 changes: 1 addition & 1 deletion tests/test_filter_refs_xml.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def test_validity():
try:
nose.assert_is_instance(ET.fromstring(xml), ET.Element)
except ET.ParseError:
assert False, 'result list XML is not valid'
nose.assert_true(False, 'result list XML is not valid')


def test_structure():
Expand Down
105 changes: 74 additions & 31 deletions utilities/add_language.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import io
import json
import urllib2

import argparse

json_params = {
'indent': 2,
Expand All @@ -26,11 +26,13 @@ def get_url_content(url, **kw):
return urllib2.urlopen(url).read().decode('utf-8')


def language_matches(text, language):
patt = '^({language}) \((\d+)\)$'.format(
language=language.lower())
matches = re.search(patt, text.lower(), flags=re.UNICODE)
return matches is not None
def get_language_name(text):
patt = '^\s*([^\W\d_]+)(?:\s*\((\d+)\))\s*$'
matches = re.search(patt, text, flags=re.UNICODE)
if matches:
return matches.group(1)
else:
return None


def get_version(version_elem):
Expand All @@ -46,17 +48,23 @@ def get_version(version_elem):

def get_version_elems(params):

d = pq(url='https://www.bible.com/versions',
d = pq(url='https://www.bible.com/{}/versions'
.format(params['language']['id']),
opener=get_url_content)

category_elems = d('#main > article > ul > li')
version_elems = None

for category_elem in category_elems:
if category_elems:

category_elem = category_elems[0]

text = category_elem.text.strip()
if language_matches(text, params['language']['name']):
version_elems = d(category_elem).find('li')
break
version_elems = d(category_elem).find('li')
params['language']['name'] = get_language_name(text)

if not params['language']['name']:
raise RuntimeError('Language name cannot be determined. Aborting.')

return version_elems

Expand All @@ -82,9 +90,9 @@ def get_versions(params):

for version_elem in version_elems:
version = get_version(version_elem)
if ('max_version_id' in params and
if (params['max_version_id'] and
(version['id'] <= params['max_version_id']) or
('max_version_id' not in params)):
(not params['max_version_id'])):
versions.append(version)

versions.sort(key=get_item_name)
Expand Down Expand Up @@ -139,7 +147,13 @@ def get_bible_data(params):

bible['versions'] = get_versions(params)

if 'default_version' not in params:
if (params['default_version'] and
not any(version['id'] == params['default_version'] for version in
bible['versions'])):
raise RuntimeError(
'Given default version does not exist in given language. Aborting.')

if not params['default_version']:
params['default_version'] = min(bible['versions'],
key=get_item_id)['id']

Expand All @@ -155,9 +169,11 @@ def save_bible_data(params):
language = params['language']
bible = get_bible_data(params)
bible_path = os.path.join('yv_suggest', 'data', 'bible',
'language-{}.json'.format(language['id']))
'language-{}.json'
.format(language['id'].replace('-', '_')))
with open(bible_path, 'w') as bible_file:
json.dump(bible, bible_file, **json_params)
bible_file.write('\n')


def update_language_list(params):
Expand All @@ -179,24 +195,51 @@ def update_language_list(params):

def add_language(params):

print('Adding support for {}...'
.format(params['language']['name']))
save_bible_data(params)
update_language_list(params)


def parse_args():

parser = argparse.ArgumentParser()
parser.add_argument('code')
parser.add_argument(
'--max-version-id',
type=int)
parser.add_argument(
'--default-version',
type=int)

args = parser.parse_args()

if '-' in args.code or '_' in args.code:
raise RuntimeError(
'Only two-letter language codes are supported. Aborting.')

return args


def get_params(args):

params = {
'language': {
'id': args.code,
'name': None
},
'max_version_id': args.max_version_id,
'default_version': args.default_version
}
return params


def main():

args = parse_args()
params = get_params(args)
print('Adding language support...')
add_language(params)
print('Support for {} has been successfully added.'
.format(params['language']['name']))


# Example usage
# add_language({
# 'language': {
# # Name of language must be written in said language
# 'name': 'Español',
# # ISO language code
# 'id': 'es'
# },
# # Versions with lower IDs tend to be more popular and less obscure
# 'max_version_id': 200,
# # If you know the default version you want to use, specify its ID
# 'default_version': 128
# })
if __name__ == '__main__':
main()
2 changes: 1 addition & 1 deletion yv_suggest/data/bible/language-en.json
Original file line number Diff line number Diff line change
Expand Up @@ -356,4 +356,4 @@
"name": "OJB"
}
]
}
}
2 changes: 1 addition & 1 deletion yv_suggest/data/bible/language-es.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,4 +316,4 @@
"name": "TLAD"
}
]
}
}
2 changes: 1 addition & 1 deletion yv_suggest/data/bible/language-nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -276,4 +276,4 @@
"name": "SV1750"
}
]
}
}
4 changes: 2 additions & 2 deletions yv_suggest/data/schema/schema-bible.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"name": {
"description": "The acronym for this version",
"type": "string",
"pattern": "^[^\\W\\d_]+\\d*$"
"pattern": "^[A-Z]+[0-9]*$"
},
"id": {
"description": "The ID used by YouVersion to uniquely identify this version.",
Expand Down Expand Up @@ -48,7 +48,7 @@
"title": "Book ID",
"description": "The ID used by YouVersion to uniquely identify this book",
"type": "string",
"pattern": "^\\d?[a-z]+$"
"pattern": "^[1-9]?[a-z]+$"
}
},
"required": ["name", "id"],
Expand Down
2 changes: 1 addition & 1 deletion yv_suggest/data/schema/schema-languages.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"id": {
"description": "The language's ISO 639-1 code",
"type": "string",
"pattern": "^[a-z]{2}(_[A-Z]{2})?$"
"pattern": "^[a-z]{2}$"
}
},
"required": ["name", "id"],
Expand Down
Loading

0 comments on commit 2f43dec

Please sign in to comment.