python-fast-logger 0.1.0__tar.gz → 0.1.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: python-fast-logger
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: A simple, no-fuss logging setup for Python applications
5
5
  Author-email: Ravi Mishra <ravi@paisafintech.com>
6
6
  Maintainer-email: Ravi Mishra <ravi@paisafintech.com>
@@ -15,15 +15,13 @@ Classifier: Intended Audience :: Developers
15
15
  Classifier: License :: OSI Approved :: MIT License
16
16
  Classifier: Operating System :: OS Independent
17
17
  Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.7
19
- Classifier: Programming Language :: Python :: 3.8
20
18
  Classifier: Programming Language :: Python :: 3.9
21
19
  Classifier: Programming Language :: Python :: 3.10
22
20
  Classifier: Programming Language :: Python :: 3.11
23
21
  Classifier: Programming Language :: Python :: 3.12
24
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
23
  Classifier: Topic :: System :: Logging
26
- Requires-Python: >=3.7
24
+ Requires-Python: >=3.9
27
25
  Description-Content-Type: text/markdown
28
26
  License-File: LICENSE
29
27
  Provides-Extra: dev
@@ -52,7 +50,7 @@ A simple, no-fuss logging setup for Python applications with sensible defaults.
52
50
  ## Installation
53
51
 
54
52
  ```bash
55
- pip install fast-logger
53
+ pip install python-fast-logger
56
54
  ```
57
55
 
58
56
  ## Quick Start
@@ -216,7 +214,7 @@ logger = quick_logger("my_app")
216
214
 
217
215
  ## Requirements
218
216
 
219
- - Python 3.7+
217
+ - Python 3.9+
220
218
  - No external dependencies
221
219
 
222
220
  ## License
@@ -16,7 +16,7 @@ A simple, no-fuss logging setup for Python applications with sensible defaults.
16
16
  ## Installation
17
17
 
18
18
  ```bash
19
- pip install fast-logger
19
+ pip install python-fast-logger
20
20
  ```
21
21
 
22
22
  ## Quick Start
@@ -180,7 +180,7 @@ logger = quick_logger("my_app")
180
180
 
181
181
  ## Requirements
182
182
 
183
- - Python 3.7+
183
+ - Python 3.9+
184
184
  - No external dependencies
185
185
 
186
186
  ## License
@@ -40,4 +40,4 @@ __all__ = [
40
40
  "get_logger",
41
41
  "quick_logger",
42
42
  "__version__",
43
- ]
43
+ ]
@@ -6,21 +6,23 @@ import logging
6
6
  import sys
7
7
  from logging.handlers import RotatingFileHandler
8
8
  from pathlib import Path
9
- from typing import Optional, Union
9
+ from typing import Any, Optional, Union, cast
10
10
 
11
11
 
12
12
  class FastLogger:
13
13
  """A simple logger setup with sensible defaults."""
14
14
 
