openmodule-test 14.2.0__tar.gz → 15.0.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 (32) hide show
  1. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/PKG-INFO +13 -8
  2. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/core.py +1 -3
  3. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/database.py +8 -6
  4. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/health.py +2 -4
  5. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/interrupt.py +4 -4
  6. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/io_simulator.py +7 -7
  7. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/openmodule_test.egg-info/PKG-INFO +14 -9
  8. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/openmodule_test.egg-info/SOURCES.txt +0 -4
  9. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/package_reader.py +12 -13
  10. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/presence.py +20 -19
  11. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/rpc.py +14 -14
  12. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/sentry.py +4 -5
  13. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/settings.py +7 -7
  14. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/setup.cfg +1 -2
  15. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/signal_simulator.py +6 -6
  16. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/utils.py +2 -2
  17. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/zeromq.py +19 -17
  18. openmodule_test-14.2.0/AUTHORS +0 -11
  19. openmodule_test-14.2.0/ChangeLog +0 -217
  20. openmodule_test-14.2.0/openmodule_test.egg-info/pbr.json +0 -1
  21. openmodule_test-14.2.0/requirements.txt +0 -2
  22. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/__init__.py +0 -0
  23. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/alert.py +0 -0
  24. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/connection_status.py +0 -0
  25. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/eventlistener.py +0 -0
  26. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/files.py +0 -0
  27. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/gate.py +0 -0
  28. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/openmodule_test.egg-info/dependency_links.txt +0 -0
  29. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/openmodule_test.egg-info/not-zip-safe +0 -0
  30. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/openmodule_test.egg-info/requires.txt +0 -0
  31. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/openmodule_test.egg-info/top_level.txt +0 -0
  32. {openmodule_test-14.2.0 → openmodule_test-15.0.0}/setup.py +0 -0
@@ -1,18 +1,23 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: openmodule_test
3
- Version: 14.2.0
3
+ Version: 15.0.0
4
4
  Summary: Libraries for testing openmodule services
5
5
  Home-page: https://gitlab.com/arivo-public/device-python/openmodule.git
6
6
  Author: ARIVO
7
7
  Author-email: support@arivo.co
8
8
  License: GNU General Public License v2 (GPLv2)
9
9
  Keywords: arivo openmodule openmodule_test test
10
- Platform: UNKNOWN
11
10
  Classifier: Intended Audience :: Developers
12
11
  Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
13
12
  Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3.7
15
- Classifier: Programming Language :: Python :: 3.8
16
-
17
- UNKNOWN
18
-
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Requires-Dist: multiprocessing_logging
15
+ Requires-Dist: freezegun
16
+ Dynamic: author
17
+ Dynamic: author-email
18
+ Dynamic: classifier
19
+ Dynamic: home-page
20
+ Dynamic: keywords
21
+ Dynamic: license
22
+ Dynamic: requires-dist
23
+ Dynamic: summary
@@ -1,5 +1,3 @@
1
- from typing import Dict
2
-
3
1
  from openmodule.core import init_openmodule, shutdown_openmodule, OpenModuleCore
4
2
  from openmodule_test.health import HealthTestMixin
5
3
 
@@ -9,7 +7,7 @@ class OpenModuleCoreTestMixin(HealthTestMixin):
9
7
  Mixin which creates a core, zmq, and health mixin
10
8
  """
11
9
 
12
- init_kwargs: Dict = {}
10
+ init_kwargs: dict = {}
13
11
  core: OpenModuleCore
14
12
 
15
13
  def get_init_kwargs(self):
@@ -5,7 +5,7 @@ from unittest import TestCase
5
5
 
6
6
  from alembic import command
7
7
  from alembic.runtime.migration import MigrationContext
8
- from sqlalchemy import MetaData
8
+ from sqlalchemy import MetaData, text
9
9
  from sqlalchemy.ext.automap import automap_base
10
10
 
11
11
  from openmodule.config import settings
@@ -19,8 +19,8 @@ _first_start = True
19
19
 
20
20
  def truncate_all_tables(database: Database, keep=("alembic_version",)):
21
21
  assert any(x in database.db_folder for x in ["/test/"]), "deleting all tables is only for testing"
22
- metadata = MetaData(bind=database._engine)
23
- metadata.reflect()
22
+ metadata = MetaData()
23
+ metadata.reflect(bind=database._engine)
24
24
  with database._engine.connect() as con:
25
25
  trans = con.begin()
26
26
  for table in reversed(metadata.sorted_tables):
@@ -123,7 +123,7 @@ class AlembicMigrationTestMixin(SQLiteTestMixin):
123
123
 
124
124
  def reload_models(self):
125
125
  self.base = automap_base()
126
- self.base.prepare(self.connection, reflect=True)
126
+ self.base.prepare(autoload_with=self.connection)
127
127
 
128
128
  def alembic_config(self):
129
129
  alembic_path = self.alembic_path or os.path.join(os.getcwd(), "database")
@@ -134,13 +134,15 @@ class AlembicMigrationTestMixin(SQLiteTestMixin):
134
134
  def migrate_up(self, revision="head"):
135
135
  config = self.alembic_config()
136
136
  command.upgrade(config, revision)
137
- assert self.connection.execute("PRAGMA foreign_keys").fetchone()[0] == 1, "foreign keys are not enabled"
137
+ with self.connection.connect() as connection:
138
+ assert connection.execute(text("PRAGMA foreign_keys")).fetchone()[0] == 1, "foreign keys are not enabled"
138
139
  self.reload_models()
139
140
 
140
141
  def migrate_down(self, revision="base"):
141
142
  config = self.alembic_config()
142
143
  command.downgrade(config, revision)
143
- assert self.connection.execute("PRAGMA foreign_keys").fetchone()[0] == 1, "foreign keys are not enabled"
144
+ with self.connection.connect() as connection:
145
+ assert connection.execute(text("PRAGMA foreign_keys")).fetchone()[0] == 1, "foreign keys are not enabled"
144
146
  self.reload_models()
145
147
 
146
148
  def current_revision(self):
@@ -1,5 +1,3 @@
1
- from typing import Optional
2
-
3
1
  from openmodule_test.zeromq import ZMQTestMixin
4
2
 
5
3
 
@@ -10,7 +8,7 @@ def _get_health_filter(name):
10
8
 
11
9
 
12
10
  class HealthTestMixin(ZMQTestMixin):
13
- def get_health(self, name: Optional[str] = None, timeout: float = 3):
11
+ def get_health(self, name: str | None = None, timeout: float = 3):
14
12
  self.assertSubscription("healthpong")
15
13
  self.zmq_client.send("healthz", {"type": "ping", "ping": "ping"})
16
14
  _, message = self.zmq_client.wait_for_message(
@@ -29,7 +27,7 @@ class HealthTestMixin(ZMQTestMixin):
29
27
  pong = message.get("pong", {})
30
28
  self.assertEqual("error", pong.get("status"))
31
29
 
32
- def wait_for_health(self, name: Optional[str] = None):
30
+ def wait_for_health(self, name: str | None = None):
33
31
  """
