From 330da01b8ef5cb7bf04df7220c95c530c58983e6 Mon Sep 17 00:00:00 2001 From: Scott <38087336+mergemaven11@users.noreply.github.com> Date: Sat, 18 May 2024 08:37:36 -0400 Subject: [PATCH] with test & resructure dir --- cli/__init__.py | 0 cli/handlers.py | 45 +++++++++++++++++ journal.py => cli/journal.py | 4 +- utils.py => cli/utils.py | 0 handlers.py | 64 ----------------------- poetry.lock | 98 +++++++++++++++++++++++++++++++++++- pyproject.toml | 2 + tests/__init__.py | 0 tests/test_handlers.py | 66 ++++++++++++++++++++++++ tests/test_utils.py | 49 ++++++++++++++++++ 10 files changed, 261 insertions(+), 67 deletions(-) create mode 100644 cli/__init__.py create mode 100644 cli/handlers.py rename journal.py => cli/journal.py (90%) rename utils.py => cli/utils.py (100%) delete mode 100644 handlers.py create mode 100644 tests/__init__.py create mode 100644 tests/test_handlers.py create mode 100644 tests/test_utils.py diff --git a/cli/__init__.py b/cli/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/cli/handlers.py b/cli/handlers.py new file mode 100644 index 0000000..94db0f8 --- /dev/null +++ b/cli/handlers.py @@ -0,0 +1,45 @@ +import json +import uuid +import typing as t + +import cli.utils as util # Import utility functions + +def add_entry_to_file(entry_obj: t.Dict[str, t.Any], entries_file: str) -> None: + """ + Add a JSON object representing a journal entry to the entries file. + + Args: + entry_obj (Dict[str, Any]): Dictionary representing the journal entry. + entries_file (str): Path to the entries file. + + Returns: + None + """ + # Load existing entries from the file + with open(entries_file, 'r') as f: + entries_data: list = json.load(f) + + # Generate a unique ID and timestamp for the new entry + entry_obj['id'] = str(uuid.uuid4()) + entry_obj['timestamp'] = util.current_datetime() + + # Append the new entry object to the existing list + entries_data.append(entry_obj) + + # Write the updated entry data back to the file + with open(entries_file, 'w') as f: + json.dump(entries_data, f, indent=4) # indent for pretty printing + +# Searching an entry + +def search_entries(title: str): + """ Search Entires by title, dropdown selection for muliple finds. + + View all vs view one + + Args: + title (str): _description_ + """ + pass + +# viewing an entry \ No newline at end of file diff --git a/journal.py b/cli/journal.py similarity index 90% rename from journal.py rename to cli/journal.py index 480aeff..7f0fbe1 100644 --- a/journal.py +++ b/cli/journal.py @@ -1,6 +1,6 @@ import typer import handlers as handler -import utils as util +import cli.utils as util app = typer.Typer() @@ -13,7 +13,7 @@ def add(): title = typer.prompt("Please enter a title") entry = typer.prompt("Please enter your journal entry") # Send data to add handler - handler.add_entry_to_file({"Title": title, "entry": entry}) + handler.add_entry_to_file({"Title": title, "Entry": entry}) @app.command() diff --git a/utils.py b/cli/utils.py similarity index 100% rename from utils.py rename to cli/utils.py diff --git a/handlers.py b/handlers.py deleted file mode 100644 index a9ce63c..0000000 --- a/handlers.py +++ /dev/null @@ -1,64 +0,0 @@ -import typing as t -import json -import os -import uuid # Import the uuid module to generate unique IDs -import utils as util - - -# Add entry - -def add_entry_to_file(entry_obj: t.Dict[str, any]): - """ - Add a JSON object representing a journal entry to the entries file. - - # Example usage - new_entry = { - "id": "982ija902i28129", - "date": "2024-05-17", - "title": "My New Entry", - "content": "This is my new journal entry." - } - """ - entries_file = 'entries/entries.json' - - # Check if the entries file exists, if not, create it with an empty list - if not os.path.exists(entries_file): - with open(entries_file, 'w') as f: - json.dump([], f) - - # Load existing entries from the file - with open(entries_file, 'r') as f: - entries_data = json.load(f) - - # Generate a unique ID for the new entry - entry_id = str(uuid.uuid4()) - - # Add the ID to the entry object - entry_obj['id'] = entry_id - - # Add the datetime stamp - entry_obj['timestamp'] = util.current_datetime() - - # Append the new entry object to the existing list - entries_data.append(entry_obj) - - # Write the updated entries data back to the file - with open(entries_file, 'w') as f: - json.dump(entries_data, f, indent=4) # indent for pretty printing - - print(entry_obj) - - -# Searching an entry - -def search_entries(title: str): - """ Search Entires by title, dropdown selection for muliple finds. - - View all vs view one - - Args: - title (str): _description_ - """ - pass - -# viewing an entry diff --git a/poetry.lock b/poetry.lock index d2d7c3e..4434693 100644 --- a/poetry.lock +++ b/poetry.lock @@ -25,6 +25,31 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +[[package]] +name = "freezegun" +version = "1.5.1" +description = "Let your Python tests travel through time" +optional = false +python-versions = ">=3.7" +files = [ + {file = "freezegun-1.5.1-py3-none-any.whl", hash = "sha256:bf111d7138a8abe55ab48a71755673dbaa4ab87f4cff5634a4442dfec34c15f1"}, + {file = "freezegun-1.5.1.tar.gz", hash = "sha256:b29dedfcda6d5e8e083ce71b2b542753ad48cfec44037b3fc79702e2980a89e9"}, +] + +[package.dependencies] +python-dateutil = ">=2.7" + +[[package]] +name = "iniconfig" +version = "2.0.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.7" +files = [ + {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, + {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, +] + [[package]] name = "markdown-it-py" version = "3.0.0" @@ -60,6 +85,32 @@ files = [ {file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"}, ] +[[package]] +name = "packaging" +version = "24.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, + {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + [[package]] name = "pygments" version = "2.18.0" @@ -74,6 +125,40 @@ files = [ [package.extras] windows-terminal = ["colorama (>=0.4.6)"] +[[package]] +name = "pytest" +version = "8.2.0" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.2.0-py3-none-any.whl", hash = "sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233"}, + {file = "pytest-8.2.0.tar.gz", hash = "sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2.0" + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + [[package]] name = "rich" version = "13.7.1" @@ -103,6 +188,17 @@ files = [ {file = "shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de"}, ] +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "typer" version = "0.12.3" @@ -134,4 +230,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "288210d68b53e9f92f04441767e3f9e9dbdab52d3c183d5aeca19af4c18c58ab" +content-hash = "3a9e106acea18843ea40c5171a90978d3dee0d481e68901b1296d0199bfbe5b6" diff --git a/pyproject.toml b/pyproject.toml index f949431..165ff1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,8 @@ readme = "README.md" [tool.poetry.dependencies] python = "^3.12" typer = "^0.12.3" +pytest = "^8.2.0" +freezegun = "^1.5.1" [build-system] diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_handlers.py b/tests/test_handlers.py new file mode 100644 index 0000000..764dad2 --- /dev/null +++ b/tests/test_handlers.py @@ -0,0 +1,66 @@ +import json +import os +import pytest +from uuid import UUID +from datetime import datetime + +import cli.handlers as handler + +@pytest.fixture +def temp_entries_file(tmp_path): + """ + Fixture to create a temporary file for entries. + """ + entries_dir = tmp_path / "entries" + entries_dir.mkdir() + + # Create 'entries.json' file with an empty list + entries_file = entries_dir / "entries.json" + with open(entries_file, 'w') as f: + json.dump([], f) + + print("Temporary entries file created:", entries_file) # Add debug output + return entries_file + + + +def test_add_entry_to_file(temp_entries_file): + """Test add entry to file handler.""" + + entry_data = { + "title": "foo bar", + "content": "Lorem ipsum" + } + + # Add the entry to the temporary entries file + handler.add_entry_to_file(entry_data, entries_file=str(temp_entries_file)) + + # Load the entries from the file + with open(temp_entries_file, 'r') as f: + entries = json.load(f) + + # Check if one entry was added + assert len(entries) == 1 + + # Validate the entry fields + entry = entries[0] + assert "id" in entry + assert "title" in entry + assert "content" in entry + assert "timestamp" in entry + + # Check if the ID is a valid UUID + try: + UUID(entry["id"], version=4) + except ValueError: + pytest.fail("Invalid UUID") + + # Check the values + assert entry["title"] == "foo bar" + assert entry["content"] == "Lorem ipsum" + + # Check if the timestamp is not none + try: + assert entry["timestamp"] is not None + except ValueError: + pytest.fail("Timestamp is empty") \ No newline at end of file diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..8a9ad41 --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,49 @@ +import os +import json +import pytest + +import cli.utils as util + + +@pytest.fixture +def temp_entries_env(tmp_path): + """ + Fixture to create a temporary directory for entries. + """ + original_dir = os.getcwd() + temp_dir = tmp_path / "entries_test" + temp_dir.mkdir(parents=True, exist_ok=True) # Create directory if it doesn't exist + + # Change the current directory to the temp directory + os.chdir(temp_dir) + + # Yield to the test + yield + + # After the test, restore the original working directory + os.chdir(original_dir) + +def test_check_entries_dir(temp_entries_env): + """Test the check_entries_dir function.""" + + entries_dir = './entries' + entries_file = './entries/entries.json' + + # Call the function to check and create the directory and file + result_file = util.check_entries_dir() + + # Verify the directory was created + assert os.path.exists(entries_dir) + assert os.path.isdir(entries_dir) + + # Verify the file was created + assert os.path.exists(entries_file) + assert os.path.isfile(entries_file) + + # Verify the file content is an empty list + with open(entries_file, 'r') as f: + content = json.load(f) + assert content == [] + + # Verify the function returns the correct file path + assert result_file == entries_file