libres 0.7.2__tar.gz → 0.8.0__tar.gz

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.
Files changed (66) hide show
  1. {libres-0.7.2 → libres-0.8.0}/HISTORY.rst +18 -0
  2. {libres-0.7.2/src/libres.egg-info → libres-0.8.0}/PKG-INFO +33 -9
  3. {libres-0.7.2 → libres-0.8.0}/README.rst +4 -4
  4. libres-0.8.0/pyproject.toml +285 -0
  5. {libres-0.7.2 → libres-0.8.0}/setup.cfg +14 -6
  6. {libres-0.7.2 → libres-0.8.0}/src/libres/__init__.py +3 -1
  7. {libres-0.7.2 → libres-0.8.0}/src/libres/context/core.py +32 -26
  8. libres-0.8.0/src/libres/context/exposure.py +13 -0
  9. {libres-0.7.2 → libres-0.8.0}/src/libres/context/registry.py +14 -10
  10. {libres-0.7.2 → libres-0.8.0}/src/libres/context/session.py +8 -6
  11. {libres-0.7.2 → libres-0.8.0}/src/libres/context/settings.py +9 -6
  12. libres-0.8.0/src/libres/db/__init__.py +7 -0
  13. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/__init__.py +2 -0
  14. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/allocation.py +60 -56
  15. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/base.py +2 -0
  16. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/other.py +12 -7
  17. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/reservation.py +28 -23
  18. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/reserved_slot.py +12 -10
  19. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/timestamp.py +9 -7
  20. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/types/__init__.py +2 -0
  21. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/types/json_type.py +12 -9
  22. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/types/utcdatetime.py +10 -8
  23. {libres-0.7.2 → libres-0.8.0}/src/libres/db/models/types/uuid_type.py +10 -8
  24. {libres-0.7.2 → libres-0.8.0}/src/libres/db/queries.py +32 -27
  25. {libres-0.7.2 → libres-0.8.0}/src/libres/db/scheduler.py +133 -127
  26. {libres-0.7.2 → libres-0.8.0}/src/libres/modules/errors.py +9 -7
  27. {libres-0.7.2 → libres-0.8.0}/src/libres/modules/events.py +57 -56
  28. {libres-0.7.2 → libres-0.8.0}/src/libres/modules/rasterizer.py +11 -7
  29. {libres-0.7.2 → libres-0.8.0}/src/libres/modules/utils.py +16 -14
  30. libres-0.8.0/src/libres/py.typed +0 -0
  31. {libres-0.7.2 → libres-0.8.0/src/libres.egg-info}/PKG-INFO +33 -9
  32. {libres-0.7.2 → libres-0.8.0}/src/libres.egg-info/requires.txt +6 -1
  33. {libres-0.7.2 → libres-0.8.0}/tests/test_allocation.py +1 -1
  34. libres-0.7.2/pyproject.toml +0 -81
  35. libres-0.7.2/src/libres/context/exposure.py +0 -9
  36. libres-0.7.2/src/libres/db/__init__.py +0 -5
  37. libres-0.7.2/src/libres/modules/__init__.py +0 -1
  38. {libres-0.7.2 → libres-0.8.0}/LICENSE +0 -0
  39. {libres-0.7.2 → libres-0.8.0}/MANIFEST.in +0 -0
  40. {libres-0.7.2 → libres-0.8.0}/docs/Makefile +0 -0
  41. {libres-0.7.2 → libres-0.8.0}/docs/_static/custom.css +0 -0
  42. {libres-0.7.2 → libres-0.8.0}/docs/_static/favicon.ico +0 -0
  43. {libres-0.7.2 → libres-0.8.0}/docs/_static/logo.svg +0 -0
  44. {libres-0.7.2 → libres-0.8.0}/docs/api.rst +0 -0
  45. {libres-0.7.2 → libres-0.8.0}/docs/concepts.rst +0 -0
  46. {libres-0.7.2 → libres-0.8.0}/docs/conf.py +0 -0
  47. {libres-0.7.2 → libres-0.8.0}/docs/customizations.rst +0 -0
  48. {libres-0.7.2 → libres-0.8.0}/docs/faq.rst +0 -0
  49. {libres-0.7.2 → libres-0.8.0}/docs/index.rst +0 -0
  50. {libres-0.7.2 → libres-0.8.0}/docs/requirements.txt +0 -0
  51. {libres-0.7.2 → libres-0.8.0}/docs/under_the_hood.rst +0 -0
  52. {libres-0.7.2 → libres-0.8.0}/src/libres/.gitignore +0 -0
  53. {libres-0.7.2 → libres-0.8.0}/src/libres/context/__init__.py +0 -0
  54. /libres-0.7.2/src/libres/py.typed → /libres-0.8.0/src/libres/modules/__init__.py +0 -0
  55. {libres-0.7.2 → libres-0.8.0}/src/libres.egg-info/SOURCES.txt +0 -0
  56. {libres-0.7.2 → libres-0.8.0}/src/libres.egg-info/dependency_links.txt +0 -0
  57. {libres-0.7.2 → libres-0.8.0}/src/libres.egg-info/not-zip-safe +0 -0
  58. {libres-0.7.2 → libres-0.8.0}/src/libres.egg-info/top_level.txt +0 -0
  59. {libres-0.7.2 → libres-0.8.0}/tests/test_registry.py +0 -0
  60. {libres-0.7.2 → libres-0.8.0}/tests/test_reservation.py +0 -0
  61. {libres-0.7.2 → libres-0.8.0}/tests/test_reserved_slot.py +0 -0
  62. {libres-0.7.2 → libres-0.8.0}/tests/test_scheduler.py +0 -0
  63. {libres-0.7.2 → libres-0.8.0}/tests/test_session.py +0 -0
  64. {libres-0.7.2 → libres-0.8.0}/tests/test_test.py +0 -0
  65. {libres-0.7.2 → libres-0.8.0}/tests/test_types.py +0 -0
  66. {libres-0.7.2 → libres-0.8.0}/tests/test_utils.py +0 -0
