@typespec/http-client-python 0.38.1 → 0.39.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,5 @@
1
1
  # coding=utf-8
2
+ {% set enable_sse_reconnect = code_model.options["enable-sse-reconnect"] %}
2
3
  {% if code_model.license_header %}
3
4
  {{ code_model.license_header }}
4
5
  {% endif %}
@@ -33,8 +34,11 @@ from typing import (
33
34
 
34
35
  from typing_extensions import Self
35
36
 
37
+ {% if enable_sse_reconnect %}
36
38
  from {{ code_model.core_library }}.exceptions import StreamClosedError, StreamConsumedError
37
- from {{ code_model.core_library }}.rest import AsyncHttpResponse, HttpRequest, HttpResponse
39
+ from {{ code_model.core_library }}.rest import HttpRequest
40
+ {% endif %}
41
+ from {{ code_model.core_library }}.rest import AsyncHttpResponse, HttpResponse
38
42
 
39
43
  DecodedType = TypeVar("DecodedType")
40
44
  ReturnType_co = TypeVar("ReturnType_co", covariant=True)
@@ -436,6 +440,7 @@ async def _aiter_sse_lines(iter_bytes: AsyncIterator[bytes]) -> AsyncGenerator[s
436
440
  yield line
437
441
 
438
442
 
443
+ {% if enable_sse_reconnect %}
439
444
  def _read_sse_response(response: HttpResponse) -> None:
440
445
  """Read an SSE response body, ignoring responses that are already consumed or closed.
441
446
 
@@ -474,14 +479,22 @@ def _update_sse_request_headers(request: HttpRequest, last_event_id: Optional[st
474
479
  request.headers.pop("Last-Event-ID", None)
475
480
 
476
481
 
482
+ {% endif %}
477
483
  class _SSEEventBuilder:
478
484
  """Accumulates SSE field lines and builds :class:`ServerSentEvent` instances.
479
485
 
486
+ {% if enable_sse_reconnect %}
480
487
  :param last_event_id: The initial value of the SSE last event ID buffer.
481
488
  :type last_event_id: str
489
+ {% endif %}
482
490
  """
483
491
 
492
+ {% if enable_sse_reconnect %}
484
493
  def __init__(self, last_event_id: str = "") -> None:
494
+ {% else %}
495
+ def __init__(self) -> None:
496
+ last_event_id = ""
497
+ {% endif %}
485
498
  self._data: List[str] = []
486
499
  self._event_type = ""
487
500
  self._last_id = last_event_id
@@ -565,12 +578,19 @@ class SSEDecoder:
565
578
 
566
579
  https://html.spec.whatwg.org/multipage/server-sent-events.html
567
580
 
581
+ {% if enable_sse_reconnect %}
568
582
  :keyword last_event_id: The initial value of the SSE last event ID buffer.
569
583
  :paramtype last_event_id: str or None
584
+ {% endif %}
570
585
  """
571
586
 
587
+ {% if enable_sse_reconnect %}
572
588
  def __init__(self, *, last_event_id: Optional[str] = None) -> None:
573
589
  self._builder = _SSEEventBuilder(last_event_id or "")
590
+ {% else %}
591
+ def __init__(self) -> None:
592
+ self._builder = _SSEEventBuilder()
593
+ {% endif %}
574
594
 
575
595
  @property
576
596
  def last_event_id(self) -> str:
@@ -609,12 +629,19 @@ class AsyncSSEDecoder:
609
629
 
610
630
  https://html.spec.whatwg.org/multipage/server-sent-events.html
611
631
 
632
+ {% if enable_sse_reconnect %}
612
633
  :keyword last_event_id: The initial value of the SSE last event ID buffer.
613
634
  :paramtype last_event_id: str or None
635
+ {% endif %}
614
636
  """
615
637
 
638
+ {% if enable_sse_reconnect %}
616
639
  def __init__(self, *, last_event_id: Optional[str] = None) -> None:
617
640
  self._builder = _SSEEventBuilder(last_event_id or "")
641
+ {% else %}
642
+ def __init__(self) -> None:
643
+ self._builder = _SSEEventBuilder()
644
+ {% endif %}
618
645
 
619
646
  @property
620
647
  def last_event_id(self) -> str:
@@ -672,6 +699,7 @@ class Stream(Iterator[ReturnType_co]):
672
699
  :keyword terminal_event_predicate: Optional predicate that identifies a payload-bearing
673
700
  terminal event. The event is yielded before iteration stops.
674
701
  :paramtype terminal_event_predicate: Callable[[Any], bool] or None
702
+ {% if enable_sse_reconnect %}
675
703
  :keyword last_event_id: Optional event ID from which this stream is resuming.
676
704
  :paramtype last_event_id: str or None
677
705
  :keyword reconnect_callback: Optional callback used to re-establish the underlying response
@@ -680,6 +708,7 @@ class Stream(Iterator[ReturnType_co]):
680
708
  called with the last-seen SSE event ID (or ``None``) and the reconnect delay in seconds,
681
709
  and must return a new response.
682
710
  :paramtype reconnect_callback: Callable[[str or None, float], ~{{ code_model.core_library }}.rest.HttpResponse] or None
711
+ {% endif %}
683
712
  """
684
713
 
685
714
  def __init__(
@@ -691,8 +720,10 @@ class Stream(Iterator[ReturnType_co]):
691
720
  terminal_event: Optional[str] = None,
692
721
  terminal_event_names: Optional[Sequence[str]] = None,
693
722
  terminal_event_predicate: Optional[Callable[[DecodedType], bool]] = None,
723
+ {% if enable_sse_reconnect %}
694
724
  last_event_id: Optional[str] = None,
695
725
  reconnect_callback: Optional[Callable[[Optional[str], float], HttpResponse]] = None,
726
+ {% endif %}
696
727
  ) -> None:
697
728
  self._response = response
698
729
  content_type = response.headers.get("Content-Type", "").split(";", 1)[0].strip().lower()
@@ -700,7 +731,7 @@ class Stream(Iterator[ReturnType_co]):
700
731
  decoder
701
732
  if decoder is not None
702
733
  else (
703
- SSEDecoder(last_event_id=last_event_id)
734
+ SSEDecoder({% if enable_sse_reconnect %}last_event_id=last_event_id{% endif %})
704
735
  if content_type == "text/event-stream"
705
736
  else JSONLDecoder()
706
737
  )
@@ -709,8 +740,12 @@ class Stream(Iterator[ReturnType_co]):
709
740
  self._terminal_event = terminal_event
710
741
  self._terminal_event_names = frozenset(terminal_event_names or ())
711
742
  self._terminal_event_predicate = terminal_event_predicate
743
+ {% if enable_sse_reconnect %}
712
744
  self._reconnect_callback = reconnect_callback
713
745
  self._last_event_id = last_event_id
746
+ {% else %}
747
+ self._last_event_id: Optional[str] = None
748
+ {% endif %}
714
749
  self._retry: Optional[int] = None
715
750
  self._iterator = self._iter_results()
716
751
 
@@ -731,7 +766,9 @@ class Stream(Iterator[ReturnType_co]):
731
766
  return self
732
767
 
733
768
  def _iter_results(self) -> Generator[ReturnType_co, None, None]:
769
+ {% if enable_sse_reconnect %}
734
770
  terminal = False
771
+ {% endif %}
735
772
  try:
736
773
  while True:
737
774
  if getattr(self._response, "status_code", None) == 204:
@@ -744,7 +781,9 @@ class Stream(Iterator[ReturnType_co]):
744
781
  if event_retry is not None:
745
782
  self._retry = event_retry
746
783
  if self._terminal_event is not None and getattr(event, "data", None) == self._terminal_event:
784
+ {% if enable_sse_reconnect %}
747
785
  terminal = True
786
+ {% endif %}
748
787
  break
749
788
  result = self._deserialization_callback(self._response, cast(Any, event))
750
789
  yield result
@@ -755,14 +794,17 @@ class Stream(Iterator[ReturnType_co]):
755
794
  self._terminal_event_predicate is not None
756
795
  and self._terminal_event_predicate(cast(Any, event))
757
796
  ):
797
+ {% if enable_sse_reconnect %}
758
798
  terminal = True
799
+ {% endif %}
759
800
  break
760
- if terminal or self._reconnect_callback is None:
761
- break
762
801
  if isinstance(self._decoder, SSEDecoder):
763
802
  self._last_event_id = self._decoder.last_event_id
764
803
  if self._decoder.retry is not None:
765
804
  self._retry = self._decoder.retry
805
+ {% if enable_sse_reconnect %}
806
+ if terminal or self._reconnect_callback is None:
807
+ break
766
808
  self._response.close()
767
809
  reconnect_delay = (self._retry if self._retry is not None else 3000) / 1000
768
810
  self._response = self._reconnect_callback(self._last_event_id, reconnect_delay)
@@ -771,6 +813,9 @@ class Stream(Iterator[ReturnType_co]):
771
813
  if isinstance(self._decoder, SSEDecoder)
772
814
  else type(self._decoder)()
773
815
  )
