Skip to content

Commit 239419f

Browse files
authored
feat: added context to the logger (#112)
1 parent 8347c74 commit 239419f

22 files changed

Lines changed: 591 additions & 325 deletions

src/openapi_parser/builders/common.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,21 @@ def cast_value(
3535
type_cast_func: Callable[..., Any] | None,
3636
) -> Any:
3737
try:
38-
return type_cast_func(value) if type_cast_func is not None else value
38+
if type_cast_func is not None:
39+
return type_cast_func(value)
40+
41+
return value
3942
except ValueError:
4043
raise ParserError(
41-
f"Invalid value for '{name}' property, got '{value}'"
44+
f"Invalid value for '{name}' property, got '{value}'",
4245
) from None
4346

4447
custom_attrs = {
45-
attr_name: cast_value(attr_info.name, data[attr_info.name], attr_info.cast)
48+
attr_name: cast_value(
49+
attr_info.name,
50+
data[attr_info.name],
51+
attr_info.cast,
52+
)
4653
for attr_name, attr_info in attrs_map.items()
4754
if data.get(attr_info.name) is not None
4855
}

src/openapi_parser/builders/content.py

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from openapi_parser.builders.encoding import EncodingBuilder
77
from openapi_parser.builders.schema import SchemaFactory
88
from openapi_parser.enumeration import ContentType
9+
from openapi_parser.logging import log_ctx
910
from openapi_parser.loose_types import LooseContentType
1011
from openapi_parser.specification import Content
1112

@@ -38,13 +39,13 @@ def __init__(
3839
self._encoding_builder = encoding_builder
3940
self._strict_enum = strict_enum
4041

41-
def build_list(self, data: dict[str, Any]) -> list[Content]:
42+
def build_list(
43+
self,
44+
data: dict[str, Any],
45+
) -> list[Content]:
4246
"""Build a list of content objects from a dict of media types."""
4347
return [
44-
self._create_content(
45-
content_type,
46-
content_value,
47-
)
48+
self._create_content(content_type, content_value)
4849
for content_type, content_value in data.items()
4950
]
5051

@@ -53,22 +54,23 @@ def _create_content(
5354
content_type: str,
5455
content_value: dict[str, Any],
5556
) -> Content:
56-
logger.debug(f"Content building [type={content_type}]")
57+
with log_ctx("content", content_type):
58+
logger.debug(f"Content building [type={content_type}]")
5759

58-
ContentTypeCls: ContentTypeType = (
59-
ContentType if self._strict_enum else LooseContentType
60-
)
60+
ContentTypeCls: ContentTypeType = (
61+
ContentType if self._strict_enum else LooseContentType
62+
)
6163

62-
encoding = (
63-
self._encoding_builder.build_dict(content_value["encoding"])
64-
if content_value.get("encoding")
65-
else None
66-
)
64+
encoding = (
65+
self._encoding_builder.build_dict(content_value["encoding"])
66+
if content_value.get("encoding")
67+
else None
68+
)
6769

68-
return Content(
69-
type=ContentTypeCls(content_type),
70-
schema=self._schema_factory.create(content_value.get("schema", {})),
71-
example=content_value.get("example"),
72-
examples=content_value.get("examples", {}),
73-
encoding=encoding,
74-
)
70+
return Content(
71+
type=ContentTypeCls(content_type),
72+
schema=self._schema_factory.create(content_value.get("schema", {})),
73+
example=content_value.get("example"),
74+
examples=content_value.get("examples", {}),
75+
encoding=encoding,
76+
)

src/openapi_parser/builders/encoding.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
extract_typed_props,
1010
)
1111
from openapi_parser.builders.header import HeaderBuilder
12+
from openapi_parser.logging import log_ctx
1213
from openapi_parser.specification import Encoding
1314

1415
logger = logging.getLogger(__name__)
@@ -27,12 +28,18 @@ def __init__(self, header_builder: HeaderBuilder) -> None:
2728
"""
2829
self._header_builder = header_builder
2930

30-
def build_dict(self, data: dict[str, dict[str, Any]]) -> dict[str, Encoding]:
31+
def build_dict(
32+
self,
33+
data: dict[str, dict[str, Any]],
34+
) -> dict[str, Encoding]:
3135
"""Build a dict of encodings from a dict of raw encoding definitions."""
32-
return {
33-
property_name: self._build(encoding_data)
34-
for property_name, encoding_data in data.items()
35-
}
36+
result: dict[str, Encoding] = {}
37+
38+
for property_name, encoding_data in data.items():
39+
with log_ctx("encoding", property_name):
40+
result[property_name] = self._build(encoding_data)
41+
42+
return result
3643

3744
def _build(self, data: dict[str, Any]) -> Encoding:
3845
logger.debug("Encoding building")

src/openapi_parser/builders/header.py

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
extract_typed_props,
1010
)
1111
from openapi_parser.builders.schema import SchemaFactory
12+
from openapi_parser.logging import log_ctx
1213
from openapi_parser.specification import Header
1314

1415
logger = logging.getLogger(__name__)
@@ -27,29 +28,41 @@ def __init__(self, schema_factory: SchemaFactory) -> None:
2728
"""
2829
self._schema_factory = schema_factory
2930

30-
def build_list(self, data: dict[str, Any]) -> list[Header]:
31+
def build_list(
32+
self,
33+
data: dict[str, Any],
34+
) -> list[Header]:
3135
"""Build a list of headers from a dict of header definitions."""
3236
return [
3337
self._build(header_name, header_value)
3438
for header_name, header_value in data.items()
3539
]
3640

37-
def _build(self, name: str, data: dict[str, Any]) -> Header:
38-
logger.debug(f"Header parsing: {name}")
41+
def _build(
42+
self,
43+
name: str,
44+
data: dict[str, Any],
45+
) -> Header:
46+
with log_ctx("headers", name):
47+
logger.debug(f"Header parsing: {name}")
3948

40-
attrs_map = {
41-
"schema": PropertyMeta(name="schema", cast=self._schema_factory.create),
42-
"description": PropertyMeta(name="description", cast=str),
43-
"deprecated": PropertyMeta(name="deprecated", cast=bool),
44-
"required": PropertyMeta(name="required", cast=bool),
45-
}
49+
attrs_map = {
50+
"description": PropertyMeta(name="description", cast=str),
51+
"deprecated": PropertyMeta(name="deprecated", cast=bool),
52+
"required": PropertyMeta(name="required", cast=bool),
53+
}
4654

47-
attrs = extract_typed_props(data, attrs_map)
55+
attrs = extract_typed_props(data, attrs_map)
4856

49-
attrs["name"] = name
50-
attrs["extensions"] = extract_extension_attributes(data)
57+
if data.get("schema") is not None:
58+
attrs["schema"] = self._schema_factory.create(data["schema"])
5159

52-
if attrs["extensions"]:
53-
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
60+
attrs["name"] = name
61+
attrs["extensions"] = extract_extension_attributes(data)
5462

55-
return Header(**attrs)
63+
if attrs["extensions"]:
64+
logger.debug(
65+
f"Extracted custom properties [{attrs['extensions'].keys()}]"
66+
)
67+
68+
return Header(**attrs)

src/openapi_parser/builders/info.py

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
extract_typed_props,
1010
)
1111
from openapi_parser.errors import ParserError
12+
from openapi_parser.logging import log_ctx
1213
from openapi_parser.specification import Contact, Info, License
1314

1415
logger = logging.getLogger(__name__)
@@ -19,29 +20,34 @@ class InfoBuilder:
1920

2021
def build(self, data: dict[str, Any]) -> Info:
2122
"""Build an Info object from a raw dict."""
22-
title = data.get("title")
23-
24-
if title is None:
25-
raise ParserError("Info section is missing required 'title' property")
26-
27-
logger.debug(f"Info section parsing [title={title}]")
28-
29-
attrs_map = {
30-
"title": PropertyMeta(name="title", cast=str),
31-
"version": PropertyMeta(name="version", cast=str),
32-
"description": PropertyMeta(name="description", cast=str),
33-
"terms_of_service": PropertyMeta(name="termsOfService", cast=str),
34-
"license": PropertyMeta(name="license", cast=self._create_license),
35-
"contact": PropertyMeta(name="contact", cast=self._create_contact),
36-
}
37-
38-
attrs = extract_typed_props(data, attrs_map)
39-
attrs["extensions"] = extract_extension_attributes(data)
40-
41-
if attrs["extensions"]:
42-
logger.debug(f"Extracted custom properties [{attrs['extensions'].keys()}]")
43-
44-
return Info(**attrs)
23+
with log_ctx("info"):
24+
title = data.get("title")
25+
26+
if title is None:
27+
raise ParserError(
28+
"Info section is missing required 'title' property",
29+
)
30+
31+
logger.debug(f"Info section parsing [title={title}]")
32+
33+
attrs_map = {
34+
"title": PropertyMeta(name="title", cast=str),
35+
"version": PropertyMeta(name="version", cast=str),
36+
"description": PropertyMeta(name="description", cast=str),
37+
"terms_of_service": PropertyMeta(name="termsOfService", cast=str),
38+
"license": PropertyMeta(name="license", cast=self._create_license),
39+
"contact": PropertyMeta(name="contact", cast=self._create_contact),
40+
}
41+
42+
attrs = extract_typed_props(data, attrs_map)
43+
attrs["extensions"] = extract_extension_attributes(data)
44+
45+
if attrs["extensions"]:
46+
logger.debug(
47+
f"Extracted custom properties [{attrs['extensions'].keys()}]"
48+
)
49+
50+
return Info(**attrs)
4551

