Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
_tzpath.py190 linesDownload Raw Back to zoneinfo
1import os2import sysconfig3 4 5def _reset_tzpath(to=None, stacklevel=4):6    global TZPATH7 8    tzpaths = to9    if tzpaths is not None:10        if isinstance(tzpaths, (str, bytes)):11            raise TypeError(12                f"tzpaths must be a list or tuple, "13                + f"not {type(tzpaths)}: {tzpaths!r}"14            )15 16        tzpaths = [os.fspath(p) for p in tzpaths]17        if not all(isinstance(p, str) for p in tzpaths):18            raise TypeError(19                "All elements of a tzpath sequence must be strings or "20                "os.PathLike objects which convert to strings."21            )22 23        if not all(map(os.path.isabs, tzpaths)):24            raise ValueError(_get_invalid_paths_message(tzpaths))25        base_tzpath = tzpaths26    else:27        env_var = os.environ.get("PYTHONTZPATH", None)28        if env_var is None:29            env_var = sysconfig.get_config_var("TZPATH")30        base_tzpath = _parse_python_tzpath(env_var, stacklevel)31 32    TZPATH = tuple(base_tzpath)33 34 35def reset_tzpath(to=None):36    """Reset global TZPATH."""37    # We need `_reset_tzpath` helper function because it produces a warning,38    # it is used as both a module-level call and a public API.39    # This is how we equalize the stacklevel for both calls.40    _reset_tzpath(to)41 42 43def _parse_python_tzpath(env_var, stacklevel):44    if not env_var:45        return ()46 47    raw_tzpath = env_var.split(os.pathsep)48    new_tzpath = tuple(filter(os.path.isabs, raw_tzpath))49 50    # If anything has been filtered out, we will warn about it51    if len(new_tzpath) != len(raw_tzpath):52        import warnings53 54        msg = _get_invalid_paths_message(raw_tzpath)55 56        warnings.warn(57            "Invalid paths specified in PYTHONTZPATH environment variable. "58            + msg,59            InvalidTZPathWarning,60            stacklevel=stacklevel,61        )62 63    return new_tzpath64 65 66def _get_invalid_paths_message(tzpaths):67    invalid_paths = (path for path in tzpaths if not os.path.isabs(path))68 69    prefix = "\n    "70    indented_str = prefix + prefix.join(invalid_paths)71 72    return (73        "Paths should be absolute but found the following relative paths:"74        + indented_str75    )76 77 78def find_tzfile(key):79    """Retrieve the path to a TZif file from a key."""80    _validate_tzfile_path(key)81    for search_path in TZPATH:82        filepath = os.path.join(search_path, key)83        if os.path.isfile(filepath):84            return filepath85 86    return None87 88 89_TEST_PATH = os.path.normpath(os.path.join("_", "_"))[:-1]90 91 92def _validate_tzfile_path(path, _base=_TEST_PATH):93    if os.path.isabs(path):94        raise ValueError(95            f"ZoneInfo keys may not be absolute paths, got: {path}"96        )97 98    # We only care about the kinds of path normalizations that would change the99    # length of the key - e.g. a/../b -> a/b, or a/b/ -> a/b. On Windows,100    # normpath will also change from a/b to a\b, but that would still preserve101    # the length.102    new_path = os.path.normpath(path)103    if len(new_path) != len(path):104        raise ValueError(105            f"ZoneInfo keys must be normalized relative paths, got: {path}"106        )107 108    resolved = os.path.normpath(os.path.join(_base, new_path))109    if not resolved.startswith(_base):110        raise ValueError(111            f"ZoneInfo keys must refer to subdirectories of TZPATH, got: {path}"112        )113 114 115del _TEST_PATH116 117 118def available_timezones():119    """Returns a set containing all available time zones.120 121    .. caution::122 123        This may attempt to open a large number of files, since the best way to124        determine if a given file on the time zone search path is to open it125        and check for the "magic string" at the beginning.126    """127    from importlib import resources128 129    valid_zones = set()130 131    # Start with loading from the tzdata package if it exists: this has a132    # pre-assembled list of zones that only requires opening one file.133    try:134        zones_file = resources.files("tzdata").joinpath("zones")135        with zones_file.open("r", encoding="utf-8") as f:136            for zone in f:137                zone = zone.strip()138                if zone:139                    valid_zones.add(zone)140    except (ImportError, FileNotFoundError):141        pass142 143    def valid_key(fpath):144        try:145            with open(fpath, "rb") as f:146                return f.read(4) == b"TZif"147        except Exception:  # pragma: nocover148            return False149 150    for tz_root in TZPATH:151        if not os.path.exists(tz_root):152            continue153 154        for root, dirnames, files in os.walk(tz_root):155            if root == tz_root:156                # right/ and posix/ are special directories and shouldn't be157                # included in the output of available zones158                if "right" in dirnames:159                    dirnames.remove("right")160                if "posix" in dirnames:161                    dirnames.remove("posix")162 163            for file in files:164                fpath = os.path.join(root, file)165 166                key = os.path.relpath(fpath, start=tz_root)167                if os.sep != "/":  # pragma: nocover168                    key = key.replace(os.sep, "/")169 170                if not key or key in valid_zones:171                    continue172 173                if valid_key(fpath):174                    valid_zones.add(key)175 176    if "posixrules" in valid_zones:177        # posixrules is a special symlink-only time zone where it exists, it178        # should not be included in the output179        valid_zones.remove("posixrules")180 181    return valid_zones182 183 184class InvalidTZPathWarning(RuntimeWarning):185    """Warning raised if an invalid path is specified in PYTHONTZPATH."""186 187 188TZPATH = ()189_reset_tzpath(stacklevel=5)190 
codekingpro/portable-devtools · Team Ai