Repository: pex-tool/pex

Issue:
The `--lock` resolver only includes extras from the 1st encounter of a required project in its graph walk.
The issue is summed up by the types here:
https://github.com/pantsbuild/pex/blob/aad57bfaf738c6c493389398232beebdf478a08b/pex/resolve/locked_resolve.py#L532-L553

The `visited` set is of `ProjectName`s and there is no account taken of extras; so if the 1st encounter of the project name in a requirement is `GPy` (for example) and transitive dependency asks for `GPy[plotting]`, the `plotting` extra will be ignored in the `visited` set lookup and the requirement will be seen as resolved by the original `GPy` requirement.

Here's a repro:
```
$ pex3 lock create --style universal --resolver-version pip-2020-resolver --interpreter-constraint "==3.8.*" GPy emukit==0.4.8 -o lock.json
$ pex --python python3.8 --lock lock.json -o all_from_lock.pex
$ pex-tools all_from_lock.pex info -i4
{
    "bootstrap_hash": "194811fc66631583971925a2a1c59e3bfb6c6d49",
    "build_properties": {
        "pex_version": "2.1.78"
    },
    "code_hash": "7506e475892b062c4c5f74f795b09a08a9feb157",
    "distributions": {
        "Cython-0.29.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl": "300800a1c9828650ffeba8325b1afc978c026b1fe81eb923852afc363909ecb3",
        "GPy-1.10.0-py3-none-any.whl": "7618d519f3b108be265f2f963987cf559a560d0c0b836a8f1013c9c87d573aae",
        "decorator-5.1.1-py3-none-any.whl": "7ed6dc469274d0b89fff2c3b5a28d1ddc0937210510a7b13016a8327fc28bc3b",
        "emcee-3.1.1-py2.py3-none-any.whl": "e404ed544fe2c8678b16388b8c35abea3a404a626068d10d0bbb617da540a044",
        "emukit-0.4.8-py3-none-any.whl": "706dfd068037f73b383d3cf8c65c3c926dc67a499e6ba336adebde2585f6c204",
        "numpy-1.22.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl": "fb7879661e502744c416238e5779680ce4e6d2cb6c3c70f30bd364d1475befe9",
        "paramz-0.9.5-py3-none-any.whl": "809087cc272c458d865f491fe8a112e6f200a4776fda9d2271bb4f22acc5db9c",
        "scipy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl": "bcf91dc99a0fbf9915203b26a1371b5798eab488bf7cbc696b4f83b6ce53b060",
        "setuptools-62.1.0-py3-none-any.whl": "8f28465858fe3db86603d42b80b8e3d7f306d805bbae398986878e1d593e2d50",
        "six-1.16.0-py2.py3-none-any.whl": "3e1c439c88d2e7681372427bab751b3fc99969891e95a714fed9604bf7710213"
    },
    "emit_warnings": true,
    "ignore_errors": false,
    "includes_tools": false,
    "inherit_path": "false",
    "interpreter_constraints": [],
    "pex_hash": "e4b596cc533c996c1b31f32ba75804be1dd13b79",
    "pex_path": null,
    "requirements": [
        "GPy",
        "emukit==0.4.8"
    ],
    "strip_pex_env": true,
    "venv": false,
    "venv_bin_path": "false",
    "venv_copies": false,
    "venv_site_packages_copies": false,
    "pex_root": "/home/jsirois/.pex"
}
```

