_unicodefun.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. import codecs
  2. import os
  3. from gettext import gettext as _
  4. def _verify_python_env() -> None:
  5. """Ensures that the environment is good for Unicode."""
  6. try:
  7. from locale import getpreferredencoding
  8. fs_enc = codecs.lookup(getpreferredencoding()).name
  9. except Exception:
  10. fs_enc = "ascii"
  11. if fs_enc != "ascii":
  12. return
  13. extra = [
  14. _(
  15. "Click will abort further execution because Python was"
  16. " configured to use ASCII as encoding for the environment."
  17. " Consult https://click.palletsprojects.com/unicode-support/"
  18. " for mitigation steps."
  19. )
  20. ]
  21. if os.name == "posix":
  22. import subprocess
  23. try:
  24. rv = subprocess.Popen(
  25. ["locale", "-a"],
  26. stdout=subprocess.PIPE,
  27. stderr=subprocess.PIPE,
  28. encoding="ascii",
  29. errors="replace",
  30. ).communicate()[0]
  31. except OSError:
  32. rv = ""
  33. good_locales = set()
  34. has_c_utf8 = False
  35. for line in rv.splitlines():
  36. locale = line.strip()
  37. if locale.lower().endswith((".utf-8", ".utf8")):
  38. good_locales.add(locale)
  39. if locale.lower() in ("c.utf8", "c.utf-8"):
  40. has_c_utf8 = True
  41. if not good_locales:
  42. extra.append(
  43. _(
  44. "Additional information: on this system no suitable"
  45. " UTF-8 locales were discovered. This most likely"
  46. " requires resolving by reconfiguring the locale"
  47. " system."
  48. )
  49. )
  50. elif has_c_utf8:
  51. extra.append(
  52. _(
  53. "This system supports the C.UTF-8 locale which is"
  54. " recommended. You might be able to resolve your"
  55. " issue by exporting the following environment"
  56. " variables:"
  57. )
  58. )
  59. extra.append(" export LC_ALL=C.UTF-8\n export LANG=C.UTF-8")
  60. else:
  61. extra.append(
  62. _(
  63. "This system lists some UTF-8 supporting locales"
  64. " that you can pick from. The following suitable"
  65. " locales were discovered: {locales}"
  66. ).format(locales=", ".join(sorted(good_locales)))
  67. )
  68. bad_locale = None
  69. for env_locale in os.environ.get("LC_ALL"), os.environ.get("LANG"):
  70. if env_locale and env_locale.lower().endswith((".utf-8", ".utf8")):
  71. bad_locale = env_locale
  72. if env_locale is not None:
  73. break
  74. if bad_locale is not None:
  75. extra.append(
  76. _(
  77. "Click discovered that you exported a UTF-8 locale"
  78. " but the locale system could not pick up from it"
  79. " because it does not exist. The exported locale is"
  80. " {locale!r} but it is not supported."
  81. ).format(locale=bad_locale)
  82. )
  83. raise RuntimeError("\n\n".join(extra))