Compare commits
3 Commits
0ebf359647
...
2ffe2ac5f3
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ffe2ac5f3 | |||
| a51c2ec2e0 | |||
| 3c5b049b1f |
69
chatmastermind/commands/glossary.py
Normal file
69
chatmastermind/commands/glossary.py
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import sys
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
from ..configuration import Config
|
||||||
|
from ..glossary import Glossary
|
||||||
|
|
||||||
|
|
||||||
|
class GlossaryCmdError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def get_glossary_file(name: str, config: Config) -> Path:
|
||||||
|
"""
|
||||||
|
Get the complete filename for a glossary with the given path.
|
||||||
|
"""
|
||||||
|
if not config.glossaries:
|
||||||
|
raise GlossaryCmdError("Can't create glossary name without a glossary directory")
|
||||||
|
return Path(config.glossaries, name).with_suffix(Glossary.file_suffix).absolute()
|
||||||
|
|
||||||
|
|
||||||
|
def list_glossaries(args: argparse.Namespace, config: Config) -> None:
|
||||||
|
"""
|
||||||
|
List existing glossaries in the 'glossaries' directory.
|
||||||
|
"""
|
||||||
|
if not config.glossaries:
|
||||||
|
raise GlossaryCmdError("Glossaries directory missing in the configuration file")
|
||||||
|
glossaries = Path(config.glossaries).glob(f'*.{Glossary.file_suffix}')
|
||||||
|
for glo in glossaries:
|
||||||
|
print(Glossary.from_file(glo).to_str(args.entries))
|
||||||
|
|
||||||
|
|
||||||
|
def create_glossary(args: argparse.Namespace, config: Config) -> None:
|
||||||
|
"""
|
||||||
|
Create a new glossary and write it either to the glossaries directory
|
||||||
|
or the given file.
|
||||||
|
"""
|
||||||
|
# we need to know where the glossary should be stored
|
||||||
|
if config.glossaries is None and args.file is None:
|
||||||
|
raise GlossaryCmdError("Glossaries directory missing in the configuration file")
|
||||||
|
# sanity checks
|
||||||
|
if args.name is None:
|
||||||
|
print("Error: please specify the glossary name.")
|
||||||
|
sys.exit(1)
|
||||||
|
if args.source_lang is None:
|
||||||
|
print("Error: please specify the source language.")
|
||||||
|
sys.exit(1)
|
||||||
|
if args.target_lang is None:
|
||||||
|
print("Error: please specify the target language.")
|
||||||
|
sys.exit(1)
|
||||||
|
# create file or use the given one
|
||||||
|
glo_file = Path(args.file) if args.file else get_glossary_file(args.name, config)
|
||||||
|
if glo_file.exists():
|
||||||
|
print(f"Error: glossary '{glo_file}' already exists!")
|
||||||
|
sys.exit(1)
|
||||||
|
glo = Glossary(name=args.name,
|
||||||
|
source_lang=args.source_lang,
|
||||||
|
target_lang=args.target_lang,
|
||||||
|
desc=args.description,
|
||||||
|
file_path=glo_file)
|
||||||
|
glo.to_file()
|
||||||
|
print(f"Successfully created new glossary '{glo_file}'.")
|
||||||
|
|
||||||
|
|
||||||
|
def glossary_cmd(args: argparse.Namespace, config: Config) -> None:
|
||||||
|
"""
|
||||||
|
Handler for the 'glossary' command.
|
||||||
|
"""
|
||||||
|
if args.create:
|
||||||
|
create_glossary(args, config)
|
||||||
@ -47,6 +47,10 @@ class Glossary:
|
|||||||
ID: str | None = None
|
ID: str | None = None
|
||||||
file_suffix: ClassVar[str] = '.glo'
|
file_suffix: ClassVar[str] = '.glo'
|
||||||
|
|
||||||
|
def __post_init__(self) -> None:
|
||||||
|
# FIXME: check for valid languages
|
||||||
|
pass
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_file(cls: Type[GlossaryInst], file_path: Path) -> GlossaryInst:
|
def from_file(cls: Type[GlossaryInst], file_path: Path) -> GlossaryInst:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -16,6 +16,7 @@ from .commands.config import config_cmd
|
|||||||
from .commands.hist import hist_cmd
|
from .commands.hist import hist_cmd
|
||||||
from .commands.print import print_cmd
|
from .commands.print import print_cmd
|
||||||
from .commands.translation import translation_cmd
|
from .commands.translation import translation_cmd
|
||||||
|
from .commands.glossary import glossary_cmd
|
||||||
from .chat import msg_location
|
from .chat import msg_location
|
||||||
|
|
||||||
|
|
||||||
@ -140,7 +141,7 @@ def create_parser() -> argparse.ArgumentParser:
|
|||||||
|
|
||||||
# 'translation' command parser
|
# 'translation' command parser
|
||||||
translation_cmd_parser = cmdparser.add_parser('translation', parents=[ai_parser, tag_parser],
|
translation_cmd_parser = cmdparser.add_parser('translation', parents=[ai_parser, tag_parser],
|
||||||
help="ask, create and repeat translations.",
|
help="Ask, create and repeat translations.",
|
||||||
aliases=['t'])
|
aliases=['t'])
|
||||||
translation_cmd_parser.set_defaults(func=translation_cmd)
|
translation_cmd_parser.set_defaults(func=translation_cmd)
|
||||||
translation_group = translation_cmd_parser.add_mutually_exclusive_group(required=True)
|
translation_group = translation_cmd_parser.add_mutually_exclusive_group(required=True)
|
||||||
@ -149,10 +150,25 @@ def create_parser() -> argparse.ArgumentParser:
|
|||||||
translation_group.add_argument('-r', '--repeat', nargs='*', help='Repeat a translation', metavar='MESSAGE')
|
translation_group.add_argument('-r', '--repeat', nargs='*', help='Repeat a translation', metavar='MESSAGE')
|
||||||
translation_cmd_parser.add_argument('-S', '--source-lang', help="Source language", metavar="LANGUAGE", required=True)
|
translation_cmd_parser.add_argument('-S', '--source-lang', help="Source language", metavar="LANGUAGE", required=True)
|
||||||
translation_cmd_parser.add_argument('-T', '--target-lang', help="Target language", metavar="LANGUAGE", required=True)
|
translation_cmd_parser.add_argument('-T', '--target-lang', help="Target language", metavar="LANGUAGE", required=True)
|
||||||
translation_cmd_parser.add_argument('-G', '--glossaries', nargs='+', help="List of glossaries", metavar="GLOSSARY")
|
translation_cmd_parser.add_argument('-G', '--glossaries', nargs='+', help="List of glossary names", metavar="GLOSSARY")
|
||||||
translation_cmd_parser.add_argument('-d', '--input-document', help="Document to translate", metavar="FILE")
|
translation_cmd_parser.add_argument('-d', '--input-document', help="Document to translate", metavar="FILE")
|
||||||
translation_cmd_parser.add_argument('-D', '--output-document', help="Path for the translated document", metavar="FILE")
|
translation_cmd_parser.add_argument('-D', '--output-document', help="Path for the translated document", metavar="FILE")
|
||||||
|
|
||||||
|
# 'glossary' command parser
|
||||||
|
glossary_cmd_parser = cmdparser.add_parser('glossary', parents=[ai_parser],
|
||||||
|
help="Manage glossaries.",
|
||||||
|
aliases=['g'])
|
||||||
|
glossary_cmd_parser.set_defaults(func=glossary_cmd)
|
||||||
|
glossary_group = glossary_cmd_parser.add_mutually_exclusive_group(required=True)
|
||||||
|
glossary_group.add_argument('-c', '--create', help='Create a glossary', action='store_true')
|
||||||
|
glossary_cmd_parser.add_argument('-n', '--name', help="Glossary name (not ID)", metavar="NAME")
|
||||||
|
glossary_cmd_parser.add_argument('-S', '--source-lang', help="Source language", metavar="LANGUAGE")
|
||||||
|
glossary_cmd_parser.add_argument('-T', '--target-lang', help="Target language", metavar="LANGUAGE")
|
||||||
|
glossary_cmd_parser.add_argument('-f', '--file', help='File path of the goven glossary', metavar='GLOSSARY_FILE')
|
||||||
|
glossary_cmd_parser.add_argument('-D', '--description', help="Glossary description", metavar="DESCRIPTION")
|
||||||
|
glossary_group.add_argument('-l', '--list', help='List existing glossaries', action='store_true')
|
||||||
|
glossary_cmd_parser.add_argument('-E', '--entries', help="Print entries when listing glossaries", action='store_true')
|
||||||
|
|
||||||
argcomplete.autocomplete(parser)
|
argcomplete.autocomplete(parser)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
|
|||||||
37
tests/test_glossary_cmd.py
Normal file
37
tests/test_glossary_cmd.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import unittest
|
||||||
|
import argparse
|
||||||
|
import tempfile
|
||||||
|
from chatmastermind.configuration import Config
|
||||||
|
from chatmastermind.commands.glossary import glossary_cmd, GlossaryCmdError
|
||||||
|
|
||||||
|
|
||||||
|
class TestGlossaryCmd(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
# create DB and cache
|
||||||
|
self.db_dir = tempfile.TemporaryDirectory()
|
||||||
|
self.cache_dir = tempfile.TemporaryDirectory()
|
||||||
|
self.glossaries_dir = tempfile.TemporaryDirectory()
|
||||||
|
# create configuration
|
||||||
|
self.config = Config()
|
||||||
|
self.config.cache = self.cache_dir.name
|
||||||
|
self.config.db = self.db_dir.name
|
||||||
|
self.config.glossaries = self.glossaries_dir.name
|
||||||
|
# create a mock argparse.Namespace
|
||||||
|
self.args = argparse.Namespace(
|
||||||
|
create=True,
|
||||||
|
list=False,
|
||||||
|
name='new_glossary',
|
||||||
|
file=None,
|
||||||
|
source_lang='en',
|
||||||
|
target_lang='de',
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_glossary_cmd_no_glossaries_err(self) -> None:
|
||||||
|
"""
|
||||||
|
Test calling the glossary command without a glossaries directory.
|
||||||
|
"""
|
||||||
|
self.config.glossaries = None
|
||||||
|
with self.assertRaises(GlossaryCmdError) as err:
|
||||||
|
glossary_cmd(self.args, self.config)
|
||||||
|
self.assertIn(str(err.exception).lower(), "glossaries directory missing")
|
||||||
Loading…
x
Reference in New Issue
Block a user