resourceutil.py
120 lines
| 3.8 KiB
| text/x-python
|
PythonLexer
|
r44067 | # resourceutil.py - utility for looking up resources | ||
# | ||||
# Copyright 2005 K. Thananchayan <thananck@yahoo.com> | ||||
|
r47575 | # Copyright 2005-2007 Olivia Mackall <olivia@selenic.com> | ||
|
r44067 | # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> | ||
# | ||||
# This software may be used and distributed according to the terms of the | ||||
# GNU General Public License version 2 or any later version. | ||||
|
r51649 | import _imp | ||
|
r44068 | import os | ||
|
r44067 | import sys | ||
from .. import pycompat | ||||
def mainfrozen(): | ||||
"""return True if we are a frozen executable. | ||||
The code supports py2exe (most common, Windows only) and tools/freeze | ||||
(portable, not much used). | ||||
""" | ||||
return ( | ||||
|
r45476 | pycompat.safehasattr(sys, "frozen") # new py2exe | ||
or pycompat.safehasattr(sys, "importers") # old py2exe | ||||
|
r51649 | or _imp.is_frozen("__main__") # tools/freeze | ||
|
r45476 | ) | ||
|
r44068 | |||
# the location of data files matching the source code | ||||
|
r44723 | if mainfrozen() and getattr(sys, "frozen", None) != "macosx_app": | ||
|
r44068 | # executable version (py2exe) doesn't support __file__ | ||
datapath = os.path.dirname(pycompat.sysexecutable) | ||||
|
r44678 | _rootpath = datapath | ||
|
r44706 | |||
# The installers store the files outside of library.zip, like | ||||
# C:\Program Files\Mercurial\defaultrc\*.rc. This strips the | ||||
# leading "mercurial." off of the package name, so that these | ||||
# pseudo resources are found in their directory next to the | ||||
# executable. | ||||
def _package_path(package): | ||||
|
r44723 | dirs = package.split(b".") | ||
assert dirs[0] == b"mercurial" | ||||
|
r44706 | return os.path.join(_rootpath, *dirs[1:]) | ||
|
r44723 | |||
|
r44068 | else: | ||
datapath = os.path.dirname(os.path.dirname(pycompat.fsencode(__file__))) | ||||
|
r44479 | _rootpath = os.path.dirname(datapath) | ||
|
r44323 | |||
|
r44706 | def _package_path(package): | ||
|
r44723 | return os.path.join(_rootpath, *package.split(b".")) | ||
|
r44706 | |||
|
r44323 | try: | ||
|
r46024 | # importlib.resources exists from Python 3.7; see fallback in except clause | ||
# further down | ||||
|
r48821 | from importlib import resources # pytype: disable=import-error | ||
|
r44323 | |||
# Force loading of the resources module | ||||
r50838 | if pycompat.safehasattr(resources, 'files'): | |||
resources.files # pytype: disable=module-attr | ||||
else: | ||||
resources.open_binary # pytype: disable=module-attr | ||||
|
r44323 | |||
|
r49965 | # py2exe raises an AssertionError if uses importlib.resources | ||
if getattr(sys, "frozen", None) in ("console_exe", "windows_exe"): | ||||
raise ImportError | ||||
|
r44407 | except (ImportError, AttributeError): | ||
|
r46024 | # importlib.resources was not found (almost definitely because we're on a | ||
# Python version before 3.7) | ||||
|
r44323 | |||
def open_resource(package, name): | ||||
path = os.path.join(_package_path(package), name) | ||||
|
r44723 | return open(path, "rb") | ||
|
r44480 | |||
def is_resource(package, name): | ||||
path = os.path.join(_package_path(package), name) | ||||
try: | ||||
return os.path.isfile(pycompat.fsdecode(path)) | ||||
except (IOError, OSError): | ||||
return False | ||||
|
r44481 | |||
def contents(package): | ||||
path = pycompat.fsdecode(_package_path(package)) | ||||
for p in os.listdir(path): | ||||
yield pycompat.fsencode(p) | ||||
r48668 | ||||
else: | ||||
from .. import encoding | ||||
def open_resource(package, name): | ||||
r50838 | if pycompat.safehasattr(resources, 'files'): | |||
return ( | ||||
resources.files( # pytype: disable=module-attr | ||||
pycompat.sysstr(package) | ||||
) | ||||
.joinpath(pycompat.sysstr(name)) | ||||
.open('rb') | ||||
) | ||||
else: | ||||
return resources.open_binary( # pytype: disable=module-attr | ||||
pycompat.sysstr(package), pycompat.sysstr(name) | ||||
) | ||||
r48668 | ||||
def is_resource(package, name): | ||||
return resources.is_resource( # pytype: disable=module-attr | ||||
pycompat.sysstr(package), encoding.strfromlocal(name) | ||||
) | ||||
def contents(package): | ||||
# pytype: disable=module-attr | ||||
for r in resources.contents(pycompat.sysstr(package)): | ||||
# pytype: enable=module-attr | ||||
yield encoding.strtolocal(r) | ||||