Maybe a silly question.. but how does archiving/ta...
# general
p
Maybe a silly question.. but how does archiving/taring a pex file and supporting files work in practice? What I mean is.. if I have a tar that contains: • pex • index.html If I want to serve the index.html from the pex file.. would it be the path to whereever the tar was extracted?
Basically I have a shell_command creating a react app. I can use the experimental_wrap_as_resources to pull that into PEX.. but I can't load it with importlib unless a
__init__.py
file lives in the directory? Or at least it isn't working for me.
b
We have resource directories that we can load via
importlib
, the directory itself doesn't have
__init__.py
in it, although it is nested within a top-level one that does. I think PEXes ~always run as actual files on disk these days, so using
open
+
__file__
can likely work too. I don't know of a way to identify the location of the original PEX file, although there might be some goodies hiding in https://pex.readthedocs.io/en/v2.1.138/api/vars.html
ah, maybe the
PEX
environment variable
p
Got it. I’ll try again. Almost certainly a typo. Shrug. Another thing I don’t understand does importlib unzip things in a context (then clean up when it closes?) Essentially we load a bunch of static files into flask. Today people do this with ../../path/to/staticDir kind of thing.
Load with flask.send_file* I suppose I can do that in a contextmanager 🤔
b
Do you mean
<http://importlib.resources.as|importlib.resources.as>_file
? It seems to have documentation that suggests you are right... that said, by the time user code within a PEX is running, it's always normal files on disk; the unzipping happens as part of PEX start-up
p
Hmm okay where is where I'm at. I have this function
Copy code
def __get_resource_dir_path(package: str, directory: str, file: str = None) -> str:
    """Get a posix path to a resource directory or file within the directory."""
    directories = directory.split('/')
    resource = importlib.resources.files(package)

    path = resource.joinpath(*directories)

    if file:
        path = path.joinpath(file)
        if not path.exists():
            raise FileNotFoundError(f"The file '{file}' does not exist in the directory path '{directory}'")
    else:
        if not path.is_dir():
            print(resource.joinpath())
            raise NotADirectoryError(f"The directory path '{directory}' does not exist")

    return path.as_posix()
and this BUILD file
Copy code
python_sources(
    dependencies=[
        "//frontend:python-sources",
    ]
)

pex_binary(
    name="binary",
    entry_point="main.py",
)
pants run path/to/main.py
-> works
pants run path/to:binary
-> throws a NotADirectoryError 🤔 How does run
path/to/module.py
differ from run
path/to:binary
?
Hmm I see. I think that the frontend
__init__.py
is being passed but the actual build/dist dirs are just showing up without an init file
in
teletom/frontend/BUILD
I have
Copy code
...
shell_command(
    name="build",
    command="npm run build",
    tools=["node", "sh", "npm"],
    execution_dependencies=[":node-modules", ":frontend-sources"],
    extra_env_vars=["CI=true"],
    output_directories=["dist", "build"],
    timeout=300,
)

experimental_wrap_as_resources(
    name="resources",
    inputs=[":build"],
)

python_sources(name="python-sources", dependencies=[":resources"])
in experimental/gerald/BUILD I have
Copy code
python_sources(
    dependencies=[
        "//teletom/frontend:python-sources",
    ]
)

pex_binary(
    name="binary",
    entry_point="main.py",
)
Adding this to my
package.json
did the trick
Copy code
"postbuild": "touch __init__.py",
    "pantsbuild": "npm run build && npm run postbuild",
Then I can load the package
teletom.frontend