@@ -1,6 +1,24 @@
1
1
  Changelog
2
2
  ---------
3
3
 
4
+ 0.8.0 (15.01.2025)
5
+ ~~~~~~~~~~~~~~~~~~~
6
+
7
+ - Adds support for Python 3.13
8
+ [Daverball]
9
+
10
+ - Drops support for Python 3.8
11
+ [Daverball]
12
+
13
+ - Modernizes type hints
14
+ [Daverball]
15
+
16
+ 0.7.3 (2024-08-21)
17
+ ~~~~~~~~~~~~~~~~~~~
18
+
19
+ - Adds support for Python 3.12.
20
+ [Daverball]
21
+
4
22
  0.7.2 (2024-02-07)
5
23
  ~~~~~~~~~~~~~~~~~~~
6
24
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: libres
3
- Version: 0.7.2
3
+ Version: 0.8.0
4
4
  Summary: A library to reserve things
5
5
  Home-page: http://github.com/seantis/libres/
6
6
  Author: Denis Krienbühl
@@ -14,12 +14,13 @@ Classifier: License :: OSI Approved :: BSD License
14
14
  Classifier: Operating System :: OS Independent
15
15
  Classifier: Programming Language :: Python
16
16
  Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.8
18
17
  Classifier: Programming Language :: Python :: 3.9
19
18
  Classifier: Programming Language :: Python :: 3.10
20
19
  Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
21
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
- Requires-Python: >=3.8
23
+ Requires-Python: >=3.9
23
24
  Description-Content-Type: text/x-rst
24
25
  License-File: LICENSE
25
26
  Requires-Dist: python-dateutil
@@ -29,10 +30,15 @@ Requires-Dist: sedate>=1.0.0
29
30
  Requires-Dist: SQLAlchemy<2,>=0.9
30
31
  Provides-Extra: dev
31
32
  Requires-Dist: bandit[toml]; extra == "dev"
33
+ Requires-Dist: bump-my-version; extra == "dev"
32
34
  Requires-Dist: flake8; extra == "dev"
33
- Requires-Dist: flake8-bugbear; extra == "dev"
35
+ Requires-Dist: flake8-type-checking; extra == "dev"
34
36
  Requires-Dist: pre-commit; extra == "dev"
37
+ Requires-Dist: pre-commit-uv; extra == "dev"
38
+ Requires-Dist: ruff; extra == "dev"
39
+ Requires-Dist: uv; extra == "dev"
35
40
  Requires-Dist: tox; extra == "dev"
