diracx-testing 0.0.1a23__py3-none-any.whl → 0.0.1a25__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,67 @@
1
+ from __future__ import annotations
2
+
3
+ import tomllib
4
+ from collections import defaultdict
5
+ from importlib.metadata import PackageNotFoundError, distribution, entry_points
6
+
7
+ import pytest
8
+
9
+
10
+ def get_installed_entry_points():
11
+ """Retrieve the installed entry points from the environment."""
12
+ entry_pts = entry_points()
13
+ diracx_eps = defaultdict(dict)
14
+ for group in entry_pts.groups:
15
+ if "diracx" in group:
16
+ for ep in entry_pts.select(group=group):
17
+ diracx_eps[group][ep.name] = ep.value
18
+ return dict(diracx_eps)
19
+
20
+
21
+ def get_entry_points_from_toml(toml_file):
22
+ """Parse entry points from pyproject.toml."""
23
+ with open(toml_file, "rb") as f:
24
+ pyproject = tomllib.load(f)
25
+ package_name = pyproject["project"]["name"]
26
+ return package_name, pyproject.get("project", {}).get("entry-points", {})
27
+
28
+
29
+ def get_current_entry_points(repo_base) -> bool:
30
+ """Create current entry points dict for comparison."""
31
+ current_eps = {}
32
+ for toml_file in repo_base.glob("diracx-*/pyproject.toml"):
33
+ package_name, entry_pts = get_entry_points_from_toml(f"{toml_file}")
34
+ # Ignore packages that are not installed
35
+ try:
36
+ distribution(package_name)
37
+ except PackageNotFoundError:
38
+ continue
39
+ # Merge the entry points
40
+ for key, value in entry_pts.items():
41
+ current_eps[key] = current_eps.get(key, {}) | value
42
+ return current_eps
43
+
44
+
45
+ @pytest.fixture(scope="session", autouse=True)
46
+ def verify_entry_points(request, pytestconfig):
47
+ try:
48
+ ini_toml_name = tomllib.loads(pytestconfig.inipath.read_text())["project"][
49
+ "name"
50
+ ]
51
+ except tomllib.TOMLDecodeError:
52
+ return
53
+ if ini_toml_name == "diracx":
54
+ repo_base = pytestconfig.inipath.parent
55
+ elif ini_toml_name.startswith("diracx-"):
56
+ repo_base = pytestconfig.inipath.parent.parent
57
+ else:
58
+ return
59
+
60
+ installed_eps = get_installed_entry_points()
61
+ current_eps = get_current_entry_points(repo_base)
62
+
63
+ if installed_eps != current_eps:
64
+ pytest.fail(
65
+ "Project and installed entry-points are not consistent. "
66
+ "You should run `pip install -r requirements-dev.txt`",
67
+ )
@@ -42,8 +42,8 @@ class MockOSDBMixin:
42
42
  from diracx.db.sql.utils import DateNowColumn
43
43
 
44
44
  # Dynamically create a subclass of BaseSQLDB so we get clearer errors
45
- MockedDB = type(f"Mocked{self.__class__.__name__}", (sql_utils.BaseSQLDB,), {})
46
- self._sql_db = MockedDB(connection_kwargs["sqlalchemy_dsn"])
45
+ mocked_db = type(f"Mocked{self.__class__.__name__}", (sql_utils.BaseSQLDB,), {})
46
+ self._sql_db = mocked_db(connection_kwargs["sqlalchemy_dsn"])
47
47
 
48
48
  # Dynamically create the table definition based on the fields
49
49
  columns = [
@@ -53,16 +53,16 @@ class MockOSDBMixin:
53
53
  for field, field_type in self.fields.items():
54
54
  match field_type["type"]:
55
55
  case "date":
56
- ColumnType = DateNowColumn
56
+ column_type = DateNowColumn
57
57
  case "long":
58
- ColumnType = partial(Column, type_=Integer)
58
+ column_type = partial(Column, type_=Integer)
59
59
  case "keyword":
60
- ColumnType = partial(Column, type_=String(255))
60
+ column_type = partial(Column, type_=String(255))
61
61
  case "text":
62
- ColumnType = partial(Column, type_=String(64 * 1024))
62
+ column_type = partial(Column, type_=String(64 * 1024))
63
63
  case _:
64
64
  raise NotImplementedError(f"Unknown field type: {field_type=}")
65
- columns.append(ColumnType(field, default=None))
65
+ columns.append(column_type(field, default=None))
66
66
  self._sql_db.metadata = MetaData()
67
67
  self._table = Table("dummy", self._sql_db.metadata, *columns)
68
68
 
@@ -72,18 +72,22 @@ class MockOSDBMixin:
72
72
  yield
73
73
 
74
74
  async def __aenter__(self):
75
- await self._sql_db.__aenter__()
75
+ """Enter the request context.
76
+
77
+ This is a no-op as the real OpenSearch class doesn't use transactions.
78
+ Instead we enter a transaction in each method that needs it.
79
+ """
76
80
  return self
77
81
 
78
82
  async def __aexit__(self, exc_type, exc_value, traceback):
79
- await self._sql_db.__aexit__(exc_type, exc_value, traceback)
83
+ pass
80
84
 
81
85
  async def create_index_template(self) -> None:
82
86
  async with self._sql_db.engine.begin() as conn:
83
87
  await conn.run_sync(self._sql_db.metadata.create_all)
84
88
 
85
89
  async def upsert(self, doc_id, document) -> None:
86
- async with self:
90
+ async with self._sql_db:
87
91
  values = {}
88
92
  for key, value in document.items():
89
93
  if key in self.fields:
@@ -106,7 +110,7 @@ class MockOSDBMixin:
106
110
  per_page: int = 100,
107
111
  page: int | None = None,
108
112
  ) -> tuple[int, list[dict[Any, Any]]]:
109
- async with self:
113
+ async with self._sql_db:
110
114
  # Apply selection
111
115
  if parameters:
112
116
  columns = []
@@ -150,7 +154,8 @@ class MockOSDBMixin:
150
154
  return results
151
155
 
152
156
  async def ping(self):
153
- return await self._sql_db.ping()
157
+ async with self._sql_db:
158
+ return await self._sql_db.ping()
154
159
 
155
160
 
156
161
  def fake_available_osdb_implementations(name, *, real_available_implementations):
@@ -158,6 +163,6 @@ def fake_available_osdb_implementations(name, *, real_available_implementations)
158
163
 
159
164
  # Dynamically generate a class that inherits from the first implementation
160
165
  # but that also has the MockOSDBMixin
161
- MockParameterDB = type(name, (MockOSDBMixin, implementations[0]), {})
166
+ mock_parameter_db = type(name, (MockOSDBMixin, implementations[0]), {})
162
167
 
163
- return [MockParameterDB] + implementations
168
+ return [mock_parameter_db] + implementations