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

Kozea / Radicale / 16388870099

19 Jul 2025 12:51PM UTC coverage: 72.024% (-0.1%) from 72.129%
16388870099

push

github

web-flow
Merge pull request #1825 from pbiering/add-trace-logging-feature

Add trace logging feature

2024 of 2959 branches covered (68.4%)

Branch coverage included in aggregate %.

16 of 31 new or added lines in 4 files covered. (51.61%)

4685 of 6356 relevant lines covered (73.71%)

12.12 hits per line

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

26.53
/radicale/__init__.py
1
# This file is part of Radicale - CalDAV and CardDAV server
2
# Copyright © 2008 Nicolas Kandel
3
# Copyright © 2008 Pascal Halter
4
# Copyright © 2008-2017 Guillaume Ayoub
5
# Copyright © 2017-2022 Unrud <unrud@outlook.com>
6
# Copyright © 2024-2024 Peter Bieringer <pb@bieringer.de>
7
#
8
# This library is free software: you can redistribute it and/or modify
9
# it under the terms of the GNU General Public License as published by
10
# the Free Software Foundation, either version 3 of the License, or
11
# (at your option) any later version.
12
#
13
# This library is distributed in the hope that it will be useful,
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
# GNU General Public License for more details.
17
#
18
# You should have received a copy of the GNU General Public License
19
# along with Radicale.  If not, see <http://www.gnu.org/licenses/>.
20

21
"""
3✔
22
Entry point for external WSGI servers (like uWSGI or Gunicorn).
23

24
Configuration files can be specified in the environment variable
25
``RADICALE_CONFIG``.
26

27
"""
28

29
import os
17✔
30
import threading
17✔
31
from typing import Iterable, Optional, cast
17✔
32

33
from radicale import config, log, types, utils
17✔
34
from radicale.app import Application
17✔
35
from radicale.log import logger
17✔
36

37
VERSION: str = utils.package_version("radicale")
17✔
38

39
_application_instance: Optional[Application] = None
17✔
40
_application_config_path: Optional[str] = None
17✔
41
_application_lock = threading.Lock()
17✔
42

43

44
def _get_application_instance(config_path: str, wsgi_errors: types.ErrorStream
17✔
45
                              ) -> Application:
46
    global _application_instance, _application_config_path
47
    with _application_lock:
×
48
        if _application_instance is None:
×
49
            log.setup()
×
50
            with log.register_stream(wsgi_errors):
×
51
                _application_config_path = config_path
×
52
                configuration = config.load(config.parse_compound_paths(
×
53
                    config.DEFAULT_CONFIG_PATH,
54
                    config_path))
NEW
55
                log.set_level(cast(str, configuration.get("logging", "level")),
×
56
                              configuration.get("logging", "backtrace_on_debug"),
57
                              configuration.get("logging", "trace_on_debug"),
58
                              configuration.get("logging", "trace_filter"))
59
                # Log configuration after logger is configured
60
                default_config_active = True
×
61
                for source, miss in configuration.sources():
×
62
                    logger.info("%s %s", "Skipped missing/unreadable" if miss
×
63
                                else "Loaded", source)
64
                    if not miss and source != "default config":
×
65
                        default_config_active = False
×
66
                if default_config_active:
×
67
                    logger.warning("%s", "No config file found/readable - only default config is active")
×
68
                _application_instance = Application(configuration)
×
69
    if _application_config_path != config_path:
×
70
        raise ValueError("RADICALE_CONFIG must not change: %r != %r" %
×
71
                         (config_path, _application_config_path))
72
    return _application_instance
×
73

74

75
def application(environ: types.WSGIEnviron,
17✔
76
                start_response: types.WSGIStartResponse) -> Iterable[bytes]:
77
    """Entry point for external WSGI servers."""
78
    config_path = environ.get("RADICALE_CONFIG",
×
79
                              os.environ.get("RADICALE_CONFIG"))
80
    app = _get_application_instance(config_path, environ["wsgi.errors"])
×
81
    return app(environ, start_response)
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc