@@ -359,7 +359,13 @@ def _render_method(operation: Operation, errors: dict[str, dict[str, Any]], *, i
359359 " )" ,
360360 ]
361361 elif operation .kind == "void" :
362- lines += [f" { awaiting } self._client.request(" , * request_options , ' kind="void",' , " )" ]
362+ # Returned so ``with_raw_response`` can hand back the response; a plain call returns ``None``.
363+ lines += [
364+ f' return cast("None", { awaiting } self._client.request(' ,
365+ * request_options ,
366+ ' kind="void",' ,
367+ " ))" ,
368+ ]
363369 elif operation .kind == "binary" :
364370 lines += [
365371 f' return cast("bytes", { awaiting } self._client.request(' ,
@@ -412,13 +418,67 @@ def _resource_classes(resource: Resource, errors: dict[str, dict[str, Any]], *,
412418 f' """Operations under ``client.{ _attr_path (child )} ``."""' ,
413419 f" return { prefix } { child .class_name } Resource(self._client)\n " ,
414420 ]
421+ for kind , summary in _WRAPPERS :
422+ lines += [
423+ " @cached_property" ,
424+ f" def { kind } (self) -> { prefix } { resource .class_name } Resource{ _WRAPPER_SUFFIX [kind ]} :" ,
425+ f' """{ summary } """' ,
426+ f" return { prefix } { resource .class_name } Resource{ _WRAPPER_SUFFIX [kind ]} (self)\n " ,
427+ ]
415428 for operation in resource .operations :
416429 lines += _render_method (operation , errors , is_async = is_async )
417430 lines .append ("" )
418431 blocks .append ("\n " .join (lines ).rstrip () + "\n " )
432+ for kind , _ in _WRAPPERS :
433+ blocks .append (_wrapper_class (resource , kind , is_async = is_async ))
419434 return blocks
420435
421436
437+ _WRAPPERS = (
438+ (
439+ "with_raw_response" ,
440+ "Same methods, returning the raw HTTP response; call ``.parse()`` on it for the usual value." ,
441+ ),
442+ (
443+ "with_streaming_response" ,
444+ "Same methods, returning a context manager over the HTTP response without reading the body." ,
445+ ),
446+ )
447+ _WRAPPER_SUFFIX = {"with_raw_response" : "WithRawResponse" , "with_streaming_response" : "WithStreamingResponse" }
448+ _WRAPPER_FUNCTION = {
449+ ("with_raw_response" , False ): "to_raw_response_wrapper" ,
450+ ("with_streaming_response" , False ): "to_streamed_response_wrapper" ,
451+ ("with_raw_response" , True ): "async_to_raw_response_wrapper" ,
452+ ("with_streaming_response" , True ): "async_to_streamed_response_wrapper" ,
453+ }
454+
455+
456+ def _wrapper_class (resource : Resource , kind : str , * , is_async : bool ) -> str :
457+ prefix = "Async" if is_async else ""
458+ suffix = _WRAPPER_SUFFIX [kind ]
459+ name = f"{ prefix } { resource .class_name } Resource"
460+ wrap = _WRAPPER_FUNCTION [(kind , is_async )]
461+ lines = [
462+ f"class { name } { suffix } :" ,
463+ f' """``client.{ _attr_path (resource )} .{ kind } ``."""\n ' ,
464+ f" def __init__(self, resource: { name } ) -> None:" ,
465+ " self._resource = resource" ,
466+ * [
467+ f" self.{ operation .method_name } = { wrap } (resource.{ operation .method_name } )"
468+ for operation in resource .operations
469+ ],
470+ "" ,
471+ ]
472+ for child_name , child in resource .children .items ():
473+ lines += [
474+ " @cached_property" ,
475+ f" def { child_name } (self) -> { prefix } { child .class_name } Resource{ suffix } :" ,
476+ f' """``client.{ _attr_path (child )} .{ kind } ``."""' ,
477+ f" return { prefix } { child .class_name } Resource{ suffix } (self._resource.{ child_name } )\n " ,
478+ ]
479+ return "\n " .join (lines ).rstrip () + "\n "
480+
481+
422482def _attr_path (resource : Resource ) -> str :
423483 return "." .join (safe_identifier (snake (part )) for part in resource .path )
424484
@@ -478,6 +538,12 @@ def render_resource_module(
478538 * [f"from ..{ module } import { ', ' .join (sorted ({sync , async_ }))} " for module , sync , async_ in _mixins (resource )],
479539 * ([f"from .._qs import { ', ' .join (runtime )} " ] if runtime else []),
480540 "from .._resource import AsyncAPIResource, SyncAPIResource" ,
541+ "from .._response import (" ,
542+ " async_to_raw_response_wrapper," ,
543+ " async_to_streamed_response_wrapper," ,
544+ " to_raw_response_wrapper," ,
545+ " to_streamed_response_wrapper," ,
546+ ")" ,
481547 * (["from .._streaming import AsyncStream, Stream" ] if any (op .kind == "stream" for op in operations ) else []),
482548 "from .._types import NOT_GIVEN, Body, Headers, NotGiven, Query, Timeout"
483549 + (", OpenEnum" if "OpenEnum" in uses else "" ),
0 commit comments