[Storage-Files] Tsp migration#45828
Conversation
API Change CheckAPIView identified API level changes in this PR and created the following API reviews |
|
/azp run python - tables - tests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run python - storage - tests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run python - storage - tests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run python - storage - tests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
Pull request overview
Migrates azure-storage-file-share to the newer TypeSpec-generated client surface and updates handwritten convenience layers to accommodate updated generated models/operations.
Changes:
- Switched service/share/directory/file clients to use the new generated
FileClient(and patch layers) and updated many call sites to new parameter names/shapes. - Updated serialization/response handling to align with new generated types (e.g., lease/access conditions, stream download wrapping, etag field name changes).
- Added APIView metadata and updated packaging manifest to include generated typing marker.
Reviewed changes
Copilot reviewed 59 out of 114 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
azure/storage/fileshare/_directory_client.py |
Updates directory client to use TypeSpec-generated FileClient and new operation parameter names. |
azure/storage/fileshare/_share_client.py |
Updates share client to new generated client + lease/access policy payload changes. |
azure/storage/fileshare/_generated/** |
Replaces/patches generated code for TypeSpec (new client/config, enums/models init, patch hooks). |
| destination_range = f"bytes={offset}-{end_range}" | ||
| source_range = f"bytes={source_offset}-{source_offset + length - 1}" | ||
| source_authorization = kwargs.pop("source_authorization", None) | ||
| _source_mod_conditions = get_source_conditions(kwargs) | ||
| access_conditions = get_access_conditions(kwargs.pop("lease", None)) | ||
| file_last_write_mode = kwargs.pop("file_last_write_mode", None) | ||
|
|
||
| options = { | ||
| 'copy_source_authorization': source_authorization, | ||
| 'copy_source': source_url, | ||
| 'content_length': 0, | ||
| 'source_range': source_range, | ||
| 'range': destination_range, | ||
| 'file_last_written_mode': file_last_write_mode, | ||
| 'source_modified_access_conditions': source_mod_conditions, | ||
| 'lease_access_conditions': access_conditions, | ||
| 'timeout': kwargs.pop('timeout', None), | ||
| 'cls': return_response_headers | ||
| "copy_source_authorization": source_authorization, | ||
| "copy_source": source_url, | ||
| "content_length": 0, | ||
| "source_range": source_range, | ||
| "range": destination_range, | ||
| "file_range_write_from_url": "update", | ||
| "file_last_written_mode": file_last_write_mode, | ||
| "source_content_crc64": kwargs.pop("source_content_crc64", None), | ||
| "source_if_match_crc64": kwargs.pop("source_if_match_crc64", None), | ||
| "source_if_none_match_crc64": kwargs.pop("source_if_none_match_crc64", None), | ||
| "lease_id": access_conditions, | ||
| "timeout": kwargs.pop("timeout", None), | ||
| "cls": return_response_headers, | ||
| } |
There was a problem hiding this comment.
get_source_conditions(kwargs) is computed but never applied to options, which drops all source conditional headers (e.g., source_if_match, source_if_modified_since) for upload_range_from_url. This is a functional regression from the prior behavior where source access conditions were sent. Fix by merging the returned dict into options (or explicitly mapping each expected key for the new generated operation) and removing the leading-underscore variable name once it’s used.
| _MyMutableMapping.__getattr__ = _patched_getattr | ||
| _MyMutableMapping.__setattr__ = _patched_setattr | ||
| _MyMutableMapping.__getattribute__ = _patched_getattribute | ||
| _Model.__new__ = _patched_new |
There was a problem hiding this comment.
This module performs global monkeypatching at import time (modifying _MyMutableMapping and _Model for all consumers). That’s risky operationally and makes import side effects hard to reason about. Recommendation: move these assignments into patch_sdk() (and ensure patch_sdk() is invoked once from package init), so patching is explicit/controlled and easier to test/roll back if needed.
| def _strip_snapshot_from_url(url: str) -> str: | ||
| """Strip sharesnapshot and snapshot query params from a URL. | ||
|
|
||
| The generated client should receive a base URL without snapshot params, | ||
| since snapshots are passed per-operation. | ||
|
|
||
| :param str url: The full URL possibly containing snapshot query params. | ||
| :return: The URL with sharesnapshot and snapshot query params removed. | ||
| :rtype: str | ||
| """ | ||
| if "?" not in url: | ||
| return url | ||
| base, qs = url.split("?", 1) | ||
| filtered = "&".join(part for part in qs.split("&") if not part.startswith(("sharesnapshot=", "snapshot="))) | ||
| return f"{base}?{filtered}" if filtered else base |
There was a problem hiding this comment.
This introduces new URL normalization behavior that affects how all generated clients are constructed (snapshot params stripped at client creation instead of being preserved). Please add unit tests covering snapshot stripping behavior (including combinations with SAS query params and ordering) to prevent regressions during further generator updates.
|
/azp run python - storage - tests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Move pylint disable comments to the correct lines where violations occur (protected-access, unused-argument) and fix implicit string concatenation in _parser.py. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…h hacks Refactor the 10 custom subclasses in azure/storage/fileshare/_models.py (RetentionPolicy, Metrics, CorsRule, SmbMultichannel, SmbEncryptionInTransit, ShareSmbSettings, NfsEncryptionInTransit, ShareNfsSettings, ShareProtocolSettings, AccessPolicy) so they no longer shadow the parent _RestField descriptors and properly delegate to super().__init__(**kwargs). With the subclasses fixed at the source, the runtime monkey-patches in _generated/models/_patch.py (_patched_getattr/setattr/getattribute/new) are no longer needed; revert that file to the empty stock template. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
| @@ -1,3 +1,4 @@ | |||
| # pylint: disable=line-too-long,useless-suppression | |||
| # ------------------------------------------------------------------------- | |||
| # Copyright (c) Microsoft Corporation. All rights reserved. | |||
There was a problem hiding this comment.
will need to sync _shared here once finalized
Port changes from azure-storage-blob storageblob3 branch to keep _shared files consistent across Storage packages: - request_handlers.py: collapse split string literals - uploads.py / uploads_async.py: switch BlockBlob/PageBlob/AppendBlob ChunkUploader callers to keyword args and to the new etag / match_condition / append_position kwarg names; pop those kwargs in upload_data_chunks and upload_substream_blocks when running in parallel. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The wire format for creationTime/lastAccessTime/lastWriteTime/changeTime is ISO 8601, not RFC 7231 (only Last-Modified is RFC 7231). Declaring them as Optional[datetime.datetime] with format="rfc7231" causes the XML deserializer to fail and leave a raw xml.etree.ElementTree.Element in _data, which crashes JSON serialization downstream (Azure CLI). Match the legacy SDK behavior by declaring these fields as Optional[str]. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run python - storage - tests |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Resolved conflicts in azure-storage-file-share tests/perfstress by keeping the PR's reformatted versions (#46609 was pure pylint reformatting, already covered by the branch's own reformat). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Move 'protected-access' disables from closing-bracket lines onto the lines where '_from_generated' is actually accessed (Metrics, SharePropertiesPaged, HandlesPaged). - Use scoped 'disable/enable=protected-access' block in DirectoryPropertiesPaged._extract_data_cb (two accesses too long to carry inline disables under the 120-char limit). - Add 'unused-argument' disables to the backcompat **kwargs catch-all __init__ methods on SmbMultichannel, SmbEncryptionInTransit, ShareSmbSettings, NfsEncryptionInTransit, ShareNfsSettings, and ShareProtocolSettings. No logic changes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
See #46929 (to avoid continuously pinging Anna)