1212# See the License for the specific language governing permissions and
1313# limitations under the License.
1414
15+ import abc
1516import dataclasses
1617import os
1718import re
2223from gapic import utils
2324from gapic .generator import options
2425
25-
26- @dataclasses .dataclass (frozen = True )
27- class Naming :
26+ # See https://github.com/python/mypy/issues/5374 for details on the mypy false
27+ # positive.
28+ @dataclasses .dataclass (frozen = True ) # type: ignore
29+ class Naming (abc .ABC ):
2830 """Naming data for an API.
2931
3032 This class contains the naming nomenclature used for this API
3133 within templates.
3234
33- An instance of this object is made available to every template
35+ An concrete child of this object is made available to every template
3436 (as ``api.naming``).
3537 """
3638 name : str = ''
@@ -43,11 +45,11 @@ def __post_init__(self):
4345 if not self .product_name :
4446 self .__dict__ ['product_name' ] = self .name
4547
46- @classmethod
47- def build (cls ,
48- * file_descriptors : descriptor_pb2 .FileDescriptorProto ,
49- opts : options .Options = options .Options (),
50- ) -> 'Naming' :
48+ @staticmethod
49+ def build (
50+ * file_descriptors : descriptor_pb2 .FileDescriptorProto ,
51+ opts : options .Options = options .Options (),
52+ ) -> 'Naming' :
5153 """Return a full Naming instance based on these file descriptors.
5254
5355 This is pieced together from the proto package names as well as the
@@ -103,10 +105,12 @@ def build(cls,
103105 match = cast (Match ,
104106 re .search (pattern = pattern , string = root_package )).groupdict ()
105107 match ['namespace' ] = match ['namespace' ] or ''
106- package_info = cls (
108+ klass = OldNaming if opts .old_naming else NewNaming
109+ package_info = klass (
107110 name = match ['name' ].capitalize (),
108- namespace = tuple ([i .capitalize ()
109- for i in match ['namespace' ].split ('.' ) if i ]),
111+ namespace = tuple (
112+ i .capitalize () for i in match ['namespace' ].split ('.' ) if i
113+ ),
110114 product_name = match ['name' ].capitalize (),
111115 proto_package = root_package ,
112116 version = match .get ('version' , '' ),
@@ -125,24 +129,24 @@ def build(cls,
125129 # likely make sense to many users to use dot-separated namespaces and
126130 # snake case, so handle that and do the right thing.
127131 if opts .name :
128- package_info = dataclasses .replace (package_info , name = ' ' .join ([
132+ package_info = dataclasses .replace (package_info , name = ' ' .join ((
129133 i .capitalize () for i in opts .name .replace ('_' , ' ' ).split (' ' )
130- ] ))
134+ ) ))
131135 if opts .namespace :
132- package_info = dataclasses .replace (package_info , namespace = tuple ([
136+ package_info = dataclasses .replace (package_info , namespace = tuple (
133137 # The join-and-split on "." here causes us to expand out
134138 # dot notation that we may have been sent; e.g. a one-tuple
135139 # with ('x.y',) will become a two-tuple: ('x', 'y')
136140 i .capitalize () for i in '.' .join (opts .namespace ).split ('.' )
137- ] ))
141+ ))
138142
139143 # Done; return the naming information.
140144 return package_info
141145
142146 def __bool__ (self ):
143147 """Return True if any of the fields are truthy, False otherwise."""
144148 return any (
145- [ getattr (self , i .name ) for i in dataclasses .fields (self )] ,
149+ ( getattr (self , i .name ) for i in dataclasses .fields (self )) ,
146150 )
147151
148152 @property
@@ -164,19 +168,18 @@ def module_namespace(self) -> Tuple[str, ...]:
164168 def namespace_packages (self ) -> Tuple [str , ...]:
165169 """Return the appropriate Python namespace packages."""
166170 answer : List [str ] = []
167- for cursor in [ i .lower () for i in self .namespace ] :
171+ for cursor in ( i .lower () for i in self .namespace ) :
168172 answer .append (f'{ answer [- 1 ]} .{ cursor } ' if answer else cursor )
169173 return tuple (answer )
170174
171175 @property
176+ @abc .abstractmethod
172177 def versioned_module_name (self ) -> str :
173178 """Return the versiond module name (e.g. ``apiname_v1``).
174179
175180 If there is no version, this is the same as ``module_name``.
176181 """
177- if self .version :
178- return f'{ self .module_name } _{ self .version } '
179- return self .module_name
182+ raise NotImplementedError
180183
181184 @property
182185 def warehouse_package_name (self ) -> str :
@@ -186,3 +189,23 @@ def warehouse_package_name(self) -> str:
186189 # proper package name.
187190 answer = list (self .namespace ) + self .name .split (' ' )
188191 return '-' .join (answer ).lower ()
192+
193+
194+ class NewNaming (Naming ):
195+ @property
196+ def versioned_module_name (self ) -> str :
197+ """Return the versiond module name (e.g. ``apiname_v1``).
198+
199+ If there is no version, this is the same as ``module_name``.
200+ """
201+ return self .module_name + (f'_{ self .version } ' if self .version else '' )
202+
203+
204+ class OldNaming (Naming ):
205+ @property
206+ def versioned_module_name (self ) -> str :
207+ """Return the versiond module name (e.g. ``apiname_v1``).
208+
209+ If there is no version, this is the same as ``module_name``.
210+ """
211+ return self .module_name + (f'.{ self .version } ' if self .version else '' )
0 commit comments