41
+ Requires-Dist: tox-uv; extra == "dev"
36
42
  Provides-Extra: test
37
43
  Requires-Dist: jsonpickle; extra == "test"
38
44
  Requires-Dist: pytest; extra == "test"
@@ -90,19 +96,19 @@ Run the Tests
90
96
 
91
97
  Install tox and run it::
92
98
 
93
- pip install tox
99
+ pip install tox tox-uv
94
100
  tox
95
101
 
96
102
  Limit the tests to a specific python version::
97
103
 
98
- tox -e py27
104
+ tox -e py311
99
105
 
100
106
  Conventions
101
107
  -----------
102
108
 
103
109
  Libres follows PEP8 as close as possible. To test for it run::
104
110
 
105
- tox -e pep8
111
+ tox -e ruff,flake8
106
112
 
107
113
  Libres uses `Semantic Versioning <http://semver.org/>`_
108
114
 
@@ -127,7 +133,7 @@ Making a new Release
127
133
 
128
134
  Make sure all changes are in the HISTORY.rst, then bump the version::
129
135
 
130
- bump2version major|minor|patch
136
+ bump-my-version bump major|minor|patch
131
137
  git push && git push --tags
132
138
 
133
139
  After this, create a new release on Github.
@@ -135,6 +141,24 @@ After this, create a new release on Github.
135
141
  Changelog
136
142
  ---------
137
143
 
144
+ 0.8.0 (15.01.2025)
145
+ ~~~~~~~~~~~~~~~~~~~
146
+
147
+ - Adds support for Python 3.13
148
+ [Daverball]
149
+
150
+ - Drops support for Python 3.8
151
+ [Daverball]
152
+
153
+ - Modernizes type hints
154
+ [Daverball]
155
+
156
+ 0.7.3 (2024-08-21)
157
+ ~~~~~~~~~~~~~~~~~~~
158
+
159
+ - Adds support for Python 3.12.
160
+ [Daverball]
161
+
138
162
  0.7.2 (2024-02-07)
139
163
  ~~~~~~~~~~~~~~~~~~~
140
164
 
@@ -42,19 +42,19 @@ Run the Tests
42
42
 
43
43
  Install tox and run it::
44
44
 
45
- pip install tox
45
+ pip install tox tox-uv
46
46
  tox
47
47
 
48
48
  Limit the tests to a specific python version::
49
49
 
50
- tox -e py27
50
+ tox -e py311
51
51
 
52
52
  Conventions
53
53
  -----------
54
54
 
55
55
  Libres follows PEP8 as close as possible. To test for it run::
56
56
 
57
- tox -e pep8
57
+ tox -e ruff,flake8
58
58
 
59
59
  Libres uses `Semantic Versioning <http://semver.org/>`_
60
60
 
@@ -79,7 +79,7 @@ Making a new Release
79
79
 
80
80
  Make sure all changes are in the HISTORY.rst, then bump the version::
81
81
 
82
- bump2version major|minor|patch
82
+ bump-my-version bump major|minor|patch
83
83
  git push && git push --tags
84
84
 
85
85
  After this, create a new release on Github.
