snyk-labs / pysnyk

A Python client for the Snyk API.
https://snyk.docs.apiary.io/
MIT License
88 stars 116 forks source link

[BUG]: 'NoneType' object has no attribute 'get' ProjectManager._rest_to_v1_response_format #187

Closed avipunes-devOcean closed 1 year ago

avipunes-devOcean commented 1 year ago

Is there an existing issue for this?

Description of the bug

Following version 0.9.7 release, which contains this PR, there is a bug when a project doesn't have "meta.latest_issue_counts` property. The following line change is missing handling the missing property case. Therefore the entire call raises an exception, and all projects, even valid ones with the expected property, don't get returned.

To fix this issue, adding default values and two places is necessary.

The following is a fix suggestion:

    def _rest_to_v1_response_format(self, project):
        attributes = project.get("attributes", {})
        settings = attributes.get("settings", {})
        recurring_tests = settings.get("recurring_tests", {})
        issue_counts = project.get("meta", {}).get("latest_issue_counts", {})  # default value for None `latest_issue_counts`

        return {
            "name": attributes.get("name"),
            "id": project.get("id"),
            "created": attributes.get("created"),
            "origin": attributes.get("origin"),
            "type": attributes.get("type"),
            "readOnly": attributes.get("read_only"),
            "testFrequency": recurring_tests.get("frequency"),
            "isMonitored": True if attributes.get("status") == "active" else False,
            "issueCountsBySeverity": {
                "low": issue_counts.get("low", 0), # default value for None `issue_counts` (and for the below as well)
                "medium": issue_counts.get("medium", 0),
                "high": issue_counts.get("high", 0),
                "critical": issue_counts.get("critical"),
            },
            "targetReference": attributes.get("target_reference"),
            "_tags": attributes.get("tags", []),
            "importingUserId": project.get("relationships", {})
            .get("importer", {})
            .get("data", {})
            .get("id"),
            "owningUserId": project.get("relationships", {})
            .get("owner", {})
            .get("data", {})
            .get("id"),
        }

The second default value is needed because Project.issueCountsBySeverity.low, Project.issueCountsBySeverity.medium, and Project.issueCountsBySeverity.high are mandatory fields.

Steps To Reproduce

import snyk
snyk_client = snyk.SnykClient("<put-snyk-api-token-here>")
orgs = snyk_client.organizations.all()
for org in orgs:
    org.projects.all() # exception here

Additional Information

No response

nathan-roys commented 1 year ago

Released v0.9.14 to address this issue. Thank you for the detailed report & suggested fix.