No `matplotlib` makes it into the PEX built from the lock, but the lock shows it should be included when you track (transitive) requirements + extras in-play:
```json
{
  "allow_builds": true,
  "allow_prereleases": false,
  "allow_wheels": true,
  "build_isolation": true,
  "constraints": [],
  "locked_resolves": [
    {
      "locked_requirements": [
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "3a27e95f763a428a739d2add979fa7494c912a32c17c4c38c4d5f082cad165a3",
              "url": "https://files.pythonhosted.org/packages/5c/f9/695d6bedebd747e5eb0fe8fad57b72fdf25411273a39791cde838d5a8f51/cycler-0.11.0-py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "9c87405839a19696e837b3b818fed3f5f69f16f1eec1a1ad77e043dcea9c772f",
              "url": "https://files.pythonhosted.org/packages/34/45/a7caaacbfc2fa60bee42effc4bcc7d7c6dbe9c349500e04f65a861c15eb9/cycler-0.11.0.tar.gz"
            }
          ],
          "project_name": "cycler",
          "requires_dists": [],
          "requires_python": ">=3.6",
          "version": "0.11"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "26d8d0ededca42be50e0ac377c08408e18802b1391caa3aea045a72c1bff47ac",
              "url": "https://files.pythonhosted.org/packages/9f/79/311cfbca90332ab37ef8ea08f1af3266f20a9a0e7a1d652842db832226bb/Cython-0.29.28-py2.py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "49076747b731ed78acf203666c3b3c5d664754ea01ca4527f62f6d8675703688",
              "url": "https://files.pythonhosted.org/packages/0e/04/cb4f477865b0387e1da8a62c71f184a5dad8f835f247388e36251e641538/Cython-0.29.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_24_i686.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "d7d7beb600d5dd551e9322e1393b74286f4a3d4aa387f7bfbaccc1495a98603b",
              "url": "https://files.pythonhosted.org/packages/38/41/c4a5b0947c5122c08712bb28079ea086c49a234638d5abc5bb5bb6739ce1/Cython-0.29.28-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "0378a14d2580dcea234d7a2dc8d75f60c091105885096e6dd5b032be97542c16",
              "url": "https://files.pythonhosted.org/packages/3e/d1/9682cdedfebf099f1c039428a3b30ec38f9675b190bc10b780a3505d3584/Cython-0.29.28-cp38-cp38-musllinux_1_1_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "5e82f6b3dc2133b2e0e2c5c63d352d40a695e40cc7ed99f4cbe83334bcf9ab39",
              "url": "https://files.pythonhosted.org/packages/4e/49/de6a8d259103ecd12d3ed1b674b92c5207d6ad8d0b8dfc4fccb338c7497c/Cython-0.29.28-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "9f2b7c86a73db0d8dbbd885fe67f04c7b787df37a3848b9867270d3484101fbd",
              "url": "https://files.pythonhosted.org/packages/a1/b5/fc74f3976f50d0bdfa333c9e8c5027420bcb9721b5b6a182dc9667fa72df/Cython-0.29.28-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "a3b27812ac9e9737026bfbb1dd47434f3e84013f430bafe1c6cbaf1cd51b5518",
              "url": "https://files.pythonhosted.org/packages/bc/4d/b5b9adba04b688dd8984afde404a89d99bcb656527508bc0201ea431a0d6/Cython-0.29.28-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "d6fac2342802c30e51426828fe084ff4deb1b3387367cf98976bb2e64b6f8e45",
              "url": "https://files.pythonhosted.org/packages/cb/da/54a5d7a7d9afc90036d21f4b58229058270cc14b4c81a86d9b2c77fd072e/Cython-0.29.28.tar.gz"
            }
          ],
          "project_name": "cython",
          "requires_dists": [],
          "requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,>=2.6",
          "version": "0.29.28"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186",
              "url": "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330",
              "url": "https://files.pythonhosted.org/packages/66/0c/8d907af351aa16b42caae42f9d6aa37b900c67308052d10fdce809f8d952/decorator-5.1.1.tar.gz"
            }
          ],
          "project_name": "decorator",
          "requires_dists": [],
          "requires_python": ">=3.5",
          "version": "5.1.1"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "e01d68a84725f6c0734c3c31394e88a7252b12fddb44efe981e10956a7028a93",
              "url": "https://files.pythonhosted.org/packages/ca/41/62ddfd3847bbf9247dcf163de1ff79d56eaa1ac33bfb382f925ab22ba638/emcee-3.1.1-py2.py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "48ffc6a7f5c51760b7a836056184c7286a9959ef81b45b977b02794f1210fb5c",
              "url": "https://files.pythonhosted.org/packages/d1/cf/d6956ba3ec1b1593a4efb1965b35b01793c3adcc701516a4a85b53357807/emcee-3.1.1.tar.gz"
            }
          ],
          "project_name": "emcee",
          "requires_dists": [
            "coverage[toml]; extra == \"tests\"",
            "h5py; extra == \"extras\"",
            "numpy",
            "pytest-cov; extra == \"tests\"",
            "pytest; extra == \"tests\"",
            "scipy; extra == \"extras\""
          ],
          "requires_python": null,
          "version": "3.1.1"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "e19b6504ec4b6f1d4b13f5967c55131ce7e07e3ca6680efc1d67f8ad4f9f488f",
              "url": "https://files.pythonhosted.org/packages/55/2b/470c00da66a70035003eaaabf85c71827e18147c3414f4903b998b542211/emukit-0.4.8.tar.gz"
            }
          ],
          "project_name": "emukit",
          "requires_dists": [
            "GPy[plotting]>=1.9.9",
            "emcee>=2.2.1",
            "matplotlib; extra == \"benchmarking\"",
            "numpy>=1.14.5",
            "scipy>=1.1.0",
            "setuptools>=40.8.0"
          ],
          "requires_python": ">=3",
          "version": "0.4.8"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "b038d1a0dee0079de7ade57071e2e2aced6e35bd697de244ac62938b2b1628c1",
              "url": "https://files.pythonhosted.org/packages/bc/83/43991c6f0dfb395cc9ccf5c19fd51fc6068cb3919cee4b78eddd4b16efd1/fonttools-4.32.0-py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "59a90de72149893167e3d552ae2402c6874e006b9adc3feaf5f6d706fe20d392",
              "url": "https://files.pythonhosted.org/packages/88/27/418ac6f1b85856608df81fe6e72fbb85929d7b904540056f3061e27bba04/fonttools-4.32.0.zip"
            }
          ],
          "project_name": "fonttools",
          "requires_dists": [
            "brotli>=1.0.1; platform_python_implementation == \"CPython\" and extra == \"all\"",
            "brotli>=1.0.1; platform_python_implementation == \"CPython\" and extra == \"woff\"",
            "brotlicffi>=0.8.0; platform_python_implementation != \"CPython\" and extra == \"all\"",
            "brotlicffi>=0.8.0; platform_python_implementation != \"CPython\" and extra == \"woff\"",
            "fs<3,>=2.2.0; extra == \"all\"",
            "fs<3,>=2.2.0; extra == \"ufo\"",
            "lxml<5,>=4.0; extra == \"all\"",
            "lxml<5,>=4.0; extra == \"lxml\"",
            "lz4>=1.7.4.2; extra == \"all\"",
            "lz4>=1.7.4.2; extra == \"graphite\"",
            "matplotlib; extra == \"all\"",
            "matplotlib; extra == \"plot\"",
            "munkres; platform_python_implementation == \"PyPy\" and extra == \"all\"",
            "munkres; platform_python_implementation == \"PyPy\" and extra == \"interpolatable\"",
            "scipy; platform_python_implementation != \"PyPy\" and extra == \"all\"",
            "scipy; platform_python_implementation != \"PyPy\" and extra == \"interpolatable\"",
            "skia-pathops>=0.5.0; extra == \"all\"",
            "skia-pathops>=0.5.0; extra == \"pathops\"",
            "sympy; extra == \"all\"",
            "sympy; extra == \"symfont\"",
            "unicodedata2>=14.0.0; python_version < \"3.11\" and extra == \"all\"",
            "unicodedata2>=14.0.0; python_version < \"3.11\" and extra == \"unicode\"",
            "xattr; sys_platform == \"darwin\" and extra == \"all\"",
            "xattr; sys_platform == \"darwin\" and extra == \"type1\"",
            "zopfli>=0.1.4; extra == \"all\"",
            "zopfli>=0.1.4; extra == \"woff\""
          ],
          "requires_python": ">=3.7",
          "version": "4.32"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "af2b49327a61d3ef246fe0f1099351b2a7f367243dde56373f72ab3bd46843e7",
              "url": "https://files.pythonhosted.org/packages/cb/51/0faf4277f2b53e1ffa5228bc0a1e8204a236ce9091de29fbb7a838e7c9d3/GPy-1.10.0-cp38-cp38-win_amd64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "938b20ca5c1ddac31b825cb319630f62b19e73cfa745fe41fc6dedece67cab54",
              "url": "https://files.pythonhosted.org/packages/ae/62/b49f7a41919f88905e5aa305b629395e37bcb474eaa55c4180a8a05af2f3/GPy-1.10.0-cp38-cp38-macosx_10_9_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "a2b793ef8d0ac71739e7ba1c203bc8a5afa191058b42caa617e0e29aa52aa6fb",
              "url": "https://files.pythonhosted.org/packages/ce/4a/43d6f07b8b493bc216ecf1d5c447809e8c9d0b1b18b0b9db496dfadd87ea/GPy-1.10.0.tar.gz"
            }
          ],
          "project_name": "gpy",
          "requires_dists": [
            "cython>=0.29",
            "ipykernel>=4.1.0; extra == \"notebook\"",
            "ipython>=4.0.0; extra == \"optional\"",
            "ipywidgets>=4.0.3; extra == \"notebook\"",
            "jupyter-client>=4.0.6; extra == \"notebook\"",
            "matplotlib>=3.0; extra == \"plotting\"",
            "mpi4py; extra == \"optional\"",
            "notebook>=4.0.5; extra == \"notebook\"",
            "numpy>=1.7",
            "paramz>=0.9.0",
            "plotly>=1.8.6; extra == \"plotting\"",
            "scipy>=1.3.0",
            "six",
            "sphinx; extra == \"docs\""
          ],
          "requires_python": null,
          "version": "1.10"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "0d98dca86f77b851350c250f0149aa5852b36572514d20feeadd3c6b1efe38d0",
              "url": "https://files.pythonhosted.org/packages/97/2d/32ae1ce44d5b514dce568a809b3bed15d60ee1501b9fa9853a0fee705b59/kiwisolver-1.4.2-cp38-cp38-win_amd64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "8b6086aa6936865962b2cee0e7aaecf01ab6778ce099288354a7229b4d9f1408",
              "url": "https://files.pythonhosted.org/packages/08/47/40596187aa22a094b30e866570c66a0b497750078edd44122aab59a99fc5/kiwisolver-1.4.2-cp38-cp38-win32.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "8ec2e55bf31b43aabe32089125dca3b46fdfe9f50afbf0756ae11e14c97b80ca",
              "url": "https://files.pythonhosted.org/packages/11/be/560da5b0fde2c111784d7dabae1aef6d941840e98a167e2c09e3707fba73/kiwisolver-1.4.2-cp38-cp38-macosx_10_9_universal2.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "240009fdf4fa87844f805e23f48995537a8cb8f8c361e35fda6b5ac97fcb906f",
              "url": "https://files.pythonhosted.org/packages/27/47/9b9e76748d7d002bfcc59038a2cfadca9594df6e32748d2d152926907872/kiwisolver-1.4.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "7f606d91b8a8816be476513a77fd30abe66227039bd6f8b406c348cb0247dcc9",
              "url": "https://files.pythonhosted.org/packages/2b/65/9eb6841880f6214f70e891a97ac945137bb6b2dd65ac35da219a752255fe/kiwisolver-1.4.2.tar.gz"
            },
            {
              "algorithm": "sha256",
              "hash": "cbb5eb4a2ea1ffec26268d49766cafa8f957fe5c1b41ad00733763fae77f9436",
              "url": "https://files.pythonhosted.org/packages/33/b9/37de7a59dd64d76752609962b8f53b1270b287ee150df58a6b6d1170d643/kiwisolver-1.4.2-cp38-cp38-macosx_11_0_arm64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "2e6cda72db409eefad6b021e8a4f964965a629f577812afc7860c69df7bdb84a",
              "url": "https://files.pythonhosted.org/packages/46/42/c585df21d4ffcb1a69c184b668876b9dd96d3d4db6b13f6e6ea1d514535c/kiwisolver-1.4.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "81237957b15469ea9151ec8ca08ce05656090ffabc476a752ef5ad7e2644c526",
              "url": "https://files.pythonhosted.org/packages/58/07/e18a0f74b60eb1833a52378587255b3b55c40919e510c3e61502da36bf37/kiwisolver-1.4.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "1d1078ba770d6165abed3d9a1be1f9e79b61515de1dd00d942fa53bba79f01ae",
              "url": "https://files.pythonhosted.org/packages/6d/3e/e37c9b03baee9f2d392214d8ed68f54996f6a789a4a0dedef8b976dc14e5/kiwisolver-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "b1605c7c38cc6a85212dfd6a641f3905a33412e49f7c003f35f9ac6d71f67720",
              "url": "https://files.pythonhosted.org/packages/89/2c/1b03d8ad14cd866eeb5c6dd4b31b5d00295eae4344f0b17390ffe978283a/kiwisolver-1.4.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "240c2d51d098395c012ddbcb9bd7b3ba5de412a1d11840698859f51d0e643c4f",
              "url": "https://files.pythonhosted.org/packages/c1/1a/c7557d40fc0f94aa589fed98196dac67b030fda63e1b3ea2f269351cc409/kiwisolver-1.4.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl"
            }
          ],
          "project_name": "kiwisolver",
          "requires_dists": [
            "typing-extensions; python_version < \"3.8\""
          ],
          "requires_python": ">=3.7",
          "version": "1.4.2"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "778d398c4866d8e36ee3bf833779c940b5f57192fa0a549b3ad67bc4c822771b",
              "url": "https://files.pythonhosted.org/packages/83/a5/d079d2287ac7a6389059a0e52537dc2e2ff342580512f42f6c7844c451a0/matplotlib-3.5.1-cp38-cp38-win_amd64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "577ed20ec9a18d6bdedb4616f5e9e957b4c08563a9f985563a31fd5b10564d2a",
              "url": "https://files.pythonhosted.org/packages/11/4d/85c14771ac49b172e558f07f98e7c8f0d65ad9d8f1a49c16626897c1b5b4/matplotlib-3.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "b71f3a7ca935fc759f2aed7cec06cfe10bc3100fadb5dbd9c435b04e557971e1",
              "url": "https://files.pythonhosted.org/packages/22/1c/d5e535b36c1de4eef4205656e76ac993c6d01b62cfdcac579edb63cd82e0/matplotlib-3.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "d24e5bb8028541ce25e59390122f5e48c8506b7e35587e5135efcb6471b4ac6c",
              "url": "https://files.pythonhosted.org/packages/55/2e/515c7dc51fc4d0fa2da899d227164672563b1ed4f470c17ef5dccc827e71/matplotlib-3.5.1-cp38-cp38-win32.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "e486f60db0cd1c8d68464d9484fd2a94011c1ac8593d765d0211f9daba2bd535",
              "url": "https://files.pythonhosted.org/packages/5f/eb/1fe0b343ef5020b0175e5f688ee49f1ffa3f88ec95ad97b47f0ac968bddf/matplotlib-3.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "6c094e4bfecd2fa7f9adffd03d8abceed7157c928c2976899de282f3600f0a3d",
              "url": "https://files.pythonhosted.org/packages/62/42/5f6d283d3e52604fb3461d94464bb92a2f4bd55c04530087df7ac3c882d8/matplotlib-3.5.1-cp38-cp38-macosx_10_9_universal2.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "b2e9810e09c3a47b73ce9cab5a72243a1258f61e7900969097a817232246ce1c",
              "url": "https://files.pythonhosted.org/packages/8a/46/425a44ab9a71afd2f2c8a78b039c1af8ec21e370047f0ad6e43ca819788e/matplotlib-3.5.1.tar.gz"
            },
            {
              "algorithm": "sha256",
              "hash": "506b210cc6e66a0d1c2bb765d055f4f6bc2745070fb1129203b67e85bbfa5c18",
              "url": "https://files.pythonhosted.org/packages/9f/35/73d0df80bff331638e42a214d03dfab3606b3687cbbd6724f4e05dd06ccf/matplotlib-3.5.1-cp38-cp38-macosx_10_9_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "b04fc29bcef04d4e2d626af28d9d892be6aba94856cb46ed52bcb219ceac8943",
              "url": "https://files.pythonhosted.org/packages/fe/0b/6cbdf2e71e9502058ab7ed318367464a7d781cf7d15b0ff2624f02d0e9c7/matplotlib-3.5.1-cp38-cp38-macosx_11_0_arm64.whl"
            }
          ],
          "project_name": "matplotlib",
          "requires_dists": [
            "cycler>=0.10",
            "fonttools>=4.22.0",
            "kiwisolver>=1.0.1",
            "numpy>=1.17",
            "packaging>=20.0",
            "pillow>=6.2.0",
            "pyparsing>=2.2.1",
            "python-dateutil>=2.7"
          ],
          "requires_python": ">=3.7",
          "version": "3.5.1"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "c34ea7e9d13a70bf2ab64a2532fe149a9aced424cd05a2c4ba662fd989e3e45f",
              "url": "https://files.pythonhosted.org/packages/d8/30/2facfdcee2f9af55e6a7277c089736edfce1144acb3ccffaf3cff8781058/numpy-1.22.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "e7927a589df200c5e23c57970bafbd0cd322459aa7b1ff73b7c2e84d6e3eae62",
              "url": "https://files.pythonhosted.org/packages/2f/0d/5a0a0bb939f4cc6db6fe777a7221c7c33bf5f5a601f5abfc82692bb4b6aa/numpy-1.22.3-cp38-cp38-win32.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "3ca688e1b9b95d80250bca34b11a05e389b1420d00e87a0d12dc45f131f704a1",
              "url": "https://files.pythonhosted.org/packages/38/c0/c45c5eb0e25247d5fbb333fd0b56e570ba21cf0e3dca3abad174fb780e8c/numpy-1.22.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "201b4d0552831f7250a08d3b38de0d989d6f6e4658b709a02a73c524ccc6ffce",
              "url": "https://files.pythonhosted.org/packages/52/d0/d7a200f2c3d6c6a879dbdc6d762c7dbed542527333ac9a6a72c8ffab9814/numpy-1.22.3-cp38-cp38-macosx_10_14_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "f8c1f39caad2c896bc0018f699882b345b2a63708008be29b1f355ebf6f933fe",
              "url": "https://files.pythonhosted.org/packages/5c/51/872b5c1f40c740e9ebdad87dca8bd42fc7cb5aafab14b96d3a83fca52fd3/numpy-1.22.3-cp38-cp38-macosx_11_0_arm64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "dbc7601a3b7472d559dc7b933b18b4b66f9aa7452c120e87dfb33d02008c8a18",
              "url": "https://files.pythonhosted.org/packages/64/4a/b008d1f8a7b9f5206ecf70a53f84e654707e7616a771d84c05151a4713e9/numpy-1.22.3.zip"
            },
            {
              "algorithm": "sha256",
              "hash": "568dfd16224abddafb1cbcce2ff14f522abe037268514dd7e42c6776a1c3f8e5",
              "url": "https://files.pythonhosted.org/packages/e1/f0/5c3cf38272793a610cc843052e58c93b40b424e2c4a933422cd0bd6391ba/numpy-1.22.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "07a8c89a04997625236c5ecb7afe35a02af3896c8aa01890a849913a2309c676",
              "url": "https://files.pythonhosted.org/packages/fa/f2/f4ec28f935f980167740c5af5a1908090a48a564bed5e689f4b92386d7d9/numpy-1.22.3-cp38-cp38-win_amd64.whl"
            }
          ],
          "project_name": "numpy",
          "requires_dists": [],
          "requires_python": ">=3.8",
          "version": "1.22.3"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522",
              "url": "https://files.pythonhosted.org/packages/05/8e/8de486cbd03baba4deef4142bd643a3e7bbe954a784dc1bb17142572d127/packaging-21.3-py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb",
              "url": "https://files.pythonhosted.org/packages/df/9e/d1a7217f69310c1db8fdf8ab396229f55a699ce34a203691794c5d1cad0c/packaging-21.3.tar.gz"
            }
          ],
          "project_name": "packaging",
          "requires_dists": [
            "pyparsing!=3.0.5,>=2.0.2"
          ],
          "requires_python": ">=3.6",
          "version": "21.3"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "0917211c0f083f344e7f1bc997e0d713dbc147b6380bc19f606119394f820b9a",
              "url": "https://files.pythonhosted.org/packages/d8/37/4abbeb78d30f20d3402887f46e6e9f3ef32034a9dea65d243654c82c8553/paramz-0.9.5.tar.gz"
            }
          ],
          "project_name": "paramz",
          "requires_dists": [
            "climin; extra == \"optimization\"",
            "decorator>=4.0.10",
            "ipykernel>=4.1.0; extra == \"notebook\"",
            "ipywidgets>=4.0.3; extra == \"notebook\"",
            "jupyter-client>=4.0.6; extra == \"notebook\"",
            "notebook>=4.0.5; extra == \"notebook\"",
            "numpy>=1.7",
            "scipy",
            "six",
            "sphinx; extra == \"docs\""
          ],
          "requires_python": null,
          "version": "0.9.5"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "8d79c6f468215d1a8415aa53d9868a6b40c4682165b8cb62a221b1baa47db458",
              "url": "https://files.pythonhosted.org/packages/0d/8f/389d09451d455eb9d40d52932b84d1ce4e0fc107b963498e841e007aa19a/Pillow-9.1.0-pp38-pypy38_pp73-win_amd64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "c7110ec1701b0bf8df569a7592a196c9d07c764a0a74f65471ea56816f10e2c8",
              "url": "https://files.pythonhosted.org/packages/0e/ac/3726c9d83a4ce5da132a75d4c3f66396d46b8432c6ead22e8fe5ba9106f4/Pillow-9.1.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "25023a6209a4d7c42154073144608c9a71d3512b648a2f5d4465182cb93d3477",
              "url": "https://files.pythonhosted.org/packages/19/c3/59708a4a2b30c3e443fb6aeb5268ba1fcfc64770e12871b70fc28db222de/Pillow-9.1.0-cp38-cp38-macosx_11_0_arm64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "17869489de2fce6c36690a0c721bd3db176194af5f39249c1ac56d0bb0fcc512",
              "url": "https://files.pythonhosted.org/packages/26/d3/a2e03e21e82841b7f4dafa196ad2af03f44c7143cfdb281925e74844ed4d/Pillow-9.1.0-cp38-cp38-macosx_10_9_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "5a3ecc026ea0e14d0ad7cd990ea7f48bfcb3eb4271034657dc9d06933c6629a7",
              "url": "https://files.pythonhosted.org/packages/3b/69/d482438c15067b67490fe13fddceaa3e53f1ae5dac18ce2b3f1a5e419eea/Pillow-9.1.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "3f42364485bfdab19c1373b5cd62f7c5ab7cc052e19644862ec8f15bb8af289e",
              "url": "https://files.pythonhosted.org/packages/44/cf/ea13e8a564f7d69077832bd619f8c7dfb643a701a56dc26867aa4cc9f6d8/Pillow-9.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "f401ed2bbb155e1ade150ccc63db1a4f6c1909d3d378f7d1235a44e90d75fb97",
              "url": "https://files.pythonhosted.org/packages/4b/83/090146d7871d90a2643d469c319c1d014e41b315ab5cf0f8b4b6a764ef31/Pillow-9.1.0.tar.gz"
            },
            {
              "algorithm": "sha256",
              "hash": "4fe29a070de394e449fd88ebe1624d1e2d7ddeed4c12e0b31624561b58948d9a",
              "url": "https://files.pythonhosted.org/packages/8f/d6/4b299a9af1c61b9a6e3ecd0aaa596c952d601e44673f1088cc76c6b14421/Pillow-9.1.0-cp38-cp38-win32.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "463acf531f5d0925ca55904fa668bb3461c3ef6bc779e1d6d8a488092bdee378",
              "url": "https://files.pythonhosted.org/packages/a3/09/3993bb76fb412ef64b221cec0d3e43fba46a3c873b879e29f578036ec3e5/Pillow-9.1.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "8782189c796eff29dbb37dd87afa4ad4d40fc90b2742704f94812851b725964b",
              "url": "https://files.pythonhosted.org/packages/ca/bc/2f740e19c3047560259b9593cf63c5d4c970793ce1369af58e6cfc4dd91d/Pillow-9.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "3fddcdb619ba04491e8f771636583a7cc5a5051cd193ff1aa1ee8616d2a692c5",
              "url": "https://files.pythonhosted.org/packages/cb/91/abee1c4c040db36aba441b193f52c2ffe4685f27d292471b3d53ef0317a1/Pillow-9.1.0-cp38-cp38-musllinux_1_1_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "c24f718f9dd73bb2b31a6201e6db5ea4a61fdd1d1c200f43ee585fc6dcd21b34",
              "url": "https://files.pythonhosted.org/packages/cf/81/b40ed97024fa0e7c6305495928996e8f46ab153b07e0f74240f49eec7b7c/Pillow-9.1.0-cp38-cp38-win_amd64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "c5b0ff59785d93b3437c3703e3c64c178aabada51dea2a7f2c5eccf1bcf565a3",
              "url": "https://files.pythonhosted.org/packages/d2/99/d414e5d0e5dfec6ba7d14192efcae2b28b5941fcb7aae68b9568911c7fbb/Pillow-9.1.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl"
            }
          ],
          "project_name": "pillow",
          "requires_dists": [
            "check-manifest; extra == \"tests\"",
            "coverage; extra == \"tests\"",
            "defusedxml; extra == \"tests\"",
            "markdown2; extra == \"tests\"",
            "olefile; extra == \"docs\"",
            "olefile; extra == \"tests\"",
            "packaging; extra == \"tests\"",
            "pyroma; extra == \"tests\"",
            "pytest-cov; extra == \"tests\"",
            "pytest-timeout; extra == \"tests\"",
            "pytest; extra == \"tests\"",
            "sphinx-copybutton; extra == \"docs\"",
            "sphinx-issues>=3.0.1; extra == \"docs\"",
            "sphinx-removed-in; extra == \"docs\"",
            "sphinx-rtd-theme>=1.0; extra == \"docs\"",
            "sphinx>=2.4; extra == \"docs\"",
            "sphinxext-opengraph; extra == \"docs\""
          ],
          "requires_python": ">=3.7",
          "version": "9.1"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "3a35131762c6567813012462e1d496e1d3898f56ab3d386b32f103f7f0c79cf1",
              "url": "https://files.pythonhosted.org/packages/cb/70/53e9f634e6d3aedbe2e99deca846226385d5d845212171e227e2502fb240/plotly-5.7.0-py2.py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "15ab20e9ed8b55f669b3d35e186eb48f9e1fe07321a1337b8b7df8d3573d265a",
              "url": "https://files.pythonhosted.org/packages/aa/92/69d702f337dd179525562631c2e2113504a4ea5b4183f993f372a9b72e3c/plotly-5.7.0.tar.gz"
            }
          ],
          "project_name": "plotly",
          "requires_dists": [
            "six",
            "tenacity>=6.2.0"
          ],
          "requires_python": ">=3.6",
          "version": "5.7"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "ef7b523f6356f763771559412c0d7134753f037822dad1b16945b7b846f7ad06",
              "url": "https://files.pythonhosted.org/packages/d9/41/d9cfb4410589805cd787f8a82cddd13142d9bf7449d12adf2d05a4a7d633/pyparsing-3.0.8-py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "7bf433498c016c4314268d95df76c81b842a4cb2b276fa3312cfb1e1d85f6954",
              "url": "https://files.pythonhosted.org/packages/31/df/789bd0556e65cf931a5b87b603fcf02f79ff04d5379f3063588faaf9c1e4/pyparsing-3.0.8.tar.gz"
            }
          ],
          "project_name": "pyparsing",
          "requires_dists": [
            "jinja2; extra == \"diagrams\"",
            "railroad-diagrams; extra == \"diagrams\""
          ],
          "requires_python": ">=3.6.8",
          "version": "3.0.8"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9",
              "url": "https://files.pythonhosted.org/packages/36/7a/87837f39d0296e723bb9b62bbb257d0355c7f6128853c78955f57342a56d/python_dateutil-2.8.2-py2.py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86",
              "url": "https://files.pythonhosted.org/packages/4c/c4/13b4776ea2d76c115c1d1b84579f3764ee6d57204f6be27119f13a61d0a9/python-dateutil-2.8.2.tar.gz"
            }
          ],
          "project_name": "python-dateutil",
          "requires_dists": [
            "six>=1.5"
          ],
          "requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7",
          "version": "2.8.2"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "5e73343c5e0d413c1f937302b2e04fb07872f5843041bcfd50699aef6e95e399",
              "url": "https://files.pythonhosted.org/packages/56/a3/591dbf477c35f173279afa7b9ba8e13d9c7c3d001e09aebbf6100aae33a8/scipy-1.8.0-cp38-cp38-win_amd64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "38aa39b6724cb65271e469013aeb6f2ce66fd44f093e241c28a9c6bc64fd79ed",
              "url": "https://files.pythonhosted.org/packages/0c/a5/dca69d5ddb81da167d434f72b0ecfa10f68bf99b648fc49e4d9db81dff1c/scipy-1.8.0-cp38-cp38-macosx_10_9_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "559a8a4c03a5ba9fe3232f39ed24f86457e4f3f6c0abbeae1fb945029f092720",
              "url": "https://files.pythonhosted.org/packages/70/ba/82877dfa10828cb585cff9df6d87a66564a0571859c15488d16a9413598a/scipy-1.8.0-cp38-cp38-macosx_12_0_arm64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "92b2c2af4183ed09afb595709a8ef5783b2baf7f41e26ece24e1329c109691a7",
              "url": "https://files.pythonhosted.org/packages/84/d1/74a1e3b528556bdb94a1360e731eb838ffcb05106ea95eb8ba4af85f71e6/scipy-1.8.0-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "31d4f2d6b724bc9a98e527b5849b8a7e589bf1ea630c33aa563eda912c9ff0bd",
              "url": "https://files.pythonhosted.org/packages/b4/a2/4faa34bf0cdbefd5c706625f1234987795f368eb4e97bde9d6f46860843e/scipy-1.8.0.tar.gz"
            },
            {
              "algorithm": "sha256",
              "hash": "a279e27c7f4566ef18bab1b1e2c37d168e365080974758d107e7d237d3f0f484",
              "url": "https://files.pythonhosted.org/packages/bd/84/6f6218c338e1fa77f715e2db777b162bf1e4535289cf462ee3f002612ed6/scipy-1.8.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "ad5be4039147c808e64f99c0e8a9641eb5d2fa079ff5894dcd8240e94e347af4",
              "url": "https://files.pythonhosted.org/packages/d2/27/b2648569175ba233cb6ad13029f8df4049a581c268156c5dd1db5ca44a8c/scipy-1.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "3d9dd6c8b93a22bf9a3a52d1327aca7e092b1299fb3afc4f89e8eba381be7b59",
              "url": "https://files.pythonhosted.org/packages/e5/2c/fd50b818174554057294ea7f788bd3f8d448bb0f9cbefeeaf8e19067bee0/scipy-1.8.0-cp38-cp38-win32.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "f4a6d3b9f9797eb2d43938ac2c5d96d02aed17ef170c8b38f11798717523ddba",
              "url": "https://files.pythonhosted.org/packages/f4/45/9b57c6fd181f5031d99e1395b3cc3bc83653ff064c614ff211882bd85d50/scipy-1.8.0-cp38-cp38-macosx_12_0_universal2.macosx_10_9_x86_64.whl"
            }
          ],
          "project_name": "scipy",
          "requires_dists": [
            "numpy<1.25.0,>=1.17.3"
          ],
          "requires_python": "<3.11,>=3.8",
          "version": "1.8"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "26ead7d1f93efc0f8c804d9fafafbe4a44b179580a7105754b245155f9af05a8",
              "url": "https://files.pythonhosted.org/packages/fb/58/9efbfe68482dab9557c49d433a60fff9efd7ed8835f829eba8297c2c124a/setuptools-62.1.0-py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "47c7b0c0f8fc10eec4cf1e71c6fdadf8decaa74ffa087e68cd1c20db7ad6a592",
              "url": "https://files.pythonhosted.org/packages/ea/a3/3d3cbbb7150f90c4cf554048e1dceb7c6ab330e4b9138a40e130a4cc79e1/setuptools-62.1.0.tar.gz"
            }
          ],
          "project_name": "setuptools",
          "requires_dists": [
            "build[virtualenv]; extra == \"testing\"",
            "build[virtualenv]; extra == \"testing-integration\"",
            "filelock>=3.4.0; extra == \"testing\"",
            "filelock>=3.4.0; extra == \"testing-integration\"",
            "flake8-2020; extra == \"testing\"",
            "furo; extra == \"docs\"",
            "ini2toml[lite]>=0.9; extra == \"testing\"",
            "jaraco.envs>=2.2; extra == \"testing\"",
            "jaraco.envs>=2.2; extra == \"testing-integration\"",
            "jaraco.packaging>=9; extra == \"docs\"",
            "jaraco.path>=3.2.0; extra == \"testing\"",
            "jaraco.path>=3.2.0; extra == \"testing-integration\"",
            "jaraco.tidelift>=1.4; extra == \"docs\"",
            "mock; extra == \"testing\"",
            "pip-run>=8.8; extra == \"testing\"",
            "pip>=19.1; extra == \"testing\"",
            "pygments-github-lexers==0.0.5; extra == \"docs\"",
            "pytest-black>=0.3.7; platform_python_implementation != \"PyPy\" and extra == \"testing\"",
            "pytest-checkdocs>=2.4; extra == \"testing\"",
            "pytest-cov; platform_python_implementation != \"PyPy\" and extra == \"testing\"",
            "pytest-enabler; extra == \"testing-integration\"",
            "pytest-enabler>=1.0.1; extra == \"testing\"",
            "pytest-flake8; extra == \"testing\"",
            "pytest-mypy>=0.9.1; platform_python_implementation != \"PyPy\" and extra == \"testing\"",
            "pytest-perf; extra == \"testing\"",
            "pytest-xdist; extra == \"testing\"",
            "pytest-xdist; extra == \"testing-integration\"",
            "pytest; extra == \"testing-integration\"",
            "pytest>=6; extra == \"testing\"",
            "rst.linker>=1.9; extra == \"docs\"",
            "sphinx-favicon; extra == \"docs\"",
            "sphinx-inline-tabs; extra == \"docs\"",
            "sphinx; extra == \"docs\"",
            "sphinxcontrib-towncrier; extra == \"docs\"",
            "tomli-w>=1.0.0; extra == \"testing\"",
            "tomli; extra == \"testing-integration\"",
            "virtualenv>=13.0.0; extra == \"testing\"",
            "virtualenv>=13.0.0; extra == \"testing-integration\"",
            "wheel; extra == \"testing\"",
            "wheel; extra == \"testing-integration\""
          ],
          "requires_python": ">=3.7",
          "version": "62.1"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254",
              "url": "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926",
              "url": "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz"
            }
          ],
          "project_name": "six",
          "requires_dists": [],
          "requires_python": "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7",
          "version": "1.16"
        },
        {
          "artifacts": [
            {
              "algorithm": "sha256",
              "hash": "f78f4ea81b0fabc06728c11dc2a8c01277bfc5181b321a4770471902e3eb844a",
              "url": "https://files.pythonhosted.org/packages/f2/a5/f86bc8d67c979020438c8559cc70cfe3a1643fd160d35e09c9cca6a09189/tenacity-8.0.1-py3-none-any.whl"
            },
            {
              "algorithm": "sha256",
              "hash": "43242a20e3e73291a28bcbcacfd6e000b02d3857a9a9fff56b297a27afdc932f",
              "url": "https://files.pythonhosted.org/packages/2c/f5/04748914f5c78f7418b803226bd56cdddd70ac369b936b3e24f5158017f1/tenacity-8.0.1.tar.gz"
            }
          ],
          "project_name": "tenacity",
          "requires_dists": [
            "reno; extra == \"doc\"",
            "sphinx; extra == \"doc\"",
            "tornado>=4.5; extra == \"doc\""
          ],
          "requires_python": ">=3.6",
          "version": "8.0.1"
        }
      ],
      "platform_tag": [
        "cp310",
        "cp310",
        "manylinux_2_35_x86_64"
      ]
    }
  ],
  "pex_version": "2.1.78",
  "prefer_older_binary": false,
  "requirements": [
    "GPy",
    "emukit==0.4.8"
  ],
  "requires_python": [
    "==3.8.*"
  ],
  "resolver_version": "pip-2020-resolver",
  "style": "universal",
  "transitive": true,
  "use_pep517": null
}
```


