Skip to content
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

[PSM interop] Introduce isort/pylint to the GKE framework #29476

Merged
merged 3 commits into from May 3, 2022

Conversation

lidizheng
Copy link
Contributor

@lidizheng lidizheng commented Apr 21, 2022

This PR introduces the PSM GKE framework to:

  • isort
  • pylint

This PR also tries to fix the sanity complains if possible, but there were lots of places where the best fix is ambiguous: https://paste.googleplex.com/5988734773231616 (pylint has ~200 complains). In those ambiguous cases, this PR disables pylint, folks, please lift the disable comments during daily coding (boy-scout rule). Here are a few note-worthy ones:


Our pytype sanity tests might need more work. Currently, we are using a 2019 release of pytype, which don't support Python > 3.7. On the other hand, the latest pytype don't support Python < 3.7. It requires more delicate testing to sort out what version of pytype + Python suits our infra.

Also, the latest pytype release found more issues with our existing code, the upgrade won't be easy.

@lidizheng lidizheng added lang/Python kind/internal cleanup release notes: no Indicates if PR should not be in release notes labels Apr 21, 2022
@lidizheng lidizheng changed the title [PSM interop] Introduce sanity to the GKE framework [PSM interop] Introduce isort/pylint to the GKE framework Apr 21, 2022
@lidizheng
Copy link
Contributor Author

lidizheng commented Apr 21, 2022

@lidizheng lidizheng force-pushed the psm-sanity branch 2 times, most recently from 78a8608 to 42297f7 Compare April 22, 2022 20:21
@lidizheng lidizheng marked this pull request as ready for review April 22, 2022 22:18
@lidizheng lidizheng requested a review from sergiitk April 23, 2022 00:25
Copy link
Member

@sergiitk sergiitk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great, without any exaggeration. Thank you so much for the hard work.

I left a few comments/notes, but this is almost good to go.

