Content-Length: 552315 | pFad | http://github.com/nhairs/python-json-logger/pull/52/files

CD [core,json,orjson,msgspec] Remove use of str_to_object by nhairs · Pull Request #52 · nhairs/python-json-logger · GitHub
Skip to content

[core,json,orjson,msgspec] Remove use of str_to_object #52

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [UNRELEASED]
## [4.0.0](https://github.com/nhairs/python-json-logger/compare/v3.3.3...v4.0.0) - UNRELEASED

### Added
- Support `DictConfigurator` prefixes for `rename_fields` and `static_fields`. [#45](https://github.com/nhairs/python-json-logger/pull/45)
- Allows using values like `ext://sys.stderr` in `fileConfig`/`dictConfig` value fields.

### Removed
- Remove support for providing strings instead of objects when instantiating formatters. Instead use the `DictConfigurator` `ext://` prefix format when using `fileConfig`/`dictConfig`. [#47](https://github.com/nhairs/python-json-logger/issues/47)
- Affects `pythonjsonlogger.json.JsonFormatter`: `json_default`, `json_encoder`, `json_serializer`.
- Affects `pythonjsonlogger.orjson.OrjsonFormatter`: `json_default`.
- Affects `pythonjsonlogger.msgspec.MsgspecFormatter`: `json_default`.

Thanks @rubensa

## [3.3.0](https://github.com/nhairs/python-json-logger/compare/v3.2.1...v3.3.0) - 2025-03-06
Expand Down
13 changes: 12 additions & 1 deletion docs/cookbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ formatters:
default:
"()": pythonjsonlogger.json.JsonFormatter
format: "%(asctime)s %(levelname)s %(name)s %(module)s %(funcName)s %(lineno)s %(message)s"
json_default: ext://logging_config.my_json_default
rename_fields:
"asctime": "timestamp"
"levelname": "status"
Expand Down Expand Up @@ -178,13 +179,23 @@ loggers:
propagate: no
```

You'll notice that we are using `ext://...` for the `static_fields`. This will load data from other modules such as the one below.
You'll notice that we are using `ext://...` for `json_default` and`static_fields`. This will load data from other modules such as the one below.

```python title="logging_config.py"
import importlib.metadata
import os


class Dummy:
pass


def my_json_default(obj: Any) -> Any:
if isinstance(obj, Dummy):
return "DUMMY"
return obj


def get_version_metadata():
# https://stackoverflow.com/a/78082532
version = importlib.metadata.version(PROJECT_NAME)
Expand Down
22 changes: 1 addition & 21 deletions src/pythonjsonlogger/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@

## Standard Library
from datetime import datetime, timezone
import importlib
import logging
import re
import sys
from typing import Optional, Union, Callable, List, Dict, Container, Any, Sequence
from typing import Optional, Union, List, Dict, Container, Any, Sequence

if sys.version_info >= (3, 10):
from typing import TypeAlias
Expand Down Expand Up @@ -72,31 +71,12 @@

## Type Aliases
## -----------------------------------------------------------------------------
OptionalCallableOrStr: TypeAlias = Optional[Union[Callable, str]]
"""Type alias"""

LogRecord: TypeAlias = Dict[str, Any]
"""Type alias"""


### FUNCTIONS
### ============================================================================
def str_to_object(obj: Any) -> Any:
"""Import strings to an object, leaving non-strings as-is.

Args:
obj: the object or string to process

*New in 3.1*
"""

if not isinstance(obj, str):
return obj

module_name, attribute_name = obj.rsplit(".", 1)
return getattr(importlib.import_module(module_name), attribute_name)


def merge_record_extra(
record: logging.LogRecord,
target: Dict,
Expand Down
12 changes: 6 additions & 6 deletions src/pythonjsonlogger/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ class JsonFormatter(core.BaseJsonFormatter):
def __init__(
self,
*args,
json_default: core.OptionalCallableOrStr = None,
json_encoder: core.OptionalCallableOrStr = None,
json_serializer: Union[Callable, str] = json.dumps,
json_default: Optional[Callable] = None,
json_encoder: Optional[Callable] = None,
json_serializer: Callable = json.dumps,
json_indent: Optional[Union[int, str]] = None,
json_ensure_ascii: bool = True,
**kwargs,
Expand All @@ -87,9 +87,9 @@ def __init__(
"""
super().__init__(*args, **kwargs)

self.json_default = core.str_to_object(json_default)
self.json_encoder = core.str_to_object(json_encoder)
self.json_serializer = core.str_to_object(json_serializer)
self.json_default = json_default
self.json_encoder = json_encoder
self.json_serializer = json_serializer
self.json_indent = json_indent
self.json_ensure_ascii = json_ensure_ascii
if not self.json_encoder and not self.json_default:
Expand Down
6 changes: 3 additions & 3 deletions src/pythonjsonlogger/msgspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from __future__ import annotations

## Standard Library
from typing import Any
from typing import Any, Optional, Callable

## Installed

Expand Down Expand Up @@ -43,7 +43,7 @@ class MsgspecFormatter(core.BaseJsonFormatter):
def __init__(
self,
*args,
json_default: core.OptionalCallableOrStr = msgspec_default,
json_default: Optional[Callable] = msgspec_default,
**kwargs,
) -> None:
"""
Expand All @@ -54,7 +54,7 @@ def __init__(
"""
super().__init__(*args, **kwargs)

self.json_default = core.str_to_object(json_default)
self.json_default = json_default
self._encoder = msgspec.json.Encoder(enc_hook=self.json_default)
return

Expand Down
6 changes: 3 additions & 3 deletions src/pythonjsonlogger/orjson.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from __future__ import annotations

## Standard Library
from typing import Any
from typing import Any, Optional, Callable

## Installed

Expand Down Expand Up @@ -45,7 +45,7 @@ class OrjsonFormatter(core.BaseJsonFormatter):
def __init__(
self,
*args,
json_default: core.OptionalCallableOrStr = orjson_default,
json_default: Optional[Callable] = orjson_default,
json_indent: bool = False,
**kwargs,
) -> None:
Expand All @@ -58,7 +58,7 @@ def __init__(
"""
super().__init__(*args, **kwargs)

self.json_default = core.str_to_object(json_default)
self.json_default = json_default
self.json_indent = json_indent
return

Expand Down
18 changes: 17 additions & 1 deletion tests/test_dictconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,24 @@
_LOGGER_COUNT = 0
EXT_VAL = 999


class Dummy:
pass


def my_json_default(obj: Any) -> Any:
if isinstance(obj, Dummy):
return "DUMMY"
return obj


LOGGING_CONFIG = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"default": {
"()": "pythonjsonlogger.json.JsonFormatter",
"json_default": "ext://tests.test_dictconfig.my_json_default",
"static_fields": {"ext-val": "ext://tests.test_dictconfig.EXT_VAL"},
}
},
Expand Down Expand Up @@ -73,8 +85,12 @@ def env() -> Generator[LoggingEnvironment, None, None]:
### TESTS
### ============================================================================
def test_external_reference_support(env: LoggingEnvironment):
env.logger.info("hello")

assert logging.root.handlers[0].formatter.json_default is my_json_default # type: ignore[union-attr]

env.logger.info("hello", extra={"dummy": Dummy()})
log_json = env.load_json()

assert log_json["ext-val"] == EXT_VAL
assert log_json["dummy"] == "DUMMY"
return








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/nhairs/python-json-logger/pull/52/files

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy