We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
dvc status error with S3 output
DVC version 0.17.1, installed with pip.

Running `dvc status` shows
```
Failed to obtain data status: 'OutputS3' object has no attribute 'rel_path'
```
and nothing else (e.g. files that are not output to S3)

My .dvc/config:
```
['remote "data"']
url = s3://xxxxx/data
[core]
remote = data
['remote "s3cache"']
url = s3://xxxxx/cache
[cache]
s3 = s3cache
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `dvc/dependency/base.py`
Content:
```
1 import re
2 
3 from dvc.exceptions import DvcException
4 
5 
6 class DependencyError(DvcException):
7     def __init__(self, path, msg):
8         msg = 'Dependency \'{}\' error: {}'
9         super(DependencyError, self).__init__(msg.format(path, msg))
10 
11 
12 class DependencyDoesNotExistError(DependencyError):
13     def __init__(self, path):
14         msg = 'does not exist'
15         super(DependencyDoesNotExistError, self).__init__(path, msg)
16 
17 
18 class DependencyIsNotFileOrDirError(DependencyError):
19     def __init__(self, path):
20         msg = 'not a file or directory'
21         super(DependencyIsNotFileOrDirError, self).__init__(path, msg)
22 
23 
24 class DependencyBase(object):
25     REGEX = None
26 
27     PARAM_PATH = 'path'
28 
29     def __init__(self, stage, path):
30         self.stage = stage
31         self.project = stage.project
32         self.path = path
33 
34     @classmethod
35     def match(cls, url):
36         return re.match(cls.REGEX, url)
37 
38     def group(self, name):
39         match = self.match(self.path)
40         if not match:
41             return None
42         return match.group(name)
43 
44     @classmethod
45     def supported(cls, url):
46         return cls.match(url) is not None
47 
48     @property
49     def sep(self):
50         return '/'
51 
52     @property
53     def exists(self):
54         return self.remote.exists([self.path_info])
55 
56     def changed(self):
57         raise NotImplementedError
58 
59     def status(self):
60         if self.changed():
61             # FIXME better msgs
62             return {self.rel_path: 'changed'}
63         return {}
64 
65     def save(self):
66         raise NotImplementedError
67 
68     def dumpd(self):
69         return {self.PARAM_PATH: self.path}
70 
71     def download(self, to_info):
72         self.remote.download([self.path_info], [to_info])
73
```

Path: `dvc/config.py`
Content:
```
1 """
2 DVC config objects.
3 """
4 import os
5 import configobj
6 from schema import Schema, Optional, And, Use, Regex
7 
8 from dvc.exceptions import DvcException
9 
10 
11 class ConfigError(DvcException):
12     """ DVC config exception """
13     def __init__(self, ex=None):
14         super(ConfigError, self).__init__('Config file error', ex)
15 
16 
17 def supported_url(url):
18     from dvc.remote import supported_url as supported
19     return supported(url)
20 
21 
22 def supported_cache_type(types):
23     if isinstance(types, str):
24         types = [t.strip() for t in types.split(',')]
25     for t in types:
26         if t not in ['reflink', 'hardlink', 'symlink', 'copy']:
27             return False
28     return True
29 
30 
31 def supported_loglevel(level):
32     return level in ['info', 'debug', 'warning', 'error']
33 
34 
35 def supported_cloud(cloud):
36     return cloud in ['aws', 'gcp', 'local', '']
37 
38 
39 def is_bool(val):
40     return val.lower() in ['true', 'false']
41 
42 
43 def to_bool(val):
44     return val.lower() == 'true'
45 
46 
47 class Config(object):
48     CONFIG = 'config'
49     CONFIG_LOCAL = 'config.local'
50 
51     SECTION_CORE = 'core'
52     SECTION_CORE_LOGLEVEL = 'loglevel'
53     SECTION_CORE_LOGLEVEL_SCHEMA = And(Use(str.lower), supported_loglevel)
54     SECTION_CORE_REMOTE = 'remote'
55     SECTION_CORE_INTERACTIVE_SCHEMA = And(str, is_bool, Use(to_bool))
56     SECTION_CORE_INTERACTIVE = 'interactive'
57 
58     SECTION_CACHE = 'cache'
59     SECTION_CACHE_DIR = 'dir'
60     SECTION_CACHE_TYPE = 'type'
61     SECTION_CACHE_TYPE_SCHEMA = supported_cache_type
62     SECTION_CACHE_LOCAL = 'local'
63     SECTION_CACHE_S3 = 's3'
64     SECTION_CACHE_GS = 'gs'
65     SECTION_CACHE_SSH = 'ssh'
66     SECTION_CACHE_HDFS = 'hdfs'
67     SECTION_CACHE_AZURE = 'azure'
68     SECTION_CACHE_SCHEMA = {
69         Optional(SECTION_CACHE_LOCAL): str,
70         Optional(SECTION_CACHE_S3): str,
71         Optional(SECTION_CACHE_GS): str,
72         Optional(SECTION_CACHE_HDFS): str,
73         Optional(SECTION_CACHE_SSH): str,
74         Optional(SECTION_CACHE_AZURE): str,
75 
76         # backward compatibility
77         Optional(SECTION_CACHE_DIR, default='cache'): str,
78         Optional(SECTION_CACHE_TYPE, default=None): SECTION_CACHE_TYPE_SCHEMA,
79     }
80 
81     # backward compatibility
82     SECTION_CORE_CLOUD = 'cloud'
83     SECTION_CORE_CLOUD_SCHEMA = And(Use(str.lower), supported_cloud)
84     SECTION_CORE_STORAGEPATH = 'storagepath'
85 
86     SECTION_CORE_SCHEMA = {
87         Optional(SECTION_CORE_LOGLEVEL,
88                  default='info'): And(str, Use(str.lower),
89                                       SECTION_CORE_LOGLEVEL_SCHEMA),
90         Optional(SECTION_CORE_REMOTE, default=''): And(str, Use(str.lower)),
91         Optional(SECTION_CORE_INTERACTIVE,
92                  default=False): SECTION_CORE_INTERACTIVE_SCHEMA,
93 
94         # backward compatibility
95         Optional(SECTION_CORE_CLOUD, default=''): SECTION_CORE_CLOUD_SCHEMA,
96         Optional(SECTION_CORE_STORAGEPATH, default=''): str,
97     }
98 
99     # backward compatibility
100     SECTION_AWS = 'aws'
101     SECTION_AWS_STORAGEPATH = 'storagepath'
102     SECTION_AWS_CREDENTIALPATH = 'credentialpath'
103     SECTION_AWS_ENDPOINT_URL = 'endpointurl'
104     SECTION_AWS_REGION = 'region'
105     SECTION_AWS_PROFILE = 'profile'
106     SECTION_AWS_SCHEMA = {
107         SECTION_AWS_STORAGEPATH: str,
108         Optional(SECTION_AWS_REGION): str,
109         Optional(SECTION_AWS_PROFILE, default='default'): str,
110         Optional(SECTION_AWS_CREDENTIALPATH, default=''): str,
111         Optional(SECTION_AWS_ENDPOINT_URL, default=None): str,
112     }
113 
114     # backward compatibility
115     SECTION_GCP = 'gcp'
116     SECTION_GCP_STORAGEPATH = SECTION_AWS_STORAGEPATH
117     SECTION_GCP_PROJECTNAME = 'projectname'
118     SECTION_GCP_SCHEMA = {
119         SECTION_GCP_STORAGEPATH: str,
120         Optional(SECTION_GCP_PROJECTNAME): str,
121     }
122 
123     # backward compatibility
124     SECTION_LOCAL = 'local'
125     SECTION_LOCAL_STORAGEPATH = SECTION_AWS_STORAGEPATH
126     SECTION_LOCAL_SCHEMA = {
127         SECTION_LOCAL_STORAGEPATH: str,
128     }
129 
130     SECTION_REMOTE_REGEX = r'^\s*remote\s*"(?P<name>.*)"\s*$'
131     SECTION_REMOTE_FMT = 'remote "{}"'
132     SECTION_REMOTE_URL = 'url'
133     SECTION_REMOTE_USER = 'user'
134     SECTION_REMOTE_SCHEMA = {
135         SECTION_REMOTE_URL: And(supported_url, error="Unsupported URL"),
136         Optional(SECTION_AWS_REGION): str,
137         Optional(SECTION_AWS_PROFILE, default='default'): str,
138         Optional(SECTION_AWS_CREDENTIALPATH, default=''): str,
139         Optional(SECTION_AWS_ENDPOINT_URL, default=None): str,
140         Optional(SECTION_GCP_PROJECTNAME): str,
141         Optional(SECTION_CACHE_TYPE): SECTION_CACHE_TYPE_SCHEMA,
142         Optional(SECTION_REMOTE_USER): str,
143     }
144 
145     SCHEMA = {
146         Optional(SECTION_CORE, default={}): SECTION_CORE_SCHEMA,
147         Optional(Regex(SECTION_REMOTE_REGEX)): SECTION_REMOTE_SCHEMA,
148         Optional(SECTION_CACHE, default={}): SECTION_CACHE_SCHEMA,
149 
150         # backward compatibility
151         Optional(SECTION_AWS, default={}): SECTION_AWS_SCHEMA,
152         Optional(SECTION_GCP, default={}): SECTION_GCP_SCHEMA,
153         Optional(SECTION_LOCAL, default={}): SECTION_LOCAL_SCHEMA,
154     }
155 
156     def __init__(self, dvc_dir):
157         self.dvc_dir = os.path.abspath(os.path.realpath(dvc_dir))
158         self.config_file = os.path.join(dvc_dir, self.CONFIG)
159         self.config_local_file = os.path.join(dvc_dir, self.CONFIG_LOCAL)
160 
161         try:
162             self._config = configobj.ConfigObj(self.config_file)
163             local = configobj.ConfigObj(self.config_local_file)
164 
165             # NOTE: schema doesn't support ConfigObj.Section validation, so we
166             # need to convert our config to dict before passing it to
167             self._config = self._lower(self._config)
168             local = self._lower(local)
169             self._config.update(local)
170 
171             self._config = Schema(self.SCHEMA).validate(self._config)
172 
173             # NOTE: now converting back to ConfigObj
174             self._config = configobj.ConfigObj(self._config,
175                                                write_empty_values=True)
176             self._config.filename = self.config_file
177         except Exception as ex:
178             raise ConfigError(ex)
179 
180     @staticmethod
181     def _lower(config):
182         new_config = {}
183         for s_key, s_value in config.items():
184             new_s = {}
185             for key, value in s_value.items():
186                 new_s[key.lower()] = value
187             new_config[s_key.lower()] = new_s
188         return new_config
189 
190     @staticmethod
191     def init(dvc_dir):
192         config_file = os.path.join(dvc_dir, Config.CONFIG)
193         open(config_file, 'w+').close()
194         return Config(dvc_dir)
195
```
--- 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/dvc/config.py b/dvc/config.py
--- a/dvc/config.py
+++ b/dvc/config.py
@@ -10,8 +10,9 @@
 
 class ConfigError(DvcException):
     """ DVC config exception """
-    def __init__(self, ex=None):
-        super(ConfigError, self).__init__('Config file error', ex)
+    def __init__(self, msg, ex=None):
+        super(ConfigError, self).__init__('Config file error: {}'.format(msg),
+                                          ex)
 
 
 def supported_url(url):
diff --git a/dvc/dependency/base.py b/dvc/dependency/base.py
--- a/dvc/dependency/base.py
+++ b/dvc/dependency/base.py
@@ -59,7 +59,11 @@
     def status(self):
         if self.changed():
             # FIXME better msgs
-            return {self.rel_path: 'changed'}
+            if self.path_info['scheme'] == 'local':
+                p = self.rel_path
+            else:
+                p = self.path
+            return {p: 'changed'}
         return {}
 
     def save(self):

{"golden_diff": "diff --git a/dvc/config.py b/dvc/config.py\n--- a/dvc/config.py\n+++ b/dvc/config.py\n@@ -10,8 +10,9 @@\n \n class ConfigError(DvcException):\n     \"\"\" DVC config exception \"\"\"\n-    def __init__(self, ex=None):\n-        super(ConfigError, self).__init__('Config file error', ex)\n+    def __init__(self, msg, ex=None):\n+        super(ConfigError, self).__init__('Config file error: {}'.format(msg),\n+                                          ex)\n \n \n def supported_url(url):\ndiff --git a/dvc/dependency/base.py b/dvc/dependency/base.py\n--- a/dvc/dependency/base.py\n+++ b/dvc/dependency/base.py\n@@ -59,7 +59,11 @@\n     def status(self):\n         if self.changed():\n             # FIXME better msgs\n-            return {self.rel_path: 'changed'}\n+            if self.path_info['scheme'] == 'local':\n+                p = self.rel_path\n+            else:\n+                p = self.path\n+            return {p: 'changed'}\n         return {}\n \n     def save(self):\n", "issue": "dvc status error with S3 output\nDVC version 0.17.1, installed with pip.\r\n\r\nRunning `dvc status` shows\r\n```\r\nFailed to obtain data status: 'OutputS3' object has no attribute 'rel_path'\r\n```\r\nand nothing else (e.g. files that are not output to S3)\r\n\r\nMy .dvc/config:\r\n```\r\n['remote \"data\"']\r\nurl = s3://xxxxx/data\r\n[core]\r\nremote = data\r\n['remote \"s3cache\"']\r\nurl = s3://xxxxx/cache\r\n[cache]\r\ns3 = s3cache\r\n```\n", "before_files": [{"content": "import re\n\nfrom dvc.exceptions import DvcException\n\n\nclass DependencyError(DvcException):\n    def __init__(self, path, msg):\n        msg = 'Dependency \\'{}\\' error: {}'\n        super(DependencyError, self).__init__(msg.format(path, msg))\n\n\nclass DependencyDoesNotExistError(DependencyError):\n    def __init__(self, path):\n        msg = 'does not exist'\n        super(DependencyDoesNotExistError, self).__init__(path, msg)\n\n\nclass DependencyIsNotFileOrDirError(DependencyError):\n    def __init__(self, path):\n        msg = 'not a file or directory'\n        super(DependencyIsNotFileOrDirError, self).__init__(path, msg)\n\n\nclass DependencyBase(object):\n    REGEX = None\n\n    PARAM_PATH = 'path'\n\n    def __init__(self, stage, path):\n        self.stage = stage\n        self.project = stage.project\n        self.path = path\n\n    @classmethod\n    def match(cls, url):\n        return re.match(cls.REGEX, url)\n\n    def group(self, name):\n        match = self.match(self.path)\n        if not match:\n            return None\n        return match.group(name)\n\n    @classmethod\n    def supported(cls, url):\n        return cls.match(url) is not None\n\n    @property\n    def sep(self):\n        return '/'\n\n    @property\n    def exists(self):\n        return self.remote.exists([self.path_info])\n\n    def changed(self):\n        raise NotImplementedError\n\n    def status(self):\n        if self.changed():\n            # FIXME better msgs\n            return {self.rel_path: 'changed'}\n        return {}\n\n    def save(self):\n        raise NotImplementedError\n\n    def dumpd(self):\n        return {self.PARAM_PATH: self.path}\n\n    def download(self, to_info):\n        self.remote.download([self.path_info], [to_info])\n", "path": "dvc/dependency/base.py"}, {"content": "\"\"\"\nDVC config objects.\n\"\"\"\nimport os\nimport configobj\nfrom schema import Schema, Optional, And, Use, Regex\n\nfrom dvc.exceptions import DvcException\n\n\nclass ConfigError(DvcException):\n    \"\"\" DVC config exception \"\"\"\n    def __init__(self, ex=None):\n        super(ConfigError, self).__init__('Config file error', ex)\n\n\ndef supported_url(url):\n    from dvc.remote import supported_url as supported\n    return supported(url)\n\n\ndef supported_cache_type(types):\n    if isinstance(types, str):\n        types = [t.strip() for t in types.split(',')]\n    for t in types:\n        if t not in ['reflink', 'hardlink', 'symlink', 'copy']:\n            return False\n    return True\n\n\ndef supported_loglevel(level):\n    return level in ['info', 'debug', 'warning', 'error']\n\n\ndef supported_cloud(cloud):\n    return cloud in ['aws', 'gcp', 'local', '']\n\n\ndef is_bool(val):\n    return val.lower() in ['true', 'false']\n\n\ndef to_bool(val):\n    return val.lower() == 'true'\n\n\nclass Config(object):\n    CONFIG = 'config'\n    CONFIG_LOCAL = 'config.local'\n\n    SECTION_CORE = 'core'\n    SECTION_CORE_LOGLEVEL = 'loglevel'\n    SECTION_CORE_LOGLEVEL_SCHEMA = And(Use(str.lower), supported_loglevel)\n    SECTION_CORE_REMOTE = 'remote'\n    SECTION_CORE_INTERACTIVE_SCHEMA = And(str, is_bool, Use(to_bool))\n    SECTION_CORE_INTERACTIVE = 'interactive'\n\n    SECTION_CACHE = 'cache'\n    SECTION_CACHE_DIR = 'dir'\n    SECTION_CACHE_TYPE = 'type'\n    SECTION_CACHE_TYPE_SCHEMA = supported_cache_type\n    SECTION_CACHE_LOCAL = 'local'\n    SECTION_CACHE_S3 = 's3'\n    SECTION_CACHE_GS = 'gs'\n    SECTION_CACHE_SSH = 'ssh'\n    SECTION_CACHE_HDFS = 'hdfs'\n    SECTION_CACHE_AZURE = 'azure'\n    SECTION_CACHE_SCHEMA = {\n        Optional(SECTION_CACHE_LOCAL): str,\n        Optional(SECTION_CACHE_S3): str,\n        Optional(SECTION_CACHE_GS): str,\n        Optional(SECTION_CACHE_HDFS): str,\n        Optional(SECTION_CACHE_SSH): str,\n        Optional(SECTION_CACHE_AZURE): str,\n\n        # backward compatibility\n        Optional(SECTION_CACHE_DIR, default='cache'): str,\n        Optional(SECTION_CACHE_TYPE, default=None): SECTION_CACHE_TYPE_SCHEMA,\n    }\n\n    # backward compatibility\n    SECTION_CORE_CLOUD = 'cloud'\n    SECTION_CORE_CLOUD_SCHEMA = And(Use(str.lower), supported_cloud)\n    SECTION_CORE_STORAGEPATH = 'storagepath'\n\n    SECTION_CORE_SCHEMA = {\n        Optional(SECTION_CORE_LOGLEVEL,\n                 default='info'): And(str, Use(str.lower),\n                                      SECTION_CORE_LOGLEVEL_SCHEMA),\n        Optional(SECTION_CORE_REMOTE, default=''): And(str, Use(str.lower)),\n        Optional(SECTION_CORE_INTERACTIVE,\n                 default=False): SECTION_CORE_INTERACTIVE_SCHEMA,\n\n        # backward compatibility\n        Optional(SECTION_CORE_CLOUD, default=''): SECTION_CORE_CLOUD_SCHEMA,\n        Optional(SECTION_CORE_STORAGEPATH, default=''): str,\n    }\n\n    # backward compatibility\n    SECTION_AWS = 'aws'\n    SECTION_AWS_STORAGEPATH = 'storagepath'\n    SECTION_AWS_CREDENTIALPATH = 'credentialpath'\n    SECTION_AWS_ENDPOINT_URL = 'endpointurl'\n    SECTION_AWS_REGION = 'region'\n    SECTION_AWS_PROFILE = 'profile'\n    SECTION_AWS_SCHEMA = {\n        SECTION_AWS_STORAGEPATH: str,\n        Optional(SECTION_AWS_REGION): str,\n        Optional(SECTION_AWS_PROFILE, default='default'): str,\n        Optional(SECTION_AWS_CREDENTIALPATH, default=''): str,\n        Optional(SECTION_AWS_ENDPOINT_URL, default=None): str,\n    }\n\n    # backward compatibility\n    SECTION_GCP = 'gcp'\n    SECTION_GCP_STORAGEPATH = SECTION_AWS_STORAGEPATH\n    SECTION_GCP_PROJECTNAME = 'projectname'\n    SECTION_GCP_SCHEMA = {\n        SECTION_GCP_STORAGEPATH: str,\n        Optional(SECTION_GCP_PROJECTNAME): str,\n    }\n\n    # backward compatibility\n    SECTION_LOCAL = 'local'\n    SECTION_LOCAL_STORAGEPATH = SECTION_AWS_STORAGEPATH\n    SECTION_LOCAL_SCHEMA = {\n        SECTION_LOCAL_STORAGEPATH: str,\n    }\n\n    SECTION_REMOTE_REGEX = r'^\\s*remote\\s*\"(?P<name>.*)\"\\s*$'\n    SECTION_REMOTE_FMT = 'remote \"{}\"'\n    SECTION_REMOTE_URL = 'url'\n    SECTION_REMOTE_USER = 'user'\n    SECTION_REMOTE_SCHEMA = {\n        SECTION_REMOTE_URL: And(supported_url, error=\"Unsupported URL\"),\n        Optional(SECTION_AWS_REGION): str,\n        Optional(SECTION_AWS_PROFILE, default='default'): str,\n        Optional(SECTION_AWS_CREDENTIALPATH, default=''): str,\n        Optional(SECTION_AWS_ENDPOINT_URL, default=None): str,\n        Optional(SECTION_GCP_PROJECTNAME): str,\n        Optional(SECTION_CACHE_TYPE): SECTION_CACHE_TYPE_SCHEMA,\n        Optional(SECTION_REMOTE_USER): str,\n    }\n\n    SCHEMA = {\n        Optional(SECTION_CORE, default={}): SECTION_CORE_SCHEMA,\n        Optional(Regex(SECTION_REMOTE_REGEX)): SECTION_REMOTE_SCHEMA,\n        Optional(SECTION_CACHE, default={}): SECTION_CACHE_SCHEMA,\n\n        # backward compatibility\n        Optional(SECTION_AWS, default={}): SECTION_AWS_SCHEMA,\n        Optional(SECTION_GCP, default={}): SECTION_GCP_SCHEMA,\n        Optional(SECTION_LOCAL, default={}): SECTION_LOCAL_SCHEMA,\n    }\n\n    def __init__(self, dvc_dir):\n        self.dvc_dir = os.path.abspath(os.path.realpath(dvc_dir))\n        self.config_file = os.path.join(dvc_dir, self.CONFIG)\n        self.config_local_file = os.path.join(dvc_dir, self.CONFIG_LOCAL)\n\n        try:\n            self._config = configobj.ConfigObj(self.config_file)\n            local = configobj.ConfigObj(self.config_local_file)\n\n            # NOTE: schema doesn't support ConfigObj.Section validation, so we\n            # need to convert our config to dict before passing it to\n            self._config = self._lower(self._config)\n            local = self._lower(local)\n            self._config.update(local)\n\n            self._config = Schema(self.SCHEMA).validate(self._config)\n\n            # NOTE: now converting back to ConfigObj\n            self._config = configobj.ConfigObj(self._config,\n                                               write_empty_values=True)\n            self._config.filename = self.config_file\n        except Exception as ex:\n            raise ConfigError(ex)\n\n    @staticmethod\n    def _lower(config):\n        new_config = {}\n        for s_key, s_value in config.items():\n            new_s = {}\n            for key, value in s_value.items():\n                new_s[key.lower()] = value\n            new_config[s_key.lower()] = new_s\n        return new_config\n\n    @staticmethod\n    def init(dvc_dir):\n        config_file = os.path.join(dvc_dir, Config.CONFIG)\n        open(config_file, 'w+').close()\n        return Config(dvc_dir)\n", "path": "dvc/config.py"}], "after_files": [{"content": "import re\n\nfrom dvc.exceptions import DvcException\n\n\nclass DependencyError(DvcException):\n    def __init__(self, path, msg):\n        msg = 'Dependency \\'{}\\' error: {}'\n        super(DependencyError, self).__init__(msg.format(path, msg))\n\n\nclass DependencyDoesNotExistError(DependencyError):\n    def __init__(self, path):\n        msg = 'does not exist'\n        super(DependencyDoesNotExistError, self).__init__(path, msg)\n\n\nclass DependencyIsNotFileOrDirError(DependencyError):\n    def __init__(self, path):\n        msg = 'not a file or directory'\n        super(DependencyIsNotFileOrDirError, self).__init__(path, msg)\n\n\nclass DependencyBase(object):\n    REGEX = None\n\n    PARAM_PATH = 'path'\n\n    def __init__(self, stage, path):\n        self.stage = stage\n        self.project = stage.project\n        self.path = path\n\n    @classmethod\n    def match(cls, url):\n        return re.match(cls.REGEX, url)\n\n    def group(self, name):\n        match = self.match(self.path)\n        if not match:\n            return None\n        return match.group(name)\n\n    @classmethod\n    def supported(cls, url):\n        return cls.match(url) is not None\n\n    @property\n    def sep(self):\n        return '/'\n\n    @property\n    def exists(self):\n        return self.remote.exists([self.path_info])\n\n    def changed(self):\n        raise NotImplementedError\n\n    def status(self):\n        if self.changed():\n            # FIXME better msgs\n            if self.path_info['scheme'] == 'local':\n                p = self.rel_path\n            else:\n                p = self.path\n            return {p: 'changed'}\n        return {}\n\n    def save(self):\n        raise NotImplementedError\n\n    def dumpd(self):\n        return {self.PARAM_PATH: self.path}\n\n    def download(self, to_info):\n        self.remote.download([self.path_info], [to_info])\n", "path": "dvc/dependency/base.py"}, {"content": "\"\"\"\nDVC config objects.\n\"\"\"\nimport os\nimport configobj\nfrom schema import Schema, Optional, And, Use, Regex\n\nfrom dvc.exceptions import DvcException\n\n\nclass ConfigError(DvcException):\n    \"\"\" DVC config exception \"\"\"\n    def __init__(self, msg, ex=None):\n        super(ConfigError, self).__init__('Config file error: {}'.format(msg),\n                                          ex)\n\n\ndef supported_url(url):\n    from dvc.remote import supported_url as supported\n    return supported(url)\n\n\ndef supported_cache_type(types):\n    if isinstance(types, str):\n        types = [t.strip() for t in types.split(',')]\n    for t in types:\n        if t not in ['reflink', 'hardlink', 'symlink', 'copy']:\n            return False\n    return True\n\n\ndef supported_loglevel(level):\n    return level in ['info', 'debug', 'warning', 'error']\n\n\ndef supported_cloud(cloud):\n    return cloud in ['aws', 'gcp', 'local', '']\n\n\ndef is_bool(val):\n    return val.lower() in ['true', 'false']\n\n\ndef to_bool(val):\n    return val.lower() == 'true'\n\n\nclass Config(object):\n    CONFIG = 'config'\n    CONFIG_LOCAL = 'config.local'\n\n    SECTION_CORE = 'core'\n    SECTION_CORE_LOGLEVEL = 'loglevel'\n    SECTION_CORE_LOGLEVEL_SCHEMA = And(Use(str.lower), supported_loglevel)\n    SECTION_CORE_REMOTE = 'remote'\n    SECTION_CORE_INTERACTIVE_SCHEMA = And(str, is_bool, Use(to_bool))\n    SECTION_CORE_INTERACTIVE = 'interactive'\n\n    SECTION_CACHE = 'cache'\n    SECTION_CACHE_DIR = 'dir'\n    SECTION_CACHE_TYPE = 'type'\n    SECTION_CACHE_TYPE_SCHEMA = supported_cache_type\n    SECTION_CACHE_LOCAL = 'local'\n    SECTION_CACHE_S3 = 's3'\n    SECTION_CACHE_GS = 'gs'\n    SECTION_CACHE_SSH = 'ssh'\n    SECTION_CACHE_HDFS = 'hdfs'\n    SECTION_CACHE_AZURE = 'azure'\n    SECTION_CACHE_SCHEMA = {\n        Optional(SECTION_CACHE_LOCAL): str,\n        Optional(SECTION_CACHE_S3): str,\n        Optional(SECTION_CACHE_GS): str,\n        Optional(SECTION_CACHE_HDFS): str,\n        Optional(SECTION_CACHE_SSH): str,\n        Optional(SECTION_CACHE_AZURE): str,\n\n        # backward compatibility\n        Optional(SECTION_CACHE_DIR, default='cache'): str,\n        Optional(SECTION_CACHE_TYPE, default=None): SECTION_CACHE_TYPE_SCHEMA,\n    }\n\n    # backward compatibility\n    SECTION_CORE_CLOUD = 'cloud'\n    SECTION_CORE_CLOUD_SCHEMA = And(Use(str.lower), supported_cloud)\n    SECTION_CORE_STORAGEPATH = 'storagepath'\n\n    SECTION_CORE_SCHEMA = {\n        Optional(SECTION_CORE_LOGLEVEL,\n                 default='info'): And(str, Use(str.lower),\n                                      SECTION_CORE_LOGLEVEL_SCHEMA),\n        Optional(SECTION_CORE_REMOTE, default=''): And(str, Use(str.lower)),\n        Optional(SECTION_CORE_INTERACTIVE,\n                 default=False): SECTION_CORE_INTERACTIVE_SCHEMA,\n\n        # backward compatibility\n        Optional(SECTION_CORE_CLOUD, default=''): SECTION_CORE_CLOUD_SCHEMA,\n        Optional(SECTION_CORE_STORAGEPATH, default=''): str,\n    }\n\n    # backward compatibility\n    SECTION_AWS = 'aws'\n    SECTION_AWS_STORAGEPATH = 'storagepath'\n    SECTION_AWS_CREDENTIALPATH = 'credentialpath'\n    SECTION_AWS_ENDPOINT_URL = 'endpointurl'\n    SECTION_AWS_REGION = 'region'\n    SECTION_AWS_PROFILE = 'profile'\n    SECTION_AWS_SCHEMA = {\n        SECTION_AWS_STORAGEPATH: str,\n        Optional(SECTION_AWS_REGION): str,\n        Optional(SECTION_AWS_PROFILE, default='default'): str,\n        Optional(SECTION_AWS_CREDENTIALPATH, default=''): str,\n        Optional(SECTION_AWS_ENDPOINT_URL, default=None): str,\n    }\n\n    # backward compatibility\n    SECTION_GCP = 'gcp'\n    SECTION_GCP_STORAGEPATH = SECTION_AWS_STORAGEPATH\n    SECTION_GCP_PROJECTNAME = 'projectname'\n    SECTION_GCP_SCHEMA = {\n        SECTION_GCP_STORAGEPATH: str,\n        Optional(SECTION_GCP_PROJECTNAME): str,\n    }\n\n    # backward compatibility\n    SECTION_LOCAL = 'local'\n    SECTION_LOCAL_STORAGEPATH = SECTION_AWS_STORAGEPATH\n    SECTION_LOCAL_SCHEMA = {\n        SECTION_LOCAL_STORAGEPATH: str,\n    }\n\n    SECTION_REMOTE_REGEX = r'^\\s*remote\\s*\"(?P<name>.*)\"\\s*$'\n    SECTION_REMOTE_FMT = 'remote \"{}\"'\n    SECTION_REMOTE_URL = 'url'\n    SECTION_REMOTE_USER = 'user'\n    SECTION_REMOTE_SCHEMA = {\n        SECTION_REMOTE_URL: And(supported_url, error=\"Unsupported URL\"),\n        Optional(SECTION_AWS_REGION): str,\n        Optional(SECTION_AWS_PROFILE, default='default'): str,\n        Optional(SECTION_AWS_CREDENTIALPATH, default=''): str,\n        Optional(SECTION_AWS_ENDPOINT_URL, default=None): str,\n        Optional(SECTION_GCP_PROJECTNAME): str,\n        Optional(SECTION_CACHE_TYPE): SECTION_CACHE_TYPE_SCHEMA,\n        Optional(SECTION_REMOTE_USER): str,\n    }\n\n    SCHEMA = {\n        Optional(SECTION_CORE, default={}): SECTION_CORE_SCHEMA,\n        Optional(Regex(SECTION_REMOTE_REGEX)): SECTION_REMOTE_SCHEMA,\n        Optional(SECTION_CACHE, default={}): SECTION_CACHE_SCHEMA,\n\n        # backward compatibility\n        Optional(SECTION_AWS, default={}): SECTION_AWS_SCHEMA,\n        Optional(SECTION_GCP, default={}): SECTION_GCP_SCHEMA,\n        Optional(SECTION_LOCAL, default={}): SECTION_LOCAL_SCHEMA,\n    }\n\n    def __init__(self, dvc_dir):\n        self.dvc_dir = os.path.abspath(os.path.realpath(dvc_dir))\n        self.config_file = os.path.join(dvc_dir, self.CONFIG)\n        self.config_local_file = os.path.join(dvc_dir, self.CONFIG_LOCAL)\n\n        try:\n            self._config = configobj.ConfigObj(self.config_file)\n            local = configobj.ConfigObj(self.config_local_file)\n\n            # NOTE: schema doesn't support ConfigObj.Section validation, so we\n            # need to convert our config to dict before passing it to\n            self._config = self._lower(self._config)\n            local = self._lower(local)\n            self._config.update(local)\n\n            self._config = Schema(self.SCHEMA).validate(self._config)\n\n            # NOTE: now converting back to ConfigObj\n            self._config = configobj.ConfigObj(self._config,\n                                               write_empty_values=True)\n            self._config.filename = self.config_file\n        except Exception as ex:\n            raise ConfigError(ex)\n\n    @staticmethod\n    def _lower(config):\n        new_config = {}\n        for s_key, s_value in config.items():\n            new_s = {}\n            for key, value in s_value.items():\n                new_s[key.lower()] = value\n            new_config[s_key.lower()] = new_s\n        return new_config\n\n    @staticmethod\n    def init(dvc_dir):\n        config_file = os.path.join(dvc_dir, Config.CONFIG)\n        open(config_file, 'w+').close()\n        return Config(dvc_dir)\n", "path": "dvc/config.py"}]}