Skip to content

Commit 1310d11

Browse files
authored
Merge pull request #21 from mutating/develop
0.0.19
2 parents feae2af + 8f8d287 commit 1310d11

24 files changed

Lines changed: 131 additions & 128 deletions

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
strategy:
99
matrix:
1010
os: [ubuntu-latest]
11-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
11+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]
1212

1313
steps:
1414
- uses: actions/checkout@v4

.github/workflows/publish.yml

Lines changed: 0 additions & 34 deletions
This file was deleted.

.github/workflows/tests_and_coverage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
strategy:
99
matrix:
1010
os: [ubuntu-latest, windows-latest, macos-latest]
11-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
11+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14", "3.14t"]
1212

1313
steps:
1414
- uses: actions/checkout@v4

.ruff.toml

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
![logo](https://raw.githubusercontent.com/pomponchik/locklib/develop/docs/assets/logo_7.svg)
1+
<details>
2+
<summary>ⓘ</summary>
23

34
[![Downloads](https://static.pepy.tech/badge/locklib/month)](https://pepy.tech/project/locklib)
45
[![Downloads](https://static.pepy.tech/badge/locklib)](https://pepy.tech/project/locklib)
@@ -12,6 +13,14 @@
1213
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
1314
[![DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/pomponchik/locklib)
1415

16+
</details>
17+
18+
<p align="center">
19+
20+
![logo](https://raw.githubusercontent.com/pomponchik/locklib/develop/docs/assets/logo_7.svg)
21+
22+
</p>
23+
1524
It contains several useful additions to the standard thread synchronization tools, such as lock protocols and locks with advanced functionality.
1625

1726

locklib/__init__.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1-
from locklib.locks.smart_lock.lock import SmartLock as SmartLock # noqa: F401
2-
from locklib.errors import DeadLockError as DeadLockError # noqa: F401
3-
from locklib.protocols.lock import LockProtocol as LockProtocol # noqa: F401
4-
from locklib.protocols.context_lock import ContextLockProtocol as ContextLockProtocol # noqa: F401
5-
from locklib.protocols.async_context_lock import AsyncContextLockProtocol as AsyncContextLockProtocol # noqa: F401
6-
from locklib.locks.tracer.tracer import LockTraceWrapper as LockTraceWrapper # noqa: F401
7-
from locklib.errors import StrangeEventOrderError as StrangeEventOrderError # noqa: F401
1+
from locklib.errors import DeadLockError as DeadLockError
2+
from locklib.errors import (
3+
StrangeEventOrderError as StrangeEventOrderError,
4+
)
5+
from locklib.locks.smart_lock.lock import SmartLock as SmartLock
6+
from locklib.locks.tracer.tracer import (
7+
LockTraceWrapper as LockTraceWrapper,
8+
)
9+
from locklib.protocols.async_context_lock import (
10+
AsyncContextLockProtocol as AsyncContextLockProtocol,
11+
)
12+
from locklib.protocols.context_lock import (
13+
ContextLockProtocol as ContextLockProtocol,
14+
)
15+
from locklib.protocols.lock import LockProtocol as LockProtocol

locklib/locks/smart_lock/graph.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from threading import Lock
21
from collections import defaultdict
3-
from typing import List, Set, DefaultDict, Optional
2+
from threading import Lock
3+
from typing import DefaultDict, List, Optional, Set
44

55
from locklib.errors import DeadLockError
66

locklib/locks/smart_lock/lock.py

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
try:
2-
from threading import Lock, get_native_id # type: ignore[attr-defined, unused-ignore]
2+
from threading import ( # type: ignore[attr-defined, unused-ignore]
3+
Lock,
4+
get_native_id,
5+
)
36
except ImportError: # pragma: no cover
4-
from threading import Lock, get_ident as get_native_id # get_native_id is available only since python 3.8
7+
from threading import Lock # get_native_id is available only since python 3.8
8+
from threading import get_ident as get_native_id
59

610
from collections import deque
7-
from typing import Type, Deque, Dict, Optional
811
from types import TracebackType
12+
from typing import Deque, Dict, Optional, Type
913

1014
from locklib.locks.smart_lock.graph import LocksGraph
1115

12-
1316
graph = LocksGraph()
1417

1518
class SmartLock:
@@ -26,40 +29,38 @@ def __exit__(self, exception_type: Optional[Type[BaseException]], exception_valu
2629
self.release()
2730

2831
def acquire(self) -> None:
29-
id = get_native_id()
32+
thread_id = get_native_id()
3033
previous_element_lock = None
3134

32-
with self.lock:
33-
with self.graph.lock:
34-
if not self.deque:
35-
self.deque.appendleft(id)
36-
self.local_locks[id] = Lock()
37-
self.local_locks[id].acquire()
38-
else:
39-
previous_element = self.deque[0]
40-
self.graph.add_link(id, previous_element)
41-
self.deque.appendleft(id)
42-
self.local_locks[id] = Lock()
43-
self.local_locks[id].acquire()
44-
previous_element_lock = self.local_locks[previous_element]
35+
with self.lock, self.graph.lock:
36+
if not self.deque:
37+
self.deque.appendleft(thread_id)
38+
self.local_locks[thread_id] = Lock()
39+
self.local_locks[thread_id].acquire()
40+
else:
41+
previous_element = self.deque[0]
42+
self.graph.add_link(thread_id, previous_element)
43+
self.deque.appendleft(thread_id)
44+
self.local_locks[thread_id] = Lock()
45+
self.local_locks[thread_id].acquire()
46+
previous_element_lock = self.local_locks[previous_element]
4547

4648
if previous_element_lock is not None:
4749
previous_element_lock.acquire()
4850

4951
def release(self) -> None:
50-
id = get_native_id()
52+
thread_id = get_native_id()
5153

52-
with self.lock:
53-
with self.graph.lock:
54-
if id not in self.local_locks:
55-
raise RuntimeError('Release unlocked lock.')
54+
with self.lock, self.graph.lock:
55+
if thread_id not in self.local_locks:
56+
raise RuntimeError('Release unlocked lock.')
5657

57-
self.deque.pop()
58-
lock = self.local_locks[id]
59-
del self.local_locks[id]
58+
self.deque.pop()
59+
lock = self.local_locks[thread_id]
60+
del self.local_locks[thread_id]
6061

61-
if len(self.deque) != 0:
62-
next_element = self.deque[-1]
63-
self.graph.delete_link(next_element, id)
62+
if len(self.deque) != 0:
63+
next_element = self.deque[-1]
64+
self.graph.delete_link(next_element, thread_id)
6465

65-
lock.release()
66+
lock.release()

locklib/locks/tracer/events.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from typing import Optional
2-
from enum import Enum
31
from dataclasses import dataclass
2+
from enum import Enum
3+
from typing import Optional
44

55

66
class TracerEventType(Enum):

locklib/locks/tracer/tracer.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
from typing import List, Dict, Optional, Type
2-
from types import TracebackType
3-
from threading import get_ident
41
from collections import defaultdict
2+
from threading import get_ident
3+
from types import TracebackType
4+
from typing import Dict, List, Optional, Type
55

6-
from locklib.protocols.lock import LockProtocol
7-
from locklib.locks.tracer.events import TracerEvent, TracerEventType
86
from locklib.errors import StrangeEventOrderError
7+
from locklib.locks.tracer.events import TracerEvent, TracerEventType
8+
from locklib.protocols.lock import LockProtocol
99

1010

1111
class LockTraceWrapper:
@@ -25,7 +25,7 @@ def acquire(self) -> None:
2525
TracerEvent(
2626
TracerEventType.ACQUIRE,
2727
thread_id=get_ident(),
28-
)
28+
),
2929
)
3030

3131
def release(self) -> None:
@@ -34,7 +34,7 @@ def release(self) -> None:
3434
TracerEvent(
3535
TracerEventType.RELEASE,
3636
thread_id=get_ident(),
37-
)
37+
),
3838
)
3939

4040
def notify(self, identifier: str) -> None:
@@ -43,7 +43,7 @@ def notify(self, identifier: str) -> None:
4343
TracerEventType.ACTION,
4444
thread_id=get_ident(),
4545
identifier=identifier,
46-
)
46+
),
4747
)
4848

4949
def was_event_locked(self, identifier: str) -> bool:

0 commit comments

Comments
 (0)