We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Unable to specify destination path when download_artifacts with MlflowClient
### The problem
When downloading artifacts with download_artifacts on MlflowClient there is no argument that can specify what is the destination path where the artifacts should be downloaded to. 

I will open a PR that fixes it.

### Source code
**mlflow/tracking/client.py**

    def download_artifacts(self, run_id, path):
        """
        Download an artifact file or directory from a run to a local directory if applicable,
        and return a local path for it.

        :param run_id: The run to download artifacts from.
        :param path: Relative source path to the desired artifact.
        :return: Local path of desired artifact.
        """
        run = self.get_run(run_id)
        artifact_root = run.info.artifact_uri
        artifact_repo = get_artifact_repository(artifact_root, self.store)
        return artifact_repo.download_artifacts(path)


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mlflow/tracking/client.py`
Content:
```
1 """
2 Internal package providing a Python CRUD interface to MLflow experiments and runs.
3 This is a lower level API than the :py:mod:`mlflow.tracking.fluent` module, and is
4 exposed in the :py:mod:`mlflow.tracking` module.
5 """
6 
7 import time
8 from six import iteritems
9 
10 from mlflow.store import SEARCH_MAX_RESULTS_DEFAULT
11 from mlflow.tracking import utils
12 from mlflow.utils.validation import _validate_param_name, _validate_tag_name, _validate_run_id, \
13     _validate_experiment_artifact_location, _validate_experiment_name, _validate_metric
14 from mlflow.entities import Param, Metric, RunStatus, RunTag, ViewType
15 from mlflow.store.artifact_repository_registry import get_artifact_repository
16 from mlflow.utils.mlflow_tags import MLFLOW_USER
17 
18 
19 class MlflowClient(object):
20     """
21     Client of an MLflow Tracking Server that creates and manages experiments and runs.
22     """
23 
24     def __init__(self, tracking_uri=None):
25         """
26         :param tracking_uri: Address of local or remote tracking server. If not provided, defaults
27                              to the service set by ``mlflow.tracking.set_tracking_uri``. See
28                              `Where Runs Get Recorded <../tracking.html#where-runs-get-recorded>`_
29                              for more info.
30         """
31         self.tracking_uri = tracking_uri or utils.get_tracking_uri()
32         self.store = utils._get_store(self.tracking_uri)
33 
34     def get_run(self, run_id):
35         """
36         Fetch the run from backend store. The resulting :py:class:`Run <mlflow.entities.Run>`
37         contains a collection of run metadata -- :py:class:`RunInfo <mlflow.entities.RunInfo>`,
38         as well as a collection of run parameters, tags, and metrics --
39         :py:class:`RunData <mlflow.entities.RunData>`. In the case where multiple metrics with the
40         same key are logged for the run, the :py:class:`RunData <mlflow.entities.RunData>` contains
41         the most recently logged value at the largest step for each metric.
42 
43         :param run_id: Unique identifier for the run.
44 
45         :return: A single :py:class:`mlflow.entities.Run` object, if the run exists. Otherwise,
46                  raises an exception.
47         """
48         _validate_run_id(run_id)
49         return self.store.get_run(run_id)
50 
51     def get_metric_history(self, run_id, key):
52         """
53         Return a list of metric objects corresponding to all values logged for a given metric.
54 
55         :param run_id: Unique identifier for run
56         :param key: Metric name within the run
57 
58         :return: A list of :py:class:`mlflow.entities.Metric` entities if logged, else empty list
59         """
60         return self.store.get_metric_history(run_id=run_id, metric_key=key)
61 
62     def create_run(self, experiment_id, start_time=None, tags=None):
63         """
64         Create a :py:class:`mlflow.entities.Run` object that can be associated with
65         metrics, parameters, artifacts, etc.
66         Unlike :py:func:`mlflow.projects.run`, creates objects but does not run code.
67         Unlike :py:func:`mlflow.start_run`, does not change the "active run" used by
68         :py:func:`mlflow.log_param`.
69 
70         :param experiment_id: The ID of then experiment to create a run in.
71         :param start_time: If not provided, use the current timestamp.
72         :param tags: A dictionary of key-value pairs that are converted into
73                      :py:class:`mlflow.entities.RunTag` objects.
74         :return: :py:class:`mlflow.entities.Run` that was created.
75         """
76 
77         tags = tags if tags else {}
78 
79         # Extract user from tags
80         # This logic is temporary; the user_id attribute of runs is deprecated and will be removed
81         # in a later release.
82         user_id = tags.get(MLFLOW_USER, "unknown")
83 
84         return self.store.create_run(
85             experiment_id=experiment_id,
86             user_id=user_id,
87             start_time=start_time or int(time.time() * 1000),
88             tags=[RunTag(key, value) for (key, value) in iteritems(tags)]
89         )
90 
91     def list_run_infos(self, experiment_id, run_view_type=ViewType.ACTIVE_ONLY):
92         """:return: List of :py:class:`mlflow.entities.RunInfo`"""
93         return self.store.list_run_infos(experiment_id, run_view_type)
94 
95     def list_experiments(self, view_type=None):
96         """
97         :return: List of :py:class:`mlflow.entities.Experiment`
98         """
99         final_view_type = ViewType.ACTIVE_ONLY if view_type is None else view_type
100         return self.store.list_experiments(view_type=final_view_type)
101 
102     def get_experiment(self, experiment_id):
103         """
104         :param experiment_id: The experiment ID returned from ``create_experiment``.
105         :return: :py:class:`mlflow.entities.Experiment`
106         """
107         return self.store.get_experiment(experiment_id)
108 
109     def get_experiment_by_name(self, name):
110         """
111         :param name: The experiment name.
112         :return: :py:class:`mlflow.entities.Experiment`
113         """
114         return self.store.get_experiment_by_name(name)
115 
116     def create_experiment(self, name, artifact_location=None):
117         """Create an experiment.
118 
119         :param name: The experiment name. Must be unique.
120         :param artifact_location: The location to store run artifacts.
121                                   If not provided, the server picks an appropriate default.
122         :return: Integer ID of the created experiment.
123         """
124         _validate_experiment_name(name)
125         _validate_experiment_artifact_location(artifact_location)
126         return self.store.create_experiment(
127             name=name,
128             artifact_location=artifact_location,
129         )
130 
131     def delete_experiment(self, experiment_id):
132         """
133         Delete an experiment from the backend store.
134 
135         :param experiment_id: The experiment ID returned from ``create_experiment``.
136         """
137         self.store.delete_experiment(experiment_id)
138 
139     def restore_experiment(self, experiment_id):
140         """
141         Restore a deleted experiment unless permanently deleted.
142 
143         :param experiment_id: The experiment ID returned from ``create_experiment``.
144         """
145         self.store.restore_experiment(experiment_id)
146 
147     def rename_experiment(self, experiment_id, new_name):
148         """
149         Update an experiment's name. The new name must be unique.
150 
151         :param experiment_id: The experiment ID returned from ``create_experiment``.
152         """
153         self.store.rename_experiment(experiment_id, new_name)
154 
155     def log_metric(self, run_id, key, value, timestamp=None, step=None):
156         """
157         Log a metric against the run ID. The timestamp defaults to the current timestamp.
158         The step defaults to 0.
159         """
160         timestamp = timestamp if timestamp is not None else int(time.time())
161         step = step if step is not None else 0
162         _validate_metric(key, value, timestamp, step)
163         metric = Metric(key, value, timestamp, step)
164         self.store.log_metric(run_id, metric)
165 
166     def log_param(self, run_id, key, value):
167         """
168         Log a parameter against the run ID. Value is converted to a string.
169         """
170         _validate_param_name(key)
171         param = Param(key, str(value))
172         self.store.log_param(run_id, param)
173 
174     def set_tag(self, run_id, key, value):
175         """
176         Set a tag on the run ID. Value is converted to a string.
177         """
178         _validate_tag_name(key)
179         tag = RunTag(key, str(value))
180         self.store.set_tag(run_id, tag)
181 
182     def log_batch(self, run_id, metrics, params, tags):
183         """
184         Log multiple metrics, params, and/or tags.
185 
186         :param metrics: List of Metric(key, value, timestamp) instances.
187         :param params: List of Param(key, value) instances.
188         :param tags: List of RunTag(key, value) instances.
189 
190         Raises an MlflowException if any errors occur.
191         :returns: None
192         """
193         for metric in metrics:
194             _validate_metric(metric.key, metric.value, metric.timestamp, metric.step)
195         for param in params:
196             _validate_param_name(param.key)
197         for tag in tags:
198             _validate_tag_name(tag.key)
199         self.store.log_batch(run_id=run_id, metrics=metrics, params=params, tags=tags)
200 
201     def log_artifact(self, run_id, local_path, artifact_path=None):
202         """
203         Write a local file to the remote ``artifact_uri``.
204 
205         :param local_path: Path to the file to write.
206         :param artifact_path: If provided, the directory in ``artifact_uri`` to write to.
207         """
208         run = self.get_run(run_id)
209         artifact_repo = get_artifact_repository(run.info.artifact_uri)
210         artifact_repo.log_artifact(local_path, artifact_path)
211 
212     def log_artifacts(self, run_id, local_dir, artifact_path=None):
213         """
214         Write a directory of files to the remote ``artifact_uri``.
215 
216         :param local_dir: Path to the directory of files to write.
217         :param artifact_path: If provided, the directory in ``artifact_uri`` to write to.
218         """
219         run = self.get_run(run_id)
220         artifact_repo = get_artifact_repository(run.info.artifact_uri)
221         artifact_repo.log_artifacts(local_dir, artifact_path)
222 
223     def list_artifacts(self, run_id, path=None):
224         """
225         List the artifacts for a run.
226 
227         :param run_id: The run to list artifacts from.
228         :param path: The run's relative artifact path to list from. By default it is set to None
229                      or the root artifact path.
230         :return: List of :py:class:`mlflow.entities.FileInfo`
231         """
232         run = self.get_run(run_id)
233         artifact_root = run.info.artifact_uri
234         artifact_repo = get_artifact_repository(artifact_root)
235         return artifact_repo.list_artifacts(path)
236 
237     def download_artifacts(self, run_id, path):
238         """
239         Download an artifact file or directory from a run to a local directory if applicable,
240         and return a local path for it.
241 
242         :param run_id: The run to download artifacts from.
243         :param path: Relative source path to the desired artifact.
244         :return: Local path of desired artifact.
245         """
246         run = self.get_run(run_id)
247         artifact_root = run.info.artifact_uri
248         artifact_repo = get_artifact_repository(artifact_root)
249         return artifact_repo.download_artifacts(path)
250 
251     def set_terminated(self, run_id, status=None, end_time=None):
252         """Set a run's status to terminated.
253 
254         :param status: A string value of :py:class:`mlflow.entities.RunStatus`.
255                        Defaults to "FINISHED".
256         :param end_time: If not provided, defaults to the current time."""
257         end_time = end_time if end_time else int(time.time() * 1000)
258         status = status if status else RunStatus.to_string(RunStatus.FINISHED)
259         self.store.update_run_info(run_id, run_status=RunStatus.from_string(status),
260                                    end_time=end_time)
261 
262     def delete_run(self, run_id):
263         """
264         Deletes a run with the given ID.
265         """
266         self.store.delete_run(run_id)
267 
268     def restore_run(self, run_id):
269         """
270         Restores a deleted run with the given ID.
271         """
272         self.store.restore_run(run_id)
273 
274     def search_runs(self, experiment_ids, filter_string="", run_view_type=ViewType.ACTIVE_ONLY,
275                     max_results=SEARCH_MAX_RESULTS_DEFAULT, order_by=None, page_token=None):
276         """
277         Search experiments that fit the search criteria.
278 
279         :param experiment_ids: List of experiment IDs, or a single int or string id.
280         :param filter_string: Filter query string, defaults to searching all runs.
281         :param run_view_type: one of enum values ACTIVE_ONLY, DELETED_ONLY, or ALL runs
282                               defined in :py:class:`mlflow.entities.ViewType`.
283         :param max_results: Maximum number of runs desired.
284         :param order_by: List of columns to order by (e.g., "metrics.rmse"). The default
285                          ordering is to sort by start_time DESC, then run_id.
286         :param page_token: Token specifying the next page of results. It should be obtained from
287             a ``search_runs`` call.
288 
289         :return: A list of :py:class:`mlflow.entities.Run` objects that satisfy the search
290             expressions. If the underlying tracking store supports pagination, the token for
291             the next page may be obtained via the ``token`` attribute of the returned object.
292         """
293         if isinstance(experiment_ids, int) or isinstance(experiment_ids, str):
294             experiment_ids = [experiment_ids]
295         return self.store.search_runs(experiment_ids=experiment_ids, filter_string=filter_string,
296                                       run_view_type=run_view_type, max_results=max_results,
297                                       order_by=order_by, page_token=page_token)
298
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mlflow/tracking/client.py b/mlflow/tracking/client.py
--- a/mlflow/tracking/client.py
+++ b/mlflow/tracking/client.py
@@ -234,19 +234,24 @@
         artifact_repo = get_artifact_repository(artifact_root)
         return artifact_repo.list_artifacts(path)
 
