Skip to content

Commit 70ed7a2

Browse files
authored
chore: fix CI invocations to use Python 3.9 (googleapis#1148)
1 parent bcd446e commit 70ed7a2

File tree

25 files changed

+162
-77
lines changed

25 files changed

+162
-77
lines changed

.github/workflows/tests.yaml

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ jobs:
1818
runs-on: ubuntu-latest
1919
steps:
2020
- uses: actions/checkout@v2
21-
- name: Set up Python 3.8
21+
- name: Set up Python 3.9
2222
uses: actions/setup-python@v2
2323
with:
24-
python-version: 3.8
24+
python-version: 3.9
2525
cache: 'pip'
2626
- name: Install nox.
2727
run: python -m pip install nox
@@ -31,10 +31,10 @@ jobs:
3131
runs-on: ubuntu-latest
3232
steps:
3333
- uses: actions/checkout@v2
34-
- name: Set up Python 3.8
34+
- name: Set up Python 3.9
3535
uses: actions/setup-python@v2
3636
with:
37-
python-version: 3.8
37+
python-version: 3.9
3838
cache: 'pip'
3939
- name: Install nox.
4040
run: python -m pip install nox
@@ -47,10 +47,10 @@ jobs:
4747
runs-on: ubuntu-latest
4848
steps:
4949
- uses: actions/checkout@v2
50-
- name: Set up Python 3.8
50+
- name: Set up Python 3.9
5151
uses: actions/setup-python@v2
5252
with:
53-
python-version: 3.8
53+
python-version: 3.9
5454
cache: 'pip'
5555
- name: Install system dependencies.
5656
run: |
@@ -90,10 +90,10 @@ jobs:
9090
run: |
9191
sudo mkdir -p /tmp/workspace/tests/cert/
9292
sudo chown -R ${USER} /tmp/workspace/
93-
- name: Set up Python 3.8
93+
- name: Set up Python 3.9
9494
uses: actions/setup-python@v2
9595
with:
96-
python-version: 3.8
96+
python-version: 3.9
9797
cache: 'pip'
9898
- name: Copy mtls files
9999
run: cp tests/cert/mtls.* /tmp/workspace/tests/cert/
@@ -172,10 +172,10 @@ jobs:
172172
runs-on: ubuntu-latest
173173
steps:
174174
- uses: actions/checkout@v2
175-
- name: Set up Python 3.8
175+
- name: Set up Python 3.9
176176
uses: actions/setup-python@v2
177177
with:
178-
python-version: 3.8
178+
python-version: 3.9
179179
cache: 'pip'
180180
- name: Install system dependencies.
181181
run: |
@@ -202,10 +202,10 @@ jobs:
202202
variant: ['', _alternative_templates]
203203
steps:
204204
- uses: actions/checkout@v2
205-
- name: Set up Python 3.8
205+
- name: Set up Python 3.9
206206
uses: actions/setup-python@v2
207207
with:
208-
python-version: 3.8
208+
python-version: 3.9
209209
cache: 'pip'
210210
- name: Install system dependencies.
211211
run: |
@@ -229,10 +229,10 @@ jobs:
229229
runs-on: ubuntu-latest
230230
steps:
231231
- uses: actions/checkout@v2
232-
- name: Set up Python 3.8
232+
- name: Set up Python 3.9
233233
uses: actions/setup-python@v2
234234
with:
235-
python-version: 3.8
235+
python-version: 3.9
236236
cache: 'pip'
237237
- name: Install system dependencies.
238238
run: |
@@ -320,10 +320,10 @@ jobs:
320320
runs-on: ubuntu-latest
321321
steps:
322322
- uses: actions/checkout@v2
323-
- name: Set up Python 3.8
323+
- name: Set up Python 3.9
324324
uses: actions/setup-python@v2
325325
with:
326-
python-version: 3.8
326+
python-version: 3.9
327327
cache: 'pip'
328328
- name: Install autopep8
329329
run: |

gapic/ads-templates/%namespace/%name/%version/%sub/services/%service/transports/rest.py.j2

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ from google.protobuf import json_format
1919
{% endif %}
2020
from requests import __version__ as requests_version
2121
import dataclasses
22-
from typing import Callable, Dict, Optional, Sequence, Tuple, Union
22+
import re
23+
from typing import Callable, Dict, List, Optional, Sequence, Tuple, Union
2324
import warnings
2425

2526
try:
@@ -65,7 +66,7 @@ class {{ service.name }}RestInterceptor:
6566

6667
.. code-block:
6768
class MyCustom{{ service.name }}Interceptor({{ service.name }}RestInterceptor):
68-
{% for _, method in service.methods|dictsort if not (method.server_streaming or method.client_streaming) %}
69+
{% for _, method in service.methods|dictsort if not (method.server_streaming or method.client_streaming) %}
6970
def pre_{{ method.name|snake_case }}(request, metadata):
7071
logging.log(f"Received request: {request}")
7172
return request, metadata
@@ -81,7 +82,7 @@ class {{ service.name }}RestInterceptor:
8182

8283

8384
"""
84-
{% for method in service.methods.values()|sort(attribute="name") if not(method.server_streaming or method.client_streaming) %}
85+
{% for method in service.methods.values()|sort(attribute="name") if not (method.server_streaming or method.client_streaming) %}
8586
def pre_{{ method.name|snake_case }}(self, request: {{method.input.ident}}, metadata: Sequence[Tuple[str, str]]) -> Tuple[{{method.input.ident}}, Sequence[Tuple[str, str]]]:
8687
"""Pre-rpc interceptor for {{ method.name|snake_case }}
8788

@@ -175,6 +176,14 @@ class {{service.name}}RestTransport({{service.name}}Transport):
175176
# TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc.
176177
# TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the
177178
# credentials object
179+
maybe_url_match = re.match("^(?P<scheme>http(?:s)?://)?(?P<host>.*)$", host)
180+
if maybe_url_match is None:
181+
raise ValueError(f"Unexpected hostname structure: {host}") # pragma: NO COVER
182+
183+
url_match_items = maybe_url_match.groupdict()
184+
185+
host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host
186+
178187
super().__init__(
179188
host=host,
180189
credentials=credentials,
@@ -184,7 +193,7 @@ class {{service.name}}RestTransport({{service.name}}Transport):
184193
self._session = AuthorizedSession(
185194
self._credentials, default_host=self.DEFAULT_HOST)
186195
{% if service.has_lro %}
187-
self._operations_client = None
196+
self._operations_client: Optional[operations_v1.AbstractOperationsClient] = None
188197
{% endif %}
189198
if client_cert_source_for_mtls:
190199
self._session.configure_mtls_channel(client_cert_source_for_mtls)
@@ -202,7 +211,7 @@ class {{service.name}}RestTransport({{service.name}}Transport):
202211
"""
203212
# Only create a new client if we do not already have one.
204213
if self._operations_client is None:
205-
http_options = {
214+
http_options: Dict[str, List[Dict[str, str]]] = {
206215
{% for selector, rules in api.http_options.items() %}
207216
{% if selector.startswith('google.longrunning.Operations') %}
208217
'{{ selector }}': [
@@ -238,9 +247,10 @@ class {{service.name}}RestTransport({{service.name}}Transport):
238247
def __hash__(self):
239248
return hash("{{method.name}}")
240249

250+
241251
{% if not (method.server_streaming or method.client_streaming) %}
242252
{% if method.input.required_fields %}
243-
__REQUIRED_FIELDS_DEFAULT_VALUES = {
253+
__REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, str] = {
244254
{% for req_field in method.input.required_fields if req_field.is_primitive and req_field.name in method.query_params %}
245255
"{{ req_field.name | camel_case }}" : {% if req_field.field_pb.type == 9 %}"{{req_field.field_pb.default_value }}"{% else %}{{ req_field.type.python_type(req_field.field_pb.default_value or 0) }}{% endif %},{# default is str #}
246256
{% endfor %}
@@ -258,7 +268,7 @@ class {{service.name}}RestTransport({{service.name}}Transport):
258268
retry: OptionalRetry=gapic_v1.method.DEFAULT,
259269
timeout: float=None,
260270
metadata: Sequence[Tuple[str, str]]=(),
261-
) -> {{method.output.ident}}:
271+
){% if not method.void %} -> {{method.output.ident}}{% endif %}:
262272
{% if method.http_options and not (method.server_streaming or method.client_streaming) %}
263273
r"""Call the {{- ' ' -}}
264274
{{ (method.name|snake_case).replace('_',' ')|wrap(
@@ -282,7 +292,7 @@ class {{service.name}}RestTransport({{service.name}}Transport):
282292
{% endif %}
283293
"""
284294

285-
http_options = [
295+
http_options: List[Dict[str, str]] = [
286296
{%- for rule in method.http_options %}{
287297
'method': '{{ rule.method }}',
288298
'uri': '{{ rule.uri }}',
@@ -330,8 +340,7 @@ class {{service.name}}RestTransport({{service.name}}Transport):
330340
headers = dict(metadata)
331341
headers['Content-Type'] = 'application/json'
332342
response = getattr(self._session, method)(
333-
# Replace with proper schema configuration (http/https) logic
334-
"https://{host}{uri}".format(host=self._host, uri=uri),
343+
"{host}{uri}".format(host=self._host, uri=uri),
335344
timeout=timeout,
336345
headers=headers,
337346
params=rest_helpers.flatten_query_params(query_params),
@@ -344,6 +353,7 @@ class {{service.name}}RestTransport({{service.name}}Transport):
344353
# subclass.
345354
if response.status_code >= 400:
346355
raise core_exceptions.from_http_response(response)
356+
347357
{% if not method.void %}
348358
# Return the response
349359
{% if method.lro %}
@@ -357,6 +367,7 @@ class {{service.name}}RestTransport({{service.name}}Transport):
357367
{% endif %}{# method.lro #}
358368
resp = self._interceptor.post_{{ method.name|snake_case }}(resp)
359369
return resp
370+
360371
{% endif %}{# method.void #}
361372
{% else %}{# method.http_options and not (method.server_streaming or method.client_streaming) #}
362373
{% if not method.http_options %}
@@ -384,7 +395,9 @@ class {{service.name}}RestTransport({{service.name}}Transport):
384395
if not stub:
385396
stub = self._STUBS["{{method.name | snake_case}}"] = self._{{method.name}}(self._session, self._host, self._interceptor)
386397

387-
return stub
398+
# The return type is fine, but mypy isn't sophisticated enough to determine what's going on here.
399+
# In C++ this would require a dynamic_cast
400+
return stub # type: ignore
388401

389402
{% endfor %}
390403

gapic/ads-templates/docs/conf.py.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ __version__ = "0.1.0"
2828
# -- General configuration ------------------------------------------------
2929

3030
# If your documentation needs a minimal Sphinx version, state it here.
31-
needs_sphinx = "1.6.3"
31+
needs_sphinx = "4.0.1"
3232

3333
# Add any Sphinx extension module names here, as strings. They can be
3434
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom

gapic/ads-templates/tests/unit/gapic/%name_%version/%sub/test_%service.py.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ def test_{{ method.name|snake_case }}_rest_flattened():
12511251
assert len(req.mock_calls) == 1
12521252
_, args, _ = req.mock_calls[0]
12531253
{% with uri = method.http_options[0].uri %}
1254-
assert path_template.validate("https://%s{{ uri }}" % client.transport._host, args[1])
1254+
assert path_template.validate("%s{{ uri }}" % client.transport._host, args[1])
12551255
{% endwith %}
12561256
{# TODO(kbandes) - reverse-transcode request args to check all request fields #}
12571257

gapic/schema/api.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -628,15 +628,25 @@ def proto(self) -> Proto:
628628

629629
@cached_property
630630
def api_enums(self) -> Mapping[str, wrappers.EnumType]:
631-
return collections.ChainMap({}, self.proto_enums,
632-
*[p.all_enums for p in self.prior_protos.values()],
633-
)
631+
return collections.ChainMap(
632+
{},
633+
self.proto_enums,
634+
# This is actually fine from a typing perspective:
635+
# we're agglutinating all the prior protos' enums, which are
636+
# stored in maps. This is just a convenient way to expand it out.
637+
*[p.all_enums for p in self.prior_protos.values()], # type: ignore
638+
)
634639

635640
@cached_property
636641
def api_messages(self) -> Mapping[str, wrappers.MessageType]:
637-
return collections.ChainMap({}, self.proto_messages,
638-
*[p.all_messages for p in self.prior_protos.values()],
639-
)
642+
return collections.ChainMap(
643+
{},
644+
self.proto_messages,
645+
# This is actually fine from a typing perspective:
646+
# we're agglutinating all the prior protos' enums, which are
647+
# stored in maps. This is just a convenient way to expand it out.
648+
*[p.all_messages for p in self.prior_protos.values()], # type: ignore
649+
)
640650

641651
def _load_children(self,
642652
children: Sequence, loader: Callable, *,

gapic/schema/wrappers.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -770,16 +770,16 @@ class HttpRule:
770770
uri: str
771771
body: Optional[str]
772772

773-
def path_fields(self, method: "~.Method") -> List[Tuple[Field, str, str]]:
773+
def path_fields(self, method: "Method") -> List[Tuple[Field, str, str]]:
774774
"""return list of (name, template) tuples extracted from uri."""
775775
input = method.input
776776
return [(input.get_field(*match.group("name").split(".")), match.group("name"), match.group("template"))
777777
for match in path_template._VARIABLE_RE.finditer(self.uri)]
778778

779-
def sample_request(self, method: "~.Method") -> str:
779+
def sample_request(self, method: "Method") -> Dict[str, Any]:
780780
"""return json dict for sample request matching the uri template."""
781781

782-
def sample_from_path_fields(paths: List[Tuple["wrappers.Field", str, str]]) -> Dict[Any, Any]:
782+
def sample_from_path_fields(paths: List[Tuple[Field, str, str]]) -> Dict[str, Any]:
783783
"""Construct a dict for a sample request object from a list of fields
784784
and template patterns.
785785
@@ -1040,7 +1040,11 @@ def query_params(self) -> Set[str]:
10401040
params = set(self.path_params)
10411041
body = self.http_opt.get('body')
10421042
if body:
1043-
params.add(body)
1043+
if body == "*":
1044+
# The entire request is the REST body.
1045+
return set()
1046+
else:
1047+
params.add(body)
10441048

10451049
return set(self.input.fields) - params
10461050

0 commit comments

Comments
 (0)