python-json-logger 3.1.0__tar.gz → 3.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. {python_json_logger-3.1.0/src/python_json_logger.egg-info → python_json_logger-3.2.1}/PKG-INFO +9 -10
  2. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/README.md +3 -6
  3. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/pyproject.toml +6 -4
  4. {python_json_logger-3.1.0 → python_json_logger-3.2.1/src/python_json_logger.egg-info}/PKG-INFO +9 -10
  5. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/python_json_logger.egg-info/SOURCES.txt +5 -1
  6. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/python_json_logger.egg-info/requires.txt +8 -1
  7. python_json_logger-3.2.1/src/pythonjsonlogger/__init__.py +17 -0
  8. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/pythonjsonlogger/core.py +11 -4
  9. python_json_logger-3.2.1/src/pythonjsonlogger/exception.py +27 -0
  10. python_json_logger-3.2.1/src/pythonjsonlogger/jsonlogger.py +18 -0
  11. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/pythonjsonlogger/msgspec.py +5 -1
  12. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/pythonjsonlogger/orjson.py +6 -2
  13. python_json_logger-3.2.1/src/pythonjsonlogger/utils.py +40 -0
  14. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/tests/test_deprecation.py +18 -1
  15. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/tests/test_formatters.py +39 -0
  16. python_json_logger-3.2.1/tests/test_missing.py +67 -0
  17. python_json_logger-3.1.0/src/pythonjsonlogger/__init__.py +0 -40
  18. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/LICENSE +0 -0
  19. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/MANIFEST.in +0 -0
  20. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/NOTICE +0 -0
  21. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/setup.cfg +0 -0
  22. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/python_json_logger.egg-info/dependency_links.txt +0 -0
  23. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/python_json_logger.egg-info/top_level.txt +0 -0
  24. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/pythonjsonlogger/defaults.py +0 -0
  25. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/pythonjsonlogger/json.py +0 -0
  26. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/src/pythonjsonlogger/py.typed +0 -0
  27. {python_json_logger-3.1.0 → python_json_logger-3.2.1}/tests/__init__.py +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-json-logger
3
- Version: 3.1.0
3
+ Version: 3.2.1
4
4
  Summary: JSON Log Formatter for the Python Logging Package
5
5
  Author-email: Zakaria Zajac <zak@madzak.com>, Nicholas Hairs <info+python-json-logger@nicholashairs.com>
6
6
  Maintainer-email: Nicholas Hairs <info+python-json-logger@nicholashairs.com>
7
7
  License: BSD-2-Clause License
8
- Project-URL: Homepage, https://nhairs.github.io/python-json-logger/latest/
8
+ Project-URL: Homepage, https://nhairs.github.io/python-json-logger
9
9
  Project-URL: GitHub, https://github.com/nhairs/python-json-logger
10
10
  Classifier: Development Status :: 6 - Mature
11
11
  Classifier: Intended Audience :: Developers
@@ -17,16 +17,18 @@ Classifier: Programming Language :: Python :: 3.9
17
17
  Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
20
21
  Classifier: Topic :: System :: Logging
21
22
  Classifier: Typing :: Typed
22
23
  Requires-Python: >=3.8
23
24
  Description-Content-Type: text/markdown
24
25
  License-File: LICENSE
25
26
  License-File: NOTICE
26
- Requires-Dist: typing_extensions
27
+ Requires-Dist: typing_extensions; python_version < "3.10"
27
28
  Provides-Extra: dev
28
- Requires-Dist: orjson; (implementation_name != "pypy" and python_version < "3.13") and extra == "dev"
29
+ Requires-Dist: orjson; implementation_name != "pypy" and extra == "dev"
29
30
  Requires-Dist: msgspec; (implementation_name != "pypy" and python_version < "3.13") and extra == "dev"
31
+ Requires-Dist: msgspec-python313-pre; (implementation_name != "pypy" and python_version == "3.13") and extra == "dev"
30
32
  Requires-Dist: validate-pyproject[all]; extra == "dev"
