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

uw-it-aca / uw-restclients-core / 3961026490

pending completion
3961026490

push

github

GitHub
Merge pull request #104 from uw-it-aca/task/threading-db-connections

251 of 304 branches covered (82.57%)

14 of 14 new or added lines in 1 file covered. (100.0%)

1363 of 1442 relevant lines covered (94.52%)

0.95 hits per line

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

47.46
/restclients_core/thread.py
1
# Copyright 2023 UW-IT, University of Washington
2
# SPDX-License-Identifier: Apache-2.0
3

4
from commonconf import settings
1✔
5
import threading
1✔
6

7
try:
1✔
8
    from django.db import connection as db_connection
1✔
9
except ImportError:
1✔
10
    db_connection = None
1✔
11

12

13
"""
14
This is a wrapper around threading.Thread, but it will only actually thread
15
if django configuration is enabled.  Otherwise, it will be an object with the
16
same api where start() just calls run().
17
"""
18

19

20
class Thread(threading.Thread):
1✔
21
    _use_thread = False
1✔
22
    parent = None
1✔
23

24
    def __init__(self, *args, **kwargs):
1✔
25
        self.parent = threading.currentThread()
1✔
26

27
        if self._db_compatible:
1✔
28
            self._use_thread = not getattr(
1✔
29
                settings, "RESTCLIENTS_DISABLE_THREADING", False)
30

31
        else:
32
            self._use_thread = getattr(
1✔
33
                settings, "RESTCLIENTS_USE_THREADING", False)
34

35
        super().__init__(*args, **kwargs)
1✔
36

37
    @property
1✔
38
    def _db_compatible(self):
1✔
39
        return db_connection is not None and db_connection.vendor != 'sqlite'
1✔
40

41
    def start(self):
1✔
42
        if self._use_thread:
×
43
            super().start()
×
44

45
        else:
46
            # Needed to test failures in the threads.
47
            # But it can't be on all the time - sqlite dbs aren't shared to
48
            # threads.
49
            if getattr(settings, "RESTCLIENTS_USE_INLINE_THREADS", False):
×
50
                super().start()
×
51
                super().join()
×
52
            else:
53
                self.run()
×
54

55
    """
56
    Subclasses should call final() in their overridden run().
57
    """
58
    def run(self):
1✔
59
        # Override to perform specific tasks.
60
        self.final()
×
61

62
    def join(self):
1✔
63
        if self._use_thread:
×
64
            return super().join()
×
65
        return True
×
66

67
    def final(self):
1✔
68
        if (self._use_thread and db_connection is not None and
×
69
                not db_connection.in_atomic_block):
70
            db_connection.close()
×
71

72

73
class GenericPrefetchThread(Thread):
1✔
74
    method = None
1✔
75

76
    def run(self):
1✔
77
        if self.method is not None:
×
78
            try:
×
79
                self.method()
×
80
            except Exception as ex:
×
81
                # Errors in prefetching should also manifest during actual
82
                # processing, where they can be handled appropriately
83
                pass
×
84

85
        self.final()
×
86

87

88
def generic_prefetch(method, args):
1✔
89
    def ret():
×
90
        return method(*args)
×
91
    return ret
×
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