panel-openapi¶
panel_openapi
¶
Accessible imports for the panel_openapi package.
__all__ = ['Field', 'OpenAPIForm', 'OpenAPIRecordEditor', '__version__', 'collect_fields', 'create_app', 'find_update_operations', 'get_operation', 'load_openapi', 'response_schema', 'schema_to_widget']
module-attribute
¶
__version__ = importlib.metadata.version(__name__)
module-attribute
¶
Field
dataclass
¶
A single input derived from an operation's parameters or request body.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The parameter or property name used when assembling the request. |
required |
location
|
FieldLocation
|
Where the value belongs in the request ( |
required |
schema
|
Schema
|
The resolved JSON schema describing the value. |
required |
required
|
bool
|
Whether the field must be provided. |
False
|
read_only
|
bool
|
Whether the schema marks the value |
False
|
OpenAPIForm
¶
Bases: Viewer
Auto-generated form for a single OpenAPI operation.
Setting :attr:path or :attr:method rebuilds the widgets for the newly
referenced operation in place, and setting :attr:base_url redirects
subsequent requests, so one form can be pointed at any operation in the
document it was constructed with. To change both at once use
form.param.update(path=..., method=...), which rebuilds only once and
avoids a transient pair the document does not define.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
str or dict or OpenAPI
|
The OpenAPI document, as a URL, raw dict or parsed model. |
required |
base_url
|
str
|
The base URL requests are issued against, e.g. |
required |
path
|
str
|
The templated operation path, e.g. |
required |
method
|
str
|
The HTTP method for the operation. |
'get'
|
headers
|
dict
|
Static headers (e.g. authentication) sent with every request. The mapping is read on each submit, so mutating it swaps credentials at runtime. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
form |
Column
|
The widgets and submit button. Rebuilt in place when the operation changes, so the container may be laid out once and kept. |
response |
Column
|
The status and body of the most recent response, empty until submit. |
base_url = param.String(default='', doc='Base URL requests are issued against.')
class-attribute
instance-attribute
¶
fields
property
¶
Descriptors for the inputs of the current operation.
form = pmui.Column(sizing_mode='stretch_width')
instance-attribute
¶
method = param.Selector(default='get', objects=['get', 'post', 'put', 'patch', 'delete'], doc='HTTP method of the operation.')
class-attribute
instance-attribute
¶
operation
property
¶
The operation the form currently targets.
path = param.String(default='', doc='Templated path of the operation.')
class-attribute
instance-attribute
¶
response = pmui.Column(sizing_mode='stretch_width')
instance-attribute
¶
skip_read_only = param.Boolean(default=False, constant=True, doc='Whether to omit body properties marked readOnly entirely. When False they are shown as disabled widgets. Either way they are never sent, since the server does not accept them.')
class-attribute
instance-attribute
¶
title = param.String(default='', doc='Human-readable title, derived from the operation unless set explicitly.')
class-attribute
instance-attribute
¶
values
property
¶
The values that would be sent, keyed by field name.
widgets
property
¶
The current widgets, keyed by field name.
get_values(location=None)
¶
Return the values that would be sent, keyed by field name.
JSON text areas are returned parsed. Fields left empty and fields marked
readOnly are omitted, mirroring the request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
location
|
str
|
Restrict the result to one of |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Field name to value. |
populate(record)
¶
Set widget values from a record, ignoring what does not fit.
Population is deliberately tolerant: a record fetched from a live API routinely carries keys the request body does not accept, and values a widget cannot represent. Rather than raising, both are skipped and reported, so a partially populated form is still usable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
dict
|
Field name to value, e.g. the parsed body of a |
required |
Returns:
| Type | Description |
|---|---|
list of str
|
Names of keys that could not be applied, either because no widget matched or because the value was rejected. |
submit(extra=None)
async
¶
Issue the request for the current values and render the response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
extra
|
dict
|
Additional body properties merged into the payload, overriding the widget values. Used to send a subset or superset of the form, e.g. a PATCH diff. |
None
|
Returns:
| Type | Description |
|---|---|
Response or None
|
The response, or |
OpenAPIRecordEditor
¶
Bases: Viewer
Fetch a record from an operation and edit it via another.
The editor composes two :class:~panel_openapi.form.OpenAPIForm instances:
a lookup form for the read operation, and an edit form for the update
operation. Loading a record populates the edit form, and saving sends the
edits back to the same resource.
The update operation is discovered on the same path, preferring PATCH
over PUT over POST, unless update_method names one. Because
POST on a path means "update this" in some APIs and "create a
subresource" in others, the resolved operation is always displayed.
A PATCH save sends only the fields that differ from the loaded record,
matching the convention that omitted keys are left alone. PUT and
POST send the full body.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
str or dict or OpenAPI
|
The OpenAPI document, as a URL, raw dict or parsed model. |
required |
base_url
|
str
|
The base URL requests are issued against. |
required |
path
|
str
|
The templated path of the record, e.g. |
required |
method
|
str
|
The method used to read the record. |
'get'
|
update_method
|
str
|
The method used to save. Auto-detected when omitted. |
None
|
headers
|
dict
|
Static headers sent with every request. |
None
|
show_lookup
|
bool
|
Whether to render the lookup form. Set |
True
|
**params
|
Any
|
Remaining parameters, notably |
{}
|
Examples:
Point it at a path and let it find the update operation:
>>> editor = OpenAPIRecordEditor(
... spec, base_url="https://petstore3.swagger.io/api/v3", path="/pet/{petId}"
... )
Or drive it without the lookup UI:
>>> editor = OpenAPIRecordEditor(spec, base_url=..., path=..., show_lookup=False)
>>> await editor.load(petId=7)
base_url = param.String(default='', doc='Base URL requests are issued against.')
class-attribute
instance-attribute
¶
confirm = param.Boolean(default=False, doc='Whether the Save button opens a dialog showing the pending changes first.')
class-attribute
instance-attribute
¶
editor = None
instance-attribute
¶
loaded
property
¶
Whether a record has been loaded.
lookup = OpenAPIForm(self._openapi, base_url=(self.base_url), path=(self.path), method=(self.method), headers=(self._headers))
instance-attribute
¶
method = param.Selector(default='get', objects=['get', 'post', 'put', 'patch', 'delete'], doc='Method used to read the record.')
class-attribute
instance-attribute
¶
path = param.String(default='', doc='Templated path of the record.')
class-attribute
instance-attribute
¶
record = param.Dict(default=None, allow_None=True, doc='The record last loaded or saved, and the baseline a PATCH diffs against.')
class-attribute
instance-attribute
¶
update_method = candidates[0] if candidates else None
class-attribute
instance-attribute
¶
diff()
¶
Return the edits pending against the loaded record.
Returns:
| Type | Description |
|---|---|
dict
|
Field name to |
load(**lookup)
async
¶
Fetch a record and populate the edit form.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**lookup
|
Any
|
Values for the read operation's inputs, e.g. |
{}
|
Returns:
| Type | Description |
|---|---|
dict or None
|
The fetched record, or |
populate(record)
¶
Populate the edit form from a record without fetching it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
dict
|
The record to edit. Becomes the baseline a |
required |
save()
async
¶
Send the edits and adopt the response as the new record.
Bypasses the confirmation dialog, which is only wired to the Save button, so calling this always saves.
Returns:
| Type | Description |
|---|---|
dict or None
|
The saved record as the server returned it, or |
collect_fields(openapi, operation, skip_read_only=False)
¶
Flatten an operation's parameters and JSON body into fields.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
OpenAPI
|
The document the operation belongs to. |
required |
operation
|
Operation
|
The operation to introspect. |
required |
skip_read_only
|
bool
|
Whether to drop body properties marked |
False
|
Returns:
| Type | Description |
|---|---|
list of Field
|
Ordered descriptors for every path, query, header and body field. |
create_app()
¶
Create the demo OpenAPI form.
Returns:
| Type | Description |
|---|---|
OpenAPIForm
|
A form for the |
find_update_operations(openapi, path)
¶
Return the methods on path that could update the record it returns.
Only the path is used as evidence, since request and response schemas
routinely differ for the same record: the Swagger Petstore reuses Pet
for both, while FastAPI typically responds with a model carrying
server-assigned fields that the request model omits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
OpenAPI
|
The document to inspect. |
required |
path
|
str
|
The templated path whose operations are considered. |
required |
Returns:
| Type | Description |
|---|---|
list of str
|
Matching methods, most likely first ( |
get_operation(openapi, path, method)
¶
Return the :class:Operation for a path and HTTP method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
OpenAPI
|
The document to look the operation up in. |
required |
path
|
str
|
The templated path, e.g. |
required |
method
|
str
|
The HTTP method, case-insensitive. |
required |
Returns:
| Type | Description |
|---|---|
Operation
|
The matching operation, with any parameters declared on the path item merged into its own. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the path is unknown or the method is not defined for it. |
load_openapi(source)
¶
Load and validate an OpenAPI document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str or dict or OpenAPI
|
Either an already parsed :class: |
required |
Returns:
| Type | Description |
|---|---|
OpenAPI
|
The validated OpenAPI model. |
response_schema(openapi, operation)
¶
Return the JSON schema of an operation's success response.
The lowest 2xx response that declares a JSON body wins, falling back to a
default response. This is the schema of the record a GET returns,
which :class:~panel_openapi.editor.OpenAPIRecordEditor populates a form
from.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
OpenAPI
|
The document the operation belongs to. |
required |
operation
|
Operation
|
The operation to inspect. |
required |
Returns:
| Type | Description |
|---|---|
Schema or None
|
The response schema, or |
schema_to_widget(name, schema, required=False)
¶
Return a panel-material-ui widget for editing a schema value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The field name, used as the widget label when no |
required |
schema
|
Schema
|
The resolved JSON schema describing the value. |
required |
required
|
bool
|
Whether the field is required. Recorded on the widget's |
False
|
Returns:
| Type | Description |
|---|---|
Widget
|
The widget best matching the schema. Values of type |
editor
¶
Look up a record from an OpenAPI operation and edit it.
:class:OpenAPIRecordEditor pairs a read operation with an update operation on
the same path: it fetches a record, populates a form from the response, and
sends the edits back.
OpenAPIRecordEditor
¶
Bases: Viewer
Fetch a record from an operation and edit it via another.
The editor composes two :class:~panel_openapi.form.OpenAPIForm instances:
a lookup form for the read operation, and an edit form for the update
operation. Loading a record populates the edit form, and saving sends the
edits back to the same resource.
The update operation is discovered on the same path, preferring PATCH
over PUT over POST, unless update_method names one. Because
POST on a path means "update this" in some APIs and "create a
subresource" in others, the resolved operation is always displayed.
A PATCH save sends only the fields that differ from the loaded record,
matching the convention that omitted keys are left alone. PUT and
POST send the full body.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
str or dict or OpenAPI
|
The OpenAPI document, as a URL, raw dict or parsed model. |
required |
base_url
|
str
|
The base URL requests are issued against. |
required |
path
|
str
|
The templated path of the record, e.g. |
required |
method
|
str
|
The method used to read the record. |
'get'
|
update_method
|
str
|
The method used to save. Auto-detected when omitted. |
None
|
headers
|
dict
|
Static headers sent with every request. |
None
|
show_lookup
|
bool
|
Whether to render the lookup form. Set |
True
|
**params
|
Any
|
Remaining parameters, notably |
{}
|
Examples:
Point it at a path and let it find the update operation:
>>> editor = OpenAPIRecordEditor(
... spec, base_url="https://petstore3.swagger.io/api/v3", path="/pet/{petId}"
... )
Or drive it without the lookup UI:
>>> editor = OpenAPIRecordEditor(spec, base_url=..., path=..., show_lookup=False)
>>> await editor.load(petId=7)
base_url = param.String(default='', doc='Base URL requests are issued against.')
class-attribute
instance-attribute
¶
confirm = param.Boolean(default=False, doc='Whether the Save button opens a dialog showing the pending changes first.')
class-attribute
instance-attribute
¶
editor = None
instance-attribute
¶
loaded
property
¶
Whether a record has been loaded.
lookup = OpenAPIForm(self._openapi, base_url=(self.base_url), path=(self.path), method=(self.method), headers=(self._headers))
instance-attribute
¶
method = param.Selector(default='get', objects=['get', 'post', 'put', 'patch', 'delete'], doc='Method used to read the record.')
class-attribute
instance-attribute
¶
path = param.String(default='', doc='Templated path of the record.')
class-attribute
instance-attribute
¶
record = param.Dict(default=None, allow_None=True, doc='The record last loaded or saved, and the baseline a PATCH diffs against.')
class-attribute
instance-attribute
¶
update_method = candidates[0] if candidates else None
class-attribute
instance-attribute
¶
diff()
¶
Return the edits pending against the loaded record.
Returns:
| Type | Description |
|---|---|
dict
|
Field name to |
load(**lookup)
async
¶
Fetch a record and populate the edit form.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
**lookup
|
Any
|
Values for the read operation's inputs, e.g. |
{}
|
Returns:
| Type | Description |
|---|---|
dict or None
|
The fetched record, or |
populate(record)
¶
Populate the edit form from a record without fetching it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
dict
|
The record to edit. Becomes the baseline a |
required |
save()
async
¶
Send the edits and adopt the response as the new record.
Bypasses the confirmation dialog, which is only wired to the Save button, so calling this always saves.
Returns:
| Type | Description |
|---|---|
dict or None
|
The saved record as the server returned it, or |
form
¶
A Panel form that drives a single OpenAPI operation.
:class:OpenAPIForm introspects one path + method of an OpenAPI document,
renders a panel-material-ui widget per parameter and JSON body property, and on
submit issues the HTTP request and displays the response.
OpenAPIForm
¶
Bases: Viewer
Auto-generated form for a single OpenAPI operation.
Setting :attr:path or :attr:method rebuilds the widgets for the newly
referenced operation in place, and setting :attr:base_url redirects
subsequent requests, so one form can be pointed at any operation in the
document it was constructed with. To change both at once use
form.param.update(path=..., method=...), which rebuilds only once and
avoids a transient pair the document does not define.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
str or dict or OpenAPI
|
The OpenAPI document, as a URL, raw dict or parsed model. |
required |
base_url
|
str
|
The base URL requests are issued against, e.g. |
required |
path
|
str
|
The templated operation path, e.g. |
required |
method
|
str
|
The HTTP method for the operation. |
'get'
|
headers
|
dict
|
Static headers (e.g. authentication) sent with every request. The mapping is read on each submit, so mutating it swaps credentials at runtime. |
None
|
Attributes:
| Name | Type | Description |
|---|---|---|
form |
Column
|
The widgets and submit button. Rebuilt in place when the operation changes, so the container may be laid out once and kept. |
response |
Column
|
The status and body of the most recent response, empty until submit. |
base_url = param.String(default='', doc='Base URL requests are issued against.')
class-attribute
instance-attribute
¶
fields
property
¶
Descriptors for the inputs of the current operation.
form = pmui.Column(sizing_mode='stretch_width')
instance-attribute
¶
method = param.Selector(default='get', objects=['get', 'post', 'put', 'patch', 'delete'], doc='HTTP method of the operation.')
class-attribute
instance-attribute
¶
operation
property
¶
The operation the form currently targets.
path = param.String(default='', doc='Templated path of the operation.')
class-attribute
instance-attribute
¶
response = pmui.Column(sizing_mode='stretch_width')
instance-attribute
¶
skip_read_only = param.Boolean(default=False, constant=True, doc='Whether to omit body properties marked readOnly entirely. When False they are shown as disabled widgets. Either way they are never sent, since the server does not accept them.')
class-attribute
instance-attribute
¶
title = param.String(default='', doc='Human-readable title, derived from the operation unless set explicitly.')
class-attribute
instance-attribute
¶
values
property
¶
The values that would be sent, keyed by field name.
widgets
property
¶
The current widgets, keyed by field name.
get_values(location=None)
¶
Return the values that would be sent, keyed by field name.
JSON text areas are returned parsed. Fields left empty and fields marked
readOnly are omitted, mirroring the request.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
location
|
str
|
Restrict the result to one of |
None
|
Returns:
| Type | Description |
|---|---|
dict
|
Field name to value. |
populate(record)
¶
Set widget values from a record, ignoring what does not fit.
Population is deliberately tolerant: a record fetched from a live API routinely carries keys the request body does not accept, and values a widget cannot represent. Rather than raising, both are skipped and reported, so a partially populated form is still usable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
record
|
dict
|
Field name to value, e.g. the parsed body of a |
required |
Returns:
| Type | Description |
|---|---|
list of str
|
Names of keys that could not be applied, either because no widget matched or because the value was rejected. |
submit(extra=None)
async
¶
Issue the request for the current values and render the response.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
extra
|
dict
|
Additional body properties merged into the payload, overriding the widget values. Used to send a subset or superset of the form, e.g. a PATCH diff. |
None
|
Returns:
| Type | Description |
|---|---|
Response or None
|
The response, or |
main
¶
Demo entry point for panel-openapi.
Running panel serve src/panel_openapi/main.py builds an :class:OpenAPIForm
for a small inline OpenAPI spec targeting httpbin.org <https://httpbin.org>_,
so the generated form can be submitted against a live endpoint.
DEMO_SPEC = {'openapi': '3.0.0', 'info': {'title': 'httpbin demo', 'version': '1.0.0'}, 'paths': {'/anything': {'post': {'summary': 'Echo a payload', 'description': 'Send a JSON payload to httpbin and see it echoed back.', 'requestBody': {'required': True, 'content': {'application/json': {'schema': {'type': 'object', 'required': ['name'], 'properties': {'name': {'type': 'string', 'title': 'Name'}, 'role': {'type': 'string', 'enum': ['admin', 'user', 'guest'], 'title': 'Role'}, 'age': {'type': 'integer', 'minimum': 0, 'maximum': 120, 'title': 'Age'}, 'subscribed': {'type': 'boolean', 'title': 'Subscribed'}}}}}}, 'responses': {'200': {'description': 'The echoed request.'}}}}}}
module-attribute
¶
create_app()
¶
Create the demo OpenAPI form.
Returns:
| Type | Description |
|---|---|
OpenAPIForm
|
A form for the |
schema
¶
Load and introspect OpenAPI documents.
This module wraps :mod:openapi_pydantic to load an OpenAPI schema from a URL
or dictionary, resolve $ref references, locate a specific operation and
flatten its parameters and JSON request body into a list of field descriptors
that the widget layer can turn into inputs.
FieldLocation = Literal['path', 'query', 'header', 'body']
module-attribute
¶
Field
dataclass
¶
A single input derived from an operation's parameters or request body.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The parameter or property name used when assembling the request. |
required |
location
|
FieldLocation
|
Where the value belongs in the request ( |
required |
schema
|
Schema
|
The resolved JSON schema describing the value. |
required |
required
|
bool
|
Whether the field must be provided. |
False
|
read_only
|
bool
|
Whether the schema marks the value |
False
|
collect_fields(openapi, operation, skip_read_only=False)
¶
Flatten an operation's parameters and JSON body into fields.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
OpenAPI
|
The document the operation belongs to. |
required |
operation
|
Operation
|
The operation to introspect. |
required |
skip_read_only
|
bool
|
Whether to drop body properties marked |
False
|
Returns:
| Type | Description |
|---|---|
list of Field
|
Ordered descriptors for every path, query, header and body field. |
find_update_operations(openapi, path)
¶
Return the methods on path that could update the record it returns.
Only the path is used as evidence, since request and response schemas
routinely differ for the same record: the Swagger Petstore reuses Pet
for both, while FastAPI typically responds with a model carrying
server-assigned fields that the request model omits.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
OpenAPI
|
The document to inspect. |
required |
path
|
str
|
The templated path whose operations are considered. |
required |
Returns:
| Type | Description |
|---|---|
list of str
|
Matching methods, most likely first ( |
get_operation(openapi, path, method)
¶
Return the :class:Operation for a path and HTTP method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
OpenAPI
|
The document to look the operation up in. |
required |
path
|
str
|
The templated path, e.g. |
required |
method
|
str
|
The HTTP method, case-insensitive. |
required |
Returns:
| Type | Description |
|---|---|
Operation
|
The matching operation, with any parameters declared on the path item merged into its own. |
Raises:
| Type | Description |
|---|---|
KeyError
|
If the path is unknown or the method is not defined for it. |
load_openapi(source)
¶
Load and validate an OpenAPI document.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source
|
str or dict or OpenAPI
|
Either an already parsed :class: |
required |
Returns:
| Type | Description |
|---|---|
OpenAPI
|
The validated OpenAPI model. |
resolve_ref(openapi, obj)
¶
Resolve a $ref against the document's components.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
OpenAPI
|
The document the reference is resolved against. |
required |
obj
|
Reference or Schema or Parameter or None
|
The object to resolve. Non-reference objects are returned unchanged. |
required |
Returns:
| Type | Description |
|---|---|
Any
|
The referenced component, or |
response_schema(openapi, operation)
¶
Return the JSON schema of an operation's success response.
The lowest 2xx response that declares a JSON body wins, falling back to a
default response. This is the schema of the record a GET returns,
which :class:~panel_openapi.editor.OpenAPIRecordEditor populates a form
from.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
openapi
|
OpenAPI
|
The document the operation belongs to. |
required |
operation
|
Operation
|
The operation to inspect. |
required |
Returns:
| Type | Description |
|---|---|
Schema or None
|
The response schema, or |
widgets
¶
Map OpenAPI/JSON schemas to panel-material-ui widgets.
The single public entry point is :func:schema_to_widget, which inspects a
resolved :class:~openapi_pydantic.Schema and returns the most appropriate
panel-material-ui widget for editing that value.
schema_to_widget(name, schema, required=False)
¶
Return a panel-material-ui widget for editing a schema value.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
The field name, used as the widget label when no |
required |
schema
|
Schema
|
The resolved JSON schema describing the value. |
required |
required
|
bool
|
Whether the field is required. Recorded on the widget's |
False
|
Returns:
| Type | Description |
|---|---|
Widget
|
The widget best matching the schema. Values of type |
unwrap_nullable(schema)
¶
Collapse a nullable union to the single schema that carries the type.
anyOf/oneOf with exactly one non-null branch is how an optional
value is expressed in OpenAPI 3.0 and by pydantic for T | None, which
covers most fields of a PATCH request model. Unwrapping it means such fields
get a real widget rather than a JSON text area. Genuine unions of two or more
types are left alone.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
schema
|
Schema
|
The schema to unwrap. |
required |
Returns:
| Type | Description |
|---|---|
Schema
|
The sole non-null branch with the outer title and description preserved,
or |