libres 0.7.2__py3-none-any.whl → 0.8.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.
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import sedate
2
4
 
3
5
  from datetime import datetime, timedelta, time
@@ -24,9 +26,12 @@ from libres.modules.rasterizer import (
24
26
  )
25
27
 
26
28
 
27
- import typing as _t
28
- if _t.TYPE_CHECKING:
29
+ from typing import Any
30
+ from typing import TypeVar
31
+ from typing import TYPE_CHECKING
32
+ if TYPE_CHECKING:
29
33
  import uuid
34
+ from collections.abc import Iterator
30
35
  from sedate.types import TzInfoOrName
31
36
  from sqlalchemy.orm import Query
32
37
  from typing_extensions import Self
@@ -34,8 +39,8 @@ if _t.TYPE_CHECKING:
34
39
  from libres.db.models import Reservation, ReservedSlot
35
40
  from libres.modules.rasterizer import Raster
36
41
 
37
- _OptDT1 = _t.TypeVar('_OptDT1', _t.Optional[datetime], datetime, None)
38
- _OptDT2 = _t.TypeVar('_OptDT2', _t.Optional[datetime], datetime, None)
42
+ _OptDT1 = TypeVar('_OptDT1', 'datetime | None', datetime, None)
43
+ _OptDT2 = TypeVar('_OptDT2', 'datetime | None', datetime, None)
39
44
 
40
45
 
41
46
  class Allocation(TimestampMixin, ORMBase, OtherModels):
@@ -63,7 +68,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
63
68
  __tablename__ = 'allocations'
64
69
 
65
70
  #: the id of the allocation, autoincremented
