custom-python-logger 1.0.10__tar.gz → 2.0.0__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 (23) hide show
  1. custom_python_logger-2.0.0/PKG-INFO +139 -0
  2. custom_python_logger-2.0.0/README.md +112 -0
  3. custom_python_logger-2.0.0/custom_python_logger/__init__.py +15 -0
  4. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/custom_python_logger/logger.py +48 -46
  5. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/custom_python_logger/usage_example.py +10 -8
  6. custom_python_logger-2.0.0/custom_python_logger.egg-info/PKG-INFO +139 -0
  7. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/custom_python_logger.egg-info/SOURCES.txt +3 -1
  8. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/setup.py +1 -1
  9. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/tests/test_logger.py +4 -4
  10. custom_python_logger-2.0.0/tests/test_logger_pytest.py +126 -0
  11. custom_python_logger-2.0.0/tests/test_usage_example_pytest.py +8 -0
  12. custom_python_logger-1.0.10/PKG-INFO +0 -83
  13. custom_python_logger-1.0.10/README.md +0 -56
  14. custom_python_logger-1.0.10/custom_python_logger/__init__.py +0 -10
  15. custom_python_logger-1.0.10/custom_python_logger.egg-info/PKG-INFO +0 -83
  16. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/LICENSE +0 -0
  17. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/MANIFEST.in +0 -0
  18. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/custom_python_logger.egg-info/dependency_links.txt +0 -0
  19. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/custom_python_logger.egg-info/requires.txt +0 -0
  20. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/custom_python_logger.egg-info/top_level.txt +0 -0
  21. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/pyproject.toml +0 -0
  22. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/requirements.txt +0 -0
  23. {custom_python_logger-1.0.10 → custom_python_logger-2.0.0}/setup.cfg +0 -0
