dycw-utilities 0.174.12__py3-none-any.whl → 0.175.31__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.

Potentially problematic release.


This version of dycw-utilities might be problematic. Click here for more details.

utilities/tempfile.py CHANGED
@@ -73,29 +73,62 @@ class _TemporaryDirectoryNoResourceWarning(tempfile.TemporaryDirectory):
73
73
  @contextmanager
74
74
  def TemporaryFile( # noqa: N802
75
75
  *,
76
+ dir: PathLike | None = None, # noqa: A002
76
77
  suffix: str | None = None,
77
78
  prefix: str | None = None,
78
- dir: PathLike | None = None, # noqa: A002
79
79
  ignore_cleanup_errors: bool = False,
80
80
  delete: bool = True,
81
81
  name: str | None = None,
82
+ text: str | None = None,
82
83
  ) -> Iterator[Path]:
83
84
  """Yield a temporary file."""
84
- with TemporaryDirectory(
85
- suffix=suffix,
86
- prefix=prefix,
87
- dir=dir,
88
- ignore_cleanup_errors=ignore_cleanup_errors,
89
- delete=delete,
90
- ) as temp_dir:
91
- temp_file = _NamedTemporaryFile( # noqa: SIM115
92
- dir=temp_dir, delete=delete, delete_on_close=False
93
- )
94
- if name is None:
95
- yield temp_dir / temp_file.name
96
- else:
97
- _ = move(temp_dir / temp_file.name, temp_dir / name)
98
- yield temp_dir / name
85
+ if dir is None:
86
+ with (
87
+ TemporaryDirectory(
88
+ suffix=suffix,
89
+ prefix=prefix,
90
+ dir=dir,
91
+ ignore_cleanup_errors=ignore_cleanup_errors,
92
+ delete=delete,
93
+ ) as temp_dir,
94
+ _temporary_file_outer(
95
+ temp_dir, delete=delete, name=name, text=text
96
+ ) as temp,
97
+ ):
98
+ yield temp
99
+ else:
100
+ with _temporary_file_outer(dir, delete=delete, name=name, text=text) as temp:
101
+ yield temp
102
+
103
+
104
+ @contextmanager
105
+ def _temporary_file_outer(
106
+ path: PathLike,
107
+ /,
108
+ *,
109
+ delete: bool = True,
110
+ name: str | None = None,
111
+ text: str | None = None,
112
+ ) -> Iterator[Path]:
113
+ with _temporary_file_inner(path, delete=delete, name=name) as temp:
114
+ if text is not None:
115
+ _ = temp.write_text(text)
116
+ yield temp
117
+
118
+
119
+ @contextmanager
120
+ def _temporary_file_inner(
121
+ path: PathLike, /, *, delete: bool = True, name: str | None = None
122
+ ) -> Iterator[Path]:
123
+ path = Path(path)
124
+ temp = _NamedTemporaryFile( # noqa: SIM115
125
+ dir=path, delete=delete, delete_on_close=False
126
+ )
127
+ if name is None:
128
+ yield path / temp.name
129
+ else:
130
+ _ = move(path / temp.name, path / name)
131
+ yield path / name
99
132
 
100
133
 
101
134
  ##
