3636from gapic .utils import cached_property
3737from gapic .utils import RESERVED_NAMES
3838
39+ # This class is a minor hack to optimize Address's __eq__ method.
40+
3941
4042@dataclasses .dataclass (frozen = True )
41- class Address :
43+ class BaseAddress :
4244 name : str = ''
4345 module : str = ''
4446 module_path : Tuple [int , ...] = dataclasses .field (default_factory = tuple )
4547 package : Tuple [str , ...] = dataclasses .field (default_factory = tuple )
4648 parent : Tuple [str , ...] = dataclasses .field (default_factory = tuple )
49+
50+
51+ @dataclasses .dataclass (frozen = True )
52+ class Address (BaseAddress ):
4753 api_naming : naming .Naming = dataclasses .field (
4854 default_factory = naming .NewNaming ,
4955 )
5056 collisions : FrozenSet [str ] = dataclasses .field (default_factory = frozenset )
5157
5258 def __eq__ (self , other ) -> bool :
53- return all (getattr (self , i ) == getattr (other , i )
54- for i in ('name' , 'module' , 'module_path' , 'package' , 'parent' ))
59+ # We don't want to use api_naming or collisions to determine equality,
60+ # so defer to the parent class's eq method.
61+ # This is an fairly important optimization for large APIs.
62+ return super ().__eq__ (other )
5563
5664 def __hash__ (self ):
5765 # Do NOT include collisions; they are not relevant.
@@ -94,7 +102,8 @@ def __str__(self) -> str:
94102 # Return the Python identifier.
95103 return '.' .join (self .parent + (self .name ,))
96104
97- def __repr__ (self ) -> str :
105+ @cached_property
106+ def __cached_string_repr (self ):
98107 return "({})" .format (
99108 ", " .join (
100109 (
@@ -108,6 +117,9 @@ def __repr__(self) -> str:
108117 )
109118 )
110119
120+ def __repr__ (self ) -> str :
121+ return self .__cached_string_repr
122+
111123 @property
112124 def module_alias (self ) -> str :
113125 """Return an appropriate module alias if necessary.
@@ -118,16 +130,15 @@ def module_alias(self) -> str:
118130 while still providing names that are fundamentally readable
119131 to users (albeit looking auto-generated).
120132 """
121- if self .module in self .collisions | RESERVED_NAMES :
133+ # This is a minor optimization to prevent constructing a temporary set.
134+ if self .module in self .collisions or self .module in RESERVED_NAMES :
122135 return '_' .join (
123136 (
124137 '' .join (
125- [
126- partial_name [0 ]
127- for i in self .package
128- for partial_name in i .split ("_" )
129- if i != self .api_naming .version
130- ]
138+ partial_name [0 ]
139+ for i in self .package
140+ for partial_name in i .split ("_" )
141+ if i != self .api_naming .version
131142 ),
132143 self .module ,
133144 )
@@ -302,7 +313,11 @@ def with_context(self, *, collisions: FrozenSet[str]) -> 'Address':
302313 ``Address`` object aliases module names to avoid naming collisions in
303314 the file being written.
304315 """
305- return dataclasses .replace (self , collisions = collisions )
316+ return (
317+ dataclasses .replace (self , collisions = collisions )
318+ if collisions and collisions != self .collisions
319+ else self
320+ )
306321
307322
308323@dataclasses .dataclass (frozen = True )
@@ -340,7 +355,7 @@ def with_context(self, *, collisions: FrozenSet[str]) -> 'Metadata':
340355 return dataclasses .replace (
341356 self ,
342357 address = self .address .with_context (collisions = collisions ),
343- )
358+ ) if collisions and collisions != self . address . collisions else self
344359
345360
346361@dataclasses .dataclass (frozen = True )
0 commit comments