34
32
  :param name: if specified the function waits for a specific service name on startup
35
33
  """
@@ -7,7 +7,7 @@ import traceback
7
7
  from multiprocessing import Process, Event
8
8
  from signal import SIGINT, SIGKILL
9
9
  from textwrap import dedent
10
- from typing import Callable, Union, Type, Optional
10
+ from typing import Callable
11
11
  from unittest import TestCase
12
12
 
13
13
  import multiprocessing_logging
@@ -76,7 +76,7 @@ class InterruptTestMixin(TestCase):
76
76
  for usage, look at file tests/test_interrupt
77
77
  """
78
78
 
79
- process: Optional[ExceptionProcess] = None
79
+ process: ExceptionProcess | None = None
80
80
 
81
81
  def _kill_process(self):
82
82
  # this is called in tear down and as a cleanup to make sure that under any circumstances the process is killed
@@ -132,13 +132,13 @@ class InterruptTestMixin(TestCase):
132
132
  else:
133
133
  raise AssertionError("Process did not finish gracefully")
134
134
 
135
- def send_signal_to_process(self, process: ExceptionProcess, signal: Union[Type[KeyboardInterrupt], int]):
135
+ def send_signal_to_process(self, process: ExceptionProcess, signal: type[KeyboardInterrupt] | int):
136
136
  self.assertFalse(process.is_finished.is_set(), msg="process crashed before we could send the signal")
137
137
  if signal == KeyboardInterrupt:
138
138
  signal = SIGINT
139
139
  os.kill(process.pid, signal)
140
140
 