4652
@staticmethod
4753
def _create_license(data: dict[str, Any]) -> License:

src/openapi_parser/builders/link.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
extract_extension_attributes,
99
extract_typed_props,
1010
)
11+
from openapi_parser.logging import log_ctx
1112
from openapi_parser.specification import Link, Server
1213

1314
logger = logging.getLogger(__name__)
@@ -24,11 +25,18 @@ def build_server(value: dict[str, Any]) -> Server:
2425
class LinkBuilder:
2526
"""Builds link objects from raw specification data."""
2627

27-
def build_dict(self, data: dict[str, dict[str, Any]]) -> dict[str, Link]:
28+
def build_dict(
29+
self,
30+
data: dict[str, dict[str, Any]],
31+
) -> dict[str, Link]:
2832
"""Build a dict of links from a dict of raw link definitions."""
29-
return {
30-
link_name: self._build(link_data) for link_name, link_data in data.items()
31-
}
33+
result: dict[str, Link] = {}
34+
35+
for link_name, link_data in data.items():
36+
with log_ctx("links", link_name):
37+
result[link_name] = self._build(link_data)
38+
39+
return result
3240

3341
def _build(self, data: dict[str, Any]) -> Link:
3442
logger.debug("Link building")

src/openapi_parser/builders/oauth_flow.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ class OAuthFlowBuilder:
1818
"""Builds OAuth flow collections from raw specification data."""
1919

2020
@staticmethod
21-
def build_collection(data: dict[str, Any]) -> dict[OAuthFlowType, OAuthFlow]:
21+
def build_collection(
22+
data: dict[str, Any],
23+
) -> dict[OAuthFlowType, OAuthFlow]:
2224
"""Build a dict of OAuthFlow objects from a raw dict."""
2325
logger.debug(f"Parsing OAuth items collection: {data.keys()}")
2426

@@ -45,7 +47,8 @@ def build_collection(data: dict[str, Any]) -> dict[OAuthFlowType, OAuthFlow]:
4547

4648
for extension in extensions:
4749
result_oauth_dict[cast(OAuthFlowType, extension)] = cast(
48-
OAuthFlow, extensions[extension]
50+
OAuthFlow,
51+
extensions[extension],
4952
)
5053

5154
return result_oauth_dict

0 commit comments

Comments
 (0)