Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

46 switch to python 311 #52

Merged
merged 6 commits into from
Nov 19, 2023
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
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