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