mercurial/utils/resourceutil.py
author Gregory Szorc <gregory.szorc@gmail.com>
Sun, 26 Jan 2020 16:23:57 -0800
changeset 44290 281b6690e646
parent 44136 a90039b07343
child 44146 9e367157a990
permissions -rw-r--r--
packaging: add support for PyOxidizer I've successfully built Mercurial on the development tip of PyOxidizer on Linux and Windows. It mostly "just works" on Linux. Windows is a bit more finicky. In-memory resource files are probably not all working correctly due to bugs in PyOxidizer's naming of modules. PyOxidizer now now supports installing files next to the produced binary. (We do this for templates in the added file.) So a workaround should be available. Also, since the last time I submitted support for PyOxidizer, PyOxidizer gained the ability to auto-generate Rust projects to build executables. So we don't need to worry about vendoring any Rust code to initially support PyOxidizer. However, at some point we will likely want to write our own command line driver that embeds a Python interpreter via PyOxidizer so we can run Rust code outside the confines of a Python interpreter. But that will be a follow-up. I would also like to add packaging.py CLI commands to build PyOxidizer distributions. This can come later, if ever. PyOxidizer's new "targets" feature makes it really easy to define packaging tasks in its Starlark configuration file. While not much is implemented yet, eventually we should be able to produce MSIs, etc using a `pyoxidizer build` one-liner. We'll get there... Differential Revision: https://phab.mercurial-scm.org/D7450
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
43712
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43701
diff changeset
     1
# resourceutil.py - utility for looking up resources
8226
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     2
#
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     3
#  Copyright 2005 K. Thananchayan <thananck@yahoo.com>
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     4
#  Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     5
#  Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     6
#
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
     7
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9996
diff changeset
     8
# GNU General Public License version 2 or any later version.
1082
ce96e316278a Update util.py docstrings, fix walk test
mpm@selenic.com
parents: 1081
diff changeset
     9
37121
5be286db5fb5 procutil: move process/executable management functions to new module
Yuya Nishihara <yuya@tcha.org>
parents: 37120
diff changeset
    10
from __future__ import absolute_import
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
    11
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
    12
import imp
43713
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43712
diff changeset
    13
import os
27358
ac839ee45b6a util: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 27357
diff changeset
    14
import sys
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
    15
43712
664e24207728 procutil: move mainfrozen() to new resourceutil.py
Martin von Zweigbergk <martinvonz@google.com>
parents: 43701
diff changeset
    16
from .. import pycompat
1293
a6ffcebd3315 Enhance the file filtering capabilities.
Bryan O'Sullivan <bos@serpentine.com>
parents: 1292
diff changeset
    17
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
    18
14228
116de1da2154 rename util.main_is_frozen to mainfrozen
Adrian Buehlmann <adrian@cadifra.com>
parents: 14167
diff changeset
    19
def mainfrozen():
6499
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    20
    """return True if we are a frozen executable.
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    21
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    22
    The code supports py2exe (most common, Windows only) and tools/freeze
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    23
    (portable, not much used).
479847ccabe0 Added hgexecutable support for py2exe/frozen scripts
"Paul Moore <p.f.moore@gmail.com>"
parents: 5659
diff changeset
    24
    """
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
    25
    return (
43115
4aa72cdf616f py3: delete b'' prefix from safehasattr arguments
Martin von Zweigbergk <martinvonz@google.com>
parents: 43106
diff changeset
    26
        pycompat.safehasattr(sys, "frozen")
4aa72cdf616f py3: delete b'' prefix from safehasattr arguments
Martin von Zweigbergk <martinvonz@google.com>
parents: 43106
diff changeset
    27
        or pycompat.safehasattr(sys, "importers")  # new py2exe
43551
313e3a279828 cleanup: remove pointless r-prefixes on double-quoted strings
Augie Fackler <augie@google.com>
parents: 43526
diff changeset
    28
        or imp.is_frozen("__main__")  # old py2exe
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 43021
diff changeset
    29
    )  # tools/freeze
43713
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43712
diff changeset
    30
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43712
diff changeset
    31
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43712
diff changeset
    32