816
+ {% else %}
817
+ break
818
+ {% endif %}
774
819
  finally:
775
820
  self._response.close()
776
821
 
@@ -814,6 +859,7 @@ class AsyncStream(AsyncIterator[ReturnType_co]):
814
859
  :keyword terminal_event_predicate: Optional predicate that identifies a payload-bearing
815
860
  terminal event. The event is yielded before iteration stops.
816
861
  :paramtype terminal_event_predicate: Callable[[Any], bool] or None
862
+ {% if enable_sse_reconnect %}
817
863
  :keyword last_event_id: Optional event ID from which this stream is resuming.
818
864
  :paramtype last_event_id: str or None
819
865
  :keyword reconnect_callback: Optional callback used to re-establish the underlying response
@@ -822,6 +868,7 @@ class AsyncStream(AsyncIterator[ReturnType_co]):
822
868
  called with the last-seen SSE event ID (or ``None``) and the reconnect delay in seconds,
823
869
  and must resolve to a new response.
824
870
  :paramtype reconnect_callback: Callable[[str or None, float], Any] or None
871
+ {% endif %}
825
872
  """
826
873
 
827
874
  def __init__(
@@ -833,8 +880,10 @@ class AsyncStream(AsyncIterator[ReturnType_co]):
833
880
  terminal_event: Optional[str] = None,
834
881
  terminal_event_names: Optional[Sequence[str]] = None,
835
882
  terminal_event_predicate: Optional[Callable[[DecodedType], bool]] = None,
883
+ {% if enable_sse_reconnect %}
836
884
  last_event_id: Optional[str] = None,
837
885
  reconnect_callback: Optional[Callable[[Optional[str], float], Any]] = None,
886
+ {% endif %}
838
887
  ) -> None:
839
888
  self._response = response
840
889
  content_type = response.headers.get("Content-Type", "").split(";", 1)[0].strip().lower()
@@ -842,7 +891,7 @@ class AsyncStream(AsyncIterator[ReturnType_co]):
842
891
  decoder
843
892
  if decoder is not None
844
893
  else (
845
- AsyncSSEDecoder(last_event_id=last_event_id)
894
+ AsyncSSEDecoder({% if enable_sse_reconnect %}last_event_id=last_event_id{% endif %})
846
895
  if content_type == "text/event-stream"
847
896
  else AsyncJSONLDecoder()
848
897
  )
@@ -851,8 +900,12 @@ class AsyncStream(AsyncIterator[ReturnType_co]):
851
900
  self._terminal_event = terminal_event
852
901
  self._terminal_event_names = frozenset(terminal_event_names or ())
853
902
  self._terminal_event_predicate = terminal_event_predicate
903
+ {% if enable_sse_reconnect %}
854
904
  self._reconnect_callback = reconnect_callback
855
905
  self._last_event_id = last_event_id
906
+ {% else %}
907
+ self._last_event_id: Optional[str] = None
908
+ {% endif %}
856
909
  self._retry: Optional[int] = None
857
910
  self._iterator = self._iter_results()
858
911
 
@@ -873,7 +926,9 @@ class AsyncStream(AsyncIterator[ReturnType_co]):
873
926
  return self
874
927
 
875
928
  async def _iter_results(self) -> AsyncGenerator[ReturnType_co, None]:
929
+ {% if enable_sse_reconnect %}
876
930
  terminal = False
931
+ {% endif %}
877
932
  try:
878
933
  while True:
879
934
  if getattr(self._response, "status_code", None) == 204:
@@ -888,7 +943,9 @@ class AsyncStream(AsyncIterator[ReturnType_co]):
888
943
  if event_retry is not None:
889
944
  self._retry = event_retry
890
945
  if self._terminal_event is not None and getattr(event, "data", None) == self._terminal_event:
946
+ {% if enable_sse_reconnect %}
891
947
  terminal = True
948
+ {% endif %}
892
949
  break
893
950
  result = self._deserialization_callback(self._response, cast(Any, event))
894
951
  yield result
@@ -899,18 +956,21 @@ class AsyncStream(AsyncIterator[ReturnType_co]):
899
956
  self._terminal_event_predicate is not None
900
957
  and self._terminal_event_predicate(cast(Any, event))
901
958
  ):
959
+ {% if enable_sse_reconnect %}
902
960
  terminal = True
961
+ {% endif %}
903
962
  break
904
963
  finally:
905
964
  aclose = getattr(events, "aclose", None)
906
965
  if aclose is not None:
907
966
  await aclose()
908
- if terminal or self._reconnect_callback is None:
909
- break
910
967
  if isinstance(self._decoder, AsyncSSEDecoder):
911
968
  self._last_event_id = self._decoder.last_event_id
912
969
  if self._decoder.retry is not None:
913
970
  self._retry = self._decoder.retry
971
+ {% if enable_sse_reconnect %}
972
+ if terminal or self._reconnect_callback is None:
973
+ break
914
974
  await self._response.close()
915
975
  reconnect_delay = (self._retry if self._retry is not None else 3000) / 1000
916
976
  self._response = await self._reconnect_callback(self._last_event_id, reconnect_delay)
@@ -919,6 +979,9 @@ class AsyncStream(AsyncIterator[ReturnType_co]):
919
979
  if isinstance(self._decoder, AsyncSSEDecoder)
920
980
  else type(self._decoder)()
921
981
  )
982
+ {% else %}
983
+ break
984
+ {% endif %}
922
985
  finally:
923
986
  await self._response.close()
924
987
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/http-client-python",
3
- "version": "0.38.1",
3
+ "version": "0.39.0",
4
4
  "author": "Microsoft Corporation",
5
5
  "description": "TypeSpec emitter for Python SDKs",
6
6
  "homepage": "https://typespec.io",