From c5cd1cd9f5a514a4298f073a29a935ff88a18420 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 23 Aug 2021 15:53:02 -0400 Subject: [PATCH 01/15] Add Typer CLI App code --- typer-cli-python/README.md | 94 ++++++++ typer-cli-python/source_code_final/README.md | 94 ++++++++ .../source_code_final/requirements.txt | 3 + .../source_code_final/rptodo/__init__.py | 22 ++ .../source_code_final/rptodo/__main__.py | 11 + .../source_code_final/rptodo/cli.py | 217 ++++++++++++++++++ .../source_code_final/rptodo/config.py | 45 ++++ .../source_code_final/rptodo/database.py | 56 +++++ .../source_code_final/rptodo/rptodo.py | 69 ++++++ .../source_code_final/tests/__init__.py | 0 .../source_code_final/tests/test_rptodo.py | 151 ++++++++++++ typer-cli-python/source_code_step_1/README.md | 0 .../source_code_step_1/rptodo/__init__.py | 0 .../source_code_step_1/rptodo/__main__.py | 0 .../source_code_step_1/rptodo/cli.py | 0 .../source_code_step_1/rptodo/config.py | 0 .../source_code_step_1/rptodo/database.py | 0 .../source_code_step_1/rptodo/rptodo.py | 0 .../source_code_step_1/tests/__init__.py | 0 .../source_code_step_1/tests/test_rptodo.py | 0 typer-cli-python/source_code_step_2/README.md | 0 .../source_code_step_2/rptodo/__init__.py | 22 ++ .../source_code_step_2/rptodo/__main__.py | 11 + .../source_code_step_2/rptodo/cli.py | 29 +++ .../source_code_step_2/rptodo/config.py | 0 .../source_code_step_2/rptodo/database.py | 0 .../source_code_step_2/rptodo/rptodo.py | 0 .../source_code_step_2/tests/__init__.py | 0 .../source_code_step_2/tests/test_rptodo.py | 11 + typer-cli-python/source_code_step_3/README.md | 0 .../source_code_step_3/rptodo/__init__.py | 22 ++ .../source_code_step_3/rptodo/__main__.py | 11 + .../source_code_step_3/rptodo/cli.py | 58 +++++ .../source_code_step_3/rptodo/config.py | 45 ++++ .../source_code_step_3/rptodo/database.py | 26 +++ .../source_code_step_3/rptodo/rptodo.py | 0 .../source_code_step_3/tests/__init__.py | 0 .../source_code_step_3/tests/test_rptodo.py | 11 + typer-cli-python/source_code_step_4/README.md | 0 .../source_code_step_4/rptodo/__init__.py | 22 ++ .../source_code_step_4/rptodo/__main__.py | 11 + .../source_code_step_4/rptodo/cli.py | 58 +++++ .../source_code_step_4/rptodo/config.py | 45 ++++ .../source_code_step_4/rptodo/database.py | 56 +++++ .../source_code_step_4/rptodo/rptodo.py | 16 ++ .../source_code_step_4/tests/__init__.py | 0 .../source_code_step_4/tests/test_rptodo.py | 11 + typer-cli-python/source_code_step_5/README.md | 0 .../source_code_step_5/rptodo/__init__.py | 22 ++ .../source_code_step_5/rptodo/__main__.py | 11 + .../source_code_step_5/rptodo/cli.py | 130 +++++++++++ .../source_code_step_5/rptodo/config.py | 45 ++++ .../source_code_step_5/rptodo/database.py | 56 +++++ .../source_code_step_5/rptodo/rptodo.py | 39 ++++ .../source_code_step_5/tests/__init__.py | 0 .../source_code_step_5/tests/test_rptodo.py | 104 +++++++++ typer-cli-python/source_code_step_6/README.md | 0 .../source_code_step_6/rptodo/__init__.py | 22 ++ .../source_code_step_6/rptodo/__main__.py | 11 + .../source_code_step_6/rptodo/cli.py | 148 ++++++++++++ .../source_code_step_6/rptodo/config.py | 45 ++++ .../source_code_step_6/rptodo/database.py | 56 +++++ .../source_code_step_6/rptodo/rptodo.py | 52 +++++ .../source_code_step_6/tests/__init__.py | 0 .../source_code_step_6/tests/test_rptodo.py | 124 ++++++++++ typer-cli-python/source_code_step_7/README.md | 0 .../source_code_step_7/rptodo/__init__.py | 22 ++ .../source_code_step_7/rptodo/__main__.py | 11 + .../source_code_step_7/rptodo/cli.py | 217 ++++++++++++++++++ .../source_code_step_7/rptodo/config.py | 45 ++++ .../source_code_step_7/rptodo/database.py | 56 +++++ .../source_code_step_7/rptodo/rptodo.py | 69 ++++++ .../source_code_step_7/tests/__init__.py | 0 .../source_code_step_7/tests/test_rptodo.py | 149 ++++++++++++ 74 files changed, 2661 insertions(+) create mode 100644 typer-cli-python/README.md create mode 100644 typer-cli-python/source_code_final/README.md create mode 100644 typer-cli-python/source_code_final/requirements.txt create mode 100644 typer-cli-python/source_code_final/rptodo/__init__.py create mode 100644 typer-cli-python/source_code_final/rptodo/__main__.py create mode 100644 typer-cli-python/source_code_final/rptodo/cli.py create mode 100644 typer-cli-python/source_code_final/rptodo/config.py create mode 100644 typer-cli-python/source_code_final/rptodo/database.py create mode 100644 typer-cli-python/source_code_final/rptodo/rptodo.py create mode 100644 typer-cli-python/source_code_final/tests/__init__.py create mode 100644 typer-cli-python/source_code_final/tests/test_rptodo.py create mode 100644 typer-cli-python/source_code_step_1/README.md create mode 100644 typer-cli-python/source_code_step_1/rptodo/__init__.py create mode 100644 typer-cli-python/source_code_step_1/rptodo/__main__.py create mode 100644 typer-cli-python/source_code_step_1/rptodo/cli.py create mode 100644 typer-cli-python/source_code_step_1/rptodo/config.py create mode 100644 typer-cli-python/source_code_step_1/rptodo/database.py create mode 100644 typer-cli-python/source_code_step_1/rptodo/rptodo.py create mode 100644 typer-cli-python/source_code_step_1/tests/__init__.py create mode 100644 typer-cli-python/source_code_step_1/tests/test_rptodo.py create mode 100644 typer-cli-python/source_code_step_2/README.md create mode 100644 typer-cli-python/source_code_step_2/rptodo/__init__.py create mode 100644 typer-cli-python/source_code_step_2/rptodo/__main__.py create mode 100644 typer-cli-python/source_code_step_2/rptodo/cli.py create mode 100644 typer-cli-python/source_code_step_2/rptodo/config.py create mode 100644 typer-cli-python/source_code_step_2/rptodo/database.py create mode 100644 typer-cli-python/source_code_step_2/rptodo/rptodo.py create mode 100644 typer-cli-python/source_code_step_2/tests/__init__.py create mode 100644 typer-cli-python/source_code_step_2/tests/test_rptodo.py create mode 100644 typer-cli-python/source_code_step_3/README.md create mode 100644 typer-cli-python/source_code_step_3/rptodo/__init__.py create mode 100644 typer-cli-python/source_code_step_3/rptodo/__main__.py create mode 100644 typer-cli-python/source_code_step_3/rptodo/cli.py create mode 100644 typer-cli-python/source_code_step_3/rptodo/config.py create mode 100644 typer-cli-python/source_code_step_3/rptodo/database.py create mode 100644 typer-cli-python/source_code_step_3/rptodo/rptodo.py create mode 100644 typer-cli-python/source_code_step_3/tests/__init__.py create mode 100644 typer-cli-python/source_code_step_3/tests/test_rptodo.py create mode 100644 typer-cli-python/source_code_step_4/README.md create mode 100644 typer-cli-python/source_code_step_4/rptodo/__init__.py create mode 100644 typer-cli-python/source_code_step_4/rptodo/__main__.py create mode 100644 typer-cli-python/source_code_step_4/rptodo/cli.py create mode 100644 typer-cli-python/source_code_step_4/rptodo/config.py create mode 100644 typer-cli-python/source_code_step_4/rptodo/database.py create mode 100644 typer-cli-python/source_code_step_4/rptodo/rptodo.py create mode 100644 typer-cli-python/source_code_step_4/tests/__init__.py create mode 100644 typer-cli-python/source_code_step_4/tests/test_rptodo.py create mode 100644 typer-cli-python/source_code_step_5/README.md create mode 100644 typer-cli-python/source_code_step_5/rptodo/__init__.py create mode 100644 typer-cli-python/source_code_step_5/rptodo/__main__.py create mode 100644 typer-cli-python/source_code_step_5/rptodo/cli.py create mode 100644 typer-cli-python/source_code_step_5/rptodo/config.py create mode 100644 typer-cli-python/source_code_step_5/rptodo/database.py create mode 100644 typer-cli-python/source_code_step_5/rptodo/rptodo.py create mode 100644 typer-cli-python/source_code_step_5/tests/__init__.py create mode 100644 typer-cli-python/source_code_step_5/tests/test_rptodo.py create mode 100644 typer-cli-python/source_code_step_6/README.md create mode 100644 typer-cli-python/source_code_step_6/rptodo/__init__.py create mode 100644 typer-cli-python/source_code_step_6/rptodo/__main__.py create mode 100644 typer-cli-python/source_code_step_6/rptodo/cli.py create mode 100644 typer-cli-python/source_code_step_6/rptodo/config.py create mode 100644 typer-cli-python/source_code_step_6/rptodo/database.py create mode 100644 typer-cli-python/source_code_step_6/rptodo/rptodo.py create mode 100644 typer-cli-python/source_code_step_6/tests/__init__.py create mode 100644 typer-cli-python/source_code_step_6/tests/test_rptodo.py create mode 100644 typer-cli-python/source_code_step_7/README.md create mode 100644 typer-cli-python/source_code_step_7/rptodo/__init__.py create mode 100644 typer-cli-python/source_code_step_7/rptodo/__main__.py create mode 100644 typer-cli-python/source_code_step_7/rptodo/cli.py create mode 100644 typer-cli-python/source_code_step_7/rptodo/config.py create mode 100644 typer-cli-python/source_code_step_7/rptodo/database.py create mode 100644 typer-cli-python/source_code_step_7/rptodo/rptodo.py create mode 100644 typer-cli-python/source_code_step_7/tests/__init__.py create mode 100644 typer-cli-python/source_code_step_7/tests/test_rptodo.py diff --git a/typer-cli-python/README.md b/typer-cli-python/README.md new file mode 100644 index 0000000000..afbd917a0f --- /dev/null +++ b/typer-cli-python/README.md @@ -0,0 +1,94 @@ +# RP to-do + +**RP to-do** is a command-line interface application built with [Typer](https://typer.tiangolo.com/) to help you manage your to-do list. + +## Installation + +To run **RP to-do**, you need to run the following steps: + +1. Download the application's source code to a `rptodo_project/` directory +2. Create a Python virtual environment and activate it + +```sh +$ cd rptodo_project/ +$ python -m venv ./venv +$ source venv/bin/activate +(venv) $ +``` + +2. Install the dependencies + +```sh +(venv) $ python -m pip install -r requirements.txt +``` + +3. Initialize the application + +```sh +(venv) $ python -m rptodo init +``` + +This command asks you to introduce the file path to store the application's database. You can also accept the default file path by pressing enter. + +## Usage + +Once you've download the source code and run the installation steps, you can run the following command to access the application's usage description: + +```sh +$ python -m rptodo --help +Usage: rptodo [OPTIONS] COMMAND [ARGS]... + +Options: + -v, --version Show the application's version and exit. + --install-completion Install completion for the current shell. + --show-completion Show completion for the current shell, to copy it + or customize the installation. + + --help Show this message and exit. + +Commands: + add Add a new to-do with a DESCRIPTION. + init Initialize the to-do database. + list-all List all to-dos. + remove Remove a to-do using its TODO_ID. + remove-all Remove all to-dos. + set-done Set a to-do as done using its TODO_ID. +``` + +You can also access the help message for specific commands by typing the command and then `--help`. For example, to display the help content for the `add` command, you can run the following: + +```sh +$ python -m rptodo add --help +Usage: rptodo add [OPTIONS] DESCRIPTION... + + Add a new to-do with a DESCRIPTION. + +Arguments: + DESCRIPTION... [required] + +Options: + -p, --priority INTEGER RANGE [default: 2] + --help Show this message and exit. +``` + +Calling `--help` on each command provides specific and useful information about how to use the command at hand. + +## Features + +**RP to-do** has the following features: + +- **`init`** initializes the application's to-do database. +- **`add DESCRIPTION`** adds a new to-do to the database with a `DESCRIPTION`. +- **`list-all`** lists all the to-dos in the database. +- **`set-done TODO_ID`** set a to-do as done using its `TODO_ID`. +- **`remove TODO_ID`** remove a to-do from the database using its `TODO_ID`. +- **`remove-all`** remove all the to-dos in the database. + +## Release History + +- 0.1.0 + - A work in progress + +## About the Author + +Leodanis Pozo Ramos - Email: leodanis@realpython.com diff --git a/typer-cli-python/source_code_final/README.md b/typer-cli-python/source_code_final/README.md new file mode 100644 index 0000000000..afbd917a0f --- /dev/null +++ b/typer-cli-python/source_code_final/README.md @@ -0,0 +1,94 @@ +# RP to-do + +**RP to-do** is a command-line interface application built with [Typer](https://typer.tiangolo.com/) to help you manage your to-do list. + +## Installation + +To run **RP to-do**, you need to run the following steps: + +1. Download the application's source code to a `rptodo_project/` directory +2. Create a Python virtual environment and activate it + +```sh +$ cd rptodo_project/ +$ python -m venv ./venv +$ source venv/bin/activate +(venv) $ +``` + +2. Install the dependencies + +```sh +(venv) $ python -m pip install -r requirements.txt +``` + +3. Initialize the application + +```sh +(venv) $ python -m rptodo init +``` + +This command asks you to introduce the file path to store the application's database. You can also accept the default file path by pressing enter. + +## Usage + +Once you've download the source code and run the installation steps, you can run the following command to access the application's usage description: + +```sh +$ python -m rptodo --help +Usage: rptodo [OPTIONS] COMMAND [ARGS]... + +Options: + -v, --version Show the application's version and exit. + --install-completion Install completion for the current shell. + --show-completion Show completion for the current shell, to copy it + or customize the installation. + + --help Show this message and exit. + +Commands: + add Add a new to-do with a DESCRIPTION. + init Initialize the to-do database. + list-all List all to-dos. + remove Remove a to-do using its TODO_ID. + remove-all Remove all to-dos. + set-done Set a to-do as done using its TODO_ID. +``` + +You can also access the help message for specific commands by typing the command and then `--help`. For example, to display the help content for the `add` command, you can run the following: + +```sh +$ python -m rptodo add --help +Usage: rptodo add [OPTIONS] DESCRIPTION... + + Add a new to-do with a DESCRIPTION. + +Arguments: + DESCRIPTION... [required] + +Options: + -p, --priority INTEGER RANGE [default: 2] + --help Show this message and exit. +``` + +Calling `--help` on each command provides specific and useful information about how to use the command at hand. + +## Features + +**RP to-do** has the following features: + +- **`init`** initializes the application's to-do database. +- **`add DESCRIPTION`** adds a new to-do to the database with a `DESCRIPTION`. +- **`list-all`** lists all the to-dos in the database. +- **`set-done TODO_ID`** set a to-do as done using its `TODO_ID`. +- **`remove TODO_ID`** remove a to-do from the database using its `TODO_ID`. +- **`remove-all`** remove all the to-dos in the database. + +## Release History + +- 0.1.0 + - A work in progress + +## About the Author + +Leodanis Pozo Ramos - Email: leodanis@realpython.com diff --git a/typer-cli-python/source_code_final/requirements.txt b/typer-cli-python/source_code_final/requirements.txt new file mode 100644 index 0000000000..8aaab9a4ce --- /dev/null +++ b/typer-cli-python/source_code_final/requirements.txt @@ -0,0 +1,3 @@ +typer[all]==0.3.2 +poetry==1.1.7 +pytest==6.2.4 diff --git a/typer-cli-python/source_code_final/rptodo/__init__.py b/typer-cli-python/source_code_final/rptodo/__init__.py new file mode 100644 index 0000000000..fc5ba0e413 --- /dev/null +++ b/typer-cli-python/source_code_final/rptodo/__init__.py @@ -0,0 +1,22 @@ +"""Top-level package for RP to-do.""" + +__app_name__ = "rptodo" +__version__ = "0.1.0" + +( + SUCCESS, + DIR_ERROR, + FILE_ERROR, + DB_READ_ERROR, + DB_WRITE_ERROR, + JSON_ERROR, + ID_ERROR, +) = range(7) + +ERRORS = { + DIR_ERROR: "config directory error", + FILE_ERROR: "config file error", + DB_READ_ERROR: "database read error", + DB_WRITE_ERROR: "database write error", + ID_ERROR: "to-do id error", +} diff --git a/typer-cli-python/source_code_final/rptodo/__main__.py b/typer-cli-python/source_code_final/rptodo/__main__.py new file mode 100644 index 0000000000..79c8c51733 --- /dev/null +++ b/typer-cli-python/source_code_final/rptodo/__main__.py @@ -0,0 +1,11 @@ +"""RP to-do entry point script.""" + +from rptodo import cli, __app_name__ + + +def main(): + cli.app(prog_name=__app_name__) + + +if __name__ == "__main__": + main() diff --git a/typer-cli-python/source_code_final/rptodo/cli.py b/typer-cli-python/source_code_final/rptodo/cli.py new file mode 100644 index 0000000000..69c579a598 --- /dev/null +++ b/typer-cli-python/source_code_final/rptodo/cli.py @@ -0,0 +1,217 @@ +"""This module provides the RP to-do CLI.""" + +from pathlib import Path +from typing import List, Optional + +import typer + +from rptodo import ERRORS, __app_name__, __version__, config, database, rptodo + +app = typer.Typer() + + +@app.command() +def init( + db_path: str = typer.Option( + str(database.DEFAULT_DB_FILE_PATH), + "--db-path", + "-db", + prompt="to-do database location?", + ), +) -> None: + """Initialize the to-do database.""" + error = config.init_app(db_path) + if error: + typer.secho( + f'Creating config file failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + error = database.init_database(Path(db_path)) + if error: + typer.secho( + f'Creating database failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho(f"The to-do database is {db_path}", fg=typer.colors.GREEN) + + +def get_todoer() -> rptodo.Todoer: + if config.CONFIG_FILE_PATH.exists(): + db_path = database.get_database_path(config.CONFIG_FILE_PATH) + else: + typer.secho( + 'Config file not found. Please, run "rptodo init"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + if db_path.exists(): + return rptodo.Todoer(db_path) + else: + typer.secho( + 'Database not found. Please, run "rptodo init"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + + +@app.command() +def add( + description: List[str] = typer.Argument(...), + priority: int = typer.Option(2, "--priority", "-p", min=1, max=3), +) -> None: + """Add a new to-do with a DESCRIPTION.""" + todoer = get_todoer() + todo, error = todoer.add(description, priority) + if error: + typer.secho( + f'Adding to-do failed with "{ERRORS[error]}"', fg=typer.colors.RED + ) + raise typer.Exit(1) + else: + typer.secho( + f"""to-do: "{todo['Description']}" was added """ + f"""with priority: {priority}""", + fg=typer.colors.GREEN, + ) + + +@app.command() +def list_all() -> None: + """List all to-dos.""" + todoer = get_todoer() + todo_list = todoer.get_todo_list() + if len(todo_list) == 0: + typer.secho( + "There are no tasks in the to-do list yet", fg=typer.colors.RED + ) + raise typer.Exit() + typer.secho("\nto-do list:\n", fg=typer.colors.BLUE, bold=True) + columns = ( + "ID. ", + "| Priority ", + "| Done ", + "| Description ", + ) + headers = "".join(columns) + typer.secho(headers, fg=typer.colors.BLUE, bold=True) + typer.secho("-" * len(headers), fg=typer.colors.BLUE) + for id, todo in enumerate(todo_list, 1): + desc, priority, done = todo.values() + typer.secho( + f"{id}{(len(columns[0]) - len(str(id))) * ' '}" + f"| ({priority}){(len(columns[1]) - len(str(priority)) - 4) * ' '}" + f"| {done}{(len(columns[2]) - len(str(done)) - 2) * ' '}" + f"| {desc}", + fg=typer.colors.BLUE, + ) + typer.secho("-" * len(headers) + "\n", fg=typer.colors.BLUE) + + +@app.command() +def set_done(todo_id: int = typer.Argument(...)) -> None: + """Set a to-do as done using its TODO_ID.""" + todoer = get_todoer() + todo, error = todoer.set_done(todo_id) + if error: + typer.secho( + f'Setting to-do # "{todo_id}" done failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho( + f"""to-do # {todo_id} "{todo['Description']}" set done!""", + fg=typer.colors.GREEN, + ) + + +@app.command() +def remove( + todo_id: int = typer.Argument(...), + force: bool = typer.Option( + False, + "--force", + "-f", + help="Force deletion without confirmation.", + ), +) -> None: + """Remove a to-do using its TODO_ID.""" + todoer = get_todoer() + + def _remove(): + todo, error = todoer.remove(todo_id) + if error: + typer.secho( + f'Removing to-do # {todo_id} failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho( + f"""to-do # {todo_id}: '{todo["Description"]}' was removed""", + fg=typer.colors.GREEN, + ) + + if force: + _remove() + else: + todo_list = todoer.get_todo_list() + try: + todo = todo_list[todo_id - 1] + except IndexError: + typer.secho("Invalid TODO_ID", fg=typer.colors.RED) + raise typer.Exit(1) + delete = typer.confirm( + f"Delete to-do # {todo_id}: {todo['Description']}?" + ) + if delete: + _remove() + else: + typer.echo("Operation canceled") + + +@app.command() +def remove_all( + force: bool = typer.Option( + ..., + prompt="Delete all to-dos?", + help="Force deletion without confirmation.", + ), +) -> None: + """Remove all to-dos.""" + todoer = get_todoer() + if force: + error = todoer.remove_all().error + if error: + typer.secho( + f'Removing to-dos failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho("All to-dos were removed", fg=typer.colors.GREEN) + else: + typer.echo("Operation canceled") + + +def _version_callback(value: bool) -> None: + if value: + typer.echo(f"{__app_name__} v{__version__}") + raise typer.Exit() + + +@app.callback() +def main( + version: Optional[bool] = typer.Option( + None, + "--version", + "-v", + help="Show the application's version and exit.", + callback=_version_callback, + is_eager=True, + ) +) -> None: + return diff --git a/typer-cli-python/source_code_final/rptodo/config.py b/typer-cli-python/source_code_final/rptodo/config.py new file mode 100644 index 0000000000..1e0f8d545f --- /dev/null +++ b/typer-cli-python/source_code_final/rptodo/config.py @@ -0,0 +1,45 @@ +"""This module provides the RP to-do config functionality.""" + +import configparser +from pathlib import Path + +import typer + +from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ + +CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) +CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" + + +def init_app(db_path: str) -> int: + """Initialize the application.""" + config = _init_config_file() + if config != SUCCESS: + return config + database = _create_database(db_path) + if database != SUCCESS: + return database + return SUCCESS + + +def _init_config_file() -> int: + try: + CONFIG_DIR_PATH.mkdir(exist_ok=True) + except OSError: + return DIR_ERROR + try: + CONFIG_FILE_PATH.touch(exist_ok=True) + except OSError: + return FILE_ERROR + return SUCCESS + + +def _create_database(db_path: str) -> int: + config_parser = configparser.ConfigParser() + config_parser["General"] = {"database": db_path} + try: + with CONFIG_FILE_PATH.open("w") as file: + config_parser.write(file) + except OSError: + return DB_WRITE_ERROR + return SUCCESS diff --git a/typer-cli-python/source_code_final/rptodo/database.py b/typer-cli-python/source_code_final/rptodo/database.py new file mode 100644 index 0000000000..4865ec2a5a --- /dev/null +++ b/typer-cli-python/source_code_final/rptodo/database.py @@ -0,0 +1,56 @@ +"""This module provides the RP to-do database functionality.""" + +import configparser +import json +from pathlib import Path +from typing import Any, Dict, List, NamedTuple + +from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS + +DEFAULT_DB_FILE_PATH = Path.home().joinpath( + "." + Path.home().stem + "_todo.json" +) + + +def get_database_path(config_file: Path) -> Path: + """Return the current path to the to-do database.""" + config_parser = configparser.ConfigParser() + config_parser.read(config_file) + return Path(config_parser["General"]["database"]) + + +def init_database(db_path: Path) -> int: + """Create the to-do database.""" + try: + db_path.write_text("[]") # Empty to-do list + return SUCCESS + except OSError: + return DB_WRITE_ERROR + + +class DBResponse(NamedTuple): + todo_list: List[Dict[str, Any]] + error: int + + +class DatabaseHandler: + def __init__(self, db_path: Path) -> None: + self._db_path = db_path + + def read_todos(self) -> DBResponse: + try: + with self._db_path.open("r") as db: + try: + return DBResponse(json.load(db), SUCCESS) + except json.JSONDecodeError: # Catch wrong JSON format + return DBResponse([], JSON_ERROR) + except OSError: # Catch file IO problems + return DBResponse([], DB_READ_ERROR) + + def write_todos(self, todo_list: List[Dict[str, Any]]) -> DBResponse: + try: + with self._db_path.open("w") as db: + json.dump(todo_list, db, indent=4) + return DBResponse(todo_list, SUCCESS) + except OSError: # Catch file IO problems + return DBResponse(todo_list, DB_WRITE_ERROR) diff --git a/typer-cli-python/source_code_final/rptodo/rptodo.py b/typer-cli-python/source_code_final/rptodo/rptodo.py new file mode 100644 index 0000000000..d7e52b87ea --- /dev/null +++ b/typer-cli-python/source_code_final/rptodo/rptodo.py @@ -0,0 +1,69 @@ +"""This module provides the RP to-do model-controller.""" + +from pathlib import Path +from typing import Any, Dict, List, NamedTuple + +from . import DB_READ_ERROR, ID_ERROR +from .database import DatabaseHandler + + +class CurrentTodo(NamedTuple): + todo: Dict[str, Any] + error: int + + +class Todoer: + def __init__(self, db_path: Path) -> None: + self._db_handler = DatabaseHandler(db_path) + + def add(self, description: List[str], priority: int = 2) -> CurrentTodo: + """Add a new to-do to the database.""" + description_text = " ".join(description) + if not description_text.endswith("."): + description_text += "." + todo = { + "Description": description_text, + "Priority": priority, + "Done": False, + } + read = self._db_handler.read_todos() + if read.error == DB_READ_ERROR: + return CurrentTodo(todo, read.error) + read.todo_list.append(todo) + write = self._db_handler.write_todos(read.todo_list) + return CurrentTodo(todo, write.error) + + def get_todo_list(self) -> List[Dict[str, Any]]: + """Return the current to-do list.""" + read = self._db_handler.read_todos() + return read.todo_list + + def set_done(self, todo_id: int) -> CurrentTodo: + """Set a to-do as done.""" + read = self._db_handler.read_todos() + if read.error: + return CurrentTodo({}, read.error) + try: + todo = read.todo_list[todo_id - 1] + except IndexError: + return CurrentTodo({}, ID_ERROR) + todo["Done"] = True + write = self._db_handler.write_todos(read.todo_list) + return CurrentTodo(todo, write.error) + + def remove(self, todo_id: int) -> CurrentTodo: + """Remove a to-do from the database using its id or index.""" + read = self._db_handler.read_todos() + if read.error: + return CurrentTodo({}, read.error) + try: + todo = read.todo_list.pop(todo_id - 1) + except IndexError: + return CurrentTodo({}, ID_ERROR) + write = self._db_handler.write_todos(read.todo_list) + return CurrentTodo(todo, write.error) + + def remove_all(self) -> CurrentTodo: + """Remove all to-dos from the database.""" + write = self._db_handler.write_todos([]) + return CurrentTodo({}, write.error) diff --git a/typer-cli-python/source_code_final/tests/__init__.py b/typer-cli-python/source_code_final/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_final/tests/test_rptodo.py b/typer-cli-python/source_code_final/tests/test_rptodo.py new file mode 100644 index 0000000000..60a2657db6 --- /dev/null +++ b/typer-cli-python/source_code_final/tests/test_rptodo.py @@ -0,0 +1,151 @@ +import json + +import pytest +from typer.testing import CliRunner + +from rptodo import ( + cli, + __app_name__, + __version__, + rptodo, + SUCCESS, + DB_READ_ERROR, + ID_ERROR, +) + + +runner = CliRunner() + + +def test_version(): + result = runner.invoke(cli.app, ["--version"]) + assert result.exit_code == 0 + assert f"{__app_name__} v{__version__}\n" in result.stdout + + +@pytest.fixture +def mock_json_file(tmp_path): + todo = [{"Description": "buy some milk.", "Priority": 2, "Done": False}] + db_file = tmp_path / "todo.json" + with db_file.open("w") as db: + json.dump(todo, db, indent=4) + return db_file + + +test_data1 = { + "description": ["clean", "the", "house"], + "priority": 1, + "todo": { + "Description": "clean the house.", + "Priority": 1, + "Done": False, + }, +} +test_data2 = { + "description": ["go for a walk"], + "priority": 2, + "todo": { + "Description": "go for a walk.", + "Priority": 2, + "Done": False, + }, +} + + +@pytest.mark.parametrize( + "description, priority, expected", + [ + pytest.param( + test_data1["description"], + test_data1["priority"], + (test_data1["todo"], SUCCESS), + ), + pytest.param( + test_data2["description"], + test_data2["priority"], + (test_data2["todo"], SUCCESS), + ), + ], +) +def test_add(mock_json_file, description, priority, expected): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.add(description, priority) == expected + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 2 + + +@pytest.fixture +def mock_wrong_json_file(tmp_path): + db_file = tmp_path / "todo.json" + return db_file + + +def test_add_wrong_json_file(mock_wrong_json_file): + todoer = rptodo.Todoer(mock_wrong_json_file) + response = todoer.add(["test task"], 1) + assert response.error == DB_READ_ERROR + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 0 + + +@pytest.fixture +def mock_wrong_json_format(tmp_path): + db_file = tmp_path / "todo.json" + with db_file.open("w") as db: + db.write("") + return db_file + + +def test_add_wrong_json_format(mock_wrong_json_format): + todoer = rptodo.Todoer(mock_wrong_json_format) + assert todoer.add(test_data1["description"], test_data1["priority"]) == ( + test_data1["todo"], + SUCCESS, + ) + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 1 + + +test_todo1 = { + "Description": "buy some milk.", + "Priority": 2, + "Done": True, +} +test_todo2 = {} + + +@pytest.mark.parametrize( + "todo_id, expected", + [ + pytest.param(1, (test_todo1, SUCCESS)), + pytest.param(3, (test_todo2, ID_ERROR)), + ], +) +def test_set_done(mock_json_file, todo_id, expected): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.set_done(todo_id) == expected + + +test_todo3 = { + "Description": "buy some milk.", + "Priority": 2, + "Done": False, +} +test_todo4 = {} + + +@pytest.mark.parametrize( + "todo_id, expected", + [ + pytest.param(1, (test_todo3, SUCCESS)), + pytest.param(3, (test_todo4, ID_ERROR)), + ], +) +def test_remove(mock_json_file, todo_id, expected): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.remove(todo_id) == expected + + +def test_remove_all(mock_json_file): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.remove_all() == ({}, SUCCESS) diff --git a/typer-cli-python/source_code_step_1/README.md b/typer-cli-python/source_code_step_1/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_1/rptodo/__init__.py b/typer-cli-python/source_code_step_1/rptodo/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_1/rptodo/__main__.py b/typer-cli-python/source_code_step_1/rptodo/__main__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_1/rptodo/cli.py b/typer-cli-python/source_code_step_1/rptodo/cli.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_1/rptodo/config.py b/typer-cli-python/source_code_step_1/rptodo/config.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_1/rptodo/database.py b/typer-cli-python/source_code_step_1/rptodo/database.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_1/rptodo/rptodo.py b/typer-cli-python/source_code_step_1/rptodo/rptodo.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_1/tests/__init__.py b/typer-cli-python/source_code_step_1/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_1/tests/test_rptodo.py b/typer-cli-python/source_code_step_1/tests/test_rptodo.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_2/README.md b/typer-cli-python/source_code_step_2/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_2/rptodo/__init__.py b/typer-cli-python/source_code_step_2/rptodo/__init__.py new file mode 100644 index 0000000000..fc5ba0e413 --- /dev/null +++ b/typer-cli-python/source_code_step_2/rptodo/__init__.py @@ -0,0 +1,22 @@ +"""Top-level package for RP to-do.""" + +__app_name__ = "rptodo" +__version__ = "0.1.0" + +( + SUCCESS, + DIR_ERROR, + FILE_ERROR, + DB_READ_ERROR, + DB_WRITE_ERROR, + JSON_ERROR, + ID_ERROR, +) = range(7) + +ERRORS = { + DIR_ERROR: "config directory error", + FILE_ERROR: "config file error", + DB_READ_ERROR: "database read error", + DB_WRITE_ERROR: "database write error", + ID_ERROR: "to-do id error", +} diff --git a/typer-cli-python/source_code_step_2/rptodo/__main__.py b/typer-cli-python/source_code_step_2/rptodo/__main__.py new file mode 100644 index 0000000000..79c8c51733 --- /dev/null +++ b/typer-cli-python/source_code_step_2/rptodo/__main__.py @@ -0,0 +1,11 @@ +"""RP to-do entry point script.""" + +from rptodo import cli, __app_name__ + + +def main(): + cli.app(prog_name=__app_name__) + + +if __name__ == "__main__": + main() diff --git a/typer-cli-python/source_code_step_2/rptodo/cli.py b/typer-cli-python/source_code_step_2/rptodo/cli.py new file mode 100644 index 0000000000..cc9cb737e1 --- /dev/null +++ b/typer-cli-python/source_code_step_2/rptodo/cli.py @@ -0,0 +1,29 @@ +"""This module provides the RP to-do CLI.""" + +from typing import Optional + +import typer + +from rptodo import __app_name__, __version__ + +app = typer.Typer() + + +def _version_callback(value: bool) -> None: + if value: + typer.echo(f"{__app_name__} v{__version__}") + raise typer.Exit() + + +@app.callback() +def main( + version: Optional[bool] = typer.Option( + None, + "--version", + "-v", + help="Show the application's version and exit.", + callback=_version_callback, + is_eager=True, + ) +) -> None: + return diff --git a/typer-cli-python/source_code_step_2/rptodo/config.py b/typer-cli-python/source_code_step_2/rptodo/config.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_2/rptodo/database.py b/typer-cli-python/source_code_step_2/rptodo/database.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_2/rptodo/rptodo.py b/typer-cli-python/source_code_step_2/rptodo/rptodo.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_2/tests/__init__.py b/typer-cli-python/source_code_step_2/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_2/tests/test_rptodo.py b/typer-cli-python/source_code_step_2/tests/test_rptodo.py new file mode 100644 index 0000000000..d86d142ec2 --- /dev/null +++ b/typer-cli-python/source_code_step_2/tests/test_rptodo.py @@ -0,0 +1,11 @@ +from typer.testing import CliRunner + +from rptodo import __app_name__, __version__, cli + +runner = CliRunner() + + +def test_version(): + result = runner.invoke(cli.app, ["--version"]) + assert result.exit_code == 0 + assert f"{__app_name__} v{__version__}\n" in result.stdout diff --git a/typer-cli-python/source_code_step_3/README.md b/typer-cli-python/source_code_step_3/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_3/rptodo/__init__.py b/typer-cli-python/source_code_step_3/rptodo/__init__.py new file mode 100644 index 0000000000..fc5ba0e413 --- /dev/null +++ b/typer-cli-python/source_code_step_3/rptodo/__init__.py @@ -0,0 +1,22 @@ +"""Top-level package for RP to-do.""" + +__app_name__ = "rptodo" +__version__ = "0.1.0" + +( + SUCCESS, + DIR_ERROR, + FILE_ERROR, + DB_READ_ERROR, + DB_WRITE_ERROR, + JSON_ERROR, + ID_ERROR, +) = range(7) + +ERRORS = { + DIR_ERROR: "config directory error", + FILE_ERROR: "config file error", + DB_READ_ERROR: "database read error", + DB_WRITE_ERROR: "database write error", + ID_ERROR: "to-do id error", +} diff --git a/typer-cli-python/source_code_step_3/rptodo/__main__.py b/typer-cli-python/source_code_step_3/rptodo/__main__.py new file mode 100644 index 0000000000..79c8c51733 --- /dev/null +++ b/typer-cli-python/source_code_step_3/rptodo/__main__.py @@ -0,0 +1,11 @@ +"""RP to-do entry point script.""" + +from rptodo import cli, __app_name__ + + +def main(): + cli.app(prog_name=__app_name__) + + +if __name__ == "__main__": + main() diff --git a/typer-cli-python/source_code_step_3/rptodo/cli.py b/typer-cli-python/source_code_step_3/rptodo/cli.py new file mode 100644 index 0000000000..42f994e7d8 --- /dev/null +++ b/typer-cli-python/source_code_step_3/rptodo/cli.py @@ -0,0 +1,58 @@ +"""This module provides the RP to-do CLI.""" + +from pathlib import Path +from typing import Optional + +import typer + +from rptodo import ERRORS, __app_name__, __version__, config, database + +app = typer.Typer() + + +@app.command() +def init( + db_path: str = typer.Option( + str(database.DEFAULT_DB_FILE_PATH), + "--db-path", + "-db", + prompt="to-do database location?", + ), +) -> None: + """Initialize the to-do database.""" + error = config.init_app(db_path) + if error: + typer.secho( + f'Creating config file failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + error = database.init_database(Path(db_path)) + if error: + typer.secho( + f'Creating database failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho(f"The to-do database is {db_path}", fg=typer.colors.GREEN) + + +def _version_callback(value: bool) -> None: + if value: + typer.echo(f"{__app_name__} v{__version__}") + raise typer.Exit() + + +@app.callback() +def main( + version: Optional[bool] = typer.Option( + None, + "--version", + "-v", + help="Show the application's version and exit.", + callback=_version_callback, + is_eager=True, + ) +) -> None: + return diff --git a/typer-cli-python/source_code_step_3/rptodo/config.py b/typer-cli-python/source_code_step_3/rptodo/config.py new file mode 100644 index 0000000000..1e0f8d545f --- /dev/null +++ b/typer-cli-python/source_code_step_3/rptodo/config.py @@ -0,0 +1,45 @@ +"""This module provides the RP to-do config functionality.""" + +import configparser +from pathlib import Path + +import typer + +from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ + +CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) +CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" + + +def init_app(db_path: str) -> int: + """Initialize the application.""" + config = _init_config_file() + if config != SUCCESS: + return config + database = _create_database(db_path) + if database != SUCCESS: + return database + return SUCCESS + + +def _init_config_file() -> int: + try: + CONFIG_DIR_PATH.mkdir(exist_ok=True) + except OSError: + return DIR_ERROR + try: + CONFIG_FILE_PATH.touch(exist_ok=True) + except OSError: + return FILE_ERROR + return SUCCESS + + +def _create_database(db_path: str) -> int: + config_parser = configparser.ConfigParser() + config_parser["General"] = {"database": db_path} + try: + with CONFIG_FILE_PATH.open("w") as file: + config_parser.write(file) + except OSError: + return DB_WRITE_ERROR + return SUCCESS diff --git a/typer-cli-python/source_code_step_3/rptodo/database.py b/typer-cli-python/source_code_step_3/rptodo/database.py new file mode 100644 index 0000000000..121307f96f --- /dev/null +++ b/typer-cli-python/source_code_step_3/rptodo/database.py @@ -0,0 +1,26 @@ +"""This module provides the RP to-do database functionality.""" + +import configparser +from pathlib import Path + +from . import DB_WRITE_ERROR, SUCCESS + +DEFAULT_DB_FILE_PATH = Path.home().joinpath( + "." + Path.home().stem + "_todo.json" +) + + +def get_database_path(config_file: Path) -> Path: + """Return the current path to the to-do database.""" + config_parser = configparser.ConfigParser() + config_parser.read(config_file) + return Path(config_parser["General"]["database"]) + + +def init_database(db_path: Path) -> int: + """Create the to-do database.""" + try: + db_path.write_text("[]") # Empty to-do list + return SUCCESS + except OSError: + return DB_WRITE_ERROR diff --git a/typer-cli-python/source_code_step_3/rptodo/rptodo.py b/typer-cli-python/source_code_step_3/rptodo/rptodo.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_3/tests/__init__.py b/typer-cli-python/source_code_step_3/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_3/tests/test_rptodo.py b/typer-cli-python/source_code_step_3/tests/test_rptodo.py new file mode 100644 index 0000000000..71946f5760 --- /dev/null +++ b/typer-cli-python/source_code_step_3/tests/test_rptodo.py @@ -0,0 +1,11 @@ +from typer.testing import CliRunner + +from rptodo import cli, __app_name__, __version__ + +runner = CliRunner() + + +def test_version(): + result = runner.invoke(cli.app, ["--version"]) + assert result.exit_code == 0 + assert f"{__app_name__} v{__version__}\n" in result.stdout diff --git a/typer-cli-python/source_code_step_4/README.md b/typer-cli-python/source_code_step_4/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_4/rptodo/__init__.py b/typer-cli-python/source_code_step_4/rptodo/__init__.py new file mode 100644 index 0000000000..fc5ba0e413 --- /dev/null +++ b/typer-cli-python/source_code_step_4/rptodo/__init__.py @@ -0,0 +1,22 @@ +"""Top-level package for RP to-do.""" + +__app_name__ = "rptodo" +__version__ = "0.1.0" + +( + SUCCESS, + DIR_ERROR, + FILE_ERROR, + DB_READ_ERROR, + DB_WRITE_ERROR, + JSON_ERROR, + ID_ERROR, +) = range(7) + +ERRORS = { + DIR_ERROR: "config directory error", + FILE_ERROR: "config file error", + DB_READ_ERROR: "database read error", + DB_WRITE_ERROR: "database write error", + ID_ERROR: "to-do id error", +} diff --git a/typer-cli-python/source_code_step_4/rptodo/__main__.py b/typer-cli-python/source_code_step_4/rptodo/__main__.py new file mode 100644 index 0000000000..79c8c51733 --- /dev/null +++ b/typer-cli-python/source_code_step_4/rptodo/__main__.py @@ -0,0 +1,11 @@ +"""RP to-do entry point script.""" + +from rptodo import cli, __app_name__ + + +def main(): + cli.app(prog_name=__app_name__) + + +if __name__ == "__main__": + main() diff --git a/typer-cli-python/source_code_step_4/rptodo/cli.py b/typer-cli-python/source_code_step_4/rptodo/cli.py new file mode 100644 index 0000000000..42f994e7d8 --- /dev/null +++ b/typer-cli-python/source_code_step_4/rptodo/cli.py @@ -0,0 +1,58 @@ +"""This module provides the RP to-do CLI.""" + +from pathlib import Path +from typing import Optional + +import typer + +from rptodo import ERRORS, __app_name__, __version__, config, database + +app = typer.Typer() + + +@app.command() +def init( + db_path: str = typer.Option( + str(database.DEFAULT_DB_FILE_PATH), + "--db-path", + "-db", + prompt="to-do database location?", + ), +) -> None: + """Initialize the to-do database.""" + error = config.init_app(db_path) + if error: + typer.secho( + f'Creating config file failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + error = database.init_database(Path(db_path)) + if error: + typer.secho( + f'Creating database failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho(f"The to-do database is {db_path}", fg=typer.colors.GREEN) + + +def _version_callback(value: bool) -> None: + if value: + typer.echo(f"{__app_name__} v{__version__}") + raise typer.Exit() + + +@app.callback() +def main( + version: Optional[bool] = typer.Option( + None, + "--version", + "-v", + help="Show the application's version and exit.", + callback=_version_callback, + is_eager=True, + ) +) -> None: + return diff --git a/typer-cli-python/source_code_step_4/rptodo/config.py b/typer-cli-python/source_code_step_4/rptodo/config.py new file mode 100644 index 0000000000..1e0f8d545f --- /dev/null +++ b/typer-cli-python/source_code_step_4/rptodo/config.py @@ -0,0 +1,45 @@ +"""This module provides the RP to-do config functionality.""" + +import configparser +from pathlib import Path + +import typer + +from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ + +CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) +CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" + + +def init_app(db_path: str) -> int: + """Initialize the application.""" + config = _init_config_file() + if config != SUCCESS: + return config + database = _create_database(db_path) + if database != SUCCESS: + return database + return SUCCESS + + +def _init_config_file() -> int: + try: + CONFIG_DIR_PATH.mkdir(exist_ok=True) + except OSError: + return DIR_ERROR + try: + CONFIG_FILE_PATH.touch(exist_ok=True) + except OSError: + return FILE_ERROR + return SUCCESS + + +def _create_database(db_path: str) -> int: + config_parser = configparser.ConfigParser() + config_parser["General"] = {"database": db_path} + try: + with CONFIG_FILE_PATH.open("w") as file: + config_parser.write(file) + except OSError: + return DB_WRITE_ERROR + return SUCCESS diff --git a/typer-cli-python/source_code_step_4/rptodo/database.py b/typer-cli-python/source_code_step_4/rptodo/database.py new file mode 100644 index 0000000000..4865ec2a5a --- /dev/null +++ b/typer-cli-python/source_code_step_4/rptodo/database.py @@ -0,0 +1,56 @@ +"""This module provides the RP to-do database functionality.""" + +import configparser +import json +from pathlib import Path +from typing import Any, Dict, List, NamedTuple + +from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS + +DEFAULT_DB_FILE_PATH = Path.home().joinpath( + "." + Path.home().stem + "_todo.json" +) + + +def get_database_path(config_file: Path) -> Path: + """Return the current path to the to-do database.""" + config_parser = configparser.ConfigParser() + config_parser.read(config_file) + return Path(config_parser["General"]["database"]) + + +def init_database(db_path: Path) -> int: + """Create the to-do database.""" + try: + db_path.write_text("[]") # Empty to-do list + return SUCCESS + except OSError: + return DB_WRITE_ERROR + + +class DBResponse(NamedTuple): + todo_list: List[Dict[str, Any]] + error: int + + +class DatabaseHandler: + def __init__(self, db_path: Path) -> None: + self._db_path = db_path + + def read_todos(self) -> DBResponse: + try: + with self._db_path.open("r") as db: + try: + return DBResponse(json.load(db), SUCCESS) + except json.JSONDecodeError: # Catch wrong JSON format + return DBResponse([], JSON_ERROR) + except OSError: # Catch file IO problems + return DBResponse([], DB_READ_ERROR) + + def write_todos(self, todo_list: List[Dict[str, Any]]) -> DBResponse: + try: + with self._db_path.open("w") as db: + json.dump(todo_list, db, indent=4) + return DBResponse(todo_list, SUCCESS) + except OSError: # Catch file IO problems + return DBResponse(todo_list, DB_WRITE_ERROR) diff --git a/typer-cli-python/source_code_step_4/rptodo/rptodo.py b/typer-cli-python/source_code_step_4/rptodo/rptodo.py new file mode 100644 index 0000000000..a05fcce4c8 --- /dev/null +++ b/typer-cli-python/source_code_step_4/rptodo/rptodo.py @@ -0,0 +1,16 @@ +"""This module provides the RP to-do model-controller.""" + +from pathlib import Path +from typing import Any, Dict, NamedTuple + +from .database import DatabaseHandler + + +class CurrentTodo(NamedTuple): + todo: Dict[str, Any] + error: int + + +class Todoer: + def __init__(self, db_path: Path) -> None: + self._db_handler = DatabaseHandler(db_path) diff --git a/typer-cli-python/source_code_step_4/tests/__init__.py b/typer-cli-python/source_code_step_4/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_4/tests/test_rptodo.py b/typer-cli-python/source_code_step_4/tests/test_rptodo.py new file mode 100644 index 0000000000..71946f5760 --- /dev/null +++ b/typer-cli-python/source_code_step_4/tests/test_rptodo.py @@ -0,0 +1,11 @@ +from typer.testing import CliRunner + +from rptodo import cli, __app_name__, __version__ + +runner = CliRunner() + + +def test_version(): + result = runner.invoke(cli.app, ["--version"]) + assert result.exit_code == 0 + assert f"{__app_name__} v{__version__}\n" in result.stdout diff --git a/typer-cli-python/source_code_step_5/README.md b/typer-cli-python/source_code_step_5/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_5/rptodo/__init__.py b/typer-cli-python/source_code_step_5/rptodo/__init__.py new file mode 100644 index 0000000000..fc5ba0e413 --- /dev/null +++ b/typer-cli-python/source_code_step_5/rptodo/__init__.py @@ -0,0 +1,22 @@ +"""Top-level package for RP to-do.""" + +__app_name__ = "rptodo" +__version__ = "0.1.0" + +( + SUCCESS, + DIR_ERROR, + FILE_ERROR, + DB_READ_ERROR, + DB_WRITE_ERROR, + JSON_ERROR, + ID_ERROR, +) = range(7) + +ERRORS = { + DIR_ERROR: "config directory error", + FILE_ERROR: "config file error", + DB_READ_ERROR: "database read error", + DB_WRITE_ERROR: "database write error", + ID_ERROR: "to-do id error", +} diff --git a/typer-cli-python/source_code_step_5/rptodo/__main__.py b/typer-cli-python/source_code_step_5/rptodo/__main__.py new file mode 100644 index 0000000000..79c8c51733 --- /dev/null +++ b/typer-cli-python/source_code_step_5/rptodo/__main__.py @@ -0,0 +1,11 @@ +"""RP to-do entry point script.""" + +from rptodo import cli, __app_name__ + + +def main(): + cli.app(prog_name=__app_name__) + + +if __name__ == "__main__": + main() diff --git a/typer-cli-python/source_code_step_5/rptodo/cli.py b/typer-cli-python/source_code_step_5/rptodo/cli.py new file mode 100644 index 0000000000..0350c34204 --- /dev/null +++ b/typer-cli-python/source_code_step_5/rptodo/cli.py @@ -0,0 +1,130 @@ +"""This module provides the RP to-do CLI.""" + +from pathlib import Path +from typing import List, Optional + +import typer + +from rptodo import ERRORS, __app_name__, __version__, config, database, rptodo + +app = typer.Typer() + + +@app.command() +def init( + db_path: str = typer.Option( + str(database.DEFAULT_DB_FILE_PATH), + "--db-path", + "-db", + prompt="to-do database location?", + ), +) -> None: + """Initialize the to-do database.""" + error = config.init_app(db_path) + if error: + typer.secho( + f'Creating config file failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + error = database.init_database(Path(db_path)) + if error: + typer.secho( + f'Creating database failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho(f"The to-do database is {db_path}", fg=typer.colors.GREEN) + + +def get_todoer() -> rptodo.Todoer: + if config.CONFIG_FILE_PATH.exists(): + db_path = database.get_database_path(config.CONFIG_FILE_PATH) + else: + typer.secho( + 'Config file not found. Please, run "rptodo init"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + if db_path.exists(): + return rptodo.Todoer(db_path) + else: + typer.secho( + 'Database not found. Please, run "rptodo init"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + + +@app.command() +def add( + description: List[str] = typer.Argument(...), + priority: int = typer.Option(2, "--priority", "-p", min=1, max=3), +) -> None: + """Add a new to-do with a DESCRIPTION.""" + todoer = get_todoer() + todo, error = todoer.add(description, priority) + if error: + typer.secho( + f'Adding to-do failed with "{ERRORS[error]}"', fg=typer.colors.RED + ) + raise typer.Exit(1) + else: + typer.secho( + f"""to-do: "{todo['Description']}" was added """ + f"""with priority: {priority}""", + fg=typer.colors.GREEN, + ) + + +@app.command() +def list_all() -> None: + """List all to-dos.""" + todoer = get_todoer() + todo_list = todoer.get_todo_list() + if len(todo_list) == 0: + typer.secho( + "There are no tasks in the to-do list yet", fg=typer.colors.RED + ) + raise typer.Exit() + typer.secho("\nto-do list:\n", fg=typer.colors.BLUE, bold=True) + columns = ( + "ID. ", + "| Priority ", + "| Done ", + "| Description ", + ) + headers = "".join(columns) + typer.secho(headers, fg=typer.colors.BLUE, bold=True) + typer.secho("-" * len(headers), fg=typer.colors.BLUE) + for id, todo in enumerate(todo_list, 1): + desc, priority, done = todo.values() + typer.secho( + f"{id}{(len(columns[0]) - len(str(id))) * ' '}" + f"| ({priority}){(len(columns[1]) - len(str(priority)) - 4) * ' '}" + f"| {done}{(len(columns[2]) - len(str(done)) - 2) * ' '}" + f"| {desc}", + fg=typer.colors.BLUE, + ) + typer.secho("-" * len(headers) + "\n", fg=typer.colors.BLUE) + + +def _version_callback(value: bool) -> None: + if value: + typer.echo(f"{__app_name__} v{__version__}") + raise typer.Exit() + + +@app.callback() +def main( + version: Optional[bool] = typer.Option( + None, + "--version", + "-v", + help="Show the application's version and exit.", + callback=_version_callback, + is_eager=True, + ) +) -> None: + return diff --git a/typer-cli-python/source_code_step_5/rptodo/config.py b/typer-cli-python/source_code_step_5/rptodo/config.py new file mode 100644 index 0000000000..1e0f8d545f --- /dev/null +++ b/typer-cli-python/source_code_step_5/rptodo/config.py @@ -0,0 +1,45 @@ +"""This module provides the RP to-do config functionality.""" + +import configparser +from pathlib import Path + +import typer + +from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ + +CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) +CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" + + +def init_app(db_path: str) -> int: + """Initialize the application.""" + config = _init_config_file() + if config != SUCCESS: + return config + database = _create_database(db_path) + if database != SUCCESS: + return database + return SUCCESS + + +def _init_config_file() -> int: + try: + CONFIG_DIR_PATH.mkdir(exist_ok=True) + except OSError: + return DIR_ERROR + try: + CONFIG_FILE_PATH.touch(exist_ok=True) + except OSError: + return FILE_ERROR + return SUCCESS + + +def _create_database(db_path: str) -> int: + config_parser = configparser.ConfigParser() + config_parser["General"] = {"database": db_path} + try: + with CONFIG_FILE_PATH.open("w") as file: + config_parser.write(file) + except OSError: + return DB_WRITE_ERROR + return SUCCESS diff --git a/typer-cli-python/source_code_step_5/rptodo/database.py b/typer-cli-python/source_code_step_5/rptodo/database.py new file mode 100644 index 0000000000..4865ec2a5a --- /dev/null +++ b/typer-cli-python/source_code_step_5/rptodo/database.py @@ -0,0 +1,56 @@ +"""This module provides the RP to-do database functionality.""" + +import configparser +import json +from pathlib import Path +from typing import Any, Dict, List, NamedTuple + +from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS + +DEFAULT_DB_FILE_PATH = Path.home().joinpath( + "." + Path.home().stem + "_todo.json" +) + + +def get_database_path(config_file: Path) -> Path: + """Return the current path to the to-do database.""" + config_parser = configparser.ConfigParser() + config_parser.read(config_file) + return Path(config_parser["General"]["database"]) + + +def init_database(db_path: Path) -> int: + """Create the to-do database.""" + try: + db_path.write_text("[]") # Empty to-do list + return SUCCESS + except OSError: + return DB_WRITE_ERROR + + +class DBResponse(NamedTuple): + todo_list: List[Dict[str, Any]] + error: int + + +class DatabaseHandler: + def __init__(self, db_path: Path) -> None: + self._db_path = db_path + + def read_todos(self) -> DBResponse: + try: + with self._db_path.open("r") as db: + try: + return DBResponse(json.load(db), SUCCESS) + except json.JSONDecodeError: # Catch wrong JSON format + return DBResponse([], JSON_ERROR) + except OSError: # Catch file IO problems + return DBResponse([], DB_READ_ERROR) + + def write_todos(self, todo_list: List[Dict[str, Any]]) -> DBResponse: + try: + with self._db_path.open("w") as db: + json.dump(todo_list, db, indent=4) + return DBResponse(todo_list, SUCCESS) + except OSError: # Catch file IO problems + return DBResponse(todo_list, DB_WRITE_ERROR) diff --git a/typer-cli-python/source_code_step_5/rptodo/rptodo.py b/typer-cli-python/source_code_step_5/rptodo/rptodo.py new file mode 100644 index 0000000000..80da4fe2ea --- /dev/null +++ b/typer-cli-python/source_code_step_5/rptodo/rptodo.py @@ -0,0 +1,39 @@ +"""This module provides the RP to-do model-controller.""" + +from pathlib import Path +from typing import Any, Dict, List, NamedTuple + +from . import DB_READ_ERROR +from .database import DatabaseHandler + + +class CurrentTodo(NamedTuple): + todo: Dict[str, Any] + error: int + + +class Todoer: + def __init__(self, db_path: Path) -> None: + self._db_handler = DatabaseHandler(db_path) + + def add(self, description: List[str], priority: int = 2) -> CurrentTodo: + """Add a new to-do to the database.""" + description_text = " ".join(description) + if not description_text.endswith("."): + description_text += "." + todo = { + "Description": description_text, + "Priority": priority, + "Done": False, + } + read = self._db_handler.read_todos() + if read.error == DB_READ_ERROR: + return CurrentTodo(todo, read.error) + read.todo_list.append(todo) + write = self._db_handler.write_todos(read.todo_list) + return CurrentTodo(todo, write.error) + + def get_todo_list(self) -> List[Dict[str, Any]]: + """Return the current to-do list.""" + read = self._db_handler.read_todos() + return read.todo_list diff --git a/typer-cli-python/source_code_step_5/tests/__init__.py b/typer-cli-python/source_code_step_5/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_5/tests/test_rptodo.py b/typer-cli-python/source_code_step_5/tests/test_rptodo.py new file mode 100644 index 0000000000..daa4fcb4f4 --- /dev/null +++ b/typer-cli-python/source_code_step_5/tests/test_rptodo.py @@ -0,0 +1,104 @@ +import json + +import pytest +from typer.testing import CliRunner + +from rptodo import ( + DB_READ_ERROR, + SUCCESS, + __app_name__, + __version__, + cli, + rptodo, +) + +runner = CliRunner() + + +def test_version(): + result = runner.invoke(cli.app, ["--version"]) + assert result.exit_code == 0 + assert f"{__app_name__} v{__version__}\n" in result.stdout + + +@pytest.fixture +def mock_json_file(tmp_path): + todo = [{"Description": "Get some milk.", "Priority": 2, "Done": False}] + db_file = tmp_path / "todo.json" + with db_file.open("w") as db: + json.dump(todo, db, indent=4) + return db_file + + +test_data1 = { + "description": ["Clean", "the", "house"], + "priority": 1, + "todo": { + "Description": "Clean the house.", + "Priority": 1, + "Done": False, + }, +} +test_data2 = { + "description": ["Wash the car"], + "priority": 2, + "todo": { + "Description": "Wash the car.", + "Priority": 2, + "Done": False, + }, +} + + +@pytest.mark.parametrize( + "description, priority, expected", + [ + pytest.param( + test_data1["description"], + test_data1["priority"], + (test_data1["todo"], SUCCESS), + ), + pytest.param( + test_data2["description"], + test_data2["priority"], + (test_data2["todo"], SUCCESS), + ), + ], +) +def test_add(mock_json_file, description, priority, expected): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.add(description, priority) == expected + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 2 + + +@pytest.fixture +def mock_wrong_json_file(tmp_path): + db_file = tmp_path / "todo.json" + return db_file + + +def test_add_wrong_json_file(mock_wrong_json_file): + todoer = rptodo.Todoer(mock_wrong_json_file) + response = todoer.add(["test task"], 1) + assert response.error == DB_READ_ERROR + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 0 + + +@pytest.fixture +def mock_wrong_json_format(tmp_path): + db_file = tmp_path / "todo.json" + with db_file.open("w") as db: + db.write("") + return db_file + + +def test_add_wrong_json_format(mock_wrong_json_format): + todoer = rptodo.Todoer(mock_wrong_json_format) + assert todoer.add(test_data1["description"], test_data1["priority"]) == ( + test_data1["todo"], + SUCCESS, + ) + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 1 diff --git a/typer-cli-python/source_code_step_6/README.md b/typer-cli-python/source_code_step_6/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_6/rptodo/__init__.py b/typer-cli-python/source_code_step_6/rptodo/__init__.py new file mode 100644 index 0000000000..fc5ba0e413 --- /dev/null +++ b/typer-cli-python/source_code_step_6/rptodo/__init__.py @@ -0,0 +1,22 @@ +"""Top-level package for RP to-do.""" + +__app_name__ = "rptodo" +__version__ = "0.1.0" + +( + SUCCESS, + DIR_ERROR, + FILE_ERROR, + DB_READ_ERROR, + DB_WRITE_ERROR, + JSON_ERROR, + ID_ERROR, +) = range(7) + +ERRORS = { + DIR_ERROR: "config directory error", + FILE_ERROR: "config file error", + DB_READ_ERROR: "database read error", + DB_WRITE_ERROR: "database write error", + ID_ERROR: "to-do id error", +} diff --git a/typer-cli-python/source_code_step_6/rptodo/__main__.py b/typer-cli-python/source_code_step_6/rptodo/__main__.py new file mode 100644 index 0000000000..79c8c51733 --- /dev/null +++ b/typer-cli-python/source_code_step_6/rptodo/__main__.py @@ -0,0 +1,11 @@ +"""RP to-do entry point script.""" + +from rptodo import cli, __app_name__ + + +def main(): + cli.app(prog_name=__app_name__) + + +if __name__ == "__main__": + main() diff --git a/typer-cli-python/source_code_step_6/rptodo/cli.py b/typer-cli-python/source_code_step_6/rptodo/cli.py new file mode 100644 index 0000000000..1924a28cb0 --- /dev/null +++ b/typer-cli-python/source_code_step_6/rptodo/cli.py @@ -0,0 +1,148 @@ +"""This module provides the RP to-do CLI.""" + +from pathlib import Path +from typing import List, Optional + +import typer + +from rptodo import ERRORS, __app_name__, __version__, config, database, rptodo + +app = typer.Typer() + + +@app.command() +def init( + db_path: str = typer.Option( + str(database.DEFAULT_DB_FILE_PATH), + "--db-path", + "-db", + prompt="to-do database location?", + ), +) -> None: + """Initialize the to-do database.""" + error = config.init_app(db_path) + if error: + typer.secho( + f'Creating config file failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + error = database.init_database(Path(db_path)) + if error: + typer.secho( + f'Creating database failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho(f"The to-do database is {db_path}", fg=typer.colors.GREEN) + + +def get_todoer() -> rptodo.Todoer: + if config.CONFIG_FILE_PATH.exists(): + db_path = database.get_database_path(config.CONFIG_FILE_PATH) + else: + typer.secho( + 'Config file not found. Please, run "rptodo init"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + if db_path.exists(): + return rptodo.Todoer(db_path) + else: + typer.secho( + 'Database not found. Please, run "rptodo init"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + + +@app.command() +def add( + description: List[str] = typer.Argument(...), + priority: int = typer.Option(2, "--priority", "-p", min=1, max=3), +) -> None: + """Add a new to-do with a DESCRIPTION.""" + todoer = get_todoer() + todo, error = todoer.add(description, priority) + if error: + typer.secho( + f'Adding to-do failed with "{ERRORS[error]}"', fg=typer.colors.RED + ) + raise typer.Exit(1) + else: + typer.secho( + f"""to-do: "{todo['Description']}" was added """ + f"""with priority: {priority}""", + fg=typer.colors.GREEN, + ) + + +@app.command() +def list_all() -> None: + """List all to-dos.""" + todoer = get_todoer() + todo_list = todoer.get_todo_list() + if len(todo_list) == 0: + typer.secho( + "There are no tasks in the to-do list yet", fg=typer.colors.RED + ) + raise typer.Exit() + typer.secho("\nto-do list:\n", fg=typer.colors.BLUE, bold=True) + columns = ( + "ID. ", + "| Priority ", + "| Done ", + "| Description ", + ) + headers = "".join(columns) + typer.secho(headers, fg=typer.colors.BLUE, bold=True) + typer.secho("-" * len(headers), fg=typer.colors.BLUE) + for id, todo in enumerate(todo_list, 1): + desc, priority, done = todo.values() + typer.secho( + f"{id}{(len(columns[0]) - len(str(id))) * ' '}" + f"| ({priority}){(len(columns[1]) - len(str(priority)) - 4) * ' '}" + f"| {done}{(len(columns[2]) - len(str(done)) - 2) * ' '}" + f"| {desc}", + fg=typer.colors.BLUE, + ) + typer.secho("-" * len(headers) + "\n", fg=typer.colors.BLUE) + + +@app.command() +def set_done(todo_id: int = typer.Argument(...)) -> None: + """Set a to-do as done using its TODO_ID.""" + todoer = get_todoer() + todo, error = todoer.set_done(todo_id) + if error: + typer.secho( + f'Setting to-do # "{todo_id}" done failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho( + f"""to-do # {todo_id} "{todo['Description']}" set done!""", + fg=typer.colors.GREEN, + ) + + +def _version_callback(value: bool) -> None: + if value: + typer.echo(f"{__app_name__} v{__version__}") + raise typer.Exit() + + +@app.callback() +def main( + version: Optional[bool] = typer.Option( + None, + "--version", + "-v", + help="Show the application's version and exit.", + callback=_version_callback, + is_eager=True, + ) +) -> None: + return diff --git a/typer-cli-python/source_code_step_6/rptodo/config.py b/typer-cli-python/source_code_step_6/rptodo/config.py new file mode 100644 index 0000000000..1e0f8d545f --- /dev/null +++ b/typer-cli-python/source_code_step_6/rptodo/config.py @@ -0,0 +1,45 @@ +"""This module provides the RP to-do config functionality.""" + +import configparser +from pathlib import Path + +import typer + +from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ + +CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) +CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" + + +def init_app(db_path: str) -> int: + """Initialize the application.""" + config = _init_config_file() + if config != SUCCESS: + return config + database = _create_database(db_path) + if database != SUCCESS: + return database + return SUCCESS + + +def _init_config_file() -> int: + try: + CONFIG_DIR_PATH.mkdir(exist_ok=True) + except OSError: + return DIR_ERROR + try: + CONFIG_FILE_PATH.touch(exist_ok=True) + except OSError: + return FILE_ERROR + return SUCCESS + + +def _create_database(db_path: str) -> int: + config_parser = configparser.ConfigParser() + config_parser["General"] = {"database": db_path} + try: + with CONFIG_FILE_PATH.open("w") as file: + config_parser.write(file) + except OSError: + return DB_WRITE_ERROR + return SUCCESS diff --git a/typer-cli-python/source_code_step_6/rptodo/database.py b/typer-cli-python/source_code_step_6/rptodo/database.py new file mode 100644 index 0000000000..4865ec2a5a --- /dev/null +++ b/typer-cli-python/source_code_step_6/rptodo/database.py @@ -0,0 +1,56 @@ +"""This module provides the RP to-do database functionality.""" + +import configparser +import json +from pathlib import Path +from typing import Any, Dict, List, NamedTuple + +from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS + +DEFAULT_DB_FILE_PATH = Path.home().joinpath( + "." + Path.home().stem + "_todo.json" +) + + +def get_database_path(config_file: Path) -> Path: + """Return the current path to the to-do database.""" + config_parser = configparser.ConfigParser() + config_parser.read(config_file) + return Path(config_parser["General"]["database"]) + + +def init_database(db_path: Path) -> int: + """Create the to-do database.""" + try: + db_path.write_text("[]") # Empty to-do list + return SUCCESS + except OSError: + return DB_WRITE_ERROR + + +class DBResponse(NamedTuple): + todo_list: List[Dict[str, Any]] + error: int + + +class DatabaseHandler: + def __init__(self, db_path: Path) -> None: + self._db_path = db_path + + def read_todos(self) -> DBResponse: + try: + with self._db_path.open("r") as db: + try: + return DBResponse(json.load(db), SUCCESS) + except json.JSONDecodeError: # Catch wrong JSON format + return DBResponse([], JSON_ERROR) + except OSError: # Catch file IO problems + return DBResponse([], DB_READ_ERROR) + + def write_todos(self, todo_list: List[Dict[str, Any]]) -> DBResponse: + try: + with self._db_path.open("w") as db: + json.dump(todo_list, db, indent=4) + return DBResponse(todo_list, SUCCESS) + except OSError: # Catch file IO problems + return DBResponse(todo_list, DB_WRITE_ERROR) diff --git a/typer-cli-python/source_code_step_6/rptodo/rptodo.py b/typer-cli-python/source_code_step_6/rptodo/rptodo.py new file mode 100644 index 0000000000..9021dd2c75 --- /dev/null +++ b/typer-cli-python/source_code_step_6/rptodo/rptodo.py @@ -0,0 +1,52 @@ +"""This module provides the RP to-do model-controller.""" + +from pathlib import Path +from typing import Any, Dict, List, NamedTuple + +from . import DB_READ_ERROR, ID_ERROR +from .database import DatabaseHandler + + +class CurrentTodo(NamedTuple): + todo: Dict[str, Any] + error: int + + +class Todoer: + def __init__(self, db_path: Path) -> None: + self._db_handler = DatabaseHandler(db_path) + + def add(self, description: List[str], priority: int = 2) -> CurrentTodo: + """Add a new to-do to the database.""" + description_text = " ".join(description) + if not description_text.endswith("."): + description_text += "." + todo = { + "Description": description_text, + "Priority": priority, + "Done": False, + } + read = self._db_handler.read_todos() + if read.error == DB_READ_ERROR: + return CurrentTodo(todo, read.error) + read.todo_list.append(todo) + write = self._db_handler.write_todos(read.todo_list) + return CurrentTodo(todo, write.error) + + def get_todo_list(self) -> List[Dict[str, Any]]: + """Return the current to-do list.""" + read = self._db_handler.read_todos() + return read.todo_list + + def set_done(self, todo_id: int) -> CurrentTodo: + """Set a to-do as done.""" + read = self._db_handler.read_todos() + if read.error: + return CurrentTodo({}, read.error) + try: + todo = read.todo_list[todo_id - 1] + except IndexError: + return CurrentTodo({}, ID_ERROR) + todo["Done"] = True + write = self._db_handler.write_todos(read.todo_list) + return CurrentTodo(todo, write.error) diff --git a/typer-cli-python/source_code_step_6/tests/__init__.py b/typer-cli-python/source_code_step_6/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_6/tests/test_rptodo.py b/typer-cli-python/source_code_step_6/tests/test_rptodo.py new file mode 100644 index 0000000000..e061646891 --- /dev/null +++ b/typer-cli-python/source_code_step_6/tests/test_rptodo.py @@ -0,0 +1,124 @@ +import json + +import pytest +from typer.testing import CliRunner + +from rptodo import ( + DB_READ_ERROR, + SUCCESS, + __app_name__, + __version__, + cli, + rptodo, +) + +runner = CliRunner() + + +def test_version(): + result = runner.invoke(cli.app, ["--version"]) + assert result.exit_code == 0 + assert f"{__app_name__} v{__version__}\n" in result.stdout + + +@pytest.fixture +def mock_json_file(tmp_path): + todo = [{"Description": "Get some milk.", "Priority": 2, "Done": False}] + db_file = tmp_path / "todo.json" + with db_file.open("w") as db: + json.dump(todo, db, indent=4) + return db_file + + +test_data1 = { + "description": ["Clean", "the", "house"], + "priority": 1, + "todo": { + "Description": "Clean the house.", + "Priority": 1, + "Done": False, + }, +} +test_data2 = { + "description": ["Wash the car"], + "priority": 2, + "todo": { + "Description": "Wash the car.", + "Priority": 2, + "Done": False, + }, +} + + +@pytest.mark.parametrize( + "description, priority, expected", + [ + pytest.param( + test_data1["description"], + test_data1["priority"], + (test_data1["todo"], SUCCESS), + ), + pytest.param( + test_data2["description"], + test_data2["priority"], + (test_data2["todo"], SUCCESS), + ), + ], +) +def test_add(mock_json_file, description, priority, expected): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.add(description, priority) == expected + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 2 + + +@pytest.fixture +def mock_wrong_json_file(tmp_path): + db_file = tmp_path / "todo.json" + return db_file + + +def test_add_wrong_json_file(mock_wrong_json_file): + todoer = rptodo.Todoer(mock_wrong_json_file) + response = todoer.add(["test task"], 1) + assert response.error == DB_READ_ERROR + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 0 + + +@pytest.fixture +def mock_wrong_json_format(tmp_path): + db_file = tmp_path / "todo.json" + with db_file.open("w") as db: + db.write("") + return db_file + + +def test_add_wrong_json_format(mock_wrong_json_format): + todoer = rptodo.Todoer(mock_wrong_json_format) + assert todoer.add(test_data1["description"], test_data1["priority"]) == ( + test_data1["todo"], + SUCCESS, + ) + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 1 + + +test_todo1 = { + "Description": "buy some milk.", + "Priority": 2, + "Done": True, +} +test_todo2 = {} + + +@pytest.mark.parametrize( + "todo_id, expected", + [ + pytest.param(1, (test_todo1, SUCCESS)), + pytest.param(3, (test_todo2, ID_ERROR)), + ], +) +def test_set_done(mock_json_file, todo_id, expected): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.set_done(todo_id) == expected diff --git a/typer-cli-python/source_code_step_7/README.md b/typer-cli-python/source_code_step_7/README.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_7/rptodo/__init__.py b/typer-cli-python/source_code_step_7/rptodo/__init__.py new file mode 100644 index 0000000000..fc5ba0e413 --- /dev/null +++ b/typer-cli-python/source_code_step_7/rptodo/__init__.py @@ -0,0 +1,22 @@ +"""Top-level package for RP to-do.""" + +__app_name__ = "rptodo" +__version__ = "0.1.0" + +( + SUCCESS, + DIR_ERROR, + FILE_ERROR, + DB_READ_ERROR, + DB_WRITE_ERROR, + JSON_ERROR, + ID_ERROR, +) = range(7) + +ERRORS = { + DIR_ERROR: "config directory error", + FILE_ERROR: "config file error", + DB_READ_ERROR: "database read error", + DB_WRITE_ERROR: "database write error", + ID_ERROR: "to-do id error", +} diff --git a/typer-cli-python/source_code_step_7/rptodo/__main__.py b/typer-cli-python/source_code_step_7/rptodo/__main__.py new file mode 100644 index 0000000000..79c8c51733 --- /dev/null +++ b/typer-cli-python/source_code_step_7/rptodo/__main__.py @@ -0,0 +1,11 @@ +"""RP to-do entry point script.""" + +from rptodo import cli, __app_name__ + + +def main(): + cli.app(prog_name=__app_name__) + + +if __name__ == "__main__": + main() diff --git a/typer-cli-python/source_code_step_7/rptodo/cli.py b/typer-cli-python/source_code_step_7/rptodo/cli.py new file mode 100644 index 0000000000..69c579a598 --- /dev/null +++ b/typer-cli-python/source_code_step_7/rptodo/cli.py @@ -0,0 +1,217 @@ +"""This module provides the RP to-do CLI.""" + +from pathlib import Path +from typing import List, Optional + +import typer + +from rptodo import ERRORS, __app_name__, __version__, config, database, rptodo + +app = typer.Typer() + + +@app.command() +def init( + db_path: str = typer.Option( + str(database.DEFAULT_DB_FILE_PATH), + "--db-path", + "-db", + prompt="to-do database location?", + ), +) -> None: + """Initialize the to-do database.""" + error = config.init_app(db_path) + if error: + typer.secho( + f'Creating config file failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + error = database.init_database(Path(db_path)) + if error: + typer.secho( + f'Creating database failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho(f"The to-do database is {db_path}", fg=typer.colors.GREEN) + + +def get_todoer() -> rptodo.Todoer: + if config.CONFIG_FILE_PATH.exists(): + db_path = database.get_database_path(config.CONFIG_FILE_PATH) + else: + typer.secho( + 'Config file not found. Please, run "rptodo init"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + if db_path.exists(): + return rptodo.Todoer(db_path) + else: + typer.secho( + 'Database not found. Please, run "rptodo init"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + + +@app.command() +def add( + description: List[str] = typer.Argument(...), + priority: int = typer.Option(2, "--priority", "-p", min=1, max=3), +) -> None: + """Add a new to-do with a DESCRIPTION.""" + todoer = get_todoer() + todo, error = todoer.add(description, priority) + if error: + typer.secho( + f'Adding to-do failed with "{ERRORS[error]}"', fg=typer.colors.RED + ) + raise typer.Exit(1) + else: + typer.secho( + f"""to-do: "{todo['Description']}" was added """ + f"""with priority: {priority}""", + fg=typer.colors.GREEN, + ) + + +@app.command() +def list_all() -> None: + """List all to-dos.""" + todoer = get_todoer() + todo_list = todoer.get_todo_list() + if len(todo_list) == 0: + typer.secho( + "There are no tasks in the to-do list yet", fg=typer.colors.RED + ) + raise typer.Exit() + typer.secho("\nto-do list:\n", fg=typer.colors.BLUE, bold=True) + columns = ( + "ID. ", + "| Priority ", + "| Done ", + "| Description ", + ) + headers = "".join(columns) + typer.secho(headers, fg=typer.colors.BLUE, bold=True) + typer.secho("-" * len(headers), fg=typer.colors.BLUE) + for id, todo in enumerate(todo_list, 1): + desc, priority, done = todo.values() + typer.secho( + f"{id}{(len(columns[0]) - len(str(id))) * ' '}" + f"| ({priority}){(len(columns[1]) - len(str(priority)) - 4) * ' '}" + f"| {done}{(len(columns[2]) - len(str(done)) - 2) * ' '}" + f"| {desc}", + fg=typer.colors.BLUE, + ) + typer.secho("-" * len(headers) + "\n", fg=typer.colors.BLUE) + + +@app.command() +def set_done(todo_id: int = typer.Argument(...)) -> None: + """Set a to-do as done using its TODO_ID.""" + todoer = get_todoer() + todo, error = todoer.set_done(todo_id) + if error: + typer.secho( + f'Setting to-do # "{todo_id}" done failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho( + f"""to-do # {todo_id} "{todo['Description']}" set done!""", + fg=typer.colors.GREEN, + ) + + +@app.command() +def remove( + todo_id: int = typer.Argument(...), + force: bool = typer.Option( + False, + "--force", + "-f", + help="Force deletion without confirmation.", + ), +) -> None: + """Remove a to-do using its TODO_ID.""" + todoer = get_todoer() + + def _remove(): + todo, error = todoer.remove(todo_id) + if error: + typer.secho( + f'Removing to-do # {todo_id} failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho( + f"""to-do # {todo_id}: '{todo["Description"]}' was removed""", + fg=typer.colors.GREEN, + ) + + if force: + _remove() + else: + todo_list = todoer.get_todo_list() + try: + todo = todo_list[todo_id - 1] + except IndexError: + typer.secho("Invalid TODO_ID", fg=typer.colors.RED) + raise typer.Exit(1) + delete = typer.confirm( + f"Delete to-do # {todo_id}: {todo['Description']}?" + ) + if delete: + _remove() + else: + typer.echo("Operation canceled") + + +@app.command() +def remove_all( + force: bool = typer.Option( + ..., + prompt="Delete all to-dos?", + help="Force deletion without confirmation.", + ), +) -> None: + """Remove all to-dos.""" + todoer = get_todoer() + if force: + error = todoer.remove_all().error + if error: + typer.secho( + f'Removing to-dos failed with "{ERRORS[error]}"', + fg=typer.colors.RED, + ) + raise typer.Exit(1) + else: + typer.secho("All to-dos were removed", fg=typer.colors.GREEN) + else: + typer.echo("Operation canceled") + + +def _version_callback(value: bool) -> None: + if value: + typer.echo(f"{__app_name__} v{__version__}") + raise typer.Exit() + + +@app.callback() +def main( + version: Optional[bool] = typer.Option( + None, + "--version", + "-v", + help="Show the application's version and exit.", + callback=_version_callback, + is_eager=True, + ) +) -> None: + return diff --git a/typer-cli-python/source_code_step_7/rptodo/config.py b/typer-cli-python/source_code_step_7/rptodo/config.py new file mode 100644 index 0000000000..1e0f8d545f --- /dev/null +++ b/typer-cli-python/source_code_step_7/rptodo/config.py @@ -0,0 +1,45 @@ +"""This module provides the RP to-do config functionality.""" + +import configparser +from pathlib import Path + +import typer + +from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ + +CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) +CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" + + +def init_app(db_path: str) -> int: + """Initialize the application.""" + config = _init_config_file() + if config != SUCCESS: + return config + database = _create_database(db_path) + if database != SUCCESS: + return database + return SUCCESS + + +def _init_config_file() -> int: + try: + CONFIG_DIR_PATH.mkdir(exist_ok=True) + except OSError: + return DIR_ERROR + try: + CONFIG_FILE_PATH.touch(exist_ok=True) + except OSError: + return FILE_ERROR + return SUCCESS + + +def _create_database(db_path: str) -> int: + config_parser = configparser.ConfigParser() + config_parser["General"] = {"database": db_path} + try: + with CONFIG_FILE_PATH.open("w") as file: + config_parser.write(file) + except OSError: + return DB_WRITE_ERROR + return SUCCESS diff --git a/typer-cli-python/source_code_step_7/rptodo/database.py b/typer-cli-python/source_code_step_7/rptodo/database.py new file mode 100644 index 0000000000..4865ec2a5a --- /dev/null +++ b/typer-cli-python/source_code_step_7/rptodo/database.py @@ -0,0 +1,56 @@ +"""This module provides the RP to-do database functionality.""" + +import configparser +import json +from pathlib import Path +from typing import Any, Dict, List, NamedTuple + +from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS + +DEFAULT_DB_FILE_PATH = Path.home().joinpath( + "." + Path.home().stem + "_todo.json" +) + + +def get_database_path(config_file: Path) -> Path: + """Return the current path to the to-do database.""" + config_parser = configparser.ConfigParser() + config_parser.read(config_file) + return Path(config_parser["General"]["database"]) + + +def init_database(db_path: Path) -> int: + """Create the to-do database.""" + try: + db_path.write_text("[]") # Empty to-do list + return SUCCESS + except OSError: + return DB_WRITE_ERROR + + +class DBResponse(NamedTuple): + todo_list: List[Dict[str, Any]] + error: int + + +class DatabaseHandler: + def __init__(self, db_path: Path) -> None: + self._db_path = db_path + + def read_todos(self) -> DBResponse: + try: + with self._db_path.open("r") as db: + try: + return DBResponse(json.load(db), SUCCESS) + except json.JSONDecodeError: # Catch wrong JSON format + return DBResponse([], JSON_ERROR) + except OSError: # Catch file IO problems + return DBResponse([], DB_READ_ERROR) + + def write_todos(self, todo_list: List[Dict[str, Any]]) -> DBResponse: + try: + with self._db_path.open("w") as db: + json.dump(todo_list, db, indent=4) + return DBResponse(todo_list, SUCCESS) + except OSError: # Catch file IO problems + return DBResponse(todo_list, DB_WRITE_ERROR) diff --git a/typer-cli-python/source_code_step_7/rptodo/rptodo.py b/typer-cli-python/source_code_step_7/rptodo/rptodo.py new file mode 100644 index 0000000000..d7e52b87ea --- /dev/null +++ b/typer-cli-python/source_code_step_7/rptodo/rptodo.py @@ -0,0 +1,69 @@ +"""This module provides the RP to-do model-controller.""" + +from pathlib import Path +from typing import Any, Dict, List, NamedTuple + +from . import DB_READ_ERROR, ID_ERROR +from .database import DatabaseHandler + + +class CurrentTodo(NamedTuple): + todo: Dict[str, Any] + error: int + + +class Todoer: + def __init__(self, db_path: Path) -> None: + self._db_handler = DatabaseHandler(db_path) + + def add(self, description: List[str], priority: int = 2) -> CurrentTodo: + """Add a new to-do to the database.""" + description_text = " ".join(description) + if not description_text.endswith("."): + description_text += "." + todo = { + "Description": description_text, + "Priority": priority, + "Done": False, + } + read = self._db_handler.read_todos() + if read.error == DB_READ_ERROR: + return CurrentTodo(todo, read.error) + read.todo_list.append(todo) + write = self._db_handler.write_todos(read.todo_list) + return CurrentTodo(todo, write.error) + + def get_todo_list(self) -> List[Dict[str, Any]]: + """Return the current to-do list.""" + read = self._db_handler.read_todos() + return read.todo_list + + def set_done(self, todo_id: int) -> CurrentTodo: + """Set a to-do as done.""" + read = self._db_handler.read_todos() + if read.error: + return CurrentTodo({}, read.error) + try: + todo = read.todo_list[todo_id - 1] + except IndexError: + return CurrentTodo({}, ID_ERROR) + todo["Done"] = True + write = self._db_handler.write_todos(read.todo_list) + return CurrentTodo(todo, write.error) + + def remove(self, todo_id: int) -> CurrentTodo: + """Remove a to-do from the database using its id or index.""" + read = self._db_handler.read_todos() + if read.error: + return CurrentTodo({}, read.error) + try: + todo = read.todo_list.pop(todo_id - 1) + except IndexError: + return CurrentTodo({}, ID_ERROR) + write = self._db_handler.write_todos(read.todo_list) + return CurrentTodo(todo, write.error) + + def remove_all(self) -> CurrentTodo: + """Remove all to-dos from the database.""" + write = self._db_handler.write_todos([]) + return CurrentTodo({}, write.error) diff --git a/typer-cli-python/source_code_step_7/tests/__init__.py b/typer-cli-python/source_code_step_7/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/typer-cli-python/source_code_step_7/tests/test_rptodo.py b/typer-cli-python/source_code_step_7/tests/test_rptodo.py new file mode 100644 index 0000000000..bfa16dc3ab --- /dev/null +++ b/typer-cli-python/source_code_step_7/tests/test_rptodo.py @@ -0,0 +1,149 @@ +import json + +import pytest +from typer.testing import CliRunner + +from rptodo import ( + DB_READ_ERROR, + SUCCESS, + __app_name__, + __version__, + cli, + rptodo, +) + +runner = CliRunner() + + +def test_version(): + result = runner.invoke(cli.app, ["--version"]) + assert result.exit_code == 0 + assert f"{__app_name__} v{__version__}\n" in result.stdout + + +@pytest.fixture +def mock_json_file(tmp_path): + todo = [{"Description": "Get some milk.", "Priority": 2, "Done": False}] + db_file = tmp_path / "todo.json" + with db_file.open("w") as db: + json.dump(todo, db, indent=4) + return db_file + + +test_data1 = { + "description": ["Clean", "the", "house"], + "priority": 1, + "todo": { + "Description": "Clean the house.", + "Priority": 1, + "Done": False, + }, +} +test_data2 = { + "description": ["Wash the car"], + "priority": 2, + "todo": { + "Description": "Wash the car.", + "Priority": 2, + "Done": False, + }, +} + + +@pytest.mark.parametrize( + "description, priority, expected", + [ + pytest.param( + test_data1["description"], + test_data1["priority"], + (test_data1["todo"], SUCCESS), + ), + pytest.param( + test_data2["description"], + test_data2["priority"], + (test_data2["todo"], SUCCESS), + ), + ], +) +def test_add(mock_json_file, description, priority, expected): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.add(description, priority) == expected + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 2 + + +@pytest.fixture +def mock_wrong_json_file(tmp_path): + db_file = tmp_path / "todo.json" + return db_file + + +def test_add_wrong_json_file(mock_wrong_json_file): + todoer = rptodo.Todoer(mock_wrong_json_file) + response = todoer.add(["test task"], 1) + assert response.error == DB_READ_ERROR + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 0 + + +@pytest.fixture +def mock_wrong_json_format(tmp_path): + db_file = tmp_path / "todo.json" + with db_file.open("w") as db: + db.write("") + return db_file + + +def test_add_wrong_json_format(mock_wrong_json_format): + todoer = rptodo.Todoer(mock_wrong_json_format) + assert todoer.add(test_data1["description"], test_data1["priority"]) == ( + test_data1["todo"], + SUCCESS, + ) + read = todoer._db_handler.read_todos() + assert len(read.todo_list) == 1 + + +test_todo1 = { + "Description": "buy some milk.", + "Priority": 2, + "Done": True, +} +test_todo2 = {} + + +@pytest.mark.parametrize( + "todo_id, expected", + [ + pytest.param(1, (test_todo1, SUCCESS)), + pytest.param(3, (test_todo2, ID_ERROR)), + ], +) +def test_set_done(mock_json_file, todo_id, expected): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.set_done(todo_id) == expected + + +test_todo3 = { + "Description": "buy some milk.", + "Priority": 2, + "Done": False, +} +test_todo4 = {} + + +@pytest.mark.parametrize( + "todo_id, expected", + [ + pytest.param(1, (test_todo3, SUCCESS)), + pytest.param(3, (test_todo4, ID_ERROR)), + ], +) +def test_remove(mock_json_file, todo_id, expected): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.remove(todo_id) == expected + + +def test_remove_all(mock_json_file): + todoer = rptodo.Todoer(mock_json_file) + assert todoer.remove_all() == ({}, SUCCESS) From 5749f498fe663ee371cb69f2c049fb6f2be4bb9d Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 23 Aug 2021 15:57:37 -0400 Subject: [PATCH 02/15] Fix import --- typer-cli-python/source_code_step_6/tests/test_rptodo.py | 1 + typer-cli-python/source_code_step_7/tests/test_rptodo.py | 1 + 2 files changed, 2 insertions(+) diff --git a/typer-cli-python/source_code_step_6/tests/test_rptodo.py b/typer-cli-python/source_code_step_6/tests/test_rptodo.py index e061646891..bc277561c0 100644 --- a/typer-cli-python/source_code_step_6/tests/test_rptodo.py +++ b/typer-cli-python/source_code_step_6/tests/test_rptodo.py @@ -5,6 +5,7 @@ from rptodo import ( DB_READ_ERROR, + ID_ERROR, SUCCESS, __app_name__, __version__, diff --git a/typer-cli-python/source_code_step_7/tests/test_rptodo.py b/typer-cli-python/source_code_step_7/tests/test_rptodo.py index bfa16dc3ab..2162020c8b 100644 --- a/typer-cli-python/source_code_step_7/tests/test_rptodo.py +++ b/typer-cli-python/source_code_step_7/tests/test_rptodo.py @@ -5,6 +5,7 @@ from rptodo import ( DB_READ_ERROR, + ID_ERROR, SUCCESS, __app_name__, __version__, From ee99cfc3965e448eaafa26e4005a11b87631e4e3 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 27 Sep 2021 19:40:03 -0400 Subject: [PATCH 03/15] TR update, first round --- typer-cli-python/source_code_final/rptodo/cli.py | 12 ++++++------ typer-cli-python/source_code_final/rptodo/config.py | 12 ++++++------ typer-cli-python/source_code_step_3/rptodo/config.py | 12 ++++++------ typer-cli-python/source_code_step_4/rptodo/config.py | 12 ++++++------ typer-cli-python/source_code_step_5/rptodo/cli.py | 2 +- typer-cli-python/source_code_step_5/rptodo/config.py | 12 ++++++------ typer-cli-python/source_code_step_6/rptodo/cli.py | 10 +++++----- typer-cli-python/source_code_step_6/rptodo/config.py | 12 ++++++------ typer-cli-python/source_code_step_7/rptodo/cli.py | 12 ++++++------ typer-cli-python/source_code_step_7/rptodo/config.py | 12 ++++++------ 10 files changed, 54 insertions(+), 54 deletions(-) diff --git a/typer-cli-python/source_code_final/rptodo/cli.py b/typer-cli-python/source_code_final/rptodo/cli.py index 69c579a598..e294a53325 100644 --- a/typer-cli-python/source_code_final/rptodo/cli.py +++ b/typer-cli-python/source_code_final/rptodo/cli.py @@ -78,7 +78,7 @@ def add( ) -@app.command() +@app.command(name="list") def list_all() -> None: """List all to-dos.""" todoer = get_todoer() @@ -110,20 +110,20 @@ def list_all() -> None: typer.secho("-" * len(headers) + "\n", fg=typer.colors.BLUE) -@app.command() +@app.command(name="complete") def set_done(todo_id: int = typer.Argument(...)) -> None: - """Set a to-do as done using its TODO_ID.""" + """Complete a to-do by setting it as done using its TODO_ID.""" todoer = get_todoer() todo, error = todoer.set_done(todo_id) if error: typer.secho( - f'Setting to-do # "{todo_id}" done failed with "{ERRORS[error]}"', + f'Completting to-do # "{todo_id}" failed with "{ERRORS[error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) else: typer.secho( - f"""to-do # {todo_id} "{todo['Description']}" set done!""", + f"""to-do # {todo_id} "{todo['Description']}" completed!""", fg=typer.colors.GREEN, ) @@ -173,7 +173,7 @@ def _remove(): typer.echo("Operation canceled") -@app.command() +@app.command(name="clear") def remove_all( force: bool = typer.Option( ..., diff --git a/typer-cli-python/source_code_final/rptodo/config.py b/typer-cli-python/source_code_final/rptodo/config.py index 1e0f8d545f..e1fd40d6ce 100644 --- a/typer-cli-python/source_code_final/rptodo/config.py +++ b/typer-cli-python/source_code_final/rptodo/config.py @@ -13,12 +13,12 @@ def init_app(db_path: str) -> int: """Initialize the application.""" - config = _init_config_file() - if config != SUCCESS: - return config - database = _create_database(db_path) - if database != SUCCESS: - return database + config_code = _init_config_file() + if config_code != SUCCESS: + return config_code + database_code = _create_database(db_path) + if database_code != SUCCESS: + return database_code return SUCCESS diff --git a/typer-cli-python/source_code_step_3/rptodo/config.py b/typer-cli-python/source_code_step_3/rptodo/config.py index 1e0f8d545f..e1fd40d6ce 100644 --- a/typer-cli-python/source_code_step_3/rptodo/config.py +++ b/typer-cli-python/source_code_step_3/rptodo/config.py @@ -13,12 +13,12 @@ def init_app(db_path: str) -> int: """Initialize the application.""" - config = _init_config_file() - if config != SUCCESS: - return config - database = _create_database(db_path) - if database != SUCCESS: - return database + config_code = _init_config_file() + if config_code != SUCCESS: + return config_code + database_code = _create_database(db_path) + if database_code != SUCCESS: + return database_code return SUCCESS diff --git a/typer-cli-python/source_code_step_4/rptodo/config.py b/typer-cli-python/source_code_step_4/rptodo/config.py index 1e0f8d545f..e1fd40d6ce 100644 --- a/typer-cli-python/source_code_step_4/rptodo/config.py +++ b/typer-cli-python/source_code_step_4/rptodo/config.py @@ -13,12 +13,12 @@ def init_app(db_path: str) -> int: """Initialize the application.""" - config = _init_config_file() - if config != SUCCESS: - return config - database = _create_database(db_path) - if database != SUCCESS: - return database + config_code = _init_config_file() + if config_code != SUCCESS: + return config_code + database_code = _create_database(db_path) + if database_code != SUCCESS: + return database_code return SUCCESS diff --git a/typer-cli-python/source_code_step_5/rptodo/cli.py b/typer-cli-python/source_code_step_5/rptodo/cli.py index 0350c34204..b3f1efe32e 100644 --- a/typer-cli-python/source_code_step_5/rptodo/cli.py +++ b/typer-cli-python/source_code_step_5/rptodo/cli.py @@ -78,7 +78,7 @@ def add( ) -@app.command() +@app.command(name="list") def list_all() -> None: """List all to-dos.""" todoer = get_todoer() diff --git a/typer-cli-python/source_code_step_5/rptodo/config.py b/typer-cli-python/source_code_step_5/rptodo/config.py index 1e0f8d545f..e1fd40d6ce 100644 --- a/typer-cli-python/source_code_step_5/rptodo/config.py +++ b/typer-cli-python/source_code_step_5/rptodo/config.py @@ -13,12 +13,12 @@ def init_app(db_path: str) -> int: """Initialize the application.""" - config = _init_config_file() - if config != SUCCESS: - return config - database = _create_database(db_path) - if database != SUCCESS: - return database + config_code = _init_config_file() + if config_code != SUCCESS: + return config_code + database_code = _create_database(db_path) + if database_code != SUCCESS: + return database_code return SUCCESS diff --git a/typer-cli-python/source_code_step_6/rptodo/cli.py b/typer-cli-python/source_code_step_6/rptodo/cli.py index 1924a28cb0..3dad273391 100644 --- a/typer-cli-python/source_code_step_6/rptodo/cli.py +++ b/typer-cli-python/source_code_step_6/rptodo/cli.py @@ -79,7 +79,7 @@ def add( @app.command() -def list_all() -> None: +def list_all(name="list") -> None: """List all to-dos.""" todoer = get_todoer() todo_list = todoer.get_todo_list() @@ -110,20 +110,20 @@ def list_all() -> None: typer.secho("-" * len(headers) + "\n", fg=typer.colors.BLUE) -@app.command() +@app.command(name="complete") def set_done(todo_id: int = typer.Argument(...)) -> None: - """Set a to-do as done using its TODO_ID.""" + """Complete a to-do by setting it as done using its TODO_ID.""" todoer = get_todoer() todo, error = todoer.set_done(todo_id) if error: typer.secho( - f'Setting to-do # "{todo_id}" done failed with "{ERRORS[error]}"', + f'Completting to-do # "{todo_id}" failed with "{ERRORS[error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) else: typer.secho( - f"""to-do # {todo_id} "{todo['Description']}" set done!""", + f"""to-do # {todo_id} "{todo['Description']}" completed!""", fg=typer.colors.GREEN, ) diff --git a/typer-cli-python/source_code_step_6/rptodo/config.py b/typer-cli-python/source_code_step_6/rptodo/config.py index 1e0f8d545f..e1fd40d6ce 100644 --- a/typer-cli-python/source_code_step_6/rptodo/config.py +++ b/typer-cli-python/source_code_step_6/rptodo/config.py @@ -13,12 +13,12 @@ def init_app(db_path: str) -> int: """Initialize the application.""" - config = _init_config_file() - if config != SUCCESS: - return config - database = _create_database(db_path) - if database != SUCCESS: - return database + config_code = _init_config_file() + if config_code != SUCCESS: + return config_code + database_code = _create_database(db_path) + if database_code != SUCCESS: + return database_code return SUCCESS diff --git a/typer-cli-python/source_code_step_7/rptodo/cli.py b/typer-cli-python/source_code_step_7/rptodo/cli.py index 69c579a598..cfff55075e 100644 --- a/typer-cli-python/source_code_step_7/rptodo/cli.py +++ b/typer-cli-python/source_code_step_7/rptodo/cli.py @@ -79,7 +79,7 @@ def add( @app.command() -def list_all() -> None: +def list_all(name="list") -> None: """List all to-dos.""" todoer = get_todoer() todo_list = todoer.get_todo_list() @@ -110,20 +110,20 @@ def list_all() -> None: typer.secho("-" * len(headers) + "\n", fg=typer.colors.BLUE) -@app.command() +@app.command(name="complete") def set_done(todo_id: int = typer.Argument(...)) -> None: - """Set a to-do as done using its TODO_ID.""" + """Complete a to-do by setting it as done using its TODO_ID.""" todoer = get_todoer() todo, error = todoer.set_done(todo_id) if error: typer.secho( - f'Setting to-do # "{todo_id}" done failed with "{ERRORS[error]}"', + f'Completting to-do # "{todo_id}" failed with "{ERRORS[error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) else: typer.secho( - f"""to-do # {todo_id} "{todo['Description']}" set done!""", + f"""to-do # {todo_id} "{todo['Description']}" completed!""", fg=typer.colors.GREEN, ) @@ -173,7 +173,7 @@ def _remove(): typer.echo("Operation canceled") -@app.command() +@app.command(name="clear") def remove_all( force: bool = typer.Option( ..., diff --git a/typer-cli-python/source_code_step_7/rptodo/config.py b/typer-cli-python/source_code_step_7/rptodo/config.py index 1e0f8d545f..e1fd40d6ce 100644 --- a/typer-cli-python/source_code_step_7/rptodo/config.py +++ b/typer-cli-python/source_code_step_7/rptodo/config.py @@ -13,12 +13,12 @@ def init_app(db_path: str) -> int: """Initialize the application.""" - config = _init_config_file() - if config != SUCCESS: - return config - database = _create_database(db_path) - if database != SUCCESS: - return database + config_code = _init_config_file() + if config_code != SUCCESS: + return config_code + database_code = _create_database(db_path) + if database_code != SUCCESS: + return database_code return SUCCESS From 9655fc6761c13220e25f4ca436ffe79364b2af1b Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 11 Oct 2021 13:11:21 -0400 Subject: [PATCH 04/15] Fix a typo --- typer-cli-python/source_code_final/rptodo/cli.py | 2 +- typer-cli-python/source_code_step_6/rptodo/cli.py | 2 +- typer-cli-python/source_code_step_7/rptodo/cli.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/typer-cli-python/source_code_final/rptodo/cli.py b/typer-cli-python/source_code_final/rptodo/cli.py index e294a53325..653c4cb1c7 100644 --- a/typer-cli-python/source_code_final/rptodo/cli.py +++ b/typer-cli-python/source_code_final/rptodo/cli.py @@ -117,7 +117,7 @@ def set_done(todo_id: int = typer.Argument(...)) -> None: todo, error = todoer.set_done(todo_id) if error: typer.secho( - f'Completting to-do # "{todo_id}" failed with "{ERRORS[error]}"', + f'Completing to-do # "{todo_id}" failed with "{ERRORS[error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) diff --git a/typer-cli-python/source_code_step_6/rptodo/cli.py b/typer-cli-python/source_code_step_6/rptodo/cli.py index 3dad273391..cb960c792f 100644 --- a/typer-cli-python/source_code_step_6/rptodo/cli.py +++ b/typer-cli-python/source_code_step_6/rptodo/cli.py @@ -117,7 +117,7 @@ def set_done(todo_id: int = typer.Argument(...)) -> None: todo, error = todoer.set_done(todo_id) if error: typer.secho( - f'Completting to-do # "{todo_id}" failed with "{ERRORS[error]}"', + f'Completing to-do # "{todo_id}" failed with "{ERRORS[error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) diff --git a/typer-cli-python/source_code_step_7/rptodo/cli.py b/typer-cli-python/source_code_step_7/rptodo/cli.py index cfff55075e..6bd2ae0596 100644 --- a/typer-cli-python/source_code_step_7/rptodo/cli.py +++ b/typer-cli-python/source_code_step_7/rptodo/cli.py @@ -117,7 +117,7 @@ def set_done(todo_id: int = typer.Argument(...)) -> None: todo, error = todoer.set_done(todo_id) if error: typer.secho( - f'Completting to-do # "{todo_id}" failed with "{ERRORS[error]}"', + f'Completing to-do # "{todo_id}" failed with "{ERRORS[error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) From 31eab7079a8fed398cd9584dedd389d2c5686b04 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 11 Oct 2021 13:11:52 -0400 Subject: [PATCH 05/15] Fix the list command --- typer-cli-python/source_code_step_6/rptodo/cli.py | 4 ++-- typer-cli-python/source_code_step_7/rptodo/cli.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/typer-cli-python/source_code_step_6/rptodo/cli.py b/typer-cli-python/source_code_step_6/rptodo/cli.py index cb960c792f..77cf1fa3cb 100644 --- a/typer-cli-python/source_code_step_6/rptodo/cli.py +++ b/typer-cli-python/source_code_step_6/rptodo/cli.py @@ -78,8 +78,8 @@ def add( ) -@app.command() -def list_all(name="list") -> None: +@app.command(name="list") +def list_all() -> None: """List all to-dos.""" todoer = get_todoer() todo_list = todoer.get_todo_list() diff --git a/typer-cli-python/source_code_step_7/rptodo/cli.py b/typer-cli-python/source_code_step_7/rptodo/cli.py index 6bd2ae0596..653c4cb1c7 100644 --- a/typer-cli-python/source_code_step_7/rptodo/cli.py +++ b/typer-cli-python/source_code_step_7/rptodo/cli.py @@ -78,8 +78,8 @@ def add( ) -@app.command() -def list_all(name="list") -> None: +@app.command(name="list") +def list_all() -> None: """List all to-dos.""" todoer = get_todoer() todo_list = todoer.get_todo_list() From 8cdd71eda81fb1760b24a2292c8f0af2a1d52b44 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 11 Oct 2021 13:15:26 -0400 Subject: [PATCH 06/15] Fix tests --- .../source_code_final/tests/test_rptodo.py | 22 +++++++++---------- .../source_code_step_6/tests/test_rptodo.py | 2 +- .../source_code_step_7/tests/test_rptodo.py | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/typer-cli-python/source_code_final/tests/test_rptodo.py b/typer-cli-python/source_code_final/tests/test_rptodo.py index 60a2657db6..88e98142a5 100644 --- a/typer-cli-python/source_code_final/tests/test_rptodo.py +++ b/typer-cli-python/source_code_final/tests/test_rptodo.py @@ -4,13 +4,13 @@ from typer.testing import CliRunner from rptodo import ( - cli, + DB_READ_ERROR, + ID_ERROR, + SUCCESS, __app_name__, __version__, + cli, rptodo, - SUCCESS, - DB_READ_ERROR, - ID_ERROR, ) @@ -25,7 +25,7 @@ def test_version(): @pytest.fixture def mock_json_file(tmp_path): - todo = [{"Description": "buy some milk.", "Priority": 2, "Done": False}] + todo = [{"Description": "Get some milk.", "Priority": 2, "Done": False}] db_file = tmp_path / "todo.json" with db_file.open("w") as db: json.dump(todo, db, indent=4) @@ -33,19 +33,19 @@ def mock_json_file(tmp_path): test_data1 = { - "description": ["clean", "the", "house"], + "description": ["Clean", "the", "house"], "priority": 1, "todo": { - "Description": "clean the house.", + "Description": "Clean the house.", "Priority": 1, "Done": False, }, } test_data2 = { - "description": ["go for a walk"], + "description": ["Wash the car"], "priority": 2, "todo": { - "Description": "go for a walk.", + "Description": "Wash the car.", "Priority": 2, "Done": False, }, @@ -107,7 +107,7 @@ def test_add_wrong_json_format(mock_wrong_json_format): test_todo1 = { - "Description": "buy some milk.", + "Description": "Get some milk.", "Priority": 2, "Done": True, } @@ -127,7 +127,7 @@ def test_set_done(mock_json_file, todo_id, expected): test_todo3 = { - "Description": "buy some milk.", + "Description": "Get some milk.", "Priority": 2, "Done": False, } diff --git a/typer-cli-python/source_code_step_6/tests/test_rptodo.py b/typer-cli-python/source_code_step_6/tests/test_rptodo.py index bc277561c0..0109e1a9fd 100644 --- a/typer-cli-python/source_code_step_6/tests/test_rptodo.py +++ b/typer-cli-python/source_code_step_6/tests/test_rptodo.py @@ -106,7 +106,7 @@ def test_add_wrong_json_format(mock_wrong_json_format): test_todo1 = { - "Description": "buy some milk.", + "Description": "Get some milk.", "Priority": 2, "Done": True, } diff --git a/typer-cli-python/source_code_step_7/tests/test_rptodo.py b/typer-cli-python/source_code_step_7/tests/test_rptodo.py index 2162020c8b..6833cf8e4a 100644 --- a/typer-cli-python/source_code_step_7/tests/test_rptodo.py +++ b/typer-cli-python/source_code_step_7/tests/test_rptodo.py @@ -106,7 +106,7 @@ def test_add_wrong_json_format(mock_wrong_json_format): test_todo1 = { - "Description": "buy some milk.", + "Description": "Get some milk.", "Priority": 2, "Done": True, } @@ -126,7 +126,7 @@ def test_set_done(mock_json_file, todo_id, expected): test_todo3 = { - "Description": "buy some milk.", + "Description": "Get some milk.", "Priority": 2, "Done": False, } From 77bf1ebf1fa542e6181a4b37be731193d289dd7a Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 11 Oct 2021 13:42:31 -0400 Subject: [PATCH 07/15] Remove Poetry from the requirements.txt file --- typer-cli-python/source_code_final/requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/typer-cli-python/source_code_final/requirements.txt b/typer-cli-python/source_code_final/requirements.txt index 8aaab9a4ce..5843b5256d 100644 --- a/typer-cli-python/source_code_final/requirements.txt +++ b/typer-cli-python/source_code_final/requirements.txt @@ -1,3 +1,2 @@ typer[all]==0.3.2 -poetry==1.1.7 pytest==6.2.4 From 2bfb3aac5e6b5dafd367ef7a663d25aed9249f4a Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 11 Oct 2021 13:43:10 -0400 Subject: [PATCH 08/15] Add the requirements.txt file to each step --- typer-cli-python/source_code_step_1/requirements.txt | 2 ++ typer-cli-python/source_code_step_2/requirements.txt | 2 ++ typer-cli-python/source_code_step_3/requirements.txt | 2 ++ typer-cli-python/source_code_step_4/requirements.txt | 2 ++ typer-cli-python/source_code_step_5/requirements.txt | 2 ++ typer-cli-python/source_code_step_6/requirements.txt | 2 ++ typer-cli-python/source_code_step_7/requirements.txt | 2 ++ 7 files changed, 14 insertions(+) create mode 100644 typer-cli-python/source_code_step_1/requirements.txt create mode 100644 typer-cli-python/source_code_step_2/requirements.txt create mode 100644 typer-cli-python/source_code_step_3/requirements.txt create mode 100644 typer-cli-python/source_code_step_4/requirements.txt create mode 100644 typer-cli-python/source_code_step_5/requirements.txt create mode 100644 typer-cli-python/source_code_step_6/requirements.txt create mode 100644 typer-cli-python/source_code_step_7/requirements.txt diff --git a/typer-cli-python/source_code_step_1/requirements.txt b/typer-cli-python/source_code_step_1/requirements.txt new file mode 100644 index 0000000000..5843b5256d --- /dev/null +++ b/typer-cli-python/source_code_step_1/requirements.txt @@ -0,0 +1,2 @@ +typer[all]==0.3.2 +pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_2/requirements.txt b/typer-cli-python/source_code_step_2/requirements.txt new file mode 100644 index 0000000000..5843b5256d --- /dev/null +++ b/typer-cli-python/source_code_step_2/requirements.txt @@ -0,0 +1,2 @@ +typer[all]==0.3.2 +pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_3/requirements.txt b/typer-cli-python/source_code_step_3/requirements.txt new file mode 100644 index 0000000000..5843b5256d --- /dev/null +++ b/typer-cli-python/source_code_step_3/requirements.txt @@ -0,0 +1,2 @@ +typer[all]==0.3.2 +pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_4/requirements.txt b/typer-cli-python/source_code_step_4/requirements.txt new file mode 100644 index 0000000000..5843b5256d --- /dev/null +++ b/typer-cli-python/source_code_step_4/requirements.txt @@ -0,0 +1,2 @@ +typer[all]==0.3.2 +pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_5/requirements.txt b/typer-cli-python/source_code_step_5/requirements.txt new file mode 100644 index 0000000000..5843b5256d --- /dev/null +++ b/typer-cli-python/source_code_step_5/requirements.txt @@ -0,0 +1,2 @@ +typer[all]==0.3.2 +pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_6/requirements.txt b/typer-cli-python/source_code_step_6/requirements.txt new file mode 100644 index 0000000000..5843b5256d --- /dev/null +++ b/typer-cli-python/source_code_step_6/requirements.txt @@ -0,0 +1,2 @@ +typer[all]==0.3.2 +pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_7/requirements.txt b/typer-cli-python/source_code_step_7/requirements.txt new file mode 100644 index 0000000000..5843b5256d --- /dev/null +++ b/typer-cli-python/source_code_step_7/requirements.txt @@ -0,0 +1,2 @@ +typer[all]==0.3.2 +pytest==6.2.4 From 1b6fe924426b23ad0a29afe51c77baf2352a8e55 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 11 Oct 2021 13:53:29 -0400 Subject: [PATCH 09/15] Update README.md --- typer-cli-python/README.md | 30 +++++++++++--------- typer-cli-python/source_code_final/README.md | 30 +++++++++++--------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/typer-cli-python/README.md b/typer-cli-python/README.md index afbd917a0f..ebd47fad5e 100644 --- a/typer-cli-python/README.md +++ b/typer-cli-python/README.md @@ -41,18 +41,18 @@ Usage: rptodo [OPTIONS] COMMAND [ARGS]... Options: -v, --version Show the application's version and exit. --install-completion Install completion for the current shell. - --show-completion Show completion for the current shell, to copy it - or customize the installation. + --show-completion Show completion for the current shell, to copy it or + customize the installation. --help Show this message and exit. Commands: - add Add a new to-do with a DESCRIPTION. - init Initialize the to-do database. - list-all List all to-dos. - remove Remove a to-do using its TODO_ID. - remove-all Remove all to-dos. - set-done Set a to-do as done using its TODO_ID. + add Add a new to-do with a DESCRIPTION. + clear Remove all to-dos. + complete Complete a to-do by setting it as done using its TODO_ID. + init Initialize the to-do database. + list List all to-dos. + remove Remove a to-do using its TODO_ID. ``` You can also access the help message for specific commands by typing the command and then `--help`. For example, to display the help content for the `add` command, you can run the following: @@ -77,12 +77,14 @@ Calling `--help` on each command provides specific and useful information about **RP to-do** has the following features: -- **`init`** initializes the application's to-do database. -- **`add DESCRIPTION`** adds a new to-do to the database with a `DESCRIPTION`. -- **`list-all`** lists all the to-dos in the database. -- **`set-done TODO_ID`** set a to-do as done using its `TODO_ID`. -- **`remove TODO_ID`** remove a to-do from the database using its `TODO_ID`. -- **`remove-all`** remove all the to-dos in the database. +| Command | Description | + | ------------------ | ------------------------------------------------------------ | + | `init` | Initializes the application's to-do database. | + | `add DESCRIPTION` | Adds a new to-do to the database with a `DESCRIPTION`. | + | `list` | Lists all the to-dos in the database. | + | `complete TODO_ID` | Completes a to-do by setting it as done using its `TODO_ID`. | + | `remove TODO_ID` | Removes a to-do from the database using its `TODO_ID`. | + | `clear` | Removes all the to-dos by clearing the database. | ## Release History diff --git a/typer-cli-python/source_code_final/README.md b/typer-cli-python/source_code_final/README.md index afbd917a0f..ebd47fad5e 100644 --- a/typer-cli-python/source_code_final/README.md +++ b/typer-cli-python/source_code_final/README.md @@ -41,18 +41,18 @@ Usage: rptodo [OPTIONS] COMMAND [ARGS]... Options: -v, --version Show the application's version and exit. --install-completion Install completion for the current shell. - --show-completion Show completion for the current shell, to copy it - or customize the installation. + --show-completion Show completion for the current shell, to copy it or + customize the installation. --help Show this message and exit. Commands: - add Add a new to-do with a DESCRIPTION. - init Initialize the to-do database. - list-all List all to-dos. - remove Remove a to-do using its TODO_ID. - remove-all Remove all to-dos. - set-done Set a to-do as done using its TODO_ID. + add Add a new to-do with a DESCRIPTION. + clear Remove all to-dos. + complete Complete a to-do by setting it as done using its TODO_ID. + init Initialize the to-do database. + list List all to-dos. + remove Remove a to-do using its TODO_ID. ``` You can also access the help message for specific commands by typing the command and then `--help`. For example, to display the help content for the `add` command, you can run the following: @@ -77,12 +77,14 @@ Calling `--help` on each command provides specific and useful information about **RP to-do** has the following features: -- **`init`** initializes the application's to-do database. -- **`add DESCRIPTION`** adds a new to-do to the database with a `DESCRIPTION`. -- **`list-all`** lists all the to-dos in the database. -- **`set-done TODO_ID`** set a to-do as done using its `TODO_ID`. -- **`remove TODO_ID`** remove a to-do from the database using its `TODO_ID`. -- **`remove-all`** remove all the to-dos in the database. +| Command | Description | + | ------------------ | ------------------------------------------------------------ | + | `init` | Initializes the application's to-do database. | + | `add DESCRIPTION` | Adds a new to-do to the database with a `DESCRIPTION`. | + | `list` | Lists all the to-dos in the database. | + | `complete TODO_ID` | Completes a to-do by setting it as done using its `TODO_ID`. | + | `remove TODO_ID` | Removes a to-do from the database using its `TODO_ID`. | + | `clear` | Removes all the to-dos by clearing the database. | ## Release History From b2a2ae9a18aa12da0575bbaf7ec3376f2253962d Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 11 Oct 2021 14:00:45 -0400 Subject: [PATCH 10/15] Remove unneeded spaces --- typer-cli-python/README.md | 14 +++++++------- typer-cli-python/source_code_final/README.md | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/typer-cli-python/README.md b/typer-cli-python/README.md index ebd47fad5e..441b466d12 100644 --- a/typer-cli-python/README.md +++ b/typer-cli-python/README.md @@ -78,13 +78,13 @@ Calling `--help` on each command provides specific and useful information about **RP to-do** has the following features: | Command | Description | - | ------------------ | ------------------------------------------------------------ | - | `init` | Initializes the application's to-do database. | - | `add DESCRIPTION` | Adds a new to-do to the database with a `DESCRIPTION`. | - | `list` | Lists all the to-dos in the database. | - | `complete TODO_ID` | Completes a to-do by setting it as done using its `TODO_ID`. | - | `remove TODO_ID` | Removes a to-do from the database using its `TODO_ID`. | - | `clear` | Removes all the to-dos by clearing the database. | +| ------------------ | ------------------------------------------------------------ | +| `init` | Initializes the application's to-do database. | +| `add DESCRIPTION` | Adds a new to-do to the database with a `DESCRIPTION`. | +| `list` | Lists all the to-dos in the database. | +| `complete TODO_ID` | Completes a to-do by setting it as done using its `TODO_ID`. | +| `remove TODO_ID` | Removes a to-do from the database using its `TODO_ID`. | +| `clear` | Removes all the to-dos by clearing the database. | ## Release History diff --git a/typer-cli-python/source_code_final/README.md b/typer-cli-python/source_code_final/README.md index ebd47fad5e..441b466d12 100644 --- a/typer-cli-python/source_code_final/README.md +++ b/typer-cli-python/source_code_final/README.md @@ -78,13 +78,13 @@ Calling `--help` on each command provides specific and useful information about **RP to-do** has the following features: | Command | Description | - | ------------------ | ------------------------------------------------------------ | - | `init` | Initializes the application's to-do database. | - | `add DESCRIPTION` | Adds a new to-do to the database with a `DESCRIPTION`. | - | `list` | Lists all the to-dos in the database. | - | `complete TODO_ID` | Completes a to-do by setting it as done using its `TODO_ID`. | - | `remove TODO_ID` | Removes a to-do from the database using its `TODO_ID`. | - | `clear` | Removes all the to-dos by clearing the database. | +| ------------------ | ------------------------------------------------------------ | +| `init` | Initializes the application's to-do database. | +| `add DESCRIPTION` | Adds a new to-do to the database with a `DESCRIPTION`. | +| `list` | Lists all the to-dos in the database. | +| `complete TODO_ID` | Completes a to-do by setting it as done using its `TODO_ID`. | +| `remove TODO_ID` | Removes a to-do from the database using its `TODO_ID`. | +| `clear` | Removes all the to-dos by clearing the database. | ## Release History From e4cb915ea8d5500ef7c57e690b2f82fff7d9b056 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 11 Oct 2021 17:15:28 -0400 Subject: [PATCH 11/15] Rename errors --- typer-cli-python/source_code_final/rptodo/cli.py | 12 ++++++------ typer-cli-python/source_code_step_3/rptodo/cli.py | 12 ++++++------ typer-cli-python/source_code_step_4/rptodo/cli.py | 12 ++++++------ typer-cli-python/source_code_step_5/rptodo/cli.py | 12 ++++++------ typer-cli-python/source_code_step_6/rptodo/cli.py | 12 ++++++------ typer-cli-python/source_code_step_7/rptodo/cli.py | 12 ++++++------ 6 files changed, 36 insertions(+), 36 deletions(-) diff --git a/typer-cli-python/source_code_final/rptodo/cli.py b/typer-cli-python/source_code_final/rptodo/cli.py index 653c4cb1c7..6abf91ce1d 100644 --- a/typer-cli-python/source_code_final/rptodo/cli.py +++ b/typer-cli-python/source_code_final/rptodo/cli.py @@ -20,17 +20,17 @@ def init( ), ) -> None: """Initialize the to-do database.""" - error = config.init_app(db_path) - if error: + app_init_error = config.init_app(db_path) + if app_init_error: typer.secho( - f'Creating config file failed with "{ERRORS[error]}"', + f'Creating config file failed with "{ERRORS[app_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) - error = database.init_database(Path(db_path)) - if error: + db_init_error = database.init_database(Path(db_path)) + if db_init_error: typer.secho( - f'Creating database failed with "{ERRORS[error]}"', + f'Creating database failed with "{ERRORS[db_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) diff --git a/typer-cli-python/source_code_step_3/rptodo/cli.py b/typer-cli-python/source_code_step_3/rptodo/cli.py index 42f994e7d8..bc50e855cd 100644 --- a/typer-cli-python/source_code_step_3/rptodo/cli.py +++ b/typer-cli-python/source_code_step_3/rptodo/cli.py @@ -20,17 +20,17 @@ def init( ), ) -> None: """Initialize the to-do database.""" - error = config.init_app(db_path) - if error: + app_init_error = config.init_app(db_path) + if app_init_error: typer.secho( - f'Creating config file failed with "{ERRORS[error]}"', + f'Creating config file failed with "{ERRORS[app_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) - error = database.init_database(Path(db_path)) - if error: + db_init_error = database.init_database(Path(db_path)) + if db_init_error: typer.secho( - f'Creating database failed with "{ERRORS[error]}"', + f'Creating database failed with "{ERRORS[db_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) diff --git a/typer-cli-python/source_code_step_4/rptodo/cli.py b/typer-cli-python/source_code_step_4/rptodo/cli.py index 42f994e7d8..bc50e855cd 100644 --- a/typer-cli-python/source_code_step_4/rptodo/cli.py +++ b/typer-cli-python/source_code_step_4/rptodo/cli.py @@ -20,17 +20,17 @@ def init( ), ) -> None: """Initialize the to-do database.""" - error = config.init_app(db_path) - if error: + app_init_error = config.init_app(db_path) + if app_init_error: typer.secho( - f'Creating config file failed with "{ERRORS[error]}"', + f'Creating config file failed with "{ERRORS[app_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) - error = database.init_database(Path(db_path)) - if error: + db_init_error = database.init_database(Path(db_path)) + if db_init_error: typer.secho( - f'Creating database failed with "{ERRORS[error]}"', + f'Creating database failed with "{ERRORS[db_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) diff --git a/typer-cli-python/source_code_step_5/rptodo/cli.py b/typer-cli-python/source_code_step_5/rptodo/cli.py index b3f1efe32e..4eed234d48 100644 --- a/typer-cli-python/source_code_step_5/rptodo/cli.py +++ b/typer-cli-python/source_code_step_5/rptodo/cli.py @@ -20,17 +20,17 @@ def init( ), ) -> None: """Initialize the to-do database.""" - error = config.init_app(db_path) - if error: + app_init_error = config.init_app(db_path) + if app_init_error: typer.secho( - f'Creating config file failed with "{ERRORS[error]}"', + f'Creating config file failed with "{ERRORS[app_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) - error = database.init_database(Path(db_path)) - if error: + db_init_error = database.init_database(Path(db_path)) + if db_init_error: typer.secho( - f'Creating database failed with "{ERRORS[error]}"', + f'Creating database failed with "{ERRORS[db_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) diff --git a/typer-cli-python/source_code_step_6/rptodo/cli.py b/typer-cli-python/source_code_step_6/rptodo/cli.py index 77cf1fa3cb..167196e771 100644 --- a/typer-cli-python/source_code_step_6/rptodo/cli.py +++ b/typer-cli-python/source_code_step_6/rptodo/cli.py @@ -20,17 +20,17 @@ def init( ), ) -> None: """Initialize the to-do database.""" - error = config.init_app(db_path) - if error: + app_init_error = config.init_app(db_path) + if app_init_error: typer.secho( - f'Creating config file failed with "{ERRORS[error]}"', + f'Creating config file failed with "{ERRORS[app_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) - error = database.init_database(Path(db_path)) - if error: + db_init_error = database.init_database(Path(db_path)) + if db_init_error: typer.secho( - f'Creating database failed with "{ERRORS[error]}"', + f'Creating database failed with "{ERRORS[db_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) diff --git a/typer-cli-python/source_code_step_7/rptodo/cli.py b/typer-cli-python/source_code_step_7/rptodo/cli.py index 653c4cb1c7..6abf91ce1d 100644 --- a/typer-cli-python/source_code_step_7/rptodo/cli.py +++ b/typer-cli-python/source_code_step_7/rptodo/cli.py @@ -20,17 +20,17 @@ def init( ), ) -> None: """Initialize the to-do database.""" - error = config.init_app(db_path) - if error: + app_init_error = config.init_app(db_path) + if app_init_error: typer.secho( - f'Creating config file failed with "{ERRORS[error]}"', + f'Creating config file failed with "{ERRORS[app_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) - error = database.init_database(Path(db_path)) - if error: + db_init_error = database.init_database(Path(db_path)) + if db_init_error: typer.secho( - f'Creating database failed with "{ERRORS[error]}"', + f'Creating database failed with "{ERRORS[db_init_error]}"', fg=typer.colors.RED, ) raise typer.Exit(1) From 1d129c29a12e0375200fe7d89ed83e6175fcadc0 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Mon, 11 Oct 2021 17:16:12 -0400 Subject: [PATCH 12/15] Use absolute imports --- typer-cli-python/source_code_final/rptodo/config.py | 2 +- typer-cli-python/source_code_final/rptodo/database.py | 2 +- typer-cli-python/source_code_final/rptodo/rptodo.py | 4 ++-- typer-cli-python/source_code_step_3/rptodo/config.py | 2 +- typer-cli-python/source_code_step_3/rptodo/database.py | 2 +- typer-cli-python/source_code_step_4/rptodo/config.py | 2 +- typer-cli-python/source_code_step_4/rptodo/database.py | 2 +- typer-cli-python/source_code_step_4/rptodo/rptodo.py | 2 +- typer-cli-python/source_code_step_5/rptodo/config.py | 2 +- typer-cli-python/source_code_step_5/rptodo/database.py | 2 +- typer-cli-python/source_code_step_5/rptodo/rptodo.py | 4 ++-- typer-cli-python/source_code_step_6/rptodo/config.py | 2 +- typer-cli-python/source_code_step_6/rptodo/database.py | 2 +- typer-cli-python/source_code_step_6/rptodo/rptodo.py | 4 ++-- typer-cli-python/source_code_step_7/rptodo/config.py | 2 +- typer-cli-python/source_code_step_7/rptodo/database.py | 2 +- typer-cli-python/source_code_step_7/rptodo/rptodo.py | 4 ++-- 17 files changed, 21 insertions(+), 21 deletions(-) diff --git a/typer-cli-python/source_code_final/rptodo/config.py b/typer-cli-python/source_code_final/rptodo/config.py index e1fd40d6ce..219ca83902 100644 --- a/typer-cli-python/source_code_final/rptodo/config.py +++ b/typer-cli-python/source_code_final/rptodo/config.py @@ -5,7 +5,7 @@ import typer -from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ +from rptodo import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" diff --git a/typer-cli-python/source_code_final/rptodo/database.py b/typer-cli-python/source_code_final/rptodo/database.py index 4865ec2a5a..fea581e3f9 100644 --- a/typer-cli-python/source_code_final/rptodo/database.py +++ b/typer-cli-python/source_code_final/rptodo/database.py @@ -5,7 +5,7 @@ from pathlib import Path from typing import Any, Dict, List, NamedTuple -from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS +from rptodo import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS DEFAULT_DB_FILE_PATH = Path.home().joinpath( "." + Path.home().stem + "_todo.json" diff --git a/typer-cli-python/source_code_final/rptodo/rptodo.py b/typer-cli-python/source_code_final/rptodo/rptodo.py index d7e52b87ea..b675cb5169 100644 --- a/typer-cli-python/source_code_final/rptodo/rptodo.py +++ b/typer-cli-python/source_code_final/rptodo/rptodo.py @@ -3,8 +3,8 @@ from pathlib import Path from typing import Any, Dict, List, NamedTuple -from . import DB_READ_ERROR, ID_ERROR -from .database import DatabaseHandler +from rptodo import DB_READ_ERROR, ID_ERROR +from rptodo.database import DatabaseHandler class CurrentTodo(NamedTuple): diff --git a/typer-cli-python/source_code_step_3/rptodo/config.py b/typer-cli-python/source_code_step_3/rptodo/config.py index e1fd40d6ce..219ca83902 100644 --- a/typer-cli-python/source_code_step_3/rptodo/config.py +++ b/typer-cli-python/source_code_step_3/rptodo/config.py @@ -5,7 +5,7 @@ import typer -from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ +from rptodo import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" diff --git a/typer-cli-python/source_code_step_3/rptodo/database.py b/typer-cli-python/source_code_step_3/rptodo/database.py index 121307f96f..d664f5db2a 100644 --- a/typer-cli-python/source_code_step_3/rptodo/database.py +++ b/typer-cli-python/source_code_step_3/rptodo/database.py @@ -3,7 +3,7 @@ import configparser from pathlib import Path -from . import DB_WRITE_ERROR, SUCCESS +from rptodo import DB_WRITE_ERROR, SUCCESS DEFAULT_DB_FILE_PATH = Path.home().joinpath( "." + Path.home().stem + "_todo.json" diff --git a/typer-cli-python/source_code_step_4/rptodo/config.py b/typer-cli-python/source_code_step_4/rptodo/config.py index e1fd40d6ce..219ca83902 100644 --- a/typer-cli-python/source_code_step_4/rptodo/config.py +++ b/typer-cli-python/source_code_step_4/rptodo/config.py @@ -5,7 +5,7 @@ import typer -from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ +from rptodo import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" diff --git a/typer-cli-python/source_code_step_4/rptodo/database.py b/typer-cli-python/source_code_step_4/rptodo/database.py index 4865ec2a5a..fea581e3f9 100644 --- a/typer-cli-python/source_code_step_4/rptodo/database.py +++ b/typer-cli-python/source_code_step_4/rptodo/database.py @@ -5,7 +5,7 @@ from pathlib import Path from typing import Any, Dict, List, NamedTuple -from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS +from rptodo import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS DEFAULT_DB_FILE_PATH = Path.home().joinpath( "." + Path.home().stem + "_todo.json" diff --git a/typer-cli-python/source_code_step_4/rptodo/rptodo.py b/typer-cli-python/source_code_step_4/rptodo/rptodo.py index a05fcce4c8..0830d1eeed 100644 --- a/typer-cli-python/source_code_step_4/rptodo/rptodo.py +++ b/typer-cli-python/source_code_step_4/rptodo/rptodo.py @@ -3,7 +3,7 @@ from pathlib import Path from typing import Any, Dict, NamedTuple -from .database import DatabaseHandler +from rptodo.database import DatabaseHandler class CurrentTodo(NamedTuple): diff --git a/typer-cli-python/source_code_step_5/rptodo/config.py b/typer-cli-python/source_code_step_5/rptodo/config.py index e1fd40d6ce..219ca83902 100644 --- a/typer-cli-python/source_code_step_5/rptodo/config.py +++ b/typer-cli-python/source_code_step_5/rptodo/config.py @@ -5,7 +5,7 @@ import typer -from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ +from rptodo import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" diff --git a/typer-cli-python/source_code_step_5/rptodo/database.py b/typer-cli-python/source_code_step_5/rptodo/database.py index 4865ec2a5a..fea581e3f9 100644 --- a/typer-cli-python/source_code_step_5/rptodo/database.py +++ b/typer-cli-python/source_code_step_5/rptodo/database.py @@ -5,7 +5,7 @@ from pathlib import Path from typing import Any, Dict, List, NamedTuple -from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS +from rptodo import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS DEFAULT_DB_FILE_PATH = Path.home().joinpath( "." + Path.home().stem + "_todo.json" diff --git a/typer-cli-python/source_code_step_5/rptodo/rptodo.py b/typer-cli-python/source_code_step_5/rptodo/rptodo.py index 80da4fe2ea..28cc3d9132 100644 --- a/typer-cli-python/source_code_step_5/rptodo/rptodo.py +++ b/typer-cli-python/source_code_step_5/rptodo/rptodo.py @@ -3,8 +3,8 @@ from pathlib import Path from typing import Any, Dict, List, NamedTuple -from . import DB_READ_ERROR -from .database import DatabaseHandler +from rptodo import DB_READ_ERROR +from rptodo.database import DatabaseHandler class CurrentTodo(NamedTuple): diff --git a/typer-cli-python/source_code_step_6/rptodo/config.py b/typer-cli-python/source_code_step_6/rptodo/config.py index e1fd40d6ce..219ca83902 100644 --- a/typer-cli-python/source_code_step_6/rptodo/config.py +++ b/typer-cli-python/source_code_step_6/rptodo/config.py @@ -5,7 +5,7 @@ import typer -from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ +from rptodo import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" diff --git a/typer-cli-python/source_code_step_6/rptodo/database.py b/typer-cli-python/source_code_step_6/rptodo/database.py index 4865ec2a5a..fea581e3f9 100644 --- a/typer-cli-python/source_code_step_6/rptodo/database.py +++ b/typer-cli-python/source_code_step_6/rptodo/database.py @@ -5,7 +5,7 @@ from pathlib import Path from typing import Any, Dict, List, NamedTuple -from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS +from rptodo import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS DEFAULT_DB_FILE_PATH = Path.home().joinpath( "." + Path.home().stem + "_todo.json" diff --git a/typer-cli-python/source_code_step_6/rptodo/rptodo.py b/typer-cli-python/source_code_step_6/rptodo/rptodo.py index 9021dd2c75..700fbdd2f4 100644 --- a/typer-cli-python/source_code_step_6/rptodo/rptodo.py +++ b/typer-cli-python/source_code_step_6/rptodo/rptodo.py @@ -3,8 +3,8 @@ from pathlib import Path from typing import Any, Dict, List, NamedTuple -from . import DB_READ_ERROR, ID_ERROR -from .database import DatabaseHandler +from rptodo import DB_READ_ERROR, ID_ERROR +from rptodo.database import DatabaseHandler class CurrentTodo(NamedTuple): diff --git a/typer-cli-python/source_code_step_7/rptodo/config.py b/typer-cli-python/source_code_step_7/rptodo/config.py index e1fd40d6ce..219ca83902 100644 --- a/typer-cli-python/source_code_step_7/rptodo/config.py +++ b/typer-cli-python/source_code_step_7/rptodo/config.py @@ -5,7 +5,7 @@ import typer -from . import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ +from rptodo import DB_WRITE_ERROR, DIR_ERROR, FILE_ERROR, SUCCESS, __app_name__ CONFIG_DIR_PATH = Path(typer.get_app_dir(__app_name__)) CONFIG_FILE_PATH = CONFIG_DIR_PATH / "config.ini" diff --git a/typer-cli-python/source_code_step_7/rptodo/database.py b/typer-cli-python/source_code_step_7/rptodo/database.py index 4865ec2a5a..fea581e3f9 100644 --- a/typer-cli-python/source_code_step_7/rptodo/database.py +++ b/typer-cli-python/source_code_step_7/rptodo/database.py @@ -5,7 +5,7 @@ from pathlib import Path from typing import Any, Dict, List, NamedTuple -from . import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS +from rptodo import DB_READ_ERROR, DB_WRITE_ERROR, JSON_ERROR, SUCCESS DEFAULT_DB_FILE_PATH = Path.home().joinpath( "." + Path.home().stem + "_todo.json" diff --git a/typer-cli-python/source_code_step_7/rptodo/rptodo.py b/typer-cli-python/source_code_step_7/rptodo/rptodo.py index d7e52b87ea..b675cb5169 100644 --- a/typer-cli-python/source_code_step_7/rptodo/rptodo.py +++ b/typer-cli-python/source_code_step_7/rptodo/rptodo.py @@ -3,8 +3,8 @@ from pathlib import Path from typing import Any, Dict, List, NamedTuple -from . import DB_READ_ERROR, ID_ERROR -from .database import DatabaseHandler +from rptodo import DB_READ_ERROR, ID_ERROR +from rptodo.database import DatabaseHandler class CurrentTodo(NamedTuple): From 48c1e520f694ca73de0dd8c2a412d34e128b0832 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Tue, 12 Oct 2021 14:19:21 -0400 Subject: [PATCH 13/15] Update requirements.txt --- typer-cli-python/source_code_final/requirements.txt | 4 +++- typer-cli-python/source_code_step_1/requirements.txt | 4 +++- typer-cli-python/source_code_step_2/requirements.txt | 4 +++- typer-cli-python/source_code_step_3/requirements.txt | 4 +++- typer-cli-python/source_code_step_4/requirements.txt | 4 +++- typer-cli-python/source_code_step_5/requirements.txt | 4 +++- typer-cli-python/source_code_step_6/requirements.txt | 4 +++- typer-cli-python/source_code_step_7/requirements.txt | 4 +++- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/typer-cli-python/source_code_final/requirements.txt b/typer-cli-python/source_code_final/requirements.txt index 5843b5256d..e5e0199018 100644 --- a/typer-cli-python/source_code_final/requirements.txt +++ b/typer-cli-python/source_code_final/requirements.txt @@ -1,2 +1,4 @@ -typer[all]==0.3.2 +typer==0.3.2 +colorama==0.4.4 +shellingham==1.4.0 pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_1/requirements.txt b/typer-cli-python/source_code_step_1/requirements.txt index 5843b5256d..e5e0199018 100644 --- a/typer-cli-python/source_code_step_1/requirements.txt +++ b/typer-cli-python/source_code_step_1/requirements.txt @@ -1,2 +1,4 @@ -typer[all]==0.3.2 +typer==0.3.2 +colorama==0.4.4 +shellingham==1.4.0 pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_2/requirements.txt b/typer-cli-python/source_code_step_2/requirements.txt index 5843b5256d..e5e0199018 100644 --- a/typer-cli-python/source_code_step_2/requirements.txt +++ b/typer-cli-python/source_code_step_2/requirements.txt @@ -1,2 +1,4 @@ -typer[all]==0.3.2 +typer==0.3.2 +colorama==0.4.4 +shellingham==1.4.0 pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_3/requirements.txt b/typer-cli-python/source_code_step_3/requirements.txt index 5843b5256d..e5e0199018 100644 --- a/typer-cli-python/source_code_step_3/requirements.txt +++ b/typer-cli-python/source_code_step_3/requirements.txt @@ -1,2 +1,4 @@ -typer[all]==0.3.2 +typer==0.3.2 +colorama==0.4.4 +shellingham==1.4.0 pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_4/requirements.txt b/typer-cli-python/source_code_step_4/requirements.txt index 5843b5256d..e5e0199018 100644 --- a/typer-cli-python/source_code_step_4/requirements.txt +++ b/typer-cli-python/source_code_step_4/requirements.txt @@ -1,2 +1,4 @@ -typer[all]==0.3.2 +typer==0.3.2 +colorama==0.4.4 +shellingham==1.4.0 pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_5/requirements.txt b/typer-cli-python/source_code_step_5/requirements.txt index 5843b5256d..e5e0199018 100644 --- a/typer-cli-python/source_code_step_5/requirements.txt +++ b/typer-cli-python/source_code_step_5/requirements.txt @@ -1,2 +1,4 @@ -typer[all]==0.3.2 +typer==0.3.2 +colorama==0.4.4 +shellingham==1.4.0 pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_6/requirements.txt b/typer-cli-python/source_code_step_6/requirements.txt index 5843b5256d..e5e0199018 100644 --- a/typer-cli-python/source_code_step_6/requirements.txt +++ b/typer-cli-python/source_code_step_6/requirements.txt @@ -1,2 +1,4 @@ -typer[all]==0.3.2 +typer==0.3.2 +colorama==0.4.4 +shellingham==1.4.0 pytest==6.2.4 diff --git a/typer-cli-python/source_code_step_7/requirements.txt b/typer-cli-python/source_code_step_7/requirements.txt index 5843b5256d..e5e0199018 100644 --- a/typer-cli-python/source_code_step_7/requirements.txt +++ b/typer-cli-python/source_code_step_7/requirements.txt @@ -1,2 +1,4 @@ -typer[all]==0.3.2 +typer==0.3.2 +colorama==0.4.4 +shellingham==1.4.0 pytest==6.2.4 From 73a239f7f66ebd884d49508d7884939a0f1f75c3 Mon Sep 17 00:00:00 2001 From: Leodanis Pozo Ramos Date: Tue, 19 Oct 2021 06:30:40 -0400 Subject: [PATCH 14/15] DR update --- typer-cli-python/README.md | 8 ++++---- typer-cli-python/source_code_final/README.md | 8 ++++---- typer-cli-python/source_code_final/rptodo/__init__.py | 2 +- typer-cli-python/source_code_final/rptodo/__main__.py | 2 +- typer-cli-python/source_code_final/rptodo/cli.py | 2 +- typer-cli-python/source_code_final/rptodo/config.py | 2 +- typer-cli-python/source_code_final/rptodo/database.py | 2 +- typer-cli-python/source_code_final/rptodo/rptodo.py | 2 +- typer-cli-python/source_code_step_2/rptodo/__init__.py | 2 +- typer-cli-python/source_code_step_2/rptodo/__main__.py | 2 +- typer-cli-python/source_code_step_2/rptodo/cli.py | 2 +- typer-cli-python/source_code_step_3/rptodo/__init__.py | 2 +- typer-cli-python/source_code_step_3/rptodo/__main__.py | 2 +- typer-cli-python/source_code_step_3/rptodo/cli.py | 2 +- typer-cli-python/source_code_step_3/rptodo/config.py | 2 +- typer-cli-python/source_code_step_3/rptodo/database.py | 2 +- typer-cli-python/source_code_step_4/rptodo/__init__.py | 2 +- typer-cli-python/source_code_step_4/rptodo/__main__.py | 2 +- typer-cli-python/source_code_step_4/rptodo/cli.py | 2 +- typer-cli-python/source_code_step_4/rptodo/config.py | 2 +- typer-cli-python/source_code_step_4/rptodo/database.py | 2 +- typer-cli-python/source_code_step_4/rptodo/rptodo.py | 2 +- typer-cli-python/source_code_step_5/rptodo/__init__.py | 2 +- typer-cli-python/source_code_step_5/rptodo/__main__.py | 2 +- typer-cli-python/source_code_step_5/rptodo/cli.py | 2 +- typer-cli-python/source_code_step_5/rptodo/config.py | 2 +- typer-cli-python/source_code_step_5/rptodo/database.py | 2 +- typer-cli-python/source_code_step_5/rptodo/rptodo.py | 2 +- typer-cli-python/source_code_step_6/rptodo/__init__.py | 2 +- typer-cli-python/source_code_step_6/rptodo/__main__.py | 2 +- typer-cli-python/source_code_step_6/rptodo/cli.py | 2 +- typer-cli-python/source_code_step_6/rptodo/config.py | 2 +- typer-cli-python/source_code_step_6/rptodo/database.py | 2 +- typer-cli-python/source_code_step_6/rptodo/rptodo.py | 2 +- typer-cli-python/source_code_step_7/rptodo/__init__.py | 2 +- typer-cli-python/source_code_step_7/rptodo/__main__.py | 2 +- typer-cli-python/source_code_step_7/rptodo/cli.py | 2 +- typer-cli-python/source_code_step_7/rptodo/config.py | 2 +- typer-cli-python/source_code_step_7/rptodo/database.py | 2 +- typer-cli-python/source_code_step_7/rptodo/rptodo.py | 2 +- 40 files changed, 46 insertions(+), 46 deletions(-) diff --git a/typer-cli-python/README.md b/typer-cli-python/README.md index 441b466d12..ff68e807b1 100644 --- a/typer-cli-python/README.md +++ b/typer-cli-python/README.md @@ -1,10 +1,10 @@ -# RP to-do +# RP To-Do -**RP to-do** is a command-line interface application built with [Typer](https://typer.tiangolo.com/) to help you manage your to-do list. +**RP To-Do** is a command-line interface application built with [Typer](https://typer.tiangolo.com/) to help you manage your to-do list. ## Installation -To run **RP to-do**, you need to run the following steps: +To run **RP To-Do**, you need to run the following steps: 1. Download the application's source code to a `rptodo_project/` directory 2. Create a Python virtual environment and activate it @@ -75,7 +75,7 @@ Calling `--help` on each command provides specific and useful information about ## Features -**RP to-do** has the following features: +**RP To-Do** has the following features: | Command | Description | | ------------------ | ------------------------------------------------------------ | diff --git a/typer-cli-python/source_code_final/README.md b/typer-cli-python/source_code_final/README.md index 441b466d12..ff68e807b1 100644 --- a/typer-cli-python/source_code_final/README.md +++ b/typer-cli-python/source_code_final/README.md @@ -1,10 +1,10 @@ -# RP to-do +# RP To-Do -**RP to-do** is a command-line interface application built with [Typer](https://typer.tiangolo.com/) to help you manage your to-do list. +**RP To-Do** is a command-line interface application built with [Typer](https://typer.tiangolo.com/) to help you manage your to-do list. ## Installation -To run **RP to-do**, you need to run the following steps: +To run **RP To-Do**, you need to run the following steps: 1. Download the application's source code to a `rptodo_project/` directory 2. Create a Python virtual environment and activate it @@ -75,7 +75,7 @@ Calling `--help` on each command provides specific and useful information about ## Features -**RP to-do** has the following features: +**RP To-Do** has the following features: | Command | Description | | ------------------ | ------------------------------------------------------------ | diff --git a/typer-cli-python/source_code_final/rptodo/__init__.py b/typer-cli-python/source_code_final/rptodo/__init__.py index fc5ba0e413..346d9d75ed 100644 --- a/typer-cli-python/source_code_final/rptodo/__init__.py +++ b/typer-cli-python/source_code_final/rptodo/__init__.py @@ -1,4 +1,4 @@ -"""Top-level package for RP to-do.""" +"""Top-level package for RP To-Do.""" __app_name__ = "rptodo" __version__ = "0.1.0" diff --git a/typer-cli-python/source_code_final/rptodo/__main__.py b/typer-cli-python/source_code_final/rptodo/__main__.py index 79c8c51733..57c45b04a2 100644 --- a/typer-cli-python/source_code_final/rptodo/__main__.py +++ b/typer-cli-python/source_code_final/rptodo/__main__.py @@ -1,4 +1,4 @@ -"""RP to-do entry point script.""" +"""RP To-Do entry point script.""" from rptodo import cli, __app_name__ diff --git a/typer-cli-python/source_code_final/rptodo/cli.py b/typer-cli-python/source_code_final/rptodo/cli.py index 6abf91ce1d..9e9d84944a 100644 --- a/typer-cli-python/source_code_final/rptodo/cli.py +++ b/typer-cli-python/source_code_final/rptodo/cli.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do CLI.""" +"""This module provides the RP To-Do CLI.""" from pathlib import Path from typing import List, Optional diff --git a/typer-cli-python/source_code_final/rptodo/config.py b/typer-cli-python/source_code_final/rptodo/config.py index 219ca83902..22d8a30467 100644 --- a/typer-cli-python/source_code_final/rptodo/config.py +++ b/typer-cli-python/source_code_final/rptodo/config.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do config functionality.""" +"""This module provides the RP To-Do config functionality.""" import configparser from pathlib import Path diff --git a/typer-cli-python/source_code_final/rptodo/database.py b/typer-cli-python/source_code_final/rptodo/database.py index fea581e3f9..b703fafc25 100644 --- a/typer-cli-python/source_code_final/rptodo/database.py +++ b/typer-cli-python/source_code_final/rptodo/database.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do database functionality.""" +"""This module provides the RP To-Do database functionality.""" import configparser import json diff --git a/typer-cli-python/source_code_final/rptodo/rptodo.py b/typer-cli-python/source_code_final/rptodo/rptodo.py index b675cb5169..ec53186132 100644 --- a/typer-cli-python/source_code_final/rptodo/rptodo.py +++ b/typer-cli-python/source_code_final/rptodo/rptodo.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do model-controller.""" +"""This module provides the RP To-Do model-controller.""" from pathlib import Path from typing import Any, Dict, List, NamedTuple diff --git a/typer-cli-python/source_code_step_2/rptodo/__init__.py b/typer-cli-python/source_code_step_2/rptodo/__init__.py index fc5ba0e413..346d9d75ed 100644 --- a/typer-cli-python/source_code_step_2/rptodo/__init__.py +++ b/typer-cli-python/source_code_step_2/rptodo/__init__.py @@ -1,4 +1,4 @@ -"""Top-level package for RP to-do.""" +"""Top-level package for RP To-Do.""" __app_name__ = "rptodo" __version__ = "0.1.0" diff --git a/typer-cli-python/source_code_step_2/rptodo/__main__.py b/typer-cli-python/source_code_step_2/rptodo/__main__.py index 79c8c51733..57c45b04a2 100644 --- a/typer-cli-python/source_code_step_2/rptodo/__main__.py +++ b/typer-cli-python/source_code_step_2/rptodo/__main__.py @@ -1,4 +1,4 @@ -"""RP to-do entry point script.""" +"""RP To-Do entry point script.""" from rptodo import cli, __app_name__ diff --git a/typer-cli-python/source_code_step_2/rptodo/cli.py b/typer-cli-python/source_code_step_2/rptodo/cli.py index cc9cb737e1..d9733cb8dd 100644 --- a/typer-cli-python/source_code_step_2/rptodo/cli.py +++ b/typer-cli-python/source_code_step_2/rptodo/cli.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do CLI.""" +"""This module provides the RP To-Do CLI.""" from typing import Optional diff --git a/typer-cli-python/source_code_step_3/rptodo/__init__.py b/typer-cli-python/source_code_step_3/rptodo/__init__.py index fc5ba0e413..346d9d75ed 100644 --- a/typer-cli-python/source_code_step_3/rptodo/__init__.py +++ b/typer-cli-python/source_code_step_3/rptodo/__init__.py @@ -1,4 +1,4 @@ -"""Top-level package for RP to-do.""" +"""Top-level package for RP To-Do.""" __app_name__ = "rptodo" __version__ = "0.1.0" diff --git a/typer-cli-python/source_code_step_3/rptodo/__main__.py b/typer-cli-python/source_code_step_3/rptodo/__main__.py index 79c8c51733..57c45b04a2 100644 --- a/typer-cli-python/source_code_step_3/rptodo/__main__.py +++ b/typer-cli-python/source_code_step_3/rptodo/__main__.py @@ -1,4 +1,4 @@ -"""RP to-do entry point script.""" +"""RP To-Do entry point script.""" from rptodo import cli, __app_name__ diff --git a/typer-cli-python/source_code_step_3/rptodo/cli.py b/typer-cli-python/source_code_step_3/rptodo/cli.py index bc50e855cd..89531fcd5b 100644 --- a/typer-cli-python/source_code_step_3/rptodo/cli.py +++ b/typer-cli-python/source_code_step_3/rptodo/cli.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do CLI.""" +"""This module provides the RP To-Do CLI.""" from pathlib import Path from typing import Optional diff --git a/typer-cli-python/source_code_step_3/rptodo/config.py b/typer-cli-python/source_code_step_3/rptodo/config.py index 219ca83902..22d8a30467 100644 --- a/typer-cli-python/source_code_step_3/rptodo/config.py +++ b/typer-cli-python/source_code_step_3/rptodo/config.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do config functionality.""" +"""This module provides the RP To-Do config functionality.""" import configparser from pathlib import Path diff --git a/typer-cli-python/source_code_step_3/rptodo/database.py b/typer-cli-python/source_code_step_3/rptodo/database.py index d664f5db2a..a8f706d582 100644 --- a/typer-cli-python/source_code_step_3/rptodo/database.py +++ b/typer-cli-python/source_code_step_3/rptodo/database.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do database functionality.""" +"""This module provides the RP To-Do database functionality.""" import configparser from pathlib import Path diff --git a/typer-cli-python/source_code_step_4/rptodo/__init__.py b/typer-cli-python/source_code_step_4/rptodo/__init__.py index fc5ba0e413..346d9d75ed 100644 --- a/typer-cli-python/source_code_step_4/rptodo/__init__.py +++ b/typer-cli-python/source_code_step_4/rptodo/__init__.py @@ -1,4 +1,4 @@ -"""Top-level package for RP to-do.""" +"""Top-level package for RP To-Do.""" __app_name__ = "rptodo" __version__ = "0.1.0" diff --git a/typer-cli-python/source_code_step_4/rptodo/__main__.py b/typer-cli-python/source_code_step_4/rptodo/__main__.py index 79c8c51733..57c45b04a2 100644 --- a/typer-cli-python/source_code_step_4/rptodo/__main__.py +++ b/typer-cli-python/source_code_step_4/rptodo/__main__.py @@ -1,4 +1,4 @@ -"""RP to-do entry point script.""" +"""RP To-Do entry point script.""" from rptodo import cli, __app_name__ diff --git a/typer-cli-python/source_code_step_4/rptodo/cli.py b/typer-cli-python/source_code_step_4/rptodo/cli.py index bc50e855cd..89531fcd5b 100644 --- a/typer-cli-python/source_code_step_4/rptodo/cli.py +++ b/typer-cli-python/source_code_step_4/rptodo/cli.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do CLI.""" +"""This module provides the RP To-Do CLI.""" from pathlib import Path from typing import Optional diff --git a/typer-cli-python/source_code_step_4/rptodo/config.py b/typer-cli-python/source_code_step_4/rptodo/config.py index 219ca83902..22d8a30467 100644 --- a/typer-cli-python/source_code_step_4/rptodo/config.py +++ b/typer-cli-python/source_code_step_4/rptodo/config.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do config functionality.""" +"""This module provides the RP To-Do config functionality.""" import configparser from pathlib import Path diff --git a/typer-cli-python/source_code_step_4/rptodo/database.py b/typer-cli-python/source_code_step_4/rptodo/database.py index fea581e3f9..b703fafc25 100644 --- a/typer-cli-python/source_code_step_4/rptodo/database.py +++ b/typer-cli-python/source_code_step_4/rptodo/database.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do database functionality.""" +"""This module provides the RP To-Do database functionality.""" import configparser import json diff --git a/typer-cli-python/source_code_step_4/rptodo/rptodo.py b/typer-cli-python/source_code_step_4/rptodo/rptodo.py index 0830d1eeed..fa9bc43c9d 100644 --- a/typer-cli-python/source_code_step_4/rptodo/rptodo.py +++ b/typer-cli-python/source_code_step_4/rptodo/rptodo.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do model-controller.""" +"""This module provides the RP To-Do model-controller.""" from pathlib import Path from typing import Any, Dict, NamedTuple diff --git a/typer-cli-python/source_code_step_5/rptodo/__init__.py b/typer-cli-python/source_code_step_5/rptodo/__init__.py index fc5ba0e413..346d9d75ed 100644 --- a/typer-cli-python/source_code_step_5/rptodo/__init__.py +++ b/typer-cli-python/source_code_step_5/rptodo/__init__.py @@ -1,4 +1,4 @@ -"""Top-level package for RP to-do.""" +"""Top-level package for RP To-Do.""" __app_name__ = "rptodo" __version__ = "0.1.0" diff --git a/typer-cli-python/source_code_step_5/rptodo/__main__.py b/typer-cli-python/source_code_step_5/rptodo/__main__.py index 79c8c51733..57c45b04a2 100644 --- a/typer-cli-python/source_code_step_5/rptodo/__main__.py +++ b/typer-cli-python/source_code_step_5/rptodo/__main__.py @@ -1,4 +1,4 @@ -"""RP to-do entry point script.""" +"""RP To-Do entry point script.""" from rptodo import cli, __app_name__ diff --git a/typer-cli-python/source_code_step_5/rptodo/cli.py b/typer-cli-python/source_code_step_5/rptodo/cli.py index 4eed234d48..b3277ecc12 100644 --- a/typer-cli-python/source_code_step_5/rptodo/cli.py +++ b/typer-cli-python/source_code_step_5/rptodo/cli.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do CLI.""" +"""This module provides the RP To-Do CLI.""" from pathlib import Path from typing import List, Optional diff --git a/typer-cli-python/source_code_step_5/rptodo/config.py b/typer-cli-python/source_code_step_5/rptodo/config.py index 219ca83902..22d8a30467 100644 --- a/typer-cli-python/source_code_step_5/rptodo/config.py +++ b/typer-cli-python/source_code_step_5/rptodo/config.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do config functionality.""" +"""This module provides the RP To-Do config functionality.""" import configparser from pathlib import Path diff --git a/typer-cli-python/source_code_step_5/rptodo/database.py b/typer-cli-python/source_code_step_5/rptodo/database.py index fea581e3f9..b703fafc25 100644 --- a/typer-cli-python/source_code_step_5/rptodo/database.py +++ b/typer-cli-python/source_code_step_5/rptodo/database.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do database functionality.""" +"""This module provides the RP To-Do database functionality.""" import configparser import json diff --git a/typer-cli-python/source_code_step_5/rptodo/rptodo.py b/typer-cli-python/source_code_step_5/rptodo/rptodo.py index 28cc3d9132..04636de081 100644 --- a/typer-cli-python/source_code_step_5/rptodo/rptodo.py +++ b/typer-cli-python/source_code_step_5/rptodo/rptodo.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do model-controller.""" +"""This module provides the RP To-Do model-controller.""" from pathlib import Path from typing import Any, Dict, List, NamedTuple diff --git a/typer-cli-python/source_code_step_6/rptodo/__init__.py b/typer-cli-python/source_code_step_6/rptodo/__init__.py index fc5ba0e413..346d9d75ed 100644 --- a/typer-cli-python/source_code_step_6/rptodo/__init__.py +++ b/typer-cli-python/source_code_step_6/rptodo/__init__.py @@ -1,4 +1,4 @@ -"""Top-level package for RP to-do.""" +"""Top-level package for RP To-Do.""" __app_name__ = "rptodo" __version__ = "0.1.0" diff --git a/typer-cli-python/source_code_step_6/rptodo/__main__.py b/typer-cli-python/source_code_step_6/rptodo/__main__.py index 79c8c51733..57c45b04a2 100644 --- a/typer-cli-python/source_code_step_6/rptodo/__main__.py +++ b/typer-cli-python/source_code_step_6/rptodo/__main__.py @@ -1,4 +1,4 @@ -"""RP to-do entry point script.""" +"""RP To-Do entry point script.""" from rptodo import cli, __app_name__ diff --git a/typer-cli-python/source_code_step_6/rptodo/cli.py b/typer-cli-python/source_code_step_6/rptodo/cli.py index 167196e771..3956d0561c 100644 --- a/typer-cli-python/source_code_step_6/rptodo/cli.py +++ b/typer-cli-python/source_code_step_6/rptodo/cli.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do CLI.""" +"""This module provides the RP To-Do CLI.""" from pathlib import Path from typing import List, Optional diff --git a/typer-cli-python/source_code_step_6/rptodo/config.py b/typer-cli-python/source_code_step_6/rptodo/config.py index 219ca83902..22d8a30467 100644 --- a/typer-cli-python/source_code_step_6/rptodo/config.py +++ b/typer-cli-python/source_code_step_6/rptodo/config.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do config functionality.""" +"""This module provides the RP To-Do config functionality.""" import configparser from pathlib import Path diff --git a/typer-cli-python/source_code_step_6/rptodo/database.py b/typer-cli-python/source_code_step_6/rptodo/database.py index fea581e3f9..b703fafc25 100644 --- a/typer-cli-python/source_code_step_6/rptodo/database.py +++ b/typer-cli-python/source_code_step_6/rptodo/database.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do database functionality.""" +"""This module provides the RP To-Do database functionality.""" import configparser import json diff --git a/typer-cli-python/source_code_step_6/rptodo/rptodo.py b/typer-cli-python/source_code_step_6/rptodo/rptodo.py index 700fbdd2f4..0e338cfdbe 100644 --- a/typer-cli-python/source_code_step_6/rptodo/rptodo.py +++ b/typer-cli-python/source_code_step_6/rptodo/rptodo.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do model-controller.""" +"""This module provides the RP To-Do model-controller.""" from pathlib import Path from typing import Any, Dict, List, NamedTuple diff --git a/typer-cli-python/source_code_step_7/rptodo/__init__.py b/typer-cli-python/source_code_step_7/rptodo/__init__.py index fc5ba0e413..346d9d75ed 100644 --- a/typer-cli-python/source_code_step_7/rptodo/__init__.py +++ b/typer-cli-python/source_code_step_7/rptodo/__init__.py @@ -1,4 +1,4 @@ -"""Top-level package for RP to-do.""" +"""Top-level package for RP To-Do.""" __app_name__ = "rptodo" __version__ = "0.1.0" diff --git a/typer-cli-python/source_code_step_7/rptodo/__main__.py b/typer-cli-python/source_code_step_7/rptodo/__main__.py index 79c8c51733..57c45b04a2 100644 --- a/typer-cli-python/source_code_step_7/rptodo/__main__.py +++ b/typer-cli-python/source_code_step_7/rptodo/__main__.py @@ -1,4 +1,4 @@ -"""RP to-do entry point script.""" +"""RP To-Do entry point script.""" from rptodo import cli, __app_name__ diff --git a/typer-cli-python/source_code_step_7/rptodo/cli.py b/typer-cli-python/source_code_step_7/rptodo/cli.py index 6abf91ce1d..9e9d84944a 100644 --- a/typer-cli-python/source_code_step_7/rptodo/cli.py +++ b/typer-cli-python/source_code_step_7/rptodo/cli.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do CLI.""" +"""This module provides the RP To-Do CLI.""" from pathlib import Path from typing import List, Optional diff --git a/typer-cli-python/source_code_step_7/rptodo/config.py b/typer-cli-python/source_code_step_7/rptodo/config.py index 219ca83902..22d8a30467 100644 --- a/typer-cli-python/source_code_step_7/rptodo/config.py +++ b/typer-cli-python/source_code_step_7/rptodo/config.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do config functionality.""" +"""This module provides the RP To-Do config functionality.""" import configparser from pathlib import Path diff --git a/typer-cli-python/source_code_step_7/rptodo/database.py b/typer-cli-python/source_code_step_7/rptodo/database.py index fea581e3f9..b703fafc25 100644 --- a/typer-cli-python/source_code_step_7/rptodo/database.py +++ b/typer-cli-python/source_code_step_7/rptodo/database.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do database functionality.""" +"""This module provides the RP To-Do database functionality.""" import configparser import json diff --git a/typer-cli-python/source_code_step_7/rptodo/rptodo.py b/typer-cli-python/source_code_step_7/rptodo/rptodo.py index b675cb5169..ec53186132 100644 --- a/typer-cli-python/source_code_step_7/rptodo/rptodo.py +++ b/typer-cli-python/source_code_step_7/rptodo/rptodo.py @@ -1,4 +1,4 @@ -"""This module provides the RP to-do model-controller.""" +"""This module provides the RP To-Do model-controller.""" from pathlib import Path from typing import Any, Dict, List, NamedTuple From 934a86683e8d17a0fcf25acda959f5d89c4071b3 Mon Sep 17 00:00:00 2001 From: Sadie Parker Date: Sat, 30 Oct 2021 10:33:28 +0200 Subject: [PATCH 15/15] Update README.md --- typer-cli-python/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typer-cli-python/README.md b/typer-cli-python/README.md index ff68e807b1..ed554f8e8d 100644 --- a/typer-cli-python/README.md +++ b/typer-cli-python/README.md @@ -28,7 +28,7 @@ $ source venv/bin/activate (venv) $ python -m rptodo init ``` -This command asks you to introduce the file path to store the application's database. You can also accept the default file path by pressing enter. +This command asks you to introduce the file path to store the application's database. You can also accept the default file path by pressing Enter. ## Usage