sciform 0.33.0__py3-none-any.whl → 0.34.0__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.
- sciform/__init__.py +16 -8
- sciform/formatter.py +149 -90
- sciform/formatting.py +92 -5
- sciform/fsml.py +4 -4
- sciform/global_configuration.py +35 -28
- sciform/options/__init__.py +1 -0
- sciform/options/conversion.py +120 -0
- sciform/{rendered_options.py → options/finalized_options.py} +7 -11
- sciform/{global_options.py → options/global_options.py} +10 -10
- sciform/options/input_options.py +104 -0
- sciform/options/populated_options.py +136 -0
- sciform/options/validation.py +101 -0
- sciform/output_conversion.py +2 -2
- sciform/scinum.py +13 -12
- {sciform-0.33.0.dist-info → sciform-0.34.0.dist-info}/METADATA +13 -9
- sciform-0.34.0.dist-info/RECORD +23 -0
- sciform/user_options.py +0 -188
- sciform-0.33.0.dist-info/RECORD +0 -19
- {sciform-0.33.0.dist-info → sciform-0.34.0.dist-info}/LICENSE +0 -0
- {sciform-0.33.0.dist-info → sciform-0.34.0.dist-info}/WHEEL +0 -0
- {sciform-0.33.0.dist-info → sciform-0.34.0.dist-info}/top_level.txt +0 -0
sciform/__init__.py
CHANGED
@@ -1,22 +1,30 @@
|
|
1
1
|
"""``sciform`` is used to convert python numbers into scientific formatted strings."""
|
2
2
|
|
3
3
|
from sciform.formatter import Formatter
|
4
|
+
from sciform.formatting import FormattedNumber
|
4
5
|
from sciform.global_configuration import (
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
GlobalOptionsContext,
|
7
|
+
get_default_global_options,
|
8
|
+
get_global_options,
|
9
|
+
reset_global_options,
|
10
|
+
set_global_options,
|
9
11
|
)
|
10
12
|
from sciform.modes import AutoDigits, AutoExpVal
|
13
|
+
from sciform.options.input_options import InputOptions
|
14
|
+
from sciform.options.populated_options import PopulatedOptions
|
11
15
|
from sciform.scinum import SciNum
|
12
16
|
|
13
17
|
__all__ = [
|
14
18
|
"Formatter",
|
15
|
-
"
|
16
|
-
"
|
17
|
-
"
|
18
|
-
"
|
19
|
+
"FormattedNumber",
|
20
|
+
"GlobalOptionsContext",
|
21
|
+
"get_default_global_options",
|
22
|
+
"get_global_options",
|
23
|
+
"reset_global_options",
|
24
|
+
"set_global_options",
|
19
25
|
"AutoDigits",
|
20
26
|
"AutoExpVal",
|
21
27
|
"SciNum",
|
28
|
+
"InputOptions",
|
29
|
+
"PopulatedOptions",
|
22
30
|
]
|
sciform/formatter.py
CHANGED
@@ -2,42 +2,132 @@
|
|
2
2
|
|
3
3
|
from __future__ import annotations
|
4
4
|
|
5
|
-
from
|
6
|
-
from typing import TYPE_CHECKING
|
5
|
+
from typing import TYPE_CHECKING, Literal
|
7
6
|
|
8
|
-
from sciform.formatting import
|
9
|
-
from sciform.
|
10
|
-
from sciform.
|
7
|
+
from sciform.formatting import format_from_options
|
8
|
+
from sciform.options.conversion import populate_options
|
9
|
+
from sciform.options.input_options import InputOptions
|
11
10
|
|
12
11
|
if TYPE_CHECKING: # pragma: no cover
|
13
12
|
from sciform import modes
|
14
13
|
from sciform.format_utils import Number
|
14
|
+
from sciform.formatting import FormattedNumber
|
15
|
+
from sciform.options.populated_options import PopulatedOptions
|
15
16
|
|
16
17
|
|
17
18
|
class Formatter:
|
18
|
-
"""
|
19
|
-
Class to format
|
19
|
+
r"""
|
20
|
+
Class to format value and value/uncertainty pairs.
|
20
21
|
|
21
|
-
:class:`Formatter` is used to convert
|
22
|
-
into formatted strings according to a variety of formatting
|
23
|
-
See :ref:`formatting_options` for more details on the
|
24
|
-
options. Any options which are
|
25
|
-
will be populated at format time
|
26
|
-
|
27
|
-
details about how to view and
|
22
|
+
:class:`Formatter` is used to convert value and value/uncertainty
|
23
|
+
pairs into formatted strings according to a variety of formatting
|
24
|
+
options. See :ref:`formatting_options` for more details on the
|
25
|
+
available options. Any options which are not populated (not passed
|
26
|
+
in or passed in the ``None`` value) will be populated at format time
|
27
|
+
by the corresponding values in the globally configured default
|
28
|
+
options. See :ref:`global_config` for details about how to view and
|
29
|
+
modify the global options. The user supplied options cannot be
|
30
|
+
updated after the :class:`Formatter` is constructed.
|
31
|
+
|
32
|
+
After initialization, the :class:`Formatter` is used by passing in
|
33
|
+
a value into the :class:`Formatter`.
|
28
34
|
|
29
35
|
>>> from sciform import Formatter
|
30
|
-
>>>
|
31
|
-
>>> print(
|
36
|
+
>>> formatter = Formatter(exp_mode="engineering", round_mode="sig_fig", ndigits=4)
|
37
|
+
>>> print(formatter(12345.678))
|
32
38
|
12.35e+03
|
33
39
|
|
34
|
-
|
35
|
-
|
40
|
+
A value/uncertainty pair can also be passed into the
|
41
|
+
:class:`Formatter`.
|
42
|
+
|
43
|
+
>>> formatter = Formatter(
|
44
|
+
... exp_mode="engineering",
|
45
|
+
... round_mode="sig_fig",
|
46
|
+
... ndigits=2,
|
47
|
+
... superscript=True,
|
48
|
+
... )
|
49
|
+
>>> formatted = formatter(12345.678, 3.4)
|
50
|
+
>>> print(formatted)
|
51
|
+
(12.3457 ± 0.0034)×10³
|
52
|
+
|
53
|
+
The returned object behaves like a ``str``, but is, in fact, a
|
54
|
+
:class:`FormattedNumber` instance. The :class:`FormattedNumber` is
|
55
|
+
a subclass of ``str`` but provides methods for post-conversion into
|
56
|
+
LaTeX, HTML, and ASCII formats.
|
57
|
+
|
58
|
+
>>> print(formatted.as_latex())
|
59
|
+
$(12.3457\:\pm\:0.0034)\times10^{3}$
|
60
|
+
>>> print(formatted.as_html())
|
61
|
+
(12.3457 ± 0.0034)×10<sup>3</sup>
|
62
|
+
>>> print(formatted.as_ascii())
|
63
|
+
(12.3457 +/- 0.0034)e+03
|
64
|
+
|
65
|
+
The formatting options input by the user can be checked by
|
66
|
+
inspecting the :attr:`input_options` property
|
67
|
+
|
68
|
+
>>> print(formatter.input_options)
|
69
|
+
InputOptions(
|
70
|
+
'exp_mode': 'engineering',
|
71
|
+
'round_mode': 'sig_fig',
|
72
|
+
'ndigits': 2,
|
73
|
+
'superscript': True,
|
74
|
+
)
|
75
|
+
|
76
|
+
Only explicitly populated options appear in the string printout.
|
77
|
+
However, populated and unpopulated parameters can be inspected by
|
78
|
+
direct attribute access. Unpopulated parameters are ``None``-valued.
|
79
|
+
|
80
|
+
>>> print(formatter.input_options.round_mode)
|
81
|
+
sig_fig
|
82
|
+
>>> print(formatter.input_options.exp_format)
|
83
|
+
None
|
84
|
+
|
85
|
+
The :meth:`InputOptions.as_dict` method returns a dictionary of
|
86
|
+
input options that can be passed back into a :class:`Formatter`
|
87
|
+
constructor as ``**kwargs``, possibly after modification. Only
|
88
|
+
explicitly populated options are included in this dictionary.
|
89
|
+
|
90
|
+
>>> print(formatter.input_options.as_dict())
|
91
|
+
{'exp_mode': 'engineering', 'round_mode': 'sig_fig', 'ndigits': 2, 'superscript': True}
|
36
92
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
93
|
+
Likewise, the result of populating the options with the global
|
94
|
+
options can be previewed by inspecting the :attr:`populated_options`
|
95
|
+
property.
|
96
|
+
|
97
|
+
>>> print(formatter.populated_options)
|
98
|
+
PopulatedOptions(
|
99
|
+
'exp_mode': 'engineering',
|
100
|
+
'exp_val': AutoExpVal,
|
101
|
+
'round_mode': 'sig_fig',
|
102
|
+
'ndigits': 2,
|
103
|
+
'upper_separator': '',
|
104
|
+
'decimal_separator': '.',
|
105
|
+
'lower_separator': '',
|
106
|
+
'sign_mode': '-',
|
107
|
+
'left_pad_char': ' ',
|
108
|
+
'left_pad_dec_place': 0,
|
109
|
+
'exp_format': 'standard',
|
110
|
+
'extra_si_prefixes': {},
|
111
|
+
'extra_iec_prefixes': {},
|
112
|
+
'extra_parts_per_forms': {},
|
113
|
+
'capitalize': False,
|
114
|
+
'superscript': True,
|
115
|
+
'nan_inf_exp': False,
|
116
|
+
'paren_uncertainty': False,
|
117
|
+
'pdg_sig_figs': False,
|
118
|
+
'left_pad_matching': False,
|
119
|
+
'paren_uncertainty_separators': True,
|
120
|
+
'pm_whitespace': True,
|
121
|
+
)
|
122
|
+
>>> print(formatter.populated_options.exp_format)
|
123
|
+
standard
|
124
|
+
|
125
|
+
The :class:`PopulatedOptions` class also provides a
|
126
|
+
:class:`PopulatedOptions.as_dict` method which can be used to
|
127
|
+
construct ``**kwargs`` to pass into new :class:`Formatter`
|
128
|
+
instances.
|
129
|
+
|
130
|
+
""" # noqa: E501
|
41
131
|
|
42
132
|
def __init__( # noqa: PLR0913
|
43
133
|
self: Formatter,
|
@@ -50,7 +140,7 @@ class Formatter:
|
|
50
140
|
decimal_separator: modes.DecimalSeparators | None = None,
|
51
141
|
lower_separator: modes.LowerSeparators | None = None,
|
52
142
|
sign_mode: modes.SignMode | None = None,
|
53
|
-
left_pad_char: modes.LeftPadChar | None = None,
|
143
|
+
left_pad_char: modes.LeftPadChar | Literal[0] | None = None,
|
54
144
|
left_pad_dec_place: int | None = None,
|
55
145
|
exp_format: modes.ExpFormat | None = None,
|
56
146
|
extra_si_prefixes: dict[int, str] | None = None,
|
@@ -64,11 +154,11 @@ class Formatter:
|
|
64
154
|
left_pad_matching: bool | None = None,
|
65
155
|
paren_uncertainty_separators: bool | None = None,
|
66
156
|
pm_whitespace: bool | None = None,
|
67
|
-
add_c_prefix: bool =
|
68
|
-
add_small_si_prefixes: bool =
|
69
|
-
add_ppth_form: bool =
|
157
|
+
add_c_prefix: bool | None = None,
|
158
|
+
add_small_si_prefixes: bool | None = None,
|
159
|
+
add_ppth_form: bool | None = None,
|
70
160
|
) -> None:
|
71
|
-
|
161
|
+
"""
|
72
162
|
Create a new ``Formatter``.
|
73
163
|
|
74
164
|
The following checks are performed when creating a new
|
@@ -121,7 +211,7 @@ class Formatter:
|
|
121
211
|
:type sign_mode: ``Literal['-', '+', ' '] | None``
|
122
212
|
:param left_pad_char: Indicate whether to pad with zeros or
|
123
213
|
spaces.
|
124
|
-
:type left_pad_char: ``Literal[' ', '0'] | None``
|
214
|
+
:type left_pad_char: ``Literal[' ', '0', 0] | None``
|
125
215
|
:param left_pad_dec_place: Positive ``int`` indicating the
|
126
216
|
decimal place to which the string will be left padded before
|
127
217
|
the sign symbol. 0 corresponds to the ones place, 1
|
@@ -179,18 +269,19 @@ class Formatter:
|
|
179
269
|
whitespace surrounding the ``'±'`` symbols when formatting.
|
180
270
|
E.g. ``123.4±2.3`` compared to ``123.4 ± 2.3``.
|
181
271
|
:type pm_whitespace: ``bool | None``
|
182
|
-
:param add_c_prefix: (default ``False``) If
|
183
|
-
``{-2: 'c'}`` to ``extra_si_prefixes``.
|
184
|
-
:type add_c_prefix: ``bool``
|
185
|
-
:param add_small_si_prefixes: (default ``
|
272
|
+
:param add_c_prefix: (default ``None`` is like ``False``) If
|
273
|
+
``True``, adds ``{-2: 'c'}`` to ``extra_si_prefixes``.
|
274
|
+
:type add_c_prefix: ``bool | None``
|
275
|
+
:param add_small_si_prefixes: (default ``None`` is like
|
276
|
+
``False``) If ``True``, adds
|
186
277
|
``{-2: 'c', -1: 'd', +1: 'da', +2: 'h'}`` to
|
187
278
|
``extra_si_prefixes``.
|
188
|
-
:type add_small_si_prefixes: ``bool``
|
189
|
-
:param add_ppth_form: (default ``False``) if
|
190
|
-
``{-3: 'ppth'}`` to ``extra_parts_per_forms``.
|
191
|
-
:type add_ppth_form: ``bool``
|
279
|
+
:type add_small_si_prefixes: ``bool | None``
|
280
|
+
:param add_ppth_form: (default ``None`` is like ``False``) if
|
281
|
+
``True``, adds ``{-3: 'ppth'}`` to ``extra_parts_per_forms``.
|
282
|
+
:type add_ppth_form: ``bool | None``
|
192
283
|
"""
|
193
|
-
self.
|
284
|
+
self._input_options = InputOptions(
|
194
285
|
exp_mode=exp_mode,
|
195
286
|
exp_val=exp_val,
|
196
287
|
round_mode=round_mode,
|
@@ -218,6 +309,22 @@ class Formatter:
|
|
218
309
|
add_ppth_form=add_ppth_form,
|
219
310
|
)
|
220
311
|
|
312
|
+
@property
|
313
|
+
def input_options(self: Formatter) -> InputOptions:
|
314
|
+
"""Return user input options as :class:`InputOptions` instance."""
|
315
|
+
return self._input_options
|
316
|
+
|
317
|
+
@property
|
318
|
+
def populated_options(self: Formatter) -> PopulatedOptions:
|
319
|
+
"""
|
320
|
+
Return fully populated options as :class:`PopulatedOptions` instance.
|
321
|
+
|
322
|
+
:attr:`populated_options` is re-calculated from
|
323
|
+
:attr:`input_options` and the global options each time it is
|
324
|
+
accessed so that it always reflects the current global options.
|
325
|
+
"""
|
326
|
+
return populate_options(self.input_options)
|
327
|
+
|
221
328
|
def __call__(
|
222
329
|
self: Formatter,
|
223
330
|
value: Number,
|
@@ -232,56 +339,8 @@ class Formatter:
|
|
232
339
|
:param uncertainty: Optional uncertainty to be formatted.
|
233
340
|
:type uncertainty: ``Decimal | float | int | str | None``
|
234
341
|
"""
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
Decimal(str(value)),
|
241
|
-
Decimal(str(uncertainty)),
|
242
|
-
rendered_options,
|
243
|
-
)
|
244
|
-
return FormattedNumber(output)
|
245
|
-
|
246
|
-
|
247
|
-
class FormattedNumber(str):
|
248
|
-
"""
|
249
|
-
Representation (typically string) of a formatted number.
|
250
|
-
|
251
|
-
The ``FormattedNumber`` class is returned by ``sciform`` formatting
|
252
|
-
methods. In most cases it behaves like a regular python string, but
|
253
|
-
it provides the possibility for post-converting the string to
|
254
|
-
various other formats such as latex or html. This allows the
|
255
|
-
formatted number to be displayed in a range of contexts other than
|
256
|
-
e.g. text terminals.
|
257
|
-
|
258
|
-
"""
|
259
|
-
|
260
|
-
__slots__ = ()
|
261
|
-
|
262
|
-
def as_str(self: FormattedNumber) -> str:
|
263
|
-
"""Return the string representation of the formatted number."""
|
264
|
-
return self.__str__()
|
265
|
-
|
266
|
-
def as_ascii(self: FormattedNumber) -> str:
|
267
|
-
"""Return the ascii representation of the formatted number."""
|
268
|
-
return convert_sciform_format(self, "ascii")
|
269
|
-
|
270
|
-
def as_html(self: FormattedNumber) -> str:
|
271
|
-
"""Return the html representation of the formatted number."""
|
272
|
-
return convert_sciform_format(self, "html")
|
273
|
-
|
274
|
-
def as_latex(self: FormattedNumber, *, strip_math_mode: bool = False) -> str:
|
275
|
-
"""Return the latex representation of the formatted number."""
|
276
|
-
latex_repr = convert_sciform_format(self, "latex")
|
277
|
-
if strip_math_mode:
|
278
|
-
latex_repr = latex_repr.strip("$")
|
279
|
-
return latex_repr
|
280
|
-
|
281
|
-
def _repr_html_(self: FormattedNumber) -> str:
|
282
|
-
"""Hook for HTML display.""" # noqa: D401
|
283
|
-
return self.as_html()
|
284
|
-
|
285
|
-
def _repr_latex_(self: FormattedNumber) -> str:
|
286
|
-
"""Hook for LaTeX display.""" # noqa: D401
|
287
|
-
return self.as_latex()
|
342
|
+
return format_from_options(
|
343
|
+
value,
|
344
|
+
uncertainty,
|
345
|
+
input_options=self.input_options,
|
346
|
+
)
|
sciform/formatting.py
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
"""Main formatting functions."""
|
2
|
+
from __future__ import annotations
|
2
3
|
|
3
4
|
from dataclasses import replace
|
4
5
|
from decimal import Decimal
|
5
|
-
from typing import cast
|
6
|
+
from typing import TYPE_CHECKING, cast
|
6
7
|
from warnings import warn
|
7
8
|
|
9
|
+
from typing_extensions import Self
|
10
|
+
|
8
11
|
from sciform.format_utils import (
|
12
|
+
Number,
|
9
13
|
construct_val_unc_exp_str,
|
10
14
|
construct_val_unc_str,
|
11
15
|
format_num_by_top_bottom_dig,
|
@@ -25,10 +29,35 @@ from sciform.modes import (
|
|
25
29
|
RoundModeEnum,
|
26
30
|
SignModeEnum,
|
27
31
|
)
|
28
|
-
from sciform.
|
32
|
+
from sciform.options.conversion import finalize_populated_options, populate_options
|
33
|
+
from sciform.output_conversion import convert_sciform_format
|
34
|
+
|
35
|
+
if TYPE_CHECKING: # pragma: no cover
|
36
|
+
from sciform.options.finalized_options import FinalizedOptions
|
37
|
+
from sciform.options.input_options import InputOptions
|
38
|
+
from sciform.options.populated_options import PopulatedOptions
|
39
|
+
|
40
|
+
|
41
|
+
def format_from_options(
|
42
|
+
value: Number,
|
43
|
+
uncertainty: Number | None = None,
|
44
|
+
/,
|
45
|
+
input_options: InputOptions | None = None,
|
46
|
+
) -> FormattedNumber:
|
47
|
+
"""Finalize options and select value of value/uncertainty formatter."""
|
48
|
+
populated_options = populate_options(input_options)
|
49
|
+
finalized_options = finalize_populated_options(populated_options)
|
50
|
+
value = Decimal(str(value))
|
51
|
+
|
52
|
+
if uncertainty is not None:
|
53
|
+
uncertainty = Decimal(str(uncertainty))
|
54
|
+
formatted_str = format_val_unc(value, uncertainty, finalized_options)
|
55
|
+
else:
|
56
|
+
formatted_str = format_num(value, finalized_options)
|
57
|
+
return FormattedNumber(formatted_str, populated_options)
|
29
58
|
|
30
59
|
|
31
|
-
def format_non_finite(num: Decimal, options:
|
60
|
+
def format_non_finite(num: Decimal, options: FinalizedOptions) -> str:
|
32
61
|
"""Format non-finite numbers."""
|
33
62
|
if num.is_nan():
|
34
63
|
num_str = "nan"
|
@@ -73,7 +102,7 @@ def format_non_finite(num: Decimal, options: RenderedOptions) -> str:
|
|
73
102
|
return result
|
74
103
|
|
75
104
|
|
76
|
-
def format_num(num: Decimal, options:
|
105
|
+
def format_num(num: Decimal, options: FinalizedOptions) -> str:
|
77
106
|
"""Format a single number according to input options."""
|
78
107
|
if not num.is_finite():
|
79
108
|
return format_non_finite(num, options)
|
@@ -145,7 +174,7 @@ def format_num(num: Decimal, options: RenderedOptions) -> str:
|
|
145
174
|
return result
|
146
175
|
|
147
176
|
|
148
|
-
def format_val_unc(val: Decimal, unc: Decimal, options:
|
177
|
+
def format_val_unc(val: Decimal, unc: Decimal, options: FinalizedOptions) -> str:
|
149
178
|
"""Format value/uncertainty pair according to input options."""
|
150
179
|
exp_mode = options.exp_mode
|
151
180
|
|
@@ -289,3 +318,61 @@ def format_val_unc(val: Decimal, unc: Decimal, options: RenderedOptions) -> str:
|
|
289
318
|
val_unc_exp_str = f"({val_unc_exp_str})%"
|
290
319
|
|
291
320
|
return val_unc_exp_str
|
321
|
+
|
322
|
+
|
323
|
+
class FormattedNumber(str):
|
324
|
+
"""
|
325
|
+
Representation of a formatted value of value/uncertainty pair.
|
326
|
+
|
327
|
+
The :class:`FormattedNumber` class is returned by ``sciform``
|
328
|
+
formatting methods. In most cases it behaves like a regular python
|
329
|
+
string, but it provides functionality for post-converting the string
|
330
|
+
to various other formats such as latex or html. This allows the
|
331
|
+
formatted number to be displayed in a range of contexts other than
|
332
|
+
e.g. text terminals.
|
333
|
+
|
334
|
+
The :class:`FormattedNumber` class should never be instantiated
|
335
|
+
directly.
|
336
|
+
"""
|
337
|
+
|
338
|
+
__slots__ = {
|
339
|
+
"populated_options": "Record of the :class:`PopulatedOptions` used to "
|
340
|
+
"generate the :class:`FormattedNumber`.",
|
341
|
+
}
|
342
|
+
|
343
|
+
def __new__(
|
344
|
+
cls: type[Self],
|
345
|
+
formatted_str: str,
|
346
|
+
populated_options: PopulatedOptions,
|
347
|
+
) -> Self:
|
348
|
+
"""Get a new string."""
|
349
|
+
obj = super().__new__(cls, formatted_str)
|
350
|
+
obj.populated_options = populated_options
|
351
|
+
return obj
|
352
|
+
|
353
|
+
def as_str(self: FormattedNumber) -> str:
|
354
|
+
"""Return the string representation of the formatted number."""
|
355
|
+
return self.__str__()
|
356
|
+
|
357
|
+
def as_ascii(self: FormattedNumber) -> str:
|
358
|
+
"""Return the ascii representation of the formatted number."""
|
359
|
+
return convert_sciform_format(self, "ascii")
|
360
|
+
|
361
|
+
def as_html(self: FormattedNumber) -> str:
|
362
|
+
"""Return the html representation of the formatted number."""
|
363
|
+
return convert_sciform_format(self, "html")
|
364
|
+
|
365
|
+
def as_latex(self: FormattedNumber, *, strip_math_mode: bool = False) -> str:
|
366
|
+
"""Return the latex representation of the formatted number."""
|
367
|
+
latex_repr = convert_sciform_format(self, "latex")
|
368
|
+
if strip_math_mode:
|
369
|
+
latex_repr = latex_repr.strip("$")
|
370
|
+
return latex_repr
|
371
|
+
|
372
|
+
def _repr_html_(self: FormattedNumber) -> str:
|
373
|
+
"""Hook for HTML display.""" # noqa: D401
|
374
|
+
return self.as_html()
|
375
|
+
|
376
|
+
def _repr_latex_(self: FormattedNumber) -> str:
|
377
|
+
"""Hook for LaTeX display.""" # noqa: D401
|
378
|
+
return self.as_latex()
|
sciform/fsml.py
CHANGED
@@ -4,7 +4,7 @@ from __future__ import annotations
|
|
4
4
|
|
5
5
|
import re
|
6
6
|
|
7
|
-
from sciform.
|
7
|
+
from sciform.options.input_options import InputOptions
|
8
8
|
|
9
9
|
pattern = re.compile(
|
10
10
|
r"""^
|
@@ -51,8 +51,8 @@ def parse_exp_mode(
|
|
51
51
|
return exp_mode, capitalize
|
52
52
|
|
53
53
|
|
54
|
-
def format_options_from_fmt_spec(fmt_spec: str) ->
|
55
|
-
"""Resolve
|
54
|
+
def format_options_from_fmt_spec(fmt_spec: str) -> InputOptions:
|
55
|
+
"""Resolve InputOptions from format specification string."""
|
56
56
|
match = pattern.match(fmt_spec)
|
57
57
|
if match is None:
|
58
58
|
msg = f"Invalid format specifier: '{fmt_spec}'"
|
@@ -101,7 +101,7 @@ def format_options_from_fmt_spec(fmt_spec: str) -> UserOptions:
|
|
101
101
|
else:
|
102
102
|
paren_uncertainty = None
|
103
103
|
|
104
|
-
return
|
104
|
+
return InputOptions(
|
105
105
|
left_pad_char=left_pad_char,
|
106
106
|
sign_mode=sign_mode,
|
107
107
|
left_pad_dec_place=left_pad_dec_place,
|
sciform/global_configuration.py
CHANGED
@@ -4,21 +4,28 @@ from __future__ import annotations
|
|
4
4
|
|
5
5
|
from typing import TYPE_CHECKING
|
6
6
|
|
7
|
-
from sciform import global_options
|
8
|
-
from sciform.
|
7
|
+
from sciform.options import global_options
|
8
|
+
from sciform.options.conversion import populate_options
|
9
|
+
from sciform.options.input_options import InputOptions
|
9
10
|
|
10
11
|
if TYPE_CHECKING: # pragma: no cover
|
11
12
|
from types import TracebackType
|
12
13
|
|
13
|
-
from sciform
|
14
|
+
from sciform import modes
|
15
|
+
from sciform.options.populated_options import PopulatedOptions
|
14
16
|
|
15
17
|
|
16
|
-
def
|
17
|
-
"""
|
18
|
-
|
18
|
+
def get_default_global_options() -> PopulatedOptions:
|
19
|
+
"""Return the package default global options."""
|
20
|
+
return global_options.PKG_DEFAULT_OPTIONS
|
19
21
|
|
20
22
|
|
21
|
-
def
|
23
|
+
def get_global_options() -> PopulatedOptions:
|
24
|
+
"""Return the current global options."""
|
25
|
+
return global_options.GLOBAL_DEFAULT_OPTIONS
|
26
|
+
|
27
|
+
|
28
|
+
def set_global_options( # noqa: PLR0913
|
22
29
|
*,
|
23
30
|
exp_mode: modes.ExpMode | None = None,
|
24
31
|
exp_val: int | type(modes.AutoExpVal) | None = None,
|
@@ -47,11 +54,11 @@ def set_global_defaults( # noqa: PLR0913
|
|
47
54
|
add_ppth_form: bool = False,
|
48
55
|
) -> None:
|
49
56
|
"""
|
50
|
-
Configure global
|
57
|
+
Configure the global options.
|
51
58
|
|
52
59
|
Accepts the same keyword arguments as :class:`Formatter`.
|
53
60
|
"""
|
54
|
-
|
61
|
+
input_options = InputOptions(
|
55
62
|
exp_mode=exp_mode,
|
56
63
|
exp_val=exp_val,
|
57
64
|
round_mode=round_mode,
|
@@ -78,30 +85,30 @@ def set_global_defaults( # noqa: PLR0913
|
|
78
85
|
add_small_si_prefixes=add_small_si_prefixes,
|
79
86
|
add_ppth_form=add_ppth_form,
|
80
87
|
)
|
81
|
-
|
88
|
+
set_global_options_populated(populate_options(input_options))
|
82
89
|
|
83
90
|
|
84
|
-
def
|
85
|
-
"""Directly set global
|
86
|
-
global_options.GLOBAL_DEFAULT_OPTIONS =
|
91
|
+
def set_global_options_populated(populated_options: PopulatedOptions) -> None:
|
92
|
+
"""Directly set global options to input :class:`PopulatedOptions`."""
|
93
|
+
global_options.GLOBAL_DEFAULT_OPTIONS = populated_options
|
87
94
|
|
88
95
|
|
89
|
-
def
|
90
|
-
"""Reset global
|
96
|
+
def reset_global_options() -> None:
|
97
|
+
"""Reset global options to :mod:`sciform` package defaults."""
|
91
98
|
global_options.GLOBAL_DEFAULT_OPTIONS = global_options.PKG_DEFAULT_OPTIONS
|
92
99
|
|
93
100
|
|
94
|
-
class
|
101
|
+
class GlobalOptionsContext:
|
95
102
|
"""
|
96
|
-
Temporarily update global
|
103
|
+
Temporarily update global options.
|
97
104
|
|
98
|
-
New
|
99
|
-
global settings are re-applied when the context is exited.
|
100
|
-
the same keyword arguments as :class:`Formatter`.
|
105
|
+
New global options are applied when the context is entered and the
|
106
|
+
original global settings are re-applied when the context is exited.
|
107
|
+
Accepts the same keyword arguments as :class:`Formatter`.
|
101
108
|
"""
|
102
109
|
|
103
110
|
def __init__( # noqa: PLR0913
|
104
|
-
self:
|
111
|
+
self: GlobalOptionsContext,
|
105
112
|
*,
|
106
113
|
exp_mode: modes.ExpMode | None = None,
|
107
114
|
exp_val: int | type(modes.AutoExpVal) | None = None,
|
@@ -129,7 +136,7 @@ class GlobalDefaultsContext:
|
|
129
136
|
add_small_si_prefixes: bool = False,
|
130
137
|
add_ppth_form: bool = False,
|
131
138
|
) -> None:
|
132
|
-
|
139
|
+
input_options = InputOptions(
|
133
140
|
exp_mode=exp_mode,
|
134
141
|
exp_val=exp_val,
|
135
142
|
round_mode=round_mode,
|
@@ -156,19 +163,19 @@ class GlobalDefaultsContext:
|
|
156
163
|
add_small_si_prefixes=add_small_si_prefixes,
|
157
164
|
add_ppth_form=add_ppth_form,
|
158
165
|
)
|
159
|
-
self.
|
166
|
+
self.populated_options = populate_options(input_options)
|
160
167
|
self.initial_global_defaults = None
|
161
168
|
|
162
|
-
def __enter__(self:
|
169
|
+
def __enter__(self: GlobalOptionsContext) -> None:
|
163
170
|
"""Enter the context."""
|
164
|
-
self.initial_global_defaults =
|
165
|
-
|
171
|
+
self.initial_global_defaults = get_global_options()
|
172
|
+
set_global_options_populated(self.populated_options)
|
166
173
|
|
167
174
|
def __exit__(
|
168
|
-
self:
|
175
|
+
self: GlobalOptionsContext,
|
169
176
|
exc_type: type[BaseException] | None,
|
170
177
|
exc_val: BaseException | None,
|
171
178
|
exc_tb: TracebackType | None,
|
172
179
|
) -> None:
|
173
180
|
"""Exit the context."""
|
174
|
-
|
181
|
+
set_global_options_populated(self.initial_global_defaults)
|
@@ -0,0 +1 @@
|
|
1
|
+
"""Code pertaining to sciform options handling."""
|