Skip to content

Commit

Permalink
BUG: Fix pd.show_versions as_json invalid JSON (pandas-dev#39701)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexprincel committed Feb 19, 2021
1 parent bcf2406 commit 8736b20
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 12 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.3.0.rst
Expand Up @@ -461,6 +461,7 @@ Other
- Bug in :class:`Styler` where ``subset`` arg in methods raised an error for some valid multiindex slices (:issue:`33562`)
- :class:`Styler` rendered HTML output minor alterations to support w3 good code standard (:issue:`39626`)
- Bug in :meth:`DataFrame.equals`, :meth:`Series.equals`, :meth:`Index.equals` with object-dtype containing ``np.datetime64("NaT")`` or ``np.timedelta64("NaT")`` (:issue:`39650`)
- Bug in :func:`pandas.util.show_versions` where console JSON output was not proper JSON (:issue:`39701`)


.. ---------------------------------------------------------------------------
Expand Down
70 changes: 59 additions & 11 deletions pandas/tests/util/test_show_versions.py
@@ -1,7 +1,11 @@
import json
import os
import re

import pytest

from pandas.util._print_versions import _get_dependency_info, _get_sys_info

import pandas as pd


Expand All @@ -26,21 +30,65 @@
"ignore:Distutils:UserWarning"
)
@pytest.mark.filterwarnings("ignore:Setuptools is replacing distutils:UserWarning")
def test_show_versions(capsys):
@pytest.mark.parametrize("as_json", [True, False, "test_output.json"])
def test_show_versions(capsys, as_json, tmpdir):
# gh-32041
pd.show_versions()
if isinstance(as_json, str):
as_json = os.path.join(tmpdir, as_json)

pd.show_versions(as_json=as_json)
captured = capsys.readouterr()
result = captured.out

# check header
assert "INSTALLED VERSIONS" in result
# check header for non-JSON console output
if as_json is False:
assert "INSTALLED VERSIONS" in result

# check full commit hash
assert re.search(r"commit\s*:\s[0-9a-f]{40}\n", result)

# check required dependency
# 2020-12-09 npdev has "dirty" in the tag
assert re.search(r"numpy\s*:\s([0-9\.\+a-g\_]|dev)+(dirty)?\n", result)

# check optional dependency
assert re.search(r"pyarrow\s*:\s([0-9\.]+|None)\n", result)

# Dictionary-based asserts
else:
# check valid json is printed to the console if as_json is True
if as_json is True:
dict_check = json.loads(result)
elif isinstance(as_json, str):
# make sure that the file was created
assert os.path.exists(as_json)

with open(as_json) as fd:
contents = fd.readlines()
str_contents = "".join(contents)

# make sure that there was output to the file
assert str_contents

# check if file output is valid JSON
dict_check = json.loads(str_contents)

# Basic check that each version element is found in output
version_elements = {
"system": _get_sys_info(),
"dependencies": _get_dependency_info(),
}

assert version_elements == dict_check


# check full commit hash
assert re.search(r"commit\s*:\s[0-9a-f]{40}\n", result)
def test_json_output_match(capsys, tmpdir):
pd.show_versions(as_json=True)
result_console = capsys.readouterr().out

# check required dependency
# 2020-12-09 npdev has "dirty" in the tag
assert re.search(r"numpy\s*:\s([0-9\.\+a-g\_]|dev)+(dirty)?\n", result)
out_path = os.path.join(tmpdir, "test_json.json")
pd.show_versions(as_json=out_path)
with open(out_path) as out_fd:
result_file = "".join(out_fd.readlines())

# check optional dependency
assert re.search(r"pyarrow\s*:\s([0-9\.]+|None)\n", result)
assert result_console == result_file
2 changes: 1 addition & 1 deletion pandas/util/_print_versions.py
Expand Up @@ -107,7 +107,7 @@ def show_versions(as_json: Union[str, bool] = False) -> None:
j = {"system": sys_info, "dependencies": deps}

if as_json is True:
print(j)
sys.stdout.writelines(json.dumps(j, indent=2))
else:
assert isinstance(as_json, str) # needed for mypy
with codecs.open(as_json, "wb", encoding="utf8") as f:
Expand Down

0 comments on commit 8736b20

Please sign in to comment.