Support annotations on pip packages with extras. (#865)

* Support annotations on pip packages with extras.

E.g., the following requirement:

```
requests[security]>=2.8.1
```

This is handled correctly by all of the other plumbing, but trying
to add an annotation to `requests` will fail. This is because
annotations have separate logic for parsing requirements in the
generated .bzl file. It would previously turn the requirement into
`requests[security]` rather than just `requests`.

* Add test verifying that annotations work for packages with extras.
diff --git a/examples/pip_parse_vendored/requirements.bzl b/examples/pip_parse_vendored/requirements.bzl
index 33199b0..6f1fbd0 100644
--- a/examples/pip_parse_vendored/requirements.bzl
+++ b/examples/pip_parse_vendored/requirements.bzl
@@ -38,7 +38,7 @@
 def _get_annotation(requirement):
     # This expects to parse `setuptools==58.2.0     --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11`
     # down wo `setuptools`.
-    name = requirement.split(" ")[0].split("=")[0]
+    name = requirement.split(" ")[0].split("=")[0].split("[")[0]
     return _annotations.get(name)
 
 def install_deps(**whl_library_kwargs):
diff --git a/examples/pip_repository_annotations/.gitignore b/examples/pip_repository_annotations/.gitignore
new file mode 100644
index 0000000..a6ef824
--- /dev/null
+++ b/examples/pip_repository_annotations/.gitignore
@@ -0,0 +1 @@
+/bazel-*
diff --git a/examples/pip_repository_annotations/BUILD b/examples/pip_repository_annotations/BUILD
index 4fd124e..84089f7 100644
--- a/examples/pip_repository_annotations/BUILD
+++ b/examples/pip_repository_annotations/BUILD
@@ -16,9 +16,13 @@
 py_test(
     name = "pip_parse_annotations_test",
     srcs = ["pip_repository_annotations_test.py"],
-    env = {"WHEEL_PKG_DIR": "pip_parsed_wheel"},
+    env = {
+        "REQUESTS_PKG_DIR": "pip_parsed_requests",
+        "WHEEL_PKG_DIR": "pip_parsed_wheel",
+    },
     main = "pip_repository_annotations_test.py",
     deps = [
+        "@pip_parsed_requests//:pkg",
         "@pip_parsed_wheel//:pkg",
         "@rules_python//python/runfiles",
     ],
@@ -27,10 +31,14 @@
 py_test(
     name = "pip_install_annotations_test",
     srcs = ["pip_repository_annotations_test.py"],
-    env = {"WHEEL_PKG_DIR": "pip_installed_wheel"},
+    env = {
+        "REQUESTS_PKG_DIR": "pip_installed_requests",
+        "WHEEL_PKG_DIR": "pip_installed_wheel",
+    },
     main = "pip_repository_annotations_test.py",
     deps = [
         requirement("wheel"),
+        requirement("requests"),
         "@rules_python//python/runfiles",
     ],
 )
diff --git a/examples/pip_repository_annotations/WORKSPACE b/examples/pip_repository_annotations/WORKSPACE
index aeea842..8fd998b 100644
--- a/examples/pip_repository_annotations/WORKSPACE
+++ b/examples/pip_repository_annotations/WORKSPACE
@@ -30,6 +30,19 @@
 # package. For details on `package_annotation` and it's uses, see the
 # docs at @rules_python//docs:pip.md`.
 ANNOTATIONS = {
+    # This annotation verifies that annotations work correctly for pip packages with extras
+    # specified, in this case requests[security].
+    "requests": package_annotation(
+        additive_build_content = """\
+load("@bazel_skylib//rules:write_file.bzl", "write_file")
+write_file(
+    name = "generated_file",
+    out = "generated_file.txt",
+    content = ["Hello world from requests"],
+)
+""",
+        data = [":generated_file"],
+    ),
     "wheel": package_annotation(
         additive_build_content = """\
 load("@bazel_skylib//rules:write_file.bzl", "write_file")
diff --git a/examples/pip_repository_annotations/pip_repository_annotations_test.py b/examples/pip_repository_annotations/pip_repository_annotations_test.py
index e78880a..d53b9bc 100644
--- a/examples/pip_repository_annotations/pip_repository_annotations_test.py
+++ b/examples/pip_repository_annotations/pip_repository_annotations_test.py
@@ -90,6 +90,26 @@
             self.assertTrue(Path(metadata_path).exists())
             self.assertFalse(Path(wheel_path).exists())
 
+    def requests_pkg_dir(self) -> str:
+        env = os.environ.get("REQUESTS_PKG_DIR")
+        self.assertIsNotNone(env)
+        return env
+
+    def test_extra(self):
+        # This test verifies that annotations work correctly for pip packages with extras
+        # specified, in this case requests[security].
+        r = runfiles.Create()
+        rpath = r.Rlocation(
+            "pip_repository_annotations_example/external/{}/generated_file.txt".format(
+                self.requests_pkg_dir()
+            )
+        )
+        generated_file = Path(rpath)
+        self.assertTrue(generated_file.exists())
+
+        content = generated_file.read_text().rstrip()
+        self.assertEqual(content, "Hello world from requests")
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/examples/pip_repository_annotations/requirements.in b/examples/pip_repository_annotations/requirements.in
index a955311..fd3f75c 100644
--- a/examples/pip_repository_annotations/requirements.in
+++ b/examples/pip_repository_annotations/requirements.in
@@ -3,3 +3,4 @@
 --extra-index-url https://pypi.python.org/simple/
 
 wheel
+requests[security]>=2.8.1
diff --git a/examples/pip_repository_annotations/requirements.txt b/examples/pip_repository_annotations/requirements.txt
index a2f1613..44dcbdf 100644
--- a/examples/pip_repository_annotations/requirements.txt
+++ b/examples/pip_repository_annotations/requirements.txt
@@ -6,6 +6,26 @@
 #
 --extra-index-url https://pypi.python.org/simple/
 
+certifi==2022.9.24 \
+    --hash=sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14 \
+    --hash=sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382
+    # via requests
+charset-normalizer==2.1.1 \
+    --hash=sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845 \
+    --hash=sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f
+    # via requests
+idna==3.4 \
+    --hash=sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4 \
+    --hash=sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2
+    # via requests
+requests[security]==2.28.1 \
+    --hash=sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983 \
+    --hash=sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349
+    # via -r ./requirements.in
+urllib3==1.26.12 \
+    --hash=sha256:3fa96cf423e6987997fc326ae8df396db2a8b7c667747d47ddd8ecba91f4a74e \
+    --hash=sha256:b930dd878d5a8afb066a637fbb35144fe7901e3b209d1cd4f524bd0e9deee997
+    # via requests
 wheel==0.37.1 \
     --hash=sha256:4bdcd7d840138086126cd09254dc6195fb4fc6f01c050a1d7236f2630db1d22a \
     --hash=sha256:e9a504e793efbca1b8e0e9cb979a249cf4a0a7b5b8c9e8b65a5e39d49529c1c4
diff --git a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py
index d0abcac..30071ae 100644
--- a/python/pip_install/extract_wheels/parse_requirements_to_bzl.py
+++ b/python/pip_install/extract_wheels/parse_requirements_to_bzl.py
@@ -155,7 +155,7 @@
         def _get_annotation(requirement):
             # This expects to parse `setuptools==58.2.0     --hash=sha256:2551203ae6955b9876741a26ab3e767bb3242dafe86a32a749ea0d78b6792f11`
             # down wo `setuptools`.
-            name = requirement.split(" ")[0].split("=")[0]
+            name = requirement.split(" ")[0].split("=")[0].split("[")[0]
             return _annotations.get(name)
 
         def install_deps(**whl_library_kwargs):