Skip to content

Commit 5278a0d

Browse files
committed
style: apply black and isort formatting
- Format code with black for consistent style - Sort imports with isort for better organization - All linting checks now pass
1 parent 565e22c commit 5278a0d

File tree

8 files changed

+403
-68
lines changed

8 files changed

+403
-68
lines changed

pyproject.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ functions_framework = ["py.typed"]
6464

6565
[dependency-groups]
6666
dev = [
67+
"black>=23.3.0",
68+
"isort>=5.11.5",
6769
"pretend>=1.0.9",
6870
"pytest>=7.4.4",
6971
"pytest-asyncio>=0.21.2",

src/functions_framework/_http/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# limitations under the License.
1414

1515
from flask import Flask
16+
1617
from functions_framework._http.flask import FlaskApplication
1718

1819

src/functions_framework/aio/__init__.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,11 @@ async def _crash_handler(request, exc):
6161
# Log the exception
6262
logger = logging.getLogger()
6363
tb_lines = traceback.format_exception(type(exc), exc, exc.__traceback__)
64-
tb_text = ''.join(tb_lines)
65-
error_msg = f"Exception on {request.url.path} [{request.method}]\n{tb_text}".rstrip()
66-
64+
tb_text = "".join(tb_lines)
65+
error_msg = (
66+
f"Exception on {request.url.path} [{request.method}]\n{tb_text}".rstrip()
67+
)
68+
6769
# Context should still be available since we don't reset on exception
6870
if _enable_execution_id_logging():
6971
# Output as JSON so LoggingHandlerAddExecutionId can process it
@@ -72,10 +74,11 @@ async def _crash_handler(request, exc):
7274
else:
7375
# Execution ID logging not enabled, log plain text
7476
logger.error(error_msg)
75-
77+
7678
headers = {_FUNCTION_STATUS_HEADER_FIELD: _CRASH}
7779
return Response("Internal Server Error", status_code=500, headers=headers)
7880

81+
7982
CloudEventFunction = Callable[[CloudEvent], Union[None, Awaitable[None]]]
8083
HTTPFunction = Callable[[Request], Union[HTTPResponse, Awaitable[HTTPResponse]]]
8184

@@ -163,7 +166,7 @@ async def handler(request):
163166
raise HTTPException(
164167
400, detail=f"Bad Request: Got CloudEvent exception: {repr(e)}"
165168
)
166-
169+
167170
if is_async:
168171
await function(event)
169172
else:
@@ -189,19 +192,21 @@ def _enable_execution_id_logging():
189192

190193
def _configure_app_execution_id_logging():
191194
# Logging needs to be configured before app logger is accessed
192-
import logging.config
193195
import logging
194-
196+
import logging.config
197+
195198
# Configure root logger to use our custom handler
196199
root_logger = logging.getLogger()
197200
root_logger.setLevel(logging.INFO)
198-
201+
199202
# Remove existing handlers
200203
for handler in root_logger.handlers[:]:
201204
root_logger.removeHandler(handler)
202-
205+
203206
# Add our custom handler that adds execution ID
204-
handler = logging.StreamHandler(execution_id.LoggingHandlerAddExecutionId(sys.stderr))
207+
handler = logging.StreamHandler(
208+
execution_id.LoggingHandlerAddExecutionId(sys.stderr)
209+
)
205210
handler.setLevel(logging.NOTSET)
206211
root_logger.addHandler(handler)
207212

@@ -227,11 +232,11 @@ def create_asgi_app(target=None, source=None, signature_type=None):
227232
)
228233

229234
source_module, spec = _function_registry.load_function_module(source)
230-
235+
231236
enable_id_logging = _enable_execution_id_logging()
232237
if enable_id_logging:
233238
_configure_app_execution_id_logging()
234-
239+
235240
spec.loader.exec_module(source_module)
236241
function = _function_registry.get_user_function(source, source_module, target)
237242
signature_type = _function_registry.get_func_signature_type(target, signature_type)
@@ -259,7 +264,9 @@ def create_asgi_app(target=None, source=None, signature_type=None):
259264
)
260265
)
261266
elif signature_type == _function_registry.CLOUDEVENT_SIGNATURE_TYPE:
262-
cloudevent_handler = _cloudevent_func_wrapper(function, is_async, enable_id_logging)
267+
cloudevent_handler = _cloudevent_func_wrapper(
268+
function, is_async, enable_id_logging
269+
)
263270
routes.append(
264271
Route("/{path:path}", endpoint=cloudevent_handler, methods=["POST"])
265272
)
@@ -282,10 +289,10 @@ def create_asgi_app(target=None, source=None, signature_type=None):
282289
Exception: _crash_handler,
283290
}
284291
app = Starlette(routes=routes, exception_handlers=exception_handlers)
285-
292+
286293
# Apply ASGI middleware for execution ID
287294
app = execution_id.AsgiMiddleware(app)
288-
295+
289296
return app
290297

