Skip to content

Commit ccd4591

Browse files
committed
Wrap logger manipulation around a lock
Just doing it as the standard library does, even if I do not have the proof it is the right thing to do
1 parent a76856a commit ccd4591

File tree

1 file changed

+40
-37
lines changed

1 file changed

+40
-37
lines changed

click_extra/logging.py

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -146,37 +146,39 @@ def extra_basic_config(
146146
Add more parameters for even greater configurability of the logger, by
147147
re-implementing those supported by ``logging.basicConfig``.
148148
"""
149-
# Fetch the logger or create a new one.
150-
logger = logging.getLogger(logger_name)
151-
152-
# Remove and close any existing handlers. Copy of:
153-
# https://github.com/python/cpython/blob/2b5dbd1/Lib/logging/__init__.py#L2028-L2031
154-
if force:
155-
for h in logger.handlers[:]:
156-
logger.removeHandler(h)
157-
h.close()
158-
159-
# If no handlers provided, create a new one with the default handler class.
160-
if not handlers:
161-
handlers = (handler_class(),)
162-
163-
# Set up the formatter with a default message format.
164-
formatter = formatter_class(
165-
fmt=format,
166-
datefmt=datefmt,
167-
style=style,
168-
)
149+
with logging._lock:
150+
# Fetch the logger or create a new one.
151+
logger = logging.getLogger(logger_name)
152+
153+
# Remove and close any existing handlers. Copy of:
154+
# https://github.com/python/cpython/blob/2b5dbd1/Lib/logging/__init__.py#L2028-L2031
155+
# https://loguru.readthedocs.io/en/stable/resources/recipes.html#avoiding-logs-to-be-printed-twice-on-the-terminal
156+
if force:
157+
for h in logger.handlers[:]:
158+
logger.removeHandler(h)
159+
h.close()
160+
161+
# If no handlers provided, create a new one with the default handler class.
162+
if not handlers:
163+
handlers = (handler_class(),)
164+
165+
# Set up the formatter with a default message format.
166+
formatter = formatter_class(
167+
fmt=format,
168+
datefmt=datefmt,
169+
style=style,
170+
)
169171

170-
# Attach handlers to the loggers.
171-
for h in handlers:
172-
if h.formatter is None:
173-
h.setFormatter(formatter)
174-
logger.addHandler(h)
172+
# Attach handlers to the loggers.
173+
for h in handlers:
174+
if h.formatter is None:
175+
h.setFormatter(formatter)
176+
logger.addHandler(h)
175177

176-
if level is not None:
177-
logger.setLevel(level)
178+
if level is not None:
179+
logger.setLevel(level)
178180

179-
return logger
181+
return logger
180182

181183

182184
class VerbosityOption(ExtraOption):
@@ -273,15 +275,16 @@ def __init__(
273275
if not param_decls:
274276
param_decls = ("--verbosity", "-v")
275277

276-
# Use the provided logger instance as-is.
277-
if isinstance(default_logger, Logger):
278-
logger = default_logger
279-
# If a string is provided, use it as the logger name.
280-
elif isinstance(default_logger, str):
281-
logger = logging.getLogger(default_logger)
282-
# ``None`` will produce a default root logger.
283-
else:
284-
logger = extra_basic_config(default_logger)
278+
with logging._lock:
279+
# A logger object has been provided, use it as-is.
280+
if isinstance(default_logger, Logger):
281+
logger = default_logger
282+
# Retrieves the logger object as it is from the registry, if it exists.
283+
elif default_logger in logging.Logger.manager.loggerDict:
284+
logger = logging.getLogger(default_logger)
285+
# Create a new logger with Click Extra's default configuration.
286+
else:
287+
logger = extra_basic_config(default_logger)
285288

286289
# Store the logger name for later use.
287290
self.logger_name = logger.name

0 commit comments

Comments
 (0)