Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(codebase): type all possible instances #1964

Merged
merged 4 commits into from
Jan 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/librelingo_audios/librelingo_audios/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def ensure_output_directory(output_path, settings):
show_default=True,
help="--destructive deletes existing audio and re-generates from scratch. --non-destructive performs an iterative update.",
)
def _command(input_path, output_path, course_name, dry_run, destructive):
def _command(input_path: str, output_path: str, course_name: str, dry_run, destructive):
"""
Generate audios for a YAML course.
"""
Expand Down
3 changes: 2 additions & 1 deletion apps/librelingo_audios/librelingo_audios/functions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from librelingo_types.data_types import Course
from librelingo_utils import audio_id, iterate_phrases
from librelingo_utils.utils import iterate_words


def list_required_audios(course):
def list_required_audios(course: Course):
for phrase in iterate_phrases(course):
# Returning only the first version because
# the other versions never need audio.
Expand Down
63 changes: 33 additions & 30 deletions apps/librelingo_audios/librelingo_audios/update_audios.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@
import subprocess
import json
import random
from collections import namedtuple
from typing import Set, Union
from librelingo_audios.functions import list_required_audios
from librelingo_types.data_types import Course, PhraseIdentity
from librelingo_utils import audio_id


def update_audios_for_course(output_path, course_name, course, settings):
def update_audios_for_course(
output_path: str, course_name: str, course: Course, settings
):
if not course.settings.audio_settings.enabled:
return

Expand Down Expand Up @@ -48,27 +51,34 @@ def update_audios_for_course(output_path, course_name, course, settings):
_save_index(result_index, index_file_path)


def _load_index_file(file_path):
def _load_index_file(file_path: Path):
if not file_path.is_file():
return []

with open(file_path, "r") as f:
return json.loads(f.read())


def _keep_phrases(phrases_to_keep, existing_index):
def _keep_phrases(phrases_to_keep: Union[Set, Set[PhraseIdentity]], existing_index):
return [
p
for p in existing_index
if _phrase_identity_info_from_index(p) in phrases_to_keep
phrase
for phrase in existing_index
if _phrase_identity_info_from_index(phrase) in phrases_to_keep
]


def _fetch_phrases(phrases, output_path, course, settings):
return [_fetch_audio_for_phrase(p, output_path, course, settings) for p in phrases]
def _fetch_phrases(
phrases: Set[PhraseIdentity], output_path: str, course: Course, settings
):
return [
_fetch_audio_for_phrase(phrase_identity, output_path, course, settings)
for phrase_identity in phrases
]


def _fetch_audio_for_phrase(phrase_identity, output_path, course, settings):
def _fetch_audio_for_phrase(
phrase_identity: PhraseIdentity, output_path: str, course: Course, settings
):
file_name = audio_id(course.target_language, phrase_identity.text)
destination_path = Path(Path(output_path) / f"{file_name}.mp3")

Expand All @@ -80,7 +90,11 @@ def _fetch_audio_for_phrase(phrase_identity, output_path, course, settings):


def _generate_audio_with_tts(
phrase_identity, file_name, destination_path, course, settings
phrase_identity: PhraseIdentity,
file_name: str,
destination_path: Path,
course: Course,
settings,
):
tts_settings_list = course.settings.audio_settings.text_to_speech_settings_list
if tts_settings_list == []:
Expand Down Expand Up @@ -129,13 +143,15 @@ def _generate_audio_with_tts(
}


def _delete_phrases(phrases, output_path, existing_index, settings):
for p in existing_index:
if _phrase_identity_info_from_index(p) in phrases:
_delete_audio_for_phrase(p, output_path, settings)
def _delete_phrases(
phrases: Set[PhraseIdentity], output_path: str, existing_index, settings
):
for phrase_index in existing_index:
if _phrase_identity_info_from_index(phrase_index) in phrases:
_delete_audio_for_phrase(phrase_index, output_path, settings)


def _delete_audio_for_phrase(index_entry, output_path, settings):
def _delete_audio_for_phrase(index_entry, output_path: str, settings):
target_path = Path(Path(output_path) / f"{index_entry['id']}.mp3")

if not target_path.is_file():
Expand All @@ -149,29 +165,16 @@ def _delete_audio_for_phrase(index_entry, output_path, settings):
target_path.unlink()


def _save_index(result_index, index_file_path):
def _save_index(result_index: list, index_file_path: Path):
with open(index_file_path, "w", encoding="utf-8") as f:
json.dump(
sorted(result_index, key=lambda i: i["id"]), f, ensure_ascii=False, indent=4
)


