Skip to content

Commit e4680f8

Browse files
Abel Milashclaude
andcommitted
Fix fetchxml() position in async_query.py: move above sql_columns
Order now matches sync exactly: builder, sql, fetchxml, sql_columns, odata_expands. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d738377 commit e4680f8

1 file changed

Lines changed: 60 additions & 60 deletions

File tree

src/PowerPlatform/Dataverse/aio/operations/async_query.py

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,66 @@ async def sql(self, sql: str) -> List[Record]:
148148
rows = await od._query_sql(sql)
149149
return [Record.from_api_response("", row) for row in rows]
150150

151+
# --------------------------------------------------------------- fetchxml
152+
153+
def fetchxml(self, xml: str) -> AsyncFetchXmlQuery:
154+
"""Return an inert :class:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery` object.
155+
156+
No HTTP request is made until
157+
:meth:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery.execute`
158+
or
159+
:meth:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery.execute_pages`
160+
is called on the returned object.
161+
162+
:param xml: Well-formed FetchXML query string. The root ``<entity name="...">``
163+
element determines the entity set endpoint.
164+
:type xml: :class:`str`
165+
:return: Inert async query object.
166+
:rtype: :class:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery`
167+
:raises ValidationError: If the FetchXML is not a string, is empty, or exceeds the URL
168+
length limit when encoded.
169+
:raises ValueError: If the FetchXML is missing a root ``<entity>`` element or name.
170+
171+
Example::
172+
173+
query = client.query.fetchxml(\"\"\"
174+
<fetch top="50">
175+
<entity name="account">
176+
<attribute name="name" />
177+
</entity>
178+
</fetch>
179+
\"\"\")
180+
181+
# Eager — all pages collected:
182+
result = await query.execute()
183+
df = result.to_dataframe()
184+
185+
# Lazy — one page at a time:
186+
async for page in query.execute_pages():
187+
process(page.to_dataframe())
188+
"""
189+
if not isinstance(xml, str):
190+
raise ValidationError("xml must be a string")
191+
xml = xml.strip()
192+
if not xml:
193+
raise ValidationError("xml must not be empty")
194+
if len(_url_quote(xml, safe="")) > _MAX_URL_LENGTH:
195+
raise ValidationError(
196+
f"FetchXML exceeds the Dataverse URL length limit ({_MAX_URL_LENGTH:,} characters) when encoded. "
197+
"Use a $batch POST request to send FetchXML in the request body where the limit is 64 KB."
198+
)
199+
try:
200+
root_el = _ET.fromstring(xml)
201+
except _ET.ParseError as exc:
202+
raise ValidationError(f"xml is not well-formed: {exc}") from exc
203+
entity_el = root_el.find("entity")
204+
if entity_el is None:
205+
raise ValueError("FetchXML must contain an <entity> child element")
206+
entity_name = entity_el.get("name", "")
207+
if not entity_name:
208+
raise ValueError("FetchXML <entity> element must have a 'name' attribute")
209+
return AsyncFetchXmlQuery(xml, entity_name, self._client)
210+
151211
# --------------------------------------------------------------- sql_columns
152212

153213
async def sql_columns(
@@ -232,66 +292,6 @@ async def sql_columns(
232292
result.sort(key=lambda x: (not x["is_pk"], not x["is_name"], x["name"]))
233293
return result
234294

235-
# --------------------------------------------------------------- fetchxml
236-
237-
def fetchxml(self, xml: str) -> AsyncFetchXmlQuery:
238-
"""Return an inert :class:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery` object.
239-
240-
No HTTP request is made until
241-
:meth:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery.execute`
242-
or
243-
:meth:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery.execute_pages`
244-
is called on the returned object.
245-
246-
:param xml: Well-formed FetchXML query string. The root ``<entity name="...">``
247-
element determines the entity set endpoint.
248-
:type xml: :class:`str`
249-
:return: Inert async query object.
250-
:rtype: :class:`~PowerPlatform.Dataverse.models.async_fetchxml_query.AsyncFetchXmlQuery`
251-
:raises ValidationError: If the FetchXML is not a string, is empty, or exceeds the URL
252-
length limit when encoded.
253-
:raises ValueError: If the FetchXML is missing a root ``<entity>`` element or name.
254-
255-
Example::
256-
257-
query = client.query.fetchxml(\"\"\"
258-
<fetch top="50">
259-
<entity name="account">
260-
<attribute name="name" />
261-
</entity>
262-
</fetch>
263-
\"\"\")
264-
265-
# Eager — all pages collected:
266-
result = await query.execute()
267-
df = result.to_dataframe()
268-
269-
# Lazy — one page at a time:
270-
async for page in query.execute_pages():
271-
process(page.to_dataframe())
272-
"""
273-
if not isinstance(xml, str):
274-
raise ValidationError("xml must be a string")
275-
xml = xml.strip()
276-
if not xml:
277-
raise ValidationError("xml must not be empty")
278-
if len(_url_quote(xml, safe="")) > _MAX_URL_LENGTH:
279-
raise ValidationError(
280-
f"FetchXML exceeds the Dataverse URL length limit ({_MAX_URL_LENGTH:,} characters) when encoded. "
281-
"Use a $batch POST request to send FetchXML in the request body where the limit is 64 KB."
282-
)
283-
try:
284-
root_el = _ET.fromstring(xml)
285-
except _ET.ParseError as exc:
286-
raise ValidationError(f"xml is not well-formed: {exc}") from exc
287-
entity_el = root_el.find("entity")
288-
if entity_el is None:
289-
raise ValueError("FetchXML must contain an <entity> child element")
290-
entity_name = entity_el.get("name", "")
291-
if not entity_name:
292-
raise ValueError("FetchXML <entity> element must have a 'name' attribute")
293-
return AsyncFetchXmlQuery(xml, entity_name, self._client)
294-
295295
# =========================================================================
296296
# OData helpers -- discover columns, navigation properties, and bind values
297297
# =========================================================================

0 commit comments

Comments
 (0)