Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pqn = "pqnstack.cli:app"

[project.optional-dependencies]
webapp = [
"dotenv>=0.9.9",
"fastapi[standard]>=0.115.14",
"httpx>=0.28.1",
"pydantic>=2.11.7",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"pydantic>=2.11.7",

Expand Down
49 changes: 36 additions & 13 deletions src/pqnstack/app/core/config.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
import logging
from dataclasses import dataclass
from dataclasses import field
import os
import tomllib
from pathlib import Path

from dotenv import load_dotenv
from pydantic import BaseModel
from pydantic import Field

from pqnstack.constants import BellState
from pqnstack.constants import QKDEncodingBasis
from pqnstack.pqn.protocols.measurement import MeasurementConfig

load_dotenv()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is necessary since pydantic-settings has dotenv support - see https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed



logger = logging.getLogger(__name__)


@dataclass
class CHSHSettings:
class CHSHSettings(BaseModel):
# Specifies which half waveplate to use for the CHSH experiment. First value is the provider's name, second is the motor name.
hwp: tuple[str, str] = ("", "")
request_hwp: tuple[str, str] = ("", "")
measurement_config: MeasurementConfig = field(default_factory=lambda: MeasurementConfig(5))
measurement_config: MeasurementConfig = Field(default_factory=lambda: MeasurementConfig(integration_time_s=5))


@dataclass
class QKDSettings:
class QKDSettings(BaseModel):
hwp: tuple[str, str] = ("", "")
request_hwp: tuple[str, str] = ("", "")
bitstring_length: int = 4
discriminating_threshold = 10
measurement_config: MeasurementConfig = field(default_factory=lambda: MeasurementConfig(5))
discriminating_threshold: int = 10
measurement_config: MeasurementConfig = Field(default_factory=lambda: MeasurementConfig(integration_time_s=5))


@dataclass
class Settings:
class Settings(BaseModel):
router_name: str
router_address: str
router_port: int
Expand All @@ -39,11 +42,31 @@ class Settings:
timetagger: tuple[str, str] | None = None # Name of the timetagger to use for the CHSH experiment.


static_typecheck_msg = "Please set the global 'settings' variable before use."
def load_settings_from_toml(config_path: str | Path) -> Settings:
"""Load settings from a TOML configuration file with Pydantic validation."""
config_path = Path(config_path)

with Path.open(config_path, "rb") as f:
config_data = tomllib.load(f)

# Pydantic will handle all validation and type conversion automatically
return Settings(**config_data)


def get_settings() -> Settings:
Comment on lines 62 to 63

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def get_settings() -> Settings:
@lru_cache
def get_settings() -> Settings:

raise NotImplementedError(static_typecheck_msg)
"""Load settings from the config file specified in API_CONFIG_PATH environment variable."""
config_path = os.getenv("API_CONFIG_PATH")

if config_path is None:
logger.warning("API_CONFIG_PATH environment variable not found, using default value './config.toml'")
config_path = "./config.toml"

config_file = Path(config_path)
if not config_file.exists():
msg = f"Configuration file not found: {config_file.absolute()} or 'API_CONFIG_PATH' environment variable is not set"
raise FileNotFoundError(msg)

return load_settings_from_toml(config_path)


settings = get_settings()
Expand Down
5 changes: 3 additions & 2 deletions src/pqnstack/pqn/protocols/measurement.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from dataclasses import dataclass

from pydantic import BaseModel

@dataclass
class MeasurementConfig:

class MeasurementConfig(BaseModel):
integration_time_s: float
binwidth_ps: int = 500
channel1: int = 1
Expand Down
13 changes: 13 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.