class PhraseIdentity(namedtuple("PhraseIdentity", ["text", "source"])):
"""
This is the set of information that identifies a phrase as 'the same'. If any
of these things change, the phrase will be seen as 'new' and re-generated.
"""

pass


def _phrase_identity_info_from_text(text):
return PhraseIdentity(text, "TTS")


def _phrase_identity_info_from_phrase(phrase_object):
return _phrase_identity_info_from_text(phrase_object.in_target_language[0])


def _phrase_identity_info_from_index(phrase_index_entry):
return PhraseIdentity(phrase_index_entry["text"], phrase_index_entry["source"])
2 changes: 1 addition & 1 deletion apps/librelingo_json_export/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#### export\_course

```python
export_course(export_path, course, settings=None)
export_course(export_path: str, course: Course, settings=None)
```

Writes the course to JSON files in the specified path.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import editdistance # type: ignore


from librelingo_utils import (
get_dumb_opaque_id,
audio_id,
remove_control_characters_for_display,
clean_word,
iterate_phrases,
)

from librelingo_types import Course, Word

from .dictionary import _define_words_in_sentence


def get_listening_challenge(source, course):
def get_listening_challenge(source: Word, course: Course):
if not course.settings.audio_settings.enabled:
return []

Expand All @@ -34,7 +38,7 @@ def get_listening_challenge(source, course):
]