141
- def signal_in_function(self, f: Callable, signal: Union[Type[KeyboardInterrupt], int], *,
141
+ def signal_in_function(self, f: Callable, signal: type[KeyboardInterrupt] | int, *,
142
142
  raise_exception_after: float = 3.0, shutdown_timeout: float = 3.0):
143
143
  """
144
144
  wraps the helper functions into a single function because apparently everybody likes
@@ -1,12 +1,12 @@
1
1
  from collections import defaultdict
2
- from datetime import datetime
3
- from typing import Callable, Dict, Optional
2
+ from typing import Callable
4
3
 
5
4
  from openmodule.models.base import Gateway
6
5
  from openmodule.models.io import IoMessage, IoState
6
+ from openmodule.utils.misc_functions import utcnow
7
7
 
8
8
 
9
- def generate_example_states(count: Optional[int] = 8) -> Dict[str, IoState]:
9
+ def generate_example_states(count: int | None = 8) -> dict[str, IoState]:
10
10
  """
11
11
  Creates a dict with pin as key and IoState as value.
12
12
  param count: how many pins should be created.
@@ -14,13 +14,13 @@ def generate_example_states(count: Optional[int] = 8) -> Dict[str, IoState]:
14
14
  Gateways with even x have direction in, odds have out.
15
15
  All pins created low and not inverted.
16
16
  """
17
- states: Dict[str, IoState] = defaultdict(IoState)
17
+ states: dict[str, IoState] = defaultdict(IoState)
18
18
  for i in range(count):
19
19
  gate = int(i/4)
20
20
  direction = "in" if gate % 2 == 0 else "out"
21
21
  gateway = Gateway(gate="gate_{}".format(gate), direction=direction)
22
22
  state = IoState(pin="", gateway=gateway, value=0, physical=0, inverted=False, type="input",
23
- last_timestamp=datetime.utcnow())
23
+ last_timestamp=utcnow())
24
24
  if i % 4 == 0:
25
25
  state.pin = "gate_{}_button".format(gate)
26
26
  elif i % 4 == 1:
@@ -45,14 +45,14 @@ class IoSimulator:
45
45
  There can be a race condition during init if the emitted messages have not yet been received by
46
46
  an io handler. See tests.test_io_listen.IoTest's comment in setUp()
47
47
  """
48
- def __init__(self, states: Dict[str, IoState], emit: Callable[[IoMessage], None]):
48
+ def __init__(self, states: dict[str, IoState], emit: Callable[[IoMessage], None]):
49
49
  self.pin_states = states
50
50
  self.emit = emit
51
51
  for state in self.pin_states.values():
52
52
  self.emit(IoMessage(gateway=state.gateway, type=state.type, pin=state.pin, value=state.value,
53
53
  inverted=state.inverted, physical=state.physical, edge=1))
54
54
 
55
- def get_pin_states(self) -> Dict[str, IoState]:
55
+ def get_pin_states(self) -> dict[str, IoState]:
56
56
  return self.pin_states
57
57
 
58
58
  def change_pin_sate(self, pin: str):
@@ -1,18 +1,23 @@
1
- Metadata-Version: 2.1
2
- Name: openmodule-test
3
- Version: 14.2.0
1
+ Metadata-Version: 2.4
2
+ Name: openmodule_test
3
+ Version: 15.0.0
4
4
  Summary: Libraries for testing openmodule services
5
5
  Home-page: https://gitlab.com/arivo-public/device-python/openmodule.git
6
6
  Author: ARIVO
7
7
  Author-email: support@arivo.co
8
8
  License: GNU General Public License v2 (GPLv2)
9
9
  Keywords: arivo openmodule openmodule_test test
10
- Platform: UNKNOWN
11
10
  Classifier: Intended Audience :: Developers
12
11
  Classifier: License :: OSI Approved :: GNU General Public License v2 (GPLv2)
13
12
  Classifier: Programming Language :: Python
14
- Classifier: Programming Language :: Python :: 3.7
15
- Classifier: Programming Language :: Python :: 3.8
16
-
17
- UNKNOWN
18
-
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Requires-Dist: multiprocessing_logging
15
+ Requires-Dist: freezegun
16
+ Dynamic: author
17
+ Dynamic: author-email
18
+ Dynamic: classifier
19
+ Dynamic: home-page
20
+ Dynamic: keywords
21
+ Dynamic: license
22
+ Dynamic: requires-dist
23
+ Dynamic: summary
@@ -1,6 +1,3 @@
1
- AUTHORS
2
- ChangeLog
3
- requirements.txt
4
1
  setup.cfg
5
2
  setup.py
6
3
  ./__init__.py
@@ -26,6 +23,5 @@ openmodule_test.egg-info/PKG-INFO
26
23
  openmodule_test.egg-info/SOURCES.txt
27
24
  openmodule_test.egg-info/dependency_links.txt
28
25
  openmodule_test.egg-info/not-zip-safe
29
- openmodule_test.egg-info/pbr.json
30
26
  openmodule_test.egg-info/requires.txt
31
27
  openmodule_test.egg-info/top_level.txt
@@ -1,6 +1,5 @@
1
1
  import json
2
2
  import random
3
- from typing import Optional, Dict, List
4
3
 
5
4
  from openmodule.utils.package_reader import ServiceSetting, PackageReader, PackageData
6
5
 
@@ -28,9 +27,9 @@ class FakeServiceRepo(dict):
28
27
  self[settings.name] = settings
29
28
  self._resolve_parents()
30
29
 
31
- def add_hardware_package(self, name, env: Optional[Dict] = None, yml: Optional[Dict] = None,
32
- hardware_type: Optional[List[str]] = None, ip: Optional[str] = None,
33
- revision: Optional[int] = None, package_data: Optional[PackageData] = None):
30
+ def add_hardware_package(self, name, env: dict | None = None, yml: dict | None = None,
31
+ hardware_type: list[str] | None = None, ip: str | None = None,
32
+ revision: int | None = None, package_data: PackageData | None = None):
34
33
  revision = revision or random.randint(0, 1000000000)
35
34
  merged_yml = {}
36
35
  if ip:
@@ -51,10 +50,10 @@ class FakeServiceRepo(dict):
51
50
  self.add_package(ServiceSetting(env=merged_env, yml=merged_yml, name=name,
52
51
  revision=revision, package_data=package_data))
53
52
 
54
- def add_software_package(self, name, env: Optional[Dict] = None, yml: Optional[Dict] = None,
55
- parent_type: Optional[List[str]] = None, revision: Optional[int] = None,
56
- parent: Optional[str] = None, package_data: Optional[PackageData] = None,
57
- software_type: Optional[List[str]] = None):
53
+ def add_software_package(self, name, env: dict | None = None, yml: dict | None = None,
54
+ parent_type: list[str] | None = None, revision: int | None = None,
55
+ parent: str | None = None, package_data: PackageData | None = None,
56
+ software_type: list[str] | None = None):
58
57
  revision = revision or random.randint(0, 1000000000)
59
58
  merged_env = {
60
59
  "NAME": name,
@@ -83,10 +82,10 @@ class MockPackageReader(PackageReader):
83
82
 
84
83
  self._services = FakeServiceRepo()
85
84
 
86
- def get_service_by_name(self, service: str) -> Optional[ServiceSetting]:
85
+ def get_service_by_name(self, service: str) -> ServiceSetting | None:
87
86
  return self._services.get(service)
88
87
 
89
- def list_all_services(self, prefix: Optional[str] = None, compute_id: Optional[int] = None) -> List[ServiceSetting]:
88
+ def list_all_services(self, prefix: str | None = None, compute_id: int | None = None) -> list[ServiceSetting]:
90
89
  """
91
90
  :param compute_id: compute unit id, if None packages from all units are returned
92
91
  :param prefix: prefix of the package id, if none is passed all are returned
@@ -98,7 +97,7 @@ class MockPackageReader(PackageReader):
98
97
  (compute_id is None or (x.env.get("COMPUTE_ID") or '1') == compute_id_str)
99
98
  ]
100
99
 
101
- def list_by_hardware_type(self, prefix: str, compute_id: Optional[int] = None):
100
+ def list_by_hardware_type(self, prefix: str, compute_id: int | None = None):
102
101
  """
103
102
  lists all packages with a certain hardware type (prefix). Note that these can only be hardware packages
104
103
  i.e. their name starts with "hw_"
@@ -115,7 +114,7 @@ class MockPackageReader(PackageReader):
115
114
  (compute_id is None or (x.env.get("COMPUTE_ID") or '1') == compute_id_str)
116
115
  ]
117
116
 
118
- def list_by_parent_type(self, prefix: str, compute_id: Optional[int] = None):
117
+ def list_by_parent_type(self, prefix: str, compute_id: int | None = None):
119
118
  """
120
119
  lists all packages with a certain parent type (prefix). Note that these can only be software packages
121
120
  i.e. their name starts with "om_"
@@ -132,7 +131,7 @@ class MockPackageReader(PackageReader):
132
131
  (compute_id is None or (x.env.get("COMPUTE_ID") or '1') == compute_id_str)
133
132
  ]
134
133
 
135
- def list_by_software_type(self, prefix: str, compute_id: Optional[int] = None):
134
+ def list_by_software_type(self, prefix: str, compute_id: int | None = None):
136
135
  """
137
136
  lists all packages with a certain software type (prefix). Note that these can only be software packages
138
137
  i.e. their name starts with "om_"
@@ -1,13 +1,14 @@
1
1
  import random
2
2
  import time
3
3
  from datetime import datetime
4
- from typing import Optional, Callable
4
+ from typing import Callable
5
5
 
6
6
  from openmodule.models.base import Direction, Gateway, datetime_to_timestamp
7
7
  from openmodule.models.presence import PresenceBaseMessage, PresenceEnterMessage, PresenceLeaveMessage, \
8
8
  PresenceForwardMessage, PresenceBackwardMessage, PresenceMedia, PresenceChangeMessage
9
9
  from openmodule.models.vehicle import LPRMedium, LPRCountry, Medium, Vehicle, MakeModel, PresenceAllIds, \
10
10
  EnterDirection, QRMedium, MediumType
11
+ from openmodule.utils.misc_functions import utcnow
11
12
 
12
13
 
13
14
  class VehicleBuilder:
@@ -19,7 +20,7 @@ class VehicleBuilder:
19
20
  self.medium = PresenceMedia()
20
21
  self.make_model = MakeModel(make="UNKNOWN", make_confidence=0.7, model="UNKNOWN", model_confidence=-1.0)
21
22
  self.enter_direction = EnterDirection.unknown
22
- self.enter_time = datetime.utcnow()
23
+ self.enter_time = utcnow()
23
24
  self.leave_time = None
24
25
 
25
26
  def vehicle(self) -> Vehicle:
@@ -39,7 +40,7 @@ class VehicleBuilder:
39
40
  self.vehicle_id = id
40
41
  return self
41
42
 
42
- def lpr(self, country: Optional[str], plate: Optional[str] = None, state="") -> 'VehicleBuilder':
43
+ def lpr(self, country: str | None, plate: str | None = None, state="") -> 'VehicleBuilder':
43
44
  if country is None:
44
45
  self.medium.lpr = None
45
46
  else:
@@ -49,21 +50,21 @@ class VehicleBuilder:
49
50
  )
