PyDIET 0.9.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pydiet/__init__.py +12 -0
- pydiet/api_client/__init__.py +6 -0
- pydiet/api_client/client.py +57 -0
- pydiet/cmd/__init__.py +9 -0
- pydiet/cmd/start.py +107 -0
- pydiet/data/data_config.toml +242 -0
- pydiet/data/description.txt +1 -0
- pydiet/data/instruments/description.txt +1 -0
- pydiet/data/instruments/megacam/default +0 -0
- pydiet/data/instruments/megacam/description.txt +1 -0
- pydiet/data/instruments/megacam/detector/description.txt +1 -0
- pydiet/data/instruments/megacam/detector/qe/MegaCam_QE.average.fits +0 -0
- pydiet/data/instruments/megacam/detector/qe/description.txt +2 -0
- pydiet/data/instruments/megacam/filters/CaHK.MP9303.fits +0 -0
- pydiet/data/instruments/megacam/filters/Ha.MP9603.fits +0 -0
- pydiet/data/instruments/megacam/filters/HaOFF.MP9604.fits +0 -0
- pydiet/data/instruments/megacam/filters/M4112.MP9403.fits +0 -0
- pydiet/data/instruments/megacam/filters/M4376.MP9404.fits +0 -0
- pydiet/data/instruments/megacam/filters/OIII.MP9501.fits +0 -0
- pydiet/data/instruments/megacam/filters/OIIIOFF.MP9502.fits +0 -0
- pydiet/data/instruments/megacam/filters/description.txt +1 -0
- pydiet/data/instruments/megacam/filters/g.MP9402.fits +0 -0
- pydiet/data/instruments/megacam/filters/gri.MP9605.fits +0 -0
- pydiet/data/instruments/megacam/filters/i.MP9703.fits +0 -0
- pydiet/data/instruments/megacam/filters/r.MP9602.fits +0 -0
- pydiet/data/instruments/megacam/filters/u.MP9302.fits +0 -0
- pydiet/data/instruments/megacam/filters/z.MP9901.fits +0 -0
- pydiet/data/instruments/megacam/optics/description.txt +2 -0
- pydiet/data/instruments/megacam/optics/transmission/MegaPrime_transmission.fits +0 -0
- pydiet/data/instruments/megacam/optics/transmission/description.txt +2 -0
- pydiet/data/instruments/wircam/description.txt +1 -0
- pydiet/data/instruments/wircam/detector/description.txt +1 -0
- pydiet/data/instruments/wircam/detector/qe/WIRCam_QE.average.fits +0 -0
- pydiet/data/instruments/wircam/detector/qe/description.txt +2 -0
- pydiet/data/instruments/wircam/filters/BrG.WC8305.fits +0 -0
- pydiet/data/instruments/wircam/filters/CH4Off.WC8204.fits +0 -0
- pydiet/data/instruments/wircam/filters/CH4On.WC8203.fits +0 -0
- pydiet/data/instruments/wircam/filters/CO.WC8306.fits +0 -0
- pydiet/data/instruments/wircam/filters/H.WC8201.fits +0 -0
- pydiet/data/instruments/wircam/filters/H.WC8202.fits +0 -0
- pydiet/data/instruments/wircam/filters/H2.WC8304.fits +0 -0
- pydiet/data/instruments/wircam/filters/J.WC8101.fits +0 -0
- pydiet/data/instruments/wircam/filters/J.WC8103.fits +0 -0
- pydiet/data/instruments/wircam/filters/Kcont.WC8303.fits +0 -0
- pydiet/data/instruments/wircam/filters/Ks.WC8301.fits +0 -0
- pydiet/data/instruments/wircam/filters/Ks.WC8302.fits +0 -0
- pydiet/data/instruments/wircam/filters/LowOH1.WC8104.fits +0 -0
- pydiet/data/instruments/wircam/filters/LowOH2.WC8102.fits +0 -0
- pydiet/data/instruments/wircam/filters/W.WC8105.fits +0 -0
- pydiet/data/instruments/wircam/filters/Y.WC8002.fits +0 -0
- pydiet/data/instruments/wircam/filters/description.txt +1 -0
- pydiet/data/instruments/wircam/optics/description.txt +2 -0
- pydiet/data/instruments/wircam/optics/transmission/WIRCam_transmission.fits +0 -0
- pydiet/data/instruments/wircam/optics/transmission/description.txt +2 -0
- pydiet/data/sites/description.txt +1 -0
- pydiet/data/sites/mko/default +0 -0
- pydiet/data/sites/mko/description.txt +2 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.0.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.1.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.2.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.3.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.4.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.5.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.6.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.7.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.8.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM1.9.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM2.0.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM2.5.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.bright.AM3.0.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.0.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.1.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.2.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.3.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.4.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.5.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.6.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.7.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.8.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM1.9.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM2.0.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM2.5.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.dark.AM3.0.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.0.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.1.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.2.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.3.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.4.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.5.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.6.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.7.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.8.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM1.9.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM2.0.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM2.5.fits +0 -0
- pydiet/data/sites/mko/emission/MKO_emission.grey.AM3.0.fits +0 -0
- pydiet/data/sites/mko/emission/description.txt +5 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.0.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.1.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.2.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.3.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.4.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.5.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.6.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.7.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.8.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM1.9.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM2.0.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM2.5.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM3.0.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM3.5.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM4.0.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM4.5.fits +0 -0
- pydiet/data/sites/mko/transmission/MKO_transmission.AM5.0.fits +0 -0
- pydiet/data/sites/mko/transmission/description.txt +5 -0
- pydiet/data/telescopes/cfht/default +0 -0
- pydiet/data/telescopes/cfht/description.txt +1 -0
- pydiet/data/telescopes/cfht/emission/description.txt +2 -0
- pydiet/data/telescopes/cfht/transmission/CFHT_M1_transmission.fits +0 -0
- pydiet/data/telescopes/cfht/transmission/description.txt +1 -0
- pydiet/data/telescopes/description.txt +1 -0
- pydiet/package.py +55 -0
- pydiet/py.typed +0 -0
- pydiet/server/__init__.py +9 -0
- pydiet/server/app.py +369 -0
- pydiet/server/config/__init__.py +51 -0
- pydiet/server/config/config.py +330 -0
- pydiet/server/config/fields.py +49 -0
- pydiet/server/config/settings.py +166 -0
- pydiet/server/data.py +31 -0
- pydiet/server/datafiles.py +367 -0
- pydiet/server/image.py +342 -0
- pydiet/server/models/__init__.py +34 -0
- pydiet/server/models/dataconfig.py +195 -0
- pydiet/server/models/default.py +9 -0
- pydiet/server/models/exceptions.py +9 -0
- pydiet/server/models/instrument.py +314 -0
- pydiet/server/models/query.py +172 -0
- pydiet/server/models/response.py +97 -0
- pydiet/server/models/types.py +35 -0
- pydiet/server/photsys.py +71 -0
- pydiet/server/response.py +237 -0
- pydiet/server/types/__init__.py +8 -0
- pydiet/server/types/quantity.py +532 -0
- pydiet/server/types/string.py +318 -0
- pydiet/templates/common/base.html +80 -0
- pydiet/templates/common/plot_filter.html +17 -0
- pydiet/templates/common/privacy.html +132 -0
- pydiet/templates/common/settings.html +23 -0
- pydiet/templates/common/terms.html +101 -0
- pydiet/templates/megacam/etc_form.html +319 -0
- pydiet/templates/megacam/etc_results.html +190 -0
- pydiet/templates/wircam/etc_form.html +319 -0
- pydiet/templates/wircam/etc_results.html +190 -0
- pydiet/web_client/css/style.css +221 -0
- pydiet/web_client/dist/pydiet.js +31 -0
- pydiet/web_client/images/logo.svg +6 -0
- pydiet/web_client/images/megacam/background.jpg +0 -0
- pydiet/web_client/images/megacam/logo.png +0 -0
- pydiet/web_client/images/wircam/background.jpg +0 -0
- pydiet/web_client/images/wircam/logo.png +0 -0
- pydiet/web_client/js/dom.js +51 -0
- pydiet/web_client/js/etc.js +63 -0
- pydiet/web_client/js/fetch.js +49 -0
- pydiet/web_client/js/instrument.js +62 -0
- pydiet/web_client/js/main.js +15 -0
- pydiet/web_client/js/plot.js +88 -0
- pydiet/web_client/js/settings.js +57 -0
- pydiet/web_client/js/theme.js +43 -0
- pydiet/web_client/js/url.js +12 -0
- pydiet/web_client/jsdoc.json +20 -0
- pydiet/web_client/package.json +83 -0
- pydiet-0.9.3.dist-info/METADATA +118 -0
- pydiet-0.9.3.dist-info/RECORD +177 -0
- pydiet-0.9.3.dist-info/WHEEL +4 -0
- pydiet-0.9.3.dist-info/entry_points.txt +5 -0
- pydiet-0.9.3.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provide Pydantic-compatible annotations and annotated types for enhanced string
|
|
3
|
+
validation and serialization.
|
|
4
|
+
"""
|
|
5
|
+
# Copyright UParisSaclay/CEA/CFHT/CNRS
|
|
6
|
+
# Licensed under the MIT licence
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from re import compile
|
|
11
|
+
from typing import TYPE_CHECKING, Annotated, Any, Pattern
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from pydantic import GetCoreSchemaHandler
|
|
15
|
+
from pydantic import Field
|
|
16
|
+
from pydantic_core import core_schema
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class StrAnnotation:
|
|
21
|
+
"""
|
|
22
|
+
Pydantic compatible annotation for validating and serializing strings
|
|
23
|
+
(the original Pydantic 2.x string fields only support Rust Regex).
|
|
24
|
+
|
|
25
|
+
Examples
|
|
26
|
+
--------
|
|
27
|
+
>>> from typing import Annotated
|
|
28
|
+
>>> from pydantic import BaseModel
|
|
29
|
+
>>> from .string import StrAnnotation
|
|
30
|
+
|
|
31
|
+
>>> class Person(BaseModel):
|
|
32
|
+
... firstname: Annotated[str, StrAnnotation(pattern=r"[A-Z][a-z]*")]
|
|
33
|
+
... lastname: Annotated[str, StrAnnotation(pattern=r"[A-Z][a-z]*")]
|
|
34
|
+
|
|
35
|
+
>>> # The following instantiation validates
|
|
36
|
+
>>> user = Person(firstname="Emmanuel", lastname="Bertin")
|
|
37
|
+
|
|
38
|
+
>>> # The following instantiation does not validate
|
|
39
|
+
>>> user = Person(firstname="emmanuel", lastname="Bertin")
|
|
40
|
+
Traceback (most recent call last):
|
|
41
|
+
...
|
|
42
|
+
pydantic_core._pydantic_core.ValidationError: 1 validation error for Person
|
|
43
|
+
firstname
|
|
44
|
+
Value error, string does not match [A-Z][a-z]* pattern
|
|
45
|
+
[type=value_error, input_value='emmanuel', input_type=str]
|
|
46
|
+
For further information visit https://errors.pydantic.dev/2.8/v/value_error
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
description: str, optional
|
|
51
|
+
Description string.
|
|
52
|
+
min_length: int, optional
|
|
53
|
+
Minimum string length.
|
|
54
|
+
max_length: int, optional
|
|
55
|
+
Maximum string length.
|
|
56
|
+
pattern: Pattern, optional
|
|
57
|
+
Regular expression for validation.
|
|
58
|
+
valid_list: list[str], optional
|
|
59
|
+
List of validating strings.
|
|
60
|
+
"""
|
|
61
|
+
description: str = ""
|
|
62
|
+
min_length: int | None = None
|
|
63
|
+
max_length: int | None = None
|
|
64
|
+
pattern: Pattern | None = None
|
|
65
|
+
valid_list: list[str] | None = None
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
*,
|
|
69
|
+
description: str = "",
|
|
70
|
+
min_length: int | None = None,
|
|
71
|
+
max_length: int | None = None,
|
|
72
|
+
pattern: Pattern | None = None,
|
|
73
|
+
valid_list: list[str] | None = None):
|
|
74
|
+
|
|
75
|
+
self.description = description
|
|
76
|
+
self.min_length = min_length
|
|
77
|
+
self.max_length = max_length
|
|
78
|
+
self.pattern = pattern
|
|
79
|
+
if pattern is not None:
|
|
80
|
+
self.compiled = compile(pattern)
|
|
81
|
+
self.valid_list = valid_list
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def validate(
|
|
85
|
+
self,
|
|
86
|
+
s: str,
|
|
87
|
+
info: core_schema.ValidationInfo | None = None) -> str:
|
|
88
|
+
|
|
89
|
+
"""
|
|
90
|
+
Validate `str`.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
s: str
|
|
95
|
+
String that should be validated.
|
|
96
|
+
info: ~pydantic.core_schema.ValidationInfo, optional
|
|
97
|
+
The validation info provided by the Pydantic schema.
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
s: str
|
|
102
|
+
Validated string.
|
|
103
|
+
|
|
104
|
+
Raises
|
|
105
|
+
------
|
|
106
|
+
ValueError: exception
|
|
107
|
+
An error occurred validating the specified string.
|
|
108
|
+
It is raised if any of the following occur:
|
|
109
|
+
- the provided string did not match the pattern.
|
|
110
|
+
- An unknown type was provided for the string.
|
|
111
|
+
"""
|
|
112
|
+
# Check if it is a string
|
|
113
|
+
if not isinstance(s, str):
|
|
114
|
+
raise ValueError("not a string")
|
|
115
|
+
|
|
116
|
+
# Check if it has the right size
|
|
117
|
+
if self.min_length and len(s) < self.min_length:
|
|
118
|
+
raise ValueError(f"String should have at least {self.min_length} characters")
|
|
119
|
+
if self.max_length and len(s) > self.max_length:
|
|
120
|
+
raise ValueError(f"String should have at most {self.max_length} characters")
|
|
121
|
+
|
|
122
|
+
# Check if it matches the regular expression if provided
|
|
123
|
+
if self.pattern and not self.compiled.match(s):
|
|
124
|
+
raise ValueError(f"String should match {self.pattern} pattern")
|
|
125
|
+
|
|
126
|
+
# Check if it matches any member of the list if provided
|
|
127
|
+
if self.valid_list and not s in self.valid_list:
|
|
128
|
+
raise ValueError(f"String should match any of {self.valid_list}")
|
|
129
|
+
|
|
130
|
+
return s
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def serialize(
|
|
134
|
+
self,
|
|
135
|
+
s: str,
|
|
136
|
+
info: core_schema.SerializationInfo | None = None,
|
|
137
|
+
*,
|
|
138
|
+
to_json: bool = False) -> dict | str:
|
|
139
|
+
"""
|
|
140
|
+
Serialize string.
|
|
141
|
+
|
|
142
|
+
Parameters
|
|
143
|
+
----------
|
|
144
|
+
s: str
|
|
145
|
+
String that should be serialized.
|
|
146
|
+
info: pydantic.core_schema.SerializationInfo, optional
|
|
147
|
+
Serialization info provided by the Pydantic schema.
|
|
148
|
+
to_json: bool, optional
|
|
149
|
+
Whether or not to serialize to a json convertible object.
|
|
150
|
+
|
|
151
|
+
Returns
|
|
152
|
+
-------
|
|
153
|
+
s: str
|
|
154
|
+
The serialized `str`.
|
|
155
|
+
"""
|
|
156
|
+
return s
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def __get_pydantic_core_schema__(
|
|
160
|
+
self,
|
|
161
|
+
source_type: Any,
|
|
162
|
+
handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
|
|
163
|
+
"""
|
|
164
|
+
Get the Pydantic core schema.
|
|
165
|
+
|
|
166
|
+
Parameters
|
|
167
|
+
----------
|
|
168
|
+
source_type:
|
|
169
|
+
The source type.
|
|
170
|
+
handler: ~pydantic.GetCoreSchemaHandler
|
|
171
|
+
The `GetCoreSchemaHandler` instance.
|
|
172
|
+
|
|
173
|
+
Returns
|
|
174
|
+
-------
|
|
175
|
+
The Pydantic core schema.
|
|
176
|
+
"""
|
|
177
|
+
_from_typedict_schema = {
|
|
178
|
+
"value": core_schema.typed_dict_field(
|
|
179
|
+
core_schema.str_schema()
|
|
180
|
+
),
|
|
181
|
+
"str": core_schema.typed_dict_field(core_schema.str_schema()),
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
validate_schema = core_schema.chain_schema(
|
|
185
|
+
[
|
|
186
|
+
core_schema.union_schema(
|
|
187
|
+
[
|
|
188
|
+
core_schema.is_instance_schema(str),
|
|
189
|
+
core_schema.str_schema(
|
|
190
|
+
min_length=self.min_length,
|
|
191
|
+
max_length=self.max_length,
|
|
192
|
+
pattern=self.pattern
|
|
193
|
+
)
|
|
194
|
+
]
|
|
195
|
+
),
|
|
196
|
+
core_schema.with_info_plain_validator_function(self.validate),
|
|
197
|
+
]
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
validate_json_schema = core_schema.chain_schema(
|
|
201
|
+
[
|
|
202
|
+
core_schema.str_schema(
|
|
203
|
+
min_length=self.min_length,
|
|
204
|
+
max_length=self.max_length,
|
|
205
|
+
pattern=self.pattern
|
|
206
|
+
),
|
|
207
|
+
core_schema.no_info_plain_validator_function(self.validate)
|
|
208
|
+
]
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
serialize_schema = core_schema.plain_serializer_function_ser_schema(
|
|
212
|
+
self.serialize,
|
|
213
|
+
info_arg=True,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
return core_schema.json_or_python_schema(
|
|
217
|
+
json_schema=validate_json_schema,
|
|
218
|
+
python_schema=validate_schema,
|
|
219
|
+
serialization=serialize_schema,
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def AnnotatedStr(
|
|
225
|
+
default: str,
|
|
226
|
+
short: str | None = None,
|
|
227
|
+
description: str = "",
|
|
228
|
+
min_length: int | None = None,
|
|
229
|
+
max_length: int | None = None,
|
|
230
|
+
pattern: Pattern | None = None,
|
|
231
|
+
valid_list: list[str] | None = None) -> Any:
|
|
232
|
+
"""
|
|
233
|
+
Pydantic pseudo-field for validating and serializing strings
|
|
234
|
+
(the original Pydantic 2.x string fields only support Rust Regex).
|
|
235
|
+
|
|
236
|
+
Examples
|
|
237
|
+
--------
|
|
238
|
+
>>> from pydantic_settings import BaseSettings
|
|
239
|
+
>>> from .string import AnnotatedStr
|
|
240
|
+
|
|
241
|
+
>>> class Person(BaseSettings):
|
|
242
|
+
... firstname: AnnotatedStr(
|
|
243
|
+
... short='f',
|
|
244
|
+
... description="First name.",
|
|
245
|
+
... default="Unknown",
|
|
246
|
+
... min_length=1,
|
|
247
|
+
... pattern=r"[A-Z][a-z]*"
|
|
248
|
+
... )
|
|
249
|
+
... lastname: AnnotatedStr(
|
|
250
|
+
... short='l',
|
|
251
|
+
... description="Last name.",
|
|
252
|
+
... default="Unknown",
|
|
253
|
+
... min_length=1,
|
|
254
|
+
... pattern=r"[A-Z][a-z]*"
|
|
255
|
+
... )
|
|
256
|
+
|
|
257
|
+
>>> # The following instantiation validates
|
|
258
|
+
>>> user = Person(firstname="Emmanuel", lastname="Bertin")
|
|
259
|
+
|
|
260
|
+
>>> # The following instantiation does not validate
|
|
261
|
+
user = Person(firstname="emmanuel", lastname="Bertin")
|
|
262
|
+
Traceback (most recent call last):
|
|
263
|
+
...
|
|
264
|
+
pydantic_core._pydantic_core.ValidationError: 1 validation error for Person
|
|
265
|
+
firstname
|
|
266
|
+
Value error, string does not match [A-Z][a-z]* pattern
|
|
267
|
+
[type=value_error, input_value='emmanuel', input_type=str]
|
|
268
|
+
For further information visit https://errors.pydantic.dev/2.8/v/value_error
|
|
269
|
+
|
|
270
|
+
Parameters
|
|
271
|
+
----------
|
|
272
|
+
default: str | ~astropy.units.Quantity
|
|
273
|
+
Default value
|
|
274
|
+
short: str, optional
|
|
275
|
+
shortcut for keyword
|
|
276
|
+
description: str, optional
|
|
277
|
+
Description string.
|
|
278
|
+
min_length: int, optional
|
|
279
|
+
Minimum string length.
|
|
280
|
+
max_length: int, optional
|
|
281
|
+
Maximum string length.
|
|
282
|
+
pattern: Pattern, optional
|
|
283
|
+
Regular expression for validation.
|
|
284
|
+
valid_list: list[str], optional
|
|
285
|
+
List of validating strings.
|
|
286
|
+
"""
|
|
287
|
+
|
|
288
|
+
json_extra: dict = {}
|
|
289
|
+
if default is not None:
|
|
290
|
+
json_extra['default'] = default
|
|
291
|
+
if max_length is not None:
|
|
292
|
+
json_extra['maxLength'] = str(max_length)
|
|
293
|
+
if min_length is not None:
|
|
294
|
+
json_extra['minLength'] = str(min_length)
|
|
295
|
+
if pattern is not None:
|
|
296
|
+
json_extra['pattern'] = str(pattern)
|
|
297
|
+
if valid_list is not None:
|
|
298
|
+
json_extra['valid_list'] = valid_list
|
|
299
|
+
if short:
|
|
300
|
+
json_extra['short'] = short
|
|
301
|
+
return Annotated[
|
|
302
|
+
str,
|
|
303
|
+
StrAnnotation(
|
|
304
|
+
min_length=min_length,
|
|
305
|
+
max_length=max_length,
|
|
306
|
+
pattern=pattern,
|
|
307
|
+
valid_list=valid_list
|
|
308
|
+
),
|
|
309
|
+
Field(
|
|
310
|
+
default_factory=lambda: default,
|
|
311
|
+
description=description,
|
|
312
|
+
validate_default=True,
|
|
313
|
+
json_schema_extra=json_extra
|
|
314
|
+
)
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{#
|
|
2
|
+
# Base Jinja2 template for PyDIET client.
|
|
3
|
+
#
|
|
4
|
+
# Copyright CFHT/CNRS/OSUPS/CEA/UParisSaclay
|
|
5
|
+
# Licensed under the MIT licence
|
|
6
|
+
#}<!DOCTYPE html>
|
|
7
|
+
<html lang="en">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="utf-8" />
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
11
|
+
<meta id="root_path" content="{{ root_path }}">
|
|
12
|
+
<link rel="icon" type="image/svg+xml" href="{{ root_path }}/client/images/logo.svg">
|
|
13
|
+
<title>{{ package.summary }}</title>
|
|
14
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
|
|
15
|
+
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
|
|
16
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" />
|
|
17
|
+
<link rel="stylesheet" href="{{ root_path }}/client/css/style.css" />
|
|
18
|
+
{% block headcontent %}{% endblock headcontent %}
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
<ion-app>
|
|
22
|
+
<ion-header>
|
|
23
|
+
<ion-toolbar>
|
|
24
|
+
<ion-menu-button slot="start"><ion-icon name="options"></ion-icon></ion-menu-button>
|
|
25
|
+
<ion-title size="large">
|
|
26
|
+
<ion-item lines="none">
|
|
27
|
+
<h3 style="width:100%; display:flex; justify-content:space-between; align-items: baseline;">
|
|
28
|
+
<span>DIET</span>
|
|
29
|
+
<span style="font-size: 0.75rem; color: var(--ion-color-medium);">v{{ package.version }}</span>
|
|
30
|
+
</h3>
|
|
31
|
+
</ion-item>
|
|
32
|
+
</ion-title>
|
|
33
|
+
<div id=user-slot slot="end"></div>
|
|
34
|
+
</ion-toolbar>
|
|
35
|
+
</ion-header>
|
|
36
|
+
<ion-menu side="start" content-id="main-content" style="--min-width:20rem;">
|
|
37
|
+
{% include "common/settings.html" %}
|
|
38
|
+
<ion-footer-bar>
|
|
39
|
+
<ion-item-divider>
|
|
40
|
+
</ion-item-divider>
|
|
41
|
+
<ion-item href="{{ root_path ~ doc_url }}" rel="external" target="_blank">
|
|
42
|
+
<ion-icon name="book" slot="start"></ion-icon>
|
|
43
|
+
<ion-label>Documentation</ion-label>
|
|
44
|
+
</ion-item>
|
|
45
|
+
<ion-item href="{{ root_path }}/docs" rel="external" target="_blank">
|
|
46
|
+
<ion-icon name="code-slash" slot="start"></ion-icon>
|
|
47
|
+
<ion-label>Web API</ion-label>
|
|
48
|
+
</ion-item>
|
|
49
|
+
</ion-footer-bar>
|
|
50
|
+
</ion-menu>
|
|
51
|
+
<ion-content id="main-content">
|
|
52
|
+
<div id="content-slot"></div>
|
|
53
|
+
<div id="modal-slot"></div>
|
|
54
|
+
</ion-content>
|
|
55
|
+
<ion-footer>
|
|
56
|
+
<ion-toolbar >
|
|
57
|
+
<ion-item lines="none" slot="start">
|
|
58
|
+
<ion-note id="terms" style="align-self:center; cursor:pointer">Terms of Service</ion-note>
|
|
59
|
+
</ion-item>
|
|
60
|
+
<ion-fab horizontal="center" vertical="center">
|
|
61
|
+
<ion-fab-button href="https://cfht.hawaii.edu" color="light" size="small">
|
|
62
|
+
<ion-icon src="{{ root_path }}/client/images/logo.svg"></ion-icon>
|
|
63
|
+
</ion-fab-button>
|
|
64
|
+
</ion-fab>
|
|
65
|
+
<ion-item lines="none" slot="end">
|
|
66
|
+
<ion-note id="privacy" style="align-self:center; cursor:pointer">Privacy Policy</ion-note>
|
|
67
|
+
</ion-item>
|
|
68
|
+
</ion-toolbar>
|
|
69
|
+
</ion-footer>
|
|
70
|
+
<ion-modal trigger="terms">
|
|
71
|
+
{% include "common/terms.html" %}
|
|
72
|
+
</ion-modal>
|
|
73
|
+
<ion-modal trigger="privacy">
|
|
74
|
+
{% include "common/privacy.html" %}
|
|
75
|
+
</ion-modal>
|
|
76
|
+
</ion-app>
|
|
77
|
+
<script src="{{ root_path }}/client/dist/pydiet.js"></script>
|
|
78
|
+
</body>
|
|
79
|
+
</html>
|
|
80
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{#
|
|
2
|
+
# Jinja2 template for plotting PyDIET filter curves.
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2024,2025 CFHT/CNRS/OSUPS/CEA/UParisSaclay
|
|
5
|
+
# Licensed under the MIT licence
|
|
6
|
+
#}
|
|
7
|
+
<ion-modal is-open=true backdrop-dismiss=true style="--height:auto;">
|
|
8
|
+
<ion-card>
|
|
9
|
+
<ion-card-header>
|
|
10
|
+
<ion-card-title>Instrument+telescope transmission curve</ion-card-title>
|
|
11
|
+
</ion-card-header>
|
|
12
|
+
<ion-card-content>
|
|
13
|
+
<canvas id="filter-canvas" />
|
|
14
|
+
</ion-card-content>
|
|
15
|
+
</ion-card>
|
|
16
|
+
</ion-modal>
|
|
17
|
+
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<ion-content class="ion-padding">
|
|
2
|
+
<ion-text color="medium">
|
|
3
|
+
<section class="privacy-policy">
|
|
4
|
+
<h1>Privacy Policy</h1>
|
|
5
|
+
<p><em>Last updated: March 17, 2026</em></p>
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
This Privacy Policy describes how <strong>PyDIET</strong>
|
|
9
|
+
(“the Service”), operated by <a href="https://www.cfht.hawaii.edu"><strong>CFHT</strong></a>, a
|
|
10
|
+
U.S.-based non-profit research organization, collects and uses information
|
|
11
|
+
when you access or use the Service.
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<h2>1. Scope of the Service</h2>
|
|
15
|
+
<p>
|
|
16
|
+
The Service is an academic web-based exposure time calculator accessible
|
|
17
|
+
worldwide. It does not require user accounts or authentication.
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<h2>2. Information We Collect</h2>
|
|
21
|
+
|
|
22
|
+
<h3>a. Information you provide</h3>
|
|
23
|
+
<p>
|
|
24
|
+
The Service does not require or collect personal information such as names,
|
|
25
|
+
email addresses, or account credentials.
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
<h3>b. Automatically collected information</h3>
|
|
29
|
+
<p>
|
|
30
|
+
When you access the Service, our servers may automatically record limited
|
|
31
|
+
technical information in standard server logs, including:
|
|
32
|
+
</p>
|
|
33
|
+
<ul>
|
|
34
|
+
<li>IP address</li>
|
|
35
|
+
<li>Date and time of requests</li>
|
|
36
|
+
<li>Requested URLs and query parameters</li>
|
|
37
|
+
<li>HTTP method (GET/POST)</li>
|
|
38
|
+
<li>User agent (browser or client information)</li>
|
|
39
|
+
</ul>
|
|
40
|
+
<p>
|
|
41
|
+
This information is collected solely for operational, security, and
|
|
42
|
+
debugging purposes.
|
|
43
|
+
</p>
|
|
44
|
+
|
|
45
|
+
<h3>c. Local storage</h3>
|
|
46
|
+
<p>
|
|
47
|
+
The Service may use your browser’s local storage to save application
|
|
48
|
+
settings, such as preferences. This data remains on your device and is not
|
|
49
|
+
transmitted to our servers.
|
|
50
|
+
</p>
|
|
51
|
+
|
|
52
|
+
<h2>3. Use of Information</h2>
|
|
53
|
+
<p>We use the limited data we collect to:</p>
|
|
54
|
+
<ul>
|
|
55
|
+
<li>Operate and maintain the Service</li>
|
|
56
|
+
<li>Monitor performance and ensure security</li>
|
|
57
|
+
<li>Diagnose technical issues and improve functionality</li>
|
|
58
|
+
</ul>
|
|
59
|
+
<p>
|
|
60
|
+
We do not use your data for profiling, advertising, or marketing purposes.
|
|
61
|
+
</p>
|
|
62
|
+
|
|
63
|
+
<h2>4. Legal Basis for Processing (EEA/UK users)</h2>
|
|
64
|
+
<p>
|
|
65
|
+
For users in the European Economic Area or the United Kingdom, processing
|
|
66
|
+
of technical log data is based on our legitimate interests in ensuring the
|
|
67
|
+
security, stability, and proper functioning of the Service.
|
|
68
|
+
</p>
|
|
69
|
+
|
|
70
|
+
<h2>5. Data Retention</h2>
|
|
71
|
+
<p>
|
|
72
|
+
Server logs are retained only for the minimum period required by applicable
|
|
73
|
+
laws and institutional policies, after which they are deleted or anonymized.
|
|
74
|
+
</p>
|
|
75
|
+
|
|
76
|
+
<h2>6. Data Sharing</h2>
|
|
77
|
+
<p>
|
|
78
|
+
We do not sell, rent, or share personal data with third parties.
|
|
79
|
+
</p>
|
|
80
|
+
<p>
|
|
81
|
+
Data may be disclosed only if required by law or as reasonably necessary to
|
|
82
|
+
protect the security and integrity of the Service.
|
|
83
|
+
</p>
|
|
84
|
+
|
|
85
|
+
<h2>7. International Users</h2>
|
|
86
|
+
<p>
|
|
87
|
+
The Service is operated from the United States. By using the Service, you
|
|
88
|
+
acknowledge that technical information described in this Privacy Policy may
|
|
89
|
+
be processed in the United States.
|
|
90
|
+
</p>
|
|
91
|
+
|
|
92
|
+
<h2>8. Your Rights</h2>
|
|
93
|
+
<p>
|
|
94
|
+
Depending on your jurisdiction, you may have rights regarding your personal
|
|
95
|
+
data, including rights to access, correct, delete, or object to certain
|
|
96
|
+
processing.
|
|
97
|
+
</p>
|
|
98
|
+
<p>
|
|
99
|
+
Because we do not maintain user accounts or directly identifiable user
|
|
100
|
+
profiles, we may not be able to link technical log data to a specific
|
|
101
|
+
individual except where required by law and reasonably feasible.
|
|
102
|
+
</p>
|
|
103
|
+
|
|
104
|
+
<h2>9. Children’s Privacy</h2>
|
|
105
|
+
<p>
|
|
106
|
+
The Service is intended for academic and general audiences and does not
|
|
107
|
+
knowingly collect personal data from children.
|
|
108
|
+
</p>
|
|
109
|
+
|
|
110
|
+
<h2>10. Security</h2>
|
|
111
|
+
<p>
|
|
112
|
+
We implement reasonable technical and organizational measures to protect the
|
|
113
|
+
Service and associated data, including standard web security practices.
|
|
114
|
+
</p>
|
|
115
|
+
|
|
116
|
+
<h2>11. Changes to This Policy</h2>
|
|
117
|
+
<p>
|
|
118
|
+
This Privacy Policy may be updated from time to time. Updates will be
|
|
119
|
+
posted on this page with a revised “Last updated” date.
|
|
120
|
+
</p>
|
|
121
|
+
|
|
122
|
+
<h2>12. Contact</h2>
|
|
123
|
+
<p>
|
|
124
|
+
For questions about this Privacy Policy, please contact:
|
|
125
|
+
</p>
|
|
126
|
+
<p>
|
|
127
|
+
<a href="mailto:info@cfht.hawaii.edu">info@cfht.hawaii.edu</a>
|
|
128
|
+
</p>
|
|
129
|
+
</section>
|
|
130
|
+
</ion-text>
|
|
131
|
+
</ion-content>
|
|
132
|
+
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{#
|
|
2
|
+
# Jinja2 template for PyDIET Settings section.
|
|
3
|
+
#
|
|
4
|
+
# Copyright CFHT/CNRS/OSUPS/CEA/UParisSaclay
|
|
5
|
+
# Licensed under the MIT licence
|
|
6
|
+
#}
|
|
7
|
+
<ion-list>
|
|
8
|
+
<ion-list-header>Settings</ion-list-header>
|
|
9
|
+
<ion-item slot="start">
|
|
10
|
+
<ion-label position="fixed">Theme</ion-label>
|
|
11
|
+
<ion-segment id="theme-segment" slot="end" value="auto" scrollable=true mode="ios">
|
|
12
|
+
{# Theme radio buttons will be inserted here by JS code #}
|
|
13
|
+
</ion-segment>
|
|
14
|
+
</ion-item>
|
|
15
|
+
<ion-item-divider></ion-item-divider>
|
|
16
|
+
<ion-item slot="start">
|
|
17
|
+
<ion-label position="fixed">Instrument</ion-label>
|
|
18
|
+
<ion-segment id="instrument-segment" value="megacam" scrollable=true mode="ios">
|
|
19
|
+
{# Instrument radio buttons will be inserted here by JS code #}
|
|
20
|
+
</ion-segment>
|
|
21
|
+
</ion-item>
|
|
22
|
+
</ion-list>
|
|
23
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<ion-content class="ion-padding">
|
|
2
|
+
<ion-text color="medium">
|
|
3
|
+
<section class="terms-of-service">
|
|
4
|
+
<h1>Terms of Service</h1>
|
|
5
|
+
<p><em>Last updated: March 17, 2026</em></p>
|
|
6
|
+
|
|
7
|
+
<p>
|
|
8
|
+
These Terms of Service (“Terms”) govern your use of
|
|
9
|
+
<strong>PyDIET</strong> (the “Service”), operated by
|
|
10
|
+
<a href="https://www.cfht.hawaii.edu"><strong>CFHT</strong></a>, a
|
|
11
|
+
U.S.-based non-profit research organization.
|
|
12
|
+
By accessing or using the Service, you agree to these Terms.
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
<h2>1. Description of the Service</h2>
|
|
16
|
+
<p>
|
|
17
|
+
The Service provides an exposure time calculator (ETC) intended for
|
|
18
|
+
academic, research, and educational purposes. The Service is provided
|
|
19
|
+
without user authentication and may be accessed via a web interface or API.
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
<h2>2. Open Source Software</h2>
|
|
23
|
+
<p>
|
|
24
|
+
The underlying code of the Service is made available under the MIT License.
|
|
25
|
+
Your use of the source code is governed by the terms of that license.
|
|
26
|
+
</p>
|
|
27
|
+
|
|
28
|
+
<h2>3. No Warranty</h2>
|
|
29
|
+
<p>
|
|
30
|
+
The Service is provided “as is” and “as available,” without warranty of any
|
|
31
|
+
kind, express or implied, including but not limited to warranties of
|
|
32
|
+
accuracy, reliability, fitness for a particular purpose, or non-infringement.
|
|
33
|
+
</p>
|
|
34
|
+
<p>
|
|
35
|
+
The results produced by the Service are estimates only and may not reflect
|
|
36
|
+
actual observational or instrumental performance.
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
<h2>4. Limitation of Liability</h2>
|
|
40
|
+
<p>
|
|
41
|
+
To the fullest extent permitted by applicable law, CFHT shall
|
|
42
|
+
not be liable for any direct, indirect, incidental, consequential, or
|
|
43
|
+
special damages arising out of or in connection with the use of, or inability
|
|
44
|
+
to use, the Service, including but not limited to errors in calculations,
|
|
45
|
+
scientific results, or observational planning.
|
|
46
|
+
</p>
|
|
47
|
+
|
|
48
|
+
<h2>5. Use of the Service</h2>
|
|
49
|
+
<p>
|
|
50
|
+
You agree to use the Service only for lawful purposes and in a manner
|
|
51
|
+
consistent with its intended academic and research use. You are solely
|
|
52
|
+
responsible for how you interpret and use the results.
|
|
53
|
+
</p>
|
|
54
|
+
|
|
55
|
+
<h2>6. Modifications to the Service</h2>
|
|
56
|
+
<p>
|
|
57
|
+
CFHT reserves the right to modify, update, or discontinue any
|
|
58
|
+
aspect of the Service at any time without notice.
|
|
59
|
+
</p>
|
|
60
|
+
<p>
|
|
61
|
+
This includes, but is not limited to, changes in instrument models,
|
|
62
|
+
calibration data, algorithms, or implementation details, which may result
|
|
63
|
+
in differences in the outputs produced by the Service over time.
|
|
64
|
+
</p>
|
|
65
|
+
|
|
66
|
+
<h2>7. Availability</h2>
|
|
67
|
+
<p>
|
|
68
|
+
The Service may be unavailable from time to time due to maintenance,
|
|
69
|
+
updates, or technical issues. No guarantee of uptime or availability is
|
|
70
|
+
provided.
|
|
71
|
+
</p>
|
|
72
|
+
|
|
73
|
+
<h2>8. Third-Party Use and API</h2>
|
|
74
|
+
<p>
|
|
75
|
+
The Service may be accessed programmatically via an API. Excessive or abusive
|
|
76
|
+
use may be restricted to ensure fair access and system stability.
|
|
77
|
+
</p>
|
|
78
|
+
|
|
79
|
+
<h2>9. Governing Law</h2>
|
|
80
|
+
<p>
|
|
81
|
+
These Terms shall be governed by and construed in accordance with the laws
|
|
82
|
+
of the United States, without regard to conflict of law principles.
|
|
83
|
+
</p>
|
|
84
|
+
|
|
85
|
+
<h2>10. Changes to These Terms</h2>
|
|
86
|
+
<p>
|
|
87
|
+
These Terms may be updated from time to time. Continued use of the Service
|
|
88
|
+
after changes are posted constitutes acceptance of the revised Terms.
|
|
89
|
+
</p>
|
|
90
|
+
|
|
91
|
+
<h2>11. Contact</h2>
|
|
92
|
+
<p>
|
|
93
|
+
For questions regarding these Terms, please contact:
|
|
94
|
+
</p>
|
|
95
|
+
<p>
|
|
96
|
+
<a href="mailto:info@cfht.hawaii.edu">info@cfht.hawaii.edu</a>
|
|
97
|
+
</p>
|
|
98
|
+
</section>
|
|
99
|
+
</ion-text>
|
|
100
|
+
</ion-content>
|
|
101
|
+
|