Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
mlflow/mlflow/store/artifact/local_artifact_repo.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
114 lines (98 sloc)
4.99 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import shutil | |
from mlflow.store.artifact.artifact_repo import ArtifactRepository, verify_artifact_path | |
from mlflow.utils.file_utils import ( | |
mkdir, | |
list_all, | |
get_file_info, | |
local_file_uri_to_path, | |
relative_path_to_artifact_path, | |
) | |
class LocalArtifactRepository(ArtifactRepository): | |
"""Stores artifacts as files in a local directory.""" | |
def __init__(self, *args, **kwargs): | |
super().__init__(*args, **kwargs) | |
self._artifact_dir = local_file_uri_to_path(self.artifact_uri) | |
@property | |
def artifact_dir(self): | |
return self._artifact_dir | |
def log_artifact(self, local_file, artifact_path=None): | |
verify_artifact_path(artifact_path) | |
# NOTE: The artifact_path is expected to be in posix format. | |
# Posix paths work fine on windows but just in case we normalize it here. | |
if artifact_path: | |
artifact_path = os.path.normpath(artifact_path) | |
artifact_dir = ( | |
os.path.join(self.artifact_dir, artifact_path) if artifact_path else self.artifact_dir | |
) | |
if not os.path.exists(artifact_dir): | |
mkdir(artifact_dir) | |
try: | |
shutil.copyfile(local_file, os.path.join(artifact_dir, os.path.basename(local_file))) | |
except shutil.SameFileError: | |
pass | |
def _is_directory(self, artifact_path): | |
# NOTE: The path is expected to be in posix format. | |
# Posix paths work fine on windows but just in case we normalize it here. | |
path = os.path.normpath(artifact_path) if artifact_path else "" | |
list_dir = os.path.join(self.artifact_dir, path) if path else self.artifact_dir | |
return os.path.isdir(list_dir) | |
def log_artifacts(self, local_dir, artifact_path=None): | |
verify_artifact_path(artifact_path) | |
# NOTE: The artifact_path is expected to be in posix format. | |
# Posix paths work fine on windows but just in case we normalize it here. | |
if artifact_path: | |
artifact_path = os.path.normpath(artifact_path) | |
artifact_dir = ( | |
os.path.join(self.artifact_dir, artifact_path) if artifact_path else self.artifact_dir | |
) | |
if not os.path.exists(artifact_dir): | |
mkdir(artifact_dir) | |
shutil.copytree(src=local_dir, dst=artifact_dir, dirs_exist_ok=True) | |
def download_artifacts(self, artifact_path, dst_path=None): | |
""" | |
Artifacts tracked by ``LocalArtifactRepository`` already exist on the local filesystem. | |
If ``dst_path`` is ``None``, the absolute filesystem path of the specified artifact is | |
returned. If ``dst_path`` is not ``None``, the local artifact is copied to ``dst_path``. | |
:param artifact_path: Relative source path to the desired artifacts. | |
: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 absolute path of the local artifact will be returned. | |
:return: Absolute path of the local filesystem location containing the desired artifacts. | |
""" | |
if dst_path: | |
return super().download_artifacts(artifact_path, dst_path) | |
# NOTE: The artifact_path is expected to be in posix format. | |
# Posix paths work fine on windows but just in case we normalize it here. | |
local_artifact_path = os.path.join(self.artifact_dir, os.path.normpath(artifact_path)) | |
if not os.path.exists(local_artifact_path): | |
raise OSError(f"No such file or directory: '{local_artifact_path}'") | |
return os.path.abspath(local_artifact_path) | |
def list_artifacts(self, path=None): | |
# NOTE: The path is expected to be in posix format. | |
# Posix paths work fine on windows but just in case we normalize it here. | |
if path: | |
path = os.path.normpath(path) | |
list_dir = os.path.join(self.artifact_dir, path) if path else self.artifact_dir | |
if os.path.isdir(list_dir): | |
artifact_files = list_all(list_dir, full_path=True) | |
infos = [ | |
get_file_info( | |
f, relative_path_to_artifact_path(os.path.relpath(f, self.artifact_dir)) | |
) | |
for f in artifact_files | |
] | |
return sorted(infos, key=lambda f: f.path) | |
else: | |
return [] | |
def _download_file(self, remote_file_path, local_path): | |
# NOTE: The remote_file_path is expected to be in posix format. | |
# Posix paths work fine on windows but just in case we normalize it here. | |
remote_file_path = os.path.join(self.artifact_dir, os.path.normpath(remote_file_path)) | |
shutil.copyfile(remote_file_path, local_path) | |
def delete_artifacts(self, artifact_path=None): | |
artifact_path = local_file_uri_to_path( | |
os.path.join(self._artifact_dir, artifact_path) if artifact_path else self._artifact_dir | |
) | |
if os.path.exists(artifact_path): | |
shutil.rmtree(artifact_path) |