@@ -54,7 +53,7 @@ def _replace_binding(policy: 'Policy', binding: 'Policy.Binding',
new_bindings = set(policy.bindings)
new_bindings.discard(binding)
new_bindings.add(new_binding)
return dataclasses.replace(policy, bindings=frozenset(new_bindings))
return dataclasses.replace(policy, bindings=frozenset(new_bindings)) # pylint: disable=too-many-function-args
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, what's wrong with this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. This is still a mystery to me. Here is the raw pylint complaint:

tools/run_tests/xds_k8s_test_driver/framework/infrastructure/gcp/iam.py:56:11: E1121: Too many positional arguments for function call (too-many-function-args)

Our usage complies with official doc: https://docs.python.org/3/library/dataclasses.html#dataclasses.replace

I suspect it might be a PyLint issue with dataclasses library.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, I have the same suspicion. Probably the same as pylint-dev/pylint#3492

@@ -102,7 +102,7 @@ def __init__(self, xds_json: JsonType):
for endpoint in xds_config['endpointConfig'][
'dynamicEndpointConfigs']:
self.eds.append(endpoint['endpointConfig'])
except Exception as e:
except Exception as e: # pylint: disable=broad-except
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and below:
Do we really need catching Exception here? Looking at the code, it can be replaced with LookupError. But I may be wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added as TODO. Let's do it in another PR, in case the narrowing of the catch scope causing tests to fail.

Comment on lines 73 to 74
default_test_servers: List[_XdsTestServer] = []
alternate_test_servers: List[_XdsTestServer] = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's required to assign the value, you should be able to just specify the type.

Suggested change
default_test_servers: List[_XdsTestServer] = []
alternate_test_servers: List[_XdsTestServer] = []
default_test_servers: List[_XdsTestServer]
alternate_test_servers: List[_XdsTestServer]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was afraid that in case of non-failfast run, we might carry a non-List value, then cause later tests to fail (since they assumed this value to be List, but seen None). To make the typing work, we will need to wrap it with Optional.

I found giving it an initial value saves a few lines of code (don't need to do null checks).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I see, declaring the type doesn't necessary assign it to None:

Python 3.10.4 (main, Mar 25 2022, 04:37:13) [Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from typing import List

# not defined - error
>>> print(default_test_servers)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'default_test_servers' is not defined

# only type declared - same as not defined - error
>>> default_test_servers: List[str]
>>> print(default_test_servers)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'default_test_servers' is not defined

# type and assignment - all fine
>>> default_test_servers: List[str] = []
>>> print(default_test_servers)
[]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirming py3.6 behaves the same as above.

However, if mypy complains about something and it's easier to assign the value - it's fine by me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL it will end up with "not defined" instead of giving it a value... This is very different than other languages. I will update all test cases to use the suggested pattern.

Copy link
Contributor Author

@lidizheng lidizheng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for reviewing this PR! Most comments are resolved, except the styling of variable annotations in test case files. Let's discuss that in the thread in failover_test.py.

@@ -54,7 +53,7 @@ def _replace_binding(policy: 'Policy', binding: 'Policy.Binding',
new_bindings = set(policy.bindings)
new_bindings.discard(binding)
new_bindings.add(new_binding)
return dataclasses.replace(policy, bindings=frozenset(new_bindings))
return dataclasses.replace(policy, bindings=frozenset(new_bindings)) # pylint: disable=too-many-function-args
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. This is still a mystery to me. Here is the raw pylint complaint:

tools/run_tests/xds_k8s_test_driver/framework/infrastructure/gcp/iam.py:56:11: E1121: Too many positional arguments for function call (too-many-function-args)

Our usage complies with official doc: https://docs.python.org/3/library/dataclasses.html#dataclasses.replace

I suspect it might be a PyLint issue with dataclasses library.

@@ -102,7 +102,7 @@ def __init__(self, xds_json: JsonType):
for endpoint in xds_config['endpointConfig'][
'dynamicEndpointConfigs']:
self.eds.append(endpoint['endpointConfig'])
except Exception as e:
except Exception as e: # pylint: disable=broad-except
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added as TODO. Let's do it in another PR, in case the narrowing of the catch scope causing tests to fail.

@@ -362,13 +360,13 @@ def tearDownClass(cls):

def _fetch_and_check_xds_config(self):
# Cleanup state for this attempt
self._xds_json_config = None
self._xds_json_config = None # pylint: disable=attribute-defined-outside-init
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Todo added.

I attempted that approach, the problem is unittest.TestCase contains too much magic. Theoretically, the variable declaration should happen in the constructor, but the constructor is invoked by unittest's internal code. To keep magic working, we might make the __init__ function overly complex. There might be an elegant way to pass the last-seen config to caller across the retry-layer. Feel free to suggest.

Comment on lines 73 to 74
default_test_servers: List[_XdsTestServer] = []
alternate_test_servers: List[_XdsTestServer] = []
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was afraid that in case of non-failfast run, we might carry a non-List value, then cause later tests to fail (since they assumed this value to be List, but seen None). To make the typing work, we will need to wrap it with Optional.

I found giving it an initial value saves a few lines of code (don't need to do null checks).

Copy link
Member

@sergiitk sergiitk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All good! Thank you for getting this done! This will go a long way - from making reviews simpler, to stability improvements.

@sergiitk
Copy link
Member

Let's re-run tests before merging this. Also, better to postpone the merge so we don't break anything over the weekend.

@lidizheng
Copy link
Contributor Author

lidizheng commented May 2, 2022

@lidizheng
Copy link
Contributor Author

Interestingly, Google served Golang binaries are unavailable now causing Kokoro jobs to fail:

WARNING: Download from https://dl.google.com/go/go1.18.linux-amd64.tar.gz failed: class com.google.devtools.build.lib.bazel.repository.downloader.UnrecoverableHttpException GET returned 502 Bad Gateway
ERROR: An error occurred during the fetch of repository 'go_sdk':
   Traceback (most recent call last):
	File "/root/.cache/bazel/_bazel_root/954bb7512d44d20015390af6e76121c6/external/io_bazel_rules_go/go/private/sdk.bzl", line 100, column 16, in _go_download_sdk_impl
		_remote_sdk(ctx, [url.format(filename) for url in ctx.attr.urls], ctx.attr.strip_prefix, sha256)
	File "/root/.cache/bazel/_bazel_root/954bb7512d44d20015390af6e76121c6/external/io_bazel_rules_go/go/private/sdk.bzl", line 205, column 21, in _remote_sdk
		ctx.download(
Error in download: java.io.IOException: Error downloading [https://dl.google.com/go/go1.18.linux-amd64.tar.gz] to /root/.cache/bazel/_bazel_root/954bb7512d44d20015390af6e76121c6/external/go_sdk/go_sdk.tar.gz: GET returned 502 Bad Gateway
ERROR: Error fetching repository: Traceback (most recent call last):
	File "/root/.cache/bazel/_bazel_root/954bb7512d44d20015390af6e76121c6/external/io_bazel_rules_go/go/private/sdk.bzl", line 100, column 16, in _go_download_sdk_impl
		_remote_sdk(ctx, [url.format(filename) for url in ctx.attr.urls], ctx.attr.strip_prefix, sha256)
	File "/root/.cache/bazel/_bazel_root/954bb7512d44d20015390af6e76121c6/external/io_bazel_rules_go/go/private/sdk.bzl", line 205, column 21, in _remote_sdk
		ctx.download(
Error in download: java.io.IOException: Error downloading [https://dl.google.com/go/go1.18.linux-amd64.tar.gz] to /root/.cache/bazel/_bazel_root/954bb7512d44d20015390af6e76121c6/external/go_sdk/go_sdk.tar.gz: GET returned 502 Bad Gateway
ERROR: Analysis of target '//src/python/grpcio/grpc/experimental:aio' failed; build aborted: java.io.IOException: Error downloading [https://dl.google.com/go/go1.18.linux-amd64.tar.gz] to /root/.cache/bazel/_bazel_root/954bb7512d44d20015390af6e76121c6/external/go_sdk/go_sdk.tar.gz: GET returned 502 Bad Gateway

@lidizheng
Copy link
Contributor Author

All xDS interop test passed, except AffinityTest failed due to known flake:

framework.rpc.grpc.GrpcApp.NotFound: Client has no READY channel with the server

@lidizheng lidizheng enabled auto-merge (squash) May 3, 2022 17:33
@lidizheng lidizheng merged commit 697c438 into grpc:master May 3, 2022
@copybara-service copybara-service bot added the imported Specifies if the PR has been imported to the internal repository label May 4, 2022
anicr7 pushed a commit that referenced this pull request May 6, 2022
* [PSM interop] Introduce isort/pylint to the GKE framework

* Update the rpc_types

* Update variable type annotation style in tests/*.py
lidizheng added a commit to lidizheng/grpc that referenced this pull request May 24, 2022
* [PSM interop] Introduce isort/pylint to the GKE framework

* Update the rpc_types

* Update variable type annotation style in tests/*.py
sergiitk pushed a commit to sergiitk/grpc that referenced this pull request Dec 8, 2023
* [PSM interop] Introduce isort/pylint to the GKE framework

* Update the rpc_types

* Update variable type annotation style in tests/*.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bloat/none imported Specifies if the PR has been imported to the internal repository kind/internal cleanup lang/Python per-call-memory/neutral release notes: no Indicates if PR should not be in release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants