-
Notifications
You must be signed in to change notification settings - Fork 31
feature/type-checker-compatible-with-mypy #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,3 +6,4 @@ __pycache__ | |
/.tox | ||
/.cache | ||
/JSON_log_formatter.egg-info | ||
.mypy_cache/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
repos: | ||
- repo: https://github.com/pre-commit/mirrors-mypy | ||
rev: v1.9.0 | ||
hooks: | ||
- id: mypy | ||
args: [--strict, --ignore-missing-imports] | ||
additional_dependencies: [] | ||
# If your project uses third-party packages, add them here: | ||
# additional_dependencies: | ||
# - types-requests | ||
# - types-python-dateutil | ||
|
||
- repo: https://github.com/psf/black | ||
rev: 24.3.0 | ||
hooks: | ||
- id: black | ||
args: [--line-length=88] | ||
|
||
- repo: https://github.com/PyCQA/isort | ||
rev: 5.13.2 | ||
hooks: | ||
- id: isort | ||
args: ["--profile", "black", "--filter-files"] | ||
|
||
- repo: https://github.com/PyCQA/flake8 | ||
rev: 7.0.0 | ||
hooks: | ||
- id: flake8 | ||
additional_dependencies: [flake8-bugbear] | ||
|
||
- repo: https://github.com/asottile/pyupgrade | ||
rev: v3.15.1 | ||
hooks: | ||
- id: pyupgrade | ||
args: [--py37-plus] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,37 @@ | ||
from __future__ import annotations # backward compatibility | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've deprecated Python < v3.9, could you please rebase? I wonder if we still need There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, sorry for late responding... |
||
|
||
import logging | ||
from decimal import Decimal | ||
from datetime import datetime, timezone | ||
|
||
from decimal import Decimal | ||
import json | ||
|
||
BUILTIN_ATTRS = { | ||
'args', | ||
'asctime', | ||
'created', | ||
'exc_info', | ||
'exc_text', | ||
'filename', | ||
'funcName', | ||
'levelname', | ||
'levelno', | ||
'lineno', | ||
'module', | ||
'msecs', | ||
'message', | ||
'msg', | ||
'name', | ||
'pathname', | ||
'process', | ||
'processName', | ||
'relativeCreated', | ||
'stack_info', | ||
'taskName', | ||
'thread', | ||
'threadName', | ||
from types import ModuleType | ||
from typing import Any, Optional, Dict | ||
|
||
|
||
BUILTIN_ATTRS: set[str] = { | ||
"args", | ||
"asctime", | ||
"created", | ||
"exc_info", | ||
"exc_text", | ||
"filename", | ||
"funcName", | ||
"levelname", | ||
"levelno", | ||
"lineno", | ||
"module", | ||
"msecs", | ||
"message", | ||
"msg", | ||
"name", | ||
"pathname", | ||
"process", | ||
"processName", | ||
"relativeCreated", | ||
"stack_info", | ||
"taskName", | ||
"thread", | ||
"threadName", | ||
} | ||
|
||
|
||
|
@@ -58,21 +62,21 @@ class JSONFormatter(logging.Formatter): | |
|
||
""" | ||
|
||
json_lib = json | ||
json_lib: ModuleType = json | ||
|
||
def format(self, record): | ||
message = record.getMessage() | ||
extra = self.extra_from_record(record) | ||
json_record = self.json_record(message, extra, record) | ||
mutated_record = self.mutate_json_record(json_record) | ||
def format(self, record: logging.LogRecord) -> Any | str: | ||
message: str = record.getMessage() | ||
extra: dict[str, Any] = self.extra_from_record(record) | ||
json_record: dict[str, Any] = self.json_record(message, extra, record) | ||
mutated_record: Optional[dict[str, Any]] = self.mutate_json_record(json_record) | ||
# Backwards compatibility: Functions that overwrite this but don't | ||
# return a new value will return None because they modified the | ||
# argument passed in. | ||
if mutated_record is None: | ||
mutated_record = json_record | ||
return self.to_json(mutated_record) | ||
|
||
def to_json(self, record): | ||
def to_json(self, record: dict[str, Any]) -> Any | str: | ||
"""Converts record dict to a JSON string. | ||
|
||
It makes best effort to serialize a record (represents an object as a string) | ||
|
@@ -93,9 +97,9 @@ def to_json(self, record): | |
try: | ||
return self.json_lib.dumps(record) | ||
except (TypeError, ValueError, OverflowError): | ||
return '{}' | ||
return "{}" | ||
|
||
def extra_from_record(self, record): | ||
def extra_from_record(self, record: logging.LogRecord) -> dict[str, Any]: | ||
"""Returns `extra` dict you passed to logger. | ||
|
||
The `extra` keyword argument is used to populate the `__dict__` of | ||
|
@@ -108,7 +112,9 @@ def extra_from_record(self, record): | |
if attr_name not in BUILTIN_ATTRS | ||
} | ||
|
||
def json_record(self, message, extra, record): | ||
def json_record( | ||
self, message: str, extra: dict[str, Any], record: logging.LogRecord | ||
) -> dict[str, Any]: | ||
"""Prepares a JSON payload which will be logged. | ||
|
||
Override this method to change JSON log format. | ||
|
@@ -120,16 +126,18 @@ def json_record(self, message, extra, record): | |
:return: Dictionary which will be passed to JSON lib. | ||
|
||
""" | ||
extra['message'] = message | ||
if 'time' not in extra: | ||
extra['time'] = datetime.now(timezone.utc) | ||
extra["message"] = message | ||
if "time" not in extra: | ||
extra["time"] = datetime.now(timezone.utc) | ||
|
||
if record.exc_info: | ||
extra['exc_info'] = self.formatException(record.exc_info) | ||
extra["exc_info"] = self.formatException(record.exc_info) | ||
|
||
return extra | ||
|
||
def mutate_json_record(self, json_record): | ||
def mutate_json_record( | ||
self, json_record: dict[str, Any] | ||
) -> Optional[Dict[str, Any]]: | ||
"""Override it to convert fields of `json_record` to needed types. | ||
|
||
Default implementation converts `datetime` to string in ISO8601 format. | ||
|
@@ -142,7 +150,7 @@ def mutate_json_record(self, json_record): | |
return json_record | ||
|
||
|
||
def _json_serializable(obj): | ||
def _json_serializable(obj: Any) -> Any: | ||
try: | ||
return obj.__dict__ | ||
except AttributeError: | ||
|
@@ -189,23 +197,29 @@ class VerboseJSONFormatter(JSONFormatter): | |
https://docs.python.org/3/library/logging.html#logrecord-attributes. | ||
|
||
""" | ||
def json_record(self, message, extra, record): | ||
extra['filename'] = record.filename | ||
extra['funcName'] = record.funcName | ||
extra['levelname'] = record.levelname | ||
extra['lineno'] = record.lineno | ||
extra['module'] = record.module | ||
extra['name'] = record.name | ||
extra['pathname'] = record.pathname | ||
extra['process'] = record.process | ||
extra['processName'] = record.processName | ||
if hasattr(record, 'stack_info'): | ||
extra['stack_info'] = record.stack_info | ||
else: | ||
extra['stack_info'] = None | ||
extra['thread'] = record.thread | ||
extra['threadName'] = record.threadName | ||
return super(VerboseJSONFormatter, self).json_record(message, extra, record) | ||
|
||
def json_record( | ||
self, message: str, extra: dict[str, Any], record: logging.LogRecord | ||
) -> dict[str, Any]: | ||
extra.update( | ||
{ | ||
"filename": record.filename, | ||
"funcName": record.funcName, | ||
"levelname": record.levelname, | ||
"lineno": record.lineno, | ||
"module": record.module, | ||
"name": record.name, | ||
"pathname": record.pathname, | ||
"process": record.process, | ||
"processName": record.processName, | ||
"stack_info": record.stack_info | ||
if hasattr(record, "stack_info") | ||
else None, | ||
"thread": record.thread, | ||
"threadName": record.threadName, | ||
} | ||
) | ||
return super().json_record(message, extra, record) | ||
|
||
|
||
class FlatJSONFormatter(JSONFormatter): | ||
|
@@ -230,10 +244,12 @@ class FlatJSONFormatter(JSONFormatter): | |
|
||
""" | ||
|
||
keep = (bool, int, float, Decimal, complex, str, datetime) | ||
keep: tuple[type, ...] = (bool, int, float, Decimal, complex, str, datetime) | ||
|
||
def json_record(self, message, extra, record): | ||
extra = super(FlatJSONFormatter, self).json_record(message, extra, record) | ||
def json_record( | ||
self, message: str, extra: dict[str, Any], record: logging.LogRecord | ||
) -> dict[str, Any]: | ||
extra = super().json_record(message, extra, record) | ||
return { | ||
k: v if v is None or isinstance(v, self.keep) else str(v) | ||
for k, v in extra.items() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[mypy] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please move this into There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK |
||
python_version = 3.11 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, I will task it as an important notice. |
||
# To recognize all the files | ||
files = ['__init__.py', 'tests.py', 'setup.py' ] | ||
strict = True | ||
check_untyped_defs = True | ||
disallow_untyped_defs = True | ||
disallow_incomplete_defs = True | ||
no_implicit_optional = True | ||
warn_redundant_casts = True | ||
warn_unused_ignores = True | ||
show_error_codes = True | ||
show_column_numbers = True | ||
ignore_missing_imports = False |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
from setuptools import setup | ||
from setuptools import setup # type: ignore | ||
|
||
setup( | ||
name='JSON-log-formatter', | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we need pre commit hooks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do