_print_versions.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. from __future__ import annotations
  2. import codecs
  3. import json
  4. import locale
  5. import os
  6. import platform
  7. import struct
  8. import sys
  9. from pandas._typing import JSONSerializable
  10. from pandas.compat._optional import (
  11. VERSIONS,
  12. get_version,
  13. import_optional_dependency,
  14. )
  15. def _get_commit_hash() -> str | None:
  16. """
  17. Use vendored versioneer code to get git hash, which handles
  18. git worktree correctly.
  19. """
  20. from pandas._version import get_versions
  21. versions = get_versions()
  22. return versions["full-revisionid"]
  23. def _get_sys_info() -> dict[str, JSONSerializable]:
  24. """
  25. Returns system information as a JSON serializable dictionary.
  26. """
  27. uname_result = platform.uname()
  28. language_code, encoding = locale.getlocale()
  29. return {
  30. "commit": _get_commit_hash(),
  31. "python": ".".join([str(i) for i in sys.version_info]),
  32. "python-bits": struct.calcsize("P") * 8,
  33. "OS": uname_result.system,
  34. "OS-release": uname_result.release,
  35. "Version": uname_result.version,
  36. "machine": uname_result.machine,
  37. "processor": uname_result.processor,
  38. "byteorder": sys.byteorder,
  39. "LC_ALL": os.environ.get("LC_ALL"),
  40. "LANG": os.environ.get("LANG"),
  41. "LOCALE": {"language-code": language_code, "encoding": encoding},
  42. }
  43. def _get_dependency_info() -> dict[str, JSONSerializable]:
  44. """
  45. Returns dependency information as a JSON serializable dictionary.
  46. """
  47. deps = [
  48. "pandas",
  49. # required
  50. "numpy",
  51. "pytz",
  52. "dateutil",
  53. # install / build,
  54. "setuptools",
  55. "pip",
  56. "Cython",
  57. # test
  58. "pytest",
  59. "hypothesis",
  60. # docs
  61. "sphinx",
  62. # Other, need a min version
  63. "blosc",
  64. "feather",
  65. "xlsxwriter",
  66. "lxml.etree",
  67. "html5lib",
  68. "pymysql",
  69. "psycopg2",
  70. "jinja2",
  71. # Other, not imported.
  72. "IPython",
  73. "pandas_datareader",
  74. ]
  75. deps.extend(list(VERSIONS))
  76. result: dict[str, JSONSerializable] = {}
  77. for modname in deps:
  78. mod = import_optional_dependency(modname, errors="ignore")
  79. result[modname] = get_version(mod) if mod else None
  80. return result
  81. def show_versions(as_json: str | bool = False) -> None:
  82. """
  83. Provide useful information, important for bug reports.
  84. It comprises info about hosting operation system, pandas version,
  85. and versions of other installed relative packages.
  86. Parameters
  87. ----------
  88. as_json : str or bool, default False
  89. * If False, outputs info in a human readable form to the console.
  90. * If str, it will be considered as a path to a file.
  91. Info will be written to that file in JSON format.
  92. * If True, outputs info in JSON format to the console.
  93. """
  94. sys_info = _get_sys_info()
  95. deps = _get_dependency_info()
  96. if as_json:
  97. j = {"system": sys_info, "dependencies": deps}
  98. if as_json is True:
  99. sys.stdout.writelines(json.dumps(j, indent=2))
  100. else:
  101. assert isinstance(as_json, str) # needed for mypy
  102. with codecs.open(as_json, "wb", encoding="utf8") as f:
  103. json.dump(j, f, indent=2)
  104. else:
  105. assert isinstance(sys_info["LOCALE"], dict) # needed for mypy
  106. language_code = sys_info["LOCALE"]["language-code"]
  107. encoding = sys_info["LOCALE"]["encoding"]
  108. sys_info["LOCALE"] = f"{language_code}.{encoding}"
  109. maxlen = max(len(x) for x in deps)
  110. print("\nINSTALLED VERSIONS")
  111. print("------------------")
  112. for k, v in sys_info.items():
  113. print(f"{k:<{maxlen}}: {v}")
  114. print("")
  115. for k, v in deps.items():
  116. print(f"{k:<{maxlen}}: {v}")