@@ -0,0 +1,285 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [tool.pytest.ini_options]
6
+ log_level = "INFO"
7
+ testpaths = ["tests"]
8
+
9
+ [tool.coverage.run]
10
+ branch = true
11
+ source = ["src"]
12
+
13
+ [tool.bumpversion]
14
+ current_version = "0.8.0"
15
+ commit = true
16
+ message = "Release {new_version}"
17
+ tag = true
18
+ tag_message = "Release {new_version}"
19
+
20
+ [[tool.bumpversion.files]]
21
+ filename = "src/libres/__init__.py"
22
+ search= "__version__ = '{current_version}'"
23
+ replace= "__version__ = '{new_version}'"
24
+
25
+ [[tool.bumpversion.files]]
26
+ filename = "HISTORY.rst"
27
+ search = """
28
+ ---------
29
+ """
30
+ replace = """
31
+ ---------
32
+
33
+ {new_version} ({now:%d.%m.%Y})
34
+ ~~~~~~~~~~~~~~~~~~~
35
+ """
36
+
37
+ [tool.mypy]
38
+ python_version = "3.9"
39
+ follow_imports = "silent"
40
+ namespace_packages = true
41
+ explicit_package_bases = true
42
+ warn_unused_ignores = true
43
+ warn_redundant_casts = true
44
+ warn_unreachable = true
45
+ disallow_any_generics = true
46
+ disallow_untyped_defs = true
47
+ plugins = "sqlmypy"
48
+ mypy_path = "$MYPY_CONFIG_FILE_DIR/src"
49
+
50
+ [tool.bandit]
51
+ exclude_dirs = ["tests"]
52
+ skips = ["B101"]
53
+
54
+ [tool.ruff]
55
+ exclude = [
56
+ ".bzr",
57
+ ".direnv",
58
+ ".eggs",
59
+ ".git",
60
+ ".git-rewrite",
61
+ ".hg",
62
+ ".ipynb_checkpoints",
63
+ ".mypy_cache",
64
+ ".nox",
65
+ ".pants.d",
66
+ ".pyenv",
67
+ ".pytest_cache",
68
+ ".pytype",
69
+ ".ruff_cache",
70
+ ".svn",
71
+ ".tox",
72
+ ".venv",
73
+ ".vscode",
74
+ "__pypackages__",
75
+ "_build",
76
+ "buck-out",
77
+ "build",
78
+ "dist",
79
+ "node_modules",
80
+ "site-packages",
81
+ "venv",
82
+ ]
83
+ src = ["src", "tests"]
84
+ include = [
85
+ "pyproject.toml",
86
+ "src/**/*.py",
87
+ "tests/**/*.py",
88
+ "stubs/**/*.pyi"
89
+ ]
90
+ line-length = 79
91
+ indent-width = 4
92
+ target-version = "py39"
93
+
94
+ [tool.ruff.lint]
95
+ select = [
96
+ "B0",
97
+ "B904",
98
+ "B909",
99
+ "C4",
100
+ "COM818",
101
+ "D2",
102
+ "D301",
103
+ "D4",
104
+ "E",
105
+ "F",
106
+ "FLY002",
107
+ "I002",
108
+ "ISC",
109
+ "N",
110
+ "PERF",
111
+ "PGH004",
112
+ "PIE",
113
+ "PYI",
114
+ "Q",
115
+ "RUF",
116
+ "SIM",
117
+ "SLOT",
118
+ "UP",
119
+ "W"
120
+ ]
121
+ ignore = [
122
+ "B007",
123
+ "C420",
124
+ "D200",
125
+ "D201",
126
+ "D202",
127
+ "D204",
128
+ "D205",
129
+ "D209",
130
+ "D210",
131
+ "D211",
132
+ "D400",
133
+ "D401",
134
+ "D412",
135
+ "E226",
136
+ "E402",
137
+ "E711",
138
+ "E712",
139
+ "E741",
140
+ "N818",
141
+ "PYI019",
142
+ "PYI041",
143
+ "RUF012",
144
+ "RUF013",
145
+ "RUF021",
146
+ "RUF022",
147
+ "RUF023",
148
+ "RUF031",
149
+ "RUF052",
150
+ "RUF056",
151
+ "SIM103",
152
+ "SIM105",
153
+ "SIM108",
154
+ "SIM110",
155
+ "SIM118",
156
+ "SIM210",
157
+ "SIM910",
158
+ "UP009",
159
+ "UP012",
160
+ "UP032",
161
+ "UP038",
162
+ ]
163
+ unfixable = []
164
+ external = ["TC"]
165
+ allowed-confusables = ["×"]
166
+ preview = true
167
+
168
+ [tool.ruff.lint.extend-per-file-ignores]
169
+ "tests/**/*.py" = [
170
+ "C4",
171
+ "D",
172
+ "FLY002",
173
+ "I002",
174
+ "ISC",
175
+ "N",
176
+ "Q",
177
+ "PERF",
178
+ "PGH",
179
+ "PIE",
180
+ "PYI",
181
+ "RUF",
182
+ "SIM",
183
+ "UP",
184
+ ]
185
+
186
+ [tool.ruff.lint.isort]
187
+ required-imports = ["from __future__ import annotations"]
188
+
189
+ [tool.ruff.lint.pep8-naming]
190
+ extend-ignore-names = [
191
+ "afterFlowable",
192
+ "HSTORE",
193
+ "sortKey",
194
+ "URL",
195
+ "UUID"
196
+ ]
197
+ classmethod-decorators = [
198
+ # NOTE: We can potentially get rid some of these with SQLAlchemy 2.0
199
+ # since they should cleanly combine with classmethod
200
+ "declared_attr",
201
+ "expression",
202
+ "comparator",
203
+ ]
204
+
205
+ [tool.ruff.lint.pydocstyle]
206
+ convention = "pep257"
207
+ ignore-decorators = ["typing.overload"]
208
+
209
+ [tool.ruff.lint.flake8-quotes]
210
+ avoid-escape = true
211
+ docstring-quotes = "double"
212
+ inline-quotes = "single"
213
+ multiline-quotes = "double"
214
+
215
+ [tool.ruff.format]
216
+ quote-style = "single"
217
+ indent-style = "space"
218
+ skip-magic-trailing-comma = false
219
+ line-ending = "lf"
220
+ docstring-code-format = true
221
+ docstring-code-line-length = "dynamic"
222
+
223
+ [tool.tox]
224
+ legacy_tox_ini = """
225
+ [tox]
226
+ envlist = py39,py310,py311,flake8,bandit,mypy,report
227
+
228
+ [gh-actions]
229
+ python =
230
+ 3.9: py39
231
+ 3.10: py310
232
+ 3.11: py311,flake8,bandit,mypy
233
+ 3.12: py312
234
+ 3.13: py313
235
+
236
+ [testenv]
237
+ usedevelop = true
238
+ setenv =
239
+ py{39,310,311,312,313}: COVERAGE_FILE = .coverage.{envname}
240
+ deps =
241
+ -e{toxinidir}[test]
242
+ commands = pytest --cov --cov-report= {posargs}
243
+
244
+ [testenv:ruff]
245
+ basepython = python3.11
246
+ skip_install = true
247
+ deps =
248
+ ruff
249
+ commands = ruff check
250
+
251
+ [testenv:flake8]
252
+ basepython = python3.11
253
+ skip_install = true
254
+ deps =
255
+ flake8
256
+ flake8-type-checking
257
+ commands = flake8 src/ tests/
258
+
259
+ [testenv:bandit]
260
+ basepython = python3.11
261
+ skip_install = true
262
+ deps =
263
+ bandit[toml]
264
+ commands = bandit -q -c pyproject.toml -r src
265
+
266
+ [testenv:mypy]
267
+ basepython = python3.11
268
+ deps =
269
+ -e{toxinidir}[mypy]
270
+ commands =
271
+ mypy -p libres --python-version 3.9
272
+ mypy -p libres --python-version 3.10
273
+ mypy -p libres --python-version 3.11
274
+ mypy -p libres --python-version 3.12
275
+ mypy -p libres --python-version 3.13
276
+
277
+ [testenv:report]
278
+ deps =
279
+ coverage
280
+ skip_install = true
281
+ commands =
282
+ coverage combine
283
+ coverage report -m
284
+
285
+ """
@@ -18,14 +18,15 @@ classifiers =
18
18
  Operating System :: OS Independent