@@ -0,0 +1,139 @@
1
+ Metadata-Version: 2.4
2
+ Name: custom-python-logger
3
+ Version: 2.0.0
4
+ Summary: A custom logger with color support and additional features.
5
+ Home-page: https://github.com/aviz92/custom-python-logger
6
+ Author: Avi Zaguri
7
+ Author-email:
8
+ Project-URL: Repository, https://github.com/aviz92/custom-python-logger
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: setuptools
13
+ Requires-Dist: wheel
14
+ Requires-Dist: colorlog
15
+ Requires-Dist: pytest
16
+ Requires-Dist: pathlib
17
+ Requires-Dist: PyYAML
18
+ Dynamic: author
19
+ Dynamic: description
20
+ Dynamic: description-content-type
21
+ Dynamic: home-page
22
+ Dynamic: license-file
23
+ Dynamic: project-url
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
27
+
28
+ # custom-python-logger
29
+ A powerful and flexible Python logger with colored output, custom log levels, and advanced configuration options. <br>
30
+ Easily integrate structured, readable, and context-rich logging into your Python projects for better debugging and monitoring.
31
+
32
+ ---
33
+
34
+ ## 🚀 Features
35
+ - ✅ **Colored Output**: Beautiful, readable logs in your terminal using `colorlog`.
36
+ - ✅ **Custom Log Levels**: Includes `STEP` (for process steps) and `EXCEPTION` (for exception tracking) in addition to standard levels.
37
+ - ✅ **Flexible Output**: Log to console, file, or both. Supports custom log file paths and automatic log directory creation.
38
+ - ✅ **Contextual Logging**: Add extra fields (like user, environment, etc.) to every log message.
39
+ - ✅ **UTC Support**: Optionally log timestamps in UTC for consistency across environments.
40
+ - ✅ **Pretty Formatting**: Built-in helpers for pretty-printing JSON and YAML data in logs.
41
+ - ✅ **Easy Integration**: Simple API for getting a ready-to-use logger anywhere in your codebase.
42
+
43
+ ---
44
+
45
+ ## 📦 Installation
46
+ ```bash
47
+ pip install custom-python-logger
48
+ ```
49
+
50
+ ---
51
+
52
+ ### 🔧 Usage
53
+ Here's a quick example of how to use `custom-python-logger` in your project:
54
+
55
+ ```python
56
+ import logging
57
+ from custom_python_logger import build_logger, CustomLoggerAdapter
58
+
59
+ logger: CustomLoggerAdapter = build_logger(
60
+ project_name='Logger Project Test',
61
+ log_level=logging.DEBUG,
62
+ log_file=True,
63
+ )
64
+
65
+ logger.debug("This is a debug message.")
66
+ logger.info("This is an info message.")
67
+ logger.step("This is a step message.")
68
+ logger.warning("This is a warning message.")
69
+
70
+ try:
71
+ _ = 1 / 0
72
+ except ZeroDivisionError:
73
+ logger.exception("This is an exception message.")
74
+
75
+ logger.critical("This is a critical message.")
76
+ ```
77
+
78
+ #### Advanced Usage
79
+ - Log to a file:
80
+ ```python
81
+ from custom_python_logger import build_logger
82
+
83
+ logger = build_logger(project_name='MyApp', log_file=True)
84
+ ```
85
+
86
+ - Use UTC timestamps:
87
+ ```python
88
+ from custom_python_logger import build_logger
89
+
90
+ logger = build_logger(project_name='MyApp', log_file=True, utc=True)
91
+ ```
92
+
93
+ - Add extra context:
94
+ ```python
95
+ from custom_python_logger import build_logger
96
+
97
+ logger = build_logger(project_name='MyApp', log_file=True, utc=True, extra={'user': 'alice'})
98
+ ```
99
+
100
+ - Pretty-print JSON or YAML:
101
+ ```python
102
+ from custom_python_logger import build_logger, json_pretty_format, yaml_pretty_format
103
+
104
+ logger = build_logger(project_name='MyApp', utc=True, log_file=True)
105
+
106
+ logger.info(json_pretty_format({'foo': 'bar'}))
107
+ logger.info(yaml_pretty_format({'foo': 'bar'}))
108
+ ```
109
+
110
+ - use an existing logger (CustomLoggerAdapter) and set a custom name:
111
+ ```python
112
+ from custom_python_logger import get_logger
113
+
114
+ logger = get_logger('some-name')
115
+
116
+ logger.debug("This is a debug message.")
117
+ logger.info("This is an info message.")
118
+ logger.step("This is a step message.")
119
+ ```
120
+
121
+ ---
122
+
123
+ ## 🤝 Contributing
124
+ If you have a helpful tool, pattern, or improvement to suggest:
125
+ Fork the repo <br>
126
+ Create a new branch <br>
127
+ Submit a pull request <br>
128
+ I welcome additions that promote clean, productive, and maintainable development. <br>
129
+
130
+ ---
131
+
132
+ ## 📄 License
133
+ MIT License — see [LICENSE](LICENSE) for details.
134
+
135
+ ---
136
+
137
+ ## 🙏 Thanks
138
+ Thanks for exploring this repository! <br>
139
+ Happy coding! <br>
@@ -0,0 +1,112 @@
1
+ # custom-python-logger
2
+ A powerful and flexible Python logger with colored output, custom log levels, and advanced configuration options. <br>
3
+ Easily integrate structured, readable, and context-rich logging into your Python projects for better debugging and monitoring.
4
+
5
+ ---
6
+
7
+ ## 🚀 Features
8
+ - ✅ **Colored Output**: Beautiful, readable logs in your terminal using `colorlog`.
9
+ - ✅ **Custom Log Levels**: Includes `STEP` (for process steps) and `EXCEPTION` (for exception tracking) in addition to standard levels.
10
+ - ✅ **Flexible Output**: Log to console, file, or both. Supports custom log file paths and automatic log directory creation.
11
+ - ✅ **Contextual Logging**: Add extra fields (like user, environment, etc.) to every log message.
12
+ - ✅ **UTC Support**: Optionally log timestamps in UTC for consistency across environments.
13
+ - ✅ **Pretty Formatting**: Built-in helpers for pretty-printing JSON and YAML data in logs.
14
+ - ✅ **Easy Integration**: Simple API for getting a ready-to-use logger anywhere in your codebase.
15
+
16
+ ---
17
+
18
+ ## 📦 Installation
19
+ ```bash
20
+ pip install custom-python-logger
21
+ ```
22
+
23
+ ---
24
+
25
+ ### 🔧 Usage
26
+ Here's a quick example of how to use `custom-python-logger` in your project:
27
+
28
+ ```python
29
+ import logging
30
+ from custom_python_logger import build_logger, CustomLoggerAdapter
31
+
32
+ logger: CustomLoggerAdapter = build_logger(
33
+ project_name='Logger Project Test',
34
+ log_level=logging.DEBUG,
35
+ log_file=True,
36
+ )
37
+
38
+ logger.debug("This is a debug message.")
39
+ logger.info("This is an info message.")
40
+ logger.step("This is a step message.")
41
+ logger.warning("This is a warning message.")
42
+
43
+ try:
44
+ _ = 1 / 0
45
+ except ZeroDivisionError:
46
+ logger.exception("This is an exception message.")
47
+
48
+ logger.critical("This is a critical message.")
49
+ ```
50
+
51
+ #### Advanced Usage
52
+ - Log to a file:
53
+ ```python
54
+ from custom_python_logger import build_logger
55
+
56
+ logger = build_logger(project_name='MyApp', log_file=True)
57
+ ```
58
+
59
+ - Use UTC timestamps:
60
+ ```python
61
+ from custom_python_logger import build_logger
62
+
63
+ logger = build_logger(project_name='MyApp', log_file=True, utc=True)
64
+ ```
65
+
66
+ - Add extra context:
67
+ ```python
68
+ from custom_python_logger import build_logger
69
+
70
+ logger = build_logger(project_name='MyApp', log_file=True, utc=True, extra={'user': 'alice'})
71
+ ```
72
+
73
+ - Pretty-print JSON or YAML:
74
+ ```python
75
+ from custom_python_logger import build_logger, json_pretty_format, yaml_pretty_format
76
+
77
+ logger = build_logger(project_name='MyApp', utc=True, log_file=True)
78
+
79
+ logger.info(json_pretty_format({'foo': 'bar'}))
80
+ logger.info(yaml_pretty_format({'foo': 'bar'}))
81
+ ```
82
+
83
+ - use an existing logger (CustomLoggerAdapter) and set a custom name:
84
+ ```python
85
+ from custom_python_logger import get_logger
86
+
87
+ logger = get_logger('some-name')
88
+
89
+ logger.debug("This is a debug message.")
90
+ logger.info("This is an info message.")
91
+ logger.step("This is a step message.")
92
+ ```
93
+
94
+ ---
95
+
96
+ ## 🤝 Contributing
97
+ If you have a helpful tool, pattern, or improvement to suggest:
98
+ Fork the repo <br>
99
+ Create a new branch <br>
100
+ Submit a pull request <br>
101
+ I welcome additions that promote clean, productive, and maintainable development. <br>
102
+
103
+ ---
104
+
105
+ ## 📄 License
106
+ MIT License — see [LICENSE](LICENSE) for details.
107
+
108
+ ---
109
+
110
+ ## 🙏 Thanks
111
+ Thanks for exploring this repository! <br>
112
+ Happy coding! <br>
@@ -0,0 +1,15 @@
1
+ from custom_python_logger.logger import (
2
+ CustomLoggerAdapter,
3
+ build_logger,
4
+ get_logger,
5
+ json_pretty_format,
6
+ yaml_pretty_format,
7
+ )
8
+
9
+ __all__ = [
10
+ "build_logger",
11
+ "get_logger",
12
+ "CustomLoggerAdapter",
13
+ "json_pretty_format",
14
+ "yaml_pretty_format",
15
+ ]
@@ -1,19 +1,21 @@
1
- # logger.py
2
1
  import json
