Repository: CycloneDX/cyclonedx-python

Issue:
bug: hashes not always included in BOM when present in Pipfile.lock
Hashes appear to only be included in BOM output if they were originally called in the Pipfile as direct dependencies. According to the usage document (docs/usage.rst) hashes should be included if they are present.

Given the following Pipfile, only boto3 and pydantic will have their hashes included in the BOM.
```
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
boto3 = "*"
pydantic = "*"

[dev-packages]
bandit = "*"
```

snippet of the Pipfile.lock
```
{
    "_meta": {
        "hash": {
            "sha256": "4cd7bf004b61eda536feaa2f04368e49b2197105af5c61c19d74adda5b73294b"
        },
        "pipfile-spec": 6,
        "requires": {
            "python_version": "3.9"
        },
        "sources": [
            {
                "name": "pypi",
                "url": "https://pypi.org/simple",
                "verify_ssl": true
            }
        ]
    },
    "default": {
        "boto3": {
            "hashes": [
                "sha256:1a272a1dd36414b1626a47bb580425203be0b5a34caa117f38a5e18adf21f918",
                "sha256:8129ad42cc0120d1c63daa18512d6f0b1439e385b2b6e0fe987f116bdf795546"
            ],
            "index": "pypi",
            "version": "==1.20.54"
        },
        "botocore": {
            "hashes": [
                "sha256:06ae8076c4dcf3d72bec4d37e5f2dce4a92a18a8cdaa3bfaa6e3b7b5e30a8d7e",
                "sha256:4bb9ba16cccee5f5a2602049bc3e2db6865346b2550667f3013bdf33b0a01ceb"
            ],
            "markers": "python_version >= '3.6'",
            "version": "==1.23.54"
        },
```

And the relevant BOM snippet is:
```
    "components": [
        {
            "type": "library",
            "bom-ref": "b019649c-e545-40a9-b934-6c7214d0964d",
            "name": "boto3",
            "version": "1.20.54",
            "purl": "pkg:pypi/boto3@1.20.54",
            "externalReferences": [
                {
                    "type": "distribution",
                    "url": "https://pypi.org/project/boto3/1.20.54",
                    "comment": "Distribution available from pypi.org",
                    "hashes": [
                        {
                            "alg": "SHA-256",
                            "content": "1a272a1dd36414b1626a47bb580425203be0b5a34caa117f38a5e18adf21f918"
                        }
                    ]
                },
                {
                    "type": "distribution",
                    "url": "https://pypi.org/project/boto3/1.20.54",
                    "comment": "Distribution available from pypi.org",
                    "hashes": [
                        {
                            "alg": "SHA-256",
                            "content": "8129ad42cc0120d1c63daa18512d6f0b1439e385b2b6e0fe987f116bdf795546"
                        }
                    ]
                }
            ]
        },
        {
            "type": "library",
            "bom-ref": "5934293e-4285-4c3e-8176-91352e77c789",
            "name": "botocore",
            "version": "1.23.54",
            "purl": "pkg:pypi/botocore@1.23.54"
        },

```

Potential fixes:
* Upstream repository change & update documentation to specify constraint
* Remove cyclonedx-python requirement for the index attribute to be present

Discussion:

Patch:
diff --git a/cyclonedx_py/parser/pipenv.py b/cyclonedx_py/parser/pipenv.py
index 8e1676f..9339201 100644
--- a/cyclonedx_py/parser/pipenv.py
+++ b/cyclonedx_py/parser/pipenv.py
@@ -44,7 +44,7 @@ class PipEnvParser(BaseParser):
                     type='pypi', name=package_name, version=str(package_data.get('version') or 'unknown').lstrip('=')
                 )
             )
-            if package_data.get('index') == 'pypi' and isinstance(package_data.get('hashes'), list):
+            if isinstance(package_data.get('hashes'), list):
                 # Add download location with hashes stored in Pipfile.lock
                 for pip_hash in package_data['hashes']:
                     ext_ref = ExternalReference(


Test patch:
diff --git a/tests/test_parser_pipenv.py b/tests/test_parser_pipenv.py
index 9d19f1d..751d282 100644
--- a/tests/test_parser_pipenv.py
+++ b/tests/test_parser_pipenv.py
@@ -50,7 +50,8 @@ class TestPipEnvParser(TestCase):
 
         self.assertEqual('anyio', c_anyio.name)
         self.assertEqual('3.3.3', c_anyio.version)
-        self.assertEqual(0, len(c_anyio.external_references), f'{c_anyio.external_references}')
+        self.assertEqual(2, len(c_anyio.external_references), f'{c_anyio.external_references}')
+        self.assertEqual(1, len(c_anyio.external_references.pop().hashes))
 
         self.assertEqual('toml', c_toml.name)
         self.assertEqual('0.10.2', c_toml.version)