codekingpro/portable-devtools
114k
1import logging2import os3import tempfile4import shutil5import json6from subprocess import check_call, check_output7from tarfile import TarFile8 9from dateutil.zoneinfo import METADATA_FN, ZONEFILENAME10 11 12def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None):13 """Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar*14 15 filename is the timezone tarball from ``ftp.iana.org/tz``.16 17 """18 tmpdir = tempfile.mkdtemp()19 zonedir = os.path.join(tmpdir, "zoneinfo")20 moduledir = os.path.dirname(__file__)21 try:22 with TarFile.open(filename) as tf:23 for name in zonegroups:24 tf.extract(name, tmpdir)25 filepaths = [os.path.join(tmpdir, n) for n in zonegroups]26 27 _run_zic(zonedir, filepaths)28 29 # write metadata file30 with open(os.path.join(zonedir, METADATA_FN), 'w') as f:31 json.dump(metadata, f, indent=4, sort_keys=True)32 target = os.path.join(moduledir, ZONEFILENAME)33 with TarFile.open(target, "w:%s" % format) as tf:34 for entry in os.listdir(zonedir):35 entrypath = os.path.join(zonedir, entry)36 tf.add(entrypath, entry)37 finally:38 shutil.rmtree(tmpdir)39 40 41def _run_zic(zonedir, filepaths):42 """Calls the ``zic`` compiler in a compatible way to get a "fat" binary.43 44 Recent versions of ``zic`` default to ``-b slim``, while older versions45 don't even have the ``-b`` option (but default to "fat" binaries). The46 current version of dateutil does not support Version 2+ TZif files, which47 causes problems when used in conjunction with "slim" binaries, so this48 function is used to ensure that we always get a "fat" binary.49 """50 51 try:52 help_text = check_output(["zic", "--help"])53 except OSError as e:54 _print_on_nosuchfile(e)55 raise56 57 if b"-b " in help_text:58 bloat_args = ["-b", "fat"]59 else:60 bloat_args = []61 62 check_call(["zic"] + bloat_args + ["-d", zonedir] + filepaths)63 64 65def _print_on_nosuchfile(e):66 """Print helpful troubleshooting message67 68 e is an exception raised by subprocess.check_call()69 70 """71 if e.errno == 2:72 logging.error(73 "Could not find zic. Perhaps you need to install "74 "libc-bin or some other package that provides it, "75 "or it's not in your PATH?")76 