You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

76 lines
2.3 KiB

  1. import logging
  2. import os
  3. import tempfile
  4. import shutil
  5. import json
  6. from subprocess import check_call, check_output
  7. from tarfile import TarFile
  8. from dateutil.zoneinfo import METADATA_FN, ZONEFILENAME
  9. def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None):
  10. """Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar*
  11. filename is the timezone tarball from ``ftp.iana.org/tz``.
  12. """
  13. tmpdir = tempfile.mkdtemp()
  14. zonedir = os.path.join(tmpdir, "zoneinfo")
  15. moduledir = os.path.dirname(__file__)
  16. try:
  17. with TarFile.open(filename) as tf:
  18. for name in zonegroups:
  19. tf.extract(name, tmpdir)
  20. filepaths = [os.path.join(tmpdir, n) for n in zonegroups]
  21. _run_zic(zonedir, filepaths)
  22. # write metadata file
  23. with open(os.path.join(zonedir, METADATA_FN), 'w') as f:
  24. json.dump(metadata, f, indent=4, sort_keys=True)
  25. target = os.path.join(moduledir, ZONEFILENAME)
  26. with TarFile.open(target, "w:%s" % format) as tf:
  27. for entry in os.listdir(zonedir):
  28. entrypath = os.path.join(zonedir, entry)
  29. tf.add(entrypath, entry)
  30. finally:
  31. shutil.rmtree(tmpdir)
  32. def _run_zic(zonedir, filepaths):
  33. """Calls the ``zic`` compiler in a compatible way to get a "fat" binary.
  34. Recent versions of ``zic`` default to ``-b slim``, while older versions
  35. don't even have the ``-b`` option (but default to "fat" binaries). The
  36. current version of dateutil does not support Version 2+ TZif files, which
  37. causes problems when used in conjunction with "slim" binaries, so this
  38. function is used to ensure that we always get a "fat" binary.
  39. """
  40. try:
  41. help_text = check_output(["zic", "--help"])
  42. except OSError as e:
  43. _print_on_nosuchfile(e)
  44. raise
  45. if b"-b " in help_text:
  46. bloat_args = ["-b", "fat"]
  47. else:
  48. bloat_args = []
  49. check_call(["zic"] + bloat_args + ["-d", zonedir] + filepaths)
  50. def _print_on_nosuchfile(e):
  51. """Print helpful troubleshooting message
  52. e is an exception raised by subprocess.check_call()
  53. """
  54. if e.errno == 2:
  55. logging.error(
  56. "Could not find zic. Perhaps you need to install "
  57. "libc-bin or some other package that provides it, "
  58. "or it's not in your PATH?")