mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-04 15:28:27 +01:00
+6
-7
@@ -10,12 +10,6 @@ from funcy import cached_property
|
||||
|
||||
from dvc.scheme import Schemes
|
||||
|
||||
try:
|
||||
from azure.storage.blob import BlockBlobService, BlobPermissions
|
||||
from azure.common import AzureMissingResourceHttpError
|
||||
except ImportError:
|
||||
BlockBlobService = None
|
||||
|
||||
from dvc.utils.compat import urlparse
|
||||
from dvc.progress import Tqdm
|
||||
from dvc.config import Config
|
||||
@@ -35,7 +29,7 @@ class RemoteAZURE(RemoteBASE):
|
||||
r"(ContainerName=(?P<container_name>[^;]+);?)?"
|
||||
r"(?P<connection_string>.+)?)?)$"
|
||||
)
|
||||
REQUIRES = {"azure-storage-blob": BlockBlobService}
|
||||
REQUIRES = {"azure-storage-blob": "azure.storage.blob"}
|
||||
PARAM_CHECKSUM = "etag"
|
||||
COPY_POLL_SECONDS = 5
|
||||
|
||||
@@ -72,6 +66,9 @@ class RemoteAZURE(RemoteBASE):
|
||||
|
||||
@cached_property
|
||||
def blob_service(self):
|
||||
from azure.storage.blob import BlockBlobService
|
||||
from azure.common import AzureMissingResourceHttpError
|
||||
|
||||
logger.debug("URL {}".format(self.path_info))
|
||||
logger.debug("Connection string {}".format(self.connection_string))
|
||||
blob_service = BlockBlobService(
|
||||
@@ -139,6 +136,8 @@ class RemoteAZURE(RemoteBASE):
|
||||
return any(path_info.path == path for path in paths)
|
||||
|
||||
def _generate_download_url(self, path_info, expires=3600):
|
||||
from azure.storage.blob import BlobPermissions
|
||||
|
||||
expires_at = datetime.utcnow() + timedelta(seconds=expires)
|
||||
|
||||
sas_token = self.blob_service.generate_blob_shared_access_signature(
|
||||
|
||||
+39
-25
@@ -86,31 +86,8 @@ class RemoteBASE(object):
|
||||
|
||||
def __init__(self, repo, config):
|
||||
self.repo = repo
|
||||
deps_ok = all(self.REQUIRES.values())
|
||||
if not deps_ok:
|
||||
missing = [k for k, v in self.REQUIRES.items() if v is None]
|
||||
url = config.get(
|
||||
Config.SECTION_REMOTE_URL, "{}://".format(self.scheme)
|
||||
)
|
||||
msg = (
|
||||
"URL '{}' is supported but requires these missing "
|
||||
"dependencies: {}. If you have installed dvc using pip, "
|
||||
"choose one of these options to proceed: \n"
|
||||
"\n"
|
||||
" 1) Install specific missing dependencies:\n"
|
||||
" pip install {}\n"
|
||||
" 2) Install dvc package that includes those missing "
|
||||
"dependencies: \n"
|
||||
" pip install 'dvc[{}]'\n"
|
||||
" 3) Install dvc package with all possible "
|
||||
"dependencies included: \n"
|
||||
" pip install 'dvc[all]'\n"
|
||||
"\n"
|
||||
"If you have installed dvc from a binary package and you "
|
||||
"are still seeing this message, please report it to us "
|
||||
"using https://github.com/iterative/dvc/issues. Thank you!"
|
||||
).format(url, missing, " ".join(missing), self.scheme)
|
||||
raise RemoteMissingDepsError(msg)
|
||||
|
||||
self._check_requires(config)
|
||||
|
||||
core = config.get(Config.SECTION_CORE, {})
|
||||
self.checksum_jobs = core.get(
|
||||
@@ -130,6 +107,43 @@ class RemoteBASE(object):
|
||||
self.cache_types = copy(self.DEFAULT_CACHE_TYPES)
|
||||
self.cache_type_confirmed = False
|
||||
|
||||
def _check_requires(self, config):
|
||||
import importlib
|
||||
|
||||
missing = []
|
||||
|
||||
for package, module in self.REQUIRES.items():
|
||||
try:
|
||||
importlib.import_module(module)
|
||||
except ImportError:
|
||||
missing.append(package)
|
||||
|
||||
if not missing:
|
||||
return
|
||||
|
||||
url = config.get(
|
||||
Config.SECTION_REMOTE_URL, "{}://".format(self.scheme)
|
||||
)
|
||||
msg = (
|
||||
"URL '{}' is supported but requires these missing "
|
||||
"dependencies: {}. If you have installed dvc using pip, "
|
||||
"choose one of these options to proceed: \n"
|
||||
"\n"
|
||||
" 1) Install specific missing dependencies:\n"
|
||||
" pip install {}\n"
|
||||
" 2) Install dvc package that includes those missing "
|
||||
"dependencies: \n"
|
||||
" pip install 'dvc[{}]'\n"
|
||||
" 3) Install dvc package with all possible "
|
||||
"dependencies included: \n"
|
||||
" pip install 'dvc[all]'\n"
|
||||
"\n"
|
||||
"If you have installed dvc from a binary package and you "
|
||||
"are still seeing this message, please report it to us "
|
||||
"using https://github.com/iterative/dvc/issues. Thank you!"
|
||||
).format(url, missing, " ".join(missing), self.scheme)
|
||||
raise RemoteMissingDepsError(msg)
|
||||
|
||||
def __repr__(self):
|
||||
return "{class_name}: '{path_info}'".format(
|
||||
class_name=type(self).__name__,
|
||||
|
||||
+5
-8
@@ -5,11 +5,6 @@ from datetime import timedelta
|
||||
from funcy import cached_property
|
||||
from dvc.utils.compat import FileNotFoundError
|
||||
|
||||
try:
|
||||
from google.cloud import storage
|
||||
except ImportError:
|
||||
storage = None
|
||||
|
||||
from dvc.remote.base import RemoteBASE
|
||||
from dvc.config import Config
|
||||
from dvc.exceptions import DvcException
|
||||
@@ -22,7 +17,7 @@ logger = logging.getLogger(__name__)
|
||||
class RemoteGS(RemoteBASE):
|
||||
scheme = Schemes.GS
|
||||
path_cls = CloudURLInfo
|
||||
REQUIRES = {"google.cloud.storage": storage}
|
||||
REQUIRES = {"google-cloud-storage": "google.cloud.storage"}
|
||||
PARAM_CHECKSUM = "md5"
|
||||
|
||||
def __init__(self, repo, config):
|
||||
@@ -37,10 +32,12 @@ class RemoteGS(RemoteBASE):
|
||||
|
||||
@cached_property
|
||||
def gs(self):
|
||||
from google.cloud.storage import Client
|
||||
|
||||
return (
|
||||
storage.Client.from_service_account_json(self.credentialpath)
|
||||
Client.from_service_account_json(self.credentialpath)
|
||||
if self.credentialpath
|
||||
else storage.Client(self.projectname)
|
||||
else Client(self.projectname)
|
||||
)
|
||||
|
||||
def get_file_checksum(self, path_info):
|
||||
|
||||
+4
-8
@@ -9,11 +9,6 @@ import logging
|
||||
from subprocess import Popen, PIPE
|
||||
from contextlib import contextmanager, closing
|
||||
|
||||
try:
|
||||
import pyarrow
|
||||
except ImportError:
|
||||
pyarrow = None
|
||||
|
||||
from dvc.config import Config
|
||||
from dvc.scheme import Schemes
|
||||
|
||||
@@ -30,7 +25,7 @@ class RemoteHDFS(RemoteBASE):
|
||||
scheme = Schemes.HDFS
|
||||
REGEX = r"^hdfs://((?P<user>.*)@)?.*$"
|
||||
PARAM_CHECKSUM = "checksum"
|
||||
REQUIRES = {"pyarrow": pyarrow}
|
||||
REQUIRES = {"pyarrow": "pyarrow"}
|
||||
|
||||
def __init__(self, repo, config):
|
||||
super(RemoteHDFS, self).__init__(repo, config)
|
||||
@@ -55,8 +50,9 @@ class RemoteHDFS(RemoteBASE):
|
||||
path=parsed.path,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def hdfs(path_info):
|
||||
def hdfs(self, path_info):
|
||||
import pyarrow
|
||||
|
||||
return get_connection(
|
||||
pyarrow.hdfs.connect,
|
||||
path_info.host,
|
||||
|
||||
+5
-6
@@ -6,11 +6,6 @@ import logging
|
||||
|
||||
from dvc.scheme import Schemes
|
||||
|
||||
try:
|
||||
import oss2
|
||||
except ImportError:
|
||||
oss2 = None
|
||||
|
||||
from dvc.config import Config
|
||||
from dvc.remote.base import RemoteBASE
|
||||
from dvc.progress import Tqdm
|
||||
@@ -41,7 +36,7 @@ class RemoteOSS(RemoteBASE):
|
||||
|
||||
scheme = Schemes.OSS
|
||||
path_cls = CloudURLInfo
|
||||
REQUIRES = {"oss2": oss2}
|
||||
REQUIRES = {"oss2": "oss2"}
|
||||
PARAM_CHECKSUM = "etag"
|
||||
COPY_POLL_SECONDS = 5
|
||||
|
||||
@@ -71,6 +66,8 @@ class RemoteOSS(RemoteBASE):
|
||||
|
||||
@property
|
||||
def oss_service(self):
|
||||
import oss2
|
||||
|
||||
if self._bucket is None:
|
||||
logger.debug("URL {}".format(self.path_info))
|
||||
logger.debug("key id {}".format(self.key_id))
|
||||
@@ -98,6 +95,8 @@ class RemoteOSS(RemoteBASE):
|
||||
self.oss_service.delete_object(path_info.path)
|
||||
|
||||
def _list_paths(self, prefix):
|
||||
import oss2
|
||||
|
||||
for blob in oss2.ObjectIterator(self.oss_service, prefix=prefix):
|
||||
yield blob.key
|
||||
|
||||
|
||||
+3
-6
@@ -4,11 +4,6 @@ import os
|
||||
import logging
|
||||
from funcy import cached_property
|
||||
|
||||
try:
|
||||
import boto3
|
||||
except ImportError:
|
||||
boto3 = None
|
||||
|
||||
from dvc.progress import Tqdm
|
||||
from dvc.config import Config
|
||||
from dvc.remote.base import RemoteBASE
|
||||
@@ -22,7 +17,7 @@ logger = logging.getLogger(__name__)
|
||||
class RemoteS3(RemoteBASE):
|
||||
scheme = Schemes.S3
|
||||
path_cls = CloudURLInfo
|
||||
REQUIRES = {"boto3": boto3}
|
||||
REQUIRES = {"boto3": "boto3"}
|
||||
PARAM_CHECKSUM = "etag"
|
||||
|
||||
def __init__(self, repo, config):
|
||||
@@ -61,6 +56,8 @@ class RemoteS3(RemoteBASE):
|
||||
|
||||
@cached_property
|
||||
def s3(self):
|
||||
import boto3
|
||||
|
||||
session = boto3.session.Session(
|
||||
profile_name=self.profile, region_name=self.region
|
||||
)
|
||||
|
||||
@@ -10,11 +10,6 @@ import threading
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from contextlib import contextmanager, closing
|
||||
|
||||
try:
|
||||
import paramiko
|
||||
except ImportError:
|
||||
paramiko = None
|
||||
|
||||
import dvc.prompt as prompt
|
||||
from dvc.config import Config
|
||||
from dvc.utils import to_chunks
|
||||
@@ -33,7 +28,7 @@ saved_passwords_lock = threading.Lock()
|
||||
|
||||
class RemoteSSH(RemoteBASE):
|
||||
scheme = Schemes.SSH
|
||||
REQUIRES = {"paramiko": paramiko}
|
||||
REQUIRES = {"paramiko": "paramiko"}
|
||||
|
||||
JOBS = 4
|
||||
PARAM_CHECKSUM = "md5"
|
||||
@@ -93,6 +88,8 @@ class RemoteSSH(RemoteBASE):
|
||||
|
||||
@staticmethod
|
||||
def _load_user_ssh_config(hostname):
|
||||
import paramiko
|
||||
|
||||
user_config_file = RemoteSSH.ssh_config_filename()
|
||||
user_ssh_config = {}
|
||||
if hostname and os.path.exists(user_config_file):
|
||||
|
||||
@@ -10,8 +10,8 @@ class TestRemoteBASE(object):
|
||||
|
||||
class TestMissingDeps(TestCase, TestRemoteBASE):
|
||||
def test(self):
|
||||
REQUIRES = {"foo": None, "bar": None, "mock": mock}
|
||||
with mock.patch.object(self.REMOTE_CLS, "REQUIRES", REQUIRES):
|
||||
requires = {"missing": "missing"}
|
||||
with mock.patch.object(self.REMOTE_CLS, "REQUIRES", requires):
|
||||
with self.assertRaises(RemoteMissingDepsError):
|
||||
self.REMOTE_CLS(None, {})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user