-    def download_artifacts(self, run_id, path):
+    def download_artifacts(self, run_id, path, dst_path=None):
         """
         Download an artifact file or directory from a run to a local directory if applicable,
         and return a local path for it.
 
         :param run_id: The run to download artifacts from.
         :param path: Relative source path to the desired artifact.
+        :param dst_path: Absolute path of the local filesystem destination directory to which to
+                         download the specified artifacts. This directory must already exist.
+                         If unspecified, the artifacts will either be downloaded to a new
+                         uniquely-named directory on the local filesystem or will be returned
+                         directly in the case of the LocalArtifactRepository.
         :return: Local path of desired artifact.
         """
         run = self.get_run(run_id)
         artifact_root = run.info.artifact_uri
         artifact_repo = get_artifact_repository(artifact_root)
-        return artifact_repo.download_artifacts(path)
+        return artifact_repo.download_artifacts(path, dst_path)
 
     def set_terminated(self, run_id, status=None, end_time=None):
         """Set a run's status to terminated.

{"golden_diff": "diff --git a/mlflow/tracking/client.py b/mlflow/tracking/client.py\n--- a/mlflow/tracking/client.py\n+++ b/mlflow/tracking/client.py\n@@ -234,19 +234,24 @@\n         artifact_repo = get_artifact_repository(artifact_root)\n         return artifact_repo.list_artifacts(path)\n \n-    def download_artifacts(self, run_id, path):\n+    def download_artifacts(self, run_id, path, dst_path=None):\n         \"\"\"\n         Download an artifact file or directory from a run to a local directory if applicable,\n         and return a local path for it.\n \n         :param run_id: The run to download artifacts from.\n         :param path: Relative source path to the desired artifact.\n+        :param dst_path: Absolute path of the local filesystem destination directory to which to\n+                         download the specified artifacts. This directory must already exist.\n+                         If unspecified, the artifacts will either be downloaded to a new\n+                         uniquely-named directory on the local filesystem or will be returned\n+                         directly in the case of the LocalArtifactRepository.\n         :return: Local path of desired artifact.\n         \"\"\"\n         run = self.get_run(run_id)\n         artifact_root = run.info.artifact_uri\n         artifact_repo = get_artifact_repository(artifact_root)\n-        return artifact_repo.download_artifacts(path)\n+        return artifact_repo.download_artifacts(path, dst_path)\n \n     def set_terminated(self, run_id, status=None, end_time=None):\n         \"\"\"Set a run's status to terminated.\n", "issue": "Unable to specify destination path when download_artifacts with MlflowClient\n### The problem\r\nWhen downloading artifacts with download_artifacts on MlflowClient there is no argument that can specify what is the destination path where the artifacts should be downloaded to. \r\n\r\nI will open a PR that fixes it.\r\n\r\n### Source code\r\n**mlflow/tracking/client.py**\r\n\r\n    def download_artifacts(self, run_id, path):\r\n        \"\"\"\r\n        Download an artifact file or directory from a run to a local directory if applicable,\r\n        and return a local path for it.\r\n\r\n        :param run_id: The run to download artifacts from.\r\n        :param path: Relative source path to the desired artifact.\r\n        :return: Local path of desired artifact.\r\n        \"\"\"\r\n        run = self.get_run(run_id)\r\n        artifact_root = run.info.artifact_uri\r\n        artifact_repo = get_artifact_repository(artifact_root, self.store)\r\n        return artifact_repo.download_artifacts(path)\r\n\n", "before_files": [{"content": "\"\"\"\nInternal package providing a Python CRUD interface to MLflow experiments and runs.\nThis is a lower level API than the :py:mod:`mlflow.tracking.fluent` module, and is\nexposed in the :py:mod:`mlflow.tracking` module.\n\"\"\"\n\nimport time\nfrom six import iteritems\n\nfrom mlflow.store import SEARCH_MAX_RESULTS_DEFAULT\nfrom mlflow.tracking import utils\nfrom mlflow.utils.validation import _validate_param_name, _validate_tag_name, _validate_run_id, \\\n    _validate_experiment_artifact_location, _validate_experiment_name, _validate_metric\nfrom mlflow.entities import Param, Metric, RunStatus, RunTag, ViewType\nfrom mlflow.store.artifact_repository_registry import get_artifact_repository\nfrom mlflow.utils.mlflow_tags import MLFLOW_USER\n\n\nclass MlflowClient(object):\n    \"\"\"\n    Client of an MLflow Tracking Server that creates and manages experiments and runs.\n    \"\"\"\n\n    def __init__(self, tracking_uri=None):\n        \"\"\"\n        :param tracking_uri: Address of local or remote tracking server. If not provided, defaults\n                             to the service set by ``mlflow.tracking.set_tracking_uri``. See\n                             `Where Runs Get Recorded <../tracking.html#where-runs-get-recorded>`_\n                             for more info.\n        \"\"\"\n        self.tracking_uri = tracking_uri or utils.get_tracking_uri()\n        self.store = utils._get_store(self.tracking_uri)\n\n    def get_run(self, run_id):\n        \"\"\"\n        Fetch the run from backend store. The resulting :py:class:`Run <mlflow.entities.Run>`\n        contains a collection of run metadata -- :py:class:`RunInfo <mlflow.entities.RunInfo>`,\n        as well as a collection of run parameters, tags, and metrics --\n        :py:class:`RunData <mlflow.entities.RunData>`. In the case where multiple metrics with the\n        same key are logged for the run, the :py:class:`RunData <mlflow.entities.RunData>` contains\n        the most recently logged value at the largest step for each metric.\n\n        :param run_id: Unique identifier for the run.\n\n        :return: A single :py:class:`mlflow.entities.Run` object, if the run exists. Otherwise,\n                 raises an exception.\n        \"\"\"\n        _validate_run_id(run_id)\n        return self.store.get_run(run_id)\n\n    def get_metric_history(self, run_id, key):\n        \"\"\"\n        Return a list of metric objects corresponding to all values logged for a given metric.\n\n        :param run_id: Unique identifier for run\n        :param key: Metric name within the run\n\n        :return: A list of :py:class:`mlflow.entities.Metric` entities if logged, else empty list\n        \"\"\"\n        return self.store.get_metric_history(run_id=run_id, metric_key=key)\n\n    def create_run(self, experiment_id, start_time=None, tags=None):\n        \"\"\"\n        Create a :py:class:`mlflow.entities.Run` object that can be associated with\n        metrics, parameters, artifacts, etc.\n        Unlike :py:func:`mlflow.projects.run`, creates objects but does not run code.\n        Unlike :py:func:`mlflow.start_run`, does not change the \"active run\" used by\n        :py:func:`mlflow.log_param`.\n\n        :param experiment_id: The ID of then experiment to create a run in.\n        :param start_time: If not provided, use the current timestamp.\n        :param tags: A dictionary of key-value pairs that are converted into\n                     :py:class:`mlflow.entities.RunTag` objects.\n        :return: :py:class:`mlflow.entities.Run` that was created.\n        \"\"\"\n\n        tags = tags if tags else {}\n\n        # Extract user from tags\n        # This logic is temporary; the user_id attribute of runs is deprecated and will be removed\n        # in a later release.\n        user_id = tags.get(MLFLOW_USER, \"unknown\")\n\n        return self.store.create_run(\n            experiment_id=experiment_id,\n            user_id=user_id,\n            start_time=start_time or int(time.time() * 1000),\n            tags=[RunTag(key, value) for (key, value) in iteritems(tags)]\n        )\n\n    def list_run_infos(self, experiment_id, run_view_type=ViewType.ACTIVE_ONLY):\n        \"\"\":return: List of :py:class:`mlflow.entities.RunInfo`\"\"\"\n        return self.store.list_run_infos(experiment_id, run_view_type)\n\n    def list_experiments(self, view_type=None):\n        \"\"\"\n        :return: List of :py:class:`mlflow.entities.Experiment`\n        \"\"\"\n        final_view_type = ViewType.ACTIVE_ONLY if view_type is None else view_type\n        return self.store.list_experiments(view_type=final_view_type)\n\n    def get_experiment(self, experiment_id):\n        \"\"\"\n        :param experiment_id: The experiment ID returned from ``create_experiment``.\n        :return: :py:class:`mlflow.entities.Experiment`\n        \"\"\"\n        return self.store.get_experiment(experiment_id)\n\n    def get_experiment_by_name(self, name):\n        \"\"\"\n        :param name: The experiment name.\n        :return: :py:class:`mlflow.entities.Experiment`\n        \"\"\"\n        return self.store.get_experiment_by_name(name)\n\n    def create_experiment(self, name, artifact_location=None):\n        \"\"\"Create an experiment.\n\n        :param name: The experiment name. Must be unique.\n        :param artifact_location: The location to store run artifacts.\n                                  If not provided, the server picks an appropriate default.\n        :return: Integer ID of the created experiment.\n        \"\"\"\n        _validate_experiment_name(name)\n        _validate_experiment_artifact_location(artifact_location)\n        return self.store.create_experiment(\n            name=name,\n            artifact_location=artifact_location,\n        )\n\n    def delete_experiment(self, experiment_id):\n        \"\"\"\n        Delete an experiment from the backend store.\n\n        :param experiment_id: The experiment ID returned from ``create_experiment``.\n        \"\"\"\n        self.store.delete_experiment(experiment_id)\n\n    def restore_experiment(self, experiment_id):\n        \"\"\"\n        Restore a deleted experiment unless permanently deleted.\n\n        :param experiment_id: The experiment ID returned from ``create_experiment``.\n        \"\"\"\n        self.store.restore_experiment(experiment_id)\n\n    def rename_experiment(self, experiment_id, new_name):\n        \"\"\"\n        Update an experiment's name. The new name must be unique.\n\n        :param experiment_id: The experiment ID returned from ``create_experiment``.\n        \"\"\"\n        self.store.rename_experiment(experiment_id, new_name)\n\n    def log_metric(self, run_id, key, value, timestamp=None, step=None):\n        \"\"\"\n        Log a metric against the run ID. The timestamp defaults to the current timestamp.\n        The step defaults to 0.\n        \"\"\"\n        timestamp = timestamp if timestamp is not None else int(time.time())\n        step = step if step is not None else 0\n        _validate_metric(key, value, timestamp, step)\n        metric = Metric(key, value, timestamp, step)\n        self.store.log_metric(run_id, metric)\n\n    def log_param(self, run_id, key, value):\n        \"\"\"\n        Log a parameter against the run ID. Value is converted to a string.\n        \"\"\"\n        _validate_param_name(key)\n        param = Param(key, str(value))\n        self.store.log_param(run_id, param)\n\n    def set_tag(self, run_id, key, value):\n        \"\"\"\n        Set a tag on the run ID. Value is converted to a string.\n        \"\"\"\n        _validate_tag_name(key)\n        tag = RunTag(key, str(value))\n        self.store.set_tag(run_id, tag)\n\n    def log_batch(self, run_id, metrics, params, tags):\n        \"\"\"\n        Log multiple metrics, params, and/or tags.\n\n        :param metrics: List of Metric(key, value, timestamp) instances.\n        :param params: List of Param(key, value) instances.\n        :param tags: List of RunTag(key, value) instances.\n\n        Raises an MlflowException if any errors occur.\n        :returns: None\n        \"\"\"\n        for metric in metrics:\n            _validate_metric(metric.key, metric.value, metric.timestamp, metric.step)\n        for param in params:\n            _validate_param_name(param.key)\n        for tag in tags:\n            _validate_tag_name(tag.key)\n        self.store.log_batch(run_id=run_id, metrics=metrics, params=params, tags=tags)\n\n    def log_artifact(self, run_id, local_path, artifact_path=None):\n        \"\"\"\n        Write a local file to the remote ``artifact_uri``.\n\n        :param local_path: Path to the file to write.\n        :param artifact_path: If provided, the directory in ``artifact_uri`` to write to.\n        \"\"\"\n        run = self.get_run(run_id)\n        artifact_repo = get_artifact_repository(run.info.artifact_uri)\n        artifact_repo.log_artifact(local_path, artifact_path)\n\n    def log_artifacts(self, run_id, local_dir, artifact_path=None):\n        \"\"\"\n        Write a directory of files to the remote ``artifact_uri``.\n\n        :param local_dir: Path to the directory of files to write.\n        :param artifact_path: If provided, the directory in ``artifact_uri`` to write to.\n        \"\"\"\n        run = self.get_run(run_id)\n        artifact_repo = get_artifact_repository(run.info.artifact_uri)\n        artifact_repo.log_artifacts(local_dir, artifact_path)\n\n    def list_artifacts(self, run_id, path=None):\n        \"\"\"\n        List the artifacts for a run.\n\n        :param run_id: The run to list artifacts from.\n        :param path: The run's relative artifact path to list from. By default it is set to None\n                     or the root artifact path.\n        :return: List of :py:class:`mlflow.entities.FileInfo`\n        \"\"\"\n        run = self.get_run(run_id)\n        artifact_root = run.info.artifact_uri\n        artifact_repo = get_artifact_repository(artifact_root)\n        return artifact_repo.list_artifacts(path)\n\n    def download_artifacts(self, run_id, path):\n        \"\"\"\n        Download an artifact file or directory from a run to a local directory if applicable,\n        and return a local path for it.\n\n        :param run_id: The run to download artifacts from.\n        :param path: Relative source path to the desired artifact.\n        :return: Local path of desired artifact.\n        \"\"\"\n        run = self.get_run(run_id)\n        artifact_root = run.info.artifact_uri\n        artifact_repo = get_artifact_repository(artifact_root)\n        return artifact_repo.download_artifacts(path)\n\n    def set_terminated(self, run_id, status=None, end_time=None):\n        \"\"\"Set a run's status to terminated.\n\n        :param status: A string value of :py:class:`mlflow.entities.RunStatus`.\n                       Defaults to \"FINISHED\".\n        :param end_time: If not provided, defaults to the current time.\"\"\"\n        end_time = end_time if end_time else int(time.time() * 1000)\n        status = status if status else RunStatus.to_string(RunStatus.FINISHED)\n        self.store.update_run_info(run_id, run_status=RunStatus.from_string(status),\n                                   end_time=end_time)\n\n    def delete_run(self, run_id):\n        \"\"\"\n        Deletes a run with the given ID.\n        \"\"\"\n        self.store.delete_run(run_id)\n\n    def restore_run(self, run_id):\n        \"\"\"\n        Restores a deleted run with the given ID.\n        \"\"\"\n        self.store.restore_run(run_id)\n\n    def search_runs(self, experiment_ids, filter_string=\"\", run_view_type=ViewType.ACTIVE_ONLY,\n                    max_results=SEARCH_MAX_RESULTS_DEFAULT, order_by=None, page_token=None):\n        \"\"\"\n        Search experiments that fit the search criteria.\n\n        :param experiment_ids: List of experiment IDs, or a single int or string id.\n        :param filter_string: Filter query string, defaults to searching all runs.\n        :param run_view_type: one of enum values ACTIVE_ONLY, DELETED_ONLY, or ALL runs\n                              defined in :py:class:`mlflow.entities.ViewType`.\n        :param max_results: Maximum number of runs desired.\n        :param order_by: List of columns to order by (e.g., \"metrics.rmse\"). The default\n                         ordering is to sort by start_time DESC, then run_id.\n        :param page_token: Token specifying the next page of results. It should be obtained from\n            a ``search_runs`` call.\n\n        :return: A list of :py:class:`mlflow.entities.Run` objects that satisfy the search\n            expressions. If the underlying tracking store supports pagination, the token for\n            the next page may be obtained via the ``token`` attribute of the returned object.\n        \"\"\"\n        if isinstance(experiment_ids, int) or isinstance(experiment_ids, str):\n            experiment_ids = [experiment_ids]\n        return self.store.search_runs(experiment_ids=experiment_ids, filter_string=filter_string,\n                                      run_view_type=run_view_type, max_results=max_results,\n                                      order_by=order_by, page_token=page_token)\n", "path": "mlflow/tracking/client.py"}], "after_files": [{"content": "\"\"\"\nInternal package providing a Python CRUD interface to MLflow experiments and runs.\nThis is a lower level API than the :py:mod:`mlflow.tracking.fluent` module, and is\nexposed in the :py:mod:`mlflow.tracking` module.\n\"\"\"\n\nimport time\nfrom six import iteritems\n\nfrom mlflow.store import SEARCH_MAX_RESULTS_DEFAULT\nfrom mlflow.tracking import utils\nfrom mlflow.utils.validation import _validate_param_name, _validate_tag_name, _validate_run_id, \\\n    _validate_experiment_artifact_location, _validate_experiment_name, _validate_metric\nfrom mlflow.entities import Param, Metric, RunStatus, RunTag, ViewType\nfrom mlflow.store.artifact_repository_registry import get_artifact_repository\nfrom mlflow.utils.mlflow_tags import MLFLOW_USER\n\n\nclass MlflowClient(object):\n    \"\"\"\n    Client of an MLflow Tracking Server that creates and manages experiments and runs.\n    \"\"\"\n\n    def __init__(self, tracking_uri=None):\n        \"\"\"\n        :param tracking_uri: Address of local or remote tracking server. If not provided, defaults\n                             to the service set by ``mlflow.tracking.set_tracking_uri``. See\n                             `Where Runs Get Recorded <../tracking.html#where-runs-get-recorded>`_\n                             for more info.\n        \"\"\"\n        self.tracking_uri = tracking_uri or utils.get_tracking_uri()\n        self.store = utils._get_store(self.tracking_uri)\n\n    def get_run(self, run_id):\n        \"\"\"\n        Fetch the run from backend store. The resulting :py:class:`Run <mlflow.entities.Run>`\n        contains a collection of run metadata -- :py:class:`RunInfo <mlflow.entities.RunInfo>`,\n        as well as a collection of run parameters, tags, and metrics --\n        :py:class:`RunData <mlflow.entities.RunData>`. In the case where multiple metrics with the\n        same key are logged for the run, the :py:class:`RunData <mlflow.entities.RunData>` contains\n        the most recently logged value at the largest step for each metric.\n\n        :param run_id: Unique identifier for the run.\n\n        :return: A single :py:class:`mlflow.entities.Run` object, if the run exists. Otherwise,\n                 raises an exception.\n        \"\"\"\n        _validate_run_id(run_id)\n        return self.store.get_run(run_id)\n\n    def get_metric_history(self, run_id, key):\n        \"\"\"\n        Return a list of metric objects corresponding to all values logged for a given metric.\n\n        :param run_id: Unique identifier for run\n        :param key: Metric name within the run\n\n        :return: A list of :py:class:`mlflow.entities.Metric` entities if logged, else empty list\n        \"\"\"\n        return self.store.get_metric_history(run_id=run_id, metric_key=key)\n\n    def create_run(self, experiment_id, start_time=None, tags=None):\n        \"\"\"\n        Create a :py:class:`mlflow.entities.Run` object that can be associated with\n        metrics, parameters, artifacts, etc.\n        Unlike :py:func:`mlflow.projects.run`, creates objects but does not run code.\n        Unlike :py:func:`mlflow.start_run`, does not change the \"active run\" used by\n        :py:func:`mlflow.log_param`.\n\n        :param experiment_id: The ID of then experiment to create a run in.\n        :param start_time: If not provided, use the current timestamp.\n        :param tags: A dictionary of key-value pairs that are converted into\n                     :py:class:`mlflow.entities.RunTag` objects.\n        :return: :py:class:`mlflow.entities.Run` that was created.\n        \"\"\"\n\n        tags = tags if tags else {}\n\n        # Extract user from tags\n        # This logic is temporary; the user_id attribute of runs is deprecated and will be removed\n        # in a later release.\n        user_id = tags.get(MLFLOW_USER, \"unknown\")\n\n        return self.store.create_run(\n            experiment_id=experiment_id,\n            user_id=user_id,\n            start_time=start_time or int(time.time() * 1000),\n            tags=[RunTag(key, value) for (key, value) in iteritems(tags)]\n        )\n\n    def list_run_infos(self, experiment_id, run_view_type=ViewType.ACTIVE_ONLY):\n        \"\"\":return: List of :py:class:`mlflow.entities.RunInfo`\"\"\"\n        return self.store.list_run_infos(experiment_id, run_view_type)\n\n    def list_experiments(self, view_type=None):\n        \"\"\"\n        :return: List of :py:class:`mlflow.entities.Experiment`\n        \"\"\"\n        final_view_type = ViewType.ACTIVE_ONLY if view_type is None else view_type\n        return self.store.list_experiments(view_type=final_view_type)\n\n    def get_experiment(self, experiment_id):\n        \"\"\"\n        :param experiment_id: The experiment ID returned from ``create_experiment``.\n        :return: :py:class:`mlflow.entities.Experiment`\n        \"\"\"\n        return self.store.get_experiment(experiment_id)\n\n    def get_experiment_by_name(self, name):\n        \"\"\"\n        :param name: The experiment name.\n        :return: :py:class:`mlflow.entities.Experiment`\n        \"\"\"\n        return self.store.get_experiment_by_name(name)\n\n    def create_experiment(self, name, artifact_location=None):\n        \"\"\"Create an experiment.\n\n        :param name: The experiment name. Must be unique.\n        :param artifact_location: The location to store run artifacts.\n                                  If not provided, the server picks an appropriate default.\n        :return: Integer ID of the created experiment.\n        \"\"\"\n        _validate_experiment_name(name)\n        _validate_experiment_artifact_location(artifact_location)\n        return self.store.create_experiment(\n            name=name,\n            artifact_location=artifact_location,\n        )\n\n    def delete_experiment(self, experiment_id):\n        \"\"\"\n        Delete an experiment from the backend store.\n\n        :param experiment_id: The experiment ID returned from ``create_experiment``.\n        \"\"\"\n        self.store.delete_experiment(experiment_id)\n\n    def restore_experiment(self, experiment_id):\n        \"\"\"\n        Restore a deleted experiment unless permanently deleted.\n\n        :param experiment_id: The experiment ID returned from ``create_experiment``.\n        \"\"\"\n        self.store.restore_experiment(experiment_id)\n\n    def rename_experiment(self, experiment_id, new_name):\n        \"\"\"\n        Update an experiment's name. The new name must be unique.\n\n        :param experiment_id: The experiment ID returned from ``create_experiment``.\n        \"\"\"\n        self.store.rename_experiment(experiment_id, new_name)\n\n    def log_metric(self, run_id, key, value, timestamp=None, step=None):\n        \"\"\"\n        Log a metric against the run ID. The timestamp defaults to the current timestamp.\n        The step defaults to 0.\n        \"\"\"\n        timestamp = timestamp if timestamp is not None else int(time.time())\n        step = step if step is not None else 0\n        _validate_metric(key, value, timestamp, step)\n        metric = Metric(key, value, timestamp, step)\n        self.store.log_metric(run_id, metric)\n\n    def log_param(self, run_id, key, value):\n        \"\"\"\n        Log a parameter against the run ID. Value is converted to a string.\n        \"\"\"\n        _validate_param_name(key)\n        param = Param(key, str(value))\n        self.store.log_param(run_id, param)\n\n    def set_tag(self, run_id, key, value):\n        \"\"\"\n        Set a tag on the run ID. Value is converted to a string.\n        \"\"\"\n        _validate_tag_name(key)\n        tag = RunTag(key, str(value))\n        self.store.set_tag(run_id, tag)\n\n    def log_batch(self, run_id, metrics, params, tags):\n        \"\"\"\n        Log multiple metrics, params, and/or tags.\n\n        :param metrics: List of Metric(key, value, timestamp) instances.\n        :param params: List of Param(key, value) instances.\n        :param tags: List of RunTag(key, value) instances.\n\n        Raises an MlflowException if any errors occur.\n        :returns: None\n        \"\"\"\n        for metric in metrics:\n            _validate_metric(metric.key, metric.value, metric.timestamp, metric.step)\n        for param in params:\n            _validate_param_name(param.key)\n        for tag in tags:\n            _validate_tag_name(tag.key)\n        self.store.log_batch(run_id=run_id, metrics=metrics, params=params, tags=tags)\n\n    def log_artifact(self, run_id, local_path, artifact_path=None):\n        \"\"\"\n        Write a local file to the remote ``artifact_uri``.\n\n        :param local_path: Path to the file to write.\n        :param artifact_path: If provided, the directory in ``artifact_uri`` to write to.\n        \"\"\"\n        run = self.get_run(run_id)\n        artifact_repo = get_artifact_repository(run.info.artifact_uri)\n        artifact_repo.log_artifact(local_path, artifact_path)\n\n    def log_artifacts(self, run_id, local_dir, artifact_path=None):\n        \"\"\"\n        Write a directory of files to the remote ``artifact_uri``.\n\n        :param local_dir: Path to the directory of files to write.\n        :param artifact_path: If provided, the directory in ``artifact_uri`` to write to.\n        \"\"\"\n        run = self.get_run(run_id)\n        artifact_repo = get_artifact_repository(run.info.artifact_uri)\n        artifact_repo.log_artifacts(local_dir, artifact_path)\n\n    def list_artifacts(self, run_id, path=None):\n        \"\"\"\n        List the artifacts for a run.\n\n        :param run_id: The run to list artifacts from.\n        :param path: The run's relative artifact path to list from. By default it is set to None\n                     or the root artifact path.\n        :return: List of :py:class:`mlflow.entities.FileInfo`\n        \"\"\"\n        run = self.get_run(run_id)\n        artifact_root = run.info.artifact_uri\n        artifact_repo = get_artifact_repository(artifact_root)\n        return artifact_repo.list_artifacts(path)\n\n    def download_artifacts(self, run_id, path, dst_path=None):\n        \"\"\"\n        Download an artifact file or directory from a run to a local directory if applicable,\n        and return a local path for it.\n\n        :param run_id: The run to download artifacts from.\n        :param path: Relative source path to the desired artifact.\n        :param dst_path: Absolute path of the local filesystem destination directory to which to\n                         download the specified artifacts. This directory must already exist.\n                         If unspecified, the artifacts will either be downloaded to a new\n                         uniquely-named directory on the local filesystem or will be returned\n                         directly in the case of the LocalArtifactRepository.\n        :return: Local path of desired artifact.\n        \"\"\"\n        run = self.get_run(run_id)\n        artifact_root = run.info.artifact_uri\n        artifact_repo = get_artifact_repository(artifact_root)\n        return artifact_repo.download_artifacts(path, dst_path)\n\n    def set_terminated(self, run_id, status=None, end_time=None):\n        \"\"\"Set a run's status to terminated.\n\n        :param status: A string value of :py:class:`mlflow.entities.RunStatus`.\n                       Defaults to \"FINISHED\".\n        :param end_time: If not provided, defaults to the current time.\"\"\"\n        end_time = end_time if end_time else int(time.time() * 1000)\n        status = status if status else RunStatus.to_string(RunStatus.FINISHED)\n        self.store.update_run_info(run_id, run_status=RunStatus.from_string(status),\n                                   end_time=end_time)\n\n    def delete_run(self, run_id):\n        \"\"\"\n        Deletes a run with the given ID.\n        \"\"\"\n        self.store.delete_run(run_id)\n\n    def restore_run(self, run_id):\n        \"\"\"\n        Restores a deleted run with the given ID.\n        \"\"\"\n        self.store.restore_run(run_id)\n\n    def search_runs(self, experiment_ids, filter_string=\"\", run_view_type=ViewType.ACTIVE_ONLY,\n                    max_results=SEARCH_MAX_RESULTS_DEFAULT, order_by=None, page_token=None):\n        \"\"\"\n        Search experiments that fit the search criteria.\n\n        :param experiment_ids: List of experiment IDs, or a single int or string id.\n        :param filter_string: Filter query string, defaults to searching all runs.\n        :param run_view_type: one of enum values ACTIVE_ONLY, DELETED_ONLY, or ALL runs\n                              defined in :py:class:`mlflow.entities.ViewType`.\n        :param max_results: Maximum number of runs desired.\n        :param order_by: List of columns to order by (e.g., \"metrics.rmse\"). The default\n                         ordering is to sort by start_time DESC, then run_id.\n        :param page_token: Token specifying the next page of results. It should be obtained from\n            a ``search_runs`` call.\n\n        :return: A list of :py:class:`mlflow.entities.Run` objects that satisfy the search\n            expressions. If the underlying tracking store supports pagination, the token for\n            the next page may be obtained via the ``token`` attribute of the returned object.\n        \"\"\"\n        if isinstance(experiment_ids, int) or isinstance(experiment_ids, str):\n            experiment_ids = [experiment_ids]\n        return self.store.search_runs(experiment_ids=experiment_ids, filter_string=filter_string,\n                                      run_view_type=run_view_type, max_results=max_results,\n                                      order_by=order_by, page_token=page_token)\n", "path": "mlflow/tracking/client.py"}]}