3
2
  import logging
4
3
  import os
5
4
  import time
6
- from logging import LoggerAdapter, Logger
5
+ from logging import Logger, LoggerAdapter
7
6
  from pathlib import Path
8
- from typing import Optional, Any
7
+ from typing import Any, Callable, Optional
8
+
9
9
  import yaml
10
10
  from colorlog import ColoredFormatter
11
11
 
12
12
 
13
- def get_root_project_path() -> Path:
14
- if 'venv' in str(Path(__file__)):
15
- return Path(__file__).parents[5]
16
- return Path(__file__).parent
13
+ def get_project_path_by_file(marker: str = ".git") -> Path:
14
+ path = Path(__file__).resolve()
15
+ for parent in path.parents:
16
+ if (parent / marker).exists():
17
+ return parent
18
+ raise RuntimeError(f"Project root with marker '{marker}' not found.")
17
19
 
18
20
 
19
21
  def print_before_logger(project_name: str) -> None:
@@ -30,23 +32,23 @@ class CustomLoggerAdapter(logging.LoggerAdapter):
30
32
  def exception(self, msg: str, *args, **kwargs):
31
33
  level_no = 45
32
34
  logging.addLevelName(level_no, "EXCEPTION")
33
- kwargs.setdefault('stacklevel', 2)
35
+ kwargs.setdefault("stacklevel", 2)
34
36
  self.log(level_no, msg, *args, exc_info=True, **kwargs)
35
37
 
36
38
  def step(self, msg: str, *args, **kwargs):
37
39
  level_no = 25
38
40
  logging.addLevelName(level_no, "STEP")
39
- kwargs.setdefault('stacklevel', 2)
41
+ kwargs.setdefault("stacklevel", 2)
40
42
  self.log(level_no, msg, *args, exc_info=False, **kwargs)
41
43
 
42
44
 
43
45
  def configure_logging(
44
- log_format: str,
45
- utc: bool,
46
- log_level: int = logging.INFO,
47
- log_file: bool = False,
48
- log_file_path: Optional[str] = None,
49
- console_output: bool = True,
46
+ log_format: str,
47
+ utc: bool,
48
+ log_level: int = logging.INFO,
49
+ log_file: bool = False,
50
+ log_file_path: Optional[str] = None,
51
+ console_output: bool = True,
50
52
  ) -> None:
