@@ -1800,7 +1800,9 @@ def get_openapi_schema(
18001800
18011801 # Build final components and paths
18021802 components = self ._build_openapi_components (definitions , config ["security_schemes" ])
1803- output .update (self ._finalize_openapi_output (components , config ["tags" ], paths , config ["external_documentation" ]))
1803+ output .update (
1804+ self ._finalize_openapi_output (components , config ["tags" ], paths , config ["external_documentation" ]),
1805+ )
18041806
18051807 # Apply schema fixes and return result
18061808 return self ._apply_schema_fixes (output )
@@ -1810,8 +1812,8 @@ def _resolve_openapi_config(self, **kwargs) -> dict[str, Any]:
18101812 # DEPRECATION: Will be removed in v4.0.0. Use configure_api() instead.
18111813 # Maintained for backwards compatibility.
18121814 # See: https://github.com/aws-powertools/powertools-lambda-python/issues/6122
1813- resolved = {}
1814-
1815+ resolved : dict [ str , Any ] = {}
1816+
18151817 # Handle fields with specific default value checks
18161818 self ._resolve_title_config (resolved , kwargs )
18171819 self ._resolve_version_config (resolved , kwargs )
@@ -1823,41 +1825,112 @@ def _resolve_openapi_config(self, **kwargs) -> dict[str, Any]:
18231825 return resolved
18241826
18251827 def _resolve_title_config (self , resolved : dict [str , Any ], kwargs : dict [str , Any ]) -> None :
1826- """Resolve title configuration with fallback to openapi_config."""
1828+ """
1829+ Resolve title configuration with fallback to openapi_config.
1830+
1831+ Checks if the provided title is the default value, and if so, uses the
1832+ title from openapi_config if available. This allows users to configure
1833+ a default title through the OpenAPI configuration object.
1834+
1835+ Parameters
1836+ ----------
1837+ resolved : dict[str, Any]
1838+ Dictionary to store the resolved configuration (modified in place)
1839+ kwargs : dict[str, Any]
1840+ Keyword arguments passed to get_openapi_schema
1841+ """
18271842 resolved ["title" ] = kwargs ["title" ]
18281843 if kwargs ["title" ] == DEFAULT_OPENAPI_TITLE and self .openapi_config .title :
18291844 resolved ["title" ] = self .openapi_config .title
18301845
18311846 def _resolve_version_config (self , resolved : dict [str , Any ], kwargs : dict [str , Any ]) -> None :
1832- """Resolve version configuration with fallback to openapi_config."""
1847+ """
1848+ Resolve version configuration with fallback to openapi_config.
1849+
1850+ Checks if the provided version is the default value, and if so, uses the
1851+ version from openapi_config if available. This allows users to configure
1852+ a default API version through the OpenAPI configuration object.
1853+
1854+ Parameters
1855+ ----------
1856+ resolved : dict[str, Any]
1857+ Dictionary to store the resolved configuration (modified in place)
1858+ kwargs : dict[str, Any]
1859+ Keyword arguments passed to get_openapi_schema
1860+ """
18331861 resolved ["version" ] = kwargs ["version" ]
18341862 if kwargs ["version" ] == DEFAULT_API_VERSION and self .openapi_config .version :
18351863 resolved ["version" ] = self .openapi_config .version
18361864
18371865 def _resolve_openapi_version_config (self , resolved : dict [str , Any ], kwargs : dict [str , Any ]) -> None :
1838- """Resolve openapi_version configuration with fallback to openapi_config."""
1866+ """
1867+ Resolve openapi_version configuration with fallback to openapi_config.
1868+
1869+ Checks if the provided OpenAPI version is the default value, and if so, uses
1870+ the version from openapi_config if available. This allows users to configure
1871+ a specific OpenAPI version through the OpenAPI configuration object.
1872+
1873+ Parameters
1874+ ----------
1875+ resolved : dict[str, Any]
1876+ Dictionary to store the resolved configuration (modified in place)
1877+ kwargs : dict[str, Any]
1878+ Keyword arguments passed to get_openapi_schema
1879+ """
18391880 resolved ["openapi_version" ] = kwargs ["openapi_version" ]
18401881 if kwargs ["openapi_version" ] == DEFAULT_OPENAPI_VERSION and self .openapi_config .openapi_version :
18411882 resolved ["openapi_version" ] = self .openapi_config .openapi_version
18421883
18431884 def _resolve_remaining_config_fields (self , resolved : dict [str , Any ], kwargs : dict [str , Any ]) -> None :
1844- """Resolve remaining configuration fields with simple fallbacks."""
1845- resolved .update ({
1846- "summary" : kwargs ["summary" ] or self .openapi_config .summary ,
1847- "description" : kwargs ["description" ] or self .openapi_config .description ,
1848- "tags" : kwargs ["tags" ] or self .openapi_config .tags ,
1849- "servers" : kwargs ["servers" ] or self .openapi_config .servers ,
1850- "terms_of_service" : kwargs ["terms_of_service" ] or self .openapi_config .terms_of_service ,
1851- "contact" : kwargs ["contact" ] or self .openapi_config .contact ,
1852- "license_info" : kwargs ["license_info" ] or self .openapi_config .license_info ,
1853- "security_schemes" : kwargs ["security_schemes" ] or self .openapi_config .security_schemes ,
1854- "security" : kwargs ["security" ] or self .openapi_config .security ,
1855- "external_documentation" : kwargs ["external_documentation" ] or self .openapi_config .external_documentation ,
1856- "openapi_extensions" : kwargs ["openapi_extensions" ] or self .openapi_config .openapi_extensions ,
1857- })
1885+ """
1886+ Resolve remaining configuration fields with simple fallbacks.
1887+
1888+ For fields that use simple OR logic, use the provided value from kwargs
1889+ or fall back to the value from openapi_config. This includes fields like
1890+ summary, description, tags, servers, etc.
1891+
1892+ Parameters
1893+ ----------
1894+ resolved : dict[str, Any]
1895+ Dictionary to store the resolved configuration (modified in place)
1896+ kwargs : dict[str, Any]
1897+ Keyword arguments passed to get_openapi_schema
1898+ """
1899+ resolved .update (
1900+ {
1901+ "summary" : kwargs ["summary" ] or self .openapi_config .summary ,
1902+ "description" : kwargs ["description" ] or self .openapi_config .description ,
1903+ "tags" : kwargs ["tags" ] or self .openapi_config .tags ,
1904+ "servers" : kwargs ["servers" ] or self .openapi_config .servers ,
1905+ "terms_of_service" : kwargs ["terms_of_service" ] or self .openapi_config .terms_of_service ,
1906+ "contact" : kwargs ["contact" ] or self .openapi_config .contact ,
1907+ "license_info" : kwargs ["license_info" ] or self .openapi_config .license_info ,
1908+ "security_schemes" : kwargs ["security_schemes" ] or self .openapi_config .security_schemes ,
1909+ "security" : kwargs ["security" ] or self .openapi_config .security ,
1910+ "external_documentation" : kwargs ["external_documentation" ]
1911+ or self .openapi_config .external_documentation ,
1912+ "openapi_extensions" : kwargs ["openapi_extensions" ] or self .openapi_config .openapi_extensions ,
1913+ },
1914+ )
18581915
18591916 def _build_base_openapi_structure (self , config : dict [str , Any ]) -> dict [str , Any ]:
1860- """Build the base OpenAPI structure with info, servers, and security."""
1917+ """
1918+ Build the base OpenAPI structure with info, servers, and security.
1919+
1920+ Creates the foundation of an OpenAPI schema including the required fields
1921+ (openapi version, info) and optional fields (servers, security) based on
1922+ the resolved configuration.
1923+
1924+ Parameters
1925+ ----------
1926+ config : dict[str, Any]
1927+ Resolved OpenAPI configuration dictionary containing title, version, etc.
1928+
1929+ Returns
1930+ -------
1931+ dict[str, Any]
1932+ Base OpenAPI structure dictionary ready for paths and components
1933+ """
18611934 openapi_version = self ._determine_openapi_version (config ["openapi_version" ])
18621935
18631936 # Start with the bare minimum required for a valid OpenAPI schema
@@ -1885,9 +1958,13 @@ def _build_base_openapi_structure(self, config: dict[str, Any]) -> dict[str, Any
18851958 ** openapi_extensions ,
18861959 }
18871960
1888- def _process_routes_for_openapi (self , security_schemes : dict [str , SecurityScheme ] | None ) -> tuple [dict [str , dict [str , Any ]], dict [str , dict [str , Any ]]]:
1961+ def _process_routes_for_openapi (
1962+ self ,
1963+ security_schemes : dict [str , SecurityScheme ] | None ,
1964+ ) -> tuple [dict [str , dict [str , Any ]], dict [str , dict [str , Any ]]]:
18891965 """Process all routes and build paths and definitions."""
18901966 from pydantic .json_schema import GenerateJsonSchema
1967+
18911968 from aws_lambda_powertools .event_handler .openapi .compat import (
18921969 get_compat_model_name_map ,
18931970 get_definitions ,
@@ -1912,7 +1989,7 @@ def _process_routes_for_openapi(self, security_schemes: dict[str, SecurityScheme
19121989 # Add routes to the OpenAPI schema
19131990 for route in all_routes :
19141991 self ._validate_route_security (route , security_schemes )
1915-
1992+
19161993 if not route .include_in_schema :
19171994 continue
19181995
@@ -1943,45 +2020,71 @@ def _validate_route_security(self, route, security_schemes: dict[str, SecuritySc
19432020 "See: https://docs.powertools.aws.dev/lambda/python/latest/core/event_handler/api_gateway/#security-schemes" ,
19442021 )
19452022
1946- def _build_openapi_components (self , definitions : dict [str , dict [str , Any ]], security_schemes : dict [str , SecurityScheme ] | None ) -> dict [str , dict [str , Any ]]:
2023+ def _build_openapi_components (
2024+ self ,
2025+ definitions : dict [str , dict [str , Any ]],
2026+ security_schemes : dict [str , SecurityScheme ] | None ,
2027+ ) -> dict [str , dict [str , Any ]]:
19472028 """Build the components section of the OpenAPI schema."""
19482029 components : dict [str , dict [str , Any ]] = {}
1949-
2030+
19502031 if definitions :
19512032 components ["schemas" ] = self ._generate_schemas (definitions )
19522033 if security_schemes :
19532034 components ["securitySchemes" ] = security_schemes
1954-
2035+
19552036 return components
19562037
1957- def _finalize_openapi_output (self , components : dict [str , dict [str , Any ]], tags , paths : dict [str , dict [str , Any ]], external_documentation ) -> dict [str , Any ]:
2038+ def _finalize_openapi_output (
2039+ self ,
2040+ components : dict [str , dict [str , Any ]],
2041+ tags ,
2042+ paths : dict [str , dict [str , Any ]],
2043+ external_documentation ,
2044+ ) -> dict [str , Any ]:
19582045 """Finalize the OpenAPI output with components, tags, and paths."""
19592046 from aws_lambda_powertools .event_handler .openapi .models import PathItem , Tag
19602047
1961- output = {}
1962-
2048+ output : dict [ str , Any ] = {}
2049+
19632050 if components :
19642051 output ["components" ] = components
19652052 if tags :
19662053 output ["tags" ] = [Tag (name = tag ) if isinstance (tag , str ) else tag for tag in tags ]
19672054 if external_documentation :
19682055 output ["externalDocs" ] = external_documentation
19692056
1970- output ["paths" ] = {k : PathItem (** v ) for k , v in paths .items ()}
1971-
2057+ output ["paths" ] = {k : PathItem (** v ) if not isinstance ( v , PathItem ) else v for k , v in paths .items ()}
2058+
19722059 return output
19732060
19742061 def _apply_schema_fixes (self , output : dict [str , Any ]) -> OpenAPI :
1975- """Apply schema fixes and return the final OpenAPI model."""
2062+ """
2063+ Apply schema fixes and return the final OpenAPI model.
2064+
2065+ This method handles various schema fixes, including resolving missing
2066+ component references for UploadFile parameters that can cause validation
2067+ errors in OpenAPI tools like Swagger Editor.
2068+
2069+ Parameters
2070+ ----------
2071+ output : dict[str, Any]
2072+ The OpenAPI schema dictionary to process
2073+
2074+ Returns
2075+ -------
2076+ OpenAPI
2077+ The final OpenAPI model with all fixes applied
2078+ """
19762079 from aws_lambda_powertools .event_handler .openapi .models import OpenAPI
1977- from aws_lambda_powertools .event_handler .openapi .upload_file_fix import fix_upload_file_schema
2080+ from aws_lambda_powertools .event_handler .openapi .params import fix_upload_file_schema_references
19782081
19792082 # First create the OpenAPI model
19802083 result = OpenAPI (** output )
19812084
1982- # Convert the model to a dict and apply the fix
2085+ # Convert the model to a dict and apply the upload file schema fix
19832086 result_dict = result .model_dump (by_alias = True )
1984- fixed_dict = fix_upload_file_schema (result_dict )
2087+ fixed_dict = fix_upload_file_schema_references (result_dict )
19852088
19862089 # Reconstruct the model with the fixed dict
19872090 return OpenAPI (** fixed_dict )
0 commit comments