Discussion:

Resolving patch:
diff --git a/pex/resolve/locked_resolve.py b/pex/resolve/locked_resolve.py
--- a/pex/resolve/locked_resolve.py
+++ b/pex/resolve/locked_resolve.py
@@ -29,6 +29,7 @@
         Callable,
         DefaultDict,
         Deque,
+        Dict,
         Iterable,
         Iterator,
         List,
@@ -541,16 +542,24 @@ def request_resolve(requests):
                 if target.requirement_applies(request.requirement, extras=request.extras)
             )
 
-        visited = set()  # type: Set[ProjectName]
+        resolved = {}  # type: Dict[ProjectName, Set[str]]
         request_resolve(_ResolveRequest.root(requirement) for requirement in requirements)
         while to_be_resolved:
             resolve_request = to_be_resolved.popleft()
             project_name = resolve_request.project_name
             required.setdefault(project_name, []).append(resolve_request)
 
-            if not transitive or project_name in visited:
+            if not transitive:
                 continue
-            visited.add(project_name)
+
+            required_extras = set(resolve_request.requirement.extras)
+            if project_name not in resolved:
+                resolved[project_name] = required_extras
+            else:
+                resolved_extras = resolved[project_name]
+                if required_extras.issubset(resolved_extras):
+                    continue
+                resolved_extras.update(required_extras)
 
             for locked_requirement in repository[project_name]:
                 request_resolve(resolve_request.request_dependencies(locked_requirement))