51
53
  """
52
54
  Configure global logging settings.
@@ -87,16 +89,16 @@ def configure_logging(
87
89
  if console_output:
88
90
  # log_console_formatter = logging.Formatter('%(log_color)s ' + log_format)
89
91
  log_console_formatter = ColoredFormatter(
90
- '%(log_color)s ' + log_format,
92
+ "%(log_color)s " + log_format,
91
93
  log_colors={
92
- 'DEBUG': 'white',
93
- 'INFO': 'green',
94
- 'WARNING': 'yellow',
95
- 'STEP': 'blue',
96
- 'ERROR': 'red,bold',
97
- 'EXCEPTION': 'light_red,bold',
98
- 'CRITICAL': 'red,bg_white',
99
- }
94
+ "DEBUG": "white",
95
+ "INFO": "green",
96
+ "WARNING": "yellow",
97
+ "STEP": "blue",
98
+ "ERROR": "red,bold",
99
+ "EXCEPTION": "light_red,bold",
100
+ "CRITICAL": "red,bg_white",
101
+ },
100
102
  )
101
103
 
102
104
  console_handler = logging.StreamHandler()
@@ -104,16 +106,16 @@ def configure_logging(
104
106
  root_logger.addHandler(console_handler)
105
107
 
106
108
 
107
- def get_logger(
108
- project_name: str,
109
- extra: Optional[dict[str, Any]] = None,
110
- log_format: str = "%(asctime)s | %(levelname)-10s(l.%(levelno)s) | %(filename)s:%(lineno)s | %(message)s",
111
- log_level: int = logging.INFO,
112
- log_file: bool = False,
113
- log_file_path: str = None,
114
- console_output: bool = True,
115
- utc: bool = False,
116
- ) -> CustomLoggerAdapter[Logger | LoggerAdapter[Any] | Any] | Logger:
109
+ def build_logger(
110
+ project_name: str,
111
+ extra: Optional[dict[str, Any]] = None,
112
+ log_format: str = "%(asctime)s | %(levelname)-10s(l.%(levelno)s) | %(name)s | %(filename)s:%(lineno)s | %(message)s",
113
+ log_level: int = logging.INFO,
114
+ log_file: bool = False,
115
+ log_file_path: str = None,
116
+ console_output: bool = True,
117
+ utc: bool = False,
118
+ ) -> CustomLoggerAdapter | Logger:
117
119
  """
118
120
  Get a named logger with optional extra context.
119
121
 