# the location of data files matching the source code
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43712
diff changeset
    33
if mainfrozen() and getattr(sys, 'frozen', None) != 'macosx_app':
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43712
diff changeset
    34
    # executable version (py2exe) doesn't support __file__
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43712
diff changeset
    35
    datapath = os.path.dirname(pycompat.sysexecutable)
44136
a90039b07343 resourceutil: ensure `_rootpath` is defined under py2exe
Matt Harbison <matt_harbison@yahoo.com>
parents: 44031
diff changeset
    36
    _rootpath = os.path.dirname(datapath)
43713
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43712
diff changeset
    37
else:
9fb85668ee15 util: move definition of datapath to resourceutil
Martin von Zweigbergk <martinvonz@google.com>
parents: 43712
diff changeset
    38
    datapath = os.path.dirname(os.path.dirname(pycompat.fsencode(__file__)))
44029
52f0140c2604 resourceutil: don't limit resources to the `mercurial` package
Matt Harbison <matt_harbison@yahoo.com>
parents: 43960
diff changeset
    39
    _rootpath = os.path.dirname(datapath)
43877
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    40
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    41
try:
43960
75ec46c63657 resourceutil: use `from importlib import resources`
Martin von Zweigbergk <martinvonz@google.com>
parents: 43911
diff changeset
    42
    from importlib import resources
43877
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    43
44030
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    44
    from .. import encoding
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    45
43877
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    46
    # Force loading of the resources module
43960
75ec46c63657 resourceutil: use `from importlib import resources`
Martin von Zweigbergk <martinvonz@google.com>
parents: 43911
diff changeset
    47
    resources.open_binary  # pytype: disable=module-attr
43877
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    48
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    49
    def open_resource(package, name):
43960
75ec46c63657 resourceutil: use `from importlib import resources`
Martin von Zweigbergk <martinvonz@google.com>
parents: 43911
diff changeset
    50
        return resources.open_binary(  # pytype: disable=module-attr
43877
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    51
            pycompat.sysstr(package), pycompat.sysstr(name)
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    52
        )
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    53
44030
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    54
    def is_resource(package, name):
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    55
        return resources.is_resource(
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    56
            pycompat.sysstr(package), encoding.strfromlocal(name)
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    57
        )
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    58
44031
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    59
    def contents(package):
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    60
        for r in resources.contents(pycompat.sysstr(package)):
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    61
            yield encoding.strtolocal(r)
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    62
43877
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    63
43960
75ec46c63657 resourceutil: use `from importlib import resources`
Martin von Zweigbergk <martinvonz@google.com>
parents: 43911
diff changeset
    64
except (ImportError, AttributeError):
43877
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    65
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    66
    def _package_path(package):
44029
52f0140c2604 resourceutil: don't limit resources to the `mercurial` package
Matt Harbison <matt_harbison@yahoo.com>
parents: 43960
diff changeset
    67
        return os.path.join(_rootpath, *package.split(b'.'))
43877
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    68
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    69
    def open_resource(package, name):
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    70
        path = os.path.join(_package_path(package), name)
1390bb81163e help: get helptext/ data from `resources` module if available
Martin von Zweigbergk <martinvonz@google.com>
parents: 43873
diff changeset
    71
        return open(path, 'rb')
44030
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    72
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    73
    def is_resource(package, name):
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    74
        path = os.path.join(_package_path(package), name)
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    75
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    76
        try:
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    77
            return os.path.isfile(pycompat.fsdecode(path))
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    78
        except (IOError, OSError):
42a897bf678c resourceutil: implement `is_resource()`
Matt Harbison <matt_harbison@yahoo.com>
parents: 44029
diff changeset
    79
            return False
44031
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    80
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    81
    def contents(package):
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    82
        path = pycompat.fsdecode(_package_path(package))
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    83
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    84
        for p in os.listdir(path):
bba9149adc14 resourceutil: implement `contents()` to iterate over resources in a package
Matt Harbison <matt_harbison@yahoo.com>
parents: 44030
diff changeset
    85
            yield pycompat.fsencode(p)