Test patch:
diff --git a/tests/integration/test_lock_resolver.py b/tests/integration/test_lock_resolver.py
--- a/tests/integration/test_lock_resolver.py
+++ b/tests/integration/test_lock_resolver.py
@@ -5,6 +5,7 @@
 import hashlib
 import os
 import re
+import shutil
 import subprocess
 from textwrap import dedent
 
@@ -14,13 +15,14 @@
 from pex import dist_metadata
 from pex.cli.testing import run_pex3
 from pex.common import safe_open
+from pex.dist_metadata import ProjectNameAndVersion
 from pex.interpreter import PythonInterpreter
 from pex.pep_440 import Version
 from pex.pep_503 import ProjectName
 from pex.pex_info import PexInfo
 from pex.resolve import lockfile
 from pex.resolve.locked_resolve import LockedRequirement
-from pex.testing import make_env, run_pex_command
+from pex.testing import built_wheel, make_env, run_pex_command
 from pex.typing import TYPE_CHECKING
 from pex.util import CacheHelper
 
@@ -388,3 +390,130 @@ def test_issue_1413_portable_find_links(tmpdir):
     )
     result.assert_success()
     assert colors.blue("Relocatable!") == result.output.strip()
+
+
+def test_issue_1717_transitive_extras(
+    tmpdir,  # type: Any
+):
+    # type: (...) -> None
+
+    find_links = os.path.join(str(tmpdir), "find-links")
+    # The dep graph where a naive depth first resolve not accounting for extras would grab:
+    #   [root, middle_man_with_extras, A, B, C]
+    # Instead of the expected:
+    #   [root, middle_man_with_extras, A, extra1, B, extra2, C]
+    #
+    # root ->
+    #     middle_man_with_extras
+    #     A ->
+    #         middle_man_with_extras[E1] ->
+    #             extra1
+    #         B ->
+    #             middle_man_with_extras[E1,E2] ->
+    #                 extra1
+    #                 extra2
+    #             C ->
+    #                 middle_man_with_extras[E2] ->
+    #                     extra2
+
+    with built_wheel(
+        name="root",
+        install_reqs=["middle_man_with_extras", "A"],
+    ) as root, built_wheel(
+        name="A",
+        install_reqs=["middle_man_with_extras[E1]", "B"],
+    ) as A, built_wheel(
+        name="B",
+        install_reqs=["middle_man_with_extras[E1,E2]", "C"],
+    ) as B, built_wheel(
+        name="C",
+        install_reqs=["middle_man_with_extras[E2]"],
+    ) as C, built_wheel(
+        name="middle_man_with_extras",
+        extras_require={"E1": ["extra1"], "E2": ["extra2"]},
+    ) as middle_man_with_extras, built_wheel(
+        name="extra1",
+    ) as extra1, built_wheel(
+        name="extra2",
+    ) as extra2:
+        os.mkdir(find_links)
+        for wheel in root, A, B, C, middle_man_with_extras, extra1, extra2:
+            shutil.move(wheel, find_links)
+
+    lock = os.path.join(str(tmpdir), "lock")
+    run_pex3(
+        "lock",
+        "create",
+        "--resolver-version",
+        "pip-2020-resolver",
+        "--no-pypi",
+        "-f",
+        find_links,
+        "root",
+        "-o",
+        lock,
+    ).assert_success()
+
+    pex = os.path.join(str(tmpdir), "pex")
+    pex_root = os.path.join(str(tmpdir), "pex_root")
+    create_pex_args = [
+        "--lock",
+        lock,
+        "-o",
+        pex,
+        "--pex-root",
+        pex_root,
+        "--runtime-pex-root",
+        pex_root,
+    ]
+    test_pex_args = [pex, "-c", "import root"]
+
+    def assert_requirements(pex_info):
+        # type: (PexInfo) -> None
+        assert ["root"] == list(pex_info.requirements)
+
+    def assert_dists(
+        pex_info,  # type: PexInfo
+        *expected_project_names  # type: str
+    ):
+        # type: (...) -> None
+        assert set(expected_project_names) == {
+            ProjectNameAndVersion.from_filename(d).project_name for d in pex_info.distributions
+        }
+
+    run_pex_command(args=["pex==2.1.78", "-cpex", "--"] + create_pex_args).assert_success()
+    pex_info = PexInfo.from_pex(pex)
+    assert_requirements(pex_info)
+    assert_dists(pex_info, "root", "middle_man_with_extras", "A", "B", "C")
+
+    process = subprocess.Popen(args=test_pex_args, stderr=subprocess.PIPE)
+    _, stderr = process.communicate()
+    assert 0 != process.returncode
+
+    assert (
+        re.search(
+            r"ResolveError: Failed to resolve requirements from PEX environment @ {pex_root}.*\n"
+            # Interpreter platform string wildcarded:
+            r"Needed [a-z0-9_-]+ compatible dependencies for:\n"
+            r' 1: extra1; extra == "e1"\n'
+            r"    Required by:\n"
+            r"      FingerprintedDistribution\(distribution=middle-man-with-extras .*\)\n"
+            # Python 2 unicode literal wildcarded:
+            r"    But this pex had no u?'extra1' distributions.\n"
+            r' 2: extra2; extra == "e2"\n'
+            r"    Required by:\n"
+            r"      FingerprintedDistribution\(distribution=middle-man-with-extras .*\)\n"
+            # Python 2 unicode literal wildcarded:
+            r"    But this pex had no u?'extra2' distributions.\n".format(
+                pex_root=re.escape(pex_root)
+            ),
+            stderr.decode("utf-8"),
+        )
+        is not None
+    )
+
+    run_pex_command(args=create_pex_args).assert_success()
+    pex_info = PexInfo.from_pex(pex)
+    assert_requirements(pex_info)
+    assert_dists(pex_info, "root", "middle_man_with_extras", "A", "extra1", "B", "extra2", "C")
+    subprocess.check_call(args=test_pex_args)