|
8 | 8 | Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize |
9 | 9 | """ |
10 | 10 |
|
11 | | -from __future__ import annotations |
12 | | - |
13 | | -from collections.abc import Iterable, Mapping, MutableMapping |
14 | | -from typing import Any, Optional, Sequence, Tuple, Union, Mapping as TypingMapping, List, overload |
15 | | - |
16 | | -from ._models import MetadataFilter as _GeneratedMetadataFilter |
17 | | -from ._models import MetadataRecord |
18 | | -from ._models import AnswersFromTextOptions as _GeneratedAnswersFromTextOptions |
19 | | -from ._models import TextDocument |
20 | | - |
21 | | -__all__: list[str] = ["MetadataFilter", "AnswersFromTextOptions"] |
22 | | - |
23 | | -_MISSING = object() |
24 | | - |
25 | | - |
26 | | -def _normalize_metadata_sequence( |
27 | | - metadata: Any, |
28 | | -) -> Optional[list[MetadataRecord]]: |
29 | | - """Coerce supported metadata inputs into MetadataRecord objects.""" |
30 | | - |
31 | | - if metadata is None: |
32 | | - return None |
33 | | - |
34 | | - # Single MetadataRecord instance |
35 | | - if isinstance(metadata, MetadataRecord): |
36 | | - return [metadata] |
37 | | - |
38 | | - # Mapping inputs: |
39 | | - if isinstance(metadata, Mapping): |
40 | | - if "key" in metadata and "value" in metadata and len(metadata) <= 2: |
41 | | - return [MetadataRecord(key=metadata["key"], value=metadata["value"])] |
42 | | - metadata_iterable: Iterable[Any] = metadata.items() |
43 | | - else: |
44 | | - if isinstance(metadata, (str, bytes)): |
45 | | - raise ValueError( |
46 | | - "'metadata' must be provided as key/value pairs, MetadataRecord instances, " |
47 | | - "or mappings; strings are not supported." |
48 | | - ) |
49 | | - try: |
50 | | - metadata_iterable = iter(metadata) |
51 | | - except TypeError as exc: # pragma: no cover - defensive guard |
52 | | - raise ValueError("'metadata' must be an iterable of key/value pairs or MetadataRecord instances.") from exc |
53 | | - |
54 | | - normalized: list[MetadataRecord] = [] |
55 | | - for entry in metadata_iterable: |
56 | | - if isinstance(entry, MetadataRecord): |
57 | | - normalized.append(entry) |
58 | | - continue |
59 | | - if isinstance(entry, Mapping): |
60 | | - if "key" in entry and "value" in entry: |
61 | | - key = entry["key"] |
62 | | - value = entry["value"] |
63 | | - elif len(entry) == 1: |
64 | | - key, value = next(iter(entry.items())) |
65 | | - else: |
66 | | - raise ValueError( |
67 | | - "Mapping entries for 'metadata' must either contain 'key'/'value' keys " |
68 | | - "or represent a single key/value pair." |
69 | | - ) |
70 | | - else: |
71 | | - if isinstance(entry, (str, bytes)): |
72 | | - raise ValueError("Invalid metadata entry; expected a 2-item tuple but received a string/bytes value.") |
73 | | - try: |
74 | | - key, value = entry # type: ignore[assignment] |
75 | | - except (TypeError, ValueError) as exc: |
76 | | - raise ValueError( |
77 | | - "Each metadata entry must be a MetadataRecord, a mapping with 'key'/'value', " |
78 | | - "or a 2-item iterable representing (key, value)." |
79 | | - ) from exc |
80 | | - normalized.append(MetadataRecord(key=key, value=value)) |
81 | | - |
82 | | - return normalized |
83 | | - |
84 | | - |
85 | | -class MetadataFilter(_GeneratedMetadataFilter): |
86 | | - """Backward compatible MetadataFilter supporting legacy tuple/dict inputs. |
87 | | -
|
88 | | - Supported ``metadata`` input forms (all normalized to ``List[MetadataRecord]``): |
89 | | - 1. ``None`` – leave metadata unset. |
90 | | - 2. ``[("key","value"), ("k2","v2")]`` – list of 2-item tuples. |
91 | | - 3. ``[MetadataRecord(...), ...]`` – list of generated model records. |
92 | | - 4. ``[{"key": "k", "value": "v"}, ...]`` – list of mapping objects with key/value. |
93 | | - 5. ``{"k": "v", "k2": "v2"}`` – single mapping; each item becomes a record. |
94 | | - 6. ``{"key": "k", "value": "v"}`` – single record mapping. |
95 | | - 7. Mixed list: ``[MetadataRecord(...), ("k","v"), {"key":"a","value":"b"}]``. |
96 | | -
|
97 | | - Invalid inputs raise ``ValueError`` (e.g. plain string, bytes, malformed iterable). |
98 | | -
|
99 | | - The optional ``logical_operation`` parameter is passed through unchanged. |
100 | | - """ |
101 | | - |
102 | | - # Overload stubs to improve type hints and documentation rendering. |
103 | | - @overload |
104 | | - def __init__(self, *, metadata: None = ..., logical_operation: Optional[str] = ...) -> None: ... # noqa: D401,E701 |
105 | | - @overload |
106 | | - def __init__( |
107 | | - self, *, metadata: Sequence[Tuple[str, str]], logical_operation: Optional[str] = ... |
108 | | - ) -> None: ... # noqa: E701 |
109 | | - @overload |
110 | | - def __init__( |
111 | | - self, *, metadata: Sequence[MetadataRecord], logical_operation: Optional[str] = ... |
112 | | - ) -> None: ... # noqa: E701 |
113 | | - @overload |
114 | | - def __init__( |
115 | | - self, *, metadata: TypingMapping[str, str], logical_operation: Optional[str] = ... |
116 | | - ) -> None: ... # noqa: E701 |
117 | | - @overload |
118 | | - def __init__( |
119 | | - self, |
120 | | - *, |
121 | | - metadata: Sequence[Union[Tuple[str, str], MetadataRecord, TypingMapping[str, str]]], |
122 | | - logical_operation: Optional[str] = ..., |
123 | | - ) -> None: ... # noqa: E701 |
124 | | - |
125 | | - def __init__(self, *args: Any, **kwargs: Any) -> None: |
126 | | - metadata_kwarg = kwargs.pop("metadata", _MISSING) |
127 | | - args_list = list(args) |
128 | | - |
129 | | - if metadata_kwarg is not _MISSING: |
130 | | - kwargs["metadata"] = _normalize_metadata_sequence(metadata_kwarg) |
131 | | - elif args_list and isinstance(args_list[0], MutableMapping): |
132 | | - first_mapping = dict(args_list[0]) |
133 | | - if "metadata" in first_mapping: |
134 | | - first_mapping["metadata"] = _normalize_metadata_sequence(first_mapping["metadata"]) |
135 | | - args_list[0] = first_mapping |
136 | | - |
137 | | - super().__init__(*args_list, **kwargs) |
138 | | - |
139 | | - if self.metadata is not None: |
140 | | - self.metadata = _normalize_metadata_sequence(self.metadata) |
141 | | - |
142 | | - |
143 | | -class AnswersFromTextOptions(_GeneratedAnswersFromTextOptions): |
144 | | - """Convenience wrapper allowing ``text_documents`` to be a list of either ``str`` or ``TextDocument``. |
145 | | -
|
146 | | - This subclass accepts mixed inputs and converts plain strings to ``TextDocument`` instances |
147 | | - with auto-generated incremental string IDs ("0", "1", ...). It also sets ``string_index_type`` |
148 | | - to ``"UnicodeCodePoint"`` for consistent offset interpretation, exposing it as an extra |
149 | | - serialized field ``stringIndexType``. |
150 | | -
|
151 | | - Supported ``text_documents`` forms: |
152 | | - 1. ``["text one", "text two"]`` |
153 | | - 2. ``[TextDocument(id="a", text="...")]`` |
154 | | - 3. Mixed: ``["plain", TextDocument(id="b", text="...")]`` |
155 | | -
|
156 | | - :param question: User question to query against the given text records. Required. |
157 | | - :param text_documents: Text records as list of ``str`` or ``TextDocument``. Required. |
158 | | - :param language: Optional BCP-47 language code, e.g. "en", "zh-Hans", "es". |
159 | | - """ |
160 | | - |
161 | | - @overload |
162 | | - def __init__( |
163 | | - self, |
164 | | - *, |
165 | | - question: str, |
166 | | - text_documents: Sequence[str], |
167 | | - language: Optional[str] = None, |
168 | | - ) -> None: ... # noqa: E701 |
169 | | - |
170 | | - @overload |
171 | | - def __init__( |
172 | | - self, |
173 | | - *, |
174 | | - question: str, |
175 | | - text_documents: Sequence[TextDocument], |
176 | | - language: Optional[str] = None, |
177 | | - ) -> None: ... # noqa: E701 |
178 | | - |
179 | | - @overload |
180 | | - def __init__( |
181 | | - self, |
182 | | - *, |
183 | | - question: str, |
184 | | - text_documents: Sequence[Union[str, TextDocument]], |
185 | | - language: Optional[str] = None, |
186 | | - ) -> None: ... # noqa: E701 |
187 | | - |
188 | | - def __init__( |
189 | | - self, |
190 | | - *, |
191 | | - question: str, |
192 | | - text_documents: Sequence[Union[str, TextDocument]], |
193 | | - language: Optional[str] = None, |
194 | | - **kwargs: Any, |
195 | | - ) -> None: |
196 | | - # Normalize text_documents into List[TextDocument] |
197 | | - normalized: List[TextDocument] = [] |
198 | | - for idx, doc in enumerate(text_documents): |
199 | | - if isinstance(doc, TextDocument): |
200 | | - normalized.append(doc) |
201 | | - elif isinstance(doc, str): |
202 | | - normalized.append(TextDocument(id=str(idx), text=doc)) |
203 | | - else: |
204 | | - raise TypeError( |
205 | | - "Each item in 'text_documents' must be either a str or TextDocument; got {}".format(type(doc)) |
206 | | - ) |
207 | | - super().__init__(question=question, text_documents=normalized, language=language, **kwargs) |
208 | | - # Inject custom string index type attribute/serialization map |
209 | | - self.string_index_type = "UnicodeCodePoint" |
210 | | - # _attribute_map may not exist if underlying generator changed; guard accordingly. |
211 | | - try: # pragma: no cover - defensive |
212 | | - self._attribute_map.update({"string_index_type": {"key": "stringIndexType", "type": "str"}}) |
213 | | - except AttributeError: |
214 | | - pass |
215 | | - |
| 11 | +__all__ = [] |
216 | 12 |
|
217 | 13 | def patch_sdk(): |
218 | 14 | """Do not remove from this file. |
|
0 commit comments