hundreds-father-404
10/29/2020, 4:43 PMhundreds-father-404
10/29/2020, 4:49 PMrequirements.pex
and jupyter.pex
use the same interpreter constraints. This is key to avoid a runtime error where you have “missing wheels”.
In your v1 plugin, it sounds like it was manual to tell Pants whether to use Py2 or Py3. I recommend making this automatic; the tool can do that hard work for you.
I recommend using the same approach used by ipython.py
. PexFromTargetsRequest.for_requirements()
will compute the final compatibility for all your input targets and their dependencies when merged. Then, you can pipe this into the PexRequest
for creating Jupyter. https://github.com/pantsbuild/pants/blob/c98ee3696818bc9945968ba94a14180d9466a6e7/src/python/pants/backend/python/goals/repl.py#L61-L69 and line 83
Make sure that the Jupyter hardcoded requirements work with both Py2 and Py3. If you want the versions to be different, use that trick I showed you this week to have conditional versions, the whole foo==13 ; sys_version>3
thingjolly-midnight-72759
10/29/2020, 4:51 PMjolly-midnight-72759
10/29/2020, 4:52 PMhundreds-father-404
10/29/2020, 4:53 PMjolly-midnight-72759
10/30/2020, 1:08 AMrequirements_pex_request
does not have a interpreter_contraints
like the code in pants.backend.python.goals.repl
.hundreds-father-404
10/30/2020, 1:09 AMjolly-midnight-72759
10/30/2020, 1:09 AMdir(requirements_pex_request)
21:07:04.25 [INFO] ['__abstractmethods__', '__annotations__', '__args__', '__await__', '__class__', '__dataclass_fields__', '__dataclass_params__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__extra__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__next_in_mro__', '__orig_bases__', '__origin__', '__parameters__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__tree_hash__', '__weakref__', '_abc_cache', '_abc_generic_negative_cache', '_abc_generic_negative_cache_version', '_abc_registry', '_gorg', '_is_frozen', '_validate_input', '_validate_input_type', '_validate_output_type', 'input', 'input_type', 'output_type', 'parse_input_and_output_types']
dir(requirements_pex_request.input)
21:07:04.25 [INFO] ['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_is_frozen', 'additional_args', 'additional_inputs', 'additional_requirements', 'additional_sources', 'addresses', 'description', 'direct_deps_only', 'entry_point', 'for_requirements', 'hardcoded_interpreter_constraints', 'include_source_files', 'internal_only', 'output_filename', 'platforms']
jolly-midnight-72759
10/30/2020, 1:09 AMjolly-midnight-72759
10/30/2020, 1:10 AMhundreds-father-404
10/30/2020, 1:13 AMinterpreter_constraints
is that you are saying await Get(Pex, PexFromTargetsRequest)
. This will return a Pex
object. Normally, that’s what you want, so that you actually create the Pex file.
But here, we’re gonna do something weird, that we instead say await Get(PexRequest, PexFromTargetsRequest)
. This will get us back a PexRequest
object, which has an interpreter_constraints
field.
When you say await Get(Pex, PexFromTargetsRequest)
, what really happens is the engine goes from PexFromTargetsRequest -> PexRequest -> Pex
, and does that middle step for you. Here, we care about the value in the middle step, so we explicitly ask for it.
Then, once you have that intermediate PexRequest
object, you’ll need to say await Get(Pex, PexRequest, my_pex_request_object_from_earlier)
jolly-midnight-72759
10/30/2020, 1:15 AMPexFromTargetsRequest
? i.e. Get(PexRequest, PexFromTargetsRequest, PexFromTargetsRequest.for_requirements(...),)
hundreds-father-404
10/30/2020, 1:18 AMrepl.py
, for the create_ipython_repl_request
rule, I’m seeing an await Get(Get(PexRequest, PexFromTargetsRequest, PexFromTargetsRequest.for_requirements(...))
at the top so that we get the intermediate PexRequest
.
Then we set up right after the Get(Pex, PexRequest)
for it.
And then another Get(Pex, PexRequest)
, but this time it’s for ipython, rather than requirementsjolly-midnight-72759
10/30/2020, 1:19 AMGet(Pex, PexRequest)
returns a pex, not a pex_request. So I should rename jupyter_pex_request
to something else?jolly-midnight-72759
10/30/2020, 1:20 AMGet()
question: https://gist.github.com/rcuza/bbcf8f5a13964db7760ff376649c1a44#file-goals-py-L111-L117hundreds-father-404
10/30/2020, 1:22 AMvariable name question.The variable names are kind of a mess here. We use the word “request” way too much. Sorry about that To clarify,
await Get(Pex, PexRequest)
will give back a Pex
object. It will pause execution of Python and cause the engine to trigger a subprocess to build the Pex. Note the await
.
If we leave off the await
, and only have Get(Pex, PexRequest)
, then we only have a Get
object. Nothing actually gets executed yet, until we say await
later. We’ve been calling this a “request”, which is super confusing.jolly-midnight-72759
10/30/2020, 1:26 AMjolly-midnight-72759
10/30/2020, 1:26 AMhundreds-father-404
10/30/2020, 1:28 AMPexRequest
hah
Maybe something like ipython_pex_get
is a better name than ipython_pex_request