forked from iterative/dvc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Print dvc version info for debugging (iterative#4536)
* Print dvc version info for debugging fix iterative#4095 1. seperate info from dvc version. 2. print dvc version info when some unexpected error occured. * Psutil NoneType error * Update tests/func/test_version.py Co-authored-by: Ruslan Kuprieiev <[email protected]> * Move `package` outside dvc/utils/pkg.py Co-authored-by: Ruslan Kuprieiev <[email protected]>
- Loading branch information
1 parent
cf7e534
commit 8b16af9
Showing
6 changed files
with
221 additions
and
202 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import itertools | ||
import os | ||
import pathlib | ||
import platform | ||
import uuid | ||
|
||
from dvc.exceptions import DvcException, NotDvcRepoError | ||
from dvc.repo import Repo | ||
from dvc.scm.base import SCMError | ||
from dvc.system import System | ||
from dvc.tree import TREES | ||
from dvc.utils import error_link | ||
from dvc.utils.pkg import PKG | ||
from dvc.version import __version__ | ||
|
||
try: | ||
import psutil | ||
except ImportError: | ||
psutil = None | ||
|
||
if PKG is None: | ||
package = "" | ||
else: | ||
package = f"({PKG})" | ||
|
||
|
||
def get_dvc_info(): | ||
info = [ | ||
f"DVC version: {__version__} {package}", | ||
"---------------------------------", | ||
f"Platform: Python {platform.python_version()} on " | ||
f"{platform.platform()}", | ||
f"Supports: {_get_supported_remotes()}", | ||
] | ||
|
||
try: | ||
repo = Repo() | ||
|
||
# cache_dir might not exist yet (e.g. after `dvc init`), and we | ||
# can't auto-create it, as it might cause issues if the user | ||
# later decides to enable shared cache mode with | ||
# `dvc config cache.shared group`. | ||
if os.path.exists(repo.cache.local.cache_dir): | ||
info.append( | ||
"Cache types: {}".format(_get_linktype_support_info(repo)) | ||
) | ||
if psutil: | ||
fs_type = get_fs_type(repo.cache.local.cache_dir) | ||
info.append(f"Cache directory: {fs_type}") | ||
else: | ||
info.append("Cache types: " + error_link("no-dvc-cache")) | ||
|
||
except NotDvcRepoError: | ||
pass | ||
except SCMError: | ||
info.append("Repo: dvc, git (broken)") | ||
else: | ||
root_directory = repo.root_dir | ||
if psutil: | ||
fs_root = get_fs_type(os.path.abspath(root_directory)) | ||
info.append(f"Workspace directory: {fs_root}") | ||
info.append("Repo: {}".format(_get_dvc_repo_info(repo))) | ||
return "\n".join(info) | ||
|
||
|
||
def _get_linktype_support_info(repo): | ||
|
||
links = { | ||
"reflink": (System.reflink, None), | ||
"hardlink": (System.hardlink, System.is_hardlink), | ||
"symlink": (System.symlink, System.is_symlink), | ||
} | ||
|
||
fname = "." + str(uuid.uuid4()) | ||
src = os.path.join(repo.cache.local.cache_dir, fname) | ||
open(src, "w").close() | ||
dst = os.path.join(repo.root_dir, fname) | ||
|
||
cache = [] | ||
|
||
for name, (link, is_link) in links.items(): | ||
try: | ||
link(src, dst) | ||
status = "supported" | ||
if is_link and not is_link(dst): | ||
status = "broken" | ||
os.unlink(dst) | ||
except DvcException: | ||
status = "not supported" | ||
|
||
if status == "supported": | ||
cache.append(name) | ||
os.remove(src) | ||
|
||
return ", ".join(cache) | ||
|
||
|
||
def _get_supported_remotes(): | ||
|
||
supported_remotes = [] | ||
for tree_cls in TREES: | ||
if not tree_cls.get_missing_deps(): | ||
supported_remotes.append(tree_cls.scheme) | ||
|
||
if len(supported_remotes) == len(TREES): | ||
return "All remotes" | ||
|
||
if len(supported_remotes) == 1: | ||
return supported_remotes | ||
|
||
return ", ".join(supported_remotes) | ||
|
||
|
||
def get_fs_type(path): | ||
|
||
partition = { | ||
pathlib.Path(part.mountpoint): (part.fstype + " on " + part.device) | ||
for part in psutil.disk_partitions(all=True) | ||
} | ||
|
||
path = pathlib.Path(path) | ||
|
||
for parent in itertools.chain([path], path.parents): | ||
if parent in partition: | ||
return partition[parent] | ||
return ("unknown", "none") | ||
|
||
|
||
def _get_dvc_repo_info(self): | ||
if self.config.get("core", {}).get("no_scm", False): | ||
return "dvc (no_scm)" | ||
|
||
if self.root_dir != self.scm.root_dir: | ||
return "dvc (subdir), git" | ||
|
||
return "dvc, git" |
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,72 +1,13 @@ | ||
import os | ||
import re | ||
import shutil | ||
|
||
import pytest | ||
|
||
from dvc.command.version import psutil | ||
from dvc.main import main | ||
|
||
|
||
@pytest.mark.parametrize("scm_init", [True, False]) | ||
def test_info_in_repo(scm_init, tmp_dir, caplog): | ||
tmp_dir.init(scm=scm_init, dvc=True) | ||
# Create `.dvc/cache`, that is needed to check supported link types. | ||
os.mkdir(tmp_dir.dvc.cache.local.cache_dir) | ||
|
||
def test_(tmp_dir, dvc, scm, caplog): | ||
assert main(["version"]) == 0 | ||
|
||
assert re.search(r"DVC version: \d+\.\d+\.\d+.*", caplog.text) | ||
assert re.search(r"Platform: Python \d\.\d+\.\d+ on .*", caplog.text) | ||
assert re.search(r"Supports: .*", caplog.text) | ||
assert re.search(r"Cache types: .*", caplog.text) | ||
|
||
if scm_init: | ||
assert "Repo: dvc, git" in caplog.text | ||
else: | ||
assert "Repo: dvc (no_scm)" in caplog.text | ||
|
||
|
||
def test_info_in_subdir(tmp_dir, scm, caplog): | ||
dvc_subdir = tmp_dir / "subdir" | ||
dvc_subdir.mkdir() | ||
|
||
with dvc_subdir.chdir(): | ||
dvc_subdir.init(scm=False, dvc=True) | ||
with dvc_subdir.dvc.config.edit() as conf: | ||
del conf["core"]["no_scm"] | ||
|
||
assert main(["version"]) == 0 | ||
|
||
assert "Repo: dvc (subdir), git" in caplog.text | ||
|
||
|
||
def test_info_in_broken_git_repo(tmp_dir, dvc, scm, caplog): | ||
shutil.rmtree(dvc.scm.dir) | ||
assert main(["version"]) == 0 | ||
|
||
assert "Repo: dvc, git (broken)" in caplog.text | ||
|
||
|
||
@pytest.mark.skipif(psutil is None, reason="No psutil.") | ||
def test_fs_info_in_repo(tmp_dir, dvc, caplog): | ||
os.mkdir(dvc.cache.local.cache_dir) | ||
assert main(["version"]) == 0 | ||
|
||
assert re.search(r"Cache directory: .* on .*", caplog.text) | ||
assert re.search(r"Workspace directory: .* on .*", caplog.text) | ||
|
||
|
||
def test_info_outside_of_repo(tmp_dir, caplog): | ||
assert main(["version"]) == 0 | ||
|
||
assert re.search(r"DVC version: \d+\.\d+\.\d+.*", caplog.text) | ||
assert re.search(r"Platform: Python \d\.\d+\.\d+ on .*", caplog.text) | ||
assert re.search(r"Supports: .*", caplog.text) | ||
assert not re.search(r"Cache types: .*", caplog.text) | ||
assert "Repo:" not in caplog.text | ||
|
||
|
||
@pytest.mark.skipif(psutil is None, reason="No psutil.") | ||
def test_fs_info_outside_of_repo(tmp_dir, caplog): | ||
assert main(["version"]) == 0 | ||
assert "Repo: dvc, git" in caplog.text |
Oops, something went wrong.