aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/azure/storage/fileshare/_models.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/azure/storage/fileshare/_models.py')
-rw-r--r--.venv/lib/python3.12/site-packages/azure/storage/fileshare/_models.py1294
1 files changed, 1294 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/azure/storage/fileshare/_models.py b/.venv/lib/python3.12/site-packages/azure/storage/fileshare/_models.py
new file mode 100644
index 00000000..ec95b64c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/azure/storage/fileshare/_models.py
@@ -0,0 +1,1294 @@
+# -------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for
+# license information.
+# --------------------------------------------------------------------------
+# pylint: disable=too-few-public-methods, too-many-instance-attributes, super-init-not-called, too-many-lines
+
+from enum import Enum
+from typing import (
+ Any, Callable, Dict, List, Literal, Optional, Union,
+ TYPE_CHECKING
+)
+from urllib.parse import unquote
+from typing_extensions import Self
+
+from azure.core import CaseInsensitiveEnumMeta
+from azure.core.exceptions import HttpResponseError
+from azure.core.paging import PageIterator
+
+from ._generated.models import AccessPolicy as GenAccessPolicy
+from ._generated.models import CorsRule as GeneratedCorsRule
+from ._generated.models import DirectoryItem
+from ._generated.models import Metrics as GeneratedMetrics
+from ._generated.models import RetentionPolicy as GeneratedRetentionPolicy
+from ._generated.models import ShareProtocolSettings as GeneratedShareProtocolSettings
+from ._generated.models import ShareSmbSettings as GeneratedShareSmbSettings
+from ._generated.models import SmbMultichannel as GeneratedSmbMultichannel
+from ._generated.models import StorageServiceProperties as GeneratedStorageServiceProperties
+from ._parser import _parse_datetime_from_str
+from ._shared.models import DictMixin, get_enum_value
+from ._shared.response_handlers import process_storage_error, return_context_and_deserialized
+
+if TYPE_CHECKING:
+ from datetime import datetime
+ from ._generated.models import ShareRootSquash
+
+
+def _wrap_item(item):
+ if isinstance(item, DirectoryItem):
+ return {'name': item.name, 'is_directory': True}
+ return {'name': item.name, 'size': item.properties.content_length, 'is_directory': False}
+
+
+class RetentionPolicy(GeneratedRetentionPolicy):
+ """The retention policy which determines how long the associated data should
+ persist.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param bool enabled:
+ Indicates whether a retention policy is enabled for the storage service.
+ :param Optional[int] days:
+ Indicates the number of days that metrics or logging or soft-deleted data should be retained.
+ All data older than this value will be deleted.
+ """
+
+ enabled: bool = False
+ """Indicates whether a retention policy is enabled for the storage service."""
+ days: Optional[int] = None
+ """Indicates the number of days that metrics or logging or soft-deleted data should be retained.
+ All data older than this value will be deleted."""
+
+ def __init__(self, enabled: bool = False, days: Optional[int] = None) -> None:
+ self.enabled = enabled
+ self.days = days
+ if self.enabled and (self.days is None):
+ raise ValueError("If policy is enabled, 'days' must be specified.")
+
+ @classmethod
+ def _from_generated(cls, generated):
+ if not generated:
+ return cls()
+ return cls(
+ enabled=generated.enabled,
+ days=generated.days,
+ )
+
+
+class Metrics(GeneratedMetrics):
+ """A summary of request statistics grouped by API in hour or minute aggregates
+ for files.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :keyword str version:
+ The version of Storage Analytics to configure. The default value is 1.0.
+ :keyword bool enabled:
+ Indicates whether metrics are enabled for the File service.
+ :keyword bool include_apis:
+ Indicates whether metrics should generate summary statistics for called API operations.
+ :keyword ~azure.storage.fileshare.RetentionPolicy retention_policy:
+ Determines how long the associated data should persist.
+ """
+
+ version: str = '1.0'
+ """The version of Storage Analytics to configure."""
+ enabled: bool = False
+ """Indicates whether metrics are enabled for the File service."""
+ include_apis: bool
+ """Indicates whether metrics should generate summary statistics for called API operations."""
+ retention_policy: RetentionPolicy = RetentionPolicy()
+ """Determines how long the associated data should persist."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.version = kwargs.get('version', '1.0')
+ self.enabled = kwargs.get('enabled', False)
+ self.include_apis = kwargs.get('include_apis') # type: ignore [assignment]
+ self.retention_policy = kwargs.get('retention_policy') or RetentionPolicy()
+
+ @classmethod
+ def _from_generated(cls, generated):
+ if not generated:
+ return cls()
+ return cls(
+ version=generated.version,
+ enabled=generated.enabled,
+ include_apis=generated.include_apis,
+ retention_policy=RetentionPolicy._from_generated(generated.retention_policy) # pylint: disable=protected-access
+ )
+
+
+class CorsRule(GeneratedCorsRule):
+ """CORS is an HTTP feature that enables a web application running under one
+ domain to access resources in another domain. Web browsers implement a
+ security restriction known as same-origin policy that prevents a web page
+ from calling APIs in a different domain; CORS provides a secure way to
+ allow one domain (the origin domain) to call APIs in another domain.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :param List[str] allowed_origins:
+ A list of origin domains that will be allowed via CORS, or "*" to allow
+ all domains. The list of must contain at least one entry. Limited to 64
+ origin domains. Each allowed origin can have up to 256 characters.
+ :param List[str] allowed_methods:
+ A list of HTTP methods that are allowed to be executed by the origin.
+ The list of must contain at least one entry. For Azure Storage,
+ permitted methods are DELETE, GET, HEAD, MERGE, POST, OPTIONS or PUT.
+ :keyword List[str] allowed_headers:
+ Defaults to an empty list. A list of headers allowed to be part of
+ the cross-origin request. Limited to 64 defined headers and 2 prefixed
+ headers. Each header can be up to 256 characters.
+ :keyword List[str] exposed_headers:
+ Defaults to an empty list. A list of response headers to expose to CORS
+ clients. Limited to 64 defined headers and two prefixed headers. Each
+ header can be up to 256 characters.
+ :keyword int max_age_in_seconds:
+ The number of seconds that the client/browser should cache a
+ preflight response.
+ """
+
+ allowed_origins: str
+ """The comma-delimited string representation of the list of origin domains
+ that will be allowed via CORS, or "*" to allow all domains."""
+ allowed_methods: str
+ """The comma-delimited string representation of the list of HTTP methods
+ that are allowed to be executed by the origin."""
+ allowed_headers: str
+ """The comma-delimited string representation of the list of headers
+ allowed to be a part of the cross-origin request."""
+ exposed_headers: str
+ """The comma-delimited string representation of the list of response
+ headers to expose to CORS clients."""
+ max_age_in_seconds: int
+ """The number of seconds that the client/browser should cache a pre-flight response."""
+
+ def __init__(self, allowed_origins: List[str], allowed_methods: List[str], **kwargs: Any) -> None:
+ self.allowed_origins = ','.join(allowed_origins)
+ self.allowed_methods = ','.join(allowed_methods)
+ self.allowed_headers = ','.join(kwargs.get('allowed_headers', []))
+ self.exposed_headers = ','.join(kwargs.get('exposed_headers', []))
+ self.max_age_in_seconds = kwargs.get('max_age_in_seconds', 0)
+
+ @staticmethod
+ def _to_generated(rules: Optional[List["CorsRule"]]) -> Optional[List[GeneratedCorsRule]]:
+ if rules is None:
+ return rules
+
+ generated_cors_list = []
+ for cors_rule in rules:
+ generated_cors = GeneratedCorsRule(
+ allowed_origins=cors_rule.allowed_origins,
+ allowed_methods=cors_rule.allowed_methods,
+ allowed_headers=cors_rule.allowed_headers,
+ exposed_headers=cors_rule.exposed_headers,
+ max_age_in_seconds=cors_rule.max_age_in_seconds,
+ )
+ generated_cors_list.append(generated_cors)
+
+ return generated_cors_list
+
+ @classmethod
+ def _from_generated(cls, generated):
+ return cls(
+ [generated.allowed_origins],
+ [generated.allowed_methods],
+ allowed_headers=[generated.allowed_headers],
+ exposed_headers=[generated.exposed_headers],
+ max_age_in_seconds=generated.max_age_in_seconds,
+ )
+
+
+class SmbMultichannel(GeneratedSmbMultichannel):
+ """Settings for Multichannel.
+
+ :keyword bool enabled: If SMB Multichannel is enabled.
+ """
+
+ enabled: Optional[bool]
+ """If SMB Multichannel is enabled."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.enabled = kwargs.get('enabled')
+ if self.enabled is None:
+ raise ValueError("The value 'enabled' must be specified.")
+
+
+class ShareSmbSettings(GeneratedShareSmbSettings):
+ """Settings for the SMB protocol.
+
+ :keyword SmbMultichannel multichannel: Sets the multichannel settings.
+ """
+
+ multichannel: SmbMultichannel
+ """Sets the multichannel settings."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.multichannel = kwargs.get('multichannel') # type: ignore [assignment]
+ if self.multichannel is None:
+ raise ValueError("The value 'multichannel' must be specified.")
+
+
+class ShareProtocolSettings(GeneratedShareProtocolSettings):
+ """Protocol Settings class used by the set and get service properties methods in the share service.
+
+ Contains protocol properties of the share service such as the SMB setting of the share service.
+
+ :keyword ShareSmbSettings smb: Sets SMB settings.
+ """
+
+ smb: ShareSmbSettings
+ """Sets the SMB settings."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.smb = kwargs.get('smb') # type: ignore [assignment]
+ if self.smb is None:
+ raise ValueError("The value 'smb' must be specified.")
+
+ @classmethod
+ def _from_generated(cls, generated):
+ return cls(
+ smb=generated.smb)
+
+
+class ShareSasPermissions(object):
+ """ShareSasPermissions class to be used to be used with
+ generating shared access signature and access policy operations.
+
+ :param bool read:
+ Read the content, properties or metadata of any file in the share. Use any
+ file in the share as the source of a copy operation.
+ :param bool write:
+ For any file in the share, create or write content, properties or metadata.
+ Resize the file. Use the file as the destination of a copy operation within
+ the same account.
+ Note: You cannot grant permissions to read or write share properties or
+ metadata with a service SAS. Use an account SAS instead.
+ :param bool delete:
+ Delete any file in the share.
+ Note: You cannot grant permissions to delete a share with a service SAS. Use
+ an account SAS instead.
+ :param bool list:
+ List files and directories in the share.
+ :param bool create:
+ Create a new file in the share, or copy a file to a new file in the share.
+ """
+
+ read: bool = False
+ """The read permission for share SAS."""
+ write: bool = False
+ """The write permission for share SAS."""
+ delete: bool = False
+ """The delete permission for share SAS."""
+ list: bool = False
+ """The list permission for share SAS."""
+ create: bool = False
+ """The create permission for share SAS."""
+
+ def __init__(
+ self, read: bool = False,
+ write: bool = False,
+ delete: bool = False,
+ list: bool = False,
+ create: bool = False
+ ) -> None:
+ self.read = read
+ self.create = create
+ self.write = write
+ self.delete = delete
+ self.list = list
+ self._str = (('r' if self.read else '') +
+ ('c' if self.create else '') +
+ ('w' if self.write else '') +
+ ('d' if self.delete else '') +
+ ('l' if self.list else ''))
+
+ def __str__(self) -> str:
+ return self._str
+
+ @classmethod
+ def from_string(cls, permission: str) -> Self:
+ """Create a ShareSasPermissions from a string.
+
+ To specify read, create, write, delete, or list permissions you need only to
+ include the first letter of the word in the string. E.g. For read and
+ write permissions, you would provide a string "rw".
+
+ :param str permission: The string which dictates the read, create, write,
+ delete, or list permissions
+ :return: A ShareSasPermissions object
+ :rtype: ~azure.storage.fileshare.ShareSasPermissions
+ """
+ p_read = 'r' in permission
+ p_create = 'c' in permission
+ p_write = 'w' in permission
+ p_delete = 'd' in permission
+ p_list = 'l' in permission
+
+ parsed = cls(p_read, p_write, p_delete, p_list, p_create)
+
+ return parsed
+
+
+class AccessPolicy(GenAccessPolicy):
+ """Access Policy class used by the set and get acl methods in each service.
+
+ A stored access policy can specify the start time, expiry time, and
+ permissions for the Shared Access Signatures with which it's associated.
+ Depending on how you want to control access to your resource, you can
+ specify all of these parameters within the stored access policy, and omit
+ them from the URL for the Shared Access Signature. Doing so permits you to
+ modify the associated signature's behavior at any time, as well as to revoke
+ it. Or you can specify one or more of the access policy parameters within
+ the stored access policy, and the others on the URL. Finally, you can
+ specify all of the parameters on the URL. In this case, you can use the
+ stored access policy to revoke the signature, but not to modify its behavior.
+
+ Together the Shared Access Signature and the stored access policy must
+ include all fields required to authenticate the signature. If any required
+ fields are missing, the request will fail. Likewise, if a field is specified
+ both in the Shared Access Signature URL and in the stored access policy, the
+ request will fail with status code 400 (Bad Request).
+
+ :param permission:
+ The permissions associated with the shared access signature. The
+ user is restricted to operations allowed by the permissions.
+ Required unless an id is given referencing a stored access policy
+ which contains this field. This field must be omitted if it has been
+ specified in an associated stored access policy.
+ :type permission: str or ~azure.storage.fileshare.FileSasPermissions or
+ ~azure.storage.fileshare.ShareSasPermissions
+ :param expiry:
+ The time at which the shared access signature becomes invalid.
+ Required unless an id is given referencing a stored access policy
+ which contains this field. This field must be omitted if it has
+ been specified in an associated stored access policy. Azure will always
+ convert values to UTC. If a date is passed in without timezone info, it
+ is assumed to be UTC.
+ :type expiry: ~datetime.datetime or str
+ :param start:
+ The time at which the shared access signature becomes valid. If
+ omitted, start time for this call is assumed to be the time when the
+ storage service receives the request. The provided datetime will always
+ be interpreted as UTC.
+ :type start: ~datetime.datetime or str
+ """
+
+ permission: Optional[Union[ShareSasPermissions, str]] # type: ignore [assignment]
+ """The permissions associated with the shared access signature. The user is restricted to
+ operations allowed by the permissions."""
+ expiry: Optional[Union["datetime", str]] # type: ignore [assignment]
+ """The time at which the shared access signature becomes invalid."""
+ start: Optional[Union["datetime", str]] # type: ignore [assignment]
+ """The time at which the shared access signature becomes valid."""
+
+ def __init__(
+ self, permission: Optional[Union[ShareSasPermissions, str]] = None,
+ expiry: Optional[Union["datetime", str]] = None,
+ start: Optional[Union["datetime", str]] = None
+ ) -> None:
+ self.start = start
+ self.expiry = expiry
+ self.permission = permission
+
+
+class LeaseProperties(DictMixin):
+ """File or Share Lease Properties."""
+
+ status: str
+ """The lease status of the file or share. Possible values: locked|unlocked"""
+ state: str
+ """Lease state of the file or share. Possible values: available|leased|expired|breaking|broken"""
+ duration: Optional[str]
+ """When a file or share is leased, specifies whether the lease is of infinite or fixed duration."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.status = get_enum_value(kwargs.get('x-ms-lease-status'))
+ self.state = get_enum_value(kwargs.get('x-ms-lease-state'))
+ self.duration = get_enum_value(kwargs.get('x-ms-lease-duration'))
+
+ @classmethod
+ def _from_generated(cls, generated):
+ lease = cls()
+ lease.status = get_enum_value(generated.properties.lease_status)
+ lease.state = get_enum_value(generated.properties.lease_state)
+ lease.duration = get_enum_value(generated.properties.lease_duration)
+ return lease
+
+
+class ContentSettings(DictMixin):
+ """Used to store the content settings of a file.
+
+ :param Optional[str] content_type:
+ The content type specified for the file. If no content type was
+ specified, the default content type is application/octet-stream.
+ :param Optional[str] content_encoding:
+ If the content_encoding has previously been set
+ for the file, that value is stored.
+ :param Optional[str] content_language:
+ If the content_language has previously been set
+ for the file, that value is stored.
+ :param Optional[str] content_disposition:
+ content_disposition conveys additional information about how to
+ process the response payload, and also can be used to attach
+ additional metadata. If content_disposition has previously been set
+ for the file, that value is stored.
+ :param Optional[str] cache_control:
+ If the cache_control has previously been set for
+ the file, that value is stored.
+ :param Optional[bytearray] content_md5:
+ If the content_md5 has been set for the file, this response
+ header is stored so that the client can check for message content
+ integrity.
+ """
+
+ content_type: Optional[str] = None
+ """The content type specified for the file."""
+ content_encoding: Optional[str] = None
+ """The content encoding specified for the file."""
+ content_language: Optional[str] = None
+ """The content language specified for the file."""
+ content_disposition: Optional[str] = None
+ """The content disposition specified for the file."""
+ cache_control: Optional[str] = None
+ """The cache control specified for the file."""
+ content_md5: Optional[bytearray] = None
+ """The content md5 specified for the file."""
+
+ def __init__(
+ self, content_type: Optional[str] = None,
+ content_encoding: Optional[str] = None,
+ content_language: Optional[str] = None,
+ content_disposition: Optional[str] = None,
+ cache_control: Optional[str] = None,
+ content_md5: Optional[bytearray] = None,
+ **kwargs: Any
+ ) -> None:
+ self.content_type = content_type or kwargs.get('Content-Type')
+ self.content_encoding = content_encoding or kwargs.get('Content-Encoding')
+ self.content_language = content_language or kwargs.get('Content-Language')
+ self.content_md5 = content_md5 or kwargs.get('Content-MD5')
+ self.content_disposition = content_disposition or kwargs.get('Content-Disposition')
+ self.cache_control = cache_control or kwargs.get('Cache-Control')
+
+ @classmethod
+ def _from_generated(cls, generated):
+ settings = cls()
+ settings.content_type = generated.properties.content_type or None
+ settings.content_encoding = generated.properties.content_encoding or None
+ settings.content_language = generated.properties.content_language or None
+ settings.content_md5 = generated.properties.content_md5 or None
+ settings.content_disposition = generated.properties.content_disposition or None
+ settings.cache_control = generated.properties.cache_control or None
+ return settings
+
+
+class ShareProperties(DictMixin):
+ """Share's properties class."""
+
+ name: str
+ """The name of the share."""
+ last_modified: "datetime"
+ """A datetime object representing the last time the share was modified."""
+ etag: str
+ """The ETag contains a value that you can use to perform operations conditionally."""
+ quota: int
+ """The allocated quota."""
+ access_tier: str
+ """The share's access tier.'"""
+ next_allowed_quota_downgrade_time: Optional[str] = None
+ """The share's next allowed quota downgrade time."""
+ metadata: Dict[str, str]
+ """Name-value pairs associate with the share as metadata."""
+ snapshot: Optional[str] = None
+ """Snapshot of the share."""
+ deleted: Optional[bool] = None
+ """Whether this share was deleted.
+ This is a service returned value, and the value will be set when list shared including deleted ones."""
+ deleted_time: Optional["datetime"] = None
+ """A datetime object representing the time at which the share was deleted.
+ This is a service returned value, and the value will be set when list shared including deleted ones."""
+ version: Optional[str] = None
+ """To indicate the version of deleted share.
+ This is a service returned value, and the value will be set when list shared including deleted ones."""
+ remaining_retention_days: Optional[int] = None
+ """The number of days that the share will be retained before being permanently deleted by the service.
+ This is a service returned value, and the value will be set when list shared including deleted ones."""
+ provisioned_egress_mbps: Optional[int] = None
+ """Provisioned egress in megabits/second. Only applicable to premium file accounts."""
+ provisioned_ingress_mbps: Optional[int] = None
+ """Provisioned ingress in megabits/second. Only applicable to premium file accounts."""
+ provisioned_iops: Optional[int] = None
+ """Provisioned input/output operators per second (iops). Only applicable to premium file accounts."""
+ provisioned_bandwidth: Optional[int] = None
+ """Provisioned bandwidth in megabits/second. Only applicable to premium file accounts."""
+ lease: LeaseProperties
+ """Share lease properties."""
+ protocols: Optional[List[str]] = None
+ """Indicates the protocols enabled on the share. The protocol can be either SMB or NFS."""
+ root_squash: Optional[Union["ShareRootSquash", str]] = None
+ """Possible values include: 'NoRootSquash', 'RootSquash', 'AllSquash'."""
+ enable_snapshot_virtual_directory_access: Optional[bool] = None
+ """Specifies whether the snapshot virtual directory should be accessible at the root of the share
+ mount point when NFS is enabled. if not specified, the default is True."""
+ paid_bursting_enabled: Optional[int] = None
+ """This property enables paid bursting."""
+ paid_bursting_bandwidth_mibps: Optional[int] = None
+ """The maximum throughput the file share can support in MiB/s."""
+ paid_bursting_iops: Optional[int] = None
+ """The maximum IOPS the file share can support."""
+ next_provisioned_iops_downgrade: Optional["datetime"]
+ """The share's next allowed provisioned throughput downgrade time."""
+ next_provisioned_bandwidth_downgrade: Optional["datetime"]
+ """The share's next allowed provisioned bandwidth downgrade time."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.name = None # type: ignore [assignment]
+ self.last_modified = kwargs.get('Last-Modified') # type: ignore [assignment]
+ self.etag = kwargs.get('ETag') # type: ignore [assignment]
+ self.quota = kwargs.get('x-ms-share-quota') # type: ignore [assignment]
+ self.access_tier = kwargs.get('x-ms-access-tier') # type: ignore [assignment]
+ self.next_allowed_quota_downgrade_time = kwargs.get('x-ms-share-next-allowed-quota-downgrade-time')
+ self.metadata = kwargs.get('metadata') # type: ignore [assignment]
+ self.snapshot = None
+ self.deleted = None
+ self.deleted_time = None
+ self.version = None
+ self.remaining_retention_days = None
+ self.provisioned_egress_mbps = kwargs.get('x-ms-share-provisioned-egress-mbps')
+ self.provisioned_ingress_mbps = kwargs.get('x-ms-share-provisioned-ingress-mbps')
+ self.provisioned_iops = kwargs.get('x-ms-share-provisioned-iops')
+ self.provisioned_bandwidth = kwargs.get('x-ms-share-provisioned-bandwidth-mibps')
+ self.lease = LeaseProperties(**kwargs)
+ self.protocols = [protocol.strip() for protocol in kwargs.get('x-ms-enabled-protocols', None).split(',')]\
+ if kwargs.get('x-ms-enabled-protocols', None) else None
+ self.root_squash = kwargs.get('x-ms-root-squash', None)
+ self.enable_snapshot_virtual_directory_access = \
+ kwargs.get('x-ms-enable-snapshot-virtual-directory-access')
+ self.paid_bursting_enabled = kwargs.get('x-ms-share-paid-bursting-enabled')
+ self.paid_bursting_bandwidth_mibps = kwargs.get('x-ms-share-paid-bursting-max-bandwidth-mibps')
+ self.paid_bursting_iops = kwargs.get('x-ms-share-paid-bursting-max-iops')
+ self.included_burst_iops = kwargs.get('x-ms-share-included-burst-iops')
+ self.max_burst_credits_for_iops = kwargs.get('x-ms-share-max-burst-credits-for-iops')
+ self.next_provisioned_iops_downgrade = ( # pylint: disable=name-too-long
+ kwargs.get('x-ms-share-next-allowed-provisioned-iops-downgrade-time'))
+ self.next_provisioned_bandwidth_downgrade = ( # pylint: disable=name-too-long
+ kwargs.get('x-ms-share-next-allowed-provisioned-bandwidth-downgrade-time'))
+
+ @classmethod
+ def _from_generated(cls, generated):
+ props = cls()
+ props.name = generated.name
+ props.last_modified = generated.properties.last_modified
+ props.etag = generated.properties.etag
+ props.quota = generated.properties.quota
+ props.access_tier = generated.properties.access_tier
+ props.next_allowed_quota_downgrade_time = generated.properties.next_allowed_quota_downgrade_time
+ props.metadata = generated.metadata
+ props.snapshot = generated.snapshot
+ props.deleted = generated.deleted
+ props.deleted_time = generated.properties.deleted_time
+ props.version = generated.version
+ props.remaining_retention_days = generated.properties.remaining_retention_days
+ props.provisioned_egress_mbps = generated.properties.provisioned_egress_m_bps
+ props.provisioned_ingress_mbps = generated.properties.provisioned_ingress_m_bps
+ props.provisioned_iops = generated.properties.provisioned_iops
+ props.provisioned_bandwidth = generated.properties.provisioned_bandwidth_mi_bps
+ props.lease = LeaseProperties._from_generated(generated) # pylint: disable=protected-access
+ props.protocols = [protocol.strip() for protocol in generated.properties.enabled_protocols.split(',')]\
+ if generated.properties.enabled_protocols else None
+ props.root_squash = generated.properties.root_squash
+ props.enable_snapshot_virtual_directory_access = generated.properties.enable_snapshot_virtual_directory_access
+ props.paid_bursting_enabled = generated.properties.paid_bursting_enabled
+ props.paid_bursting_bandwidth_mibps = generated.properties.paid_bursting_max_bandwidth_mibps
+ props.paid_bursting_iops = generated.properties.paid_bursting_max_iops
+ props.included_burst_iops = generated.properties.included_burst_iops
+ props.max_burst_credits_for_iops = generated.properties.max_burst_credits_for_iops
+ props.next_provisioned_iops_downgrade = ( # pylint: disable=name-too-long
+ generated.properties.next_allowed_provisioned_iops_downgrade_time)
+ props.next_provisioned_bandwidth_downgrade = ( # pylint: disable=name-too-long
+ generated.properties.next_allowed_provisioned_bandwidth_downgrade_time)
+ return props
+
+
+class SharePropertiesPaged(PageIterator):
+ """An iterable of Share properties.
+
+ :param Callable command: Function to retrieve the next page of items.
+ :param Optional[str] prefix: Filters the results to return only shares whose names
+ begin with the specified prefix.
+ :param Optional[int] results_per_page: The maximum number of share names to retrieve per call.
+ :param Optional[str] continuation_token: An opaque continuation token to retrieve the next page of results.
+ """
+
+ service_endpoint: Optional[str] = None
+ """The service URL."""
+ prefix: Optional[str] = None
+ """A filename prefix being used to filter the list."""
+ marker: Optional[str] = None
+ """The continuation token of the current page of results."""
+ results_per_page: Optional[int] = None
+ """The maximum number of results to retrieve per API call."""
+ location_mode: Optional[str] = None
+ """The location mode being used to list results. The available
+ options include "primary" and "secondary"."""
+ current_page: List[ShareProperties]
+ """The current page of listed results."""
+
+ def __init__(
+ self, command: Callable,
+ prefix: Optional[str] = None,
+ results_per_page: Optional[int] = None,
+ continuation_token: Optional[str] = None
+ ) -> None:
+ super(SharePropertiesPaged, self).__init__(
+ get_next=self._get_next_cb,
+ extract_data=self._extract_data_cb,
+ continuation_token=continuation_token or ""
+ )
+ self._command = command
+ self.service_endpoint = None
+ self.prefix = prefix
+ self.marker = None
+ self.results_per_page = results_per_page
+ self.location_mode = None
+ self.current_page = []
+
+ def _get_next_cb(self, continuation_token):
+ try:
+ return self._command(
+ marker=continuation_token or None,
+ maxresults=self.results_per_page,
+ prefix=self.prefix,
+ cls=return_context_and_deserialized,
+ use_location=self.location_mode)
+ except HttpResponseError as error:
+ process_storage_error(error)
+
+ def _extract_data_cb(self, get_next_return):
+ self.location_mode, self._response = get_next_return
+ self.service_endpoint = self._response.service_endpoint
+ self.prefix = self._response.prefix
+ self.marker = self._response.marker
+ self.results_per_page = self._response.max_results
+ self.current_page = [ShareProperties._from_generated(i) for i in self._response.share_items] # pylint: disable=protected-access
+ return self._response.next_marker or None, self.current_page
+
+
+class Handle(DictMixin):
+ """A listed Azure Storage handle item.
+
+ All required parameters must be populated in order to send to Azure.
+
+ :keyword str client_name: Name of the client machine where the share is being mounted.
+ :keyword str handle_id: XSMB service handle ID.
+ :keyword str path: File or directory name including full path starting from share root.
+ :keyword str file_id: FileId uniquely identifies the file or directory.
+ :keyword str parent_id: ParentId uniquely identifies the parent directory of the object.
+ :keyword str session_id: SMB session ID in context of which the file handle was opened.
+ :keyword str client_ip: Client IP that opened the handle.
+ :keyword ~datetime.datetime open_time: Time when the session that previously opened
+ the handle has last been reconnected. (UTC)
+ :keyword Optional[~datetime.datetime] last_reconnect_time: Time handle was last connected to. (UTC)
+ :keyword access_rights: Access rights of the handle.
+ :paramtype access_rights: List[Literal['Read', 'Write', 'Delete']]
+ """
+
+ client_name: str
+ """Name of the client machine where the share is being mounted."""
+ id: str
+ """XSMB service handle ID."""
+ path: str
+ """File or directory name including full path starting from share root."""
+ file_id: str
+ """FileId uniquely identifies the file or directory."""
+ parent_id: str
+ """ParentId uniquely identifies the parent directory of the object."""
+ session_id: str
+ """SMB session ID in context of which the file handle was opened."""
+ client_ip: str
+ """Client IP that opened the handle."""
+ open_time: "datetime"
+ """Time when the session that previously opened the handle was last been reconnected. (UTC)"""
+ last_reconnect_time: Optional["datetime"]
+ """Time handle that was last connected to. (UTC)"""
+ access_rights: List[Literal['Read', 'Write', 'Delete']]
+ """Access rights of the handle."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.client_name = kwargs.get('client_name') # type: ignore [assignment]
+ self.id = kwargs.get('handle_id') # type: ignore [assignment]
+ self.path = kwargs.get('path') # type: ignore [assignment]
+ self.file_id = kwargs.get('file_id') # type: ignore [assignment]
+ self.parent_id = kwargs.get('parent_id') # type: ignore [assignment]
+ self.session_id = kwargs.get('session_id') # type: ignore [assignment]
+ self.client_ip = kwargs.get('client_ip') # type: ignore [assignment]
+ self.open_time = kwargs.get('open_time') # type: ignore [assignment]
+ self.last_reconnect_time = kwargs.get('last_reconnect_time')
+ self.access_rights = kwargs.get('access_right_list') # type: ignore [assignment]
+
+ @classmethod
+ def _from_generated(cls, generated):
+ handle = cls()
+ handle.client_name = generated.client_name
+ handle.id = generated.handle_id
+ handle.path = unquote(generated.path.content) if generated.path.encoded else generated.path.content
+ handle.file_id = generated.file_id
+ handle.parent_id = generated.parent_id
+ handle.session_id = generated.session_id
+ handle.client_ip = generated.client_ip
+ handle.open_time = generated.open_time
+ handle.last_reconnect_time = generated.last_reconnect_time
+ handle.access_rights = generated.access_right_list
+ return handle
+
+
+class HandlesPaged(PageIterator):
+ """An iterable of Handles.
+
+ :param Callable command: Function to retrieve the next page of items.
+ :param Optional[int] results_per_page: The maximum number of share names to retrieve per call.
+ :param Optional[str] continuation_token: An opaque continuation token to retrieve the next page of results.
+ """
+
+ marker: Optional[str] = None
+ """The continuation token of the current page of results."""
+ results_per_page: Optional[int] = None
+ """The maximum number of results retrieved per API call."""
+ location_mode: Optional[str] = None
+ """The location mode being used to list results.
+ The available options include "primary" and "secondary"."""
+ current_page: List[Handle]
+ """The current page of listed results."""
+
+ def __init__(
+ self, command: Callable,
+ results_per_page: Optional[int] = None,
+ continuation_token: Optional[str] = None
+ ) -> None:
+ super(HandlesPaged, self).__init__(
+ get_next=self._get_next_cb,
+ extract_data=self._extract_data_cb,
+ continuation_token=continuation_token or ""
+ )
+ self._command = command
+ self.marker = None
+ self.results_per_page = results_per_page
+ self.location_mode = None
+ self.current_page = []
+
+ def _get_next_cb(self, continuation_token):
+ try:
+ return self._command(
+ marker=continuation_token or None,
+ maxresults=self.results_per_page,
+ cls=return_context_and_deserialized,
+ use_location=self.location_mode)
+ except HttpResponseError as error:
+ process_storage_error(error)
+
+ def _extract_data_cb(self, get_next_return):
+ self.location_mode, self._response = get_next_return
+ self.current_page = [Handle._from_generated(h) for h in self._response.handle_list] # pylint: disable=protected-access
+ return self._response.next_marker or None, self.current_page
+
+
+class NTFSAttributes(object):
+ """Valid set of attributes to set for file or directory.
+
+ To set attribute for directory, 'Directory' should always be enabled except setting 'None' for directory.
+ """
+
+ read_only: bool = False
+ """Enable/disable 'ReadOnly' attribute for DIRECTORY or FILE."""
+ hidden: bool = False
+ """Enable/disable 'Hidden' attribute for DIRECTORY or FILE."""
+ system: bool = False
+ """Enable/disable 'System' attribute for DIRECTORY or FILE."""
+ none: bool = False
+ """Enable/disable 'None' attribute for DIRECTORY or FILE to clear all attributes of FILE/DIRECTORY."""
+ directory: bool = False
+ """Enable/disable 'Directory' attribute for DIRECTORY."""
+ archive: bool = False
+ """Enable/disable 'Archive' attribute for DIRECTORY."""
+ temporary: bool = False
+ """Enable/disable 'Temporary' attribute for DIRECTORY."""
+ offline: bool = False
+ """Enable/disable 'Offline' attribute for DIRECTORY."""
+ not_content_indexed: bool = False
+ """Enable/disable 'NotContentIndexed' attribute for DIRECTORY."""
+ no_scrub_data: bool = False
+ """Enable/disable 'NoScrubData' attribute for DIRECTORY."""
+
+ def __init__(
+ self, read_only: bool = False,
+ hidden: bool = False,
+ system: bool = False,
+ none: bool = False,
+ directory: bool = False,
+ archive: bool = False,
+ temporary: bool = False,
+ offline: bool = False,
+ not_content_indexed: bool = False,
+ no_scrub_data: bool = False
+ ) -> None:
+ self.read_only = read_only
+ self.hidden = hidden
+ self.system = system
+ self.none = none
+ self.directory = directory
+ self.archive = archive
+ self.temporary = temporary
+ self.offline = offline
+ self.not_content_indexed = not_content_indexed
+ self.no_scrub_data = no_scrub_data
+ self._str = (('ReadOnly|' if self.read_only else '') +
+ ('Hidden|' if self.hidden else '') +
+ ('System|' if self.system else '') +
+ ('None|' if self.none else '') +
+ ('Directory|' if self.directory else '') +
+ ('Archive|' if self.archive else '') +
+ ('Temporary|' if self.temporary else '') +
+ ('Offline|' if self.offline else '') +
+ ('NotContentIndexed|' if self.not_content_indexed else '') +
+ ('NoScrubData|' if self.no_scrub_data else ''))
+
+ def __str__(self):
+ concatenated_params = self._str
+ return concatenated_params.strip('|')
+
+ @classmethod
+ def from_string(cls, string: str) -> Self:
+ """Create a NTFSAttributes from a string.
+
+ To specify permissions you can pass in a string with the
+ desired permissions, e.g. "ReadOnly|Hidden|System"
+
+ :param str string: The string which dictates the permissions.
+ :return: A NTFSAttributes object
+ :rtype: ~azure.storage.fileshare.NTFSAttributes
+ """
+ read_only = "ReadOnly" in string
+ hidden = "Hidden" in string
+ system = "System" in string
+ none = "None" in string
+ directory = "Directory" in string
+ archive = "Archive" in string
+ temporary = "Temporary" in string
+ offline = "Offline" in string
+ not_content_indexed = "NotContentIndexed" in string
+ no_scrub_data = "NoScrubData" in string
+
+ parsed = cls(read_only, hidden, system, none, directory, archive, temporary, offline, not_content_indexed,
+ no_scrub_data)
+ parsed._str = string
+ return parsed
+
+
+class DirectoryProperties(DictMixin):
+ """Directory's properties class."""
+
+ name: str
+ """The name of the directory."""
+ last_modified: "datetime"
+ """A datetime object representing the last time the directory was modified."""
+ etag: str
+ """The ETag contains a value that you can use to perform operations conditionally."""
+ server_encrypted: bool
+ """Whether encryption is enabled."""
+ metadata: Dict[str, str]
+ """Name_value pairs to associate with the directory as metadata."""
+ change_time: Optional[Union[str, "datetime"]] = None
+ """Change time for the file."""
+ creation_time: Optional[Union[str, "datetime"]] = None
+ """Creation time for the file."""
+ last_write_time: Optional[Union[str, "datetime"]] = None
+ """Last write time for the file."""
+ last_access_time: Optional["datetime"] = None
+ """Last access time for the file."""
+ file_attributes: Union[str, NTFSAttributes]
+ """The file system attributes for files and directories."""
+ permission_key: str
+ """Key of the permission to be set for the directory/file."""
+ file_id: str
+ """FileId uniquely identifies the file or directory."""
+ parent_id: str
+ """ParentId uniquely identifies the parent directory of the object."""
+ is_directory: bool = True
+ """Whether input is a directory."""
+ owner: Optional[str] = None
+ """NFS only. The owner of the directory."""
+ group: Optional[str] = None
+ """NFS only. The owning group of the directory."""
+ file_mode: Optional[str] = None
+ """NFS only. The file mode of the directory."""
+ nfs_file_type: Optional[Literal['Directory']] = None
+ """NFS only. The type of the directory."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.name = None # type: ignore [assignment]
+ self.last_modified = kwargs.get('Last-Modified') # type: ignore [assignment]
+ self.etag = kwargs.get('ETag') # type: ignore [assignment]
+ self.server_encrypted = kwargs.get('x-ms-server-encrypted') # type: ignore [assignment]
+ self.metadata = kwargs.get('metadata') # type: ignore [assignment]
+ self.change_time = _parse_datetime_from_str(kwargs.get('x-ms-file-change-time'))
+ self.creation_time = _parse_datetime_from_str(kwargs.get('x-ms-file-creation-time'))
+ self.last_write_time = _parse_datetime_from_str(kwargs.get('x-ms-file-last-write-time'))
+ self.last_access_time = None
+ self.file_attributes = kwargs.get('x-ms-file-attributes') # type: ignore [assignment]
+ self.permission_key = kwargs.get('x-ms-file-permission-key') # type: ignore [assignment]
+ self.file_id = kwargs.get('x-ms-file-id') # type: ignore [assignment]
+ self.parent_id = kwargs.get('x-ms-file-parent-id') # type: ignore [assignment]
+ self.is_directory = True
+ self.owner = kwargs.get('x-ms-owner')
+ self.group = kwargs.get('x-ms-group')
+ self.file_mode = kwargs.get('x-ms-mode')
+ self.nfs_file_type = kwargs.get('x-ms-file-file-type')
+
+ @classmethod
+ def _from_generated(cls, generated):
+ props = cls()
+ props.name = unquote(generated.name.content) if generated.name.encoded else generated.name.content
+ props.file_id = generated.file_id
+ props.file_attributes = generated.attributes
+ props.last_modified = generated.properties.last_modified
+ props.creation_time = generated.properties.creation_time
+ props.last_access_time = generated.properties.last_access_time
+ props.last_write_time = generated.properties.last_write_time
+ props.change_time = generated.properties.change_time
+ props.etag = generated.properties.etag
+ props.permission_key = generated.permission_key
+ return props
+
+
+class DirectoryPropertiesPaged(PageIterator):
+ """An iterable for the contents of a directory.
+
+ This iterable will yield dicts for the contents of the directory. The dicts
+ will have the keys 'name' (str) and 'is_directory' (bool).
+ Items that are files (is_directory=False) will have an additional 'content_length' key.
+
+ :param Callable command: Function to retrieve the next page of items.
+ :param Optional[str] prefix: Filters the results to return only directories whose names
+ begin with the specified prefix.
+ :param Optional[int] results_per_page: The maximum number of share names to retrieve per call.
+ :param Optional[str] continuation_token: An opaque continuation token.
+ """
+
+ service_endpoint: Optional[str] = None
+ """The service URL."""
+ prefix: Optional[str] = None
+ """A file name prefix being used to filter the list."""
+ marker: Optional[str] = None
+ """The continuation token of the current page of results."""
+ results_per_page: Optional[int] = None
+ """The maximum number of results retrieved per API call."""
+ continuation_token: Optional[str] = None
+ """The continuation token to retrieve the next page of results."""
+ location_mode: Optional[str] = None
+ """The location mode being used to list results. The available options include "primary" and "secondary"."""
+ current_page: List[Dict[str, Any]]
+ """The current page of listed results."""
+
+ def __init__(
+ self, command: Callable,
+ prefix: Optional[str] = None,
+ results_per_page: Optional[int] = None,
+ continuation_token: Optional[str] = None
+ ) -> None:
+ super(DirectoryPropertiesPaged, self).__init__(
+ get_next=self._get_next_cb,
+ extract_data=self._extract_data_cb,
+ continuation_token=continuation_token or ""
+ )
+ self._command = command
+ self.service_endpoint = None
+ self.prefix = prefix
+ self.marker = None
+ self.results_per_page = results_per_page
+ self.location_mode = None
+ self.current_page = []
+
+ def _get_next_cb(self, continuation_token):
+ try:
+ return self._command(
+ marker=continuation_token or None,
+ prefix=self.prefix,
+ maxresults=self.results_per_page,
+ cls=return_context_and_deserialized,
+ use_location=self.location_mode)
+ except HttpResponseError as error:
+ process_storage_error(error)
+
+ def _extract_data_cb(self, get_next_return):
+ self.location_mode, self._response = get_next_return
+ self.service_endpoint = self._response.service_endpoint
+ self.prefix = self._response.prefix
+ self.marker = self._response.marker
+ self.results_per_page = self._response.max_results
+ self.current_page = [DirectoryProperties._from_generated(i) for i in self._response.segment.directory_items] # pylint: disable = protected-access
+ self.current_page.extend([FileProperties._from_generated(i) for i in self._response.segment.file_items]) # pylint: disable = protected-access
+ return self._response.next_marker or None, self.current_page
+
+
+class CopyProperties(DictMixin):
+ """File Copy Properties.
+
+ These properties will be `None` if this file has never been the destination in a Copy
+ File operation, or if this file has been modified after a concluded Copy File operation.
+ """
+
+ id: str
+ """String identifier for the last attempted Copy File operation where this file
+ was the destination file. This header does not appear if this file has never
+ been the destination in a Copy File operation, or if this file has been
+ modified after a concluded Copy File operation."""
+ source: Optional[str] = None
+ """URL up to 2 KB in length that specifies the source file used in the last attempted
+ Copy File operation where this file was the destination file."""
+ status: Optional[str] = None
+ """State of the copy operation identified by Copy ID, with these values:
+ success:
+ Copy completed successfully.
+ pending:
+ Copy is in progress. Check copy_status_description if intermittent,
+ non-fatal errors impede copy progress but don't cause failure.
+ aborted:
+ Copy was ended by Abort Copy File.
+ failed:
+ Copy failed. See copy_status_description for failure details."""
+ progress: Optional[str] = None
+ """Contains the number of bytes copied and the total bytes in the source in the last
+ attempted Copy File operation where this file was the destination file. Can show
+ between 0 and Content-Length bytes copied."""
+ status_description: Optional[str] = None
+ """Only appears when x-ms-copy-status is failed or pending. Describes cause of fatal
+ or non-fatal copy operation failure."""
+ incremental_copy: Optional[bool] = None
+ """Copies the snapshot of the source file to a destination file.
+ The snapshot is copied such that only the differential changes between
+ the previously copied snapshot are transferred to the destination."""
+ destination_snapshot: Optional["datetime"] = None
+ """Included if the file is incremental copy or incremental copy snapshot,
+ if x-ms-copy-status is success. Snapshot time of the last successful
+ incremental copy snapshot for this file."""
+ datetime: Optional["datetime"] = None
+ """Conclusion time of the last attempted Copy File operation where this file was the
+ destination file. This value can specify the time of a completed, aborted, or
+ failed copy attempt."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.id = kwargs.get('x-ms-copy-id') # type: ignore [assignment]
+ self.source = kwargs.get('x-ms-copy-source')
+ self.status = get_enum_value(kwargs.get('x-ms-copy-status'))
+ self.progress = kwargs.get('x-ms-copy-progress')
+ self.completion_time = kwargs.get('x-ms-copy-completion_time')
+ self.status_description = kwargs.get('x-ms-copy-status-description')
+ self.incremental_copy = kwargs.get('x-ms-incremental-copy')
+ self.destination_snapshot = kwargs.get('x-ms-copy-destination-snapshot')
+
+ @classmethod
+ def _from_generated(cls, generated):
+ copy = cls()
+ copy.id = generated.properties.copy_id or None
+ copy.status = get_enum_value(generated.properties.copy_status) or None
+ copy.source = generated.properties.copy_source or None
+ copy.progress = generated.properties.copy_progress or None
+ copy.completion_time = generated.properties.copy_completion_time or None
+ copy.status_description = generated.properties.copy_status_description or None
+ copy.incremental_copy = generated.properties.incremental_copy or None
+ copy.destination_snapshot = generated.properties.destination_snapshot or None
+ return copy
+
+
+class FileProperties(DictMixin):
+ """File's properties class."""
+
+ name: str
+ """The name of the file."""
+ path: Optional[str] = None
+ """The path of the file."""
+ share: Optional[str] = None
+ """The name of the share."""
+ snapshot: Optional[str] = None
+ """File snapshot."""
+ content_length: int
+ """Size of file in bytes."""
+ metadata: Dict[str, str]
+ """Name-value pairs to associate with the file as metadata."""
+ file_type: str
+ """String indicating the type of file."""
+ last_modified: "datetime"
+ """A datetime object representing the last time the file was modified."""
+ etag: str
+ """The ETag contains a value that can be used to perform operations conditionally."""
+ size: int
+ """Size of the file in bytes."""
+ content_range: Optional[str] = None
+ """Indicates the range of bytes returned in the event that the client
+ requested a subset of the file."""
+ server_encrypted: bool
+ """Whether encryption is enabled."""
+ copy: CopyProperties
+ """The copy properties."""
+ content_settings: ContentSettings
+ """The content settings for the file."""
+ lease: LeaseProperties
+ """File lease properties."""
+ change_time: Optional[Union[str, "datetime"]] = None
+ """Change time for the file."""
+ creation_time: Optional[Union[str, "datetime"]] = None
+ """Creation time for the file."""
+ last_write_time: Optional[Union[str, "datetime"]] = None
+ """Last write time for the file."""
+ last_access_time: Optional["datetime"] = None
+ """Last access time for the file."""
+ file_attributes: Union[str, NTFSAttributes]
+ """The file system attributes for files and directories."""
+ permission_key: str
+ """Key of the permission to be set for the directory/file."""
+ file_id: str
+ """FileId uniquely identifies the file or directory."""
+ parent_id: Optional[str] = None
+ """ParentId uniquely identifies the parent directory of the object."""
+ is_directory: bool = False
+ """Whether input is a directory."""
+ owner: Optional[str] = None
+ """NFS only. The owner of the file."""
+ group: Optional[str] = None
+ """NFS only. The owning group of the file."""
+ file_mode: Optional[str] = None
+ """NFS only. The file mode of the file."""
+ link_count: Optional[int] = None
+ """NFS only. The number of hard links of the file."""
+ nfs_file_type: Optional[Literal['Regular']] = None
+ """NFS only. The type of the file."""
+
+ def __init__(self, **kwargs: Any) -> None:
+ self.name = kwargs.get('name') # type: ignore [assignment]
+ self.path = None
+ self.share = None
+ self.snapshot = None
+ self.content_length = kwargs.get('Content-Length') # type: ignore [assignment]
+ self.metadata = kwargs.get('metadata') # type: ignore [assignment]
+ self.file_type = kwargs.get('x-ms-type') # type: ignore [assignment]
+ self.last_modified = kwargs.get('Last-Modified') # type: ignore [assignment]
+ self.etag = kwargs.get('ETag') # type: ignore [assignment]
+ self.size = kwargs.get('Content-Length') # type: ignore [assignment]
+ self.content_range = kwargs.get('Content-Range')
+ self.server_encrypted = kwargs.get('x-ms-server-encrypted') # type: ignore [assignment]
+ self.copy = CopyProperties(**kwargs)
+ self.content_settings = ContentSettings(**kwargs)
+ self.lease = LeaseProperties(**kwargs)
+ self.change_time = _parse_datetime_from_str(kwargs.get('x-ms-file-change-time'))
+ self.creation_time = _parse_datetime_from_str(kwargs.get('x-ms-file-creation-time'))
+ self.last_write_time = _parse_datetime_from_str(kwargs.get('x-ms-file-last-write-time'))
+ self.last_access_time = None
+ self.file_attributes = kwargs.get('x-ms-file-attributes') # type: ignore [assignment]
+ self.permission_key = kwargs.get('x-ms-file-permission-key') # type: ignore [assignment]
+ self.file_id = kwargs.get('x-ms-file-id') # type: ignore [assignment]
+ self.parent_id = kwargs.get('x-ms-file-parent-id')
+ self.is_directory = False
+ self.owner = kwargs.get('x-ms-owner')
+ self.group = kwargs.get('x-ms-group')
+ self.file_mode = kwargs.get('x-ms-mode')
+ self.link_count = kwargs.get('x-ms-link-count')
+ self.nfs_file_type = kwargs.get('x-ms-file-file-type')
+
+ @classmethod
+ def _from_generated(cls, generated):
+ props = cls()
+ props.name = unquote(generated.name.content) if generated.name.encoded else generated.name.content
+ props.file_id = generated.file_id
+ props.etag = generated.properties.etag
+ props.file_attributes = generated.attributes
+ props.last_modified = generated.properties.last_modified
+ props.creation_time = generated.properties.creation_time
+ props.last_access_time = generated.properties.last_access_time
+ props.last_write_time = generated.properties.last_write_time
+ props.change_time = generated.properties.change_time
+ props.size = generated.properties.content_length
+ props.permission_key = generated.permission_key
+ return props
+
+
+class ShareProtocols(str, Enum, metaclass=CaseInsensitiveEnumMeta):
+ """Enabled protocols on the share"""
+ SMB = "SMB"
+ NFS = "NFS"
+
+
+class FileSasPermissions(object):
+ """FileSasPermissions class to be used with
+ generating shared access signature operations.
+
+ :param bool read:
+ Read the content, properties, metadata. Use the file as the source of a copy operation.
+ :param bool create:
+ Create a new file or copy a file to a new file.
+ :param bool write:
+ Create or write content, properties, metadata. Resize the file. Use the file
+ as the destination of a copy operation within the same account.
+ :param bool delete:
+ Delete the file.
+ """
+
+ read: bool = False
+ """Read the content, properties, metadata. Use the file as the source of a copy operation."""
+ create: bool = False
+ """Create a new file or copy a file to a new file."""
+ write: bool = False
+ """Create or write content, properties, metadata. Resize the file. Use the file
+ as the destination of a copy operation within the same account."""
+ delete: bool = False
+ """Delete the file."""
+
+ def __init__(
+ self, read: bool = False,
+ create: bool = False,
+ write: bool = False,
+ delete: bool = False
+ ) -> None:
+ self.read = read
+ self.create = create
+ self.write = write
+ self.delete = delete
+ self._str = (('r' if self.read else '') +
+ ('c' if self.create else '') +
+ ('w' if self.write else '') +
+ ('d' if self.delete else ''))
+
+ def __str__(self):
+ return self._str
+
+ @classmethod
+ def from_string(cls, permission: str) -> Self:
+ """Create a FileSasPermissions from a string.
+
+ To specify read, create, write, or delete permissions you need only to
+ include the first letter of the word in the string. E.g. For read and
+ create permissions, you would provide a string "rc".
+
+ :param str permission: The string which dictates the read, create,
+ write, or delete permissions
+ :return: A FileSasPermissions object
+ :rtype: ~azure.storage.fileshare.FileSasPermissions
+ """
+ p_read = 'r' in permission
+ p_create = 'c' in permission
+ p_write = 'w' in permission
+ p_delete = 'd' in permission
+
+ parsed = cls(p_read, p_create, p_write, p_delete)
+
+ return parsed
+
+
+def service_properties_deserialize(generated: GeneratedStorageServiceProperties) -> Dict[str, Any]:
+ return {
+ 'hour_metrics': Metrics._from_generated(generated.hour_metrics), # pylint: disable=protected-access
+ 'minute_metrics': Metrics._from_generated(generated.minute_metrics), # pylint: disable=protected-access
+ 'cors': [CorsRule._from_generated(cors) for cors in generated.cors], # type: ignore [union-attr] # pylint: disable=protected-access
+ 'protocol': ShareProtocolSettings._from_generated(generated.protocol), # pylint: disable=protected-access
+ }