blackducksoftware / hub-rest-api-python

HUB REST API Python bindings
Apache License 2.0
89 stars 104 forks source link

Gsnyder/extended client #198

Closed gsnyder2007 closed 2 years ago

gsnyder2007 commented 2 years ago

A proposal to extend the Client interface and add methods for common operations like getting a project by its name or getting a project-version using the project and version names. If this proposal is accepted we can proceed to populate other convenience methods that will reduce the amount of boilerplate code people have to use to retrieve and work with the BD REST objects.

mkumykov commented 2 years ago

Ah! I miss come convenient calls from HubInstance. We had to come a full circle at some point and reimplement something like that using new Client class. Cool!

gsnyder2007 commented 2 years ago

Big question is how much of this kind of functionality we are expecting to be implemented. Are we looking at somewhat more elegant re-implementation of HubInstance?

Yes, that is where this PR is headed although I only implemented two for fetching project and project-version objects by their name for now. Maybe add more later?

mkumykov commented 2 years ago

I certainly would not rush into full re-implementation. I find new Client class to be quite sufficient by itself, get_items and get_resources are very handy and useful. I do find myself doing copy-paste form script to script and getting project by name was one of the things that I would copy often.

skiyooka commented 2 years ago

Client has been strictly with generic methods that apply across the entire REST API. Is "get_by_name" generic enough that it can be implemented in such a manner?

gsnyder2007 commented 2 years ago

Client has been strictly with generic methods that apply across the entire REST API. Is "get_by_name" generic enough that it can be implemented in such a manner?

Good question and possibly a better approach. The following object types use a name field ("name"), or close variant:

There are other object types such as Scans, Reports, Notifications, Copyrights, and others that do not use a "name" field but we don't usually think of searching for those by a name anyhow.

We could, therefore, implement a generic _get_byname and within it contextualize based on the object type and respond accordingly, e.g. if object type in [Projects, Project Groups, ...], then search for the object by name, else search by name is not supported for the given object type. Or something like that. Thoughts?

OffBy0x01 commented 2 years ago

Client has been strictly with generic methods that apply across the entire REST API. Is "get_by_name" generic enough that it can be implemented in such a manner?

Or perhaps even get_resource_by?

   # untested hypothetical 
    def get_resource_by(self, field, value,  name, parent=None, **kwargs):
        params = {
            'q': [f"{field}:{value}"]
        }
        filtered = [i for i in self.get_resource(name, parent, params=params) if i.get(field) == value]
        assert len(filtered) in [0,1], f"We either found the {field} or we didn't, but we should never find this many ({len(filtered)})"

        return filtered[0] if filtered else None
gsnyder2007 commented 2 years ago

Client has been strictly with generic methods that apply across the entire REST API. Is "get_by_name" generic enough that it can be implemented in such a manner?

Or perhaps even get_resource_by?

   # untested hypothetical 
    def get_resource_by(self, field, value,  name, parent=None, **kwargs):
        params = {
            'q': [f"{field}:{value}"]
        }
        filtered = [i for i in self.get_resource(name, parent, params=params) if i.get(field) == value]
        assert len(filtered) in [0,1], f"We either found the {field} or we didn't, but we should never find this many ({len(filtered)})"

        return filtered[0] if filtered else None

Yeah, I was thinking about something similar that would be totally generic and still accomplish the same thing (i.e. make it easier to fetch common objects by their name). Let me go back and test some of these ideas and update the PR accordingly. Thanks.

gsnyder2007 commented 2 years ago

Decided to close this one and resubmit with a diff proposal