def get_short_input_challenge(source, course):
def get_short_input_challenge(source: Word, course: Course):
return [
{
"type": "shortInput",
Expand All @@ -55,7 +59,7 @@ def get_short_input_challenge(source, course):
]


def get_cards_challenge(word, _):
def get_cards_challenge(word: Word, _):
return [
{
"type": "cards",
Expand Down Expand Up @@ -96,7 +100,7 @@ def get_chips_from_string(phrase):
return list(map(clean_word, phrase.split()))


def get_chips_from_phrase(get_input_texts, phrase, course):
def get_chips_from_phrase(get_input_texts, phrase, course: Course):
extra_chips = []
solution_chips = get_chips_from_string(get_input_texts(phrase)[0])

Expand Down Expand Up @@ -125,7 +129,7 @@ def get_chips_from_phrase(get_input_texts, phrase, course):


def get_solutions_from_phrase(get_input_texts, phrase):
return [get_chips_from_string(x) for x in get_input_texts(phrase)]
return [get_chips_from_string(text) for text in get_input_texts(phrase)]


def create_chips_challenge_generator(reverse):
Expand All @@ -148,7 +152,7 @@ def is_long_enough_to_have_chips(phrase):
return False
return True

def get_chips_challenge(phrase, course):
def get_chips_challenge(phrase, course: Course):
if not is_long_enough_to_have_chips(phrase):
return []

Expand Down
11 changes: 6 additions & 5 deletions apps/librelingo_json_export/librelingo_json_export/challenges.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from librelingo_types.data_types import Course
from .challenge_types import (
get_options_challenge,
get_listening_challenge,
Expand All @@ -8,7 +9,7 @@
)


def _make_challenges_using(callback, data_source, course):
def _make_challenges_using(callback, data_source, course: Course):
"""
Calls a callback function with an item (Word or Phrase)
to create challenges. Each item in the data source will
Expand All @@ -29,7 +30,7 @@ def _challenge_mapper(challenge_types):
of the given course.
"""

def map_challenge_creators(item, course):
def map_challenge_creators(item, course: Course):
challenges = []
for challenge_type_callback in challenge_types:
for challenge in challenge_type_callback(item, course):
Expand All @@ -40,7 +41,7 @@ def map_challenge_creators(item, course):
return map_challenge_creators


def _get_phrase_challenges(phrase, course):
def _get_phrase_challenges(phrase, course: Course):
"Generate challenges based on a Phrase"
return _challenge_mapper(
[
Expand All @@ -52,14 +53,14 @@ def _get_phrase_challenges(phrase, course):
)(phrase, course)


def _get_word_challenges(word, course):
def _get_word_challenges(word, course: Course):
"Generate challenges based on a Word"
return _challenge_mapper(
[get_cards_challenge, get_short_input_challenge, get_listening_challenge]
)(word, course)


def _get_challenges_data(skill, course):
def _get_challenges_data(skill, course: Course):
"""
Generates challenges for a certain Skill
"""
Expand Down
4 changes: 2 additions & 2 deletions apps/librelingo_json_export/librelingo_json_export/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
)


def ensure_output_directory(output_path, settings):
def ensure_output_directory(output_path: str, settings: Settings):
if not settings.dry_run:
Path(output_path).mkdir(parents=True, exist_ok=True)

Expand All @@ -25,7 +25,7 @@ def ensure_output_directory(output_path, settings):
@click.argument("input_path")
@click.argument("output_path")
@click.option("--dry-run/--no-dry-run", default=DEFAULT_SETTINGS.dry_run)
def main(input_path, output_path, dry_run):
def main(input_path: str, output_path: str, dry_run):
"""
Convert a YAML course into JSON files to be consumed by the web app.
"""
Expand Down
3 changes: 2 additions & 1 deletion apps/librelingo_json_export/librelingo_json_export/course.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from librelingo_types.data_types import Course
from .module import _get_module_summary


def _get_course_data(course):
def _get_course_data(course: Course):
"""
Format Course according to the JSON structure
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
"""

from librelingo_utils import clean_word, get_words_from_phrase
from librelingo_types.data_types import Course, Word


def _get_raw_dictionary_item(course, word, is_in_target_language):
def _get_raw_dictionary_item(course: Course, word: Word, is_in_target_language):
"""
Find the matching raw dictionary item for a word.
"""
Expand All @@ -35,7 +36,7 @@ def _get_raw_dictionary_item(course, word, is_in_target_language):
return dictionary_item[0] if dictionary_item else None


def _define_word(course, word, is_in_target_language):
def _define_word(course: Course, word: Word, is_in_target_language):
"""
Creates the definition object for a word.
"""
Expand All @@ -53,7 +54,7 @@ def _define_word(course, word, is_in_target_language):
)


def _define_words_in_sentence(course, sentence, reverse):
def _define_words_in_sentence(course: Course, sentence, reverse):
"""
Converts a sentence into a list of definition objects.
"""
Expand Down
9 changes: 5 additions & 4 deletions apps/librelingo_json_export/librelingo_json_export/export.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import logging
import json
from pathlib import Path
from librelingo_types.data_types import Course, Skill
from slugify import slugify
from .skills import _get_skill_data
from .course import _get_course_data

logger = logging.getLogger("librelingo_json_export")


def _export_course_skills(export_path, course, settings=None):
def _export_course_skills(export_path: str, course: Course, settings=None):
"""
Writes every skill in a course into separate JSON files.
You probably don't need to call this function directly, because you
Expand All @@ -19,7 +20,7 @@ def _export_course_skills(export_path, course, settings=None):
_export_skill(export_path, skill, course, settings)


def _export_skill(export_path, skill, course, settings=None):
def _export_skill(export_path: str, skill: Skill, course: Course, settings=None):
"""
Writes the given skill to a JSON file in the specified path.
You probably don't need to call this function directly, because you
Expand Down Expand Up @@ -55,7 +56,7 @@ def _export_skill(export_path, skill, course, settings=None):
f.write(skill.introduction)


def _export_course_data(export_path, course, settings=None):
def _export_course_data(export_path: str, course: Course, settings=None):
"""
Writes the metadata of a course to a JSON file in the specified path.
You probably don't need to call this function directly, because you
Expand All @@ -75,7 +76,7 @@ def _export_course_data(export_path, course, settings=None):
json.dump(course_data, f, ensure_ascii=False, indent=2)


def export_course(export_path, course, settings=None):
def export_course(export_path: str, course: Course, settings=None):
"""
Writes the course to JSON files in the specified path.

Expand Down
3 changes: 2 additions & 1 deletion apps/librelingo_json_export/librelingo_json_export/skills.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from librelingo_utils import get_opaque_id, calculate_number_of_levels
from librelingo_types.data_types import Course, Skill
from .challenges import _get_challenges_data


def _get_skill_data(skill, course):
def _get_skill_data(skill: Skill, course: Course):
"""
Format Course according to the JSON structure
"""
Expand Down
10 changes: 10 additions & 0 deletions apps/librelingo_types/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,13 @@ Definition in the target language (English in this case)
>>> DictionaryItem("speak", "hablo", True)
DictionaryItem(word='speak', definition='hablo', is_in_target_language=True)

<a name="librelingo_types.data_types.PhraseIdentity"></a>
## PhraseIdentity Objects

```python
class PhraseIdentity(namedtuple("PhraseIdentity", ["text", "source"]))
```

This is the set of information that identifies a phrase as 'the same'. If any
of these things change, the phrase will be seen as 'new' and re-generated.

Loading