Skip to content
This repository was archived by the owner on Mar 26, 2026. It is now read-only.

Commit 68e453e

Browse files
committed
optimize gapic
1 parent 48ace66 commit 68e453e

3 files changed

Lines changed: 134 additions & 26 deletions

File tree

gapic/schema/api.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ def build(
115115
prior_protos: Optional[Mapping[str, "Proto"]] = None,
116116
load_services: bool = True,
117117
all_resources: Optional[Mapping[str, wrappers.MessageType]] = None,
118+
context_cache: Optional[Dict[tuple, "wrappers.MessageType"]] = None,
118119
) -> "Proto":
119120
"""Build and return a Proto instance.
120121
@@ -139,6 +140,7 @@ def build(
139140
prior_protos=prior_protos or {},
140141
load_services=load_services,
141142
all_resources=all_resources or {},
143+
context_cache=context_cache,
142144
).proto
143145

144146
@cached_property
@@ -455,6 +457,7 @@ def disambiguate_keyword_sanitize_fname(
455457
# We just load all the APIs types first and then
456458
# load the services and methods with the full scope of types.
457459
pre_protos: Dict[str, Proto] = dict(prior_protos or {})
460+
context_cache = {}
458461
for fd in file_descriptors:
459462
fd.name = disambiguate_keyword_sanitize_fname(fd.name, pre_protos)
460463
pre_protos[fd.name] = Proto.build(
@@ -465,6 +468,7 @@ def disambiguate_keyword_sanitize_fname(
465468
prior_protos=pre_protos,
466469
# Ugly, ugly hack.
467470
load_services=False,
471+
context_cache=context_cache,
468472
)
469473

470474
# A file descriptor's file-level resources are NOT visible to any importers.
@@ -485,6 +489,7 @@ def disambiguate_keyword_sanitize_fname(
485489
opts=opts,
486490
prior_protos=pre_protos,
487491
all_resources=MappingProxyType(all_file_resources),
492+
context_cache=context_cache,
488493
)
489494
for name, proto in pre_protos.items()
490495
}
@@ -1103,6 +1108,8 @@ def __init__(
11031108
prior_protos: Optional[Mapping[str, Proto]] = None,
11041109
load_services: bool = True,
11051110
all_resources: Optional[Mapping[str, wrappers.MessageType]] = None,
1111+
context_cache: Optional[Dict[tuple, "wrappers.MessageType"]] = None,
1112+
11061113
):
11071114
self.proto_messages: Dict[str, wrappers.MessageType] = {}
11081115
self.proto_enums: Dict[str, wrappers.EnumType] = {}
@@ -1111,6 +1118,7 @@ def __init__(
11111118
self.file_to_generate = file_to_generate
11121119
self.prior_protos = prior_protos or {}
11131120
self.opts = opts
1121+
self.context_cache = context_cache
11141122

11151123
# Iterate over the documentation and place it into a dictionary.
11161124
#
@@ -1220,20 +1228,22 @@ def proto(self) -> Proto:
12201228
if not self.file_to_generate:
12211229
return naive
12221230

1231+
global_collisions = frozenset(naive.names)
12231232
visited_messages: Set[wrappers.MessageType] = set()
12241233
# Return a context-aware proto object.
12251234
return dataclasses.replace(
12261235
naive,
12271236
all_enums=collections.OrderedDict(
1228-
(k, v.with_context(collisions=naive.names))
1237+
(k, v.with_context(collisions=global_collisions, context_cache=self.context_cache))
12291238
for k, v in naive.all_enums.items()
12301239
),
12311240
all_messages=collections.OrderedDict(
12321241
(
12331242
k,
12341243
v.with_context(
1235-
collisions=naive.names,
1244+
collisions=global_collisions,
12361245
visited_messages=visited_messages,
1246+
context_cache=self.context_cache,
12371247
),
12381248
)
12391249
for k, v in naive.all_messages.items()
@@ -1244,8 +1254,9 @@ def proto(self) -> Proto:
12441254
(
12451255
k,
12461256
v.with_context(
1247-
collisions=v.names,
1248-
visited_messages=visited_messages,
1257+
collisions=global_collisions,
1258+
visited_messages=frozenset(v.names),
1259+
context_cache=self.context_cache,
12491260
),
12501261
)
12511262
for k, v in naive.services.items()

gapic/schema/metadata.py

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
import dataclasses
3030
import re
31-
from typing import FrozenSet, Set, Tuple, Optional
31+
from typing import FrozenSet, Set, Tuple, Optional, Dict
3232

3333
from google.protobuf import descriptor_pb2
3434

@@ -359,19 +359,27 @@ def resolve(self, selector: str) -> str:
359359
return f'{".".join(self.package)}.{selector}'
360360
return selector
361361

362-
def with_context(self, *, collisions: Set[str]) -> "Address":
362+
def with_context(self, *, collisions: Set[str], context_cache: Optional[Dict[tuple, "MessageType"]] = None,) -> "Address":
363363
"""Return a derivative of this address with the provided context.
364364
365365
This method is used to address naming collisions. The returned
366366
``Address`` object aliases module names to avoid naming collisions in
367367
the file being written.
368368
"""
369-
return (
369+
context_cache = context_cache if context_cache is not None else {}
370+
cache_key = (id(self), id(collisions))
371+
if cache_key in context_cache:
372+
return context_cache[cache_key]
373+
374+
updated_msg = (
370375
dataclasses.replace(self, collisions=collisions)
371376
if collisions and collisions != self.collisions
372377
else self
373378
)
374379

380+
context_cache[cache_key] = updated_msg
381+
return updated_msg
382+
375383

376384
@dataclasses.dataclass(frozen=True)
377385
class Metadata:
@@ -398,14 +406,20 @@ def doc(self):
398406
return "\n\n".join(self.documentation.leading_detached_comments)
399407
return ""
400408

401-
def with_context(self, *, collisions: Set[str]) -> "Metadata":
409+
def with_context(self, *, collisions: Set[str], context_cache: Optional[Dict[tuple, "MessageType"]] = None,) -> "Metadata":
402410
"""Return a derivative of this metadata with the provided context.
403411
404412
This method is used to address naming collisions. The returned
405413
``Address`` object aliases module names to avoid naming collisions in
406414
the file being written.
407415
"""
408-
return (
416+
context_cache = context_cache if context_cache is not None else {}
417+
418+
cache_key = (id(self), id(collisions))
419+
if cache_key in context_cache:
420+
return context_cache[cache_key]
421+
422+
updated_msg = (
409423
dataclasses.replace(
410424
self,
411425
address=self.address.with_context(collisions=collisions),
@@ -414,6 +428,9 @@ def with_context(self, *, collisions: Set[str]) -> "Metadata":
414428
else self
415429
)
416430

431+
context_cache[cache_key] = updated_msg
432+
return updated_msg
433+
417434

418435
@dataclasses.dataclass(frozen=True)
419436
class FieldIdentifier:

0 commit comments

Comments
 (0)