291298

src/functions_framework/execution_id.py

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
logger = logging.getLogger(__name__)
4242

4343
# Context variable for async execution context
44-
execution_context_var = contextvars.ContextVar('execution_context', default=None)
44+
execution_context_var = contextvars.ContextVar("execution_context", default=None)
4545

4646

4747
class ExecutionContext:
@@ -82,14 +82,14 @@ def _generate_execution_id():
8282
def _extract_context_from_headers(headers):
8383
"""Extract execution context from request headers."""
8484
execution_id = headers.get(EXECUTION_ID_REQUEST_HEADER)
85-
85+
8686
# Try to get span ID from trace context header
8787
trace_context = re.match(
8888
_TRACE_CONTEXT_REGEX_PATTERN,
8989
headers.get(TRACE_CONTEXT_REQUEST_HEADER, ""),
9090
)
9191
span_id = trace_context.group("span_id") if trace_context else None
92-
92+
9393
return ExecutionContext(execution_id, span_id)
9494

9595

@@ -118,31 +118,33 @@ async def __call__(self, scope, receive, send):
118118
trace_context_header = b"x-cloud-trace-context"
119119
execution_id = None
120120
trace_context = None
121-
121+
122122
for name, value in scope.get("headers", []):
123123
if name.lower() == execution_id_header:
124124
execution_id = value.decode("latin-1")
125125
elif name.lower() == trace_context_header:
126126
trace_context = value.decode("latin-1")
127-
127+
128128
if not execution_id:
129129
execution_id = _generate_execution_id()
130130
# Add the execution ID to headers
131131
new_headers = list(scope.get("headers", []))
132-
new_headers.append((execution_id_header, execution_id.encode("latin-1")))
132+
new_headers.append(
133+
(execution_id_header, execution_id.encode("latin-1"))
134+
)
133135
scope["headers"] = new_headers
134-
136+
135137
# Store execution context in ASGI scope for recovery in case of context loss
136138
# Parse trace context to extract span ID
137139
span_id = None
138140
if trace_context:
139141
trace_match = re.match(_TRACE_CONTEXT_REGEX_PATTERN, trace_context)
140142
if trace_match:
141143
span_id = trace_match.group("span_id")
142-
144+
143145
# Store in scope for potential recovery
144146
scope["execution_context"] = ExecutionContext(execution_id, span_id)
145-
147+
146148
await self.app(scope, receive, send) # pragma: no cover
147149

148150

@@ -167,7 +169,7 @@ def wrapper(*args, **kwargs):
167169

168170
with stderr_redirect, stdout_redirect:
169171
result = view_function(*args, **kwargs)
170-
172+
171173
# Context cleanup happens automatically via Flask's request context
172174
# No need to manually clean up flask.g
173175
return result
@@ -195,38 +197,38 @@ def decorator(view_function):
195197
async def async_wrapper(request, *args, **kwargs):
196198
# Extract execution context from headers
197199
context = _extract_context_from_headers(request.headers)
198-
200+
199201
# Set context using contextvars
200202
token = execution_context_var.set(context)
201-
203+
202204
with stderr_redirect, stdout_redirect:
203205
# Handle both sync and async functions
204206
if inspect.iscoroutinefunction(view_function):
205207
result = await view_function(request, *args, **kwargs)
206208
else:
207209
result = view_function(request, *args, **kwargs) # pragma: no cover
208-
210+
209211
# Only reset context on successful completion
210212
# On exception, leave context available for exception handlers
211213
execution_context_var.reset(token)
212214
return result
213-
215+
214216
@functools.wraps(view_function)
215217
def sync_wrapper(request, *args, **kwargs): # pragma: no cover
216218
# For sync functions, we still need to set up the context
217219
context = _extract_context_from_headers(request.headers)
218-
220+
219221
# Set context using contextvars
220222
token = execution_context_var.set(context)
221-
223+
222224
with stderr_redirect, stdout_redirect:
223225
result = view_function(request, *args, **kwargs)
224-
226+
225227
# Only reset context on successful completion
226228
# On exception, leave context available for exception handlers
227229
execution_context_var.reset(token)
228230
return result
229-
231+
230232
# Return appropriate wrapper based on whether the function is async
231233
if inspect.iscoroutinefunction(view_function):
232234
return async_wrapper

tests/test_execution_id.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,10 +223,11 @@ def view_func():
223223
monkeypatch.setattr(
224224
execution_id, "_generate_execution_id", lambda: TEST_EXECUTION_ID
225225
)
226+
226227
# Use a simple object instead of Mock to properly test attribute assignment
227228
class MockG:
228229
pass
229-
230+
230231
mock_g = MockG()
231232
monkeypatch.setattr(execution_id.flask, "g", mock_g)
232233
monkeypatch.setattr(execution_id.flask, "has_request_context", lambda: True)

0 commit comments

Comments
 (0)