Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/code.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
* [db](#db)
* [DB](#db.DB)
* [\_\_init\_\_](#db.DB.__init__)
* [\_\_del\_\_](#db.DB.__del__)
* [insert\_character](#db.DB.insert_character)
* [insert\_into\_table](#db.DB.insert_into_table)
* [read\_from\_table](#db.DB.read_from_table)
Expand Down Expand Up @@ -325,6 +326,16 @@ def __init__() -> None

Initialize the database connection.

<a id="db.DB.__del__"></a>

#### \_\_del\_\_

```python
def __del__() -> None
```

Close the database connection when the object is destroyed.

<a id="db.DB.insert_character"></a>

#### insert\_character
Expand Down
16 changes: 16 additions & 0 deletions src/character.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,27 @@ def new_character(self, name: str, race: str, dnd_class: str, stats: dict[str, i
self.name = name
self.race = race
self.dnd_class = dnd_class

min_stat = 1
max_stat = 20

if stats is None:
primary_stat = CharacterClass(self.dnd_class).get_primary_stat()
worst_stat = CharacterClass(self.dnd_class).get_worst_stat()
self.roll_stats(primary_stat, worst_stat)
else:
# Validate stats
required_stats = ["Constitution", "Dexterity", "Strength", "Wisdom", "Intelligence", "Charisma"]
for stat in required_stats:
if stat not in stats:
error_message = f"Missing required stat: {stat}"
raise ValueError(error_message)
if not isinstance(stats[stat], int):
error_message = f"Stat value for {stat} must be an integer"
raise TypeError(error_message)
if stats[stat] < min_stat or stats[stat] > max_stat: # D&D stats typically range from 1-20
error_message = f"Stat value for {stat} must be between {min_stat} and {max_stat}"
raise ValueError(error_message)
self.stats = stats
self.update_race_details()
self.update_skills()
Expand Down
29 changes: 21 additions & 8 deletions src/db.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
"""A module for the database connection."""

import logging
import os

import mysql.connector

logging.basicConfig(level=logging.INFO)


class DB:
"""A class to represent a database connection."""

def __init__(self) -> None:
"""Initialize the database connection."""
self.host = "dnd-db"
self.user = os.environ["MYSQL_USER"]
self.password = os.environ["MYSQL_PASSWORD"]
self.db = mysql.connector.connect(
host=self.host,
port=3306,
user=self.user,
password=self.password,
)
try:
self.user = os.environ["MYSQL_USER"]
self.password = os.environ["MYSQL_PASSWORD"]
self.db = mysql.connector.connect(
host=self.host,
port=3306,
user=self.user,
password=self.password,
)
except (KeyError, mysql.connector.Error):
logger = logging.getLogger(__name__)
logger.exception("Database connection error")
self.db = None

def __del__(self) -> None:
"""Close the database connection when the object is destroyed."""
if hasattr(self, "db") and self.db is not None:
self.db.close()

def insert_character(
self,
Expand Down
1 change: 0 additions & 1 deletion src/dice.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ def __init__(self, num_dice: int, num_sides: int, modifier: int) -> None:
self.modifier = modifier
self.rolls = []
self.total = 0
self.rolls = []
self.critical_success = False
self.critical_fail = False

Expand Down
7 changes: 3 additions & 4 deletions src/page_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,9 @@ def left_right_dance(
subtitle: str,
) -> str:
"""Load the left right page."""
try:
if "submit" in submit:
pass
except TypeError:
if submit is not None and "submit" in submit:
pass
else:
right_content = ""
return self.load_left_right_page(left_content, right_content, subtitle)

Expand Down
18 changes: 18 additions & 0 deletions tests/test_character.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ def fixture_mock_dice() -> None:
yield mock_dice_object


def test_character_destruction() -> None:
"""Test that the Character class closes the connection when the object is destroyed."""
character = Character()
del character


@pytest.fixture(name="_mock_race")
def fixture_mock_race() -> None:
"""Mock the race class."""
Expand All @@ -42,6 +48,18 @@ def fixture_mock_character_class() -> None:
yield mock_character_class_object


def test_character__stat_validation() -> None:
"""Test the validation of the Character class."""
char = Character()

with pytest.raises(ValueError, match="Missing required stat: Dexterity"):
char.new_character("Aragorn", "Elf", "Ranger", {"Constitution": 19})
with pytest.raises(TypeError):
char.new_character("Aragorn", "Elf", "Ranger", {"Constitution": "19"})
with pytest.raises(ValueError, match="Constitution must be between 1 and 20"):
char.new_character("Aragorn", "Elf", "Ranger", {"Constitution": 200})


def test_character_initialization() -> None:
"""Test the initialization of the Character class."""
character = Character()
Expand Down
6 changes: 6 additions & 0 deletions tests/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ def test_db_initialization(mock_connect) -> None:
assert db.db is not None


def test_db_destruction() -> None:
"""Test that the DB class closes the connection when the object is destroyed."""
db = DB()
del db


@patch.dict(
os.environ,
{"MYSQL_USER": "user", "MYSQL_PASSWORD": "password"},
Expand Down
4 changes: 2 additions & 2 deletions tests/test_page_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -301,12 +301,12 @@ def test_load_create_character(
@patch("src.page_loader.Character")
def test_load_old_character(mock_character) -> None:
"""Test the load_old_character method."""
test_args = {"char_id": "42"}
char_id = 42
mock_test = Mock()
mock_character.return_value = mock_test
mock_character.load_character_from_db.return_value = None
page_loader = PageLoader()
result = page_loader.load_old_character(test_args)
result = page_loader.load_old_character(char_id)
assert result == mock_test


Expand Down