50
51
  return self
51
52
 
52
- def nfc(self, id: Optional[str]) -> 'VehicleBuilder':
53
+ def nfc(self, id: str | None) -> 'VehicleBuilder':
53
54
  if id is None:
54
55
  self.medium.nfc = id
55
56
  else:
56
57
  self.medium.nfc = Medium(id=id, type=MediumType.nfc)
57
58
  return self
58
59
 
59
- def qr(self, id: Optional[str], binary: Optional[str] = None) -> 'VehicleBuilder':
60
+ def qr(self, id: str | None, binary: str | None = None) -> 'VehicleBuilder':
60
61
  if id is None:
61
62
  self.medium.qr = id
62
63
  else:
63
64
  self.medium.qr = QRMedium(id=id, binary=binary)
64
65
  return self
65
66
 
66
- def pin(self, id: Optional[str]) -> 'VehicleBuilder':
67
+ def pin(self, id: str | None) -> 'VehicleBuilder':
67
68
  if id is None:
68
69
  self.medium.pin = id
69
70
  else:
@@ -88,10 +89,10 @@ class VehicleBuilder:
88
89
 
89
90
 
90
91
  class PresenceSimulator:
91
- current_present: Optional[VehicleBuilder] = None
92
+ current_present: VehicleBuilder | None = None
92
93
 
93
94
  def __init__(self, gate: str, direction: Direction, emit: Callable[[PresenceBaseMessage], None],
94
- present_area_name: Optional[str] = None):
95
+ present_area_name: str | None = None):
95
96
  self.gateway = Gateway(gate=gate, direction=direction)
96
97
  self.emit = emit
97
98
  self.present_area_name = present_area_name or f"{self.gateway.gate}-present"
@@ -100,7 +101,7 @@ class PresenceSimulator:
100
101
  return VehicleBuilder()
101
102
 
102
103
  def _common_kwargs(self, vehicle):
103
- timestamp = datetime_to_timestamp(datetime.utcnow())
104
+ timestamp = datetime_to_timestamp(utcnow())
104
105
  all_ids = PresenceAllIds(lpr=None if vehicle.medium.lpr is None else [vehicle.medium.lpr],
105
106
  qr=None if vehicle.medium.qr is None else [vehicle.medium.qr],
106
107
  nfc=None if vehicle.medium.nfc is None else [vehicle.medium.nfc],
@@ -120,45 +121,45 @@ class PresenceSimulator:
120
121
  "leave_time": vehicle.leave_time
121
122
  }
122
123
 
123
- def enter(self, vehicle: VehicleBuilder, enter_time: Optional[datetime] = None):
124
+ def enter(self, vehicle: VehicleBuilder, enter_time: datetime | None = None):
124
125
  vehicle.enter_time = enter_time or vehicle.enter_time
125
126
  if self.current_present:
126
127
  self.leave()
127
128
  self.current_present = vehicle
128
129
  self.emit(PresenceEnterMessage(**self._common_kwargs(vehicle)))
129
130
 
130
- def enter_without_dropping_present_vehicle(self, vehicle: VehicleBuilder, enter_time: Optional[datetime] = None):
131
+ def enter_without_dropping_present_vehicle(self, vehicle: VehicleBuilder, enter_time: datetime | None = None):
131
132
  vehicle.enter_time = enter_time or vehicle.enter_time
132
133
  self.current_present = vehicle
133
134
  self.emit(PresenceEnterMessage(**self._common_kwargs(vehicle)))
134
135
 
135
- def leave(self, leave_time: Optional[datetime] = None) -> VehicleBuilder:
136
- self.current_present.leave_time = leave_time or self.current_present.leave_time or datetime.utcnow()
136
+ def leave(self, leave_time: datetime | None = None) -> VehicleBuilder:
137
+ self.current_present.leave_time = leave_time or self.current_present.leave_time or utcnow()
137
138
  self.emit(PresenceLeaveMessage(**self._common_kwargs(self.current_present)))
138
139
  temp = self.current_present
139
140
  self.current_present = None
140
141
  return temp
141
142
 
142
- def leave_without_present(self, vehicle: VehicleBuilder, leave_time: Optional[datetime] = None):
143
- vehicle.leave_time = leave_time or vehicle.leave_time or datetime.utcnow()
143
+ def leave_without_present(self, vehicle: VehicleBuilder, leave_time: datetime | None = None):
144
+ vehicle.leave_time = leave_time or vehicle.leave_time or utcnow()
144
145
  self.emit(PresenceLeaveMessage(**self._common_kwargs(vehicle)))
145
146
 
146
- def forward(self, vehicle: Optional[VehicleBuilder] = None):
147
+ def forward(self, vehicle: VehicleBuilder | None = None):
147
148
  assert vehicle or self.current_present, "a vehicle must be present, or you have to pass a vehicle"
148
149
  if not vehicle:
149
150
  vehicle = self.leave()
150
151
  if vehicle.leave_time is None: # if leave was not called for this vehicle
151
- vehicle.leave_time = datetime.utcnow()
152
+ vehicle.leave_time = utcnow()
152
153
  self.emit(PresenceForwardMessage(
153
154
  **self._common_kwargs(vehicle)
154
155
  ))
155
156
 
156
- def backward(self, vehicle: Optional[VehicleBuilder] = None):
157
+ def backward(self, vehicle: VehicleBuilder | None = None):
157
158
  assert vehicle or self.current_present, "a vehicle must be present, or you have to pass a vehicle"
158
159
  if not vehicle:
159
160
  vehicle = self.leave()
160
161
  if vehicle.leave_time is None: # if leave was not called for this vehicle
161
- vehicle.leave_time = datetime.utcnow()
162
+ vehicle.leave_time = utcnow()
162
163
  self.emit(PresenceBackwardMessage(
163
164
  **self._common_kwargs(vehicle)
164
165
  ))