15
- def __init__(self,
16
- name: str,
17
- level: Union[int, str] = logging.INFO,
18
- log_folder: str = 'logs',
19
- max_file_size_mb: int = 50,
20
- backup_count: int = 3,
21
- log_format: Optional[str] = None,
22
- console_output: bool = True,
23
- base_path: Optional[str] = None):
15
+ def __init__(
16
+ self,
17
+ name: str,
18
+ level: Union[int, str] = logging.INFO,
19
+ log_folder: str = "logs",
20
+ max_file_size_mb: int = 50,
21
+ backup_count: int = 3,
22
+ log_format: Optional[str] = None,
23
+ console_output: bool = True,
24
+ base_path: Optional[str] = None,
25
+ ):
24
26
  """
25
27
  Initialize FastLogger with configuration.
26
28
 
@@ -44,11 +46,11 @@ class FastLogger:
44
46
 
45
47
  # Default format
46
48
  self.log_format = log_format or (
47
- '%(asctime)s - %(name)s [%(filename)s:%(lineno)d] - '
48
- '%(levelname)s - %(message)s'
49
+ "%(asctime)s - %(name)s [%(filename)s:%(lineno)d] - "
50
+ "%(levelname)s - %(message)s"
49
51
  )
50
52
 
51
- self._logger = None
53
+ self._logger: Optional[logging.Logger] = None
52
54
  self._setup_logger()
53
55
 
54
56
  @staticmethod
@@ -65,20 +67,28 @@ class FastLogger:
65
67
  else:
66
68
  # Use the directory of the calling script
67
69
  import inspect
68
- frame = inspect.currentframe()
69
- try:
70
- # Go up the stack to find the caller
71
- caller_frame = frame.f_back.f_back.f_back # Go up one more level
72
- caller_file = caller_frame.f_code.co_filename
73
- base = Path(caller_file).parent
74
- finally:
75
- del frame
70
+
71
+ # Find the first frame outside this module
72
+ current_dir = Path(__file__).parent
73
+ for frame_info in inspect.stack():
74
+ caller_file = Path(frame_info.filename)
75
+ # Skip frames that are internal to fast_logger
76
+ if caller_file.parent != current_dir:
77
+ # Found the caller script
78
+ if caller_file.exists() and caller_file.is_file():
79
+ base = caller_file.parent
80
+ else:
81
+ base = Path.cwd()
82
+ break
83
+ else:
84
+ # Fallback if stack inspection fails
85
+ base = Path.cwd()
76
86
 
77
87
  log_dir = base / self.log_folder
78
88
  log_dir.mkdir(parents=True, exist_ok=True)
79
89
  return log_dir
80
90
 
81
- def _setup_logger(self):
91
+ def _setup_logger(self) -> None:
82
92
  """Set up the logger with file and console handlers."""
83
93
  # Get or create logger
84
94
  self._logger = logging.getLogger(self.name)
@@ -98,7 +108,7 @@ class FastLogger:
98
108
  str(log_file), # Convert Path to string
99
109
  maxBytes=self.max_file_size_mb * 1024 * 1024,
100
110
  backupCount=self.backup_count,
101
- encoding='utf-8'
111
+ encoding="utf-8",
102
112
  )
103
113
  file_handler.setLevel(self.level)
104
114
  file_handler.setFormatter(formatter)
@@ -116,34 +126,41 @@ class FastLogger:
116
126
 
117
127
  def get_logger(self) -> logging.Logger:
118
128
  """Get the configured logger instance."""
129
+ assert self._logger is not None
119
130
  return self._logger
120
131
 
121
- def debug(self, message: str, *args, **kwargs):
132
+ def debug(self, message: str, *args: Any, **kwargs: Any) -> None:
122
133
  """Log a debug message."""
123
- self._logger.debug(message, *args, **kwargs)
134
+ if self._logger:
135
+ self._logger.debug(message, *args, **kwargs)
124
136
 
125
- def info(self, message: str, *args, **kwargs):
137
+ def info(self, message: str, *args: Any, **kwargs: Any) -> None:
126
138
  """Log an info message."""
127
- self._logger.info(message, *args, **kwargs)
139
+ if self._logger:
140
+ self._logger.info(message, *args, **kwargs)
128
141
 
129
- def warning(self, message: str, *args, **kwargs):
142
+ def warning(self, message: str, *args: Any, **kwargs: Any) -> None:
130
143
  """Log a warning message."""
131
- self._logger.warning(message, *args, **kwargs)
144
+ if self._logger:
145
+ self._logger.warning(message, *args, **kwargs)
132
146
 
133
- def error(self, message: str, *args, **kwargs):
147
+ def error(self, message: str, *args: Any, **kwargs: Any) -> None:
134
148
  """Log an error message."""
135
- self._logger.error(message, *args, **kwargs)
149
+ if self._logger:
150
+ self._logger.error(message, *args, **kwargs)
136
151
 
137
- def critical(self, message: str, *args, **kwargs):
152
+ def critical(self, message: str, *args: Any, **kwargs: Any) -> None:
138
153
  """Log a critical message."""
139
- self._logger.critical(message, *args, **kwargs)
154
+ if self._logger:
155
+ self._logger.critical(message, *args, **kwargs)
140
156
 
141
- def exception(self, message: str, *args, **kwargs):
157
+ def exception(self, message: str, *args: Any, **kwargs: Any) -> None:
142
158
  """Log an exception with traceback."""
143
- self._logger.exception(message, *args, **kwargs)
159
+ if self._logger:
160
+ self._logger.exception(message, *args, **kwargs)
144
161
 
145
162
 
146
- def setup_logger(name: str, **kwargs) -> logging.Logger:
163
+ def setup_logger(name: str, **kwargs: Any) -> logging.Logger:
147
164
  """
