Skip to content

Commit 330149a

Browse files
authored
Merge pull request #498 from esoteric-ephemera/main
Pydantic v2/v3 compat
2 parents 8977097 + d44e4d6 commit 330149a

File tree

2 files changed

+39
-40
lines changed

2 files changed

+39
-40
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ build/*
1313
*.egg-info
1414
dist/*
1515
.vscode
16+
17+
**/_version.py

crystal_toolkit/settings.py

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
from __future__ import annotations
22

3+
import os
34
from pathlib import Path
45
from typing import Literal
56

67
from pydantic import Field, HttpUrl, RedisDsn
7-
8-
try:
9-
# pydantic 2+
10-
from pydantic_settings import BaseSettings
11-
except ImportError:
12-
# pydantic <2
13-
from pydantic import BaseSettings
14-
8+
from pydantic_settings import BaseSettings, SettingsConfigDict
159

1610
MODULE_PATH = Path(__file__).parents[0]
1711

@@ -21,58 +15,58 @@ class Settings(BaseSettings):
2115

2216
DEBUG_MODE: bool = Field(
2317
default=False,
24-
help="This setting will set Dash's debug mode, will disable the cache used by Crystal Toolkit, and control log output.",
18+
description="This setting will set Dash's debug mode, will disable the cache used by Crystal Toolkit, and control log output.",
2519
)
2620
TEST_MODE: bool = Field(
2721
default=False,
28-
help="Set to True when Crytal Toolkit is run during automated testing. It will switch the default renderer to SVG instead of WebGL, since many testing environments do not have WebGL available.",
22+
description="Set to True when Crytal Toolkit is run during automated testing. It will switch the default renderer to SVG instead of WebGL, since many testing environments do not have WebGL available.",
2923
)
3024

3125
REDIS_URL: RedisDsn | None = Field(
3226
default="redis://localhost:6379",
33-
help="Redis instance used by Crystal Toolkit for caching. If set to None, simple caching will be used instead.",
27+
description="Redis instance used by Crystal Toolkit for caching. If set to None, simple caching will be used instead.",
3428
)
3529
ASSETS_PATH: Path = Field(
3630
default=MODULE_PATH / "apps" / "assets",
37-
help="Path to assets folder. Used only when running the example Crystal Toolkit apps.",
31+
description="Path to assets folder. Used only when running the example Crystal Toolkit apps.",
3832
)
3933

4034
PERSISTENCE: bool = Field(
4135
default=True,
42-
help="This setting controls whether Crystal Toolkit components in your app will have user-chosen values persisted by default or not. For example, choice of bonding algorithm, etc.",
36+
description="This setting controls whether Crystal Toolkit components in your app will have user-chosen values persisted by default or not. For example, choice of bonding algorithm, etc.",
4337
)
4438
PERSISTENCE_TYPE: Literal["memory", "session", "local"] = Field(
4539
default="local",
46-
help="If persistence enabled, this will control the type of persistence. See Dash documentation for more information.",
40+
description="If persistence enabled, this will control the type of persistence. See Dash documentation for more information.",
4741
)
4842

4943
PRIMARY_COLOR: str = Field(
5044
default="hsl(171, 100%, 41%)",
51-
help="A default primary color used for some user interface elements.",
45+
description="A default primary color used for some user interface elements.",
5246
)
5347

5448
BULMA_CSS_URL: HttpUrl | None = Field(
5549
default="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.4/css/bulma.min.css",
56-
help="If set, this CSS file will be loaded by default. Loading Bulma CSS is required only for aesthetic reasons.",
50+
description="If set, this CSS file will be loaded by default. Loading Bulma CSS is required only for aesthetic reasons.",
5751
)
5852
FONT_AWESOME_CSS_URL: HttpUrl | None = Field(
5953
default="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css",
60-
help="If set, this CSS file will be loaded by default. Loading Font Awesome is required to display certain icons, but otherwise is not required for functionality.",
54+
description="If set, this CSS file will be loaded by default. Loading Font Awesome is required to display certain icons, but otherwise is not required for functionality.",
6155
)
6256

6357
JUPYTER_EMBED_PORT: int | None = Field(
6458
default=8884,
65-
help="The Jupyter extension (powered by Dash) requires a port to run on. If None, an available port will be chosen.",
59+
description="The Jupyter extension (powered by Dash) requires a port to run on. If None, an available port will be chosen.",
6660
)
6761
JUPYTER_EMBED_MODE: Literal["external", "tab", "jupyterlab"] | None = Field(
6862
default=None,
69-
help="The Jupyter extension mode to use. See Dash documentation for more information.",
63+
description="The Jupyter extension mode to use. See Dash documentation for more information.",
7064
)
7165

