1# -------------------------------------------------------------------------
2# Copyright (c) Microsoft Corporation. All rights reserved.
3# Licensed under the MIT License. See License.txt in the project root for
4# license information.
5# --------------------------------------------------------------------------
6# pylint: disable=invalid-overridden-method
7from azure.multiapi.storagev2.blob.v2019_12_12.aio import BlobClient
8from .._shared.base_client_async import AsyncStorageAccountHostsMixin
9from .._path_client import PathClient as PathClientBase
10from .._models import DirectoryProperties
11from .._generated.aio import DataLakeStorageClient
12from ._data_lake_lease_async import DataLakeLeaseClient
13from .._generated.models import StorageErrorException
14from .._deserialize import process_storage_error
15from .._shared.policies_async import ExponentialRetry
16
17_ERROR_UNSUPPORTED_METHOD_FOR_ENCRYPTION = (
18    'The require_encryption flag is set, but encryption is not supported'
19    ' for this method.')
20
21
22class PathClient(AsyncStorageAccountHostsMixin, PathClientBase):
23    def __init__(
24            self, account_url,  # type: str
25            file_system_name,  # type: str
26            path_name,  # type: str
27            credential=None,  # type: Optional[Any]
28            **kwargs  # type: Any
29    ):
30        # type: (...) -> None
31        kwargs['retry_policy'] = kwargs.get('retry_policy') or ExponentialRetry(**kwargs)
32
33        super(PathClient, self).__init__(account_url, file_system_name, path_name, # type: ignore # pylint: disable=specify-parameter-names-in-call
34                                         credential=credential,
35                                         **kwargs)
36
37        kwargs.pop('_hosts', None)
38        self._blob_client = BlobClient(self._blob_account_url, file_system_name, blob_name=path_name,
39                                       credential=credential, _hosts=self._blob_client._hosts, **kwargs)  # type: ignore # pylint: disable=protected-access
40        self._client = DataLakeStorageClient(self.url, file_system_name, path_name, pipeline=self._pipeline)
41        self._loop = kwargs.get('loop', None)
42
43    async def __aexit__(self, *args):
44        await self._blob_client.close()
45        await super(PathClient, self).__aexit__(*args)
46
47    async def close(self):
48        # type: () -> None
49        """ This method is to close the sockets opened by the client.
50        It need not be used when using with a context manager.
51        """
52        await self._blob_client.close()
53        await self.__aexit__()
54
55    async def _create(self, resource_type, content_settings=None, metadata=None, **kwargs):
56        # type: (...) -> Dict[str, Union[str, datetime]]
57        """
58        Create directory or file
59
60        :param resource_type:
61            Required for Create File and Create Directory.
62            The value must be "file" or "directory". Possible values include:
63            'directory', 'file'
64        :type resource_type: str
65        :param ~azure.storage.filedatalake.ContentSettings content_settings:
66            ContentSettings object used to set path properties.
67        :param metadata:
68            Name-value pairs associated with the file/directory as metadata.
69        :type metadata: dict(str, str)
70        :keyword lease:
71            Required if the file/directory has an active lease. Value can be a DataLakeLeaseClient object
72            or the lease ID as a string.
73        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
74        :keyword str umask:
75            Optional and only valid if Hierarchical Namespace is enabled for the account.
76            When creating a file or directory and the parent folder does not have a default ACL,
77            the umask restricts the permissions of the file or directory to be created.
78            The resulting permission is given by p & ^u, where p is the permission and u is the umask.
79            For example, if p is 0777 and u is 0057, then the resulting permission is 0720.
80            The default permission is 0777 for a directory and 0666 for a file. The default umask is 0027.
81            The umask must be specified in 4-digit octal notation (e.g. 0766).
82        :keyword permissions:
83            Optional and only valid if Hierarchical Namespace
84            is enabled for the account. Sets POSIX access permissions for the file
85            owner, the file owning group, and others. Each class may be granted
86            read, write, or execute permission.  The sticky bit is also supported.
87            Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. 0766) are
88            supported.
89        :type permissions: str
90        :keyword ~datetime.datetime if_modified_since:
91            A DateTime value. Azure expects the date value passed in to be UTC.
92            If timezone is included, any non-UTC datetimes will be converted to UTC.
93            If a date is passed in without timezone info, it is assumed to be UTC.
94            Specify this header to perform the operation only
95            if the resource has been modified since the specified time.
96        :keyword ~datetime.datetime if_unmodified_since:
97            A DateTime value. Azure expects the date value passed in to be UTC.
98            If timezone is included, any non-UTC datetimes will be converted to UTC.
99            If a date is passed in without timezone info, it is assumed to be UTC.
100            Specify this header to perform the operation only if
101            the resource has not been modified since the specified date/time.
102        :keyword str etag:
103            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
104            and act according to the condition specified by the `match_condition` parameter.
105        :keyword ~azure.core.MatchConditions match_condition:
106            The match condition to use upon the etag.
107        :keyword int timeout:
108            The timeout parameter is expressed in seconds.
109        :return: Dict[str, Union[str, datetime]]
110        """
111        options = self._create_path_options(
112            resource_type,
113            content_settings=content_settings,
114            metadata=metadata,
115            **kwargs)
116        try:
117            return await self._client.path.create(**options)
118        except StorageErrorException as error:
119            process_storage_error(error)
120
121    async def _delete(self, **kwargs):
122        # type: (bool, **Any) -> None
123        """
124        Marks the specified path for deletion.
125
126        :keyword lease:
127            Required if the file/directory has an active lease. Value can be a LeaseClient object
128            or the lease ID as a string.
129        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
130        :keyword ~datetime.datetime if_modified_since:
131            A DateTime value. Azure expects the date value passed in to be UTC.
132            If timezone is included, any non-UTC datetimes will be converted to UTC.
133            If a date is passed in without timezone info, it is assumed to be UTC.
134            Specify this header to perform the operation only
135            if the resource has been modified since the specified time.
136        :keyword ~datetime.datetime if_unmodified_since:
137            A DateTime value. Azure expects the date value passed in to be UTC.
138            If timezone is included, any non-UTC datetimes will be converted to UTC.
139            If a date is passed in without timezone info, it is assumed to be UTC.
140            Specify this header to perform the operation only if
141            the resource has not been modified since the specified date/time.
142        :keyword str etag:
143            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
144            and act according to the condition specified by the `match_condition` parameter.
145        :keyword ~azure.core.MatchConditions match_condition:
146            The match condition to use upon the etag.
147        :keyword int timeout:
148            The timeout parameter is expressed in seconds.
149        :return: None
150        """
151        options = self._delete_path_options(**kwargs)
152        try:
153            return await self._client.path.delete(**options)
154        except StorageErrorException as error:
155            process_storage_error(error)
156
157    async def set_access_control(self, owner=None,  # type: Optional[str]
158                                 group=None,  # type: Optional[str]
159                                 permissions=None,  # type: Optional[str]
160                                 acl=None,  # type: Optional[str]
161                                 **kwargs):
162        # type: (...) -> Dict[str, Union[str, datetime]]
163        """
164        Set the owner, group, permissions, or access control list for a path.
165
166        :param owner:
167            Optional. The owner of the file or directory.
168        :type owner: str
169        :param group:
170            Optional. The owning group of the file or directory.
171        :type group: str
172        :param permissions:
173            Optional and only valid if Hierarchical Namespace
174            is enabled for the account. Sets POSIX access permissions for the file
175            owner, the file owning group, and others. Each class may be granted
176            read, write, or execute permission.  The sticky bit is also supported.
177            Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. 0766) are
178            supported.
179            permissions and acl are mutually exclusive.
180        :type permissions: str
181        :param acl:
182            Sets POSIX access control rights on files and directories.
183            The value is a comma-separated list of access control entries. Each
184            access control entry (ACE) consists of a scope, a type, a user or
185            group identifier, and permissions in the format
186            "[scope:][type]:[id]:[permissions]".
187            permissions and acl are mutually exclusive.
188        :type acl: str
189        :keyword lease:
190            Required if the file/directory has an active lease. Value can be a LeaseClient object
191            or the lease ID as a string.
192        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
193        :keyword ~datetime.datetime if_modified_since:
194            A DateTime value. Azure expects the date value passed in to be UTC.
195            If timezone is included, any non-UTC datetimes will be converted to UTC.
196            If a date is passed in without timezone info, it is assumed to be UTC.
197            Specify this header to perform the operation only
198            if the resource has been modified since the specified time.
199        :keyword ~datetime.datetime if_unmodified_since:
200            A DateTime value. Azure expects the date value passed in to be UTC.
201            If timezone is included, any non-UTC datetimes will be converted to UTC.
202            If a date is passed in without timezone info, it is assumed to be UTC.
203            Specify this header to perform the operation only if
204            the resource has not been modified since the specified date/time.
205        :keyword str etag:
206            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
207            and act according to the condition specified by the `match_condition` parameter.
208        :keyword ~azure.core.MatchConditions match_condition:
209            The match condition to use upon the etag.
210        :keyword int timeout:
211            The timeout parameter is expressed in seconds.
212        :keyword: response dict (Etag and last modified).
213        """
214        options = self._set_access_control_options(owner=owner, group=group, permissions=permissions, acl=acl, **kwargs)
215        try:
216            return await self._client.path.set_access_control(**options)
217        except StorageErrorException as error:
218            process_storage_error(error)
219
220    async def get_access_control(self, upn=None,  # type: Optional[bool]
221                                 **kwargs):
222        # type: (...) -> Dict[str, Any]
223        """
224        Get the owner, group, permissions, or access control list for a path.
225
226        :param upn:
227            Optional. Valid only when Hierarchical Namespace is
228            enabled for the account. If "true", the user identity values returned
229            in the x-ms-owner, x-ms-group, and x-ms-acl response headers will be
230            transformed from Azure Active Directory Object IDs to User Principal
231            Names.  If "false", the values will be returned as Azure Active
232            Directory Object IDs. The default value is false. Note that group and
233            application Object IDs are not translated because they do not have
234            unique friendly names.
235        :type upn: bool
236        :keyword lease:
237            Required if the file/directory has an active lease. Value can be a LeaseClient object
238            or the lease ID as a string.
239        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
240        :keyword ~datetime.datetime if_modified_since:
241            A DateTime value. Azure expects the date value passed in to be UTC.
242            If timezone is included, any non-UTC datetimes will be converted to UTC.
243            If a date is passed in without timezone info, it is assumed to be UTC.
244            Specify this header to perform the operation only
245            if the resource has been modified since the specified time.
246        :keyword ~datetime.datetime if_unmodified_since:
247            A DateTime value. Azure expects the date value passed in to be UTC.
248            If timezone is included, any non-UTC datetimes will be converted to UTC.
249            If a date is passed in without timezone info, it is assumed to be UTC.
250            Specify this header to perform the operation only if
251            the resource has not been modified since the specified date/time.
252        :keyword str etag:
253            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
254            and act according to the condition specified by the `match_condition` parameter.
255        :keyword ~azure.core.MatchConditions match_condition:
256            The match condition to use upon the etag.
257        :keyword int timeout:
258            The timeout parameter is expressed in seconds.
259        :keyword: response dict.
260        """
261        options = self._get_access_control_options(upn=upn, **kwargs)
262        try:
263            return await self._client.path.get_properties(**options)
264        except StorageErrorException as error:
265            process_storage_error(error)
266
267    async def _rename_path(self, rename_source,
268                           **kwargs):
269        # type: (**Any) -> Dict[str, Any]
270        """
271        Rename directory or file
272
273        :param rename_source: The value must have the following format: "/{filesystem}/{path}".
274        :type rename_source: str
275        :keyword ~azure.storage.filedatalake.ContentSettings content_settings:
276            ContentSettings object used to set path properties.
277        :keyword source_lease: A lease ID for the source path. If specified,
278            the source path must have an active lease and the leaase ID must
279            match.
280        :paramtype source_lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
281        :keyword lease:
282            Required if the file/directory has an active lease. Value can be a LeaseClient object
283            or the lease ID as a string.
284        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
285        :keyword ~datetime.datetime if_modified_since:
286            A DateTime value. Azure expects the date value passed in to be UTC.
287            If timezone is included, any non-UTC datetimes will be converted to UTC.
288            If a date is passed in without timezone info, it is assumed to be UTC.
289            Specify this header to perform the operation only
290            if the resource has been modified since the specified time.
291        :keyword ~datetime.datetime if_unmodified_since:
292            A DateTime value. Azure expects the date value passed in to be UTC.
293            If timezone is included, any non-UTC datetimes will be converted to UTC.
294            If a date is passed in without timezone info, it is assumed to be UTC.
295            Specify this header to perform the operation only if
296            the resource has not been modified since the specified date/time.
297        :keyword str etag:
298            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
299            and act according to the condition specified by the `match_condition` parameter.
300        :keyword ~azure.core.MatchConditions match_condition:
301            The match condition to use upon the etag.
302        :keyword ~datetime.datetime source_if_modified_since:
303            A DateTime value. Azure expects the date value passed in to be UTC.
304            If timezone is included, any non-UTC datetimes will be converted to UTC.
305            If a date is passed in without timezone info, it is assumed to be UTC.
306            Specify this header to perform the operation only
307            if the resource has been modified since the specified time.
308        :keyword ~datetime.datetime source_if_unmodified_since:
309            A DateTime value. Azure expects the date value passed in to be UTC.
310            If timezone is included, any non-UTC datetimes will be converted to UTC.
311            If a date is passed in without timezone info, it is assumed to be UTC.
312            Specify this header to perform the operation only if
313            the resource has not been modified since the specified date/time.
314        :keyword str source_etag:
315            The source ETag value, or the wildcard character (*). Used to check if the resource has changed,
316            and act according to the condition specified by the `match_condition` parameter.
317        :keyword ~azure.core.MatchConditions source_match_condition:
318            The source match condition to use upon the etag.
319        :keyword int timeout:
320            The timeout parameter is expressed in seconds.
321        """
322        options = self._rename_path_options(
323            rename_source,
324            **kwargs)
325        try:
326            return await self._client.path.create(**options)
327        except StorageErrorException as error:
328            process_storage_error(error)
329
330    async def _get_path_properties(self, **kwargs):
331        # type: (**Any) -> Union[FileProperties, DirectoryProperties]
332        """Returns all user-defined metadata, standard HTTP properties, and
333        system properties for the file or directory. It does not return the content of the directory or file.
334
335        :keyword lease:
336            Required if the directory or file has an active lease. Value can be a DataLakeLeaseClient object
337            or the lease ID as a string.
338        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
339        :keyword ~datetime.datetime if_modified_since:
340            A DateTime value. Azure expects the date value passed in to be UTC.
341            If timezone is included, any non-UTC datetimes will be converted to UTC.
342            If a date is passed in without timezone info, it is assumed to be UTC.
343            Specify this header to perform the operation only
344            if the resource has been modified since the specified time.
345        :keyword ~datetime.datetime if_unmodified_since:
346            A DateTime value. Azure expects the date value passed in to be UTC.
347            If timezone is included, any non-UTC datetimes will be converted to UTC.
348            If a date is passed in without timezone info, it is assumed to be UTC.
349            Specify this header to perform the operation only if
350            the resource has not been modified since the specified date/time.
351        :keyword str etag:
352            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
353            and act according to the condition specified by the `match_condition` parameter.
354        :keyword ~azure.core.MatchConditions match_condition:
355            The match condition to use upon the etag.
356        :keyword int timeout:
357            The timeout parameter is expressed in seconds.
358        :rtype: DirectoryProperties or FileProperties
359        """
360        path_properties = await self._blob_client.get_blob_properties(**kwargs)
361        path_properties.__class__ = DirectoryProperties
362        return path_properties
363
364    async def set_metadata(self, metadata,  # type: Dict[str, str]
365                           **kwargs):
366        # type: (...) -> Dict[str, Union[str, datetime]]
367        """Sets one or more user-defined name-value pairs for the specified
368        file system. Each call to this operation replaces all existing metadata
369        attached to the file system. To remove all metadata from the file system,
370        call this operation with no metadata dict.
371
372        :param metadata:
373            A dict containing name-value pairs to associate with the file system as
374            metadata. Example: {'category':'test'}
375        :type metadata: dict[str, str]
376        :keyword lease:
377            If specified, set_file_system_metadata only succeeds if the
378            file system's lease is active and matches this ID.
379        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
380        :keyword ~datetime.datetime if_modified_since:
381            A DateTime value. Azure expects the date value passed in to be UTC.
382            If timezone is included, any non-UTC datetimes will be converted to UTC.
383            If a date is passed in without timezone info, it is assumed to be UTC.
384            Specify this header to perform the operation only
385            if the resource has been modified since the specified time.
386        :keyword ~datetime.datetime if_unmodified_since:
387            A DateTime value. Azure expects the date value passed in to be UTC.
388            If timezone is included, any non-UTC datetimes will be converted to UTC.
389            If a date is passed in without timezone info, it is assumed to be UTC.
390            Specify this header to perform the operation only if
391            the resource has not been modified since the specified date/time.
392        :keyword str etag:
393            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
394            and act according to the condition specified by the `match_condition` parameter.
395        :keyword ~azure.core.MatchConditions match_condition:
396            The match condition to use upon the etag.
397        :keyword int timeout:
398            The timeout parameter is expressed in seconds.
399        :returns: file system-updated property dict (Etag and last modified).
400        """
401        return await self._blob_client.set_blob_metadata(metadata=metadata, **kwargs)
402
403    async def set_http_headers(self, content_settings=None,  # type: Optional[ContentSettings]
404                               **kwargs):
405        # type: (...) -> Dict[str, Any]
406        """Sets system properties on the file or directory.
407
408        If one property is set for the content_settings, all properties will be overriden.
409
410        :param ~azure.storage.filedatalake.ContentSettings content_settings:
411            ContentSettings object used to set file/directory properties.
412        :keyword lease:
413            If specified, set_file_system_metadata only succeeds if the
414            file system's lease is active and matches this ID.
415        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
416        :keyword ~datetime.datetime if_modified_since:
417            A DateTime value. Azure expects the date value passed in to be UTC.
418            If timezone is included, any non-UTC datetimes will be converted to UTC.
419            If a date is passed in without timezone info, it is assumed to be UTC.
420            Specify this header to perform the operation only
421            if the resource has been modified since the specified time.
422        :keyword ~datetime.datetime if_unmodified_since:
423            A DateTime value. Azure expects the date value passed in to be UTC.
424            If timezone is included, any non-UTC datetimes will be converted to UTC.
425            If a date is passed in without timezone info, it is assumed to be UTC.
426            Specify this header to perform the operation only if
427            the resource has not been modified since the specified date/time.
428        :keyword str etag:
429            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
430            and act according to the condition specified by the `match_condition` parameter.
431        :keyword ~azure.core.MatchConditions match_condition:
432            The match condition to use upon the etag.
433        :keyword int timeout:
434            The timeout parameter is expressed in seconds.
435        :returns: file/directory-updated property dict (Etag and last modified)
436        :rtype: Dict[str, Any]
437        """
438        return await self._blob_client.set_http_headers(content_settings=content_settings, **kwargs)
439
440    async def acquire_lease(self, lease_duration=-1,  # type: Optional[int]
441                            lease_id=None,  # type: Optional[str]
442                            **kwargs):
443        # type: (...) -> DataLakeLeaseClient
444        """
445        Requests a new lease. If the file or directory does not have an active lease,
446        the DataLake service creates a lease on the file/directory and returns a new
447        lease ID.
448
449        :param int lease_duration:
450            Specifies the duration of the lease, in seconds, or negative one
451            (-1) for a lease that never expires. A non-infinite lease can be
452            between 15 and 60 seconds. A lease duration cannot be changed
453            using renew or change. Default is -1 (infinite lease).
454        :param str lease_id:
455            Proposed lease ID, in a GUID string format. The DataLake service returns
456            400 (Invalid request) if the proposed lease ID is not in the correct format.
457        :keyword ~datetime.datetime if_modified_since:
458            A DateTime value. Azure expects the date value passed in to be UTC.
459            If timezone is included, any non-UTC datetimes will be converted to UTC.
460            If a date is passed in without timezone info, it is assumed to be UTC.
461            Specify this header to perform the operation only
462            if the resource has been modified since the specified time.
463        :keyword ~datetime.datetime if_unmodified_since:
464            A DateTime value. Azure expects the date value passed in to be UTC.
465            If timezone is included, any non-UTC datetimes will be converted to UTC.
466            If a date is passed in without timezone info, it is assumed to be UTC.
467            Specify this header to perform the operation only if
468            the resource has not been modified since the specified date/time.
469        :keyword str etag:
470            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
471            and act according to the condition specified by the `match_condition` parameter.
472        :keyword ~azure.core.MatchConditions match_condition:
473            The match condition to use upon the etag.
474        :keyword int timeout:
475            The timeout parameter is expressed in seconds.
476        :returns: A DataLakeLeaseClient object, that can be run in a context manager.
477        :rtype: ~azure.storage.filedatalake.aio.DataLakeLeaseClient
478
479        .. admonition:: Example:
480
481            .. literalinclude:: ../samples/test_file_system_samples.py
482                :start-after: [START acquire_lease_on_file_system]
483                :end-before: [END acquire_lease_on_file_system]
484                :language: python
485                :dedent: 8
486                :caption: Acquiring a lease on the file_system.
487        """
488        lease = DataLakeLeaseClient(self, lease_id=lease_id)  # type: ignore
489        await lease.acquire(lease_duration=lease_duration, **kwargs)
490        return lease
491