@@ -133,8 +135,8 @@ def get_logger(
133
135
  print_before_logger(project_name=project_name)
134
136
 
135
137
  if not log_file_path:
136
- log_file_path = f'{get_root_project_path()}/logs/{project_name}.log'
137
- log_file_path = log_file_path.lower().replace(' ', '_')
138
+ log_file_path = f"{get_project_path_by_file()}/logs/{project_name}.log"
139
+ log_file_path = log_file_path.lower().replace(" ", "_")
138
140
 
139
141
  configure_logging(
140
142
  log_level=logging.DEBUG,
@@ -142,7 +144,7 @@ def get_logger(
142
144
  log_file=log_file,
143
145
  log_file_path=log_file_path,
144
146
  console_output=console_output,
145
- utc=utc
147
+ utc=utc,
146
148
  )
147
149
 
148
150
  logger = logging.getLogger()
@@ -153,19 +155,19 @@ def get_logger(
153
155
  return CustomLoggerAdapter(logger, extra)
154
156
 
155
157
 
158
+ def get_logger(name: str) -> CustomLoggerAdapter:
159
+ return CustomLoggerAdapter(logging.getLogger(name), {})
160
+
161
+
156
162
  def json_pretty_format(
157
- data: any,
158
- indent: int = 4,
159
- sort_keys: bool = True,
160
- default: callable = None
163
+ data: Any, indent: int = 4, sort_keys: bool = True, default: Callable = None
161
164
  ) -> str:
162
165
  return json.dumps(data, indent=indent, sort_keys=sort_keys, default=default)
163
166
 
164
167
 
165
168
  def yaml_pretty_format(
166
- data: any,
167
- indent: int = 4,
168
- sort_keys: bool = False,
169
- allow_unicode=True
169
+ data: Any, indent: int = 4, sort_keys: bool = False, allow_unicode=True
170
170
  ) -> str:
171
- return yaml.dump(data, sort_keys=sort_keys, indent=indent, allow_unicode=allow_unicode)
171
+ return yaml.dump(
172
+ data, sort_keys=sort_keys, indent=indent, allow_unicode=allow_unicode
173
+ )
@@ -1,21 +1,23 @@
1
1
  import logging
2
2
 
3
+ from custom_python_logger import build_logger, get_logger
4
+
3
5
 
4
6
  class LoggerTest:
5
7
  def __init__(self):
6
- self.logger = logging.getLogger(self.__class__.__name__)
8
+ self.logger = get_logger(self.__class__.__name__)
7
9
 
8
10
  def main(self):
9
- self.logger.info('Hello World')
10
- self.logger.debug('Hello World')
11
+ self.logger.debug("Hello World")
12
+ self.logger.info("Hello World")
13
+ self.logger.step("Hello World")
11
14
 
12
15
 
13
16
  def main():
14
- from custom_python_logger.logger import get_logger
15
-
16
- logger = get_logger(
17
- project_name='Logger Project Test',
17
+ logger = build_logger(
18
+ project_name="Logger Project Test",
18
19
  log_level=logging.DEBUG,
20
+ log_file=True,
19
21
  # extra={'user': 'test_user'}
20
22
  )
21
23
 
@@ -35,5 +37,5 @@ def main():
35
37
  logger_test.main()
36
38
 
37
39
 
38
- if __name__ == '__main__':
40
+ if __name__ == "__main__":
39
41
  main()
@@ -0,0 +1,139 @@
1
+ Metadata-Version: 2.4
2
+ Name: custom-python-logger
3
+ Version: 2.0.0
4
+ Summary: A custom logger with color support and additional features.
5
+ Home-page: https://github.com/aviz92/custom-python-logger
6
+ Author: Avi Zaguri
7
+ Author-email:
8
+ Project-URL: Repository, https://github.com/aviz92/custom-python-logger
9
+ Requires-Python: >=3.11
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: setuptools
13
+ Requires-Dist: wheel
14
+ Requires-Dist: colorlog
15
+ Requires-Dist: pytest
16
+ Requires-Dist: pathlib
17
+ Requires-Dist: PyYAML
18
+ Dynamic: author
19
+ Dynamic: description
20
+ Dynamic: description-content-type
21
+ Dynamic: home-page
22
+ Dynamic: license-file
23
+ Dynamic: project-url
24
+ Dynamic: requires-dist
25
+ Dynamic: requires-python
26
+ Dynamic: summary
27
+
28
+ # custom-python-logger
29
+ A powerful and flexible Python logger with colored output, custom log levels, and advanced configuration options. <br>
30
+ Easily integrate structured, readable, and context-rich logging into your Python projects for better debugging and monitoring.
31
+
32
+ ---
33
+
34
+ ## 🚀 Features
35
+ - ✅ **Colored Output**: Beautiful, readable logs in your terminal using `colorlog`.
36
+ - ✅ **Custom Log Levels**: Includes `STEP` (for process steps) and `EXCEPTION` (for exception tracking) in addition to standard levels.
37
+ - ✅ **Flexible Output**: Log to console, file, or both. Supports custom log file paths and automatic log directory creation.
38
+ - ✅ **Contextual Logging**: Add extra fields (like user, environment, etc.) to every log message.
39
+ - ✅ **UTC Support**: Optionally log timestamps in UTC for consistency across environments.
40
+ - ✅ **Pretty Formatting**: Built-in helpers for pretty-printing JSON and YAML data in logs.
41
+ - ✅ **Easy Integration**: Simple API for getting a ready-to-use logger anywhere in your codebase.
42
+
43
+ ---
44
+
45
+ ## 📦 Installation
46
+ ```bash
47
+ pip install custom-python-logger
48
+ ```
49
+
50
+ ---
51
+
52
+ ### 🔧 Usage
53
+ Here's a quick example of how to use `custom-python-logger` in your project:
54
+
55
+ ```python
56
+ import logging
57
+ from custom_python_logger import build_logger, CustomLoggerAdapter
58
+
59
+ logger: CustomLoggerAdapter = build_logger(
60
+ project_name='Logger Project Test',
61
+ log_level=logging.DEBUG,
62
+ log_file=True,
63
+ )
64
+
65
+ logger.debug("This is a debug message.")
66
+ logger.info("This is an info message.")
67
+ logger.step("This is a step message.")
68
+ logger.warning("This is a warning message.")
69
+
70
+ try:
71
+ _ = 1 / 0
72
+ except ZeroDivisionError:
73
+ logger.exception("This is an exception message.")
74
+
75
+ logger.critical("This is a critical message.")
76
+ ```
77
+
78
+ #### Advanced Usage
79
+ - Log to a file:
80
+ ```python
81
+ from custom_python_logger import build_logger
82
+
83
+ logger = build_logger(project_name='MyApp', log_file=True)
84
+ ```
85
+
86
+ - Use UTC timestamps:
87
+ ```python
88
+ from custom_python_logger import build_logger
89
+
90
+ logger = build_logger(project_name='MyApp', log_file=True, utc=True)
91
+ ```
92
+
93
+ - Add extra context:
94
+ ```python
95
+ from custom_python_logger import build_logger
96
+
97
+ logger = build_logger(project_name='MyApp', log_file=True, utc=True, extra={'user': 'alice'})
98
+ ```
99
+
100
+ - Pretty-print JSON or YAML:
101
+ ```python
102
+ from custom_python_logger import build_logger, json_pretty_format, yaml_pretty_format
103
+
104
+ logger = build_logger(project_name='MyApp', utc=True, log_file=True)
105
+
106
+ logger.info(json_pretty_format({'foo': 'bar'}))
107
+ logger.info(yaml_pretty_format({'foo': 'bar'}))
108
+ ```
109
+
110
+ - use an existing logger (CustomLoggerAdapter) and set a custom name:
111
+ ```python
112
+ from custom_python_logger import get_logger
113
+
114
+ logger = get_logger('some-name')
115
+
116
+ logger.debug("This is a debug message.")
117
+ logger.info("This is an info message.")
118
+ logger.step("This is a step message.")
119
+ ```
120
+
121
+ ---
122
+
123
+ ## 🤝 Contributing
124
+ If you have a helpful tool, pattern, or improvement to suggest:
125
+ Fork the repo <br>
126
+ Create a new branch <br>
127
+ Submit a pull request <br>
128
+ I welcome additions that promote clean, productive, and maintainable development. <br>
129
+
130
+ ---
131
+
132
+ ## 📄 License
133
+ MIT License — see [LICENSE](LICENSE) for details.
134
+
135
+ ---
136
+
137
+ ## 🙏 Thanks
138
+ Thanks for exploring this repository! <br>
139
+ Happy coding! <br>
@@ -12,4 +12,6 @@ custom_python_logger.egg-info/SOURCES.txt
12
12
  custom_python_logger.egg-info/dependency_links.txt
13
13
  custom_python_logger.egg-info/requires.txt
14
14
  custom_python_logger.egg-info/top_level.txt
15
- tests/test_logger.py
15
+ tests/test_logger.py
16
+ tests/test_logger_pytest.py
17
+ tests/test_usage_example_pytest.py
@@ -1,6 +1,6 @@
1
1
  from setuptools import setup, find_packages
2
2
 
3
- package_version = '1.0.10'
3
+ package_version = '2.0.0'
4
4
 
5
5
  package_name = 'custom-python-logger'
6
6
  package_description = 'A custom logger with color support and additional features.'
@@ -1,20 +1,20 @@
1
1
  import unittest
2
- from custom_python_logger import get_logger
2
+ from custom_python_logger import build_logger
3
3
 
4
4
 
5
5
  class TestLogger(unittest.TestCase):
6
6
  def test_logger_creation(self):
7
- logger = get_logger(project_name='TestProject')
7
+ logger = build_logger(project_name='TestProject')
8
8
  self.assertIsNotNone(logger)
9
9
  self.assertEqual(logger.name, 'root')
10
10
 
11
11
  def test_step_log(self):
12
- logger = get_logger(project_name='TestProject')
12
+ logger = build_logger(project_name='TestProject')
13
13
  logger.step('Testing step log')
14
14
  self.assertTrue(True) # You can add more specific checks for actual logging output
15
15
 
16
16
  def test_exception_log(self):
17
- logger = get_logger(project_name='TestProject')
17
+ logger = build_logger(project_name='TestProject')
18
18
  try:
19
19
  raise ValueError("Test exception")
20
20
  except ValueError as e:
@@ -0,0 +1,126 @@
1
+ import logging
2
+ import os
3
+ import tempfile
4
+ import time
5
+ from datetime import timezone
6
+
7
+ import pytest
8
+
9
+ from custom_python_logger import (
10
+ CustomLoggerAdapter,
11
+ build_logger,
12
+ json_pretty_format,
13
+ yaml_pretty_format,
14
+ )
15
+
16
+
17
+ @pytest.fixture
18
+ def temp_log_file():
19
+ with tempfile.NamedTemporaryFile(delete=False) as f:
20
+ yield f.name
21
+ os.remove(f.name)
22
+
23
+
24
+ def test_logger_creation():
25
+ logger = build_logger(project_name="PytestTest")
26
+ assert logger is not None
27
+ assert isinstance(logger, CustomLoggerAdapter)
28
+ assert hasattr(logger, "step")
29
+ assert hasattr(logger, "exception")
30
+
31
+
32
+ def test_step_log(caplog):
33
+ logger = build_logger(project_name="PytestTest", console_output=False)
34
+ if not isinstance(logger, CustomLoggerAdapter):
35
+ raise AssertionError("Logger is not a CustomLoggerAdapter")
36
+ # Attach caplog.handler
37
+ logging.getLogger().addHandler(caplog.handler)
38
+ with caplog.at_level(logging.INFO):
39
+ logger.step("Step message")
40
+ assert any("Step message" in m for m in caplog.messages)
41
+ assert any("STEP" in r.levelname for r in caplog.records)
42
+
43
+
44
+ def test_step_log_2(caplog):
45
+ logger = build_logger(project_name="TestProject", console_output=False)
46
+ if not isinstance(logger, CustomLoggerAdapter):
47
+ raise AssertionError("Logger is not a CustomLoggerAdapter")
48
+ logging.getLogger().addHandler(caplog.handler)
49
+ with caplog.at_level(logging.INFO):
50
+ logger.step("Testing step log")
51
+ assert any("Testing step log" in m for m in caplog.messages)
52
+ assert any("STEP" in r.levelname for r in caplog.records)
53
+
54
+
55
+ def test_exception_log(caplog):
56
+ logger = build_logger(project_name="PytestTest", console_output=False)
57
+ logging.getLogger().addHandler(caplog.handler)
58
+ with caplog.at_level(logging.ERROR):
59
+ try:
60
+ raise RuntimeError("fail")
61
+ except RuntimeError:
62
+ logger.exception("Exception message")
63
+ assert any("Exception message" in m for m in caplog.messages)
64
+ assert any("EXCEPTION" in r.levelname for r in caplog.records)
65
+
66
+
67
+ def test_exception_log_2(caplog):
68
+ logger = build_logger(project_name="TestProject", console_output=False)
69
+ logging.getLogger().addHandler(caplog.handler)
70
+ with caplog.at_level(logging.ERROR):
71
+ try:
72
+ raise ValueError("Test exception")
73
+ except ValueError as e:
74
+ logger.exception(f"Exception occurred: {e}")
75
+ assert any("Exception occurred: Test exception" in m for m in caplog.messages)
76
+ assert any("EXCEPTION" in r.levelname for r in caplog.records)
77
+
78
+
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
+ )
83
+ logger.info("File log message")
84
+ time.sleep(0.1)
85
+ with open(temp_log_file) as f:
86
+ content = f.read()
87
+ assert "File log message" in content
88
+
89
+
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
+ )
94
+ logger.info("UTC log message")
95
+ time.sleep(0.1)
96
+ with open(temp_log_file) as f:
97
+ content = f.read()
98
+ assert "UTC log message" in content
99
+ # 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")
103
+ assert now_utc in content
104
+
105
+
106
+ def test_extra_context(caplog):
107
+ logger = build_logger(
108
+ project_name="ExtraTest", extra={"user": "pytest"}, console_output=False
109
+ )
110
+ logging.getLogger().addHandler(caplog.handler)
111
+ with caplog.at_level(logging.INFO):
112
+ logger.info("With extra")
113
+ assert any("With extra" in m for m in caplog.messages)
114
+ # The extra field is not in the default format, but test that logger works with extra
115
+
116
+
117
+ def test_json_pretty_format():
118
+ data = {"a": 1, "b": 2}
119
+ result = json_pretty_format(data)
120
+ assert "{" in result and "a" in result and "b" in result
121
+
122
+
123
+ def test_yaml_pretty_format():
124
+ data = {"a": 1, "b": 2}
125
+ result = yaml_pretty_format(data)
126
+ assert "a:" in result and "b:" in result
@@ -0,0 +1,8 @@
1
+ from custom_python_logger.usage_example import main
2
+
3
+
4
+ def test_usage_example_runs(monkeypatch):
5
+ # Patch print and time.sleep to avoid side effects
6
+ monkeypatch.setattr("builtins.print", lambda *a, **k: None)
7
+ monkeypatch.setattr("time.sleep", lambda x: None)
8
+ main() # Should not raise
@@ -1,83 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: custom-python-logger
3
- Version: 1.0.10
4
- Summary: A custom logger with color support and additional features.
5
- Home-page: https://github.com/aviz92/custom-python-logger
6
- Author: Avi Zaguri
7
- Author-email:
8
- Project-URL: Repository, https://github.com/aviz92/custom-python-logger
9
- Requires-Python: >=3.11
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: setuptools
13
- Requires-Dist: wheel
14
- Requires-Dist: colorlog
15
- Requires-Dist: pytest
16
- Requires-Dist: pathlib
17
- Requires-Dist: PyYAML
18
- Dynamic: author
19
- Dynamic: description
20
- Dynamic: description-content-type
21
- Dynamic: home-page
22
- Dynamic: license-file
23
- Dynamic: project-url
24
- Dynamic: requires-dist
25
- Dynamic: requires-python
26
- Dynamic: summary
27
-
28
- # Custom Logger
29
- A Python logger with colored output and additional log levels. <br>
30
- The logger supports custom log levels like `STEP` and `EXCEPTION` and can be easily integrated into your Python projects.
31
-
32
- ## Installation
33
- You can install the package using pip:
34
- ```bash
35
- pip install custom-python-logger
36
- ```
37
-
38
- ## Usage
39
- ```python
40
- import logging
41
- from custom_python_logger.logger import get_logger, CustomLoggerAdapter
42
-
43
- logger: CustomLoggerAdapter = CustomLoggerAdapter(logging.getLogger(__name__))
44
-
45
-
46
- def main():
47
- logger.debug("This is a debug message.")
48
- logger.info("This is an info message.")
49
- logger.step("This is a step message.")
50
- logger.warning("This is a warning message.")
51
-
52
- try:
53
- _ = 1 / 0
54
- except ZeroDivisionError:
55
- logger.exception("This is an exception message.")
56
-
57
- logger.critical("This is a critical message.")
58
-
59
-
60
- if __name__ == '__main__':
61
- _ = get_logger(
62
- project_name='Logger Project Test',
63
- log_level=logging.DEBUG,
64
- extra={'user': 'test_user'}
65
- )
66
-
67
- main()
68
- ```
69
-
70
- ---
71
-
72
- ## 🤝 Contributing
73
- If you have a helpful tool, pattern, or improvement to suggest:
74
- Fork the repo <br>
75
- Create a new branch <br>
76
- Submit a pull request <br>
77
- I welcome additions that promote clean, productive, and maintainable development. <br>
78
-
79
- ---
80
-
81
- ## 🙏 Thanks
82
- Thanks for exploring this repository! <br>
83
- Happy coding! <br>
@@ -1,56 +0,0 @@
1
- # Custom Logger
2
- A Python logger with colored output and additional log levels. <br>
3
- The logger supports custom log levels like `STEP` and `EXCEPTION` and can be easily integrated into your Python projects.
4
-
5
- ## Installation
6
- You can install the package using pip:
7
- ```bash
8
- pip install custom-python-logger
9
- ```
10
-
11
- ## Usage
12
- ```python
13
- import logging
14
- from custom_python_logger.logger import get_logger, CustomLoggerAdapter
15
-
16
- logger: CustomLoggerAdapter = CustomLoggerAdapter(logging.getLogger(__name__))
17
-
18
-
19
- def main():
20
- logger.debug("This is a debug message.")
21
- logger.info("This is an info message.")
22
- logger.step("This is a step message.")
23
- logger.warning("This is a warning message.")
24
-
25
- try:
26
- _ = 1 / 0
27
- except ZeroDivisionError:
28
- logger.exception("This is an exception message.")
29
-
30
- logger.critical("This is a critical message.")
31
-
32
-
33
- if __name__ == '__main__':
34
- _ = get_logger(
35
- project_name='Logger Project Test',
36
- log_level=logging.DEBUG,
37
- extra={'user': 'test_user'}
38
- )
39
-
40
- main()
41
- ```
42
-
43
- ---
44
-
45
- ## 🤝 Contributing
46
- If you have a helpful tool, pattern, or improvement to suggest:
47
- Fork the repo <br>
48
- Create a new branch <br>
49
- Submit a pull request <br>
50
- I welcome additions that promote clean, productive, and maintainable development. <br>
51
-
52
- ---
53
-
54
- ## 🙏 Thanks
55
- Thanks for exploring this repository! <br>
56
- Happy coding! <br>
@@ -1,10 +0,0 @@
1
- from custom_python_logger.logger import (
2
- get_logger, CustomLoggerAdapter, json_pretty_format, yaml_pretty_format
3
- )
4
-
5
- __all__ = [
6
- "get_logger",
7
- "CustomLoggerAdapter",
8
- "json_pretty_format",
9
- "yaml_pretty_format"
10
- ]
@@ -1,83 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: custom-python-logger
3
- Version: 1.0.10
4
- Summary: A custom logger with color support and additional features.
5
- Home-page: https://github.com/aviz92/custom-python-logger
6
- Author: Avi Zaguri
7
- Author-email:
8
- Project-URL: Repository, https://github.com/aviz92/custom-python-logger
9
- Requires-Python: >=3.11
10
- Description-Content-Type: text/markdown
11
- License-File: LICENSE
12
- Requires-Dist: setuptools
13
- Requires-Dist: wheel
14
- Requires-Dist: colorlog
15
- Requires-Dist: pytest
16
- Requires-Dist: pathlib
17
- Requires-Dist: PyYAML
18
- Dynamic: author
19
- Dynamic: description
20
- Dynamic: description-content-type
21
- Dynamic: home-page
22
- Dynamic: license-file
23
- Dynamic: project-url
24
- Dynamic: requires-dist
25
- Dynamic: requires-python
26
- Dynamic: summary
27
-
28
- # Custom Logger
29
- A Python logger with colored output and additional log levels. <br>
30
- The logger supports custom log levels like `STEP` and `EXCEPTION` and can be easily integrated into your Python projects.
31
-
32
- ## Installation
33
- You can install the package using pip:
34
- ```bash
35
- pip install custom-python-logger
36
- ```
37
-
38
- ## Usage
39
- ```python
40
- import logging
41
- from custom_python_logger.logger import get_logger, CustomLoggerAdapter
42
-
43
- logger: CustomLoggerAdapter = CustomLoggerAdapter(logging.getLogger(__name__))
44
-
45
-
46
- def main():
47
- logger.debug("This is a debug message.")
48
- logger.info("This is an info message.")
49
- logger.step("This is a step message.")
50
- logger.warning("This is a warning message.")
51
-
52
- try:
53
- _ = 1 / 0
54
- except ZeroDivisionError:
55
- logger.exception("This is an exception message.")
56
-
57
- logger.critical("This is a critical message.")
58
-
59
-
60
- if __name__ == '__main__':
61
- _ = get_logger(
62
- project_name='Logger Project Test',
63
- log_level=logging.DEBUG,
64
- extra={'user': 'test_user'}
65
- )
66
-
67
- main()
68
- ```
69
-
70
- ---
71
-
72
- ## 🤝 Contributing
73
- If you have a helpful tool, pattern, or improvement to suggest:
74
- Fork the repo <br>
75
- Create a new branch <br>
76
- Submit a pull request <br>
77
- I welcome additions that promote clean, productive, and maintainable development. <br>
78
-
79
- ---
80
-
81
- ## 🙏 Thanks
82
- Thanks for exploring this repository! <br>
83
- Happy coding! <br>