jerber / MagicDB

MIT License
3 stars 1 forks source link

` validate_py(self)` causes error when a variable is using alias #3

Open wasdee opened 4 years ago

wasdee commented 4 years ago

validate_py(self) causes error when a variable is using alias i.e. scopes: List[str] = Field(alias='scope'). This also causes incompatible to use with fastapi. I personally think that the function validate

    def validate_py(self):
        """Validates but also adds None for the removed fields.
        The first init validates all current info and adds None to fields that were del
        The second init validates all the None fields to make sure they can be None."""
        BaseModel.__init__(self, **self.dict())
        BaseModel.__init__(self, **self.dict())

Could be changed to solve this. For example, we could use orm style creation to avoid the error. I still not fully understand the process of the library. please advice. 😂

Error Log

 ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\uvicorn\protocols\http\h11_impl.py", line 388, in run_asgi
    result = await app(self.scope, self.receive, self.send)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\uvicorn\middleware\proxy_headers.py", line 45, in __call__
    return await self.app(scope, receive, send)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\fastapi\applications.py", line 179, in __call__
    await super().__call__(scope, receive, send)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\starlette\applications.py", line 111, in __call__
    await self.middleware_stack(scope, receive, send)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\starlette\middleware\errors.py", line 181, in __call__
    raise exc from None
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\starlette\middleware\errors.py", line 159, in __call__
    await self.app(scope, receive, _send)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\sentry_sdk\integrations\asgi.py", line 106, in _run_asgi3
    return await self._run_app(scope, lambda: self.app(scope, receive, send))
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\sentry_sdk\integrations\asgi.py", line 143, in _run_app
    raise exc from None
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\sentry_sdk\integrations\asgi.py", line 140, in _run_app
    return await callback()
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\starlette\exceptions.py", line 82, in __call__
    raise exc from None
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\starlette\exceptions.py", line 71, in __call__
    await self.app(scope, receive, sender)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\starlette\routing.py", line 566, in __call__
    await route.handle(scope, receive, send)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\starlette\routing.py", line 227, in handle
    await self.app(scope, receive, send)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\starlette\routing.py", line 41, in app
    response = await func(request)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\fastapi\routing.py", line 182, in app
    raw_response = await run_endpoint_function(
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\fastapi\routing.py", line 135, in run_endpoint_function
    return await run_in_threadpool(dependant.call, **values)
  File "C:\Users\lifep\Devs\gebwai-backend\.venv\lib\site-packages\starlette\concurrency.py", line 34, in run_in_threadpool
    return await loop.run_in_executor(None, func, *args)
  File "C:\Python38\lib\concurrent\futures\thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "C:\Users\lifep\Devs\gebwai-backend\gebwai_backend\endpoint.py", line 151, in set_google_integration
    user.save()
  File "c:\users\lifep\devs\gebwai-backend\.venv\src\magicdb\src\magicdb\Models\MagicModel.py", line 187, in save
    if not ignore_fields: self.validate_py()
  File "c:\users\lifep\devs\gebwai-backend\.venv\src\magicdb\src\magicdb\Models\MagicModel.py", line 71, in validate_py
    BaseModel.__init__(self, **self.dict())
  File "pydantic\main.py", line 346, in pydantic.main.BaseModel.__init__
    raise validation_error
pydantic.error_wrappers.ValidationError: 1 validation error for User
integrations -> google -> scope
  field required (type=value_error.missing)

Class Defination

class GoogleCredential(MagicModel):
    """
    Make for AccessTokenResponse of pub.dartlang.org\oauth2_client-1.4.5\lib\access_token_response.dart
    """
    access_token: str
    refresh_token: str
    scopes: List[str] = Field(alias='scope')
    expiration_date: datetime
    expires_in: int
    token_type: str
    http_status_code: int
    error: Optional[str] = None
    errorDescription: Optional[str] = None
    errorUri: Optional[str] = None
wasdee commented 4 years ago

for the workaround, i creates 2 class and use the orm to convert them.

class GoogleCredential_Fastapi(BaseModel):
    """
    Make for AccessTokenResponse of pub.dartlang.org\oauth2_client-1.4.5\lib\access_token_response.dart
    """
    access_token: str
    refresh_token: str
    scopes: List[str] = Field(alias='scope')
    expiration_date: datetime
    expires_in: int
    token_type: str
    http_status_code: int
    error: Optional[str] = None
    errorDescription: Optional[str] = None
    errorUri: Optional[str] = None

    @validator('expiration_date')
    def convert_to_datetime(cls, value):
        if isinstance(value, int):
            time = arrow.get(value)
            value = time.datetime
        return value

class GoogleCredential(MagicModel):
    """
    Make for AccessTokenResponse of pub.dartlang.org\oauth2_client-1.4.5\lib\access_token_response.dart
    """
    access_token: str
    refresh_token: str
    scopes: List[str]
    expiration_date: datetime
    expires_in: int
    token_type: str
    http_status_code: int
    error: Optional[str] = None
    errorDescription: Optional[str] = None
    errorUri: Optional[str] = None

    class Config:
        orm_mode = True
@app.post("/users/{user_id}/integrations/google_drive")
def set_google_integration(user_id: str, google_cred: GoogleCredential_Fastapi):
    user = User.collection.get(user_id)
    user.integrations.google = GoogleCredential.from_orm(google_cred)
    user.save()