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

Use pydantic > 1 #192

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion .github/workflows/ci-integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ jobs:
steps:
- uses: actions/checkout@v2

- uses: mamba-org/setup-micromamba@v1
- name: Install environment
uses: mamba-org/setup-micromamba@v1
with:
environment-file: devtools/conda-envs/test.yml
create-args: >-
Expand Down
2 changes: 1 addition & 1 deletion alchemiscale/compute/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def register_computeservice(
):
now = datetime.utcnow()
csreg = ComputeServiceRegistration(
identifier=compute_service_id, registered=now, heartbeat=now
identifier=ComputeServiceID(compute_service_id), registered=now, heartbeat=now
)

compute_service_id_ = n4js.register_computeservice(csreg)
Expand Down
22 changes: 11 additions & 11 deletions alchemiscale/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"""

from typing import Optional, Union
from pydantic import BaseModel, Field, validator, root_validator
from pydantic import BaseModel, Field, field_validator, model_validator, ConfigDict
from gufe.tokenization import GufeKey
from re import fullmatch

Expand Down Expand Up @@ -34,8 +34,9 @@ def __eq__(self, other):

return str(self) == str(other)

class Config:
frozen = True
model_config = ConfigDict(
frozen=True,
)

@staticmethod
def _validate_component(v, component):
Expand All @@ -61,19 +62,19 @@ def _validate_component(v, component):

return v

@validator("org")
@field_validator("org")
def valid_org(cls, v):
return cls._validate_component(v, "org")

@validator("campaign")
@field_validator("campaign")
def valid_campaign(cls, v):
return cls._validate_component(v, "campaign")

@validator("project")
@field_validator("project")
def valid_project(cls, v):
return cls._validate_component(v, "project")

@root_validator
@model_validator(mode="before")
def check_scope_hierarchy(cls, values):
if not _hierarchy_valid(values):
raise InvalidScopeError(
Expand Down Expand Up @@ -122,15 +123,14 @@ class ScopedKey(BaseModel):

"""

gufe_key: GufeKey
gufe_key: Union[GufeKey, str]
org: str
campaign: str
project: str

class Config:
frozen = True
model_config = ConfigDict(frozen=True, arbitrary_types_allowed=True)

@validator("gufe_key")
@field_validator("gufe_key")
def cast_gufe_key(cls, v):
return GufeKey(v)

Expand Down
25 changes: 22 additions & 3 deletions alchemiscale/security/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,31 @@ def generate_secret_key():
return secrets.token_hex(32)


def authenticate(db, cls, identifier: str, key: str) -> CredentialedEntity:
def authenticate(db, cls, identifier: str, key: str) -> Optional[CredentialedEntity]:
"""Authenticate the given identity+key against the db instance.

Parameters
----------
db
State store instance featuring a `get_credentialed_entity` method.
cls
The `CredentialedEntity` subclass the identity corresponds to.
identity
String identifier for the the identity.
key
Secret key string for the identity.

Returns
-------
If successfully authenticated, returns the `CredentialedEntity` subclass instance.
If not, returns `None`.

"""
entity: CredentialedEntity = db.get_credentialed_entity(identifier, cls)
if entity is None:
return False
return None
if not pwd_context.verify(key, entity.hashed_key):
return False
return None
return entity


Expand Down
28 changes: 15 additions & 13 deletions alchemiscale/security/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from datetime import datetime, timedelta
from typing import List, Union, Optional

from pydantic import BaseModel, validator
from pydantic import BaseModel, field_validator

from ..models import Scope

Expand All @@ -30,22 +30,24 @@ class CredentialedEntity(BaseModel):
class ScopedIdentity(BaseModel):
identifier: str
disabled: bool = False
scopes: List[str] = []
scopes: List[Union[Scope, str]] = []

@validator("scopes", pre=True, each_item=True)
def cast_scopes_to_str(cls, scope):
@field_validator("scopes")
def cast_scopes_to_str(cls, scopes):
"""Ensure that each scope object is correctly cast to its str representation"""
if isinstance(scope, Scope):
scope = str(scope)
elif isinstance(scope, str):
try:
Scope.from_str(scope)
except:
scopes_ = []
for scope in scopes:
if isinstance(scope, Scope):
scopes_.append(str(scope))
elif isinstance(scope, str):
try:
scopes_.append(str(Scope.from_str(scope)))
except:
raise ValueError(f"Invalid scope `{scope}` set for `{cls}`")
else:
raise ValueError(f"Invalid scope `{scope}` set for `{cls}`")
else:
raise ValueError(f"Invalid scope `{scope}` set for `{cls}`")

return scope
return scopes_


class UserIdentity(ScopedIdentity):
Expand Down
7 changes: 4 additions & 3 deletions alchemiscale/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@
from functools import lru_cache
from typing import Optional

from pydantic import BaseSettings
from pydantic_settings import BaseSettings, SettingsConfigDict


class FrozenSettings(BaseSettings):
class Config:
frozen = True
model_config = SettingsConfigDict(
frozen=True,
)


class Neo4jStoreSettings(FrozenSettings):
Expand Down
6 changes: 5 additions & 1 deletion alchemiscale/storage/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import hashlib


from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, ConfigDict
from gufe.tokenization import GufeTokenizable, GufeKey

from ..models import ScopedKey, Scope
Expand All @@ -29,6 +29,8 @@ class ComputeServiceRegistration(BaseModel):
registered: datetime
heartbeat: datetime

model_config = ConfigDict(arbitrary_types_allowed=True)

def __repr__(self): # pragma: no cover
return f"<ComputeServiceRegistration('{str(self)}')>"

Expand Down Expand Up @@ -59,6 +61,8 @@ class TaskProvenance(BaseModel):
datetime_start: datetime
datetime_end: datetime

model_config = ConfigDict(arbitrary_types_allowed=True)

# this should include versions of various libraries


Expand Down
3 changes: 2 additions & 1 deletion devtools/conda-envs/alchemiscale-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ dependencies:
- requests
- click
- httpx
- pydantic<2.0
- pydantic >1
- pydantic-settings

## user client printing
- rich
Expand Down
3 changes: 2 additions & 1 deletion devtools/conda-envs/alchemiscale-compute.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ dependencies:
- requests
- click
- httpx
- pydantic<2.0
- pydantic >1
- pydantic-settings

# perses dependencies
- openeye-toolkits
Expand Down
3 changes: 2 additions & 1 deletion devtools/conda-envs/alchemiscale-server.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ dependencies:
- openmmforcefields>=0.12.0
- requests
- click
- pydantic<2.0
- pydantic >1
- pydantic-settings

## state store
- neo4j-python-driver
Expand Down
3 changes: 2 additions & 1 deletion devtools/conda-envs/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ dependencies:
- gufe>=1.0.0
- openfe>=1.0.1
- openmmforcefields>=0.12.0
- pydantic<2.0
- pydantic >1
- pydantic-settings

## state store
- neo4j-python-driver
Expand Down
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"passlib",
"py2neo",
"pydantic",
"pydantic_settings",
"starlette",
"yaml",
]
Expand Down
Loading