7266
# Legend settings. These control the defaults for crystal structure and molecule visualization.
7367
LEGEND_COLOR_SCHEME: Literal["Jmol", "VESTA", "accessible"] = Field(
7468
default="Jmol",
75-
help="Color scheme used to display atoms.",
69+
description="Color scheme used to display atoms.",
7670
)
7771
LEGEND_RADIUS_SCHEME: Literal[
7872
"atomic",
@@ -83,72 +77,75 @@ class Settings(BaseSettings):
8377
"uniform",
8478
] = Field(
8579
default="uniform",
86-
help="Method with which to choose a radius when displaying atoms.",
80+
description="Method with which to choose a radius when displaying atoms.",
8781
)
8882
LEGEND_CMAP: str = Field(
8983
default="coolwarm",
90-
help="Color map for displaying atoms when color-coded by a site property. Choose from matplotlib color maps.",
84+
description="Color map for displaying atoms when color-coded by a site property. Choose from matplotlib color maps.",
9185
)
9286
LEGEND_FALLBACK_COLOR: tuple = Field(
9387
default=(0, 0, 0),
94-
help="Fallback color for displaying atoms when a more specific color is not defined.",
88+
description="Fallback color for displaying atoms when a more specific color is not defined.",
9589
)
9690
LEGEND_FALLBACK_RADIUS: float = Field(
9791
default=1.0,
98-
help="Fallback radius for displaying atoms when a more specific radius (e.g. ionic radius) is not defined.",
92+
description="Fallback radius for displaying atoms when a more specific radius (e.g. ionic radius) is not defined.",
9993
)
10094
LEGEND_UNIFORM_RADIUS: float = Field(
10195
default=0.5,
102-
help="Default radius for displaying atoms when uniform radii are chosen.",
96+
description="Default radius for displaying atoms when uniform radii are chosen.",
10397
)
10498

10599
# Materials Project API settings.
106100
# TODO: These should be deprecated in favor of setti
107-
API_KEY: str | None = Field(default="", help="Materials Project API key.")
101+
API_KEY: str | None = Field(
102+
default=os.environ.get("MP_API_KEY"), description="Materials Project API key."
103+
)
108104
API_EXTERNAL_ENDPOINT: str = Field(
109105
default="https://api.materialsproject.org",
110-
help="Materials Project API endpoint.",
106+
description="Materials Project API endpoint.",
111107
)
112108

113109
# Materials Project deployment settings. If not running Crystal Toolkit for the Materials Project website, these can be ignored.
114110
DEV_LOGIN_DISABLED: bool = Field(
115-
default=True, help="Used internally by Materials Project."
111+
default=True, description="Used internally by Materials Project."
116112
)
117113
LOGIN_ENDPOINT: str = Field(
118114
default="https://profile.materialsproject.org/",
119-
help="Used internally by Materials Project.",
115+
description="Used internally by Materials Project.",
120116
)
121117
APP_METADATA: Path = Field(
122118
default=MODULE_PATH / "apps" / "app_metadata.yaml",
123-
help="Path to app metadata field for Materials Project apps. Used as an alternative way of defining app metadata when defining many apps.",
119+
description="Path to app metadata field for Materials Project apps. Used as an alternative way of defining app metadata when defining many apps.",
124120
)
125121

126122
# Experimental settings.
127123
TRANSFORMATION_PREVIEWS: bool = Field(
128124
default=False,
129-
help="This setting controls whether previews are rendered for structure transformations.",
125+
description="This setting controls whether previews are rendered for structure transformations.",
130126
)
131127
DOI_CACHE_PATH: Path | None = Field(
132128
default=MODULE_PATH / "apps/assets/doi_cache.json",
133-
help="Not currently used, maybe will be deprecated. This was used to avoid a CrossRef API lookup when a small set of DOIs were used in an app.",
129+
description="Not currently used, maybe will be deprecated. This was used to avoid a CrossRef API lookup when a small set of DOIs were used in an app.",
134130
)
135131

136132
# Deprecated settings.
137133
MP_EMBED_MODE: bool = Field(
138134
default=False,
139-
help="Deprecated. This was used for early versions of Crystal Toolkit when embedded in the Materials Project website.",
135+
description="Deprecated. This was used for early versions of Crystal Toolkit when embedded in the Materials Project website.",
140136
)
141137

142-
class Config:
143-
"""Crystal Toolkit environment variable config class."""
138+
model_config = SettingsConfigDict(env_prefix="CT_", extra="ignore")
144139

145-
env_prefix = "CT_"
140+
def __repr__(self) -> str:
141+
"""Summarize settings."""
142+
return "Crystal Toolkit settings\n" + "\n".join(
143+
f" {key} = {val}" for key, val in self.dict().items()
144+
)
146145

147-
def print(self):
146+
def print(self) -> None:
148147
"""Print settings."""
149-
print("Crystal Toolkit settings")
150-
for key, val in self.dict().items():
151-
print(f" {key} = {val}")
148+
print(self.__repr__())
152149

153150

154151
SETTINGS = Settings()

0 commit comments

Comments
 (0)