@@ -3,7 +3,7 @@ import string
3
3
  import threading
4
4
  import time
5
5
  from functools import partial
6
- from typing import Dict, Tuple, Any, Callable, Type, Optional
6
+ from typing import Any, Callable
7
7
 
8
8
  from pydantic.main import BaseModel
9
9
 
@@ -18,7 +18,7 @@ class _EmptyModel(BaseModel):
18
18
 
19
19
 
20
20
  class RPCServerTestMixin(ZMQTestMixin):
21
- def wait_for_rpc_response(self, channel: str, type: str, request: BaseModel, response_type: Type[OpenModuleModel]):
21
+ def wait_for_rpc_response(self, channel: str, type: str, request: BaseModel, response_type: type[OpenModuleModel]):
22
22
  """
23
23
  waits until a rpc server is responding to the channel/type
24
24
  """
@@ -67,21 +67,21 @@ class MockRPCEntry(RPCClient.RPCEntry):
67
67
  def _run_callback(self):
68
68
  try:
69
69
  res = self.callback()
70
- self.response = {"status": "ok", **(res if isinstance(res, dict) else res.dict())}
70
+ self.response = {"status": "ok", **(res if isinstance(res, dict) else res.model_dump())}
71
71
  except Exception:
72
- self.response = RPCErrorResult(status=RPCServerError.handler_error).dict()
72
+ self.response = RPCErrorResult(status=RPCServerError.handler_error).model_dump()
73
73
  self.ready.set()
74
74
 
75
- def result(self, response_type: Type[OpenModuleModel], timeout=None):
75
+ def result(self, response_type: type[OpenModuleModel], timeout=None):
76
76
  thread = threading.Thread(target=self._run_callback, daemon=True)
77
77
  thread.start()
78
78
  return super().result(response_type, timeout)
79
79
 
80
80
 
81
81
  class MockRPCClient:
