Refactor repositories
This commit is contained in:
parent
73d92645ca
commit
90242d770d
8 changed files with 114 additions and 134 deletions
|
@ -1,85 +0,0 @@
|
||||||
from sqlalchemy import create_engine, insert, select
|
|
||||||
from sqlalchemy.engine.base import Engine
|
|
||||||
from datetime import date
|
|
||||||
from dbapi.tables import training, exercise, approach
|
|
||||||
|
|
||||||
|
|
||||||
class DatabaseInterfasesMixin:
|
|
||||||
"""Mixin for interfaces, that works with database"""
|
|
||||||
|
|
||||||
def __init__(self, engine: Engine) -> None:
|
|
||||||
self.engine: Engine = engine
|
|
||||||
|
|
||||||
|
|
||||||
class TrainingRepository(DatabaseInterfasesMixin):
|
|
||||||
"""Training table repository"""
|
|
||||||
|
|
||||||
def create_training(self, date: date) -> int:
|
|
||||||
"""Method for creating new instance of training
|
|
||||||
Args:
|
|
||||||
date: date of a training
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Primary key of created training entry
|
|
||||||
"""
|
|
||||||
new_instance_statement = insert(training).values(Date=date)
|
|
||||||
with self.engine.connect() as conn:
|
|
||||||
result = conn.execute(new_instance_statement)
|
|
||||||
inerted_entry_pk: int = result.inserted_primary_key[0]
|
|
||||||
conn.commit()
|
|
||||||
return inerted_entry_pk
|
|
||||||
|
|
||||||
|
|
||||||
class ExerciseRepository(DatabaseInterfasesMixin):
|
|
||||||
"""Exercise table repository"""
|
|
||||||
|
|
||||||
def create_exercise(self, training_pk: int, exercise_name: str) -> int:
|
|
||||||
"""Method for creating new instance of exercise table
|
|
||||||
Args:
|
|
||||||
training_pk: Primary key of associated training instance
|
|
||||||
exercise_name: Name of an exercise
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Primary key of created exercise entry
|
|
||||||
"""
|
|
||||||
new_instance_statement = insert(exercise).values(
|
|
||||||
Training=training_pk, Name=exercise_name
|
|
||||||
)
|
|
||||||
with self.engine.connect() as conn:
|
|
||||||
result = conn.execute(new_instance_statement)
|
|
||||||
inserted_entry_pk: int = result.inserted_primary_key[0]
|
|
||||||
conn.commit()
|
|
||||||
return inserted_entry_pk
|
|
||||||
|
|
||||||
def get_exercises_from_training(self, training_pk: int):
|
|
||||||
"""Method for getting rows of exercises, linked to training by its PK
|
|
||||||
|
|
||||||
Args:
|
|
||||||
training_pk: Training table primary key
|
|
||||||
"""
|
|
||||||
statement = select(exercise).where(exercise.c.Training == training_pk)
|
|
||||||
print(f"Exercises SQL statement: {statement}")
|
|
||||||
|
|
||||||
|
|
||||||
class ApproachRepository(DatabaseInterfasesMixin):
|
|
||||||
"""Approach table repository"""
|
|
||||||
|
|
||||||
def create_approach(self, exercise_pk: int, weight: float, reps: int) -> int:
|
|
||||||
"""Method for creating new instance of approach table
|
|
||||||
|
|
||||||
Args:
|
|
||||||
exercise_pk: Primary key of an associated exercise
|
|
||||||
weight: Approach weight
|
|
||||||
reps: Amount of reps in approach
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Primary key of created exercise entry
|
|
||||||
"""
|
|
||||||
new_instance_statement = insert(approach).values(
|
|
||||||
Exercise=exercise_pk, Weight=weight, Reps=reps
|
|
||||||
)
|
|
||||||
with self.engine.connect() as conn:
|
|
||||||
result = conn.execute(new_instance_statement)
|
|
||||||
inserted_entry_pk: int = result.inserted_primary_key[0]
|
|
||||||
conn.commit()
|
|
||||||
return inserted_entry_pk
|
|
0
dbapi/repositories/__init__.py
Normal file
0
dbapi/repositories/__init__.py
Normal file
27
dbapi/repositories/approach_repo.py
Normal file
27
dbapi/repositories/approach_repo.py
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
from dbapi.repositories.utils import DatabaseInterfasesMixin
|
||||||
|
from sqlalchemy import insert
|
||||||
|
from dbapi.tables import approach
|
||||||
|
|
||||||
|
|
||||||
|
class ApproachRepository(DatabaseInterfasesMixin):
|
||||||
|
"""Approach table repository"""
|
||||||
|
|
||||||
|
def create_approach(self, exercise_pk: int, weight: float, reps: int) -> int:
|
||||||
|
"""Method for creating new instance of approach table
|
||||||
|
|
||||||
|
Args:
|
||||||
|
exercise_pk: Primary key of an associated exercise
|
||||||
|
weight: Approach weight
|
||||||
|
reps: Amount of reps in approach
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Primary key of created exercise entry
|
||||||
|
"""
|
||||||
|
new_instance_statement = insert(approach).values(
|
||||||
|
Exercise=exercise_pk, Weight=weight, Reps=reps
|
||||||
|
)
|
||||||
|
with self.engine.connect() as conn:
|
||||||
|
result = conn.execute(new_instance_statement)
|
||||||
|
inserted_entry_pk: int = result.inserted_primary_key[0]
|
||||||
|
conn.commit()
|
||||||
|
return inserted_entry_pk
|
25
dbapi/repositories/exercise_repo.py
Normal file
25
dbapi/repositories/exercise_repo.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
from sqlalchemy import insert
|
||||||
|
from dbapi.repositories.utils import DatabaseInterfasesMixin
|
||||||
|
from dbapi.tables import exercise
|
||||||
|
|
||||||
|
|
||||||
|
class ExerciseRepository(DatabaseInterfasesMixin):
|
||||||
|
"""Exercise table repository"""
|
||||||
|
|
||||||
|
def create_exercise(self, training_pk: int, exercise_name: str) -> int:
|
||||||
|
"""Method for creating new instance of exercise table
|
||||||
|
Args:
|
||||||
|
training_pk: Primary key of associated training instance
|
||||||
|
exercise_name: Name of an exercise
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Primary key of created exercise entry
|
||||||
|
"""
|
||||||
|
new_instance_statement = insert(exercise).values(
|
||||||
|
Training=training_pk, Name=exercise_name
|
||||||
|
)
|
||||||
|
with self.engine.connect() as conn:
|
||||||
|
result = conn.execute(new_instance_statement)
|
||||||
|
inserted_entry_pk: int = result.inserted_primary_key[0]
|
||||||
|
conn.commit()
|
||||||
|
return inserted_entry_pk
|
23
dbapi/repositories/training_repo.py
Normal file
23
dbapi/repositories/training_repo.py
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
from sqlalchemy import insert
|
||||||
|
from datetime import date
|
||||||
|
from dbapi.repositories.utils import DatabaseInterfasesMixin
|
||||||
|
from dbapi.tables import training
|
||||||
|
|
||||||
|
|
||||||
|
class TrainingRepository(DatabaseInterfasesMixin):
|
||||||
|
"""Training table repository"""
|
||||||
|
|
||||||
|
def create_training(self, date: date) -> int:
|
||||||
|
"""Method for creating new instance of training
|
||||||
|
Args:
|
||||||
|
date: date of a training
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Primary key of created training entry
|
||||||
|
"""
|
||||||
|
new_instance_statement = insert(training).values(Date=date)
|
||||||
|
with self.engine.connect() as conn:
|
||||||
|
result = conn.execute(new_instance_statement)
|
||||||
|
inerted_entry_pk: int = result.inserted_primary_key[0]
|
||||||
|
conn.commit()
|
||||||
|
return inerted_entry_pk
|
8
dbapi/repositories/utils.py
Normal file
8
dbapi/repositories/utils.py
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
from sqlalchemy import Engine
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseInterfasesMixin:
|
||||||
|
"""Mixin for interfaces, that works with database"""
|
||||||
|
|
||||||
|
def __init__(self, engine: Engine) -> None:
|
||||||
|
self.engine: Engine = engine
|
59
main.py
59
main.py
|
@ -7,11 +7,9 @@ from sqlalchemy import Table, create_engine, text, insert
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
from sqlalchemy.ext.asyncio import create_async_engine
|
from sqlalchemy.ext.asyncio import create_async_engine
|
||||||
from dbapi.migrator import FitnessDatabseMigrator
|
from dbapi.migrator import FitnessDatabseMigrator
|
||||||
from dbapi.repositories import (
|
from dbapi.repositories.approach_repo import ApproachRepository
|
||||||
ApproachRepository,
|
from dbapi.repositories.exercise_repo import ExerciseRepository
|
||||||
ExerciseRepository,
|
from dbapi.repositories.training_repo import TrainingRepository
|
||||||
TrainingRepository,
|
|
||||||
)
|
|
||||||
from dbapi.tables import metadata_obj, training, exercise, approach
|
from dbapi.tables import metadata_obj, training, exercise, approach
|
||||||
from obsidian.notes_parser import parse_training_data, remap_unique_exercises
|
from obsidian.notes_parser import parse_training_data, remap_unique_exercises
|
||||||
from apple.notes_parser import parse_training_data as apple_parse_training_data
|
from apple.notes_parser import parse_training_data as apple_parse_training_data
|
||||||
|
@ -58,8 +56,8 @@ async_engine = create_async_engine(
|
||||||
# TODO: Check how migrations are done
|
# TODO: Check how migrations are done
|
||||||
|
|
||||||
# NOTE: Drop all Tables from database
|
# NOTE: Drop all Tables from database
|
||||||
# metadata_obj.drop_all(engine)
|
metadata_obj.drop_all(engine)
|
||||||
# metadata_obj.create_all(engine)
|
metadata_obj.create_all(engine)
|
||||||
|
|
||||||
# NOTE: Table reflection - generating table object from existing tables (only tables, that are stored in metadata)
|
# NOTE: Table reflection - generating table object from existing tables (only tables, that are stored in metadata)
|
||||||
# some_table = Table("some_table", metadata_obj, autoload_with=engine)
|
# some_table = Table("some_table", metadata_obj, autoload_with=engine)
|
||||||
|
@ -69,27 +67,26 @@ async_engine = create_async_engine(
|
||||||
|
|
||||||
# Inserting training values into database
|
# Inserting training values into database
|
||||||
|
|
||||||
# trainings: List[Training] = parse_training_data()
|
trainings: List[Training] = parse_training_data()
|
||||||
# for train in trainings:
|
for train in trainings:
|
||||||
# if not train:
|
if not train:
|
||||||
# continue
|
continue
|
||||||
# else:
|
else:
|
||||||
# print(train)
|
print(train)
|
||||||
# new_training_pk: int = TrainingRepository(engine).create_training(train.date)
|
new_training_pk: int = TrainingRepository(engine).create_training(train.date)
|
||||||
# for exr in train.exercises:
|
for exr in train.exercises:
|
||||||
# approach_statements = []
|
approach_statements = []
|
||||||
# new_exercise_pk: int = ExerciseRepository(engine).create_exercise(
|
new_exercise_pk: int = ExerciseRepository(engine).create_exercise(
|
||||||
# training_pk=new_training_pk, exercise_name=exr.name
|
training_pk=new_training_pk, exercise_name=exr.name
|
||||||
# )
|
)
|
||||||
# for appr in exr.approaches:
|
for appr in exr.approaches:
|
||||||
# new_approach_pk: int = ApproachRepository(engine).create_approach(
|
new_approach_pk: int = ApproachRepository(engine).create_approach(
|
||||||
# exercise_pk=new_exercise_pk, weight=appr.weight, reps=appr.reps
|
exercise_pk=new_exercise_pk, weight=appr.weight, reps=appr.reps
|
||||||
# )
|
)
|
||||||
#
|
|
||||||
#
|
|
||||||
# print("-------------------------\n" * 2)
|
print("-------------------------\n" * 2)
|
||||||
# print("-------------------------\n" * 2)
|
print("-------------------------\n" * 2)
|
||||||
# ExerciseRepository(engine=engine).get_exercises_from_training(1)
|
|
||||||
# -----
|
# -----
|
||||||
|
|
||||||
# Calculating unique exercises for obsidian
|
# Calculating unique exercises for obsidian
|
||||||
|
@ -185,6 +182,8 @@ async_engine = create_async_engine(
|
||||||
# pprint(unique_exercise_parsed_names)
|
# pprint(unique_exercise_parsed_names)
|
||||||
# print(len(combined_trainings))
|
# print(len(combined_trainings))
|
||||||
|
|
||||||
fbm = FitnessDatabseMigrator(async_engine=async_engine)
|
# Async engine playground
|
||||||
|
|
||||||
asyncio.run(fbm.reset_database())
|
# fbm = FitnessDatabseMigrator(async_engine=async_engine)
|
||||||
|
#
|
||||||
|
# asyncio.run(fbm.reset_database())
|
||||||
|
|
21
poetry.lock
generated
21
poetry.lock
generated
|
@ -1,10 +1,9 @@
|
||||||
# This file is automatically @generated by Poetry 1.4.2 and should not be changed by hand.
|
# This file is automatically @generated by Poetry 1.8.4 and should not be changed by hand.
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "annotated-types"
|
name = "annotated-types"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
description = "Reusable constraint types to use with typing.Annotated"
|
description = "Reusable constraint types to use with typing.Annotated"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -16,7 +15,6 @@ files = [
|
||||||
name = "async-timeout"
|
name = "async-timeout"
|
||||||
version = "5.0.1"
|
version = "5.0.1"
|
||||||
description = "Timeout context manager for asyncio programs"
|
description = "Timeout context manager for asyncio programs"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -28,7 +26,6 @@ files = [
|
||||||
name = "asyncpg"
|
name = "asyncpg"
|
||||||
version = "0.30.0"
|
version = "0.30.0"
|
||||||
description = "An asyncio PostgreSQL driver"
|
description = "An asyncio PostgreSQL driver"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8.0"
|
python-versions = ">=3.8.0"
|
||||||
files = [
|
files = [
|
||||||
|
@ -95,7 +92,6 @@ test = ["distro (>=1.9.0,<1.10.0)", "flake8 (>=6.1,<7.0)", "flake8-pyi (>=24.1.0
|
||||||
name = "colorama"
|
name = "colorama"
|
||||||
version = "0.4.6"
|
version = "0.4.6"
|
||||||
description = "Cross-platform colored terminal text."
|
description = "Cross-platform colored terminal text."
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
files = [
|
files = [
|
||||||
|
@ -107,7 +103,6 @@ files = [
|
||||||
name = "exceptiongroup"
|
name = "exceptiongroup"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
description = "Backport of PEP 654 (exception groups)"
|
description = "Backport of PEP 654 (exception groups)"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
|
@ -122,7 +117,6 @@ test = ["pytest (>=6)"]
|
||||||
name = "greenlet"
|
name = "greenlet"
|
||||||
version = "3.1.1"
|
version = "3.1.1"
|
||||||
description = "Lightweight in-process concurrent programming"
|
description = "Lightweight in-process concurrent programming"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
|
@ -209,7 +203,6 @@ test = ["objgraph", "psutil"]
|
||||||
name = "iniconfig"
|
name = "iniconfig"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
description = "brain-dead simple config-ini parsing"
|
description = "brain-dead simple config-ini parsing"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
|
@ -221,7 +214,6 @@ files = [
|
||||||
name = "packaging"
|
name = "packaging"
|
||||||
version = "24.2"
|
version = "24.2"
|
||||||
description = "Core utilities for Python packages"
|
description = "Core utilities for Python packages"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -233,7 +225,6 @@ files = [
|
||||||
name = "pluggy"
|
name = "pluggy"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
description = "plugin and hook calling mechanisms for python"
|
description = "plugin and hook calling mechanisms for python"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -249,7 +240,6 @@ testing = ["pytest", "pytest-benchmark"]
|
||||||
name = "psycopg2"
|
name = "psycopg2"
|
||||||
version = "2.9.10"
|
version = "2.9.10"
|
||||||
description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
description = "psycopg2 - Python-PostgreSQL Database Adapter"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -269,7 +259,6 @@ files = [
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "2.10.5"
|
version = "2.10.5"
|
||||||
description = "Data validation using Python type hints"
|
description = "Data validation using Python type hints"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -290,7 +279,6 @@ timezone = ["tzdata"]
|
||||||
name = "pydantic-core"
|
name = "pydantic-core"
|
||||||
version = "2.27.2"
|
version = "2.27.2"
|
||||||
description = "Core functionality for Pydantic validation and serialization"
|
description = "Core functionality for Pydantic validation and serialization"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -403,7 +391,6 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "8.3.4"
|
version = "8.3.4"
|
||||||
description = "pytest: simple powerful testing with Python"
|
description = "pytest: simple powerful testing with Python"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -426,7 +413,6 @@ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments
|
||||||
name = "python-dotenv"
|
name = "python-dotenv"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
description = "Read key-value pairs from a .env file and set them as environment variables"
|
description = "Read key-value pairs from a .env file and set them as environment variables"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -441,7 +427,6 @@ cli = ["click (>=5.0)"]
|
||||||
name = "sqlalchemy"
|
name = "sqlalchemy"
|
||||||
version = "2.0.37"
|
version = "2.0.37"
|
||||||
description = "Database Abstraction Library"
|
description = "Database Abstraction Library"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
|
@ -505,7 +490,7 @@ files = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
greenlet = {version = "!=0.4.17", markers = "python_version < \"3.14\" and platform_machine == \"aarch64\" or python_version < \"3.14\" and platform_machine == \"ppc64le\" or python_version < \"3.14\" and platform_machine == \"x86_64\" or python_version < \"3.14\" and platform_machine == \"amd64\" or python_version < \"3.14\" and platform_machine == \"AMD64\" or python_version < \"3.14\" and platform_machine == \"win32\" or python_version < \"3.14\" and platform_machine == \"WIN32\""}
|
greenlet = {version = "!=0.4.17", markers = "python_version < \"3.14\" and (platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\")"}
|
||||||
typing-extensions = ">=4.6.0"
|
typing-extensions = ">=4.6.0"
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
|
@ -537,7 +522,6 @@ sqlcipher = ["sqlcipher3_binary"]
|
||||||
name = "tomli"
|
name = "tomli"
|
||||||
version = "2.2.1"
|
version = "2.2.1"
|
||||||
description = "A lil' TOML parser"
|
description = "A lil' TOML parser"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
@ -579,7 +563,6 @@ files = [
|
||||||
name = "typing-extensions"
|
name = "typing-extensions"
|
||||||
version = "4.12.2"
|
version = "4.12.2"
|
||||||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||||
category = "main"
|
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
files = [
|
files = [
|
||||||
|
|
Loading…
Reference in a new issue