-
Notifications
You must be signed in to change notification settings - Fork 122
Comparing changes
Open a pull request
base repository: GoogleCloudPlatform/functions-framework-python
base: v3.8.3
head repository: GoogleCloudPlatform/functions-framework-python
compare: v3.9.0
- 14 commits
- 52 files changed
- 4 contributors
Commits on May 16, 2025
-
Configuration menu - View commit details
-
Copy full SHA for 3fdeaa0 - Browse repository at this point
Copy the full SHA 3fdeaa0View commit details -
Configuration menu - View commit details
-
Copy full SHA for 0ab5f03 - Browse repository at this point
Copy the full SHA 0ab5f03View commit details
Commits on Jun 9, 2025
-
fix: Pin cloudevent sdk version to support python3.7. (#373)
* fix: Pin cloudevent sdk version to support python3.7. * Pin cloudevent version on examples. * Pin cloudevent versions.
Configuration menu - View commit details
-
Copy full SHA for cc2b9b5 - Browse repository at this point
Copy the full SHA cc2b9b5View commit details
Commits on Jun 10, 2025
-
fix(ci): specify python version in tox environment (#375)
* fix(ci): specify python version in tox environment * Enable shell for github workflows.
Configuration menu - View commit details
-
Copy full SHA for 37e0bf7 - Browse repository at this point
Copy the full SHA 37e0bf7View commit details -
feat: add support for async functions (#364)
* feat: Introduce functions_framework.aio submodule that support async function execution. * Remove httpx. * Update pyproject.toml to include extra async package. * Update test deps. * Improve test coverage. * Make linter happy. * Fix test harness to support py37. * Remove version filter in tox file. * Remove dependency-groups in pyproject.toml for now. * Use py3.8 compatible types. * Fix more incompatibility with python38 * Pin cloudevent sdk to python37 compatible version. * Fix more py37 incompatibility. * fix: Prevent test_aio.py collection errors on Python 3.7 Add pytest_ignore_collect hook to skip test_aio.py entirely on Python 3.7 to prevent ImportError during test collection. The previous approach using only pytest_collection_modifyitems was too late in the process - the error occurred when pytest tried to import the module before skip markers could be applied. Both hooks are marked as safe to remove when Python 3.7 support is dropped. * style: Apply black formatting to conftest.py * fix: Use modern pytest collection_path parameter and return None - Replace deprecated 'path' parameter with 'collection_path' in pytest_ignore_collect - Return None instead of False to let pytest use default behavior - This should fix the issue where pytest was collecting tests from .tox/.pkg/ * fix: Skip tests parametrized with None on Python 3.7 Simplify the check to just skip any test parametrized with None value. On Python 3.7, create_asgi_app is always None due to the conditional import, so this catches all async-related parametrized tests. * fix: Replace asyncio.to_thread with Python 3.8 compatible code Use asyncio.get_event_loop().run_in_executor() instead of asyncio.to_thread() for Python 3.8 compatibility. Added TODO comments to switch back when Python 3.8 support is dropped. * fix: Improve async test detection for Python 3.7 - Use a list of async keywords (async, asgi, aio, starlette) - Check for these keywords in test names, file paths, and parameters - This catches more async-related tests including those with "aio" prefix * fix: Handle Flask vs Starlette redirect behavior differences - Remove unnecessary follow_redirects=True from Starlette TestClient - Make test_http_function_request_url_empty_path aware of framework differences - Starlette TestClient normalizes empty path "" to "/" while Flask preserves it - Test now expects appropriate behavior for each framework * fix: Exclude aio module from coverage on Python 3.7 Add special coverage configuration for Python 3.7 that excludes the aio module since it requires Python 3.8+ due to Starlette dependency. This prevents coverage failures on Python 3.7. * fix: Simplify conftest.py. * fix: Use full environment names for py37 coverage exclusion The tox environment names in GitHub Actions include the OS suffix (e.g., py37-ubuntu-22.04), so we need to match the full names. * fix: Explicitly list each py37 environment for coverage exclusion - List py37-ubuntu-22.04 and py37-macos-13 explicitly - Place py37 settings before general windows-latest setting - This should properly exclude aio module from coverage on Python 3.7 * fix: Add Python 3.7 specific coverage configuration - Create .coveragerc-py37 to exclude aio module from coverage on Python 3.7 - Use --cov-config flag to specify this file for py37 environments only - This prevents the aio module exclusion from affecting Python 3.8+ tests
Configuration menu - View commit details
-
Copy full SHA for 49f6985 - Browse repository at this point
Copy the full SHA 49f6985View commit details
Commits on Jun 12, 2025
-
feat: add flag to run functions framework in asgi stack (#376)
* feat: add ASGI server support for async functions - Add uvicorn and uvicorn-worker to async optional dependencies - Refactor gunicorn.py with BaseGunicornApplication for shared config - Add UvicornApplication class for ASGI apps - Add StarletteApplication in asgi.py for development mode - Update HTTPServer to auto-detect Flask (WSGI) vs other (ASGI) apps - Add --gateway CLI flag to choose between wsgi and asgi - Update test_http.py to use Flask instance in tests * fix: apply black and isort formatting to source files * test: add comprehensive tests for ASGI server support - Add tests for HTTPServer ASGI/WSGI auto-detection - Add tests for StarletteApplication and UvicornApplication - Add tests for CLI --gateway flag functionality - Add integration tests for async functions with ASGI - Ensure 100% code coverage for new ASGI features - Apply black and isort formatting to test files * fix: skip async test files on Python 3.7 * fix: exclude async code from Python 3.7 coverage * fix: Install uvicorn on windows. * fix: unable to use reload in starlette. * fix: add missing endpoint parameter to Route constructors in ASGI * feat: add async conformance tests with ASGI gateway * fix: set UvicornWorker class before parent init and update tests * fix: update asgi tests to remove reload option * feat: add async-specific conformance tests for ASGI mode * fix: apply black formatting to async files * fix: disable validateMapping for CloudEvent tests in ASGI mode ASGI mode does not support automatic conversion from legacy events to CloudEvents, so validateMapping must be false for CloudEvent conformance tests. * fix: avoid mutating options dict in Gunicorn applications Create a copy of the options dict before modifying it to prevent side effects when the same options dict is reused elsewhere. This could cause issues with timeout tests. * fix: add pragma comments for Python 3.7 coverage and fix options handling - Add pragma: no cover comments for ASGI-specific code paths that won't execute in Python 3.7 - Fix options dict handling to use consistent variable names to avoid confusion * fix: revert to separate GunicornApplication and UvicornApplication classes Remove the BaseGunicornApplication abstraction as it was causing issues with the timeout mechanism. Each class now independently extends gunicorn.app.base.BaseApplication, which is cleaner and avoids the problems we were seeing with shared state and options handling. * refactor: restore GunicornApplication to match main branch Remove unnecessary changes to GunicornApplication class, keeping only the UvicornApplication addition for ASGI support. * chore: Untrack uv.lock * chore: rename confirmance test (asgi) github workflow * chore: cleanup .gitignore. * chore: clean up unncessary comments.
Configuration menu - View commit details
-
Copy full SHA for 268acf1 - Browse repository at this point
Copy the full SHA 268acf1View commit details
Commits on Jun 17, 2025
-
feat: add execution_id support for async stack (#377)
* feat: add execution_id support for async stack - Add contextvars support to execution_id.py for async-safe context storage - Create AsgiMiddleware class to inject execution_id into ASGI requests - Add set_execution_context_async decorator for both sync and async functions - Update LoggingHandlerAddExecutionId to support both Flask g and contextvars - Integrate execution_id support in aio/__init__.py with proper exception handling - Add comprehensive async tests matching sync test functionality - Follow Starlette best practices for exception handling The implementation enables automatic execution_id injection and logging for async functions when LOG_EXECUTION_ID=true, matching the existing sync stack behavior. * refactor: move exception logging to crash handler for cleaner code - Remove try/catch blocks from wrapper functions - Centralize exception logging in _crash_handler - Extract execution_id directly from request headers in crash handler - Temporarily set context when logging exceptions to ensure execution_id is included - This approach is cleaner and more similar to Flask's centralized exception handling * refactor: improve code organization based on feedback - Move imports to top of file instead of inside functions - Extract common header parsing logic into _extract_context_from_headers helper - Reduce code duplication between sync and async decorators - Add comment explaining why crash handler needs to extract context from headers - This addresses the context reset issue where decorators clean up before exception handlers run * fix: preserve execution context for exception handlers - Don't reset context on exception, only on successful completion - This allows exception handlers to access execution_id naturally - Simplify crash handler since context is now available - Rely on Python's automatic contextvar cleanup when task completes - Each request runs in its own task, so no risk of context leakage This is more correct and follows the principle that context should be available throughout the entire request lifecycle, including error handling. * 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 * refactor: clean up async tests and remove redundant comments * chore: remove uv.lock from version control * style: fix black formatting * fix: skip async execution_id tests on Python 3.7 * refactor: reuse _enable_execution_id_logging from main module * chore: more cleanup. * test: remove unnecessary pragma no cover for sync_wrapper * test: improve coverage by removing unnecessary pragma no cover annotations * style: fix black formatting * style: fix isort import ordering * test: add back pragma no cover for genuinely hard-to-test edge cases * refactor: simplify async decorator by removing dead code branch * fix: exclude async-specific code from py37 coverage The AsgiMiddleware class and set_execution_context_async function in execution_id.py require Python 3.8+ due to async dependencies. These are now excluded from coverage calculations in Python 3.7 environments. * fix: improve async execution ID context propagation using contextvars - Use contextvars.copy_context() to properly propagate execution context in async functions - Implement AsyncExecutionIdHandler to handle JSON logging with execution_id - Redirect logging output from stderr to stdout for consistency - Add build dependency to dev dependencies - Update tests to reflect new logging output location * feat: Add execution ID logging for async functions Refactors the async logging implementation to align with the sync version, ensuring consistent execution ID logging across both stacks. * chore: clean up impl. * refactor: define custom exception handling middleware to avoid duplicate log of traceback. * style: run black * chore: clean up code a little more. * fix: propagate context in ce fns. * style: more nits. * chore: remove unncessary debug flag. * fix: respond to PR comments * fix: respond to more PR comments
Configuration menu - View commit details
-
Copy full SHA for 1123eea - Browse repository at this point
Copy the full SHA 1123eeaView commit details
Commits on Jun 18, 2025
-
Configuration menu - View commit details
-
Copy full SHA for 42b7fdd - Browse repository at this point
Copy the full SHA 42b7fddView commit details -
fix: set default log level for asgi logger to WARNING to match defaul…
…t python behavior (#381) * fix: set default log level for asgi logger to WARNING to match default python behavior. * fix: fix broken test.
Configuration menu - View commit details
-
Copy full SHA for a576a8f - Browse repository at this point
Copy the full SHA a576a8fView commit details
Commits on Jun 23, 2025
-
refactor: replace --gateway flag with --asgi boolean flag (#383)
* refactor: replace --gateway flag with --asgi boolean flag Simplify the CLI by replacing `--gateway asgi` with `--asgi`. The new flag is more intuitive as WSGI remains the default and ASGI is opt-in. Also updates the environment variable to FUNCTION_USE_ASGI for clarity. * fix: update conformance tests to use --asgi flag
Configuration menu - View commit details
-
Copy full SHA for 58deaf1 - Browse repository at this point
Copy the full SHA 58deaf1View commit details
Commits on Jul 22, 2025
-
fix: resolve CI failures for egress policies and Python 3.7 buildpack…
… support (#388) * fix: add GitHub Actions CDN to egress allowlist The conformance workflow was failing with ECONNREFUSED errors when trying to download Python binaries from GitHub releases. This was caused by the harden-runner egress policy blocking connections to the GitHub Actions CDN IP addresses. Added *.actions.githubusercontent.com:443 to the allowed endpoints to fix Python setup for all versions (3.7, 3.8, etc). * fix: remove Python 3.7 from buildpack integration tests Google Cloud Buildpacks dropped Python 3.7 support for Ubuntu 22.04. The version is not available in their runtime manifest. Note: Functions Framework still supports Python 3.7, which is tested in unit and conformance tests using GitHub Actions with Ubuntu 20.04. * fix: use correct domain for GitHub release assets The Python binaries are actually hosted on release-assets.githubusercontent.com, not *.actions.githubusercontent.com * fix: add release-assets domain to unit and conformance-asgi workflows The same ECONNREFUSED issue was affecting multiple workflows with harden-runner egress policies
Configuration menu - View commit details
-
Copy full SHA for 2de6eec - Browse repository at this point
Copy the full SHA 2de6eecView commit details -
refactor: move async dependencies from optional to direct (#386)
## Summary This PR moves starlette, uvicorn, and uvicorn-worker from optional dependencies to direct dependencies, simplifying the installation process for users who need async functionality. ## Impact Analysis - **Installation size increase: < 1MB** (specifically 816KB, ~3.5% increase) - Base installation: 23MB → With async deps: 24MB - Removes the need for `pip install functions-framework[async]` - Maintains Python 3.8+ requirement for these dependencies ## Changes - Move async dependencies to direct dependencies in `pyproject.toml` - Remove `[async]` extra dependency configuration - Update imports to be direct instead of conditional - Remove "Starlette is not installed" error messages - Update tests to reflect direct dependency availability ## Test Plan All existing tests pass with 100% coverage. The async functionality remains unchanged, just the installation method is simplified.
Configuration menu - View commit details
-
Copy full SHA for 82ba117 - Browse repository at this point
Copy the full SHA 82ba117View commit details
Commits on Jul 23, 2025
-
feat: auto-detect ASGI mode for @aio decorated functions (#387)
## Summary - Implement automatic ASGI mode detection for functions decorated with `@aio.http` or `@aio.cloud_event` - The approach creates a Flask app first, loads the module within its context, then checks if ASGI is needed - This results in an unused Flask app for ASGI functions, but we accept this memory overhead as a trade-off - The `--asgi` CLI flag still works and skips the Flask app creation for optimization ## Implementation Details - Added `ASGI_FUNCTIONS` set to `_function_registry.py` to track functions that require ASGI - Updated `@aio.http` and `@aio.cloud_event` decorators to register functions in `ASGI_FUNCTIONS` - Modified `create_app()` to auto-detect ASGI requirements after module loading: 1. Always creates a Flask app first 2. Loads the user module within Flask app context 3. Checks if target function is in `ASGI_FUNCTIONS` registry 4. If ASGI is needed, delegates to `create_asgi_app_from_module()` - The `--asgi` CLI flag continues to work, bypassing Flask app creation entirely for performance ## Trade-offs - **Memory overhead**: ASGI functions will have an unused Flask app instance created during auto-detection - **Accepted trade-off**: This avoids loading modules twice which could cause side effects - **Optimization available**: Users can still use `--asgi` flag to skip Flask app creation entirely ## Test plan - [x] Added tests to verify decorators register functions in `ASGI_FUNCTIONS` - [x] Added CLI tests to verify auto-detection works for `@aio` decorated functions - [x] Added CLI tests to verify regular functions still use Flask/WSGI mode - [x] Added proper test isolation with registry cleanup fixtures - [x] All existing tests pass - [x] Linting passes
Configuration menu - View commit details
-
Copy full SHA for ef48e70 - Browse repository at this point
Copy the full SHA ef48e70View commit details -
chore(main): release 3.9.0 (#374)
Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com>
Configuration menu - View commit details
-
Copy full SHA for d5ac6b4 - Browse repository at this point
Copy the full SHA d5ac6b4View commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v3.8.3...v3.9.0