()
| 503 | |
| 504 | |
| 505 | def _concurrent_operation_script() -> str: |
| 506 | return textwrap.dedent( |
| 507 | """ |
| 508 | from __future__ import annotations |
| 509 | |
| 510 | import queue |
| 511 | import sqlite3 |
| 512 | import sys |
| 513 | import threading |
| 514 | |
| 515 | from filelock import ReadWriteLock |
| 516 | |
| 517 | lock_path, operation = sys.argv[1:] |
| 518 | lock = ReadWriteLock(lock_path) |
| 519 | acquisition_inside_connect = threading.Event() |
| 520 | continue_acquisition = threading.Event() |
| 521 | acquire_errors: queue.SimpleQueue[BaseException] = queue.SimpleQueue() |
| 522 | operation_errors: queue.SimpleQueue[BaseException] = queue.SimpleQueue() |
| 523 | armed = True |
| 524 | |
| 525 | from typing import TYPE_CHECKING |
| 526 | |
| 527 | if TYPE_CHECKING: |
| 528 | from _typeshed import Unused |
| 529 | |
| 530 | def audit_hook(event: str, _args: Unused) -> None: |
| 531 | if armed and event == "sqlite3.connect": |
| 532 | acquisition_inside_connect.set() |
| 533 | assert continue_acquisition.wait(5) |
| 534 | |
| 535 | def acquire() -> None: |
| 536 | try: |
| 537 | lock.acquire_write() |
| 538 | except BaseException as error: |
| 539 | acquire_errors.put(error) |
| 540 | |
| 541 | def operate() -> None: |
| 542 | try: |
| 543 | getattr(lock, operation)() |
| 544 | except BaseException as error: |
| 545 | operation_errors.put(error) |
| 546 | |
| 547 | sys.addaudithook(audit_hook) |
| 548 | acquire_thread = threading.Thread(target=acquire) |
| 549 | acquire_thread.start() |
| 550 | assert acquisition_inside_connect.wait(5) |
| 551 | operation_thread = threading.Thread(target=operate) |
| 552 | operation_thread.start() |
| 553 | operation_thread.join(0.1) |
| 554 | assert operation_thread.is_alive() |
| 555 | armed = False |
| 556 | continue_acquisition.set() |
| 557 | acquire_thread.join(5) |
| 558 | operation_thread.join(5) |
| 559 | assert not acquire_thread.is_alive() |
| 560 | assert not operation_thread.is_alive() |
| 561 | assert acquire_errors.empty() |
| 562 | assert operation_errors.empty() |
no outgoing calls
no test coverage detected