From fbc6e76845dd71c386f123298f676ba3844be534 Mon Sep 17 00:00:00 2001 From: Jun-te Kim Date: Wed, 26 Mar 2025 16:49:14 +0000 Subject: [PATCH] proof of concept works --- .db-env | 3 ++- .devcontainer/devcontainer.json | 3 ++- .devcontainer/docker-compose.yml | 2 ++ etl/load.py | 35 ++++++++++++++++++++++++++++ etl/transform/types.py | 34 +++++++++++++++++++++++---- example_data/pre_site_note.pdf | Bin 0 -> 13472 bytes poetry.lock | 38 ++++++++++++++++++++++++++++++- pyproject.toml | 1 + 8 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 example_data/pre_site_note.pdf diff --git a/.db-env b/.db-env index 2874869..d5a81db 100644 --- a/.db-env +++ b/.db-env @@ -3,4 +3,5 @@ POSTGRES_PASSWORD=makingwarmhomes POSTGRES_HOST=localhost POSTGRES_PORT=5432 PGADMIN_DEFAULT_EMAIL=junte@domna.homes -PGADMIN_DEFAULT_PASSWORD=makingwarmhomes \ No newline at end of file +PGADMIN_DEFAULT_PASSWORD=makingwarmhomes +DATABASE_URL=postgresql://postgres:makingwarmhomes@db:5432/postgres \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 50bff3f..880cfb3 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -17,7 +17,8 @@ "ms-python.python", "ms-toolsai.jupyter", "mechatroner.rainbow-csv", - "ms-toolsai.datawrangler" + "ms-toolsai.datawrangler", + "lindacong.vscode-book-reader" ] } } diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 3213e61..ec14ffc 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -7,6 +7,8 @@ services: context: .. dockerfile: .devcontainer/Dockerfile command: sleep infinity + env_file: + - ../.db-env volumes: - ..:/workspaces/survey-extractor:cached diff --git a/etl/load.py b/etl/load.py index 16bce71..d4b456a 100644 --- a/etl/load.py +++ b/etl/load.py @@ -1,3 +1,38 @@ # A very simple script to read a presite note and load to a postgres database +import os +from etl.surveyedData.surveryedData import surveyedDataProcessor +from etl.transform.types import get_db_session, init_db, AssessorInfo + +pre_site_note_path = os.path.join(os.getcwd(), "..", "example_data", "pre_site_note.pdf") + +survey_one = surveyedDataProcessor("123 Fake Street", [pre_site_note_path]) + +assert survey_one.pre_site_note.assessor_information.accreditation_number == "QUID211435" + +init_db() + +assessor1 = AssessorInfo( + accreditation_number=survey_one.pre_site_note.assessor_information.accreditation_number, + name=survey_one.pre_site_note.assessor_information.name, + phone_number=survey_one.pre_site_note.assessor_information.phone_number, + email_address=survey_one.pre_site_note.assessor_information.email_address, +) + +with get_db_session() as session: + session.add(assessor1) + session.commit() + + + + + + + + + +# Download a pdf file and save it in git for easier processes and tests +# scrape the correct data +# Pydantic structure +# Load to database successfully locally \ No newline at end of file diff --git a/etl/transform/types.py b/etl/transform/types.py index 9ab8463..dada10e 100644 --- a/etl/transform/types.py +++ b/etl/transform/types.py @@ -1,12 +1,36 @@ -from sqlmodel import Field, SQLModel, create_engine, Relationship -from uuid import uuid4 +from sqlmodel import Field, SQLModel, create_engine, Relationship, Session +import uuid from datetime import datetime from pydantic import field_validator, EmailStr +from pydantic_settings import BaseSettings from typing import Optional, List +from sqlalchemy import Column +from sqlalchemy.dialects.postgresql import UUID + +class Settings(BaseSettings): + DATABASE_URL: Optional[str] = None # Default to None if not set + + class Config: + env_file = ".env" # Load from an optional .env file + +settings = Settings() +engine = create_engine(settings.DATABASE_URL) if settings.DATABASE_URL else None + + +def get_db_session(): + if engine is None: + raise RuntimeError("Database is not configured. Set DATABASE_URL in environment variables.") + return Session(engine) + +def init_db(): + if engine: + SQLModel.metadata.create_all(engine) class BaseModel(SQLModel): - id: str = Field(default_factory=uuid4, primary_key=True, index=True, sa_column_kwargs={'type_': 'UUID'}) - + id: uuid.UUID = Field( + default_factory=uuid.uuid4, + sa_column=Column(UUID(as_uuid=True), primary_key=True) + ) class Dimension(BaseModel): floor_area_m2: float @@ -75,7 +99,7 @@ class Door(BaseModel): no_of_insulated_doors: int u_value_w_m2_k: Optional[str] -class AssessorInfo(BaseModel): +class AssessorInfo(BaseModel, table=True): accreditation_number: str name: str phone_number: Optional[str] = None diff --git a/example_data/pre_site_note.pdf b/example_data/pre_site_note.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8339e03153ce2321372b8b4913a1489a46b92f99 GIT binary patch literal 13472 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.16.0)", "azure-keyvault-secrets (>=4.8.0)"] +toml = ["tomli (>=2.0.1)"] +yaml = ["pyyaml (>=6.0.1)"] + [[package]] name = "pygments" version = "2.19.1" @@ -1275,6 +1296,21 @@ files = [ [package.dependencies] six = ">=1.5" +[[package]] +name = "python-dotenv" +version = "1.1.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d"}, + {file = "python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + [[package]] name = "pytz" version = "2025.1" @@ -1698,4 +1734,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = ">=3.12" -content-hash = "8d7db7d1395e8a16703b9b23de79f9d0e53307dea379e229a26081bc301aaf93" +content-hash = "f49b1428e8390de0d5989fcd7319d0f1e54d29127e967a3a7d9c07acd74e6d39" diff --git a/pyproject.toml b/pyproject.toml index 0ec3f55..b80566d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,6 +16,7 @@ dependencies = [ "fuzzywuzzy (>=0.18.0,<0.19.0)", "sqlmodel (>=0.0.24,<0.0.25)", "psycopg2 (>=2.9.10,<3.0.0)", + "pydantic-settings (>=2.8.1,<3.0.0)", ] [tool.poetry]