Thanks for pointing me to `PexFromTargetsRequest` ...
# plugins
p
Thanks for pointing me to
PexFromTargetsRequest
@bitter-ability-32190! That worked perfectly for one of the local scripts I need to run in my pants plugin. But, I'm struggling with the other script. It is a python script named
st2-generate-schemas
- note the dashes - so, I can't figure out how how to get PEX to run the script. Using
--no-process-cleanup
, I can see that my
VenvPex
includes
bin/st2-generate-schemas
and
st2common/
which is a module used by the script. If I do
PexFromTargetsRequest(..., main=ConsoleScript("st2-generate-schemas"))
, I get pex_builder errors because nothing has that entry point registered. Same thing if I do
ConsoleScript("bin/st2-generate-schemas")
. If I do
PexFromTargetsRequest(..., main=EntryPoint("st2-generate-schemas")
, then it silently does nothing. But when I run it manually with
__run.sh
, I see the
ImportError: No module named st2-generate-schemas
. Leaving off
main=
doesn't work either, because then it pex just opens a repl. It's not an entry point, and it's not importable as a module. How do I run this script?
āœ… 1
h
how do you normally invoke the script?
p
It's an executable on the path.
h
interesting, that would suggest to me it is using entry points. Do you have the setup.py or pyproject.toml for it?
It's a hand crafted script that gets distributed (today) in an rpm/deb. Eventually I could see it becoming an entry point once I get everyone on board with distributing wheels ... But in the mean time, here I am trying to run the script.
šŸ‘ 1
I believe the shebang gets mangled when loaded in the deb/rpm so that it uses python from the venv that includes the st2common module btw.
e
ConsoleScript
is for the console script concept from setuptools. This is not that. That leaves
EntryPoint
which must be a valid Python module (and maybe function in that module) which this is not. So, as things stand, the
-
naming won't work with Pants or Pex.
😢 1
h
probably there's a better way to do this, but what about creating a custom launcher script that loads it? If the dash wasn't there, this would look like:
Copy code
from bin import my_script

if __name__ == "__main__":
   my_script.main()
We use a custom Poetry launcher: https://github.com/pantsbuild/pants/blob/1c65b9c7ee88606eb288e22fa1bc5c3267751082/src/python/pants/backend/python/subsystems/poetry.py#L36-L47 https://github.com/pantsbuild/pants/blob/1c65b9c7ee88606eb288e22fa1bc5c3267751082/src/python/pants/backend/python/goals/lockfile.py#L210-L221 But that import won't work. So I'm naively wondering if you can somehow load it as a resource, like
pkgutil.get_data()
. Or, pre-process the executable file to use underscores
p
hmm. I think I'm going to have to do more extensive refactoring to divorce that
-
script from its logic then. Thanks for validating that it doesn't work the way I was attempting.
There are a bunch of scripts like that, so, hopefully I can punt at moving the others until later.
šŸ‘ 1
Thanks @enough-analyst-54434 and @hundreds-father-404
ā¤ļø 1
e
N.B.: Kebab case could be supported using existing Pex code that slurps any file, compiles its AST and executes it: https://github.com/pantsbuild/pex/blob/825706c2cf6345c2ec494817080729c498d637cf/pex/pex.py#L688-L708 Some elbow grease plumbing options in Pex and Pants would be called for though.
p
elbow grease => signifcant effort?
e
Not sure, seems small. Boils down to evaling a file you slurp in.
p
Wow. That's quite minor. Cool.
e
I'll probably get that released today, but the next step over in Pants may be something you're interested in tackling.
p
So, once pants gets pex 2.1.93+, it will be able to use the new
--exe
arg for kebab-scripts. What might the UX look like in pants? (once that elbow grease has been applied) We already have
ConsoleScript
and
EntryPoint
, so maybe
Executable
? So:
PexFromTargetsRequest(..., main=Executable("bin/st2-generate-schemas"))
?
b
FWIW the field name on
pex_binary
is
script
, so maybe that? šŸ˜‰
p
That is for console script, a setuptools thing.
This is a new feature in pex: https://github.com/pantsbuild/pex/pull/1807
b
There's no description. Tl;DR on the difference?
p
Mapping PEX args to Pants: •
-m
,
-e
, `--entry-point`:
EntryPoint
-- a
module
or
module:func
reference •
-c
,
--script
, `--console-script`:
ConsoleScript
-- this references the name of a
console_scripts
entry point •
--exe
,
--executable
, `--python-script`:
SomethingNewHere
any python script The key difference is that for
EntryPoint
and
ConsoleScript
, the python file must be importable. I have some kebab-case python scripts (
st2-generate-schemas
) that cannot be imported because of the dash. So, the new pex feature makes it possible to run those scripts via pex.
b
Ah. Yeah maybe we use
main
on the target and lean into objects farther in BUILD files
p
I was thinking from the perspective of a plugin author, which is where that
main=
comes from (it already exists like that on the
PexFromTargetsRequest
. Maybe we would need a new
executable
field on
pex_binary
target to expose this to users as well. šŸ¤”
We can probably just duplicate the
script
field, and track down where it is used to add
executable
everywhere it is needed.
b
Yeah, we should expose this both to users and plugins authors. And while we're in, I think we can make it nice and straightforward. The plugin API already has
main
as a union type, we should make the target sikilar
Although we don't support union field types (yet) šŸ™ˆ
šŸ™ˆ 1
Honestly it's not hard to implement, but it would be hard to document, I think. It requires a certain je ne sais quoi
But for your purposes, we can muck with plugin API first. Maybe
PyScript
?
p
There we go, here's a stub commit. Don't know when I'll pick it up again. https://github.com/pantsbuild/pants/compare/main...cognifloyd:pants:pex-exe-arg
I used
Executable
, but maybe a more verbose
PythonExecutableScript
would be better... anyway.