loggingsetup 0.0.1__py3-none-any.whl
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.
- logging_setup/__init__.py +50 -0
- logging_setup/cleanup_old_logs.py +37 -0
- logging_setup/filters.py +29 -0
- logging_setup/formats.py +61 -0
- logging_setup/my_setup.py +121 -0
- loggingsetup-0.0.1.dist-info/METADATA +126 -0
- loggingsetup-0.0.1.dist-info/RECORD +9 -0
- loggingsetup-0.0.1.dist-info/WHEEL +5 -0
- loggingsetup-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Initializes the application's logging system.
|
|
3
|
+
|
|
4
|
+
Features:
|
|
5
|
+
- Automatically creates a `logs/` directory if it doesn't exist.
|
|
6
|
+
- Logs messages from DEBUG up to WARNING into `logs/app-YYYY-MM-DD.log`.
|
|
7
|
+
- Logs all ERROR and CRITICAL messages into `logs/error-YYYY-MM-DD.log`.
|
|
8
|
+
- Creates a new log file every day (daily rotation by date, UTC).
|
|
9
|
+
- Colored console output:
|
|
10
|
+
- DEBUG — white
|
|
11
|
+
- INFO — cyan
|
|
12
|
+
- WARNING — yellow
|
|
13
|
+
- ERROR — red
|
|
14
|
+
- CRITICAL — bright red
|
|
15
|
+
- STDOUT receives messages up to WARNING, STDERR receives ERROR and above.
|
|
16
|
+
- Works without `logging.getLogger(__name__)`: records sent through the root
|
|
17
|
+
logger (`logging.info(...)`) get the module name (e.g. `app.bot`) instead of `root`.
|
|
18
|
+
- All uncaught exceptions (`sys.excepthook`) and uncaught exceptions in threads
|
|
19
|
+
(`threading.excepthook`) are logged as ERRORs.
|
|
20
|
+
- Noisy third-party loggers (urllib3, aiohttp, selenium, telethon, pyrogram,
|
|
21
|
+
asyncio, apscheduler) are limited to WARNING.
|
|
22
|
+
- Old log files older than 30 days are deleted in the background:
|
|
23
|
+
once at startup and then every day (`APScheduler`, background scheduler).
|
|
24
|
+
- Repeated calls of `init_logging()` are ignored.
|
|
25
|
+
|
|
26
|
+
Example of generated log files:
|
|
27
|
+
- logs/app-2025-06-20.log
|
|
28
|
+
- logs/error-2025-06-20.log
|
|
29
|
+
|
|
30
|
+
Usage:
|
|
31
|
+
- Call once in the main entry script:
|
|
32
|
+
from logging_setup import init_logging
|
|
33
|
+
init_logging()
|
|
34
|
+
- In all other modules just use:
|
|
35
|
+
import logging
|
|
36
|
+
logging.info("message")
|
|
37
|
+
(`logger = logging.getLogger(__name__)` still works, but is optional.)
|
|
38
|
+
|
|
39
|
+
Note:
|
|
40
|
+
- The module name is calculated from the file path relative to the current
|
|
41
|
+
working directory. If the project is started from another folder, pass the
|
|
42
|
+
path to `install_module_name_factory(...)`.
|
|
43
|
+
- The entry script is shown as `main`, not `__main__`.
|
|
44
|
+
- The system is modular and extensible via `filters.py`, `formats.py`, `cleanup_old_logs.py`.
|
|
45
|
+
"""
|
|
46
|
+
from .my_setup import init_logging
|
|
47
|
+
|
|
48
|
+
__all__ = [
|
|
49
|
+
'init_logging',
|
|
50
|
+
]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from datetime import datetime, timedelta, timezone
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def cleanup_old_logs_by_filename(
|
|
10
|
+
logs_dir: str = "logs",
|
|
11
|
+
days: int = 30,
|
|
12
|
+
delete_old_logs: bool = True
|
|
13
|
+
) -> None:
|
|
14
|
+
"""
|
|
15
|
+
The function for deleting old logging files is automatic.
|
|
16
|
+
|
|
17
|
+
:param logs_dir: The directory where the logs are stored, from where they will be deleted.
|
|
18
|
+
:param days: Deleting logs that are older than the specified days.
|
|
19
|
+
:param delete_old_logs: A bullseye value, if True, it deletes the old logs.
|
|
20
|
+
"""
|
|
21
|
+
if not delete_old_logs:
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
cutoff = datetime.now(timezone.utc).date() - timedelta(days=days)
|
|
25
|
+
deleted_files = 0
|
|
26
|
+
|
|
27
|
+
for file in Path(logs_dir).glob("*-????-??-??.log"):
|
|
28
|
+
try:
|
|
29
|
+
file_date = datetime.strptime(file.stem[-10:], "%Y-%m-%d").date()
|
|
30
|
+
if file_date < cutoff:
|
|
31
|
+
file.unlink()
|
|
32
|
+
deleted_files += 1
|
|
33
|
+
logger.info(f"[logging-setup] The log was deleted: {file.name}")
|
|
34
|
+
except Exception as e:
|
|
35
|
+
logger.warning(f"[logging-setup] File problem {file.name}: {e}")
|
|
36
|
+
|
|
37
|
+
logger.info(f"[logging-setup] Deleted {deleted_files} logs older than {days} days.")
|
logging_setup/filters.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def max_level_filter(max_level_name: str):
|
|
6
|
+
max_level = getattr(logging, max_level_name.upper(), logging.WARNING)
|
|
7
|
+
|
|
8
|
+
class MaxLevelFilter(logging.Filter):
|
|
9
|
+
def filter(self, record):
|
|
10
|
+
return record.levelno <= max_level
|
|
11
|
+
|
|
12
|
+
return MaxLevelFilter()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def handle_exception(exc_type, exc_value, exc_traceback):
|
|
16
|
+
if issubclass(exc_type, KeyboardInterrupt):
|
|
17
|
+
sys.__excepthook__(exc_type, exc_value, exc_traceback)
|
|
18
|
+
return
|
|
19
|
+
|
|
20
|
+
logging.error("[logging-setup] Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def handle_thread_exception(args):
|
|
24
|
+
if issubclass(args.exc_type, SystemExit):
|
|
25
|
+
return
|
|
26
|
+
logging.error(
|
|
27
|
+
"[logging-setup] Uncaught exception in thread",
|
|
28
|
+
exc_info=(args.exc_type, args.exc_value, args.exc_traceback),
|
|
29
|
+
)
|
logging_setup/formats.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from functools import lru_cache
|
|
3
|
+
from logging.handlers import TimedRotatingFileHandler
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from colorama import Fore, Style
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ColorFormatter(logging.Formatter):
|
|
10
|
+
LEVEL_COLORS = {
|
|
11
|
+
logging.DEBUG: Fore.WHITE,
|
|
12
|
+
logging.INFO: Fore.CYAN,
|
|
13
|
+
logging.WARNING: Fore.YELLOW,
|
|
14
|
+
logging.ERROR: Fore.RED,
|
|
15
|
+
logging.CRITICAL: Fore.RED + Style.BRIGHT
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
def format(self, record):
|
|
19
|
+
color = self.LEVEL_COLORS.get(record.levelno, "")
|
|
20
|
+
message = super().format(record)
|
|
21
|
+
return f"{color}{message}{Style.RESET_ALL}"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class DatedTimedRotatingFileHandler(TimedRotatingFileHandler):
|
|
25
|
+
def __init__(self, *args, **kwargs):
|
|
26
|
+
super().__init__(*args, **kwargs)
|
|
27
|
+
|
|
28
|
+
def rotation_filename(self, default_name):
|
|
29
|
+
date_part = Path(default_name).suffix.lstrip(".") # 2025-06-20
|
|
30
|
+
base = Path(self.baseFilename)
|
|
31
|
+
return str(base.with_name(f"{base.stem}-{date_part}.log"))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def install_module_name_factory(project_root: str | Path | None = None) -> None:
|
|
35
|
+
"""
|
|
36
|
+
Replaces the logger name 'root' with the module path (like app.bot),
|
|
37
|
+
so logging.info(...) works without logger = logging.getLogger(__name__).
|
|
38
|
+
"""
|
|
39
|
+
root_dir = Path(project_root or Path.cwd()).resolve()
|
|
40
|
+
|
|
41
|
+
@lru_cache(maxsize=None)
|
|
42
|
+
def module_name(pathname: str) -> str:
|
|
43
|
+
try:
|
|
44
|
+
relative = Path(pathname).resolve().relative_to(root_dir)
|
|
45
|
+
return ".".join(relative.with_suffix("").parts)
|
|
46
|
+
except ValueError:
|
|
47
|
+
return Path(pathname).stem # file is outside the project
|
|
48
|
+
|
|
49
|
+
old_factory = logging.getLogRecordFactory()
|
|
50
|
+
|
|
51
|
+
def factory(*args, **kwargs):
|
|
52
|
+
record = old_factory(*args, **kwargs)
|
|
53
|
+
if record.name == "root":
|
|
54
|
+
record.name = module_name(record.pathname)
|
|
55
|
+
return record
|
|
56
|
+
|
|
57
|
+
logging.setLogRecordFactory(factory)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
file_fmt = "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s"
|
|
61
|
+
date_fmt = "%Y-%m-%d %H:%M:%S"
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
import threading
|
|
5
|
+
from datetime import datetime, timezone
|
|
6
|
+
|
|
7
|
+
from apscheduler.schedulers.background import BackgroundScheduler
|
|
8
|
+
from apscheduler.triggers.interval import IntervalTrigger
|
|
9
|
+
from colorama import init
|
|
10
|
+
|
|
11
|
+
from logging_setup.cleanup_old_logs import cleanup_old_logs_by_filename
|
|
12
|
+
from logging_setup.filters import max_level_filter, handle_exception, handle_thread_exception
|
|
13
|
+
from logging_setup.formats import ColorFormatter, file_fmt, date_fmt, DatedTimedRotatingFileHandler, \
|
|
14
|
+
install_module_name_factory
|
|
15
|
+
|
|
16
|
+
_initialized = False
|
|
17
|
+
|
|
18
|
+
NOISY_LOGGERS = (
|
|
19
|
+
"urllib3", "aiohttp", "selenium", "telethon",
|
|
20
|
+
"pyrogram", "asyncio", "apscheduler",
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def init_logging(
|
|
25
|
+
directory: str = "logs",
|
|
26
|
+
enable_console: bool = True,
|
|
27
|
+
delete_old_logs: bool = True,
|
|
28
|
+
days_to_delete_old_logs: int = 30,
|
|
29
|
+
):
|
|
30
|
+
"""
|
|
31
|
+
Initialization of logging of the entire project and configuration.
|
|
32
|
+
|
|
33
|
+
:param directory: The directory where the logs (app/error) from the root of the project will be stored.
|
|
34
|
+
:param enable_console: Enable or Disable logging to the console.
|
|
35
|
+
:param delete_old_logs: Delete or Not Delete old logs.
|
|
36
|
+
:param days_to_delete_old_logs: Delete logs older than these days.
|
|
37
|
+
"""
|
|
38
|
+
global _initialized
|
|
39
|
+
if _initialized:
|
|
40
|
+
return
|
|
41
|
+
_initialized = True
|
|
42
|
+
|
|
43
|
+
# Automatically reset the color
|
|
44
|
+
init(autoreset=True)
|
|
45
|
+
|
|
46
|
+
os.makedirs(directory, exist_ok=True)
|
|
47
|
+
|
|
48
|
+
color_formatter = ColorFormatter(fmt=file_fmt, datefmt=date_fmt)
|
|
49
|
+
file_formatter = logging.Formatter(fmt=file_fmt, datefmt=date_fmt)
|
|
50
|
+
handlers: list[logging.Handler] = []
|
|
51
|
+
|
|
52
|
+
# Console handlers
|
|
53
|
+
if enable_console:
|
|
54
|
+
stdout_handler = logging.StreamHandler(sys.stdout)
|
|
55
|
+
stdout_handler.setLevel(logging.DEBUG)
|
|
56
|
+
stdout_handler.setFormatter(color_formatter)
|
|
57
|
+
stdout_handler.addFilter(max_level_filter("WARNING"))
|
|
58
|
+
|
|
59
|
+
stderr_handler = logging.StreamHandler(sys.stderr)
|
|
60
|
+
stderr_handler.setLevel(logging.ERROR)
|
|
61
|
+
stderr_handler.setFormatter(color_formatter)
|
|
62
|
+
|
|
63
|
+
handlers.extend((stdout_handler, stderr_handler))
|
|
64
|
+
|
|
65
|
+
# File handlers with date rotation
|
|
66
|
+
# backupCount=0: old files are deleted only by cleanup_old_logs_by_filename
|
|
67
|
+
rotating_file = DatedTimedRotatingFileHandler(
|
|
68
|
+
filename=f"{directory}/app.log",
|
|
69
|
+
when="midnight",
|
|
70
|
+
interval=1,
|
|
71
|
+
backupCount=0,
|
|
72
|
+
encoding="utf-8",
|
|
73
|
+
utc=True,
|
|
74
|
+
)
|
|
75
|
+
rotating_file.setLevel(logging.DEBUG)
|
|
76
|
+
rotating_file.setFormatter(file_formatter)
|
|
77
|
+
rotating_file.addFilter(max_level_filter("WARNING"))
|
|
78
|
+
|
|
79
|
+
rotating_error = DatedTimedRotatingFileHandler(
|
|
80
|
+
filename=f"{directory}/error.log",
|
|
81
|
+
when="midnight",
|
|
82
|
+
interval=1,
|
|
83
|
+
backupCount=0,
|
|
84
|
+
encoding="utf-8",
|
|
85
|
+
utc=True,
|
|
86
|
+
)
|
|
87
|
+
rotating_error.setLevel(logging.ERROR)
|
|
88
|
+
rotating_error.setFormatter(file_formatter)
|
|
89
|
+
|
|
90
|
+
handlers.extend((rotating_file, rotating_error))
|
|
91
|
+
|
|
92
|
+
# Replace logger name "root" with the module name
|
|
93
|
+
install_module_name_factory()
|
|
94
|
+
|
|
95
|
+
# Root logger (force=True replaces handlers that were set before)
|
|
96
|
+
logging.basicConfig(level=logging.DEBUG, handlers=handlers, force=True)
|
|
97
|
+
|
|
98
|
+
# Make noisy libraries quiet
|
|
99
|
+
for name in NOISY_LOGGERS:
|
|
100
|
+
logging.getLogger(name).setLevel(logging.WARNING)
|
|
101
|
+
|
|
102
|
+
# Global error interception
|
|
103
|
+
sys.excepthook = handle_exception
|
|
104
|
+
threading.excepthook = handle_thread_exception
|
|
105
|
+
|
|
106
|
+
# Background cleanup of old logs
|
|
107
|
+
scheduler = BackgroundScheduler()
|
|
108
|
+
scheduler.start()
|
|
109
|
+
|
|
110
|
+
scheduler.add_job(
|
|
111
|
+
cleanup_old_logs_by_filename,
|
|
112
|
+
IntervalTrigger(days=1),
|
|
113
|
+
id="cleanup_old_logs",
|
|
114
|
+
replace_existing=True,
|
|
115
|
+
next_run_time=datetime.now(timezone.utc),
|
|
116
|
+
kwargs={
|
|
117
|
+
"delete_old_logs": delete_old_logs,
|
|
118
|
+
"days": days_to_delete_old_logs,
|
|
119
|
+
"logs_dir": directory,
|
|
120
|
+
},
|
|
121
|
+
)
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: loggingsetup
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: This is an improved and customized version of logging for a quick start.
|
|
5
|
+
Home-page: https://github.com/XEQU4/logging-setup
|
|
6
|
+
Author: xequ4
|
|
7
|
+
Author-email: b.m.04.11reg@gmail.com
|
|
8
|
+
Project-URL: GitHub, https://github.com/XEQU4/logging-setup
|
|
9
|
+
Keywords: logging colorama files logs shceduler archive
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.11
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
Requires-Dist: apscheduler>=3.11.3
|
|
16
|
+
Requires-Dist: colorama>=0.4.6
|
|
17
|
+
Dynamic: author
|
|
18
|
+
Dynamic: author-email
|
|
19
|
+
Dynamic: classifier
|
|
20
|
+
Dynamic: description
|
|
21
|
+
Dynamic: description-content-type
|
|
22
|
+
Dynamic: home-page
|
|
23
|
+
Dynamic: keywords
|
|
24
|
+
Dynamic: project-url
|
|
25
|
+
Dynamic: requires-dist
|
|
26
|
+
Dynamic: requires-python
|
|
27
|
+
Dynamic: summary
|
|
28
|
+
|
|
29
|
+
# logging-setup
|
|
30
|
+
|
|
31
|
+
[](https://www.python.org/)
|
|
32
|
+
[](LICENSE)
|
|
33
|
+
[](https://peps.python.org/pep-0008/)
|
|
34
|
+
[](https://docs.python.org/3/library/logging.html)
|
|
35
|
+
|
|
36
|
+
A ready-made configuration for Python's standard `logging` module.
|
|
37
|
+
Call `init_logging()` once, and the whole project gets colored console output, daily log files, and automatic cleanup.
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- Colored console output (DEBUG white, INFO cyan, WARNING yellow, ERROR red, CRITICAL bright red)
|
|
42
|
+
- `STDOUT` gets messages up to WARNING, `STDERR` gets ERROR and above
|
|
43
|
+
- Daily log files (UTC):
|
|
44
|
+
- `logs/app-YYYY-MM-DD.log` for DEBUG to WARNING
|
|
45
|
+
- `logs/error-YYYY-MM-DD.log` for ERROR and CRITICAL
|
|
46
|
+
- Old logs are deleted automatically (default: older than 30 days), once at startup and then every day
|
|
47
|
+
- No need for `logging.getLogger(__name__)`: `logging.info(...)` shows the real module name (for example `app.bot`) instead of `root`
|
|
48
|
+
- Uncaught exceptions in the main thread and in other threads are logged as errors
|
|
49
|
+
- Noisy libraries (`urllib3`, `aiohttp`, `selenium`, `telethon`, `pyrogram`, `asyncio`, `apscheduler`) are limited to WARNING
|
|
50
|
+
- Calling `init_logging()` twice is safe: the second call is ignored
|
|
51
|
+
|
|
52
|
+
## Requirements
|
|
53
|
+
|
|
54
|
+
- Python 3.10+
|
|
55
|
+
- [colorama](https://pypi.org/project/colorama/)
|
|
56
|
+
- [APScheduler](https://pypi.org/project/APScheduler/)
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install git+https://github.com/XEQU4/logging-setup.git
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Or copy the `logging_setup/` folder into your project.
|
|
65
|
+
|
|
66
|
+
## Quick start
|
|
67
|
+
|
|
68
|
+
In your main script, call it once:
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
import logging
|
|
72
|
+
from logging_setup import init_logging
|
|
73
|
+
|
|
74
|
+
init_logging()
|
|
75
|
+
|
|
76
|
+
logging.info("Hello World!")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
In every other module, just use the standard `logging`:
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
import logging
|
|
83
|
+
|
|
84
|
+
def run():
|
|
85
|
+
logging.info("Bot started")
|
|
86
|
+
logging.error("Something went wrong")
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Example output:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
2026-10-20 09:42:16 | INFO | app.bot | Bot started
|
|
93
|
+
2026-10-20 09:42:16 | ERROR | app.bot | Something went wrong
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
> `logger = logging.getLogger(__name__)` still works if you prefer it.
|
|
97
|
+
|
|
98
|
+
## Parameters
|
|
99
|
+
|
|
100
|
+
| Parameter | Type | Default | Description |
|
|
101
|
+
|---------------------------|--------|----------|------------------------------------------|
|
|
102
|
+
| `directory` | `str` | `"logs"` | Folder for log files |
|
|
103
|
+
| `enable_console` | `bool` | `True` | Turn console output on or off |
|
|
104
|
+
| `delete_old_logs` | `bool` | `True` | Turn automatic cleanup on or off |
|
|
105
|
+
| `days_to_delete_old_logs` | `int` | `30` | Delete logs older than this many days |
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
init_logging(directory="my_logs", enable_console=False, days_to_delete_old_logs=14)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Project structure
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
logging_setup/
|
|
115
|
+
в”њв”Ђв”Ђ __init__.py # exports init_logging
|
|
116
|
+
в”њв”Ђв”Ђ my_setup.py # main setup function
|
|
117
|
+
в”њв”Ђв”Ђ formats.py # color formatter, rotating handler, module name factory
|
|
118
|
+
в”њв”Ђв”Ђ filters.py # level filters, exception hooks
|
|
119
|
+
в””в”Ђв”Ђ cleanup_old_logs.py # background cleanup of old log files
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Notes
|
|
123
|
+
|
|
124
|
+
- The module name is calculated from the file path relative to the current working directory. If you start the project from another folder, pass the project path to `install_module_name_factory(...)`.
|
|
125
|
+
- The entry script is shown as `main`, not `__main__`.
|
|
126
|
+
- Old files are deleted only by the cleanup job, not by `backupCount`.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
logging_setup/__init__.py,sha256=snr6txw34CTLq1wrHGFMBm9Ja252mFxwtW9phg4HcjM,1950
|
|
2
|
+
logging_setup/cleanup_old_logs.py,sha256=9CJEu7SRX7BfD7_YDaSNNp0kvdvQlcD7Owy22pf5l8Y,1259
|
|
3
|
+
logging_setup/filters.py,sha256=U3mQJAdVd5vttoXwAvdn4tPIxRwXly2GzuXDJadg_vA,837
|
|
4
|
+
logging_setup/formats.py,sha256=vPWgA_vqMWjL8Gw8w33Nq8aupCDDWJxeBD2yTt2rOYc,1979
|
|
5
|
+
logging_setup/my_setup.py,sha256=Yk_71jLC1CiV9oxE3THHX8Zy_V5eGdXA-7gEUFKN9AE,3891
|
|
6
|
+
loggingsetup-0.0.1.dist-info/METADATA,sha256=LPS4uHyJfisiEZVKpC9-ea8LPsXAYOE5FE5eHyj7mVQ,4719
|
|
7
|
+
loggingsetup-0.0.1.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
8
|
+
loggingsetup-0.0.1.dist-info/top_level.txt,sha256=Eh3V7lEybRvsh8hA5WYub0Yrfllm6qZLK50nUfRTUl0,14
|
|
9
|
+
loggingsetup-0.0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
logging_setup
|