custom-python-logger 2.0.3__tar.gz → 2.0.5__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 (22) hide show
  1. {custom_python_logger-2.0.3/custom_python_logger.egg-info → custom_python_logger-2.0.5}/PKG-INFO +3 -1
  2. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/custom_python_logger/logger.py +27 -34
  3. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/custom_python_logger/usage_example.py +4 -3
  4. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5/custom_python_logger.egg-info}/PKG-INFO +3 -1
  5. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/custom_python_logger.egg-info/requires.txt +2 -0
  6. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/requirements.txt +2 -0
  7. custom_python_logger-2.0.5/setup.py +35 -0
  8. custom_python_logger-2.0.5/tests/test_logger.py +27 -0
  9. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/tests/test_logger_pytest.py +8 -21
  10. custom_python_logger-2.0.3/setup.py +0 -37
  11. custom_python_logger-2.0.3/tests/test_logger.py +0 -26
  12. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/LICENSE +0 -0
  13. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/MANIFEST.in +0 -0
  14. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/README.md +0 -0
  15. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/custom_python_logger/__init__.py +0 -0
  16. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/custom_python_logger/consts.py +0 -0
  17. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/custom_python_logger.egg-info/SOURCES.txt +0 -0
  18. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/custom_python_logger.egg-info/dependency_links.txt +0 -0
  19. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/custom_python_logger.egg-info/top_level.txt +0 -0
  20. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/pyproject.toml +0 -0
  21. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/setup.cfg +0 -0
  22. {custom_python_logger-2.0.3 → custom_python_logger-2.0.5}/tests/test_usage_example_pytest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: custom-python-logger
3
- Version: 2.0.3
3
+ Version: 2.0.5
4
4
  Summary: A custom logger with color support and additional features.
5
5
  Home-page: https://github.com/aviz92/custom-python-logger
6
6
  Author: Avi Zaguri
@@ -12,6 +12,8 @@ License-File: LICENSE
12
12
  Requires-Dist: setuptools
13
13
  Requires-Dist: wheel
14
14
  Requires-Dist: colorlog
15
+ Requires-Dist: python-dotenv
16
+ Requires-Dist: pre-commit
15
17
  Requires-Dist: pytest
16
18
  Requires-Dist: pathlib
17
19
  Requires-Dist: PyYAML
@@ -2,31 +2,28 @@ import json
2
2
  import logging
3
3
  import os
4
4
  import time
5
+ from collections.abc import Callable
5
6
  from logging import Logger
6
7
  from pathlib import Path
7
- from typing import Any, Callable, Optional
8
+ from typing import Any
8
9
 
9
10
  import yaml
10
11
  from colorlog import ColoredFormatter
11
12
 
12
13
  from custom_python_logger.consts import LOG_COLORS, CustomLoggerLevel
13
14
 
15
+ CHILD_LOGGER = "child_logger"
14
16
 
15
- def json_pretty_format(
16
- data: Any, indent: int = 4, sort_keys: bool = True, default: Callable = None
17
- ) -> str:
17
+
18
+ def json_pretty_format(data: Any, indent: int = 4, sort_keys: bool = True, default: Callable = None) -> str:
18
19
  return json.dumps(data, indent=indent, sort_keys=sort_keys, default=default)
19
20
 
20
21
 
21
- def yaml_pretty_format(
22
- data: Any, indent: int = 4, sort_keys: bool = False, allow_unicode=True
23
- ) -> str:
24
- return yaml.dump(
25
- data, sort_keys=sort_keys, indent=indent, allow_unicode=allow_unicode
26
- )
22
+ def yaml_pretty_format(data: Any, indent: int = 4, sort_keys: bool = False, allow_unicode: bool = True) -> str:
23
+ return yaml.dump(data, sort_keys=sort_keys, indent=indent, allow_unicode=allow_unicode)
27
24
 
28
25
 
29
- def get_project_path_by_file(markers: Optional[list[str]] = None) -> Path:
26
+ def get_project_path_by_file(markers: list[str] | None = None) -> Path:
30
27
  if not markers:
31
28
  markers = ["pyproject.toml", "setup.py", ".git", "requirements.txt", ".gitignore", ".github", ".gitlab"]
32
29
  path = Path(__file__).resolve() if "__file__" in globals() else Path.cwd().resolve()
@@ -53,12 +50,12 @@ def print_before_logger(project_name: str) -> None:
53
50
 
54
51
 
55
52
  class CustomLoggerAdapter(logging.LoggerAdapter):
56
- def exception(self, msg: str, *args, **kwargs):
53
+ def exception(self, msg: str, *args: Any, **kwargs: Any) -> None:
57
54
  logging.addLevelName(CustomLoggerLevel.EXCEPTION.value, "EXCEPTION")
