-
Notifications
You must be signed in to change notification settings - Fork 119
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Enhancement: clients can use REST url for all methods #219
base: master
Are you sure you want to change the base?
Enhancement: clients can use REST url for all methods #219
Conversation
snyk/client.py
Outdated
fkwargs={"json": body, "headers": {**self.api_post_headers, **headers}}, | ||
fkwargs={ | ||
"json": body, | ||
"headers": {**self.api_post_headers, **headers}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feels a bit confusing to user the api_post_headers
in the put
. Maybe use the api_headers
or create a similar api_put_headers
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line was not changed from the initial version, it is marked as modified, because I've added params and the linter splits them on multiple lines.
body: Dict[str, Any], | ||
headers: Dict[str, str] = {}, | ||
params: Dict[str, Any] = {}, | ||
) -> requests.Response: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if we should keep consistency here with a rest parameter or not. I know it would be useless, and need to be set to true. It's just triggering my OCD having this lack of uniformity of methods 🙈
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to the documentation(https://snyk.docs.apiary.io/#reference) there is no endpoint which makes use of patch verb in V1.
snyk/test_client.py
Outdated
@@ -329,3 +327,140 @@ def test_rest_limit_deduplication(self, requests_mock, rest_client): | |||
) | |||
params = {"limit": 10} | |||
rest_client.get(f"orgs/{REST_ORG}/projects?limit=100", params) | |||
|
|||
def test_patch_update_project_should_return_new_project( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe a typo? patch should not return a "new" project
assert response.status_code == 200 | ||
assert response_data == project | ||
|
||
def test_token_added_to_patch_headers(self, client): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry, don't know enough python 😅 how does this test work? What does it test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes sure that there is a value in Authorization header and nobody deletes the line which add the value, by mistake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
client
is a fixture. See the function client()
in the top of the class.
When you add an argument to the test it runs the function and uses the returned value as parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job! Just left a few comments (some just asking for clarification 😄 )
snyk/client.py
Outdated
@@ -40,13 +42,18 @@ def __init__( | |||
"Authorization": "token %s" % self.api_token, | |||
"User-Agent": user_agent, | |||
} | |||
self.api_post_headers = self.api_headers | |||
self.api_post_headers = copy.deepcopy(self.api_headers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.api_post_headers = copy.deepcopy(self.api_headers) | |
self.api_post_headers = dict(self.api_headers) |
Why do we need to copy them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since both api post headers and patch post headers have different content-type, I wanted a way to avoid side-effects(since simple assigning creates a shallow copy and dictionaries are mutable in python) when changing content-type. The solution given by you might be better rather than creating a deep-copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So my suggestion is to set those headers explicitly in the specific function.
Otherwise it's confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might introduce duplicate code, since both V1 and REST API are using the same headers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, it's a suggestion only. In my opinion it is better to duplicate code and make them explicit rather than start looking at who modified what header. Moreover, if you do that you will be able to get rid of the api_post_headers
property.
snyk/client.py
Outdated
self.api_post_headers["Content-Type"] = "application/json" | ||
self.api_patch_headers = copy.deepcopy(self.api_headers) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.api_patch_headers = copy.deepcopy(self.api_headers) | |
self.api_patch_headers = dict(self.api_headers) |
Same here. Why do we need to duplicate them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same reason as stated above.
snyk/client.py
Outdated
def post( | ||
self, | ||
path: str, | ||
body: Any, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is a dict
, so can use Dict
. If it's either a dict
or a str
you can do something like Union[Dict, str]
.
snyk/client.py
Outdated
self, | ||
path: str, | ||
body: Any, | ||
headers: dict = {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What version of Python do you use? The type dict
is allowed only from 3.9. I saw in the pyproject.toml
file that the allowed versions of Python are from version 3.7
and up. If this is still the case I suggest using Dict
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was previously in the project, I can change it, but I need to make sure every instance gets changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not suggesting to upgrade. But if we still want to support Python 3.7 we need to change line 96 to be something like:
headers: Dict = {}. # note the capital D.
snyk/client.py
Outdated
logger.debug(f"POST: {url}") | ||
|
||
if use_rest and "version" not in params: | ||
params["version"] = self.version if self.version else "2024-06-21" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
params["version"] = self.version if self.version else "2024-06-21" | |
params["version"] = self.version or "2024-06-21" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, any chance we define the default version in a constant?
snyk/client.py
Outdated
logger.debug(f"PATCH: {url}") | ||
|
||
if "version" not in params: | ||
params["version"] = self.version if self.version else "2024-06-21" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
params["version"] = self.version if self.version else "2024-06-21" | |
params["version"] = self.version or "2024-06-21" |
Any chance to define the default version in a constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last commit to package retry
's repo was in 2016.
I suggest replace it.
Description of changes
In this modification, I created the opportunity for users to decide between using v1 api or rest api route in the
SnykClient
. Previously, only the get method let user to use the rest api. Patch method was created for use cases in which the verb PATCH is necessary, thing that didn't exist previously.Technical details
SnykClient
class.Context
These changes were made to enable users use the rest api, because v1 is approaching its end of life. It provides more flexibility to the developers who wants to interact with different instances of Snyk APIs.
How to test
This modification should not impact the existing functionality of the library. Everything should work as intended.
Example Usage
Update an existing project