Skip to content
This repository was archived by the owner on May 7, 2026. It is now read-only.

Commit c771ee5

Browse files
authored
Mongo persistence (#7)
* removed errorDefinitions file, and placed into errors folder instead. Added class variable in stores/protocol to allow specifying error responses related directly to loading/unloading the Hkl object store * changed all file, variable and class names. Updated dev packages to include pep8-naming * added typed-ast package to setup.cfg to pass lint check * relocked pipfile and fixed issues to make lint pass * made constants all caps (including enum members), more explicit return types from services * added mongodb store, changed how objects are persisted so they can fall under a collection, eg several samples may relate to one beamline for example * modified files to pass pre-commit checks and tests * using motor to make store calls non blocking * abstracted the get_store functionality, took out side effects from store creation. Seperate PR to follow to take all side effects out * updated pipfile lock to include motor
1 parent 9f96b38 commit c771ee5

23 files changed

Lines changed: 693 additions & 325 deletions

Pipfile.lock

Lines changed: 266 additions & 121 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

setup.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ install_requires =
2727
diffcalc-core
2828
fastapi
2929
uvicorn
30+
pymongo
31+
motor
3032

3133
[options.extras_require]
3234
# For development tests/docs

src/diffcalc_API/__init__.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
1-
from . import config, server
1+
from . import config, database, server
22
from ._version_git import __version__
33

44
# __all__ defines the public API for the package.
55
# Each module also defines its own __all__.
6-
__all__ = [
7-
"__version__",
8-
"server",
9-
"config",
10-
]
6+
7+
__all__ = ["__version__", "server", "config", "database"]

src/diffcalc_API/config.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
# this file is for defining constants
2-
3-
SAVE_PICKLES_FOLDER = "/dls/tmp/ton99817/diffcalc_pickles"
1+
SAVE_PICKLES_FOLDER = "/"
42
VECTOR_PROPERTIES = ["n_hkl", "n_phi", "surf_nhkl", "surf_nphi"]
53
CONSTRAINTS_WITH_NO_VALUE = {"a_eq_b", "bin_eq_bout", "mu_is_gam", "bisect"}
64

5+
76
ALL_CONSTRAINTS = {
87
"delta",
98
"gam" "qaz",

src/diffcalc_API/database.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import motor.motor_asyncio
2+
from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
3+
4+
client: AsyncIOMotorClient = motor.motor_asyncio.AsyncIOMotorClient()
5+
database: AsyncIOMotorDatabase = client.test_db

src/diffcalc_API/errors/constraints.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class Codes(ErrorCodes):
1212
CHECK_CONSTRAINT_EXISTS = 400
1313

1414

15-
responses = {code: ALL_RESPONSES[code] for code in np.unique(Codes().all_codes())}
15+
responses = {code: ALL_RESPONSES[code] for code in np.unique(Codes.all_codes())}
1616

1717

1818
def check_constraint_exists(constraint: str) -> None:

src/diffcalc_API/errors/definitions.py

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from typing import Any, Dict, Union
1+
from enum import IntEnum
2+
from typing import Any, Dict, List, Union
23

34
from diffcalc.util import DiffcalcException
45
from pydantic import BaseModel
@@ -25,14 +26,10 @@ class DiffcalcExceptionModel(BaseModel):
2526
detail: str
2627

2728

28-
class ErrorCodes:
29-
def all_codes(self):
30-
attributes = [
31-
attr
32-
for attr in dir(self)
33-
if (not attr.startswith("__")) and (not attr == "all_codes")
34-
]
35-
return [getattr(self, attr) for attr in attributes]
29+
class ErrorCodes(IntEnum):
30+
@classmethod
31+
def all_codes(cls) -> List[int]:
32+
return [val.value for val in cls]
3633

3734

3835
#######################################################################################

src/diffcalc_API/errors/hkl.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class Codes(ErrorCodes):
1616
CALCULATE_UB_MATRIX = 400
1717

1818

19-
responses = {code: ALL_RESPONSES[code] for code in np.unique(Codes().all_codes())}
19+
responses = {code: ALL_RESPONSES[code] for code in np.unique(Codes.all_codes())}
2020

2121

2222
def check_valid_miller_indices(miller_indices: Tuple[float, float, float]) -> None:

src/diffcalc_API/errors/ub.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class Codes(ErrorCodes):
2020
CHECK_PROPERTY_IS_VALID = 400
2121

2222

23-
responses = {code: ALL_RESPONSES[code] for code in np.unique(Codes().all_codes())}
23+
responses = {code: ALL_RESPONSES[code] for code in np.unique(Codes.all_codes())}
2424

2525

2626
def check_params_not_empty(params: SetLatticeParams) -> None:
Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,72 @@
1-
from typing import Dict, Union
1+
from typing import Dict, Optional, Union
22

3-
from fastapi import APIRouter, Body, Depends, Response
3+
from fastapi import APIRouter, Body, Depends, Query, Response
44

55
from diffcalc_API.services import constraints as service
6-
from diffcalc_API.stores.pickling import get_store
7-
from diffcalc_API.stores.protocol import HklCalcStore
6+
from diffcalc_API.stores.protocol import HklCalcStore, get_store
87

98
router = APIRouter(prefix="/constraints", tags=["constraints"])
109

1110

1211
@router.get("/{name}")
13-
async def get_constraints(name: str, store: HklCalcStore = Depends(get_store)):
14-
content = await service.get_constraints(name, store)
15-
12+
async def get_constraints(
13+
name: str,
14+
store: HklCalcStore = Depends(get_store),
15+
collection: Optional[str] = Query(default=None, example="B07"),
16+
):
17+
content = await service.get_constraints(name, store, collection)
1618
return Response(content=content, media_type="application/text")
1719

1820

19-
@router.put("/{name}/set")
21+
@router.post("/{name}")
2022
async def set_constraints(
2123
name: str,
2224
constraints: Dict[str, Union[float, bool]] = Body(
2325
example={"qaz": 0, "alpha": 0, "eta": 0}
2426
),
2527
store: HklCalcStore = Depends(get_store),
28+
collection: Optional[str] = Query(default=None, example="B07"),
2629
):
27-
await service.set_constraints(name, constraints, store)
30+
await service.set_constraints(name, constraints, store, collection)
2831

29-
return {"message": f"constraints updated (replaced) for crystal {name}"}
32+
return {
33+
"message": (
34+
f"constraints updated (replaced) for crystal {name} in "
35+
+ f"collection {collection}"
36+
)
37+
}
3038

3139

32-
@router.patch("/{name}/unconstrain/{property}")
40+
@router.delete("/{name}/{property}")
3341
async def remove_constraint(
3442
name: str,
3543
property: str,
3644
store: HklCalcStore = Depends(get_store),
45+
collection: Optional[str] = Query(default=None, example="B07"),
3746
):
38-
await service.remove_constraint(name, property, store)
47+
await service.remove_constraint(name, property, store, collection)
3948

40-
return {"message": f"unconstrained {property} for crystal {name}. "}
49+
return {
50+
"message": (
51+
f"unconstrained {property} for crystal {name} in "
52+
+ f"collection {collection}. "
53+
)
54+
}
4155

4256

43-
@router.patch("/{name}/constrain/{property}")
57+
@router.patch("/{name}/{property}")
4458
async def set_constraint(
4559
name: str,
4660
property: str,
4761
value: Union[float, bool] = Body(...),
4862
store: HklCalcStore = Depends(get_store),
63+
collection: Optional[str] = Query(default=None, example="B07"),
4964
):
50-
await service.set_constraint(name, property, value, store)
65+
await service.set_constraint(name, property, value, store, collection)
5166

52-
return {"message": f"constrained {property} for crystal {name}. "}
67+
return {
68+
"message": (
69+
f"constrained {property} for crystal {name} in collection "
70+
+ f"{collection}. "
71+
)
72+
}

0 commit comments

Comments
 (0)