utilities/aeventkit.py DELETED
@@ -1,389 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from functools import wraps
5
- from inspect import iscoroutinefunction
6
- from typing import TYPE_CHECKING, Any, Self, assert_never, cast, override
7
-
8
- from eventkit import (
9
- Constant,
10
- Count,
11
- DropWhile,
12
- Enumerate,
13
- Event,
14
- Filter,
15
- Fork,
16
- Iterate,
17
- Map,
18
- Pack,
19
- Partial,
20
- PartialRight,
21
- Pluck,
22
- Skip,
23
- Star,
24
- Take,
25
- TakeUntil,
26
- TakeWhile,
27
- Timestamp,
28
- )
29
-
30
- from utilities.functions import apply_decorators
31
- from utilities.iterables import always_iterable
32
- from utilities.logging import to_logger
33
-
34
- if TYPE_CHECKING:
35
- from collections.abc import Callable
36
-
37
- from utilities.types import Coro, LoggerLike, MaybeCoro, MaybeIterable, TypeLike
38
-
39
-
40
- ##
41
-
42
-
43
- def add_listener[E: Event, F: Callable](
44
- event: E,
45
- listener: Callable[..., MaybeCoro[None]],
46
- /,
47
- *,
48
- error: Callable[[Event, BaseException], MaybeCoro[None]] | None = None,
49
- ignore: TypeLike[BaseException] | None = None,
50
- logger: LoggerLike | None = None,
51
- decorators: MaybeIterable[Callable[[F], F]] | None = None,
52
- done: Callable[..., MaybeCoro[None]] | None = None,
53
- keep_ref: bool = False,
54
- ) -> E:
55
- """Connect a listener to an event."""
56
- lifted = lift_listener(
57
- listener,
58
- event,
59
- error=error,
60
- ignore=ignore,
61
- logger=logger,
62
- decorators=decorators,
63
- )
64
- return cast("E", event.connect(lifted, done=done, keep_ref=keep_ref))
65
-
66
-
67
- ##
68
-
69
-
70
- @dataclass(repr=False, kw_only=True)
71
- class LiftedEvent[F: Callable[..., MaybeCoro[None]]]:
72
- """A lifted version of `Event`."""
73
-
74
- event: Event
75
-
76
- def name(self) -> str:
77
- return self.event.name() # pragma: no cover
78
-
79
- def done(self) -> bool:
80
- return self.event.done() # pragma: no cover
81
-
82
- def set_done(self) -> None:
83
- self.event.set_done() # pragma: no cover
84
-
85
- def value(self) -> Any:
86
- return self.event.value() # pragma: no cover
87
-
88
- def connect[F2: Callable](
89
- self,
90
- listener: F,
91
- /,
92
- *,
93
- error: Callable[[Event, BaseException], MaybeCoro[None]] | None = None,
94
- ignore: TypeLike[BaseException] | None = None,
95
- logger: LoggerLike | None = None,
96
- decorators: MaybeIterable[Callable[[F2], F2]] | None = None,
97
- done: Callable[..., MaybeCoro[None]] | None = None,
98
- keep_ref: bool = False,
99
- ) -> Event:
100
- return add_listener(
101
- self.event,
102
- listener,
103
- error=error,
104
- ignore=ignore,
105
- logger=logger,
106
- decorators=decorators,
107
- done=done,
108
- keep_ref=keep_ref,
109
- )
110
-
111
- def disconnect(
112
- self, listener: Any, /, *, error: Any = None, done: Any = None
113
- ) -> Any:
114
- return self.event.disconnect( # pragma: no cover
115
- listener, error=error, done=done
116
- )
117
-
118
- def disconnect_obj(self, obj: Any, /) -> None:
119
- self.event.disconnect_obj(obj) # pragma: no cover
120
-
121
- def emit(self, *args: Any) -> None:
122
- self.event.emit(*args) # pragma: no cover
123
-
124
- def emit_threadsafe(self, *args: Any) -> None:
125
- self.event.emit_threadsafe(*args) # pragma: no cover
126
-
127
- def clear(self) -> None:
128
- self.event.clear() # pragma: no cover
129
-
130
- def run(self) -> list[Any]:
131
- return self.event.run() # pragma: no cover
132
-
133
- def pipe(self, *targets: Event) -> Event:
134
- return self.event.pipe(*targets) # pragma: no cover
135
-
136
- def fork(self, *targets: Event) -> Fork:
137
- return self.event.fork(*targets) # pragma: no cover
138
-
139
- def set_source(self, source: Any, /) -> None:
140
- self.event.set_source(source) # pragma: no cover
141
-
142
- def _onFinalize(self, ref: Any) -> None: # noqa: N802
143
- self.event._onFinalize(ref) # noqa: SLF001 # pragma: no cover
144
-
145
- async def aiter(self, *, skip_to_last: bool = False, tuples: bool = False) -> Any:
146
- async for i in self.event.aiter( # pragma: no cover
147
- skip_to_last=skip_to_last, tuples=tuples
148
- ):
149
- yield i
150
-
151
- __iadd__ = connect
152
- __isub__ = disconnect
153
- __call__ = emit
154
- __or__ = pipe
155
-
156
- @override
157
- def __repr__(self) -> str:
158
- return self.event.__repr__() # pragma: no cover
159
-
160
- def __len__(self) -> int:
161
- return self.event.__len__() # pragma: no cover
162
-
163
- def __bool__(self) -> bool:
164
- return self.event.__bool__() # pragma: no cover
165
-
166
- def __getitem__(self, fork_targets: Any, /) -> Fork:
167
- return self.event.__getitem__(fork_targets) # pragma: no cover
168
-
169
- def __await__(self) -> Any:
170
- return self.event.__await__() # pragma: no cover
171
-
172
- def __aiter__(self) -> Any:
173
- return self.event.aiter() # pragma: no cover
174
-
175
- def __contains__(self, c: Any, /) -> bool:
176
- return self.event.__contains__(c) # pragma: no cover
177
-
178
- @override
179
- def __reduce__(self) -> Any:
180
- return self.event.__reduce__() # pragma: no cover
181
-
182
- def filter(self, *, predicate: Any = bool) -> Filter:
183
- return self.event.filter(predicate=predicate) # pragma: no cover
184
-
185
- def skip(self, *, count: int = 1) -> Skip:
186
- return self.event.skip(count=count) # pragma: no cover
187
-
188
- def take(self, *, count: int = 1) -> Take:
189
- return self.event.take(count=count) # pragma: no cover
190
-
191
- def takewhile(self, *, predicate: Any = bool) -> TakeWhile:
192
- return self.event.takewhile(predicate=predicate) # pragma: no cover
193
-
194
- def dropwhile(self, *, predicate: Any = lambda x: not x) -> DropWhile: # pyright: ignore[reportUnknownLambdaType]
195
- return self.event.dropwhile(predicate=predicate) # pragma: no cover
196
-
197
- def takeuntil(self, notifier: Event, /) -> TakeUntil:
198
- return self.event.takeuntil(notifier) # pragma: no cover
199
-
200
- def constant(self, constant: Any, /) -> Constant:
201
- return self.event.constant(constant) # pragma: no cover
202
-
203
- def iterate(self, it: Any, /) -> Iterate:
204
- return self.event.iterate(it) # pragma: no cover
205
-
206
- def count(self, *, start: int = 0, step: int = 1) -> Count:
207
- return self.event.count(start=start, step=step) # pragma: no cover
208
-
209
- def enumerate(self, *, start: int = 0, step: int = 1) -> Enumerate:
210
- return self.event.enumerate(start=start, step=step) # pragma: no cover
211
-
212
- def timestamp(self) -> Timestamp:
213
- return self.event.timestamp() # pragma: no cover
214
-
215
- def partial(self, *left_args: Any) -> Partial:
216
- return self.event.partial(*left_args) # pragma: no cover
217
-
218
- def partial_right(self, *right_args: Any) -> PartialRight:
219
- return self.event.partial_right(*right_args) # pragma: no cover
220
-
221
- def star(self) -> Star:
222
- return self.event.star() # pragma: no cover
223
-
224
- def pack(self) -> Pack:
225
- return self.event.pack() # pragma: no cover
226
-
227
- def pluck(self, *selections: int | str) -> Pluck:
228
- return self.event.pluck(*selections) # pragma: no cover
229
-
230
- def map(
231
- self,
232
- func: Any,
233
- /,
234
- *,
235
- timeout: float | None = None,
236
- ordered: bool = True,
237
- task_limit: int | None = None,
238
- ) -> Map:
239
- return self.event.map( # pragma: no cover
240
- func, timeout=timeout, ordered=ordered, task_limit=task_limit
241
- )
242
-
243
-
244
- ##
245
-
246
-
247
- class TypedEvent[F: Callable[..., MaybeCoro[None]]](Event):
248
- """A typed version of `Event`."""
249
-
250
- @override
251
- def connect[F2: Callable](
252
- self,
253
- listener: F,
254
- error: Callable[[Self, BaseException], MaybeCoro[None]] | None = None,
255
- done: Callable[[Self], MaybeCoro[None]] | None = None,
256
- keep_ref: bool = False,
257
- *,
258
- ignore: TypeLike[BaseException] | None = None,
259
- logger: LoggerLike | None = None,
260
- decorators: MaybeIterable[Callable[[F2], F2]] | None = None,
261
- ) -> Self:
262
- lifted = lift_listener(
263
- listener,
264
- self,
265
- error=cast(
266
- "Callable[[Event, BaseException], MaybeCoro[None]] | None", error
267
- ),
268
- ignore=ignore,
269
- logger=logger,
270
- decorators=decorators,
271
- )
272
- return cast(
273
- "Self", super().connect(lifted, error=error, done=done, keep_ref=keep_ref)
274
- )
275
-
276
-
277
- ##
278
-
279
-
280
- def lift_listener[F1: Callable[..., MaybeCoro[None]], F2: Callable](
281
- listener: F1,
282
- event: Event,
283
- /,
284
- *,
285
- error: Callable[[Event, BaseException], MaybeCoro[None]] | None = None,
286
- ignore: TypeLike[BaseException] | None = None,
287
- logger: LoggerLike | None = None,
288
- decorators: MaybeIterable[Callable[[F2], F2]] | None = None,
289
- ) -> F1:
290
- match error, bool(iscoroutinefunction(listener)):
291
- case None, False:
292
- listener_typed = cast("Callable[..., None]", listener)
293
-
294
- @wraps(listener)
295
- def listener_no_error_sync(*args: Any, **kwargs: Any) -> None:
296
- try:
297
- listener_typed(*args, **kwargs)
298
- except Exception as exc: # noqa: BLE001
299
- if (ignore is not None) and isinstance(exc, ignore):
300
- return
301
- to_logger(logger).exception("")
302
-
303
- lifted = listener_no_error_sync
304
-
305
- case None, True:
306
- listener_typed = cast("Callable[..., Coro[None]]", listener)
307
-
308
- @wraps(listener)
309
- async def listener_no_error_async(*args: Any, **kwargs: Any) -> None:
310
- try:
311
- await listener_typed(*args, **kwargs)
312
- except Exception as exc: # noqa: BLE001
313
- if (ignore is not None) and isinstance(exc, ignore):
314
- return
315
- to_logger(logger).exception("")
316
-
317
- lifted = listener_no_error_async
318
- case _, _:
319
- match bool(iscoroutinefunction(listener)), bool(iscoroutinefunction(error)):
320
- case False, False:
321
- listener_typed = cast("Callable[..., None]", listener)
322
- error_typed = cast("Callable[[Event, Exception], None]", error)
323
-
324
- @wraps(listener)
325
- def listener_have_error_sync(*args: Any, **kwargs: Any) -> None:
326
- try:
327
- listener_typed(*args, **kwargs)
328
- except Exception as exc: # noqa: BLE001
329
- if (ignore is not None) and isinstance(exc, ignore):
330
- return
331
- error_typed(event, exc)
332
-
333
- lifted = listener_have_error_sync
334
- case False, True:
335
- listener_typed = cast("Callable[..., None]", listener)
336
- error_typed = cast(
337
- "Callable[[Event, Exception], Coro[None]]", error
338
- )
339
- raise LiftListenerError(listener=listener_typed, error=error_typed)
340
- case True, _:
341
- listener_typed = cast("Callable[..., Coro[None]]", listener)
342
-
343
- @wraps(listener)
344
- async def listener_have_error_async(
345
- *args: Any, **kwargs: Any
346
- ) -> None:
347
- try:
348
- await listener_typed(*args, **kwargs)
349
- except Exception as exc: # noqa: BLE001
350
- if (ignore is not None) and isinstance(exc, ignore):
351
- return None
352
- if iscoroutinefunction(error):
353
- error_typed = cast(
354
- "Callable[[Event, Exception], Coro[None]]", error
355
- )
356
- return await error_typed(event, exc)
357
- error_typed = cast(
358
- "Callable[[Event, Exception], None]", error
359
- )
360
- error_typed(event, exc)
361
-
362
- lifted = listener_have_error_async
363
- case never:
364
- assert_never(never)
365
- case never:
366
- assert_never(never)
367
-
368
- if decorators is not None:
369
- lifted = apply_decorators(lifted, *always_iterable(decorators))
370
- return cast("F1", lifted)
371
-
372
-
373
- @dataclass(kw_only=True, slots=True)
374
- class LiftListenerError(Exception):
375
- listener: Callable[..., None]
376
- error: Callable[[Event, Exception], Coro[None]]
377
-
378
- @override
379
- def __str__(self) -> str:
380
- return f"Synchronous listener {self.listener} cannot be paired with an asynchronous error handler {self.error}"
381
-
382
-
383
- __all__ = [
384
- "LiftListenerError",
385
- "LiftedEvent",
386
- "TypedEvent",
387
- "add_listener",
388
- "lift_listener",
389
- ]