We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
lock: improve error message when .dvc/lock is taken
https://github.com/iterative/dvc/pull/2519#discussion_r326844119

--- 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/lock.py`
Content:
```
1 """Manages dvc lock file."""
2 from __future__ import unicode_literals
3 
4 import hashlib
5 import os
6 import time
7 from datetime import timedelta
8 
9 from funcy.py3 import lkeep
10 
11 from dvc.exceptions import DvcException
12 from dvc.utils import makedirs
13 from dvc.utils.compat import is_py3
14 
15 
16 DEFAULT_TIMEOUT = 5
17 
18 
19 class LockError(DvcException):
20     """Thrown when unable to acquire the lock for dvc repo."""
21 
22 
23 if is_py3:
24     import flufl.lock
25 
26     class Lock(flufl.lock.Lock):
27         """Class for dvc repo lock.
28 
29         Args:
30             lockfile (str): the lock filename
31                 in.
32             tmp_dir (str): a directory to store claim files.
33         """
34 
35         def __init__(self, lockfile, tmp_dir=None):
36             import socket
37 
38             self._tmp_dir = tmp_dir
39             if self._tmp_dir is not None:
40                 makedirs(self._tmp_dir, exist_ok=True)
41 
42             # NOTE: this is basically Lock.__init__ copy-paste, except that
43             # instead of using `socket.getfqdn()` we use `socket.gethostname()`
44             # to speed this up. We've seen [1] `getfqdn()` take ~5sec to return
45             # anything, which is way too slow. `gethostname()` is actually a
46             # fallback for `getfqdn()` when it is not able to resolve a
47             # canonical hostname through network. The claimfile that uses
48             # `self._hostname` is still usable, as it uses `pid` and random
49             # number to generate the resulting lock file name, which is unique
50             # enough for our application.
51             #
52             # [1] https://github.com/iterative/dvc/issues/2582
53             self._hostname = socket.gethostname()
54 
55             self._lockfile = lockfile
56             self._lifetime = timedelta(days=365)  # Lock for good by default
57             self._separator = flufl.lock.SEP
58             self._set_claimfile()
59             self._owned = True
60             self._retry_errnos = []
61 
62         @property
63         def lockfile(self):
64             return self._lockfile
65 
66         @property
67         def files(self):
68             return lkeep([self._lockfile, self._tmp_dir])
69 
70         def lock(self):
71             try:
72                 super(Lock, self).lock(timedelta(seconds=DEFAULT_TIMEOUT))
73             except flufl.lock.TimeOutError:
74                 raise LockError(
75                     "cannot perform the cmd since DVC is busy and "
76                     "locked. Please retry the cmd later."
77                 )
78 
79         def _set_claimfile(self, pid=None):
80             super(Lock, self)._set_claimfile(pid)
81 
82             if self._tmp_dir is not None:
83                 # Under Windows file path length is limited so we hash it
84                 filename = hashlib.md5(self._claimfile.encode()).hexdigest()
85                 self._claimfile = os.path.join(
86                     self._tmp_dir, filename + ".lock"
87                 )
88 
89         # Fix for __del__ bug in flufl.lock [1] which is causing errors on
90         # Python shutdown [2].
91         # [1] https://gitlab.com/warsaw/flufl.lock/issues/7
92         # [2] https://github.com/iterative/dvc/issues/2573
93         def __del__(self):
94             try:
95                 if self._owned:
96                     self.finalize()
97             except ImportError:
98                 pass
99 
100 
101 else:
102     import zc.lockfile
103 
104     class Lock(object):
105         """Class for dvc repo lock.
106 
107         Uses zc.lockfile as backend.
108         """
109 
110         def __init__(self, lockfile, tmp_dir=None):
111             self.lockfile = lockfile
112             self._lock = None
113 
114         @property
115         def files(self):
116             return [self.lockfile]
117 
118         def _do_lock(self):
119             try:
120                 self._lock = zc.lockfile.LockFile(self.lockfile)
121             except zc.lockfile.LockError:
122                 raise LockError(
123                     "cannot perform the cmd since DVC is busy and "
124                     "locked. Please retry the cmd later."
125                 )
126 
127         def lock(self):
128             try:
129                 self._do_lock()
130                 return
131             except LockError:
132                 time.sleep(DEFAULT_TIMEOUT)
133 
134             self._do_lock()
135 
136         def unlock(self):
137             self._lock.close()
138             self._lock = None
139 
140         def __enter__(self):
141             self.lock()
142 
143         def __exit__(self, typ, value, tbck):
144             self.unlock()
145
```

Path: `dvc/main.py`
Content:
```
1 """Main entry point for dvc CLI."""
2 from __future__ import unicode_literals
3 
4 import logging
5 
6 from dvc.analytics import Analytics
7 from dvc.cli import parse_args
8 from dvc.config import ConfigError
9 from dvc.exceptions import DvcParserError
10 from dvc.exceptions import NotDvcRepoError
11 from dvc.external_repo import clean_repos
12 from dvc.lock import LockError
13 from dvc.logger import FOOTER
14 from dvc.remote.pool import close_pools
15 from dvc.utils.compat import is_py2
16 
17 
18 # Workaround for CPython bug. See [1] and [2] for more info.
19 # [1] https://github.com/aws/aws-cli/blob/1.16.277/awscli/clidriver.py#L55
20 # [2] https://bugs.python.org/issue29288
21 "".encode("idna")
22 
23 
24 logger = logging.getLogger("dvc")
25 
26 
27 def main(argv=None):
28     """Run dvc CLI command.
29 
30     Args:
31         argv: optional list of arguments to parse. sys.argv is used by default.
32 
33     Returns:
34         int: command's return code.
35     """
36     args = None
37     cmd = None
38 
39     outerLogLevel = logger.level
40     try:
41         args = parse_args(argv)
42 
43         if args.quiet:
44             logger.setLevel(logging.CRITICAL)
45 
46         elif args.verbose:
47             logger.setLevel(logging.DEBUG)
48 
49         cmd = args.func(args)
50         ret = cmd.run()
51     except LockError:
52         logger.exception("failed to lock before running a command")
53         ret = 250
54     except ConfigError:
55         logger.exception("configuration error")
56         ret = 251
57     except KeyboardInterrupt:
58         logger.exception("interrupted by the user")
59         ret = 252
60     except NotDvcRepoError:
61         logger.exception("")
62         ret = 253
63     except DvcParserError:
64         ret = 254
65     except Exception as exc:  # pylint: disable=broad-except
66         if isinstance(exc, UnicodeError) and is_py2:
67             logger.exception(
68                 "unicode is not supported in DVC for Python 2 "
69                 "(end-of-life January 1, 2020), please upgrade to Python 3"
70             )
71         else:
72             logger.exception("unexpected error")
73         ret = 255
74     finally:
75         logger.setLevel(outerLogLevel)
76 
77         # Python 2 fails to close these clean occasionally and users see
78         # weird error messages, so we do it manually
79         close_pools()
80 
81         # Remove cached repos in the end of the call, these are anonymous
82         # so won't be reused by any other subsequent run anyway.
83         clean_repos()
84 
85     if ret != 0:
86         logger.info(FOOTER)
87 
88     Analytics().send_cmd(cmd, args, ret)
89 
90     return ret
91
```
--- 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/lock.py b/dvc/lock.py
--- a/dvc/lock.py
+++ b/dvc/lock.py
@@ -15,6 +15,12 @@
 
 DEFAULT_TIMEOUT = 5
 
+FAILED_TO_LOCK_MESSAGE = (
+    "cannot perform the command because another DVC process seems to be "
+    "running on this project. If that is not the case, manually remove "
+    "`.dvc/lock` and try again."
+)
+
 
 class LockError(DvcException):
     """Thrown when unable to acquire the lock for dvc repo."""
@@ -71,10 +77,7 @@
             try:
                 super(Lock, self).lock(timedelta(seconds=DEFAULT_TIMEOUT))
             except flufl.lock.TimeOutError:
-                raise LockError(
-                    "cannot perform the cmd since DVC is busy and "
-                    "locked. Please retry the cmd later."
-                )
+                raise LockError(FAILED_TO_LOCK_MESSAGE)
 
         def _set_claimfile(self, pid=None):
             super(Lock, self)._set_claimfile(pid)
@@ -119,10 +122,7 @@
             try:
                 self._lock = zc.lockfile.LockFile(self.lockfile)
             except zc.lockfile.LockError:
-                raise LockError(
-                    "cannot perform the cmd since DVC is busy and "
-                    "locked. Please retry the cmd later."
-                )
+                raise LockError(FAILED_TO_LOCK_MESSAGE)
 
         def lock(self):
             try:
diff --git a/dvc/main.py b/dvc/main.py
--- a/dvc/main.py
+++ b/dvc/main.py
@@ -9,7 +9,6 @@
 from dvc.exceptions import DvcParserError
 from dvc.exceptions import NotDvcRepoError
 from dvc.external_repo import clean_repos
-from dvc.lock import LockError
 from dvc.logger import FOOTER
 from dvc.remote.pool import close_pools
 from dvc.utils.compat import is_py2
@@ -48,9 +47,6 @@
 
         cmd = args.func(args)
         ret = cmd.run()
-    except LockError:
-        logger.exception("failed to lock before running a command")
-        ret = 250
     except ConfigError:
         logger.exception("configuration error")
         ret = 251

{"golden_diff": "diff --git a/dvc/lock.py b/dvc/lock.py\n--- a/dvc/lock.py\n+++ b/dvc/lock.py\n@@ -15,6 +15,12 @@\n \n DEFAULT_TIMEOUT = 5\n \n+FAILED_TO_LOCK_MESSAGE = (\n+    \"cannot perform the command because another DVC process seems to be \"\n+    \"running on this project. If that is not the case, manually remove \"\n+    \"`.dvc/lock` and try again.\"\n+)\n+\n \n class LockError(DvcException):\n     \"\"\"Thrown when unable to acquire the lock for dvc repo.\"\"\"\n@@ -71,10 +77,7 @@\n             try:\n                 super(Lock, self).lock(timedelta(seconds=DEFAULT_TIMEOUT))\n             except flufl.lock.TimeOutError:\n-                raise LockError(\n-                    \"cannot perform the cmd since DVC is busy and \"\n-                    \"locked. Please retry the cmd later.\"\n-                )\n+                raise LockError(FAILED_TO_LOCK_MESSAGE)\n \n         def _set_claimfile(self, pid=None):\n             super(Lock, self)._set_claimfile(pid)\n@@ -119,10 +122,7 @@\n             try:\n                 self._lock = zc.lockfile.LockFile(self.lockfile)\n             except zc.lockfile.LockError:\n-                raise LockError(\n-                    \"cannot perform the cmd since DVC is busy and \"\n-                    \"locked. Please retry the cmd later.\"\n-                )\n+                raise LockError(FAILED_TO_LOCK_MESSAGE)\n \n         def lock(self):\n             try:\ndiff --git a/dvc/main.py b/dvc/main.py\n--- a/dvc/main.py\n+++ b/dvc/main.py\n@@ -9,7 +9,6 @@\n from dvc.exceptions import DvcParserError\n from dvc.exceptions import NotDvcRepoError\n from dvc.external_repo import clean_repos\n-from dvc.lock import LockError\n from dvc.logger import FOOTER\n from dvc.remote.pool import close_pools\n from dvc.utils.compat import is_py2\n@@ -48,9 +47,6 @@\n \n         cmd = args.func(args)\n         ret = cmd.run()\n-    except LockError:\n-        logger.exception(\"failed to lock before running a command\")\n-        ret = 250\n     except ConfigError:\n         logger.exception(\"configuration error\")\n         ret = 251\n", "issue": "lock: improve error message when .dvc/lock is taken\nhttps://github.com/iterative/dvc/pull/2519#discussion_r326844119\n", "before_files": [{"content": "\"\"\"Manages dvc lock file.\"\"\"\nfrom __future__ import unicode_literals\n\nimport hashlib\nimport os\nimport time\nfrom datetime import timedelta\n\nfrom funcy.py3 import lkeep\n\nfrom dvc.exceptions import DvcException\nfrom dvc.utils import makedirs\nfrom dvc.utils.compat import is_py3\n\n\nDEFAULT_TIMEOUT = 5\n\n\nclass LockError(DvcException):\n    \"\"\"Thrown when unable to acquire the lock for dvc repo.\"\"\"\n\n\nif is_py3:\n    import flufl.lock\n\n    class Lock(flufl.lock.Lock):\n        \"\"\"Class for dvc repo lock.\n\n        Args:\n            lockfile (str): the lock filename\n                in.\n            tmp_dir (str): a directory to store claim files.\n        \"\"\"\n\n        def __init__(self, lockfile, tmp_dir=None):\n            import socket\n\n            self._tmp_dir = tmp_dir\n            if self._tmp_dir is not None:\n                makedirs(self._tmp_dir, exist_ok=True)\n\n            # NOTE: this is basically Lock.__init__ copy-paste, except that\n            # instead of using `socket.getfqdn()` we use `socket.gethostname()`\n            # to speed this up. We've seen [1] `getfqdn()` take ~5sec to return\n            # anything, which is way too slow. `gethostname()` is actually a\n            # fallback for `getfqdn()` when it is not able to resolve a\n            # canonical hostname through network. The claimfile that uses\n            # `self._hostname` is still usable, as it uses `pid` and random\n            # number to generate the resulting lock file name, which is unique\n            # enough for our application.\n            #\n            # [1] https://github.com/iterative/dvc/issues/2582\n            self._hostname = socket.gethostname()\n\n            self._lockfile = lockfile\n            self._lifetime = timedelta(days=365)  # Lock for good by default\n            self._separator = flufl.lock.SEP\n            self._set_claimfile()\n            self._owned = True\n            self._retry_errnos = []\n\n        @property\n        def lockfile(self):\n            return self._lockfile\n\n        @property\n        def files(self):\n            return lkeep([self._lockfile, self._tmp_dir])\n\n        def lock(self):\n            try:\n                super(Lock, self).lock(timedelta(seconds=DEFAULT_TIMEOUT))\n            except flufl.lock.TimeOutError:\n                raise LockError(\n                    \"cannot perform the cmd since DVC is busy and \"\n                    \"locked. Please retry the cmd later.\"\n                )\n\n        def _set_claimfile(self, pid=None):\n            super(Lock, self)._set_claimfile(pid)\n\n            if self._tmp_dir is not None:\n                # Under Windows file path length is limited so we hash it\n                filename = hashlib.md5(self._claimfile.encode()).hexdigest()\n                self._claimfile = os.path.join(\n                    self._tmp_dir, filename + \".lock\"\n                )\n\n        # Fix for __del__ bug in flufl.lock [1] which is causing errors on\n        # Python shutdown [2].\n        # [1] https://gitlab.com/warsaw/flufl.lock/issues/7\n        # [2] https://github.com/iterative/dvc/issues/2573\n        def __del__(self):\n            try:\n                if self._owned:\n                    self.finalize()\n            except ImportError:\n                pass\n\n\nelse:\n    import zc.lockfile\n\n    class Lock(object):\n        \"\"\"Class for dvc repo lock.\n\n        Uses zc.lockfile as backend.\n        \"\"\"\n\n        def __init__(self, lockfile, tmp_dir=None):\n            self.lockfile = lockfile\n            self._lock = None\n\n        @property\n        def files(self):\n            return [self.lockfile]\n\n        def _do_lock(self):\n            try:\n                self._lock = zc.lockfile.LockFile(self.lockfile)\n            except zc.lockfile.LockError:\n                raise LockError(\n                    \"cannot perform the cmd since DVC is busy and \"\n                    \"locked. Please retry the cmd later.\"\n                )\n\n        def lock(self):\n            try:\n                self._do_lock()\n                return\n            except LockError:\n                time.sleep(DEFAULT_TIMEOUT)\n\n            self._do_lock()\n\n        def unlock(self):\n            self._lock.close()\n            self._lock = None\n\n        def __enter__(self):\n            self.lock()\n\n        def __exit__(self, typ, value, tbck):\n            self.unlock()\n", "path": "dvc/lock.py"}, {"content": "\"\"\"Main entry point for dvc CLI.\"\"\"\nfrom __future__ import unicode_literals\n\nimport logging\n\nfrom dvc.analytics import Analytics\nfrom dvc.cli import parse_args\nfrom dvc.config import ConfigError\nfrom dvc.exceptions import DvcParserError\nfrom dvc.exceptions import NotDvcRepoError\nfrom dvc.external_repo import clean_repos\nfrom dvc.lock import LockError\nfrom dvc.logger import FOOTER\nfrom dvc.remote.pool import close_pools\nfrom dvc.utils.compat import is_py2\n\n\n# Workaround for CPython bug. See [1] and [2] for more info.\n# [1] https://github.com/aws/aws-cli/blob/1.16.277/awscli/clidriver.py#L55\n# [2] https://bugs.python.org/issue29288\n\"\".encode(\"idna\")\n\n\nlogger = logging.getLogger(\"dvc\")\n\n\ndef main(argv=None):\n    \"\"\"Run dvc CLI command.\n\n    Args:\n        argv: optional list of arguments to parse. sys.argv is used by default.\n\n    Returns:\n        int: command's return code.\n    \"\"\"\n    args = None\n    cmd = None\n\n    outerLogLevel = logger.level\n    try:\n        args = parse_args(argv)\n\n        if args.quiet:\n            logger.setLevel(logging.CRITICAL)\n\n        elif args.verbose:\n            logger.setLevel(logging.DEBUG)\n\n        cmd = args.func(args)\n        ret = cmd.run()\n    except LockError:\n        logger.exception(\"failed to lock before running a command\")\n        ret = 250\n    except ConfigError:\n        logger.exception(\"configuration error\")\n        ret = 251\n    except KeyboardInterrupt:\n        logger.exception(\"interrupted by the user\")\n        ret = 252\n    except NotDvcRepoError:\n        logger.exception(\"\")\n        ret = 253\n    except DvcParserError:\n        ret = 254\n    except Exception as exc:  # pylint: disable=broad-except\n        if isinstance(exc, UnicodeError) and is_py2:\n            logger.exception(\n                \"unicode is not supported in DVC for Python 2 \"\n                \"(end-of-life January 1, 2020), please upgrade to Python 3\"\n            )\n        else:\n            logger.exception(\"unexpected error\")\n        ret = 255\n    finally:\n        logger.setLevel(outerLogLevel)\n\n        # Python 2 fails to close these clean occasionally and users see\n        # weird error messages, so we do it manually\n        close_pools()\n\n        # Remove cached repos in the end of the call, these are anonymous\n        # so won't be reused by any other subsequent run anyway.\n        clean_repos()\n\n    if ret != 0:\n        logger.info(FOOTER)\n\n    Analytics().send_cmd(cmd, args, ret)\n\n    return ret\n", "path": "dvc/main.py"}], "after_files": [{"content": "\"\"\"Manages dvc lock file.\"\"\"\nfrom __future__ import unicode_literals\n\nimport hashlib\nimport os\nimport time\nfrom datetime import timedelta\n\nfrom funcy.py3 import lkeep\n\nfrom dvc.exceptions import DvcException\nfrom dvc.utils import makedirs\nfrom dvc.utils.compat import is_py3\n\n\nDEFAULT_TIMEOUT = 5\n\nFAILED_TO_LOCK_MESSAGE = (\n    \"cannot perform the command because another DVC process seems to be \"\n    \"running on this project. If that is not the case, manually remove \"\n    \"`.dvc/lock` and try again.\"\n)\n\n\nclass LockError(DvcException):\n    \"\"\"Thrown when unable to acquire the lock for dvc repo.\"\"\"\n\n\nif is_py3:\n    import flufl.lock\n\n    class Lock(flufl.lock.Lock):\n        \"\"\"Class for dvc repo lock.\n\n        Args:\n            lockfile (str): the lock filename\n                in.\n            tmp_dir (str): a directory to store claim files.\n        \"\"\"\n\n        def __init__(self, lockfile, tmp_dir=None):\n            import socket\n\n            self._tmp_dir = tmp_dir\n            if self._tmp_dir is not None:\n                makedirs(self._tmp_dir, exist_ok=True)\n\n            # NOTE: this is basically Lock.__init__ copy-paste, except that\n            # instead of using `socket.getfqdn()` we use `socket.gethostname()`\n            # to speed this up. We've seen [1] `getfqdn()` take ~5sec to return\n            # anything, which is way too slow. `gethostname()` is actually a\n            # fallback for `getfqdn()` when it is not able to resolve a\n            # canonical hostname through network. The claimfile that uses\n            # `self._hostname` is still usable, as it uses `pid` and random\n            # number to generate the resulting lock file name, which is unique\n            # enough for our application.\n            #\n            # [1] https://github.com/iterative/dvc/issues/2582\n            self._hostname = socket.gethostname()\n\n            self._lockfile = lockfile\n            self._lifetime = timedelta(days=365)  # Lock for good by default\n            self._separator = flufl.lock.SEP\n            self._set_claimfile()\n            self._owned = True\n            self._retry_errnos = []\n\n        @property\n        def lockfile(self):\n            return self._lockfile\n\n        @property\n        def files(self):\n            return lkeep([self._lockfile, self._tmp_dir])\n\n        def lock(self):\n            try:\n                super(Lock, self).lock(timedelta(seconds=DEFAULT_TIMEOUT))\n            except flufl.lock.TimeOutError:\n                raise LockError(FAILED_TO_LOCK_MESSAGE)\n\n        def _set_claimfile(self, pid=None):\n            super(Lock, self)._set_claimfile(pid)\n\n            if self._tmp_dir is not None:\n                # Under Windows file path length is limited so we hash it\n                filename = hashlib.md5(self._claimfile.encode()).hexdigest()\n                self._claimfile = os.path.join(\n                    self._tmp_dir, filename + \".lock\"\n                )\n\n        # Fix for __del__ bug in flufl.lock [1] which is causing errors on\n        # Python shutdown [2].\n        # [1] https://gitlab.com/warsaw/flufl.lock/issues/7\n        # [2] https://github.com/iterative/dvc/issues/2573\n        def __del__(self):\n            try:\n                if self._owned:\n                    self.finalize()\n            except ImportError:\n                pass\n\n\nelse:\n    import zc.lockfile\n\n    class Lock(object):\n        \"\"\"Class for dvc repo lock.\n\n        Uses zc.lockfile as backend.\n        \"\"\"\n\n        def __init__(self, lockfile, tmp_dir=None):\n            self.lockfile = lockfile\n            self._lock = None\n\n        @property\n        def files(self):\n            return [self.lockfile]\n\n        def _do_lock(self):\n            try:\n                self._lock = zc.lockfile.LockFile(self.lockfile)\n            except zc.lockfile.LockError:\n                raise LockError(FAILED_TO_LOCK_MESSAGE)\n\n        def lock(self):\n            try:\n                self._do_lock()\n                return\n            except LockError:\n                time.sleep(DEFAULT_TIMEOUT)\n\n            self._do_lock()\n\n        def unlock(self):\n            self._lock.close()\n            self._lock = None\n\n        def __enter__(self):\n            self.lock()\n\n        def __exit__(self, typ, value, tbck):\n            self.unlock()\n", "path": "dvc/lock.py"}, {"content": "\"\"\"Main entry point for dvc CLI.\"\"\"\nfrom __future__ import unicode_literals\n\nimport logging\n\nfrom dvc.analytics import Analytics\nfrom dvc.cli import parse_args\nfrom dvc.config import ConfigError\nfrom dvc.exceptions import DvcParserError\nfrom dvc.exceptions import NotDvcRepoError\nfrom dvc.external_repo import clean_repos\nfrom dvc.logger import FOOTER\nfrom dvc.remote.pool import close_pools\nfrom dvc.utils.compat import is_py2\n\n\n# Workaround for CPython bug. See [1] and [2] for more info.\n# [1] https://github.com/aws/aws-cli/blob/1.16.277/awscli/clidriver.py#L55\n# [2] https://bugs.python.org/issue29288\n\"\".encode(\"idna\")\n\n\nlogger = logging.getLogger(\"dvc\")\n\n\ndef main(argv=None):\n    \"\"\"Run dvc CLI command.\n\n    Args:\n        argv: optional list of arguments to parse. sys.argv is used by default.\n\n    Returns:\n        int: command's return code.\n    \"\"\"\n    args = None\n    cmd = None\n\n    outerLogLevel = logger.level\n    try:\n        args = parse_args(argv)\n\n        if args.quiet:\n            logger.setLevel(logging.CRITICAL)\n\n        elif args.verbose:\n            logger.setLevel(logging.DEBUG)\n\n        cmd = args.func(args)\n        ret = cmd.run()\n    except ConfigError:\n        logger.exception(\"configuration error\")\n        ret = 251\n    except KeyboardInterrupt:\n        logger.exception(\"interrupted by the user\")\n        ret = 252\n    except NotDvcRepoError:\n        logger.exception(\"\")\n        ret = 253\n    except DvcParserError:\n        ret = 254\n    except Exception as exc:  # pylint: disable=broad-except\n        if isinstance(exc, UnicodeError) and is_py2:\n            logger.exception(\n                \"unicode is not supported in DVC for Python 2 \"\n                \"(end-of-life January 1, 2020), please upgrade to Python 3\"\n            )\n        else:\n            logger.exception(\"unexpected error\")\n        ret = 255\n    finally:\n        logger.setLevel(outerLogLevel)\n\n        # Python 2 fails to close these clean occasionally and users see\n        # weird error messages, so we do it manually\n        close_pools()\n\n        # Remove cached repos in the end of the call, these are anonymous\n        # so won't be reused by any other subsequent run anyway.\n        clean_repos()\n\n    if ret != 0:\n        logger.info(FOOTER)\n\n    Analytics().send_cmd(cmd, args, ret)\n\n    return ret\n", "path": "dvc/main.py"}]}