66
- id: 'Column[int]' = Column(
71
+ id: Column[int] = Column(
67
72
  types.Integer(),
68
73
  primary_key=True,
69
74
  autoincrement=True
@@ -71,27 +76,27 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
71
76
 
72
77
  #: the resource uuid of the allocation, may not be an actual resource
73
78
  #: see :class:`.models.Allocation` for more information
74
- resource: 'Column[uuid.UUID]' = Column(UUID(), nullable=False)
79
+ resource: Column[uuid.UUID] = Column(UUID(), nullable=False)
75
80
 
76
81
  #: the polymorphic type of the allocation
77
- type: 'Column[_t.Optional[str]]' = Column(types.Text(), nullable=True)
82
+ type: Column[str | None] = Column(types.Text(), nullable=True)
78
83
 
79
84
  #: resource of which this allocation is a mirror. If the mirror_of
80
85
  #: attribute equals the resource, this is a real resource
81
86
  #: see :class:`.models.Allocation` for more information
82
- mirror_of: 'Column[uuid.UUID]' = Column(UUID(), nullable=False)
87
+ mirror_of: Column[uuid.UUID] = Column(UUID(), nullable=False)
83
88
 
84
89
  #: Group uuid to which this allocation belongs to. Every allocation has a
85
90
  #: group but some allocations may be the only one in their group.
86
- group: 'Column[uuid.UUID]' = Column(UUID(), nullable=False)
91
+ group: Column[uuid.UUID] = Column(UUID(), nullable=False)
87
92
 
88
93
  #: Number of times this allocation may be reserved
89
94
  # FIXME: Why is this not nullable=False? For now we pretend that it is
90
- quota: 'Column[int]' = Column(types.Integer(), default=1)
95
+ quota: Column[int] = Column(types.Integer(), default=1)
91
96
 
92
97
  #: Maximum number of times this allocation may be reserved with one
93
98
  #: single reservation.
94
- quota_limit: 'Column[int]' = Column(
99
+ quota_limit: Column[int] = Column(
95
100
  types.Integer(),
96
101
  default=0,
97
102
  nullable=False
@@ -99,37 +104,37 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
99
104
 
100
105
  #: Partly available allocations may be reserved partially. How They may
101
106
  #: be partitioned is defined by the allocation's raster.
102
- partly_available: 'Column[bool]' = Column(types.Boolean(), default=False)
107
+ partly_available: Column[bool] = Column(types.Boolean(), default=False)
103
108
 
104
109
  #: True if reservations for this allocation must be approved manually.
105
- approve_manually: 'Column[bool]' = Column(types.Boolean(), default=False)
110
+ approve_manually: Column[bool] = Column(types.Boolean(), default=False)
106
111
 
107
112
  #: The timezone this allocation resides in.
108
113
  # FIXME: Why is this not nullable=False? A lot of properties rely on this!
109
- timezone: 'Column[_t.Optional[str]]' = Column(types.String())
114
+ timezone: Column[str | None] = Column(types.String())
110
115
 
111
116
  #: Custom data reserved for the user
112
- data: 'Column[_t.Optional[_t.Any]]' = Column(
117
+ data: Column[Any | None] = Column(
113
118
  JSON(),
114
119
  nullable=True
115
120
  )
116
121
 
117
- _start: 'Column[datetime]' = Column(
122
+ _start: Column[datetime] = Column(
118
123
  UTCDateTime(timezone=False),
119
124
  nullable=False
120
125
  )
121
- _end: 'Column[datetime]' = Column(
126
+ _end: Column[datetime] = Column(
122
127
  UTCDateTime(timezone=False),
123
128
  nullable=False
124
129
  )
125
- _raster: 'Column[Raster]' = Column(
130
+ _raster: Column[Raster] = Column(
126
131
  types.Integer(), # type:ignore[arg-type]
127
132
  nullable=False
128
133
  )
129
134
 
130
- if _t.TYPE_CHECKING:
135
+ if TYPE_CHECKING:
131
136
  # forward declare backref
132
- reserved_slots: _t.List[ReservedSlot]
137
+ reserved_slots: list[ReservedSlot]
133
138
 
134
139
  __table_args__ = (
135
140
  Index('mirror_resource_ix', 'mirror_of', 'resource'),
@@ -149,7 +154,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
149
154
  def __hash__(self) -> int:
150
155
  return id(self)
151
156
 
152
- def copy(self) -> 'Self':
157
+ def copy(self) -> Self:
153
158
  """ Creates a new copy of this allocation. """
154
159
  allocation = self.__class__()
155
160
  allocation.resource = self.resource
@@ -180,7 +185,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
180
185
 
181
186
  #: The start of this allocation. Must be timezone aware.
182
187
  #: This date is rastered by the allocation's raster.
183
- if _t.TYPE_CHECKING:
188
+ if TYPE_CHECKING:
184
189
  # NOTE: type checkers perform some special sauce for property
185
190
  # so the non-decorator style isn't well supported
186
191
  @property
@@ -209,7 +214,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
209
214
  #: to avoid overlaps with other allocations.
210
215
  #: That is to say an allocation that ends at 15:00 really ends at
211
216
  #: 14:59:59.999999
212
- if _t.TYPE_CHECKING:
217
+ if TYPE_CHECKING:
213
218
  # NOTE: type checkers perform some special sauce for property
214
219
  # so the non-decorator style isn't well supported
215
220
  @property
@@ -219,10 +224,10 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
219
224
  else:
220
225
  end = property(get_end, set_end)
221
226
 
222
- def get_raster(self) -> 'Raster':
227
+ def get_raster(self) -> Raster:
223
228
  return self._raster
224
229
 
225
- def set_raster(self, raster: 'Raster') -> None:
230
+ def set_raster(self, raster: Raster) -> None:
226
231
  # the raster can only be set once!
227
232
  assert not self._raster
228
233
  self._raster = raster # type:ignore[unreachable]
@@ -239,7 +244,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
239
244
  if self._end:
240
245
  self._end = rasterize_end(self._end, self.raster)
241
246
 
242
- if _t.TYPE_CHECKING:
247
+ if TYPE_CHECKING:
243
248
  # NOTE: type checkers perform some special sauce for property
244
249
  # so the non-decorator style isn't well supported
245
250
  @property
@@ -251,7 +256,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
251
256
 
252
257
  def display_start(
253
258
  self,
254
- timezone: _t.Optional['TzInfoOrName'] = None
259
+ timezone: TzInfoOrName | None = None
255
260
  ) -> datetime:
256
261
  """Returns the start in either the timezone given or the timezone
257
262
  on the allocation."""
@@ -263,7 +268,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
263
268
 
264
269
  def display_end(
265
270
  self,
266
- timezone: _t.Optional['TzInfoOrName'] = None
271
+ timezone: TzInfoOrName | None = None
267
272
  ) -> datetime:
268
273
  """Returns the end plus one microsecond in either the timezone given
269
274
  or the timezone on the allocation.
@@ -278,9 +283,9 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
278
283
 
279
284
  def _prepare_range(
280
285
  self,
281
- start: '_OptDT1',
282
- end: '_OptDT2'
283
- ) -> _t.Tuple['_OptDT1', '_OptDT2']:
286
+ start: _OptDT1,
287
+ end: _OptDT2
288
+ ) -> tuple[_OptDT1, _OptDT2]:
284
289
 
285
290
  if start:
286
291
  assert self.timezone is not None
@@ -328,9 +333,9 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
328
333
 
329
334
  def free_slots(
330
335
  self,
331
- start: _t.Optional[datetime] = None,
332
- end: _t.Optional[datetime] = None
333
- ) -> _t.List[_t.Tuple[datetime, datetime]]:
336
+ start: datetime | None = None,
337
+ end: datetime | None = None
338
+ ) -> list[tuple[datetime, datetime]]:
334
339
  """ Returns the slots which are not yet reserved. """
335
340
  reserved = {slot.start for slot in self.reserved_slots}
336
341
 
@@ -342,9 +347,9 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
342
347
 
343
348
  def align_dates(
344
349
  self,
345
- start: _t.Optional[datetime] = None,
346
- end: _t.Optional[datetime] = None
347
- ) -> _t.Tuple[datetime, datetime]:
350
+ start: datetime | None = None,
351
+ end: datetime | None = None
352
+ ) -> tuple[datetime, datetime]:
348
353
  """ Aligns the given dates to the start and end date of the allocation.
349
354
 
350
355
  """
@@ -361,9 +366,9 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
361
366
 
362
367
  def all_slots(
363
368
  self,
364
- start: _t.Optional[datetime] = None,
365
- end: _t.Optional[datetime] = None
366
- ) -> '_t.Iterator[_t.Tuple[datetime, datetime]]':
369
+ start: datetime | None = None,
370
+ end: datetime | None = None
371
+ ) -> Iterator[tuple[datetime, datetime]]:
367
372
  """ Returns the slots which exist with this timespan. Reserved or free.
368
373
 
369
374
  """
@@ -376,8 +381,8 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
376
381
 
377
382
  def count_slots(
378
383
  self,
379
- start: _t.Optional[datetime] = None,
380
- end: _t.Optional[datetime] = None
384
+ start: datetime | None = None,
385
+ end: datetime | None = None
381
386
  ) -> int:
382
387
  """ Returns the number of slots which exist with this timespan.
383
388
  Reserved or free.
@@ -393,8 +398,8 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
393
398
 
394
399
  def is_available(
395
400
  self,
396
- start: _t.Optional[datetime] = None,
397
- end: _t.Optional[datetime] = None
401
+ start: datetime | None = None,
402
+ end: datetime | None = None
398
403
  ) -> bool:
399
404
  """ Returns true if the given daterange is completely available. """
400
405
 
@@ -414,11 +419,11 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
414
419
  self,
415
420
  start: time,
416
421
  end: time,
417
- timezone: _t.Optional['TzInfoOrName'] = None,
422
+ timezone: TzInfoOrName | None = None,
418
423
  is_dst: bool = False,
419
424
  raise_non_existent: bool = False,
420
425
  raise_ambiguous: bool = False
421
- ) -> _t.Tuple[datetime, datetime]:
426
+ ) -> tuple[datetime, datetime]:
422
427
  """ Takes the given timespan and moves the start/end date to
423
428
  the closest reservable slot. So if 10:00 - 11:00 is requested it will
424
429
 
@@ -465,7 +470,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
465
470
  return self.display_start(timezone), self.display_end(timezone)
466
471
 
467
472
  @property
468
- def pending_reservations(self) -> 'Query[Reservation]':
473
+ def pending_reservations(self) -> Query[Reservation]:
469
474
  """ Returns the pending reservations query for this allocation.
470
475
  As the pending reservations target the group and not a specific
471
476
  allocation this function returns the same value for masters and
@@ -476,7 +481,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
476
481
  "Don't call if the allocation does not yet exist"
477
482
  )
478
483
 
479
- Reservation = self.models.Reservation
484
+ Reservation = self.models.Reservation # noqa: N806
480
485
  query = object_session(self).query(Reservation.id)
481
486
  query = query.filter(Reservation.target == self.group)
482
487
  query = query.filter(Reservation.status == 'pending')
@@ -584,7 +589,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
584
589
  self,
585
590
  start: datetime,
586
591
  end: datetime
587
- ) -> _t.Optional['Self ']:
592
+ ) -> Self | None:
588
593
  """ Returns the first free allocation spot amongst the master and the
589
594
  mirrors. Honors the quota set on the master and will only try the
590
595
  master if the quota is set to 1.
@@ -623,10 +628,9 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
623
628
 
624
629
  return True
625
630
 
626
- def normalized_slots(self) -> _t.Iterator[_t.Union[
627
- _t.Tuple[datetime, datetime],
628
- _t.Tuple[None, None]
629
- ]]:
631
+ def normalized_slots(self) -> Iterator[
632
+ tuple[datetime, datetime] | tuple[None, None]
633
+ ]:
630
634
  """Most of the times this will return the same thing as all_slots
631
635
  however for DST timezones it will ensure the transitions days with
632
636
  23 and 25 hours respectively still return 24 hours worth of slots.
@@ -690,7 +694,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
690
694
  def availability_partitions(
691
695
  self,
692
696
  normalize_dst: bool = True
693
- ) -> _t.List[_t.Tuple[float, bool]]:
697
+ ) -> list[tuple[float, bool]]:
694
698
  """Partitions the space between start and end into blocks of either
695
699
  free or reserved time. Each block has a percentage representing the
696
700
  space the block occupies compared to the size of the whole allocation.
@@ -786,7 +790,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
786
790
 
787
791
  return self.resource == self.mirror_of
788
792
 
789
- def get_master(self) -> 'Self':
793
+ def get_master(self) -> Self:
790
794
  if self.is_master:
791
795
  return self
792
796
  else:
@@ -796,7 +800,7 @@ class Allocation(TimestampMixin, ORMBase, OtherModels):
796
800
 
797
801
  return query.one()
798
802
 
799
- def siblings(self, imaginary: bool = True) -> _t.List['Self']:
803
+ def siblings(self, imaginary: bool = True) -> list[Self]:
800
804
  """Returns the master/mirrors group this allocation is part of.
801
805
 
802
806
  If 'imaginary' is true, inexistant mirrors are created on the fly.
libres/db/models/base.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from sqlalchemy.ext import declarative
2
4
 
3
5
  ORMBase = declarative.declarative_base()
libres/db/models/other.py CHANGED
@@ -1,11 +1,16 @@
1
- import typing as _t
2
- if _t.TYPE_CHECKING:
1
+ from __future__ import annotations
2
+
3
+
4
+ from typing import TYPE_CHECKING
5
+ if TYPE_CHECKING:
6
+ from typing import Protocol
7
+
3
8
  import libres.db.models as _models
4
9
 
5
- class _Models(_t.Protocol):
6
- Allocation: _t.Type[_models.Allocation]
7
- ReservedSlot: _t.Type[_models.ReservedSlot]
8
- Reservation: _t.Type[_models.Reservation]
10
+ class _Models(Protocol):
11
+ Allocation: type[_models.Allocation]
12
+ ReservedSlot: type[_models.ReservedSlot]
13
+ Reservation: type[_models.Reservation]
9
14
 
10
15
 
11
16
  models = None
@@ -16,7 +21,7 @@ class OtherModels:
16
21
  classes without causing circular imports. """
17
22
 
18
23
  @property
19
- def models(self) -> '_Models':
24
+ def models(self) -> _Models:
20
25
  global models
21
26
  if not models:
22
27
  # FIXME: libres.db exports ORMBase, do we really
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import sedate
2
4
 
3
5
  from datetime import datetime, timedelta
@@ -13,8 +15,11 @@ from libres.db.models.other import OtherModels
13
15
  from libres.db.models.timestamp import TimestampMixin
14
16
 
15
17
 
16
- import typing as _t
17
- if _t.TYPE_CHECKING:
18
+ from typing import Any
19
+ from typing import Literal
20
+ from typing import NamedTuple
21
+ from typing import TYPE_CHECKING
22
+ if TYPE_CHECKING:
18
23
  import uuid
19
24
  from sedate.types import TzInfoOrName
20
25
  from sqlalchemy.orm import Query
@@ -22,7 +27,7 @@ if _t.TYPE_CHECKING:
22
27
  from libres.db.models import Allocation
23
28
 
24
29
 
25
- class Timespan(_t.NamedTuple):
30
+ class Timespan(NamedTuple):
26
31
  start: datetime
27
32
  end: datetime
28
33
 
@@ -34,23 +39,23 @@ class Reservation(TimestampMixin, ORMBase, OtherModels):
34
39
 
35
40
  __tablename__ = 'reservations'
36
41
 
37
- id: 'Column[int]' = Column(
42
+ id: Column[int] = Column(
38
43
  types.Integer(),
39
44
  primary_key=True,
40
45
  autoincrement=True
41
46
  )
42
47
 
43
- token: 'Column[uuid.UUID]' = Column(
48
+ token: Column[uuid.UUID] = Column(
44
49
  UUID(),
45
50
  nullable=False,
46
51
  )
47
52
 
48
- target: 'Column[uuid.UUID]' = Column(
53
+ target: Column[uuid.UUID] = Column(
49
54
  UUID(),
50
55
  nullable=False,
51
56
  )
52
57
 
53
- target_type: 'Column[_t.Literal["group", "allocation"]]' = Column(
58
+ target_type: Column[Literal['group', 'allocation']] = Column(
54
59
  types.Enum( # type:ignore[arg-type]
55
60
  'group', 'allocation',
56
61
  name='reservation_target_type'
@@ -58,56 +63,56 @@ class Reservation(TimestampMixin, ORMBase, OtherModels):
58
63
  nullable=False
59
64
  )
60
65
 
61
- type: 'Column[_t.Optional[str]]' = Column(
66
+ type: Column[str | None] = Column(
62
67
  types.Text(),
63
68
  nullable=True
64
69
  )
65
70
 
66
- resource: 'Column[uuid.UUID]' = Column(
71
+ resource: Column[uuid.UUID] = Column(
67
72
  UUID(),
68
73
  nullable=False
69
74
  )
70
75
 
71
- start: 'Column[_t.Optional[datetime]]' = Column(
76
+ start: Column[datetime | None] = Column(
72
77
  UTCDateTime(timezone=False),
73
78
  nullable=True
74
79
  )
75
80
 
76
- end: 'Column[_t.Optional[datetime]]' = Column(
81
+ end: Column[datetime | None] = Column(
77
82
  UTCDateTime(timezone=False),
78
83
  nullable=True
79
84
  )
80
85
 
81
- timezone: 'Column[_t.Optional[str]]' = Column(
86
+ timezone: Column[str | None] = Column(
82
87
  types.String(),
83
88
  nullable=True
84
89
  )
85
90
 
86
- status: 'Column[_t.Literal["pending", "approved"]]' = Column(
91
+ status: Column[Literal['pending', 'approved']] = Column(
87
92
  types.Enum( # type:ignore[arg-type]
88
93
  'pending', 'approved',
89
- name="reservation_status"
94
+ name='reservation_status'
90
95
  ),
91
96
  nullable=False
92
97
  )
93
98
 
94
- data: 'Column[_t.Optional[_t.Any]]' = deferred(
99
+ data: Column[Any | None] = deferred(
95
100
  Column(
96
101
  JSON(),
97
102
  nullable=True
98
103
  )
99
104
  )
100
105
 
101
- email: 'Column[str]' = Column(
106
+ email: Column[str] = Column(
102
107
  types.Unicode(254),
103
108
  nullable=False
104
109
  )
105
110
 
106
- session_id: 'Column[_t.Optional[uuid.UUID]]' = Column(
111
+ session_id: Column[uuid.UUID | None] = Column(
107
112
  UUID()
108
113
  )
109
114
 
110
- quota: 'Column[int]' = Column(
115
+ quota: Column[int] = Column(
111
116
  types.Integer(),
112
117
  nullable=False
113
118
  )
@@ -121,7 +126,7 @@ class Reservation(TimestampMixin, ORMBase, OtherModels):
121
126
  'polymorphic_on': type
122
127
  }
123
128
 
124
- def _target_allocations(self) -> 'Query[Allocation]':
129
+ def _target_allocations(self) -> Query[Allocation]:
125
130
  """ Returns the allocations this reservation is targeting. This should
126
131
  NOT be confused with db.allocations_by_reservation. The method in
127
132
  the db module returns the actual allocations belonging to an approved
@@ -133,7 +138,7 @@ class Reservation(TimestampMixin, ORMBase, OtherModels):
133
138
  be dangerous.
134
139
 
135
140
  """
136
- Allocation = self.models.Allocation
141
+ Allocation = self.models.Allocation # noqa: N806
137
142
  query = object_session(self).query(Allocation)
138
143
  query = query.filter(Allocation.group == self.target)
139
144
 
@@ -147,7 +152,7 @@ class Reservation(TimestampMixin, ORMBase, OtherModels):
147
152
 
148
153
  def display_start(
149
154
  self,
150
- timezone: _t.Optional['TzInfoOrName'] = None
155
+ timezone: TzInfoOrName | None = None
151
156
  ) -> datetime:
152
157
  """Does nothing but to form a nice pair to display_end."""
153
158
  assert self.start is not None
@@ -158,7 +163,7 @@ class Reservation(TimestampMixin, ORMBase, OtherModels):
158
163
 
159
164
  def display_end(
160
165
  self,
161
- timezone: _t.Optional['TzInfoOrName'] = None
166
+ timezone: TzInfoOrName | None = None
162
167
  ) -> datetime:
163
168
  """Returns the end plus one microsecond (nicer display)."""
164
169
  assert self.end is not None
@@ -169,7 +174,7 @@ class Reservation(TimestampMixin, ORMBase, OtherModels):
169
174
  end = self.end + timedelta(microseconds=1)
170
175
  return sedate.to_timezone(end, timezone)
171
176
 
172
- def timespans(self) -> _t.List[Timespan]:
177
+ def timespans(self) -> list[Timespan]:
173
178
  """ Returns the timespans targeted by this reservation.
174
179
 
175
180
  The result is a list of :class:`~libres.db.models.reservation.Timespan`
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import sedate
2
4
 
3
5
  from datetime import datetime, timedelta
@@ -18,8 +20,8 @@ from libres.db.models.types import UUID, UTCDateTime
18
20
  from libres.db.models.timestamp import TimestampMixin
19
21
 
20
22
 
21
- import typing as _t
22
- if _t.TYPE_CHECKING:
23
+ from typing import TYPE_CHECKING
24
+ if TYPE_CHECKING:
23
25
  import uuid
24
26
  from sedate.types import TzInfoOrName
25
27
 
@@ -29,32 +31,32 @@ class ReservedSlot(TimestampMixin, ORMBase):
29
31
 
30
32
  __tablename__ = 'reserved_slots'
31
33
 
32
- resource: 'Column[uuid.UUID]' = Column(
34
+ resource: Column[uuid.UUID] = Column(
33
35
  UUID(),
34
36
  primary_key=True,
35
37
  nullable=False,
36
38
  autoincrement=False
37
39
  )
38
40
 
39
- start: 'Column[datetime]' = Column(
41
+ start: Column[datetime] = Column(
40
42
  UTCDateTime(timezone=False),
41
43
  primary_key=True,
42
44
  nullable=False,
43
45
  autoincrement=False
44
46
  )
45
47
 
46
- end: 'Column[datetime]' = Column(
48
+ end: Column[datetime] = Column(
47
49
  UTCDateTime(timezone=False),
48
50
  nullable=False
49
51
  )
50
52
 
51
- allocation_id: 'Column[int]' = Column(
53
+ allocation_id: Column[int] = Column(
52
54
  types.Integer(),
53
55
  ForeignKey(Allocation.id),
54
56
  nullable=False
55
57
  )
56
58
 
57
- allocation: 'relationship[Allocation]' = relationship(
59
+ allocation: relationship[Allocation] = relationship(
58
60
  Allocation,
59
61
  primaryjoin=Allocation.id == allocation_id,
60
62
 
@@ -68,7 +70,7 @@ class ReservedSlot(TimestampMixin, ORMBase):
68
70
  )
69
71
  )
70
72
 
71
- reservation_token: 'Column[uuid.UUID]' = Column(
73
+ reservation_token: Column[uuid.UUID] = Column(
72
74
  UUID(),
73
75
  nullable=False
74
76
  )
@@ -79,7 +81,7 @@ class ReservedSlot(TimestampMixin, ORMBase):
79
81
 
80
82
  def display_start(
81
83
  self,
82
- timezone: _t.Optional['TzInfoOrName'] = None
84
+ timezone: TzInfoOrName | None = None
83
85
  ) -> datetime:
84
86
 
85
87
  if timezone is None:
@@ -91,7 +93,7 @@ class ReservedSlot(TimestampMixin, ORMBase):
91
93
 
92
94
  def display_end(
93
95
  self,
94
- timezone: _t.Optional['TzInfoOrName'] = None
96
+ timezone: TzInfoOrName | None = None
95
97
  ) -> datetime:
96
98
 
97
99
  if timezone is None:
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import sedate
2
4
 
3
5
  from libres.db.models.types import UTCDateTime
@@ -6,8 +8,8 @@ from sqlalchemy.orm import deferred
6
8
  from sqlalchemy.schema import Column
7
9
 
8
10
 
9
- import typing as _t
10
- if _t.TYPE_CHECKING:
11
+ from typing import TYPE_CHECKING
12
+ if TYPE_CHECKING:
11
13
  from datetime import datetime
12
14
 
13
15
 
@@ -22,16 +24,16 @@ class TimestampMixin:
22
24
  """
23
25
 
24
26
  @staticmethod
25
- def timestamp() -> 'datetime':
27
+ def timestamp() -> datetime:
26
28
  return sedate.utcnow()
27
29
 
28
- if _t.TYPE_CHECKING:
30
+ if TYPE_CHECKING:
29
31
  created: Column[datetime]
30
- modified: Column[_t.Optional[datetime]]
32
+ modified: Column[datetime | None]
31
33
 
32
34
  else:
33
35
  @declared_attr
34
- def created(cls) -> 'Column[datetime]':
36
+ def created(cls) -> Column[datetime]:
35
37
  return deferred(
36
38
  Column(
37
39
  UTCDateTime(timezone=False),
@@ -40,7 +42,7 @@ class TimestampMixin:
40
42
  )
41
43
 
42
44
  @declared_attr
43
- def modified(cls) -> 'Column[_t.Optional[datetime]]':
45
+ def modified(cls) -> Column[datetime | None]:
44
46
  return deferred(
45
47
  Column(
46
48
  UTCDateTime(timezone=False),
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from .json_type import JSON
2
4
  from .utcdatetime import UTCDateTime
3
5
  from .uuid_type import UUID