58
55
  kwargs.setdefault("stacklevel", 2)
59
56
  self.log(CustomLoggerLevel.EXCEPTION.value, msg, *args, exc_info=True, **kwargs)
60
57
 
61
- def step(self, msg: str, *args, **kwargs):
58
+ def step(self, msg: str, *args: Any, **kwargs: Any) -> None:
62
59
  logging.addLevelName(CustomLoggerLevel.STEP.value, "STEP")
63
60
  kwargs.setdefault("stacklevel", 2)
64
61
  self.log(CustomLoggerLevel.STEP.value, msg, *args, exc_info=False, **kwargs)
@@ -72,7 +69,7 @@ def clear_existing_handlers(logger: Logger) -> None:
72
69
  def add_file_handler_if_specified(
73
70
  logger: Logger,
74
71
  log_file: bool,
75
- log_file_path: Optional[str],
72
+ log_file_path: str | None,
76
73
  log_format: str,
77
74
  ) -> None:
78
75
  if log_file and log_file_path is not None:
@@ -89,11 +86,7 @@ def add_file_handler_if_specified(
89
86
  logger.addHandler(file_handler)
90
87
 
91
88
 
92
- def add_console_handler_if_specified(
93
- logger: Logger,
94
- console_output: bool,
95
- log_format: str
96
- ):
89
+ def add_console_handler_if_specified(logger: Logger, console_output: bool, log_format: str) -> None:
97
90
  if console_output:
98
91
  log_console_formatter = ColoredFormatter(
99
92
  "%(log_color)s " + log_format,
@@ -108,27 +101,24 @@ def add_console_handler_if_specified(
108
101
  def configure_logging(
109
102
  log_format: str,
110
103
  utc: bool,
111
- log_level: int = logging.INFO,
112
104
  log_file: bool = False,
113
- log_file_path: Optional[str] = None,
105
+ log_file_path: str | None = None,
114
106
  console_output: bool = True,
115
107
  ) -> None:
116
108
  """
117
109
  Configure global logging settings.
118
110
 
119
111
  Args:
120
- log_level: Logging level (default: INFO)
121
112
  log_format: Format string for log messages
113
+ utc: Whether to use UTC time for log timestamps
122
114
  log_file: Whether to log to a file
123
115
  log_file_path: Path to log file (if None, no file logging)
124
116
  console_output: Whether to output logs to console
125
- utc: Whether to use UTC time for log timestamps
126
117
  """
127
118
  if utc:
128
119
  logging.Formatter.converter = time.gmtime
129
120
 
130
121
  root_logger = logging.getLogger()
131
- root_logger.setLevel(log_level)
132
122
 
133
123
  clear_existing_handlers(logger=root_logger)
134
124
 
@@ -148,9 +138,9 @@ def configure_logging(
148
138
 
149
139
  def build_logger(
150
140
  project_name: str,
151
- extra: Optional[dict[str, Any]] = None,
152
- log_format: str = "%(asctime)s | %(levelname)-9s | l.%(levelno)s | %(name)s | %(filename)s:%(lineno)s | %(message)s",
153
- log_level: int = logging.INFO,
141
+ extra: dict[str, Any] | None = None,
142
+ log_format: str = "%(asctime)s | %(levelname)-9s | l.%(levelno)s | %(name)s | %(filename)s:%(lineno)s | %(message)s", # pylint: disable=C0301
143
+ log_level: int = logging.DEBUG,
154
144
  log_file: bool = False,
155
145
  log_file_path: str = None,
156
146
  console_output: bool = True,
@@ -176,21 +166,24 @@ def build_logger(
176
166
  log_file_path = log_file_path.lower().replace(" ", "_")
177
167
 
178
168
  configure_logging(
179
- log_level=logging.DEBUG,
180
169
  log_format=log_format,
181
170
  log_file=log_file,
182
171
  log_file_path=log_file_path,
183
172
  console_output=console_output,
184
173
  utc=utc,
185
174
  )
175
+ logger = CustomLoggerAdapter(logging.getLogger(CHILD_LOGGER), extra)
176
+ logger.setLevel(log_level)
186
177
 
187
- logger = logging.getLogger(project_name)
178
+ return logger
188
179
 
189
- if log_level is not None:
190
- logger.setLevel(log_level)
191
180
 
192
- return CustomLoggerAdapter(logger, extra)
181
+ def get_logger(name: str, log_level: int | None = None, extra: dict | None = None) -> CustomLoggerAdapter:
182
+ child_logger = logging.getLogger(CHILD_LOGGER)
183
+ new_logger = CustomLoggerAdapter(logging.getLogger(name), extra=extra)
193
184
 
185
+ if not log_level:
186
+ log_level = child_logger.level
187
+ new_logger.setLevel(log_level)
194
188
 
195
- def get_logger(name: str, extra: Optional[dict] = None) -> CustomLoggerAdapter:
196
- return CustomLoggerAdapter(logging.getLogger(name), extra=extra)
189
+ return new_logger
@@ -4,16 +4,17 @@ from custom_python_logger import build_logger, get_logger
4
4
 
5
5
 
6
6
  class LoggerTest:
7
- def __init__(self):
7
+ def __init__(self) -> None:
8
8
  self.logger = get_logger(self.__class__.__name__, extra={"class": self.__class__.__name__})
9
+ print()
9
10
 
10
- def main(self):
11
+ def main(self) -> None:
11
12
  self.logger.debug("Hello World")
12
13
  self.logger.info("Hello World")
13
14
  self.logger.step("Hello World")
14
15
 
15
16
 
16
- def main():
17
+ def main() -> None:
17
18
  logger = build_logger(
18
19
  project_name="Logger Project Test",
19
20
  log_level=logging.DEBUG,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: custom-python-logger
3
- Version: 2.0.3
3
+ Version: 2.0.5
4
4
  Summary: A custom logger with color support and additional features.
5
5
  Home-page: https://github.com/aviz92/custom-python-logger
6
6
  Author: Avi Zaguri
@@ -12,6 +12,8 @@ License-File: LICENSE
12
12
  Requires-Dist: setuptools
13
13
  Requires-Dist: wheel
14
14
  Requires-Dist: colorlog
15
+ Requires-Dist: python-dotenv
16
+ Requires-Dist: pre-commit
15
17
  Requires-Dist: pytest
16
18
  Requires-Dist: pathlib
17
19
  Requires-Dist: PyYAML
@@ -1,6 +1,8 @@
1
1
  setuptools
2
2
  wheel
3
3
  colorlog
4
+ python-dotenv
5
+ pre-commit
4
6
  pytest
5
7
  pathlib
6
8
  PyYAML
@@ -1,6 +1,8 @@
1
1
  setuptools
2
2
  wheel
3
3
  colorlog
4
+ python-dotenv
5
+ pre-commit
4
6
  pytest
5
7
  pathlib
6
8
  PyYAML
@@ -0,0 +1,35 @@
1
+ from setuptools import find_packages, setup
2
+
3
+ package_version = "2.0.5"
4
+
5
+ package_name = "custom-python-logger"
6
+ package_description = "A custom logger with color support and additional features."
7
+
8
+ package_name_ = package_name.replace("-", "_")
9
+ package_long_description_content_type = "text/markdown"
10
+ package_url = f"https://github.com/aviz92/{package_name}"
11
+ package_python_requires = ">=3.11"
12
+ package_author = "Avi Zaguri"
13
+
14
+ with open("requirements.txt") as file:
15
+ package_install_requires = [line.strip() for line in file.readlines() if line.strip() and not line.startswith("#")]
16
+
17
+ with open("README.md") as file:
18
+ package_long_description = file.read()
19
+
20
+ setup(
21
+ name=package_name,
22
+ version=package_version,
23
+ packages=find_packages(include=[package_name_, f"{package_name_}.*"]),
24
+ install_requires=package_install_requires,
25
+ author=package_author,
26
+ author_email="",
27
+ description=package_description,
28
+ long_description=package_long_description,
29
+ long_description_content_type=package_long_description_content_type,
30
+ url=package_url,
31
+ project_urls={
32
+ "Repository": package_url,
33
+ },
34
+ python_requires=package_python_requires,
35
+ )
@@ -0,0 +1,27 @@
1
+ import unittest
2
+
3
+ from custom_python_logger import build_logger
4
+
5
+
6
+ class TestLogger(unittest.TestCase):
7
+ def test_logger_creation(self):
8
+ logger = build_logger(project_name="TestProject")
9
+ self.assertIsNotNone(logger)
10
+ self.assertEqual(logger.name, "root")
11
+
12
+ def test_step_log(self):
13
+ logger = build_logger(project_name="TestProject")
14
+ logger.step("Testing step log")
15
+ self.assertTrue(True) # pylint: disable=W1503
16
+
17
+ def test_exception_log(self):
18
+ logger = build_logger(project_name="TestProject")
19
+ try:
20
+ raise ValueError("Test exception")
21
+ except ValueError as e:
22
+ logger.exception(f"Exception occurred: {e}")
23
+ self.assertTrue(True) # pylint: disable=W1503
24
+
25
+
26
+ if __name__ == "__main__":
27
+ unittest.main()
@@ -1,17 +1,12 @@
1
+ import datetime
1
2
  import logging
2
3
  import os
3
4
  import tempfile
4
5
  import time
5
- from datetime import timezone
6
6
 
7
7
  import pytest
8
8
 
9
- from custom_python_logger import (
10
- CustomLoggerAdapter,
11
- build_logger,
12
- json_pretty_format,
13
- yaml_pretty_format,
14
- )
9
+ from custom_python_logger import CustomLoggerAdapter, build_logger, json_pretty_format, yaml_pretty_format
15
10
 
16
11
 
17
12
  @pytest.fixture
@@ -76,10 +71,8 @@ def test_exception_log_2(caplog):
76
71
  assert any("EXCEPTION" in r.levelname for r in caplog.records)
77
72
 
78
73
 
79
- def test_log_to_file(temp_log_file):
80
- logger = build_logger(
81
- project_name="FileTest", log_file=True, log_file_path=temp_log_file
82
- )
74
+ def test_log_to_file(temp_log_file): # pylint: disable=W0621
75
+ logger = build_logger(project_name="FileTest", log_file=True, log_file_path=temp_log_file)
83
76
  logger.info("File log message")
84
77
  time.sleep(0.1)
85
78
  with open(temp_log_file) as f:
@@ -87,26 +80,20 @@ def test_log_to_file(temp_log_file):
87
80
  assert "File log message" in content
88
81
 
89
82
 
90
- def test_utc_logging(temp_log_file):
91
- logger = build_logger(
92
- project_name="UTCTest", log_file=True, log_file_path=temp_log_file, utc=True
93
- )
83
+ def test_utc_logging(temp_log_file): # pylint: disable=W0621
84
+ logger = build_logger(project_name="UTCTest", log_file=True, log_file_path=temp_log_file, utc=True)
94
85
  logger.info("UTC log message")
95
86
  time.sleep(0.1)
96
87
  with open(temp_log_file) as f:
97
88
  content = f.read()
98
89
  assert "UTC log message" in content
99
90
  # Check for a year in UTC (should be close to now)
100
- import datetime
101
-
102
- now_utc = datetime.datetime.now(tz=timezone.utc).strftime("%Y")
91
+ now_utc = datetime.datetime.now(tz=datetime.UTC).strftime("%Y")
103
92
  assert now_utc in content
104
93
 
105
94
 
106
95
  def test_extra_context(caplog):
107
- logger = build_logger(
108
- project_name="ExtraTest", extra={"user": "pytest"}, console_output=False
109
- )
96
+ logger = build_logger(project_name="ExtraTest", extra={"user": "pytest"}, console_output=False)
110
97
  logging.getLogger().addHandler(caplog.handler)
111
98
  with caplog.at_level(logging.INFO):
112
99
  logger.info("With extra")
@@ -1,37 +0,0 @@
1
- from setuptools import setup, find_packages
2
-
3
- package_version = '2.0.3'
4
-
5
- package_name = 'custom-python-logger'
6
- package_description = 'A custom logger with color support and additional features.'
7
-
8
- package_name_ = package_name.replace('-', '_')
9
- package_long_description_content_type = 'text/markdown'
10
- package_url = f'https://github.com/aviz92/{package_name}'
11
- package_python_requires = '>=3.11'
12
- package_author = 'Avi Zaguri'
13
-
14
- with open('requirements.txt', 'r') as file:
15
- package_install_requires = [
16
- line.strip() for line in file.readlines() if line.strip() and not line.startswith('#')
17
- ]
18
-
19
- with open('README.md', 'r') as file:
20
- package_long_description = file.read()
21
-
22
- setup(
23
- name=package_name,
24
- version=package_version,
25
- packages=find_packages(include=[package_name_, f'{package_name_}.*']),
26
- install_requires=package_install_requires,
27
- author=package_author,
28
- author_email='',
29
- description=package_description,
30
- long_description=package_long_description,
31
- long_description_content_type=package_long_description_content_type,
32
- url=package_url,
33
- project_urls={
34
- 'Repository': package_url,
35
- },
36
- python_requires=package_python_requires,
37
- )
@@ -1,26 +0,0 @@
1
- import unittest
2
- from custom_python_logger import build_logger
3
-
4
-
5
- class TestLogger(unittest.TestCase):
6
- def test_logger_creation(self):
7
- logger = build_logger(project_name='TestProject')
8
- self.assertIsNotNone(logger)
9
- self.assertEqual(logger.name, 'root')
10
-
11
- def test_step_log(self):
12
- logger = build_logger(project_name='TestProject')
13
- logger.step('Testing step log')
14
- self.assertTrue(True) # You can add more specific checks for actual logging output
15
-
16
- def test_exception_log(self):
17
- logger = build_logger(project_name='TestProject')
18
- try:
19
- raise ValueError("Test exception")
20
- except ValueError as e:
21
- logger.exception(f"Exception occurred: {e}")
22
- self.assertTrue(True) # You can add more specific checks for actual logging output
23
-
24
-
25
- if __name__ == '__main__':
26
- unittest.main()