148
165
  Quick setup function for backward compatibility and convenience.
149
166
 
@@ -158,7 +175,7 @@ def setup_logger(name: str, **kwargs) -> logging.Logger:
158
175
  return fast_logger.get_logger()
159
176
 
160
177
 
161
- def get_logger(name: str, **kwargs) -> FastLogger:
178
+ def get_logger(name: str, **kwargs: Any) -> FastLogger:
162
179
  """
163
180
  Get a FastLogger instance with fluent interface.
164
181
 
@@ -173,7 +190,7 @@ def get_logger(name: str, **kwargs) -> FastLogger:
173
190
 
174
191
 
175
192
  # Convenience function for one-liner setup
176
- def quick_logger(name: str, level: str = 'INFO') -> logging.Logger:
193
+ def quick_logger(name: str, level: str = "INFO") -> logging.Logger:
177
194
  """
178
195
  Super quick logger setup with minimal configuration.
179
196
 
@@ -184,4 +201,4 @@ def quick_logger(name: str, level: str = 'INFO') -> logging.Logger:
184
201
  Returns:
185
202
  Configured logger instance
186
203
  """
187
- return setup_logger(name, level=level)
204
+ return setup_logger(name, level=level)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-fast-logger"
7
- version = "0.1.0"
7
+ version = "0.1.1"
8
8
  description = "A simple, no-fuss logging setup for Python applications"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -20,8 +20,6 @@ classifiers = [
20
20
  "License :: OSI Approved :: MIT License",
21
21
  "Operating System :: OS Independent",
22
22
  "Programming Language :: Python :: 3",
23
- "Programming Language :: Python :: 3.7",
24
- "Programming Language :: Python :: 3.8",
25
23
  "Programming Language :: Python :: 3.9",
26
24
  "Programming Language :: Python :: 3.10",
27
25
  "Programming Language :: Python :: 3.11",
@@ -30,7 +28,7 @@ classifiers = [
30
28
  "Topic :: System :: Logging",
31
29
  ]
32
30
  keywords = ["logging", "logger", "simple", "fast", "rotating", "file"]
33
- requires-python = ">=3.7"
31
+ requires-python = ">=3.9"
34
32
  dependencies = []
35
33
 
36
34
  [project.optional-dependencies]
@@ -56,10 +54,10 @@ include = ["fast_logger*"]
56
54
 
57
55
  [tool.black]
58
56
  line-length = 88
59
- target-version = ['py37', 'py38', 'py39', 'py310', 'py311']
57
+ target-version = ['py39', 'py310', 'py311']
60
58
 
61
59
  [tool.mypy]
62
- python_version = "3.7"
60
+ python_version = "3.9"
63
61
  warn_return_any = true
64
62
  warn_unused_configs = true
65
63
  disallow_untyped_defs = true
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-fast-logger
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: A simple, no-fuss logging setup for Python applications
5
5
  Author-email: Ravi Mishra <ravi@paisafintech.com>
6
6
  Maintainer-email: Ravi Mishra <ravi@paisafintech.com>
@@ -15,15 +15,13 @@ Classifier: Intended Audience :: Developers
15
15
  Classifier: License :: OSI Approved :: MIT License
16
16
  Classifier: Operating System :: OS Independent
17
17
  Classifier: Programming Language :: Python :: 3
18
- Classifier: Programming Language :: Python :: 3.7
19
- Classifier: Programming Language :: Python :: 3.8
20
18
  Classifier: Programming Language :: Python :: 3.9
21
19
  Classifier: Programming Language :: Python :: 3.10
22
20
  Classifier: Programming Language :: Python :: 3.11
23
21
  Classifier: Programming Language :: Python :: 3.12
24
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
25
23
  Classifier: Topic :: System :: Logging
26
- Requires-Python: >=3.7
24
+ Requires-Python: >=3.9
27
25
  Description-Content-Type: text/markdown
28
26
  License-File: LICENSE
29
27
  Provides-Extra: dev
@@ -52,7 +50,7 @@ A simple, no-fuss logging setup for Python applications with sensible defaults.
52
50
  ## Installation
53
51
 
54
52
  ```bash
55
- pip install fast-logger
53
+ pip install python-fast-logger
56
54
  ```
57
55
 
58
56
  ## Quick Start
@@ -216,7 +214,7 @@ logger = quick_logger("my_app")
216
214
 
217
215
  ## Requirements
218
216
 
219
- - Python 3.7+
217
+ - Python 3.9+
220
218
  - No external dependencies
221
219
 
222
220
  ## License
@@ -19,10 +19,7 @@ class TestFastLogger(unittest.TestCase):
19
19
 
20
20
  def test_basic_logger_creation(self):
21
21
  """Test basic logger creation."""
22
- logger = FastLogger(
23
- name=self.test_name,
24
- base_path=self.temp_dir
25
- )
22
+ logger = FastLogger(name=self.test_name, base_path=self.temp_dir)
26
23
 
27
24
  self.assertIsNotNone(logger.get_logger())
28
25
  self.assertEqual(logger.name, self.test_name)
@@ -30,16 +27,13 @@ class TestFastLogger(unittest.TestCase):
30
27
 
31
28
  def test_log_file_creation(self):
32
29
  """Test that log files are created."""
33
- logger = FastLogger(
34
- name=self.test_name,
35
- base_path=self.temp_dir
36
- )
30
+ logger = FastLogger(name=self.test_name, base_path=self.temp_dir)
37
31
 
38
32
  logger.info("Test message")
39
33
 
40
34
  # Force flush to ensure file is written
41
35
  for handler in logger.get_logger().handlers:
42
- if hasattr(handler, 'flush'):
36
+ if hasattr(handler, "flush"):
43
37
  handler.flush()
44
38
 
45
39
  log_file = Path(self.temp_dir) / "logs" / f"{self.test_name}.log"
@@ -50,7 +44,7 @@ class TestFastLogger(unittest.TestCase):
50
44
  logger = FastLogger(
51
45
  name=self.test_name,
52
46
  base_path=self.temp_dir,
53
- console_output=False # Only file output for testing
47
+ console_output=False, # Only file output for testing
54
48
  )
55
49
 
56
50
  test_message = "Test log message"
@@ -58,11 +52,11 @@ class TestFastLogger(unittest.TestCase):
58
52
 
59
53
  # Force flush to ensure file is written
60
54
  for handler in logger.get_logger().handlers:
61
- if hasattr(handler, 'flush'):
55
+ if hasattr(handler, "flush"):
62
56
  handler.flush()
63
57
 
64
58
  log_file = Path(self.temp_dir) / "logs" / f"{self.test_name}.log"
65
- with open(log_file, 'r') as f:
59
+ with open(log_file, "r") as f:
66
60
  content = f.read()
67
61
 
68
62
  self.assertIn(test_message, content)
@@ -74,7 +68,7 @@ class TestFastLogger(unittest.TestCase):
74
68
  name=self.test_name,
75
69
  base_path=self.temp_dir,
76
70
  level=logging.DEBUG,
77
- console_output=False
71
+ console_output=False,
78
72
  )
79
73
 
80
74
  logger.debug("Debug message")
@@ -85,11 +79,11 @@ class TestFastLogger(unittest.TestCase):
85
79
 
86
80
  # Force flush to ensure file is written
87
81
  for handler in logger.get_logger().handlers:
88
- if hasattr(handler, 'flush'):
82
+ if hasattr(handler, "flush"):
89
83
  handler.flush()
90
84
 
91
85
  log_file = Path(self.temp_dir) / "logs" / f"{self.test_name}.log"
92
- with open(log_file, 'r') as f:
86
+ with open(log_file, "r") as f:
93
87
  content = f.read()
94
88
 
95
89
  self.assertIn("DEBUG", content)
@@ -100,18 +94,12 @@ class TestFastLogger(unittest.TestCase):
100
94
 
101
95
  def test_string_level_parsing(self):
102
96
  """Test string level parsing."""
103
- logger = FastLogger(
104
- name=self.test_name,
105
- base_path=self.temp_dir,
106
- level="DEBUG"
107
- )
97
+ logger = FastLogger(name=self.test_name, base_path=self.temp_dir, level="DEBUG")
108
98
 
109
99
  self.assertEqual(logger.level, logging.DEBUG)
110
100
 
111
101
  logger = FastLogger(
112
- name=self.test_name + "2",
113
- base_path=self.temp_dir,
114
- level="warning"
102
+ name=self.test_name + "2", base_path=self.temp_dir, level="warning"
115
103
  )
116
104
 
117
105
  self.assertEqual(logger.level, logging.WARNING)
@@ -120,16 +108,14 @@ class TestFastLogger(unittest.TestCase):
120
108
  """Test custom log folder."""
121
109
  custom_folder = "custom_logs"
122
110
  logger = FastLogger(
123
- name=self.test_name,
124
- base_path=self.temp_dir,
125
- log_folder=custom_folder
111
+ name=self.test_name, base_path=self.temp_dir, log_folder=custom_folder
126
112
  )
127
113
 
128
114
  logger.info("Test message")
129
115
 
130
116
  # Force flush to ensure file is written
131
117
  for handler in logger.get_logger().handlers:
132
- if hasattr(handler, 'flush'):
118
+ if hasattr(handler, "flush"):
133
119
  handler.flush()
134
120
 
135
121
  log_file = Path(self.temp_dir) / custom_folder / f"{self.test_name}.log"
@@ -169,16 +155,18 @@ class TestFastLogger(unittest.TestCase):
169
155
  def test_console_output_disabled(self):
170
156
  """Test logger with console output disabled."""
171
157
  logger = FastLogger(
172
- name=self.test_name,
173
- base_path=self.temp_dir,
174
- console_output=False
158
+ name=self.test_name, base_path=self.temp_dir, console_output=False
175
159
  )
176
160
 
177
161
  # Should have only file handler
178
162
  handlers = logger.get_logger().handlers
179
163
  self.assertEqual(len(handlers), 1)
180
- self.assertTrue(any(handler.__class__.__name__ == 'RotatingFileHandler'
181
- for handler in handlers))
164
+ self.assertTrue(
165
+ any(
166
+ handler.__class__.__name__ == "RotatingFileHandler"
167
+ for handler in handlers
168
+ )
169
+ )
182
170
 
183
171
  def test_custom_format(self):
184
172
  """Test custom log format."""
@@ -187,23 +175,23 @@ class TestFastLogger(unittest.TestCase):
187
175
  name=self.test_name,
188
176
  base_path=self.temp_dir,
189
177
  log_format=custom_format,
190
- console_output=False
178
+ console_output=False,
191
179
  )
192
180
 
193
181
  logger.info("Test message")
194
182
 
195
183
  # Force flush to ensure file is written
196
184
  for handler in logger.get_logger().handlers:
197
- if hasattr(handler, 'flush'):
185
+ if hasattr(handler, "flush"):
198
186
  handler.flush()
199
187
 
200
188
  log_file = Path(self.temp_dir) / "logs" / f"{self.test_name}.log"
201
- with open(log_file, 'r') as f:
189
+ with open(log_file, "r") as f:
202
190
  content = f.read().strip()
203
191
 
204
192
  # Should match our custom format
205
193
  self.assertTrue(content.startswith("INFO: Test message"))
206
194
 
207
195
 
208
- if __name__ == '__main__':
209
- unittest.main()
196
+ if __name__ == "__main__":
197
+ unittest.main()