31
33
  Requires-Dist: black; extra == "dev"
32
34
  Requires-Dist: pylint; extra == "dev"
@@ -45,9 +47,10 @@ Requires-Dist: mkdocs-gen-files; extra == "dev"
45
47
  Requires-Dist: mkdocs-literate-nav; extra == "dev"
46
48
  Requires-Dist: mike; extra == "dev"
47
49
 
48
- <!-- [![PyPi](https://img.shields.io/pypi/v/python-json-logger.svg)](https://pypi.python.org/pypi/python-json-logger/)
50
+ [![PyPi](https://img.shields.io/pypi/v/python-json-logger.svg)](https://pypi.python.org/pypi/python-json-logger/)
49
51
  [![PyPI - Status](https://img.shields.io/pypi/status/python-json-logger)](https://pypi.python.org/pypi/python-json-logger/)
50
- [![Python Versions](https://img.shields.io/pypi/pyversions/python-json-logger.svg)](https://github.com/nhairs/python-json-logger) -->
52
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/python-json-logger)](https://pypi.python.org/pypi/python-json-logger/)
53
+ [![Python Versions](https://img.shields.io/pypi/pyversions/python-json-logger.svg)](https://github.com/nhairs/python-json-logger)
51
54
  [![License](https://img.shields.io/github/license/nhairs/python-json-logger.svg)](https://github.com/nhairs/python-json-logger)
52
55
  ![Build Status](https://github.com/nhairs/python-json-logger/actions/workflows/test-suite.yml/badge.svg)
53
56
  #
@@ -58,10 +61,6 @@ Python JSON Logger enables you produce JSON logs when using Python's `logging` p
58
61
  JSON logs are machine readable allowing for much easier parsing and ingestion into log aggregation tools.
59
62
 
60
63
 
61
- ### 🚨 Important 🚨
62
-
63
- This repository is a maintained fork of [madzak/python-json-logger](https://github.com/madzak/python-json-logger) pending [a PEP 541 request](https://github.com/pypi/support/issues/3607) for the PyPI package. The future direction of the project is being discussed [here](https://github.com/nhairs/python-json-logger/issues/1).
64
-
65
64
  ## Documentation
66
65
 
67
66
  - [Documentation](https://nhairs.github.io/python-json-logger/latest/)
@@ -1,6 +1,7 @@
1
- <!-- [![PyPi](https://img.shields.io/pypi/v/python-json-logger.svg)](https://pypi.python.org/pypi/python-json-logger/)
1
+ [![PyPi](https://img.shields.io/pypi/v/python-json-logger.svg)](https://pypi.python.org/pypi/python-json-logger/)
2
2
  [![PyPI - Status](https://img.shields.io/pypi/status/python-json-logger)](https://pypi.python.org/pypi/python-json-logger/)
3
- [![Python Versions](https://img.shields.io/pypi/pyversions/python-json-logger.svg)](https://github.com/nhairs/python-json-logger) -->
3
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/python-json-logger)](https://pypi.python.org/pypi/python-json-logger/)
4
+ [![Python Versions](https://img.shields.io/pypi/pyversions/python-json-logger.svg)](https://github.com/nhairs/python-json-logger)
4
5
  [![License](https://img.shields.io/github/license/nhairs/python-json-logger.svg)](https://github.com/nhairs/python-json-logger)
5
6
  ![Build Status](https://github.com/nhairs/python-json-logger/actions/workflows/test-suite.yml/badge.svg)
6
7
  #
@@ -11,10 +12,6 @@ Python JSON Logger enables you produce JSON logs when using Python's `logging` p
11
12
  JSON logs are machine readable allowing for much easier parsing and ingestion into log aggregation tools.
12
13
 
13
14
 
14
- ### 🚨 Important 🚨
15
-
16
- This repository is a maintained fork of [madzak/python-json-logger](https://github.com/madzak/python-json-logger) pending [a PEP 541 request](https://github.com/pypi/support/issues/3607) for the PyPI package. The future direction of the project is being discussed [here](https://github.com/nhairs/python-json-logger/issues/1).
17
-
18
15
  ## Documentation
19
16
 
20
17
  - [Documentation](https://nhairs.github.io/python-json-logger/latest/)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-json-logger"
7
- version = "3.1.0"
7
+ version = "3.2.1"
8
8
  description = "JSON Log Formatter for the Python Logging Package"
9
9
  authors = [
10
10
  {name = "Zakaria Zajac", email = "zak@madzak.com"},
@@ -17,7 +17,7 @@ maintainers = [
17
17
  # Dependency Information
18
18
  requires-python = ">=3.8"
19
19
  dependencies = [
20
- "typing_extensions",
20
+ "typing_extensions;python_version<'3.10'",
21
21
  ]
22
22
 
23
23
  # Extra information
@@ -34,19 +34,21 @@ classifiers = [
34
34
  "Programming Language :: Python :: 3.10",
35
35
  "Programming Language :: Python :: 3.11",
36
36
  "Programming Language :: Python :: 3.12",
37
+ "Programming Language :: Python :: 3.13",
37
38
  "Topic :: System :: Logging",
38
39
  "Typing :: Typed",
39
40
  ]
40
41
 
41
42
  [project.urls]
42
- Homepage = "https://nhairs.github.io/python-json-logger/latest/"
43
+ Homepage = "https://nhairs.github.io/python-json-logger"
43
44
  GitHub = "https://github.com/nhairs/python-json-logger"
44
45
 
45
46
  [project.optional-dependencies]
46
47
  dev = [
47
48
  ## Optional but required for dev
48
- "orjson;implementation_name!='pypy' and python_version<'3.13'",
49
+ "orjson;implementation_name!='pypy'",
49
50
  "msgspec;implementation_name!='pypy' and python_version<'3.13'",
51
+ "msgspec-python313-pre;implementation_name!='pypy' and python_version=='3.13'",
50
52
  ## Lint
51
53
  "validate-pyproject[all]",
52
54
  "black",
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-json-logger
3
- Version: 3.1.0
3
+ Version: 3.2.1
4
4
  Summary: JSON Log Formatter for the Python Logging Package
5
5
  Author-email: Zakaria Zajac <zak@madzak.com>, Nicholas Hairs <info+python-json-logger@nicholashairs.com>
6
6
  Maintainer-email: Nicholas Hairs <info+python-json-logger@nicholashairs.com>
7
7
  License: BSD-2-Clause License
8
- Project-URL: Homepage, https://nhairs.github.io/python-json-logger/latest/
8
+ Project-URL: Homepage, https://nhairs.github.io/python-json-logger
9
9
  Project-URL: GitHub, https://github.com/nhairs/python-json-logger
10
10
  Classifier: Development Status :: 6 - Mature
11
11
  Classifier: Intended Audience :: Developers
@@ -17,16 +17,18 @@ Classifier: Programming Language :: Python :: 3.9
17
17
  Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
20
21
  Classifier: Topic :: System :: Logging
21
22
  Classifier: Typing :: Typed
22
23
  Requires-Python: >=3.8
23
24
  Description-Content-Type: text/markdown
24
25
  License-File: LICENSE
25
26
  License-File: NOTICE
26
- Requires-Dist: typing_extensions
27
+ Requires-Dist: typing_extensions; python_version < "3.10"
27
28
  Provides-Extra: dev
28
- Requires-Dist: orjson; (implementation_name != "pypy" and python_version < "3.13") and extra == "dev"
29
+ Requires-Dist: orjson; implementation_name != "pypy" and extra == "dev"
29
30
  Requires-Dist: msgspec; (implementation_name != "pypy" and python_version < "3.13") and extra == "dev"
31
+ Requires-Dist: msgspec-python313-pre; (implementation_name != "pypy" and python_version == "3.13") and extra == "dev"
30
32
  Requires-Dist: validate-pyproject[all]; extra == "dev"
31
33
  Requires-Dist: black; extra == "dev"
32
34
  Requires-Dist: pylint; extra == "dev"
@@ -45,9 +47,10 @@ Requires-Dist: mkdocs-gen-files; extra == "dev"
45
47
  Requires-Dist: mkdocs-literate-nav; extra == "dev"
46
48
  Requires-Dist: mike; extra == "dev"
47
49
 
48
- <!-- [![PyPi](https://img.shields.io/pypi/v/python-json-logger.svg)](https://pypi.python.org/pypi/python-json-logger/)
50
+ [![PyPi](https://img.shields.io/pypi/v/python-json-logger.svg)](https://pypi.python.org/pypi/python-json-logger/)
49
51
  [![PyPI - Status](https://img.shields.io/pypi/status/python-json-logger)](https://pypi.python.org/pypi/python-json-logger/)
50
- [![Python Versions](https://img.shields.io/pypi/pyversions/python-json-logger.svg)](https://github.com/nhairs/python-json-logger) -->
52
+ [![PyPI - Downloads](https://img.shields.io/pypi/dm/python-json-logger)](https://pypi.python.org/pypi/python-json-logger/)
53
+ [![Python Versions](https://img.shields.io/pypi/pyversions/python-json-logger.svg)](https://github.com/nhairs/python-json-logger)
51
54
  [![License](https://img.shields.io/github/license/nhairs/python-json-logger.svg)](https://github.com/nhairs/python-json-logger)
52
55
  ![Build Status](https://github.com/nhairs/python-json-logger/actions/workflows/test-suite.yml/badge.svg)
53
56
  #
@@ -58,10 +61,6 @@ Python JSON Logger enables you produce JSON logs when using Python's `logging` p
58
61
  JSON logs are machine readable allowing for much easier parsing and ingestion into log aggregation tools.
59
62
 
60
63
 
61
- ### 🚨 Important 🚨
62
-
63
- This repository is a maintained fork of [madzak/python-json-logger](https://github.com/madzak/python-json-logger) pending [a PEP 541 request](https://github.com/pypi/support/issues/3607) for the PyPI package. The future direction of the project is being discussed [here](https://github.com/nhairs/python-json-logger/issues/1).
64
-
65
64
  ## Documentation
66
65
 
67
66
  - [Documentation](https://nhairs.github.io/python-json-logger/latest/)
@@ -11,10 +11,14 @@ src/python_json_logger.egg-info/top_level.txt
11
11
  src/pythonjsonlogger/__init__.py
12
12
  src/pythonjsonlogger/core.py
13
13
  src/pythonjsonlogger/defaults.py
14
+ src/pythonjsonlogger/exception.py
14
15
  src/pythonjsonlogger/json.py
16
+ src/pythonjsonlogger/jsonlogger.py
15
17
  src/pythonjsonlogger/msgspec.py
16
18
  src/pythonjsonlogger/orjson.py
17
19
  src/pythonjsonlogger/py.typed
20
+ src/pythonjsonlogger/utils.py
18
21
  tests/__init__.py
19
22
  tests/test_deprecation.py
20
- tests/test_formatters.py
23
+ tests/test_formatters.py
24
+ tests/test_missing.py
@@ -1,3 +1,5 @@
1
+
2
+ [:python_version < "3.10"]
1
3
  typing_extensions
2
4
 
3
5
  [dev]
@@ -18,9 +20,14 @@ mkdocs-gen-files
18
20
  mkdocs-literate-nav
19
21
  mike
20
22
 
21
- [dev:implementation_name != "pypy" and python_version < "3.13"]
23
+ [dev:implementation_name != "pypy"]
22
24
  orjson
25
+
26
+ [dev:implementation_name != "pypy" and python_version < "3.13"]
23
27
  msgspec
24
28
 
29
+ [dev:implementation_name != "pypy" and python_version == "3.13"]
30
+ msgspec-python313-pre
31
+
25
32
  [dev:python_version < "3.9"]
26
33
  backports.zoneinfo
@@ -0,0 +1,17 @@
1
+ ### IMPORTS
2
+ ### ============================================================================
3
+ ## Future
4
+
5
+ ## Standard Library
6
+ import warnings
7
+
8
+ ## Installed
9
+
10
+ ## Application
11
+ from . import json
12
+ from . import utils
13
+
14
+ ### CONSTANTS
15
+ ### ============================================================================
16
+ ORJSON_AVAILABLE = utils.package_is_available("orjson")
17
+ MSGSPEC_AVAILABLE = utils.package_is_available("msgspec")
@@ -66,9 +66,9 @@ if sys.version_info >= (3, 12):
66
66
  RESERVED_ATTRS.sort()
67
67
 
68
68
 
69
- STYLE_STRING_TEMPLATE_REGEX = re.compile(r"\$\{(.+?)\}", re.IGNORECASE)
70
- STYLE_STRING_FORMAT_REGEX = re.compile(r"\{(.+?)\}", re.IGNORECASE)
71
- STYLE_PERCENT_REGEX = re.compile(r"%\((.+?)\)", re.IGNORECASE)
69
+ STYLE_STRING_TEMPLATE_REGEX = re.compile(r"\$\{(.+?)\}", re.IGNORECASE) # $ style
70
+ STYLE_STRING_FORMAT_REGEX = re.compile(r"\{(.+?)\}", re.IGNORECASE) # { style
71
+ STYLE_PERCENT_REGEX = re.compile(r"%\((.+?)\)", re.IGNORECASE) # % style
72
72
 
73
73
  ## Type Aliases
74
74
  ## -----------------------------------------------------------------------------
@@ -132,6 +132,8 @@ class BaseJsonFormatter(logging.Formatter):
132
132
  Must not be used directly.
133
133
 
134
134
  *New in 3.1*
135
+
136
+ *Changed in 3.2*: `defaults` argument is no longer ignored.
135
137
  """
136
138
 
137
139
  _style: Union[logging.PercentStyle, str] # type: ignore[assignment]
@@ -161,7 +163,8 @@ class BaseJsonFormatter(logging.Formatter):
161
163
  style: how to extract log fields from `fmt`
162
164
  validate: validate `fmt` against style, if implementing a custom `style` you
163
165
  must set this to `False`.
164
- defaults: ignored - kept for compatibility with python 3.10+
166
+ defaults: a dictionary containing default fields that are added before all other fields and
167
+ may be overridden. The supplied fields are still subject to `rename_fields`.
165
168
  prefix: an optional string prefix added at the beginning of
166
169
  the formatted string
167
170
  rename_fields: an optional dict, used to rename field names in the output.
@@ -215,6 +218,7 @@ class BaseJsonFormatter(logging.Formatter):
215
218
  self._required_fields = self.parse()
216
219
  self._skip_fields = set(self._required_fields)
217
220
  self._skip_fields.update(self.reserved_attrs)
221
+ self.defaults = defaults if defaults is not None else {}
218
222
  return
219
223
 
220
224
  def format(self, record: logging.LogRecord) -> str:
@@ -310,6 +314,9 @@ class BaseJsonFormatter(logging.Formatter):
310
314
  message_dict: dictionary that was logged instead of a message. e.g
311
315
  `logger.info({"is_this_message_dict": True})`
312
316
  """
317
+ for field in self.defaults:
318
+ log_record[self._get_rename(field)] = self.defaults[field]
319
+
313
320
  for field in self._required_fields:
314
321
  log_record[self._get_rename(field)] = record.__dict__.get(field)
315
322
 
@@ -0,0 +1,27 @@
1
+ ### IMPORTS
2
+ ### ============================================================================
3
+ ## Future
4
+ from __future__ import annotations
5
+
6
+ ## Standard Library
7
+
8
+ ## Installed
9
+
10
+ ## Application
11
+
12
+
13
+ ### CLASSES
14
+ ### ============================================================================
15
+ class PythonJsonLoggerError(Exception):
16
+ "Generic base clas for all Python JSON Logger exceptions"
17
+
18
+
19
+ class MissingPackageError(ImportError, PythonJsonLoggerError):
20
+ "A required package is missing"
21
+
22
+ def __init__(self, name: str, extras_name: str | None = None) -> None:
23
+ msg = f"The {name!r} package is required but could not be found."
24
+ if extras_name is not None:
25
+ msg += f" It can be installed using 'python-json-logger[{extras_name}]'."
26
+ super().__init__(msg)
27
+ return
@@ -0,0 +1,18 @@
1
+ """Stub module retained for compatibility.
2
+
3
+ It retains access to old names whilst sending deprecation warnings.
4
+ """
5
+
6
+ # pylint: disable=wrong-import-position,unused-import
7
+
8
+ import warnings
9
+
10
+ ## Throw warning
11
+ warnings.warn(
12
+ "pythonjsonlogger.jsonlogger has been moved to pythonjsonlogger.json",
13
+ DeprecationWarning,
14
+ )
15
+
16
+ ## Import names
17
+ from .json import JsonFormatter, JsonEncoder
18
+ from .core import RESERVED_ATTRS
@@ -9,11 +9,15 @@ from __future__ import annotations
9
9
  from typing import Any
10
10
 
11
11
  ## Installed
12
- import msgspec.json
13
12
 
14
13
  ## Application
15
14
  from . import core
16
15
  from . import defaults as d
16
+ from .utils import package_is_available
17
+
18
+ # We import msgspec after checking it is available
19
+ package_is_available("msgspec", throw_error=True)
20
+ import msgspec.json # pylint: disable=wrong-import-position,wrong-import-order
17
21
 
18
22
 
19
23
  ### FUNCTIONS
@@ -1,4 +1,4 @@
1
- """JSON Formatter using [msgspec](https://github.com/ijl/orjson)"""
1
+ """JSON Formatter using [orjson](https://github.com/ijl/orjson)"""
2
2
 
3
3
  ### IMPORTS
4
4
  ### ============================================================================
@@ -9,11 +9,15 @@ from __future__ import annotations
9
9
  from typing import Any
10
10
 
11
11
  ## Installed
12
- import orjson
13
12
 
14
13
  ## Application
15
14
  from . import core
16
15
  from . import defaults as d
16
+ from .utils import package_is_available
17
+
18
+ # We import msgspec after checking it is available
19
+ package_is_available("orjson", throw_error=True)
20
+ import orjson # pylint: disable=wrong-import-position,wrong-import-order
17
21
 
18
22
 
19
23
  ### FUNCTIONS
@@ -0,0 +1,40 @@
1
+ """Utilities for Python JSON Logger"""
2
+
3
+ ### IMPORTS
4
+ ### ============================================================================
5
+ ## Future
6
+ from __future__ import annotations
7
+
8
+ ## Standard Library
9
+ import importlib.util
10
+
11
+ ## Installed
12
+
13
+ ## Application
14
+ from .exception import MissingPackageError
15
+
16
+
17
+ ### FUNCTIONS
18
+ ### ============================================================================
19
+ def package_is_available(
20
+ name: str, *, throw_error: bool = False, extras_name: str | None = None
21
+ ) -> bool:
22
+ """Determine if the given package is available for import.
23
+
24
+ Args:
25
+ name: Import name of the package to check.
26
+ throw_error: Throw an error if the package is unavailable.
27
+ extras_name: Extra dependency name to use in `throw_error`'s message.
28
+
29
+ Raises:
30
+ MissingPackageError: When `throw_error` is `True` and the return value would be `False`
31
+
32
+ Returns:
33
+ If the package is available for import.
34
+ """
35
+ available = importlib.util.find_spec(name) is not None
36
+
37
+ if not available and throw_error:
38
+ raise MissingPackageError(name, extras_name)
39
+
40
+ return available
@@ -4,6 +4,8 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  ## Standard Library
7
+ import subprocess
8
+ import sys
7
9
 
8
10
  ## Installed
9
11
  import pytest
@@ -16,7 +18,7 @@ import pythonjsonlogger
16
18
  ### ============================================================================
17
19
  def test_jsonlogger_deprecated():
18
20
  with pytest.deprecated_call():
19
- pythonjsonlogger.jsonlogger
21
+ import pythonjsonlogger.jsonlogger
20
22
  return
21
23
 
22
24
 
@@ -26,3 +28,18 @@ def test_jsonlogger_reserved_attrs_deprecated():
26
28
  # a DeprecationWarning and we specifically want the one for RESERVED_ATTRS
27
29
  pythonjsonlogger.json.RESERVED_ATTRS
28
30
  return
31
+
32
+
33
+ @pytest.mark.parametrize(
34
+ "command",
35
+ [
36
+ "from pythonjsonlogger import jsonlogger",
37
+ "import pythonjsonlogger.jsonlogger",
38
+ "from pythonjsonlogger.jsonlogger import JsonFormatter",
39
+ "from pythonjsonlogger.jsonlogger import RESERVED_ATTRS",
40
+ ],
41
+ )
42
+ def test_import(command: str):
43
+ output = subprocess.check_output([sys.executable, "-c", f"{command};print('OK')"])
44
+ assert output.strip() == b"OK"
45
+ return
@@ -174,6 +174,18 @@ def test_percentage_format(env: LoggingEnvironment, class_: type[BaseJsonFormatt
174
174
  return
175
175
 
176
176
 
177
+ @pytest.mark.parametrize("class_", ALL_FORMATTERS)
178
+ def test_defaults_field(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
179
+ env.set_formatter(class_(defaults={"first": 1, "second": 2}))
180
+
181
+ env.logger.info("testing defaults field", extra={"first": 1234})
182
+ log_json = env.load_json()
183
+
184
+ assert log_json["first"] == 1234
185
+ assert log_json["second"] == 2
186
+ return
187
+
188
+
177
189
  @pytest.mark.parametrize("class_", ALL_FORMATTERS)
178
190
  def test_rename_base_field(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
179
191
  env.set_formatter(class_(rename_fields={"message": "@message"}))
@@ -186,6 +198,20 @@ def test_rename_base_field(env: LoggingEnvironment, class_: type[BaseJsonFormatt
186
198
  return
187
199
 
188
200
 
201
+ @pytest.mark.parametrize("class_", ALL_FORMATTERS)
202
+ def test_rename_with_defaults(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
203
+ """Make sure that the default fields are also renamed."""
204
+ env.set_formatter(class_(rename_fields={"custom": "@custom"}, defaults={"custom": 1234}))
205
+
206
+ msg = "testing rename with defaults"
207
+ env.logger.info(msg)
208
+ log_json = env.load_json()
209
+
210
+ assert log_json["@custom"] == 1234
211
+ assert "custom" not in log_json
212
+ return
213
+
214
+
189
215
  @pytest.mark.parametrize("class_", ALL_FORMATTERS)
190
216
  def test_rename_missing(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
191
217
  env.set_formatter(class_(rename_fields={"missing_field": "new_field"}))
@@ -321,6 +347,19 @@ def test_log_dict(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
321
347
  return
322
348
 
323
349
 
350
+ @pytest.mark.parametrize("class_", ALL_FORMATTERS)
351
+ def test_log_dict_defaults(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
352
+ env.set_formatter(class_(defaults={"d1": 1234, "d2": "hello"}))
353
+
354
+ msg = {"d2": "world"}
355
+ env.logger.info(msg)
356
+ log_json = env.load_json()
357
+
358
+ assert log_json["d1"] == 1234
359
+ assert log_json["d2"] == "world"
360
+ return
361
+
362
+
324
363
  @pytest.mark.parametrize("class_", ALL_FORMATTERS)
325
364
  def test_log_extra(env: LoggingEnvironment, class_: type[BaseJsonFormatter]):
326
365
  env.set_formatter(class_())
@@ -0,0 +1,67 @@
1
+ ### IMPORTS
2
+ ### ============================================================================
3
+ ## Future
4
+ from __future__ import annotations
5
+
6
+ ## Standard Library
7
+
8
+ ## Installed
9
+ import pytest
10
+
11
+ ## Application
12
+ import pythonjsonlogger
13
+ from pythonjsonlogger.utils import package_is_available
14
+ from pythonjsonlogger.exception import MissingPackageError
15
+
16
+ ### CONSTANTS
17
+ ### ============================================================================
18
+ MISSING_PACKAGE_NAME = "package_name_is_definintely_not_available"
19
+ MISSING_PACKAGE_EXTRA = "package_extra_that_is_unique"
20
+
21
+
22
+ ### TESTS
23
+ ### ============================================================================
24
+ def test_package_is_available():
25
+ assert package_is_available("json")
26
+ return
27
+
28
+
29
+ def test_package_not_available():
30
+ assert not package_is_available(MISSING_PACKAGE_NAME)
31
+ return
32
+
33
+
34
+ def test_package_not_available_throw():
35
+ with pytest.raises(MissingPackageError) as e:
36
+ package_is_available(MISSING_PACKAGE_NAME, throw_error=True)
37
+ assert MISSING_PACKAGE_NAME in e.value.msg
38
+ assert MISSING_PACKAGE_EXTRA not in e.value.msg
39
+ return
40
+
41
+
42
+ def test_package_not_available_throw_extras():
43
+ with pytest.raises(MissingPackageError) as e:
44
+ package_is_available(
45
+ MISSING_PACKAGE_NAME, throw_error=True, extras_name=MISSING_PACKAGE_EXTRA
46
+ )
47
+ assert MISSING_PACKAGE_NAME in e.value.msg
48
+ assert MISSING_PACKAGE_EXTRA in e.value.msg
49
+ return
50
+
51
+
52
+ ## Python JSON Logger Specific
53
+ ## -----------------------------------------------------------------------------
54
+ if not pythonjsonlogger.ORJSON_AVAILABLE:
55
+
56
+ def test_orjson_import_error():
57
+ with pytest.raises(MissingPackageError, match="orjson"):
58
+ import pythonjsonlogger.orjson
59
+ return
60
+
61
+
62
+ if not pythonjsonlogger.MSGSPEC_AVAILABLE:
63
+
64
+ def test_msgspec_import_error():
65
+ with pytest.raises(MissingPackageError, match="msgspec"):
66
+ import pythonjsonlogger.msgspec
67
+ return
@@ -1,40 +0,0 @@
1
- ### IMPORTS
2
- ### ============================================================================
3
- ## Future
4
-
5
- ## Standard Library
6
- import warnings
7
-
8
- ## Installed
9
-
10
- ## Application
11
- import pythonjsonlogger.json
12
-
13
- ### CONSTANTS
14
- ### ============================================================================
15
- try:
16
- import orjson
17
-
18
- ORJSON_AVAILABLE = True
19
- except ImportError:
20
- ORJSON_AVAILABLE = False
21
-
22
-
23
- try:
24
- import msgspec
25
-
26
- MSGSPEC_AVAILABLE = True
27
- except ImportError:
28
- MSGSPEC_AVAILABLE = False
29
-
30
-
31
- ### DEPRECATED COMPATIBILITY
32
- ### ============================================================================
33
- def __getattr__(name: str):
34
- if name == "jsonlogger":
35
- warnings.warn(
36
- "pythonjsonlogger.jsonlogger has been moved to pythonjsonlogger.json",
37
- DeprecationWarning,
38
- )
39
- return pythonjsonlogger.json
40
- raise AttributeError(f"module {__name__} has no attribute {name}")