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
7
8from ._data_lake_file_client_async import DataLakeFileClient
9from .._data_lake_directory_client import DataLakeDirectoryClient as DataLakeDirectoryClientBase
10from .._models import DirectoryProperties
11from ._path_client_async import PathClient
12
13
14class DataLakeDirectoryClient(PathClient, DataLakeDirectoryClientBase):
15    """A client to interact with the DataLake directory, even if the directory may not yet exist.
16
17    For operations relating to a specific subdirectory or file under the directory, a directory client or file client
18    can be retrieved using the :func:`~get_sub_directory_client` or :func:`~get_file_client` functions.
19
20    :ivar str url:
21        The full endpoint URL to the file system, including SAS token if used.
22    :ivar str primary_endpoint:
23        The full primary endpoint URL.
24    :ivar str primary_hostname:
25        The hostname of the primary endpoint.
26    :param str account_url:
27        The URI to the storage account.
28    :param file_system_name:
29        The file system for the directory or files.
30    :type file_system_name: str
31    :param directory_name:
32        The whole path of the directory. eg. {directory under file system}/{directory to interact with}
33    :type directory_name: str
34    :param credential:
35        The credentials with which to authenticate. This is optional if the
36        account URL already has a SAS token. The value can be a SAS token string, and account
37        shared access key, or an instance of a TokenCredentials class from azure.identity.
38        If the URL already has a SAS token, specifying an explicit credential will take priority.
39
40    .. admonition:: Example:
41
42        .. literalinclude:: ../samples/datalake_samples_instantiate_client_async.py
43            :start-after: [START instantiate_directory_client_from_conn_str]
44            :end-before: [END instantiate_directory_client_from_conn_str]
45            :language: python
46            :dedent: 4
47            :caption: Creating the DataLakeServiceClient from connection string.
48    """
49
50    def __init__(
51            self, account_url,  # type: str
52            file_system_name,  # type: str
53            directory_name,  # type: str
54            credential=None,  # type: Optional[Any]
55            **kwargs  # type: Any
56    ):
57        # type: (...) -> None
58        super(DataLakeDirectoryClient, self).__init__(account_url, file_system_name, directory_name, # pylint: disable=specify-parameter-names-in-call
59                                                      credential=credential, **kwargs)
60
61    async def create_directory(self, metadata=None,  # type: Optional[Dict[str, str]]
62                               **kwargs):
63        # type: (...) -> Dict[str, Union[str, datetime]]
64        """
65        Create a new directory.
66
67        :param metadata:
68            Name-value pairs associated with the directory as metadata.
69        :type metadata: dict(str, str)
70        :keyword ~azure.storage.filedatalake.ContentSettings content_settings:
71            ContentSettings object used to set path properties.
72        :keyword lease:
73            Required if the directory has an active lease. Value can be a DataLakeLeaseClient object
74            or the lease ID as a string.
75        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
76        :keyword str umask:
77            Optional and only valid if Hierarchical Namespace is enabled for the account.
78            When creating a file or directory and the parent folder does not have a default ACL,
79            the umask restricts the permissions of the file or directory to be created.
80            The resulting permission is given by p & ^u, where p is the permission and u is the umask.
81            For example, if p is 0777 and u is 0057, then the resulting permission is 0720.
82            The default permission is 0777 for a directory and 0666 for a file. The default umask is 0027.
83            The umask must be specified in 4-digit octal notation (e.g. 0766).
84        :keyword str permissions:
85            Optional and only valid if Hierarchical Namespace
86            is enabled for the account. Sets POSIX access permissions for the file
87            owner, the file owning group, and others. Each class may be granted
88            read, write, or execute permission.  The sticky bit is also supported.
89            Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. 0766) are
90            supported.
91        :keyword ~datetime.datetime if_modified_since:
92            A DateTime value. Azure expects the date value passed in to be UTC.
93            If timezone is included, any non-UTC datetimes will be converted to UTC.
94            If a date is passed in without timezone info, it is assumed to be UTC.
95            Specify this header to perform the operation only
96            if the resource has been modified since the specified time.
97        :keyword ~datetime.datetime if_unmodified_since:
98            A DateTime value. Azure expects the date value passed in to be UTC.
99            If timezone is included, any non-UTC datetimes will be converted to UTC.
100            If a date is passed in without timezone info, it is assumed to be UTC.
101            Specify this header to perform the operation only if
102            the resource has not been modified since the specified date/time.
103        :keyword str etag:
104            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
105            and act according to the condition specified by the `match_condition` parameter.
106        :keyword ~azure.core.MatchConditions match_condition:
107            The match condition to use upon the etag.
108        :keyword int timeout:
109            The timeout parameter is expressed in seconds.
110        :return: response dict (Etag and last modified).
111
112        .. admonition:: Example:
113
114            .. literalinclude:: ../samples/datalake_samples_directory_async.py
115                :start-after: [START create_directory]
116                :end-before: [END create_directory]
117                :language: python
118                :dedent: 8
119                :caption: Create directory.
120        """
121        return await self._create('directory', metadata=metadata, **kwargs)
122
123    async def delete_directory(self, **kwargs):
124        # type: (...) -> None
125        """
126        Marks the specified directory for deletion.
127
128        :keyword lease:
129            Required if the directory has an active lease. Value can be a LeaseClient object
130            or the lease ID as a string.
131        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
132        :keyword ~datetime.datetime if_modified_since:
133            A DateTime value. Azure expects the date value passed in to be UTC.
134            If timezone is included, any non-UTC datetimes will be converted to UTC.
135            If a date is passed in without timezone info, it is assumed to be UTC.
136            Specify this header to perform the operation only
137            if the resource has been modified since the specified time.
138        :keyword ~datetime.datetime if_unmodified_since:
139            A DateTime value. Azure expects the date value passed in to be UTC.
140            If timezone is included, any non-UTC datetimes will be converted to UTC.
141            If a date is passed in without timezone info, it is assumed to be UTC.
142            Specify this header to perform the operation only if
143            the resource has not been modified since the specified date/time.
144        :keyword str etag:
145            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
146            and act according to the condition specified by the `match_condition` parameter.
147        :keyword ~azure.core.MatchConditions match_condition:
148            The match condition to use upon the etag.
149        :keyword int timeout:
150            The timeout parameter is expressed in seconds.
151        :return: None
152
153        .. admonition:: Example:
154
155            .. literalinclude:: ../samples/datalake_samples_directory_async.py
156                :start-after: [START delete_directory]
157                :end-before: [END delete_directory]
158                :language: python
159                :dedent: 4
160                :caption: Delete directory.
161        """
162        return await self._delete(**kwargs)
163
164    async def get_directory_properties(self, **kwargs):
165        # type: (**Any) -> DirectoryProperties
166        """Returns all user-defined metadata, standard HTTP properties, and
167        system properties for the directory. It does not return the content of the directory.
168
169        :keyword lease:
170            Required if the directory or file has an active lease. Value can be a DataLakeLeaseClient object
171            or the lease ID as a string.
172        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
173        :keyword ~datetime.datetime if_modified_since:
174            A DateTime value. Azure expects the date value passed in to be UTC.
175            If timezone is included, any non-UTC datetimes will be converted to UTC.
176            If a date is passed in without timezone info, it is assumed to be UTC.
177            Specify this header to perform the operation only
178            if the resource has been modified since the specified time.
179        :keyword ~datetime.datetime if_unmodified_since:
180            A DateTime value. Azure expects the date value passed in to be UTC.
181            If timezone is included, any non-UTC datetimes will be converted to UTC.
182            If a date is passed in without timezone info, it is assumed to be UTC.
183            Specify this header to perform the operation only if
184            the resource has not been modified since the specified date/time.
185        :keyword str etag:
186            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
187            and act according to the condition specified by the `match_condition` parameter.
188        :keyword ~azure.core.MatchConditions match_condition:
189            The match condition to use upon the etag.
190        :keyword int timeout:
191            The timeout parameter is expressed in seconds.
192        :rtype: DirectoryProperties
193
194        .. admonition:: Example:
195
196            .. literalinclude:: ../samples/datalake_samples_directory_async.py
197                :start-after: [START get_directory_properties]
198                :end-before: [END get_directory_properties]
199                :language: python
200                :dedent: 4
201                :caption: Getting the properties for a file/directory.
202        """
203        blob_properties = await self._get_path_properties(**kwargs)
204        return DirectoryProperties._from_blob_properties(blob_properties)  # pylint: disable=protected-access
205
206    async def rename_directory(self, new_name,  # type: str
207                               **kwargs):
208        # type: (**Any) -> DataLakeDirectoryClient
209        """
210        Rename the source directory.
211
212        :param str new_name:
213            the new directory name the user want to rename to.
214            The value must have the following format: "{filesystem}/{directory}/{subdirectory}".
215        :keyword source_lease:
216            A lease ID for the source path. If specified,
217            the source path must have an active lease and the leaase ID must
218            match.
219        :paramtype source_lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
220        :keyword lease:
221            Required if the file/directory has an active lease. Value can be a LeaseClient object
222            or the lease ID as a string.
223        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
224        :keyword ~datetime.datetime if_modified_since:
225            A DateTime value. Azure expects the date value passed in to be UTC.
226            If timezone is included, any non-UTC datetimes will be converted to UTC.
227            If a date is passed in without timezone info, it is assumed to be UTC.
228            Specify this header to perform the operation only
229            if the resource has been modified since the specified time.
230        :keyword ~datetime.datetime if_unmodified_since:
231            A DateTime value. Azure expects the date value passed in to be UTC.
232            If timezone is included, any non-UTC datetimes will be converted to UTC.
233            If a date is passed in without timezone info, it is assumed to be UTC.
234            Specify this header to perform the operation only if
235            the resource has not been modified since the specified date/time.
236        :keyword str etag:
237            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
238            and act according to the condition specified by the `match_condition` parameter.
239        :keyword ~azure.core.MatchConditions match_condition:
240            The match condition to use upon the etag.
241        :keyword ~datetime.datetime source_if_modified_since:
242            A DateTime value. Azure expects the date value passed in to be UTC.
243            If timezone is included, any non-UTC datetimes will be converted to UTC.
244            If a date is passed in without timezone info, it is assumed to be UTC.
245            Specify this header to perform the operation only
246            if the resource has been modified since the specified time.
247        :keyword ~datetime.datetime source_if_unmodified_since:
248            A DateTime value. Azure expects the date value passed in to be UTC.
249            If timezone is included, any non-UTC datetimes will be converted to UTC.
250            If a date is passed in without timezone info, it is assumed to be UTC.
251            Specify this header to perform the operation only if
252            the resource has not been modified since the specified date/time.
253        :keyword str source_etag:
254            The source ETag value, or the wildcard character (*). Used to check if the resource has changed,
255            and act according to the condition specified by the `match_condition` parameter.
256        :keyword ~azure.core.MatchConditions source_match_condition:
257            The source match condition to use upon the etag.
258        :keyword int timeout:
259            The timeout parameter is expressed in seconds.
260        :return: DataLakeDirectoryClient
261
262        .. admonition:: Example:
263
264            .. literalinclude:: ../samples/datalake_samples_directory_async.py
265                :start-after: [START rename_directory]
266                :end-before: [END rename_directory]
267                :language: python
268                :dedent: 4
269                :caption: Rename the source directory.
270        """
271        new_name = new_name.strip('/')
272        new_file_system = new_name.split('/')[0]
273        path = new_name[len(new_file_system):]
274
275        new_directory_client = DataLakeDirectoryClient(
276            self.url, new_file_system, directory_name=path, credential=self._raw_credential,
277            _hosts=self._hosts, _configuration=self._config, _pipeline=self._pipeline,
278            _location_mode=self._location_mode, require_encryption=self.require_encryption,
279            key_encryption_key=self.key_encryption_key,
280            key_resolver_function=self.key_resolver_function)
281        await new_directory_client._rename_path('/' + self.file_system_name + '/' + self.path_name,  # pylint: disable=protected-access
282                                                **kwargs)
283        return new_directory_client
284
285    async def create_sub_directory(self, sub_directory,  # type: Union[DirectoryProperties, str]
286                                   metadata=None,  # type: Optional[Dict[str, str]]
287                                   **kwargs):
288        # type: (...) -> DataLakeDirectoryClient
289        """
290        Create a subdirectory and return the subdirectory client to be interacted with.
291
292        :param sub_directory:
293            The directory with which to interact. This can either be the name of the directory,
294            or an instance of DirectoryProperties.
295        :type sub_directory: str or ~azure.storage.filedatalake.DirectoryProperties
296        :param metadata:
297            Name-value pairs associated with the file as metadata.
298        :type metadata: dict(str, str)
299        :keyword ~azure.storage.filedatalake.ContentSettings content_settings:
300            ContentSettings object used to set path properties.
301        :keyword lease:
302            Required if the file has an active lease. Value can be a DataLakeLeaseClient object
303            or the lease ID as a string.
304        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
305        :keyword str umask:
306            Optional and only valid if Hierarchical Namespace is enabled for the account.
307            When creating a file or directory and the parent folder does not have a default ACL,
308            the umask restricts the permissions of the file or directory to be created.
309            The resulting permission is given by p & ^u, where p is the permission and u is the umask.
310            For example, if p is 0777 and u is 0057, then the resulting permission is 0720.
311            The default permission is 0777 for a directory and 0666 for a file. The default umask is 0027.
312            The umask must be specified in 4-digit octal notation (e.g. 0766).
313        :keyword str permissions:
314            Optional and only valid if Hierarchical Namespace
315            is enabled for the account. Sets POSIX access permissions for the file
316            owner, the file owning group, and others. Each class may be granted
317            read, write, or execute permission.  The sticky bit is also supported.
318            Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. 0766) are
319            supported.
320        :keyword ~datetime.datetime if_modified_since:
321            A DateTime value. Azure expects the date value passed in to be UTC.
322            If timezone is included, any non-UTC datetimes will be converted to UTC.
323            If a date is passed in without timezone info, it is assumed to be UTC.
324            Specify this header to perform the operation only
325            if the resource has been modified since the specified time.
326        :keyword ~datetime.datetime if_unmodified_since:
327            A DateTime value. Azure expects the date value passed in to be UTC.
328            If timezone is included, any non-UTC datetimes will be converted to UTC.
329            If a date is passed in without timezone info, it is assumed to be UTC.
330            Specify this header to perform the operation only if
331            the resource has not been modified since the specified date/time.
332        :keyword str etag:
333            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
334            and act according to the condition specified by the `match_condition` parameter.
335        :keyword ~azure.core.MatchConditions match_condition:
336            The match condition to use upon the etag.
337        :keyword int timeout:
338            The timeout parameter is expressed in seconds.
339        :return: DataLakeDirectoryClient for the subdirectory.
340        """
341        subdir = self.get_sub_directory_client(sub_directory)
342        await subdir.create_directory(metadata=metadata, **kwargs)
343        return subdir
344
345    async def delete_sub_directory(self, sub_directory,  # type: Union[DirectoryProperties, str]
346                                   **kwargs):
347        # type: (...) -> DataLakeDirectoryClient
348        """
349        Marks the specified subdirectory for deletion.
350
351        :param sub_directory:
352            The directory with which to interact. This can either be the name of the directory,
353            or an instance of DirectoryProperties.
354        :type sub_directory: str or ~azure.storage.filedatalake.DirectoryProperties
355        :keyword lease:
356            Required if the directory has an active lease. Value can be a LeaseClient object
357            or the lease ID as a string.
358        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
359        :keyword ~datetime.datetime if_modified_since:
360            A DateTime value. Azure expects the date value passed in to be UTC.
361            If timezone is included, any non-UTC datetimes will be converted to UTC.
362            If a date is passed in without timezone info, it is assumed to be UTC.
363            Specify this header to perform the operation only
364            if the resource has been modified since the specified time.
365        :keyword ~datetime.datetime if_unmodified_since:
366            A DateTime value. Azure expects the date value passed in to be UTC.
367            If timezone is included, any non-UTC datetimes will be converted to UTC.
368            If a date is passed in without timezone info, it is assumed to be UTC.
369            Specify this header to perform the operation only if
370            the resource has not been modified since the specified date/time.
371        :keyword str etag:
372            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
373            and act according to the condition specified by the `match_condition` parameter.
374        :keyword ~azure.core.MatchConditions match_condition:
375            The match condition to use upon the etag.
376        :keyword int timeout:
377            The timeout parameter is expressed in seconds.
378        :return: DataLakeDirectoryClient for the subdirectory
379        """
380        subdir = self.get_sub_directory_client(sub_directory)
381        await subdir.delete_directory(**kwargs)
382        return subdir
383
384    async def create_file(self, file,  # type: Union[FileProperties, str]
385                          **kwargs):
386        # type: (...) -> DataLakeFileClient
387        """
388        Create a new file and return the file client to be interacted with.
389
390        :param file:
391            The file with which to interact. This can either be the name of the file,
392            or an instance of FileProperties.
393        :type file: str or ~azure.storage.filedatalake.FileProperties
394        :keyword ~azure.storage.filedatalake.ContentSettings content_settings:
395            ContentSettings object used to set path properties.
396        :keyword metadata:
397            Name-value pairs associated with the file as metadata.
398        :type metadata: dict(str, str)
399        :keyword lease:
400            Required if the file has an active lease. Value can be a DataLakeLeaseClient object
401            or the lease ID as a string.
402        :paramtype lease: ~azure.storage.filedatalake.aio.DataLakeLeaseClient or str
403        :keyword str umask:
404            Optional and only valid if Hierarchical Namespace is enabled for the account.
405            When creating a file or directory and the parent folder does not have a default ACL,
406            the umask restricts the permissions of the file or directory to be created.
407            The resulting permission is given by p & ^u, where p is the permission and u is the umask.
408            For example, if p is 0777 and u is 0057, then the resulting permission is 0720.
409            The default permission is 0777 for a directory and 0666 for a file. The default umask is 0027.
410            The umask must be specified in 4-digit octal notation (e.g. 0766).
411        :keyword str permissions:
412            Optional and only valid if Hierarchical Namespace
413            is enabled for the account. Sets POSIX access permissions for the file
414            owner, the file owning group, and others. Each class may be granted
415            read, write, or execute permission.  The sticky bit is also supported.
416            Both symbolic (rwxrw-rw-) and 4-digit octal notation (e.g. 0766) are
417            supported.
418        :keyword ~datetime.datetime if_modified_since:
419            A DateTime value. Azure expects the date value passed in to be UTC.
420            If timezone is included, any non-UTC datetimes will be converted to UTC.
421            If a date is passed in without timezone info, it is assumed to be UTC.
422            Specify this header to perform the operation only
423            if the resource has been modified since the specified time.
424        :keyword ~datetime.datetime if_unmodified_since:
425            A DateTime value. Azure expects the date value passed in to be UTC.
426            If timezone is included, any non-UTC datetimes will be converted to UTC.
427            If a date is passed in without timezone info, it is assumed to be UTC.
428            Specify this header to perform the operation only if
429            the resource has not been modified since the specified date/time.
430        :keyword str etag:
431            An ETag value, or the wildcard character (*). Used to check if the resource has changed,
432            and act according to the condition specified by the `match_condition` parameter.
433        :keyword ~azure.core.MatchConditions match_condition:
434            The match condition to use upon the etag.
435        :keyword int timeout:
436            The timeout parameter is expressed in seconds.
437        :return: DataLakeFileClient
438        """
439        file_client = self.get_file_client(file)
440        await file_client.create_file(**kwargs)
441        return file_client
442
443    def get_file_client(self, file  # type: Union[FileProperties, str]
444                        ):
445        # type: (...) -> DataLakeFileClient
446        """Get a client to interact with the specified file.
447
448        The file need not already exist.
449
450        :param file:
451            The file with which to interact. This can either be the name of the file,
452            or an instance of FileProperties. eg. directory/subdirectory/file
453        :type file: str or ~azure.storage.filedatalake.FileProperties
454        :returns: A DataLakeFileClient.
455        :rtype: ~azure.storage.filedatalake.aio.DataLakeFileClient
456
457        .. admonition:: Example:
458
459            .. literalinclude:: ../samples/test_datalake_service_samples.py
460                :start-after: [START bsc_get_file_client]
461                :end-before: [END bsc_get_file_client]
462                :language: python
463                :dedent: 12
464                :caption: Getting the file client to interact with a specific file.
465        """
466        try:
467            file_path = file.name
468        except AttributeError:
469            file_path = self.path_name + '/' + file
470
471        return DataLakeFileClient(
472            self.url, self.file_system_name, file_path=file_path, credential=self._raw_credential,
473            _hosts=self._hosts, _configuration=self._config, _pipeline=self._pipeline,
474            _location_mode=self._location_mode, require_encryption=self.require_encryption,
475            key_encryption_key=self.key_encryption_key,
476            key_resolver_function=self.key_resolver_function)
477
478    def get_sub_directory_client(self, sub_directory  # type: Union[DirectoryProperties, str]
479                                 ):
480        # type: (...) -> DataLakeDirectoryClient
481        """Get a client to interact with the specified subdirectory of the current directory.
482
483        The sub subdirectory need not already exist.
484
485        :param sub_directory:
486            The directory with which to interact. This can either be the name of the directory,
487            or an instance of DirectoryProperties.
488        :type sub_directory: str or ~azure.storage.filedatalake.DirectoryProperties
489        :returns: A DataLakeDirectoryClient.
490        :rtype: ~azure.storage.filedatalake.aio.DataLakeDirectoryClient
491
492        .. admonition:: Example:
493
494            .. literalinclude:: ../samples/test_datalake_service_samples.py
495                :start-after: [START bsc_get_directory_client]
496                :end-before: [END bsc_get_directory_client]
497                :language: python
498                :dedent: 12
499                :caption: Getting the directory client to interact with a specific directory.
500        """
501        try:
502            subdir_path = sub_directory.name
503        except AttributeError:
504            subdir_path = self.path_name + '/' + sub_directory
505
506        return DataLakeDirectoryClient(
507            self.url, self.file_system_name, directory_name=subdir_path, credential=self._raw_credential,
508            _hosts=self._hosts, _configuration=self._config, _pipeline=self._pipeline,
509            _location_mode=self._location_mode, require_encryption=self.require_encryption,
510            key_encryption_key=self.key_encryption_key,
511            key_resolver_function=self.key_resolver_function)
512