19
19
  Programming Language :: Python
20
20
  Programming Language :: Python :: 3
21
- Programming Language :: Python :: 3.8
22
21
  Programming Language :: Python :: 3.9
23
22
  Programming Language :: Python :: 3.10
24
23
  Programming Language :: Python :: 3.11
24
+ Programming Language :: Python :: 3.12
25
+ Programming Language :: Python :: 3.13
25
26
  Topic :: Software Development :: Libraries :: Python Modules
26
27
 
27
28
  [options]
28
- python_requires = >= 3.8
29
+ python_requires = >= 3.9
29
30
  include_package_data = True
30
31
  package_dir =
31
32
  = src
@@ -46,10 +47,15 @@ libres =
46
47
  [options.extras_require]
47
48
  dev =
48
49
  bandit[toml]
50
+ bump-my-version
49
51
  flake8
50
- flake8-bugbear
52
+ flake8-type-checking
51
53
  pre-commit
54
+ pre-commit-uv
55
+ ruff
56
+ uv
52
57
  tox
58
+ tox-uv
53
59
  test =
54
60
  jsonpickle
55
61
  pytest
@@ -64,9 +70,11 @@ mypy =
64
70
  typing-extensions
65
71
 
66
72
  [flake8]
67
- ignore = E704,E712,W504
68
- extend-select = B901,B903,B904,B908
69
- exclude = .venv,.git,.tox,dist,docs,*lib/python*,*egg,build
73
+ select = TC0,TC1
74
+ per_file_ignores =
75
+ *.pyi: TC
76
+ tests/**.py: TC
77
+ exclude = .venv,venv,.git,.tox,dist,docs,*lib/python*,*egg,build
70
78
 
71
79
  [egg_info]
72
80
  tag_build =
@@ -1,9 +1,11 @@
1
+ from __future__ import annotations
2
+
1
3
  from libres.context.registry import create_default_registry
2
4
  from libres.db import new_scheduler
3
5
 
4
6
  registry = create_default_registry()
5
7
 
6
- __version__ = '0.7.2'
8
+ __version__ = '0.8.0'
7
9
  __all__ = (
8
10
  'new_scheduler',
9
11
  'registry'
@@ -1,17 +1,23 @@
1
+ from __future__ import annotations
2
+
1
3
  import enum
2
4
  import libres
3
5
  import threading
4
-
5
6
  from contextlib import contextmanager
6
7
  from functools import cached_property
7
8
 
8
9
  from libres.modules import errors
9
10
 
10
11
 
11
- import typing as _t
12
- if _t.TYPE_CHECKING:
12
+ from typing import Any
13
+ from typing import Literal
14
+ from typing import TYPE_CHECKING
15
+ if TYPE_CHECKING:
16
+ from collections.abc import Callable
17
+ from collections.abc import Iterator
13
18
  from sqlalchemy.orm import Session
14
19
  from sqlalchemy.orm.session import SessionTransaction
20
+ from typing_extensions import TypeAlias
15
21
  from uuid import UUID
16
22
 
17
23
  from libres.context.registry import Registry
@@ -24,8 +30,8 @@ class _Marker(enum.Enum):
24
30
  required = enum.auto()
25
31
 
26
32
 
27
- missing_t = _t.Literal[_Marker.missing]
28
- required_t = _t.Literal[_Marker.required]
33
+ missing_t: TypeAlias = Literal[_Marker.missing] # noqa: PYI042
34
+ required_t: TypeAlias = Literal[_Marker.required] # noqa: PYI042
29
35
  missing: missing_t = _Marker.missing
30
36
  required: required_t = _Marker.required
31
37
 
@@ -51,18 +57,18 @@ class ContextServicesMixin:
51
57
 
52
58
  """
53
59
 
54
- context: 'Context'
60
+ context: Context
55
61
 
56
62
  @cached_property
57
- def is_allocation_exposed(self) -> _t.Callable[['Allocation'], bool]:
63
+ def is_allocation_exposed(self) -> Callable[[Allocation], bool]:
58
64
  return self.context.get_service('exposure').is_allocation_exposed
59
65
 
60
66
  @cached_property
61
- def generate_uuid(self) -> _t.Callable[[str], 'UUID']:
67
+ def generate_uuid(self) -> Callable[[str], UUID]:
62
68
  return self.context.get_service('uuid_generator')
63
69
 
64
70
  @cached_property
65
- def validate_email(self) -> _t.Callable[[str], bool]:
71
+ def validate_email(self) -> Callable[[str], bool]:
66
72
  return self.context.get_service('email_validator')
67
73
 
68
74
  def clear_cache(self) -> None:
@@ -84,11 +90,11 @@ class ContextServicesMixin:
84
90
  pass
85
91
 
86
92
  @property
87
- def session_provider(self) -> 'SessionProvider':
93
+ def session_provider(self) -> SessionProvider:
88
94
  return self.context.get_service('session_provider')
89
95
 
90
96
  @property
91
- def session(self) -> 'Session':
97
+ def session(self) -> Session:
92
98
  """ Returns the current session. """
93
99
  return self.session_provider.session()
94
100
 
@@ -97,7 +103,7 @@ class ContextServicesMixin:
97
103
  self.session.close()
98
104
 
99
105
  @property
100
- def begin_nested(self) -> _t.Callable[[], 'SessionTransaction']:
106
+ def begin_nested(self) -> Callable[[], SessionTransaction]:
101
107
  return self.session.begin_nested
102
108
 
103
109
  def commit(self) -> None:
@@ -143,13 +149,13 @@ class Context:
143
149
  def __init__(
144
150
  self,
145
151
  name: str,
146
- registry: _t.Optional['Registry'] = None,
147
- parent: _t.Optional['Context'] = None,
152
+ registry: Registry | None = None,
153
+ parent: Context | None = None,
148
154
  locked: bool = False
149
155
  ):
150
156
  self.name = name
151
157
  self.registry = registry or libres.registry
152
- self.values: _t.Dict[str, _t.Any] = {}
158
+ self.values: dict[str, Any] = {}
153
159
  self.parent = parent
154
160
  self.locked = False
155
161
  self.thread_lock = threading.RLock()
@@ -158,7 +164,7 @@ class Context:
158
164
  return f"<Libres Context(name='{self.name}')>"
159
165
 
160
166
  @contextmanager
161
- def as_current_context(self) -> _t.Iterator[None]:
167
+ def as_current_context(self) -> Iterator[None]:
162
168
  with self.registry.context(self.name):
163
169
  yield
164
170
 
@@ -173,7 +179,7 @@ class Context:
173
179
  with self.thread_lock:
174
180
  self.locked = False
175
181
 
176
- def get(self, key: str) -> _t.Union[_t.Any, missing_t]:
182
+ def get(self, key: str) -> Any | missing_t:
177
183
  if key in self.values:
178
184
  return self.values[key]
179
185
  elif self.parent:
@@ -181,7 +187,7 @@ class Context:
181
187
  else:
182
188
  return missing
183
189
 
184
- def set(self, key: str, value: _t.Any) -> None:
190
+ def set(self, key: str, value: Any) -> None:
185
191
  if self.locked:
186
192
  raise errors.ContextIsLocked
187
193
 
@@ -195,21 +201,21 @@ class Context:
195
201
 
196
202
  self.values[key] = value
197
203
 
198
- def get_setting(self, name: str) -> _t.Any:
204
+ def get_setting(self, name: str) -> Any:
199
205
  return self.get(f'settings.{name}')
200
206
 
201
- def set_setting(self, name: str, value: _t.Any) -> None:
207
+ def set_setting(self, name: str, value: Any) -> None:
202
208
  with self.thread_lock:
203
209
  self.set(f'settings.{name}', value)
204
210
 
205
- def get_service(self, name: str) -> _t.Any:
206
- service_id = '/'.join(('service', name))
211
+ def get_service(self, name: str) -> Any:
212
+ service_id = f'service/{name}'
207
213
  service = self.get(service_id)
208
214
 
209
215
  if service is missing:
210
216
  raise errors.UnknownService(service_id)
211
217
 
212
- cache_id = '/'.join(('service', name, 'cache'))
218
+ cache_id = f'service/{name}/cache'
213
219
  cache = self.get(cache_id)
214
220
 
215
221
  # no cache
@@ -226,13 +232,13 @@ class Context:
226
232
  def set_service(
227
233
  self,
228
234
  name: str,
229
- factory: _t.Callable[..., _t.Any],
235
+ factory: Callable[..., Any],
230
236
  cache: bool = False
231
237
  ) -> None:
232
238
  with self.thread_lock:
233
- service_id = '/'.join(('service', name))
239
+ service_id = f'service/{name}'
234
240
  self.set(service_id, factory)
235
241
 
236
242
  if cache:
237
- cache_id = '/'.join(('service', name, 'cache'))
243
+ cache_id = f'service/{name}/cache'
238
244
  self.set(cache_id, required)
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+
4
+ from typing import Literal
5
+ from typing import TYPE_CHECKING
6
+ if TYPE_CHECKING:
7
+ from libres.db.models import Allocation
8
+
9
+
10
+ class Exposure:
11
+ @staticmethod
12
+ def is_allocation_exposed(allocation: Allocation) -> Literal[True]:
13
+ return True