• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LudovicRousseau / pyscard / 17266488819

27 Aug 2025 12:13PM UTC coverage: 64.994% (-1.2%) from 66.181%
17266488819

push

github

LudovicRousseau
ga: remove support of Python 3.9 as the build is bogus on arm64

Thanks to Juho Hovila for the bug report
"Import fails in macos-14 github action runner with python 3.9 #232"
Closes: https://github.com/LudovicRousseau/pyscard/issues/232

106 of 475 branches covered (22.32%)

4066 of 6256 relevant lines covered (64.99%)

4.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.43
/src/smartcard/Synchronization.py
1
"""
2
from Thinking in Python, Bruce Eckel
3
https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Observer.html
4

5
(c) Copyright 2008, Creative Commons Attribution-Share Alike 3.0.
6

7
Simple emulation of Java's 'synchronized'
8
keyword, from Peter Norvig.
9
"""
10

11
from __future__ import annotations
16✔
12

13
import functools
16✔
14
import sys
16✔
15
import threading
16✔
16
from collections.abc import Iterable
16✔
17
from typing import Any, Callable, Protocol, TypeVar
16✔
18

19
# pylint: disable=too-few-public-methods
20

21
if sys.version_info >= (3, 10):
16✔
22
    from typing import ParamSpec
16✔
23
else:
24
    from typing_extensions import ParamSpec
×
25

26

27
T = TypeVar("T")
16✔
28
P = ParamSpec("P")
16✔
29

30

31
def synchronized(method: Callable[P, T]) -> Callable[P, T]:
16✔
32
    """Synchronize methods with the same mutex"""
33

34
    @functools.wraps(method)
16✔
35
    def f(self: _SynchronizationProtocol, *args: Any, **kwargs: Any) -> Any:
16✔
36
        with self.mutex:
15✔
37
            return method(self, *args, **kwargs)
15✔
38

39
    return f
16✔
40

41

42
def synchronize(klass: type, names: str | Iterable[str] | None = None) -> None:
16✔
43
    """Synchronize methods in the given class.
44
    Only synchronize the methods whose names are
45
    given, or all methods if names=None."""
46

47
    if isinstance(names, str):
16✔
48
        names = names.split()
16✔
49
    for name, val in list(klass.__dict__.items()):
16✔
50
        if callable(val) and name != "__init__" and (names is None or name in names):
16✔
51
            setattr(klass, name, synchronized(val))
16✔
52

53

54
class _SynchronizationProtocol(Protocol):
16✔
55
    mutex: threading.Lock | threading.RLock
16✔
56

57

58
class Synchronization(_SynchronizationProtocol):
16✔
59
    """You can create your own self.mutex, or inherit from this class"""
60

61
    def __init__(self):
16✔
62
        self.mutex = threading.RLock()
15✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc