hydra-structlog 0.2.1__tar.gz → 1.0.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hydra-structlog
3
- Version: 0.2.1
3
+ Version: 1.0.1
4
4
  Summary: An opinionated hydra plugin to configure logging with structlog
5
5
  Keywords: hydra,structlog,plugin,hydra-zen
6
6
  Author: Sören Zapp
@@ -0,0 +1,147 @@
1
+ [project]
2
+ name = "hydra-structlog"
3
+ version = "1.0.1"
4
+ description = "An opinionated hydra plugin to configure logging with structlog"
5
+ readme = "README.md"
6
+ keywords = [
7
+ "hydra",
8
+ "structlog",
9
+ "plugin",
10
+ "hydra-zen",
11
+ ]
12
+ license = "MIT"
13
+ license-files = ["LICENSE"]
14
+ classifiers = [
15
+ "Programming Language :: Python",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3 :: Only",
18
+ "Programming Language :: Python :: 3.10",
19
+ "Programming Language :: Python :: 3.11",
20
+ "Programming Language :: Python :: 3.12",
21
+ "Programming Language :: Python :: 3.13",
22
+ "Intended Audience :: Developers",
23
+ "Intended Audience :: Information Technology",
24
+ "Operating System :: OS Independent",
25
+ "Topic :: Scientific/Engineering",
26
+ ]
27
+ requires-python = ">=3.10"
28
+ dependencies = [
29
+ "hydra-core>=1.3.2",
30
+ "structlog>=25.5.0",
31
+ ]
32
+
33
+ [[project.authors]]
34
+ name = "Sören Zapp"
35
+
36
+ [project.urls]
37
+ Source = "https://github.com/szapp/hydra-structlog"
38
+ Issues = "https://github.com/szapp/hydra-structlog/issues"
39
+ Funding = "https://ko-fi.com/szapp"
40
+
41
+ [dependency-groups]
42
+ dev = [
43
+ "ruff>=0.15.8",
44
+ "ty>=0.0.26",
45
+ "interrogate>=1.7.0",
46
+ "prek>=0.3.8",
47
+ "nox>=2026.2.9",
48
+ ]
49
+ tests = [
50
+ "dirty-equals>=0.11",
51
+ "pytest>=9.0.2",
52
+ "pytest-cov>=7.1.0",
53
+ "pytest-randomly>=4.0.1",
54
+ ]
55
+ examples = [
56
+ "hydra-zen>=0.16.0",
57
+ "pydantic>=2.12.5",
58
+ "rich>=14.3.3",
59
+ "tqdm>=4.67.3",
60
+ ]
61
+
62
+ [tool.uv]
63
+ default-groups = [
64
+ "dev",
65
+ "tests",
66
+ ]
67
+
68
+ [tool.uv.build-backend]
69
+ module-name = [
70
+ "hydra_plugins.hydra_structlog",
71
+ "hydra_structlog",
72
+ ]
73
+
74
+ [tool.ruff]
75
+ line-length = 88
76
+
77
+ [tool.ruff.lint]
78
+ extend-select = [
79
+ "I",
80
+ "E501",
81
+ "UP006",
82
+ "UP035",
83
+ "D200",
84
+ "D209",
85
+ "D210",
86
+ "D212",
87
+ "D403",
88
+ "D405",
89
+ "D416",
90
+ ]
91
+ ignore = ["E731"]
92
+
93
+ [tool.ruff.lint.per-file-ignores]
94
+ "**/tests/**/test_*.py" = ["S101"]
95
+
96
+ [tool.ruff.format]
97
+ line-ending = "lf"
98
+
99
+ [[tool.ty.overrides]]
100
+ include = ["src/hydra_structlog/handlers.py"]
101
+
102
+ [tool.ty.overrides.rules]
103
+ unused-type-ignore-comment = "ignore"
104
+
105
+ [tool.pytest]
106
+ strict_xfail = true
107
+ addopts = [
108
+ "-ra",
109
+ "-vv",
110
+ "-p",
111
+ "no:tach",
112
+ "--strict-markers",
113
+ "--strict-config",
114
+ "--doctest-modules",
115
+ "--cov",
116
+ "--import-mode=importlib",
117
+ ]
118
+ testpaths = [
119
+ "tests",
120
+ "src",
121
+ ]
122
+
123
+ [tool.coverage.run]
124
+ source = [
125
+ "src",
126
+ "tests",
127
+ ]
128
+ branch = true
129
+
130
+ [tool.coverage.report]
131
+ fail_under = 100
132
+ ignore_errors = true
133
+ show_missing = true
134
+ skip_covered = true
135
+ skip_empty = true
136
+
137
+ [tool.interrogate]
138
+ omit-covered-files = true
139
+ verbose = 2
140
+ fail-under = 100
141
+ whitelist-regex = ["test_.*"]
142
+ exclude = ["*.cache"]
143
+ style = "google"
144
+
145
+ [build-system]
146
+ requires = ["uv_build>=0.11.0,<0.12.0"]
147
+ build-backend = "uv_build"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hydra-structlog"
3
- version = "0.2.1"
3
+ version = "1.0.1"
4
4
  description = "An opinionated hydra plugin to configure logging with structlog"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -0,0 +1 @@
1
+ __version__ = "1.0.1"
@@ -66,6 +66,7 @@ formatters:
66
66
  _target_: hydra_structlog.processors.KeyRenamer
67
67
  level: status
68
68
  event: message
69
+ _event: event
69
70
  format_exc_info:
70
71
  _target_: structlog.processors.format_exc_info
71
72
  _partial_: true
@@ -81,6 +82,7 @@ formatters:
81
82
  drop_missing: true
82
83
  json_renderer:
83
84
  _target_: structlog.processors.JSONRenderer
85
+ ensure_ascii: false
84
86
  handlers:
85
87
  console:
86
88
  class: hydra_structlog.handlers.TqdmStreamHandler
@@ -107,6 +109,6 @@ handlers:
107
109
 
108
110
  root:
109
111
  level: INFO
110
- handlers: [console, file, json]
112
+ handlers: ${hydra-structlog.dev:[console, file, json],[file, json]}
111
113
 
112
114
  disable_existing_loggers: false
@@ -30,5 +30,5 @@ class TqdmStreamHandler(logging.StreamHandler): # pragma: no cover
30
30
  self.flush()
31
31
  except (KeyboardInterrupt, RecursionError, SystemExit):
32
32
  raise
33
- except Exception:
33
+ except Exception: # noqa: BLE001
34
34
  self.handleError(record)
@@ -14,6 +14,21 @@ _excepthook = None
14
14
  _configured_once = False
15
15
 
16
16
 
17
+ def _module_from_filename(filename: str) -> str | None:
18
+ """Obtain the module name from filename through call stack."""
19
+ frame = sys._getframe(1)
20
+ while frame is not None:
21
+ if frame.f_code.co_filename == filename:
22
+ return frame.f_globals.get("__name__")
23
+ frame = frame.f_back
24
+
25
+ # Fallback: Module from sys.modules
26
+ for name, mod in list(sys.modules.items()):
27
+ if getattr(mod, "__file__", None) == filename:
28
+ return name
29
+ return None
30
+
31
+
17
32
  def warning_logger(
18
33
  message: Warning | str,
19
34
  category: type[Warning],
@@ -23,10 +38,20 @@ def warning_logger(
23
38
  line: str | None = None,
24
39
  ) -> None:
25
40
  """Emit Python-native warnings as logging warnings."""
26
- frame = sys._getframe(2)
27
- module = frame.f_globals.get("__name__")
41
+ module = _module_from_filename(filename)
28
42
  logger = logging.getLogger(module)
29
- logger.warning("%s: %s (line %d)", category.__name__, message, lineno)
43
+ if not logger.isEnabledFor(logging.WARNING):
44
+ return # pragma: no cover
45
+ record = logger.makeRecord(
46
+ logger.name,
47
+ logging.WARNING,
48
+ filename,
49
+ lineno,
50
+ "%s: %s (line %d)",
51
+ (category.__name__, message, lineno),
52
+ None,
53
+ )
54
+ logger.handle(record)
30
55
 
31
56
 
32
57
  def exception_logger(
@@ -56,7 +81,7 @@ def exception_logger(
56
81
  filename = frame.f_code.co_filename.replace(os.sep, "/")
57
82
  if filename.endswith(skip_files) and tb:
58
83
  exc_traceback = tb
59
- except Exception: # pragma: no cover
84
+ except Exception: # pragma: no cover # noqa: BLE001, S110
60
85
  pass
61
86
 
62
87
  message = getattr(exc_value, "message", str(exc_value))
@@ -1,7 +1,11 @@
1
1
  from hydra.core.config_search_path import ConfigSearchPath
2
2
  from hydra.plugins.search_path_plugin import SearchPathPlugin
3
+ from omegaconf import OmegaConf
4
+
5
+ from .resolvers import dev_switch
3
6
 
4
7
 
5
8
  class HydraStructlogSearchPathPlugin(SearchPathPlugin):
6
9
  def manipulate_search_path(self, search_path: ConfigSearchPath) -> None:
10
+ OmegaConf.register_new_resolver("hydra-structlog.dev", dev_switch)
7
11
  search_path.append("hydra-structlog", "pkg://hydra_structlog.conf")
@@ -0,0 +1,9 @@
1
+ import os
2
+
3
+
4
+ def dev_switch(is_dev, is_not_dev, *, _root_):
5
+ """OmegaConf resolver to select node based on dev environment."""
6
+ # Grab ENV from 'env_set' first and fall back to environment variable
7
+ hydra_env = _root_.get("hydra", {}).get("job", {}).get("env_set", {})
8
+ ENV = hydra_env.get("ENV", os.environ.get("ENV")) or "dev"
9
+ return is_dev if ENV == "dev" else is_not_dev
@@ -1 +0,0 @@
1
- __version__ = "0.2.1"
File without changes