Skip to content

Commit

Permalink
Merge pull request #52 from grillazz/46-switch-to-python-311
Browse files Browse the repository at this point in the history
46 switch to python 311
  • Loading branch information
grillazz authored Nov 19, 2023
2 parents 8c222ed + ec1680c commit 2a73887
Show file tree
Hide file tree
Showing 13 changed files with 673 additions and 554 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.10"]
python-version: ["3.11"]
fail-fast: false

services:
mongodb:
image: mongo:6.0.4
image: mongo:7.0.3
env:
MONGO_INITDB_DATABASE: greenhouse
MONGO_INITDB_ROOT_USERNAME: farmer
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.10-slim AS base
FROM python:3.11-slim AS base
RUN apt-get update \
&& apt-get upgrade -y \
&& apt-get install -y --no-install-recommends curl git build-essential \
Expand Down
3 changes: 1 addition & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@ services:
uvicorn greens.main:app
--host 0.0.0.0 --port 8989
--lifespan=on --use-colors --loop uvloop --http httptools
--log-config=log-conf.yaml
--reload
"
volumes:
- .:/app
- .:/home/code
ports:
- "8989:8989"
depends_on:
Expand Down
34 changes: 14 additions & 20 deletions greens/config.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
import os
from functools import lru_cache

from pydantic import BaseSettings

from greens.utils import get_logger

logger = get_logger(__name__)
from pydantic_settings import BaseSettings


class Settings(BaseSettings):
"""
BaseSettings, from Pydantic, validates the data so that when we create an instance of Settings,
environment and testing will have types of str and bool, respectively.
Parameters:
Returns:
instance of Settings
Represents the configuration settings for the application.
Args:
environment (str): The environment in which the application is running. Defaults to "local".
testing (str): The testing mode of the application. Defaults to "0".
up (str): The up status of the application. Defaults to "up".
down (str): The down status of the application. Defaults to "down".
web_server (str): The web server used by the application. Defaults to "web_server".
db_url (str): The URL of the MongoDB database.
db_name (str): The name of the MongoDB database.
collection (str): The name of the MongoDB collection.
test_db_name (str): The name of the MongoDB test database.
"""

environment: str = os.getenv("ENVIRONMENT", "local")
testing: str = os.getenv("TESTING", "0")
up: str = os.getenv("UP", "up")
Expand All @@ -34,7 +31,4 @@ class Settings(BaseSettings):
test_db_name: str = os.getenv("MONGO_TEST_DB", "")


@lru_cache
def get_settings():
logger.info("Loading config settings from the environment...")
return Settings()
settings = Settings()
3 changes: 1 addition & 2 deletions greens/main.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from fastapi import FastAPI

from greens import config
from greens.config import settings as global_settings
from greens.routers import router as v1
from greens.services.repository import get_mongo_meta
from greens.utils import get_logger, init_mongo

global_settings = config.get_settings()

if global_settings.environment == "local":
get_logger("uvicorn")
Expand Down
9 changes: 4 additions & 5 deletions greens/routers/v1/vegs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,11 @@
from fastapi.encoders import jsonable_encoder
from starlette.status import HTTP_201_CREATED

from greens import config
from greens.config import settings as global_settings
from greens.routers.exceptions import NotFoundHTTPException
from greens.schemas.vegs import Document, DocumentResponse, ObjectIdField
from greens.services.repository import create_document, retrieve_document

global_settings = config.get_settings()
collection = global_settings.collection

router = APIRouter()
Expand All @@ -17,7 +16,7 @@
"",
status_code=HTTP_201_CREATED,
response_description="Document created",
response_model=DocumentResponse,
# response_model=DocumentResponse,
)
async def add_document(payload: Document):
"""
Expand All @@ -26,7 +25,7 @@ async def add_document(payload: Document):
:return:
"""
try:
payload = jsonable_encoder(payload)
# payload = jsonable_encoder(payload)
return await create_document(payload, collection)
except ValueError as exception:
raise NotFoundHTTPException(msg=str(exception))
Expand All @@ -35,7 +34,7 @@ async def add_document(payload: Document):
@router.get(
"/{object_id}",
response_description="Document retrieved",
response_model=DocumentResponse,
# response_model=DocumentResponse,
)
async def get_document(object_id: ObjectIdField):
"""
Expand Down
46 changes: 28 additions & 18 deletions greens/schemas/vegs.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,40 @@
from bson import ObjectId
from bson import ObjectId as _ObjectId
from bson.errors import InvalidId
from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, ConfigDict, AfterValidator
from typing_extensions import Annotated


class ObjectIdField(str):
@classmethod
def __get_validators__(cls):
yield cls.validate
# class ObjectIdField(str):
# @classmethod
# def __get_validators__(cls):
# yield cls.validate
#
# @classmethod
# def validate(cls, value):
# try:
# return ObjectId(str(value))
# except InvalidId as e:
# raise ValueError("Not a valid ObjectId") from e

@classmethod
def validate(cls, value):
try:
return ObjectId(str(value))
except InvalidId:
raise ValueError("Not a valid ObjectId")

def check_object_id(value: str) -> str:
if not _ObjectId.is_valid(value):
raise ValueError('Invalid ObjectId')
return value


ObjectIdField = Annotated[str, AfterValidator(check_object_id)]


config = ConfigDict(arbitrary_types_allowed=True, populate_by_name=True)


class Document(BaseModel):
# model_config = config

name: str = Field(...)
desc: str = Field(...)

class Config:
allow_population_by_field_name = True
arbitrary_types_allowed = True
json_encoders = {ObjectId: str}


class DocumentResponse(Document):
id: ObjectIdField = Field(...)
id: ObjectIdField
7 changes: 4 additions & 3 deletions greens/services/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,17 @@ async def retrieve_document(document_id: str, collection: str) -> dict:
raise ValueError(f"No document found for {document_id=} in {collection=}")


async def create_document(document: dict, collection: str) -> dict:
async def create_document(document, collection: str) -> dict:
"""
:param document:
:param collection:
:return:
"""
try:
document = await greens.app.state.mongo_collection[collection].insert_one(document)
return await retrieve_document(document.inserted_id, collection)
document = await greens.app.state.mongo_collection[collection].insert_one(document.model_dump())
# TODO: return await retrieve_document(document.inserted_id, collection)
return True
except WriteError:
raise AlreadyExistsHTTPException(f"Document with {document.inserted_id=} already exists")

Expand Down
Loading

0 comments on commit 2a73887

Please sign in to comment.