early-twilight-26336
04/01/2025, 8:33 PMTraceback (most recent call last):
File "/Users/dvangeest/.pex/venvs/70bb4cb6cccc66b8cb8e4df6a356c265d7a23b11/779eb2cc0ca9e2fdd204774cbc41848e4e7c5055/pex", line 329, in <module>
func = namespace = getattr(namespace, attr)
^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: module 'granian' has no attribute 'cli'
any ideas?early-twilight-26336
04/01/2025, 8:38 PMpex_binary(
name="bin-local",
dependencies=[":service", "3rdparty/python:common#granian"],
execution_mode="venv",
layout="packed",
script="granian",
....broad-processor-92400
04/02/2025, 12:47 AMgranian. Something like pex granian --script=granian.
If you didn't have me here to guess at a starting point, I'd suggest looking into the sandboxes and editing `__run.sh`: https://www.pantsbuild.org/stable/docs/using-pants/troubleshooting-common-issues#debug-tip-inspect-the-sandbox-with---keep-sandboxes
For this, there's two sandboxes that are likely relevant:
• the sandbox for building the pex (i.e. tells us which flags are being passed)
• the sandbox for running
I'd inspect the second one, and then copy the invocation into the __run.sh of the first one (to have it all in one place), and check it reproduces, and then cut args out to get to the minimal reproducer.wide-midnight-78598
04/02/2025, 12:43 PM⏺ demo/src % tree
.
|____hellogranian
| |______init__.py
| |____main.py
|____BUILD
python_sources(
name="lib",
sources=["**/*.py"],
)
pex_binary(
name="bin",
dependencies=[":lib", "//:reqs#granian"],
entry_point="granian",
args=["--interface", "asgi", "hellogranian.main:app"],
)
demo % pants run src:bin
[INFO] Starting granian (main PID: 4163)
[INFO] Listening at: <http://127.0.0.1:8000>
[INFO] Spawning worker-1 with PID: 4169
[WARNING] ASGI Lifespan errored, continuing without Lifespan support (to avoid Lifespan completely use "asginl" interface)
[INFO] Started worker-1
[INFO] Started worker-1 runtime-1broad-processor-92400
04/03/2025, 4:00 AMentry_point="granian" instead of script="granian", I suspectwide-midnight-78598
04/03/2025, 11:04 AMgranian is the “thing” we care about, while the app is just an arg passed in.
FastAPI and such also allow running as a script (aka, if __name__ == “__main__” can sometimes be handy for dev). Although, I guess FastAPI also has a CLI now, that I’ve just never used - so maybe that would run similarly to this.
But yeah, one of probably 10 ways to run thisearly-twilight-26336
04/03/2025, 1:47 PMmain. I will try the entry_point idea as well.