82
- def __init__(self, callbacks: Optional[Dict[Tuple[str, str], Callable[[OpenModuleModel, Any], Any]]] = None,
83
- responses: Optional[Dict[Tuple[str, str], Any]] = None,
84
- immediate_callbacks: Optional[Dict[Tuple[str, str], Callable[[OpenModuleModel, Any], Any]]] = None,
82
+ def __init__(self, callbacks: dict[tuple[str, str], Callable[[OpenModuleModel, Any], Any]] | None = None,
83
+ responses: dict[tuple[str, str], Any] | None = None,
84
+ immediate_callbacks: dict[tuple[str, str], Callable[[OpenModuleModel, Any], Any]] | None = None,
85
85
  default_timeout=1.0):
86
86
  """
87
87
  :param callbacks: callback functions executed on rpc_entry.result()
@@ -95,7 +95,7 @@ class MockRPCClient:
95
95
  self.last_request = {}
96
96
  self.default_timeout = default_timeout
97
97
 
98
- def rpc_non_blocking(self, channel: str, type: str, request: [Dict, BaseModel], timeout: float = None) \
98
+ def rpc_non_blocking(self, channel: str, type: str, request: dict | BaseModel, timeout: float | None = None) \
99
99
  -> RPCClient.RPCEntry:
100
100
  self.last_request[(channel, type)] = request
101
101
  if timeout is None:
@@ -103,17 +103,17 @@ class MockRPCClient:
103
103
  if (channel, type) in self.callbacks:
104
104
  entry = MockRPCEntry(timeout, partial(self.callbacks[(channel, type)], request, None))
105
105
  elif (channel, type) in self.immediate_callbacks:
106
- res = self.immediate_callbacks[(channel, type)](request, None).dict()
106
+ res = self.immediate_callbacks[(channel, type)](request, None).model_dump()
107
107
  entry = RPCClient.RPCEntry(timeout)
108
- entry.response = {"status": "ok", **(res if isinstance(res, dict) else res.dict())}
108
+ entry.response = {"status": "ok", **(res if isinstance(res, dict) else res.model_dump())}
109
109
  else:
110
110
  entry = RPCClient.RPCEntry(timeout)
111
111
  if (channel, type) in self.responses:
112
- res = self.responses.get((channel, type)).dict()
113
- entry.response = {"status": "ok", **(res if isinstance(res, dict) else res.dict())}
112
+ res = self.responses.get((channel, type)).model_dump()
113
+ entry.response = {"status": "ok", **(res if isinstance(res, dict) else res.model_dump())}
114
114
  return entry
115
115
 
116
- def rpc(self, channel: str, type: str, request: [Dict, BaseModel], response_type: Type[OpenModuleModel],
116
+ def rpc(self, channel: str, type: str, request: dict | BaseModel, response_type: type[OpenModuleModel],
117
117
  timeout: float = None) -> OpenModuleModel:
118
118
  entry = self.rpc_non_blocking(channel, type, request, timeout)
119
119
  return entry.result(response_type, timeout=timeout)
@@ -1,5 +1,4 @@
1
1
  import threading
2
- from typing import List
3
2
  from unittest import TestCase, mock
4
3
 
5
4
  import sentry_sdk
@@ -16,14 +15,14 @@ class SentryTestTransport(sentry_sdk.transport.Transport):
16
15
 
17
16
  def __init__(self, options=None):
18
17
  super().__init__(options)
19
- self.envelopes: List[Envelope] = []
18
+ self.envelopes: list[Envelope] = []
20
19
  self.envelopes_lock = threading.Lock()
21
20
 
22
21
  def capture_envelope(self, envelope: Envelope):
23
22
  with self.envelopes_lock:
24
23
  self.envelopes.append(envelope)
25
24
 
26
- def get_envelopes(self, clear: bool = True) -> List[Envelope]:
25
+ def get_envelopes(self, clear: bool = True) -> list[Envelope]:
27
26
  with self.envelopes_lock:
28
27
  envelopes = self.envelopes
29
28
  if clear:
@@ -59,9 +58,9 @@ class SentryTestMixin(TestCase):
59
58
  self.assertIsInstance(transport, SentryTestTransport)
60
59
  return transport
61
60
 
62
- def _get_envelopes(self) -> List[Envelope]:
61
+ def _get_envelopes(self) -> list[Envelope]:
63
62
  return self.sentry_transport.get_envelopes(clear=False)
64
63
 
65
- def get_sent_envelopes(self, timeout: float = 0, clear: bool = True) -> List[Envelope]:
64
+ def get_sent_envelopes(self, timeout: float = 0, clear: bool = True) -> list[Envelope]:
66
65
  wait_for_value(self._get_envelopes, target=[], invert_target=True, timeout=timeout)
67
66
  return self.sentry_transport.get_envelopes(clear=clear)
@@ -1,6 +1,6 @@
1
1
  import time
2
- from enum import Enum
3
- from typing import Dict, Any, Optional, Type, TypeVar, Tuple
2
+ from enum import StrEnum
3
+ from typing import Any, TypeVar
4
4
 
5
5
  from settings_models import serialization
6
6
 
@@ -20,7 +20,7 @@ class SettingsMocker:
20
20
  """
21
21
 
22
22
  # noinspection PyMissingConstructor
23
- def __init__(self, settings: Dict[Tuple[str, str], Any],
23
+ def __init__(self, settings: dict[tuple[str, str], Any],
24
24
  allow_unknown_settings: bool = False, allow_wrong_values: bool = False):
25
25
  if not allow_unknown_settings:
26
26
  for setting in settings:
@@ -32,7 +32,7 @@ class SettingsMocker:
32
32
  self.settings = settings
33
33
  self.exception = None
34
34
 
35
- def get(self, key: str, scope: str = "", custom_type: Optional[Type[T]] = None) -> Optional[T]:
35
+ def get(self, key: str, scope: str = "", custom_type: type[T] | None = None) -> T | None:
36
36
  if self.exception:
37
37
  raise self.exception
38
38
  value = self.settings.get((key, scope))
@@ -43,7 +43,7 @@ class SettingsMocker:
43
43
  except Exception:
44
44
  return None
45
45
 
46
- def get_many(self, keys_with_types: Dict[str, Type[T]], scope: str = "") -> Dict[str, T]:
46
+ def get_many(self, keys_with_types: dict[str, type[T]], scope: str = "") -> dict[str, T]:
47
47
  if self.exception:
48
48
  raise self.exception
49
49
  else:
@@ -69,14 +69,14 @@ class SettingsRPCMocker:
69
69
  use result_mode to simulate errors
70
70
  """
71
71
 
72
- class ResultMode(str, Enum):
72
+ class ResultMode(StrEnum):
73
73
  ok = "ok" # successful
74
74
  error = "error" # raise error in callback
75
75
  timeout = "timeout" # sleep in callback for 1 second
76
76
  fail = "fail" # return success false
77
77
  first_fail = "first_fail" # return success false for first in get_many
78
78
 
79
- def __init__(self, rpc_server: RPCServer, settings: Dict[Tuple[str, str], Any],
79
+ def __init__(self, rpc_server: RPCServer, settings: dict[tuple[str, str], Any],
80
80
  allow_unknown_settings: bool = False, allow_wrong_values: bool = False):
81
81
  if not allow_unknown_settings:
82
82
  for setting in settings:
@@ -10,8 +10,7 @@ classifier =
10
10
  Intended Audience :: Developers
11
11
  License :: OSI Approved :: GNU General Public License v2 (GPLv2)
12
12
  Programming Language :: Python
13
- Programming Language :: Python :: 3.7
14
- Programming Language :: Python :: 3.8
13
+ Programming Language :: Python :: 3.12
15
14
 
16
15
  [bdist_wheel]
17
16
  universal = 1
@@ -1,4 +1,4 @@
1
- from typing import Callable, Optional
1
+ from typing import Callable
2
2
 
3
3
  from openmodule.models.signals import SignalMessage, TriggerSignalsRequest, TriggerSignalsResponse, \
4
4
  GetSignalValueRequest, GetSignalValueResponse, SignalType
@@ -10,15 +10,15 @@ class SignalSimulator:
10
10
  self.emit = emit
11
11
  self._signals = {}
12
12
 
13
- def add_signal(self, value: bool, additional_data: Optional[dict], signal_type: SignalType,
14
- gate: Optional[str] = None, parking_area_id: Optional[str] = None,
15
- signal_name: Optional[str] = None):
13
+ def add_signal(self, value: bool, additional_data: dict | None, signal_type: SignalType,
14
+ gate: str | None = None, parking_area_id: str | None = None,
15
+ signal_name: str | None = None):
16
16
  if signal_type == SignalType.custom:
17
17
  assert signal_name is not None
18
18
  signal_msg = SignalMessage(signal=signal_name, type=signal_type, gate=gate, parking_area_id=parking_area_id,
19
19
  value=value, additional_data=additional_data)
20
20
  elif signal_type == SignalType.parkinglot_full:
21
- signal_name = "parkinglot_full"
21
+ signal_name = signal_type.value
22
22
  signal_msg = SignalMessage(signal=signal_name, type=signal_type,
23
23
  value=value, additional_data=additional_data)
24
24
  elif signal_type == SignalType.area_full:
@@ -36,7 +36,7 @@ class SignalSimulator:
36
36
  def remove_signal(self, signal: str):
37
37
  self._signals.pop(signal, None)
38
38
 
39
- def set_signal(self, signal: str, value: bool, additional_data: Optional[dict] = None):
39
+ def set_signal(self, signal: str, value: bool, additional_data: dict | None = None):
40
40
  self._signals[signal].value = value
41
41
  self._signals[signal].additional_data = additional_data
42
42
  self.emit(self._signals[signal])
@@ -1,5 +1,5 @@
1
1
  import time
2
- from typing import Optional, Callable, TypeVar
2
+ from typing import Callable, TypeVar
3
3
 
4
4
  T = TypeVar("T")
5
5
  NoTarget = object()
@@ -16,7 +16,7 @@ class DeveloperError(Exception):
16
16
  """
17
17
 
18
18
 
19
- def wait_for_value(getter: Callable[[], Optional[T]], target: Optional[T] = NoTarget, invert_target: bool = False,
19
+ def wait_for_value(getter: Callable[[], T | None], target: T | None = NoTarget, invert_target: bool = False,
20
20
  timeout: float = 3, sleep_time: float = 0.01) -> T:
21
21
  """
22
22
  Waits until the getter returns the target value or the target value.
@@ -10,8 +10,8 @@ import types
10
10
  import warnings
11
11
  from _weakrefset import WeakSet
12
12
  from contextlib import closing
13
- from enum import Enum
14
- from typing import List, Tuple, Optional, Union, Dict, Type, Callable
13
+ from enum import StrEnum
14
+ from typing import Callable
15
15
  from unittest import TestCase
16
16
  from uuid import uuid4, UUID
17
17
 
@@ -141,7 +141,7 @@ class TestClient(threading.Thread):
141
141
 
142
142
  _command_topic: str
143
143
  subscribed_topics: set
144
- pending_topics: Dict[str, None]
144
+ pending_topics: dict[str, None]
145
145
  zmq_dispatcher: SubscribingMessageDispatcher
146
146
 
147
147
  pub: zmq.Socket = None
@@ -251,7 +251,7 @@ class TestClient(threading.Thread):
251
251
 
252
252
  if isinstance(_message, BaseModel):
253
253
  with self.send_lock:
254
- self.pub.send_multipart((topic.encode("utf8"), orjson.dumps(_message.dict())))
254
+ self.pub.send_multipart((topic.encode("utf8"), orjson.dumps(_message.model_dump())))
255
255
  else:
256
256
  assert not (_message and kwargs), (
257
257
  "pass the message dict as the first parameter, or use the kwargs, not both"
@@ -270,7 +270,7 @@ class TestClient(threading.Thread):
270
270
  self.has_messages.clear()
271
271
  return msg
272
272
 
273
- def wait_for_message(self, filter: Callable[[str, dict], bool], timeout=3) -> Tuple[str, dict]:
273
+ def wait_for_message(self, filter: Callable[[str, dict], bool], timeout=3) -> tuple[str, dict]:
274
274
  """
275
275
  :param filter: filter function of type (topic: str, message: dict) -> bool
276
276
  :return: tuple containing [topic, message]
@@ -323,7 +323,7 @@ class TestClient(threading.Thread):
323
323
  self.join()
324
324
 
325
325
 
326
- def fake_config(broker: Optional[TestBroker] = None, **kwargs):
326
+ def fake_config(broker: TestBroker | None = None, **kwargs):
327
327
  result = {
328
328
  "NAME": "test",
329
329
  "RESOURCE": "test-resource",
@@ -357,11 +357,11 @@ class _TestRPCRequest(BaseModel):
357
357
  we do not want to depend on openmodule, this is a minimal version of the zmq message for the rpc function
358
358
  """
359
359
  timestamp: float = Field(default_factory=time.time)
360
- resource: Optional[str] = None
360
+ resource: str | None = None
361
361
  name: str
362
362
  type: str
363
363
  rpc_id: UUID
364
- request: Optional[Dict]
364
+ request: dict | None = None
365
365
 
366
366
  def __init__(self, **kwargs):
367
367
  resource = kwargs.pop("resource")
@@ -372,14 +372,14 @@ class _TestRPCRequest(BaseModel):
372
372
  super().__init__(resource=resource, **kwargs)
373
373
 
374
374
 
375
- class ZMQProcotol(str, Enum):
375
+ class ZMQProcotol(StrEnum):
376
376
  inproc = "inproc://"
377
377
  tcp = "tcp://"
378
378
 
379
379
 
380
380
  class ZMQTestMixin(TestCase):
381
- topics: List[str] = []
382
- rpc_channels: List[str] = []
381
+ topics: list[str] = []
382
+ rpc_channels: list[str] = []
383
383
  protocol: ZMQProcotol = "inproc://"
384
384
 
385
385
  zmq_broker: TestBroker = None
@@ -433,7 +433,7 @@ class ZMQTestMixin(TestCase):
433
433
  and if it is connected, all previous subscriptions will also be connected
434
434
  """
435
435
  random_topic = "_test" + "".join(random.choices(string.ascii_letters, k=10))
436
- dispatcher.register_handler(random_topic, BaseModel, handler, register_schema=False, match_type=False)
436
+ dispatcher.register_handler(random_topic, OpenModuleModel, handler, register_schema=False, match_type=False)
437
437
 
438
438
  for _ in range(self.zmq_client.startup_check_iterations):
439
439
  self.zmq_client.send(random_topic, {"type": "connection-check"})
@@ -471,25 +471,27 @@ class ZMQTestMixin(TestCase):
471
471
  super(ZMQTestMixin, self).tearDown()
472
472
  Schema.to_file()
473
473
 
474
- def rpc(self, channel: str, type: str, request, response_type: Type[OpenModuleModel], timeout=3, resource=None) \
475
- -> Union[str, OpenModuleModel]:
474
+ def rpc(self, channel: str, type: str, request, response_type: type[OpenModuleModel], timeout=3, resource=None) \
475
+ -> str | OpenModuleModel:
476
476
  """
477
477
  :return: the rpc response as parsed model
478
478
  """
479
479
  rpc_id = self.rpc_no_response(channel, type, request, resource)
480
480
  return self.receive_rpc_response(channel, rpc_id, response_type, timeout=timeout)
481
481
 
482
- def rpc_no_response(self, channel: str, type: str, request, resource=None):
482
+ def rpc_no_response(self, channel: str, type_: str, request, resource=None):
483
483
  """
484
484
  :return: the rpc id, which can be used with `receive_rpc` to receive the response async
485
485
  """
486
486
  rpc_id = str(uuid4())
487
- rpc_request = _TestRPCRequest(name="testclient", type=type, rpc_id=rpc_id,
487
+ if isinstance(request, BaseModel):
488
+ request = request.model_dump()
489
+ rpc_request = _TestRPCRequest(name="testclient", type=type_, rpc_id=rpc_id,
488
490
  resource=resource, request=request)
489
491
  self.zmq_client.send(f"rpc-req-{channel}", rpc_request)
490
492
  return rpc_id
491
493
 
492
- def receive_rpc_response(self, channel: str, rpc_id: str, response_type: Type[OpenModuleModel], timeout=3) \
494
+ def receive_rpc_response(self, channel: str, rpc_id: str, response_type: type[OpenModuleModel], timeout=3) \
493
495
  -> OpenModuleModel:
494
496
  response_topic = f"rpc-rep-{channel}"
495
497
  if response_topic not in self.zmq_client.subscribed_topics:
@@ -1,11 +0,0 @@
1
- Bernhard Lippe <b.lippe@arivo.co>
2
- Kevin Koller <k.koller@accessio.at>
3
- Kevin Koller <k.koller@arivo.co>
4
- Matthias Mietschnig <m.mietschnig@arivo.co>
5
- Maximilian Bialek <m.bialek@arivo.co>
6
- Philipp Reitter <i@philipp.ninja>
7
- Philipp Reitter <p.reitter@accessio.at>
8
- Philipp Reitter <p.reitter@gmail.com>
9
- Stefan Bräuer <s.braeuer@arivo.co>
10
- Thomas Senfter <t.senfter@accessio.at>
11
- Thomas Senfter <t.senfter@arivo.co>
@@ -1,217 +0,0 @@
1
- CHANGES
2
- =======
3
-
4
- v14.2.0
5
- -------
6
-
7
- * OM-1001: CostEntryData from settings models, added valid\_from and valid\_to to AccessCheckAccess and type hints for io/signals and io/inputs settings
8
- * docs
9
- * fixed testcase
10
- * maybe fixing openmodule\_test
11
-
12
- v14.2.0.rc0
13
- -----------
14
-
15
- * improvements for signal simulator
16
- * test util for signals
17
- * fixed testcase
18
- * added SignalListener
19
-
20
- v14.1.1
21
- -------
22
-
23
- * OM-1000: added --library flag for openmodule commands so "\_\_READABLE\_NAME" and "\_\_DESCRIPTION" are not added there
24
-
25
- v14.1.0
26
- -------
27
-
28
- * newer settings-models (non-breaking)
29
- * OM-901 Python 12 Support
30
-
31
- v14.0.4
32
- -------
33
-
34
- * OM-945 Fix Trace parent in ZMQMessage
35
-
36
- v14.0.3
37
- -------
38
-
39
- * OM-941 Sentry Bugfix
40
-
41
- v14.0.2
42
- -------
43
-
44
- * Sentry improvements
45
-
46
- v14.0.1
47
- -------
48
-
49
- * fixed sentry release name
50
-
51
- v14.0.0
52
- -------
53
-
54
- * Add breaking changes to docs
55
- * OM-693 Openmodule sentry v2
56
- * Update known\_issues.md [skip ci]
57
-
58
- v13.6.0
59
- -------
60
-
61
- * OM-697 OpenModule Verbesserungen
62
-
63
- v13.5.0
64
- -------
65
-
66
- * document breaking changes
67
- * OM-405: remove database imports from non-database services + isolate migration process to exclude alembic import in the main process
68
-
69
- v13.4.0
70
- -------
71
-
72
- * Om 164: settings-models update for enforcment settings changes
73
-
74
- v13.3.0
75
- -------
76
-
77
- * [OM-359] cleanup helper function
78
-
79
- v13.2.0
80
- -------
81
-
82
- * OM 187 Alembic migration test mixin
83
- * add a testcase for expiring session data while adding new models (noticed in OM-327)
84
- * OM-184 Openmodule Database: Migration Backups and Fix in Operations "pre\_downgrade()" and "post\_downgrade()"
85
- * Aktualisierung der Dokumentation
86
- * OM-255
87
-
88
- v13.1.4
89
- -------
90
-
91
- * fixed missing leave time in got better vehicle fake leave
92
-
93
- v13.1.3
94
- -------
95
-
96
- * [OM-134] small changes in AccessCheck Models
97
-
98
- v13.1.2
99
- -------
100
-
101
- * [OM-117] fixed error output on RPCs not sent by this RPCClient
102
-
103
- v13.1.1
104
- -------
105
-
106
- * fixed bugs in edge cases in PresenceListener
107
-
108
- v13.1.0
109
- -------
110
-
111
- * fixed testcase race condition
112
- * improvements for PresenceSimulator and new commit to fix pipeline
113
-
114
- v13.1.0.rc1
115
- -----------
116
-
117
- * settings model update
118
-
119
- v13.1.0.rc0
120
- -----------
121
-
122
- * OM-61 Openmodule Anpassungen für Access Events
123
- * [OM-56] added enter\_time and leave\_time to vehicle and implemented presence message changes
124
- * fixes and refactoring of presencelistener
125
- * Resolve OM-78 improved KVStore performance
126
- * fixes INBOX-2510
127
-
128
- v13.0.3
129
- -------
130
-
131
- * added garage\_settings mode "barrier\_bypass" in settings models removal of some unused imports
132
-
133
- v13.0.2
134
- -------
135
-
136
- * added vehicle\_id to AccessCheckRequest removed unused code (AccessServiceWithSessions, AccessTime) fix in docs
137
-
138
- v13.0.1
139
- -------
140
-
141
- * DEV-6522 Quick Task: Refactor für KVStore Update
142
-
143
- v13.0.0
144
- -------
145
-
146
- * DEV-6382 KVSync Änderungen für mehrere Datenbank Models und DEV-6432 Access Service Anpassungen
147
-
148
- v12.1.5
149
- -------
150
-
151
- * fixed crash when receiving broken messages
152
-
153
- v12.1.4
154
- -------
155
-
156
- * fixed bug in presence listener with delayed forward and backward messages
157
- * removed invalid volumn check from column rendering, because base.meta is sufficient
158
- * fixed bug in the csv export documentation
159
-
160
- v12.1.3
161
- -------
162
-
163
- * docs
164
- * use hashlib to compute hash
165
-
166
- v12.1.2
167
- -------
168
-
169
- * databox changed to rpc\_no\_blocking -> no exceptions and no waiting added immediate\_callbacks to MockRPCClient
170
-
171
- v12.1.1
172
- -------
173
-
174
- * trigger requirements update for changes in settings-models
175
- * docs and additional assertion in databox upload function
176
-
177
- v12.1.0
178
- -------
179
-
180
- * additional test cases for export\_iterator
181
- * first version of export iterator
182
-
183
- v12.0.0
184
- -------
185
-
186
- * SettingsProvider rework and small changes
187
- * docs update
188
- * settings model 1.0
189
- * small fix in test utils
190
-
191
- v12.0.0.rc1
192
- -----------
193
-
194
- * removed debug entries from kv store removed cost\_entries from AccessCheckAccess
195
-
196
- v12.0.0.rc0
197
- -----------
198
-
199
- * Removed parking\_area\_id from AccessCheckAccess changed gate permission check in AccessService to new behavior
200
-
201
- v11.1.1
202
- -------
203
-
204
- * added state parameter to VehicleBuilder.lpr function
205
-
206
- v11.1.0
207
- -------
208
-
209
- * csv export library, databox upload and schedule library tips
210
- * removed mock rpcs from schema
211
-
212
- v11.0.3
213
- -------
214
-
215
- * Fixed typo, added compute\_id as label to all metrics, convert all label values to string
216
- * touch to get rid of skip ci on my commit
217
- * docs update [skip ci]
@@ -1 +0,0 @@
1
- {"git_version": "3b899ae", "is_release": true}
@@ -1,2 +0,0 @@
1
- multiprocessing_logging
2
- freezegun