refactor: re-organize gitignore
* chore(pylint): enable pylint rule and reorganize gitignore * chore(pylint): fix pylint line-too-long pylint rule * improv: fix formatting issues * fix: fix pytest docstrings * improv: remove trailing disabled pylint error Co-authored-by: Daniel Kantor <git@daniel-kantor.com>
This commit is contained in:
parent
9c27cfa76d
commit
7d9d996176
|
@ -1,48 +1,78 @@
|
|||
.DS_Store
|
||||
# IDE
|
||||
**/.DS_Store
|
||||
**/.vscode
|
||||
**/.idea/codeStyles/codeStyleConfig.xml
|
||||
**/.idea/jsLinters/eslint.xml
|
||||
**/.idea/LibreLingo.iml
|
||||
**/.idea/misc.xml
|
||||
**/.idea/modules.xml
|
||||
**/.idea/codeStyles/Project.xml
|
||||
**/.idea/inspectionProfiles/Project_Default.xml
|
||||
**/.idea/vcs.xml
|
||||
**/.idea/workspace.xml
|
||||
**/.vim
|
||||
|
||||
|
||||
# Dependencies
|
||||
/node_modules/
|
||||
**/node_modules/
|
||||
/src/node_modules/@sapper/
|
||||
.venv/
|
||||
.env
|
||||
/apps/*/poetry.lock
|
||||
|
||||
|
||||
# Development
|
||||
yarn-error.log
|
||||
apps/web/cypress/screenshots/
|
||||
.yarn
|
||||
.yarnrc
|
||||
*.pyc
|
||||
/apps/librelingo_json_export/profile.png
|
||||
profile.dat
|
||||
|
||||
|
||||
# Static files
|
||||
/apps/web/__sapper__/
|
||||
/static/files
|
||||
staticfiles/
|
||||
apps/web/static/files/noto-*
|
||||
|
||||
|
||||
# Cypress files
|
||||
.nyc_output/
|
||||
cypress-coverage/
|
||||
jest-coverage/
|
||||
cypress/videos
|
||||
.venv/
|
||||
/course_editor/db.sqlite3
|
||||
*.pyc
|
||||
.env
|
||||
/db.sqlite3
|
||||
/src/audios_to_fetch.csv
|
||||
localData/
|
||||
staticfiles/
|
||||
git_stats/
|
||||
/.idea/codeStyles/codeStyleConfig.xml
|
||||
/.idea/jsLinters/eslint.xml
|
||||
/.idea/LibreLingo.iml
|
||||
/.idea/misc.xml
|
||||
/.idea/modules.xml
|
||||
/.idea/codeStyles/Project.xml
|
||||
/.idea/inspectionProfiles/Project_Default.xml
|
||||
/.idea/vcs.xml
|
||||
/.idea/workspace.xml
|
||||
apps/web/static/files/noto-*
|
||||
**/cypress/videos
|
||||
apps/web/cypress/screenshots/
|
||||
apps/web/cypress/screenshots/**/__tkey-*.png
|
||||
.vim
|
||||
**/coverage/
|
||||
|
||||
|
||||
# Build
|
||||
apps/librelingo_tools/dist
|
||||
**/dist/
|
||||
*.tsbuildinfo
|
||||
report.*.*.json
|
||||
/coverage/
|
||||
|
||||
|
||||
# Documentation
|
||||
apps/docs/build/
|
||||
report.*.*.json
|
||||
*.tsbuildinfo
|
||||
__sapper__
|
||||
.yarn
|
||||
.yarnrc
|
||||
|
||||
|
||||
# Stats
|
||||
git_stats/
|
||||
|
||||
|
||||
# Data
|
||||
/course_editor/db.sqlite3
|
||||
/db.sqlite3
|
||||
/src/audios_to_fetch.csv
|
||||
/apps/librelingo_json_export/profile.png
|
||||
localData/
|
||||
|
||||
|
||||
# Courses
|
||||
/apps/web/src/courses/*-*
|
||||
/courses/*-*
|
||||
profile.dat
|
||||
/apps/librelingo_json_export/profile.png
|
||||
/apps/*/poetry.lock
|
||||
.vscode/
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
from pathlib import Path
|
||||
import collections
|
||||
from pathlib import Path
|
||||
|
||||
import click # type: ignore
|
||||
from librelingo_yaml_loader import load_course
|
||||
|
||||
from librelingo_audios.update_audios import update_audios_for_course
|
||||
|
||||
Settings = collections.namedtuple(
|
||||
|
@ -32,7 +34,8 @@ def ensure_output_directory(output_path, settings):
|
|||
"--destructive/--non-destructive",
|
||||
default=DEFAULT_SETTINGS.destructive,
|
||||
show_default=True,
|
||||
help="--destructive deletes existing audio and re-generates from scratch. --non-destructive performs an iterative update.",
|
||||
help="--destructive deletes existing audio and re-generates from scratch."
|
||||
"--non-destructive performs an iterative update.",
|
||||
)
|
||||
def _command(input_path: str, output_path: str, course_name: str, dry_run, destructive):
|
||||
"""
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
from pathlib import Path
|
||||
import subprocess
|
||||
import json
|
||||
import random
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
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
|
||||
|
||||
from librelingo_audios.functions import list_required_audios
|
||||
|
||||
|
||||
def update_audios_for_course(
|
||||
output_path: str, course_name: str, course: Course, settings
|
||||
|
@ -106,11 +108,13 @@ def _generate_audio_with_tts(
|
|||
|
||||
if settings.dry_run:
|
||||
print(
|
||||
f"Would generate {destination_path} using {chosen_tts_settings.voice} {chosen_tts_settings.engine}"
|
||||
f"Would generate {destination_path} "
|
||||
f"using {chosen_tts_settings.voice} {chosen_tts_settings.engine}"
|
||||
)
|
||||
else:
|
||||
print(
|
||||
f"Generating {destination_path} using {chosen_tts_settings.voice} {chosen_tts_settings.engine}"
|
||||
f"Generating {destination_path} "
|
||||
f"using {chosen_tts_settings.voice} {chosen_tts_settings.engine}"
|
||||
)
|
||||
# This is where more more TTS providers would be added with an if statement.
|
||||
# For now there is only Polly.
|
||||
|
|
|
@ -50,6 +50,7 @@ def terminal(tmp_path, capsys):
|
|||
|
||||
return SimpleNamespace(
|
||||
assert_output_matches=assert_output_matches,
|
||||
# pylint: disable=line-too-long
|
||||
message=SimpleNamespace(
|
||||
**{
|
||||
"generating": lambda text: f"Generating {tmp_path / _mock_audio_file_for_text(text)} using Lupe standard",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
"""
|
||||
This package contains fake data for testing LibreLingo-related packages.
|
||||
|
||||
The fake data is returned using the types from [librelingo-types](https://pypi.org/project/librelingo-types/).
|
||||
The fake data is returned using the types from
|
||||
[librelingo-types](https://pypi.org/project/librelingo-types/).
|
||||
|
||||
## Usage
|
||||
```python
|
||||
|
@ -13,7 +14,8 @@ fakes.course2 # This is another Course() object
|
|||
fakes.courseEmpty # This is an empty course
|
||||
```
|
||||
|
||||
For the full list of fakes, use the autocomplete or check out the [this file](https://github.com/LibreLingo/LibreLingo/blob/main/apps/librelingo_fakes/librelingo_fakes/fakes.py).
|
||||
# pylint: disable=line-too-long
|
||||
For the full list of fakes, use the autocomplete or check out[this file](https://github.com/LibreLingo/LibreLingo/blob/main/apps/librelingo_fakes/librelingo_fakes/fakes.py).
|
||||
|
||||
### Customizing fakes
|
||||
|
||||
|
@ -29,20 +31,23 @@ fake_course = fakes.customize(fakes.course1, modules=[
|
|||
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import random
|
||||
from collections import namedtuple
|
||||
from librelingo_types import Course
|
||||
from librelingo_types import Module
|
||||
from librelingo_types import Skill
|
||||
from librelingo_types import Phrase
|
||||
from librelingo_types import Word
|
||||
from librelingo_types import License
|
||||
from librelingo_types import Language
|
||||
from librelingo_types import DictionaryItem
|
||||
from librelingo_types import Settings
|
||||
from librelingo_types import AudioSettings
|
||||
from librelingo_types import TextToSpeechSettings
|
||||
from pathlib import Path
|
||||
|
||||
from librelingo_types import (
|
||||
AudioSettings,
|
||||
Course,
|
||||
DictionaryItem,
|
||||
Language,
|
||||
License,
|
||||
Module,
|
||||
Phrase,
|
||||
Settings,
|
||||
Skill,
|
||||
TextToSpeechSettings,
|
||||
Word,
|
||||
)
|
||||
|
||||
challenge1 = "challenge1"
|
||||
challenge2 = "challenge2"
|
||||
|
|
|
@ -50,7 +50,8 @@ def _define_word(course: Course, word: Word, is_in_target_language):
|
|||
else course.source_language.name
|
||||
)
|
||||
raise ValueError(
|
||||
f'The {language_name} word "{word}" does not have a definition. Please add it to the mini-dictionary.'
|
||||
f'The {language_name} word "{word}" does not have a definition.'
|
||||
"Please add it to the mini-dictionary."
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@ from librelingo_types import DictionaryItem
|
|||
def test_definition_not_found():
|
||||
word = str(fakes.fake_value())
|
||||
pattern = re.escape(
|
||||
f'The another language word "{word}" does not have a definition. Please add it to the mini-dictionary.'
|
||||
f'The another language word "{word}" does not have a definition.'
|
||||
"Please add it to the mini-dictionary."
|
||||
)
|
||||
with pytest.raises(ValueError, match=pattern):
|
||||
assert _define_word(fakes.course1, word, is_in_target_language=False) is True
|
||||
|
|
|
@ -27,6 +27,7 @@ def test__get_course_data_return_value():
|
|||
"languageName": "my language",
|
||||
"languageCode": "de",
|
||||
"specialCharacters": ["ä", "ß"],
|
||||
# pylint: disable=line-too-long
|
||||
"repositoryURL": "https://github.com/kantord/LibreLingo/tree/main/courses/spanish-from-english",
|
||||
"license": {
|
||||
"name": {
|
||||
|
|
|
@ -28,6 +28,7 @@ class TextToSpeechSettings(
|
|||
pass
|
||||
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
class AudioSettings(
|
||||
namedtuple(
|
||||
"AudioSettings",
|
||||
|
@ -78,6 +79,7 @@ class HunspellSettings(
|
|||
pass
|
||||
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
class Settings(
|
||||
namedtuple(
|
||||
"Settings",
|
||||
|
@ -154,6 +156,7 @@ class Language(namedtuple("Language", ["name", "code"])):
|
|||
pass
|
||||
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
class License(
|
||||
namedtuple(
|
||||
"License",
|
||||
|
@ -244,6 +247,7 @@ class Skill(
|
|||
pass
|
||||
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
class Word(
|
||||
namedtuple(
|
||||
"Word",
|
||||
|
|
|
@ -26,7 +26,8 @@ def _validate_phrase_in_target_language(phrase, course):
|
|||
for variant_subword in variant.split():
|
||||
if not course.settings.hunspell.target_language.spell(variant_subword):
|
||||
raise RuntimeError(
|
||||
f'The {course.target_language.name} phrase "{variant}" is misspelled. The word "{variant_subword}" is unknown.'
|
||||
f'The {course.target_language.name} phrase "{variant}" is misspelled.'
|
||||
f'The word "{variant_subword}" is unknown.'
|
||||
)
|
||||
|
||||
|
||||
|
@ -35,7 +36,8 @@ def _validate_phrase_in_source_language(phrase, course):
|
|||
for variant_subword in variant.split():
|
||||
if not course.settings.hunspell.source_language.spell(variant_subword):
|
||||
raise RuntimeError(
|
||||
f'The {course.source_language.name} phrase "{variant}" is misspelled. The word "{variant_subword}" is unknown.'
|
||||
f'The {course.source_language.name} phrase "{variant}" is misspelled.'
|
||||
f'The word "{variant_subword}" is unknown.'
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -150,7 +150,9 @@ def _convert_word(raw_word) -> Word:
|
|||
"""
|
||||
Converts a YAML word definition into a Word() object
|
||||
|
||||
>>> _convert_word({'Images': ["abc"], 'Word': "cat", 'Synonyms': ["kitten"], 'Translation': "gato"})
|
||||
>>> _convert_word(
|
||||
... {'Images': ["abc"], 'Word': "cat", 'Synonyms': ["kitten"], 'Translation': "gato"}
|
||||
... )
|
||||
Word(in_target_language=['cat', 'kitten'], in_source_language=['gato'], pictures=['abc'])
|
||||
"""
|
||||
return Word(
|
||||
|
@ -162,6 +164,7 @@ def _convert_word(raw_word) -> Word:
|
|||
)
|
||||
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
def _convert_words(raw_words: List[Word]) -> List[Word]:
|
||||
"""
|
||||
Converts each YAML word definition into Word() objects
|
||||
|
@ -183,6 +186,7 @@ def _convert_words(raw_words: List[Word]) -> List[Word]:
|
|||
return list(map(_convert_word, raw_words))
|
||||
|
||||
|
||||
# pylint: disable=line-too-long
|
||||
def _convert_phrase(raw_phrase) -> Phrase:
|
||||
"""
|
||||
Converts a YAML phrase definition into a Phrase() object
|
||||
|
|
|
@ -893,7 +893,8 @@ def test_load_skill_complains_about_misspelled_phrase_in_target_language(load_ya
|
|||
),
|
||||
)
|
||||
expected_error = re.escape(
|
||||
f'The {fake_course.target_language.name} phrase "{fake_phrase}" is misspelled. The word "{fake_word}" is unknown.'
|
||||
f'The {fake_course.target_language.name} phrase "{fake_phrase}" is misspelled.'
|
||||
f'The word "{fake_word}" is unknown.'
|
||||
)
|
||||
with pytest.raises(RuntimeError, match=expected_error):
|
||||
_load_skill(random_path, fake_course)
|
||||
|
@ -927,7 +928,8 @@ def test_load_skill_complains_about_misspelled_phrase_in_source_language(load_ya
|
|||
),
|
||||
)
|
||||
expected_error = re.escape(
|
||||
f'The {fake_course.source_language.name} phrase "{fake_phrase}" is misspelled. The word "{fake_word}" is unknown.'
|
||||
f'The {fake_course.source_language.name} phrase "{fake_phrase}" is misspelled.'
|
||||
f'The word "{fake_word}" is unknown.'
|
||||
)
|
||||
with pytest.raises(RuntimeError, match=expected_error):
|
||||
_load_skill(random_path, fake_course)
|
||||
|
|
|
@ -78,7 +78,8 @@ def download_course(url, tempdir):
|
|||
def generate_course(links, courses_data, reldir, outdir, tdir, course_dir):
|
||||
logging.info("generate_course %s", course_dir)
|
||||
# pylint complains of "Catching too general exception Exception (broad-except)"
|
||||
# but I don't know what kind of exception can happen there, so for now let's not catch any exception.
|
||||
# but I don't know what kind of exception can happen there,
|
||||
# so for now let's not catch any exception.
|
||||
# try:
|
||||
docs_dir = os.path.join(outdir, tdir)
|
||||
course = lili.load_course(course_dir)
|
||||
|
|
|
@ -27,7 +27,11 @@ def main():
|
|||
for module in course.modules:
|
||||
for skill in module.skills:
|
||||
|
||||
# Word(in_target_language=['el chapeo', 'el chapeyo'], in_source_language=['the hat'], pictures=['hat1', 'hat2', 'hat3'])
|
||||
# Word(
|
||||
# in_target_language=['el chapeo', 'el chapeyo'],
|
||||
# in_source_language=['the hat'],
|
||||
# pictures=['hat1', 'hat2', 'hat3']
|
||||
# )
|
||||
for word in skill.words:
|
||||
collect(
|
||||
"target_word", module, skill, search_word, word.in_target_language
|
||||
|
|
|
@ -97,7 +97,8 @@ def render(template_file, **args):
|
|||
|
||||
def export_main_html_page(course, count, html_dir):
|
||||
branch = "main" # how can we know which is the default branch of a repository?
|
||||
#'count', 'dictionary', 'index', 'license', 'modules', 'repository_url', 'settings', 'source_language', 'special_characters', 'target_language'
|
||||
#'count', 'dictionary', 'index', 'license', 'modules', 'repository_url',
|
||||
#'settings', 'source_language', 'special_characters', 'target_language'
|
||||
# course.modules[0].skills[0].phrases
|
||||
# from ptpython.repl import embed
|
||||
# embed(globals(), locals())
|
||||
|
@ -435,7 +436,11 @@ class Lili:
|
|||
if picture in self.unused_images["regular"]:
|
||||
self.unused_images["regular"].remove(picture)
|
||||
# print(word.pictures)
|
||||
# Word(in_target_language=['la mujer'], in_source_language=['the woman'], pictures=['woman1', 'woman2', 'woman3'])
|
||||
# Word(
|
||||
# in_target_language=['la mujer'],
|
||||
# in_source_language=['the woman'],
|
||||
# pictures=['woman1', 'woman2', 'woman3']
|
||||
# )
|
||||
|
||||
def collect_ids_and_names(self, images, course):
|
||||
for module in course.modules:
|
||||
|
@ -444,11 +449,15 @@ class Lili:
|
|||
self.check_images(module, skill)
|
||||
if skill.id in self.skill_ids:
|
||||
self.errors.append(
|
||||
f"Duplicate id: {skill.id} in {module.title}/{skill.name} and in {self.skill_ids[skill.id]['module'].title}/{self.skill_ids[skill.id]['skill'].name}"
|
||||
f"Duplicate id: {skill.id} in {module.title}/{skill.name}"
|
||||
f"and in {self.skill_ids[skill.id]['module'].title}"
|
||||
f"/{self.skill_ids[skill.id]['skill'].name}"
|
||||
)
|
||||
if skill.name in self.skill_names:
|
||||
self.errors.append(
|
||||
f"Duplicate name: {skill.name} in {module.title}/{skill.name} and in {self.skill_names[skill.name]['module'].title}/{self.skill_names[skill.name]['skill'].name}"
|
||||
f"Duplicate name: {skill.name} in {module.title}/{skill.name} "
|
||||
f"and in {self.skill_names[skill.name]['module'].title}/"
|
||||
f"{self.skill_names[skill.name]['skill'].name}"
|
||||
)
|
||||
self.skill_ids[skill.id] = {
|
||||
"module": module,
|
||||
|
|
|
@ -53,10 +53,14 @@ def main():
|
|||
# #exit()
|
||||
# for sentence in phrase.in_target_language:
|
||||
# if found(search_word, [sentence]):
|
||||
# phrases[sentence].append({"filename": skill.filename, "translations": phrase.in_source_language})
|
||||
# phrases[sentence].append(
|
||||
# {"filename": skill.filename, "translations": phrase.in_source_language}
|
||||
# )
|
||||
# for sentence in phrase.in_source_language:
|
||||
# if found(search_word, [sentence]):
|
||||
# phrases[sentence].append({"filename": skill.filename, "translations": phrase.in_target_language})
|
||||
# phrases[sentence].append(
|
||||
# {"filename": skill.filename, "translations": phrase.in_target_language}
|
||||
# )
|
||||
|
||||
# for expression in sorted(translations.keys()):
|
||||
# for filename in translations[expression]:
|
||||
|
|
|
@ -63,7 +63,8 @@ def main():
|
|||
target, source, _ = collect_data(course)
|
||||
_show_banner()
|
||||
|
||||
# Randomly select a word or a phrase, show it, ask the user to type the answer, verify the answer
|
||||
# Randomly select a word or a phrase, show it
|
||||
# ask the user to type the answer, verify the answer
|
||||
|
||||
challenges = {
|
||||
"source_to_target_word": [0.1, lambda: guess_word(source_to_target_words)],
|
||||
|
|
2
pylintrc
2
pylintrc
|
@ -92,8 +92,6 @@ disable=raw-checker-failed,
|
|||
too-many-public-methods, # TODO: enable
|
||||
unspecified-encoding, # TODO: enable
|
||||
missing-module-docstring, # TODO: enable
|
||||
too-many-lines, # TODO: enable
|
||||
line-too-long, # TODO: enable
|
||||
import-outside-toplevel, # TODO: enable
|
||||
global-statement, # TODO: enable
|
||||
unnecessary-pass, # TODO: enable
|
||||
|
|
Loading…
Reference in New Issue