def testAtSignPolicy(self): class TestLanguageModel(language_model.LanguageModel): allowed_characters = '#' def __init__(self, **kwargs): super(TestLanguageModel, self).__init__(**kwargs) m = TestLanguageModel() # An identifier with several bad characters, including one at the end # which we expect to strip off. p = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE) self.assertEquals('Myname', m.ApplyCaseTransform('my@name', p)) self.assertEquals('Name', m.ApplyCaseTransform('@name', p)) p = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, atsign_policy=language_model.ATSIGN_STRIP) self.assertEquals('Myname', m.ApplyCaseTransform('my@name', p)) self.assertEquals('Name', m.ApplyCaseTransform('@name', p)) p = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, atsign_policy=language_model.ATSIGN_BREAK) self.assertEquals('MyName', m.ApplyCaseTransform('my@name', p)) self.assertEquals('Name', m.ApplyCaseTransform('@name', p))
class DartLanguageModel(language_model.LanguageModel): """A LanguageModel for Dart.""" language = 'dart' _SCHEMA_TYPE_TO_DART_TYPE = { 'any': 'core.Object', 'boolean': 'core.bool', 'integer': 'core.int', 'long': 'core.int', 'number': 'core.double', 'string': 'core.String', 'object': 'core.Object', } _DART_KEYWORDS = [ 'break', 'case', 'catch', 'class', 'const', 'continue', 'default', 'else', 'extends', 'final', 'finally', 'for', 'in', 'is', 'new', 'null', 'return', 'static', 'super', 'switch', 'throw', 'try', 'var', 'void', 'while' ] # We can not create classes which match a Dart keyword or built in object # type. RESERVED_CLASS_NAMES = _DART_KEYWORDS + _SCHEMA_TYPE_TO_DART_TYPE.values() array_of_policy = language_model.NamingPolicy( format_string='core.List<{name}>') map_of_policy = language_model.NamingPolicy( format_string='core.Map<core.String, {name}>') def __init__(self): super(DartLanguageModel, self).__init__(class_name_delimiter='') def GetCodeTypeFromDictionary(self, def_dict): """Gets an element's data type from its JSON definition. Overrides the default. Args: def_dict: (dict) The defintion dictionary for this type Returns: A name suitable for use as a Dart data type """ json_type = def_dict.get('type', 'String') native_type = self._SCHEMA_TYPE_TO_DART_TYPE.get(json_type) return native_type def ToMemberName(self, s, unused_the_api): """CamelCase a wire format name into a suitable Dart variable name.""" candidate = utilities.CamelCase(s) candidate = candidate[0].lower() + candidate[1:] while candidate in self.RESERVED_CLASS_NAMES: candidate += '_' return candidate
class TestLanguageModel(language_model.LanguageModel): class_name_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, separator='!CLASS!', format_string='C {name}') constant_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CASE, separator='!CONSTANT!', format_string='K {name}') def __init__(self, **kwargs): super(TestLanguageModel, self).__init__(**kwargs)
class TestLanguageModel(language_model.LanguageModel): allowed_characters = '#' member_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, format_string='{api_name}!{parent_name}!{name}') def __init__(self, **kwargs): super(TestLanguageModel, self).__init__(**kwargs)
def testApplyCaseTransform(self): class TestLanguageModel(language_model.LanguageModel): allowed_characters = '#' def __init__(self, **kwargs): super(TestLanguageModel, self).__init__(**kwargs) m = TestLanguageModel() # An identifier with several bad characters, including one at the end # which we expect to strip off. s = 'I-am -a_tesT@' p = language_model.NamingPolicy( case_transform=language_model.LOWER_CASE) self.assertEquals('iamatest', m.ApplyCaseTransform(s, p)) p = language_model.NamingPolicy( case_transform=language_model.PRESERVE_CASE, separator='_') self.assertEquals('I_am_a_tesT', m.ApplyCaseTransform(s, p)) p = language_model.NamingPolicy( case_transform=language_model.UPPER_CASE, separator='_') self.assertEquals('I_AM_A_TEST', m.ApplyCaseTransform(s, p)) p = language_model.NamingPolicy( case_transform=language_model.LOWER_CASE, separator='_') self.assertEquals('i_am_a_test', m.ApplyCaseTransform(s, p)) p = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE) self.assertEquals('IAmATesT', m.ApplyCaseTransform(s, p)) p = language_model.NamingPolicy( case_transform=language_model.LOWER_CAMEL_CASE) self.assertEquals('iAmATesT', m.ApplyCaseTransform(s, p)) p = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE) s = 'allow#this' self.assertEquals('Allow#this', m.ApplyCaseTransform(s, p))
class TestLanguageModel(language_model.LanguageModel): # transform and separator are not used for array of array_of_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, separator='will not be used', format_string='Array[{name}]') def __init__(self, **kwargs): super(TestLanguageModel, self).__init__(**kwargs)
class TestLanguageModel(language_model.LanguageModel): member_policy = language_model.NamingPolicy( case_transform=language_model.LOWER_CASE, separator='!MEMBER!', format_string='M {name}') getter_policy = language_model.NamingPolicy( case_transform=language_model.LOWER_CAMEL_CASE, separator='!GETTER!', format_string='G {name}') setter_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, separator='!SETTER!', format_string='S {name}') def __init__(self, **kwargs): super(TestLanguageModel, self).__init__(**kwargs)
class MyLanguageModel(language_model.LanguageModel): constant_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, separator='|')
class PythonLanguageModel(language_model.LanguageModel): """A LanguageModel for Python.""" language = 'python' _SCHEMA_TYPE_TO_PYTHON_TYPE = { 'any': 'object', 'array': 'list', 'boolean': 'bool', 'integer': 'long', 'number': 'float', 'object': 'object', 'string': 'str', } _PYTHON_KEYWORDS = discovery_client.RESERVED_WORDS # We can not create classes which match a Python keyword or built in object # type. RESERVED_CLASS_NAMES = _PYTHON_KEYWORDS array_of_policy = language_model.NamingPolicy(format_string='list') map_of_policy = language_model.NamingPolicy(format_string='dict') def __init__(self): super(PythonLanguageModel, self).__init__(class_name_delimiter='.') self._SUPPORTED_TYPES['array'] = self._List self._SUPPORTED_TYPES['boolean'] = self._Boolean self._SUPPORTED_TYPES['object'] = self._Dictionary def _Boolean(self, data_value): """Convert provided boolean to language specific literal.""" return unicode(bool(data_value.value)) def _Dictionary(self, data_value): """Convert provided object to language specific literal.""" wrapper = '{%s}' pairs = [] for key, val in data_value.value.iteritems(): val = self.RenderDataValue(val) pairs.append('"%s": %s' % (key, val)) return wrapper % ', '.join(pairs) def _List(self, data_value): """Convert provided array to language specific literal.""" wrapper = '[%s]' items = [self.RenderDataValue(element) for element in data_value.value] return wrapper % ', '.join(items) def GetCodeTypeFromDictionary(self, def_dict): """Gets an element's data type from its JSON definition. Overrides the default. Args: def_dict: (dict) The definition dictionary for this type Returns: A name suitable for use as a Python data type """ json_type = def_dict.get('type', 'string') native_type = (self._SCHEMA_TYPE_TO_PYTHON_TYPE.get(json_type) or self._SCHEMA_TYPE_TO_PYTHON_TYPE.get('string')) return native_type # pylint: disable=unused-argument def ToMemberName(self, s, the_api): """Convert a wire format name into a suitable Python variable name.""" return s.replace('-', '_')
class SampleLanguageModel(language_model.LanguageModel): """A LanguageModel for a sample language.""" language = 'sample' # Set up variable naming policy allowed_characters = '_' array_of_policy = language_model.NamingPolicy( format_string='{module}::Array<{name}>') map_of_policy = language_model.NamingPolicy( format_string='Map<string, {name}>') class_name_policy = language_model.NamingPolicy( case_transform=language_model.LOWER_CASE, separator='_') constant_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CASE, separator='_') member_policy = language_model.NamingPolicy(format_string='_{name}', separator='_') getter_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, format_string='get{name}') setter_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, format_string='set{name}') _SCHEMA_TYPE_TO_LANGUAGE_TYPE = { 'any': 'object', 'array': 'array', 'boolean': 'bool', 'integer': 'long', 'number': 'float', 'object': 'object', 'string': 'str', } # We can not create classes which match a keyword or built in object type. RESERVED_CLASS_NAMES = ['class', 'import', 'return'] # ... def __init__(self): super(SampleLanguageModel, self).__init__(module_name_delimiter='::') self._SUPPORTED_TYPES['array'] = self._List self._SUPPORTED_TYPES['boolean'] = self._Boolean self._SUPPORTED_TYPES['object'] = self._Dictionary def _Boolean(self, data_value): """Convert provided boolean to language specific literal.""" return unicode(bool(data_value.value)) def _Dictionary(self, data_value): """Convert provided object to language specific literal.""" wrapper = '{%s}' pairs = [] for key, val in data_value.value.iteritems(): val = self.RenderDataValue(val) pairs.append('"%s": %s' % (key, val)) return wrapper % ', '.join(pairs) def _List(self, data_value): """Convert provided array to language specific literal.""" wrapper = '[%s]' items = [self.RenderDataValue(element) for element in data_value.value] return wrapper % ', '.join(items) def GetCodeTypeFromDictionary(self, def_dict): """Gets an element's data type from its JSON definition. Overrides the default. Args: def_dict: (dict) The definition dictionary for this type Returns: A name suitable for use as a data type """ json_type = def_dict.get('type', 'string') native_type = (self._SCHEMA_TYPE_TO_LANGUAGE_TYPE.get(json_type) or self._SCHEMA_TYPE_TO_LANGUAGE_TYPE.get('string')) return native_type def ToMemberName(self, s, unused_api): """Convert a wire format name into a suitable variable name.""" return s.replace('-', '_')
def AnnotateApi(self, api_object): api_object.SetTemplateValue('enums', []) name = api_object.values['canonicalName'] api_name_policy = language_model.NamingPolicy( language_model.UPPER_CAMEL_CASE) camel_case_name = self._language_model.TransformString( api_object, name, api_name_policy) api_object.SetTemplateValue('serviceName', 'GTLService%s' % (camel_case_name)) rpc_url = api_object.GetTemplateValue('rpcUrl') if rpc_url: rpc_url += '?prettyPrint=false' api_object.SetTemplateValue('rpcUrl', rpc_url) # Only generate query class for RPC discovery documents, not REST. api_object.SetTemplateValue('query', 'GTLQuery%s' % (camel_case_name)) api_object.SetTemplateValue('parameters', [ param for param in api_object.GetTemplateValue('parameters') if param.GetTemplateValue('wireName') not in self._COMMON_PARAMS_TO_SKIP ]) super(ObjCGenerator, self).AnnotateApi(api_object) # Collect all method parameters for combined query class. # The query class has properties for all method parameters on the API, with # a static method for each API method to generate the appropriate query # object. There are likely to be naming clashes where two or more API # methods have parameters of the same name but different types. When this # happens, we use the 'id' type instead. method_parameters = {} for method in api_object.GetTemplateValue('methods'): for parameter in method.parameters: # Check for duplicate existing_parameter = method_parameters.get(parameter.codeName) if not existing_parameter: method_parameters[parameter.codeName] = parameter elif existing_parameter.codeType != parameter.codeType: # Duplicate exists with mismatched type; synthesise new parameter # using 'id' type instead. merged_param = api.Parameter( api_object, parameter.GetTemplateValue('wireName'), { 'description': '"%s" has different types for some query methods; see the ' 'documentation for the right type for each query method.' % (parameter.codeName), 'wireName': parameter['wireName'], 'codeName': parameter.codeName, }, existing_parameter.parent) merged_param.SetTemplateValue('codeType', 'id') merged_param.SetTemplateValue('attributes', 'nonatomic, retain') merged_param.SetTemplateValue('noPointer', True) method_parameters[parameter.codeName] = merged_param api_object.SetTemplateValue( 'methodParameters', [method_parameters[key] for key in sorted(method_parameters)]) # Also build a sorted list of all parameters, both common and per-method all_parameters = method_parameters.copy() for parameter in api_object.GetTemplateValue('parameters'): all_parameters[parameter.codeName] = parameter api_object.SetTemplateValue( 'allParameters', [all_parameters[key] for key in sorted(all_parameters)])
class ObjCLanguageModel(language_model.LanguageModel): """A LanguageModel for Objective-C.""" array_of_policy = language_model.NamingPolicy(format_string='NSArray') map_of_policy = language_model.NamingPolicy(format_string='NSDictionary') constant_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, format_string='k{schema.className}_{variable_name}_{name}') query_method_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, format_string='queryFor{name}') _SCHEMA_TYPE_TO_OBJC_TYPE = { ('any', None): 'String', ('boolean', None): 'NSNumber', ('integer', None): 'NSNumber', ('integer', 'int16'): 'NSNumber', ('integer', 'uint16'): 'NSNumber', ('integer', 'int32'): 'NSNumber', ('integer', 'uint32'): 'NSNumber', ('number', None): 'NSNumber', ('number', 'double'): 'NSNumber', ('number', 'float'): 'NSNumber', ('object', None): 'GTLObject', ('string', None): 'NSString', ('string', 'byte'): 'NSString', ('string', 'date'): 'NSString', ('string', 'date-time'): 'GTLDateTime', ('string', 'int64'): 'NSNumber', ('string', 'uint64'): 'NSNumber', } # http://www.binpress.com/tutorial/objective-c-reserved-keywords/43 _OBJC_KEYWORDS = [ 'asm', 'auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', 'inline', 'int', 'long', 'register', 'restrict', 'return', 'short', 'signed', 'sizeof', 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while', '_Bool', '_Complex', '_Imaginary', ] # C/C++ keywords (including C99 and C++ 0x11) _CPP_KEYWORDS = [ 'and', 'alignas', 'alignof', 'bitand', 'bitor', 'bool', 'catch', 'compl', 'constexpr', 'decltype', 'default', 'delete', 'explicit', 'export', 'false', 'friend', 'mutable', 'namespace', 'new', 'noexcept', 'not', 'nullptr', 'operator', 'or', 'private', 'protected', 'public', 'template', 'this', 'throw', 'true', 'try', 'typeid', 'typename', 'using', 'virtual', 'xor', 'restrict', ] _NAMES_TO_AVOID = [ 'bool', 'bycopy', 'byref', 'class', 'id', 'imp', 'in', 'inout', 'nil', 'no', 'null', 'object', 'oneway', 'out', 'protocol', 'sel', 'self', 'string', 'super', 'yes', 'atomic', 'nonatomic', 'retain', ] # We can not create classes which match a ObjC keyword or built in object # type. RESERVED_CLASS_NAMES = _OBJC_KEYWORDS + _CPP_KEYWORDS + _NAMES_TO_AVOID # We can not create data members which are in NSObject or GTLObject. RESERVED_MEMBER_NAMES = RESERVED_CLASS_NAMES + [ # NSObject methods 'description', 'debugDescription', 'finalize', 'hash', 'dealloc', 'init', 'superclass', 'retain', 'release', 'autorelease', 'retainCount', 'zone', 'isProxy', 'classForCoder', # Foundation protocol methods 'copy', 'copyWithZone', 'mutableCopy', 'mutableCopyWithZone', # GTLObject methods 'JSON', 'JSONString', 'surrogates', 'userProperties', 'additionalJSONKeys', 'additionalProperties', 'userData', 'fieldsDescription', ] reserved_words = RESERVED_MEMBER_NAMES def __init__(self, options=None): super(ObjCLanguageModel, self).__init__() self._options = options def GetCodeTypeFromDictionary(self, def_dict): """Convert a json primitive type to a suitable ObjC type name. Overrides the default. Args: def_dict: (dict) A dictionary describing Json schema for this Property. Returns: A name suitable for use as a class in the generator's target language. """ json_type = def_dict.get('type', 'string') json_format = def_dict.get('format') native_format = self._SCHEMA_TYPE_TO_OBJC_TYPE.get( (json_type, json_format), json_type) return native_format def ToMemberName(self, s, unused_api): """Convert a wire format name into a suitable ObjC variable name.""" if s.lower() == 'id': # Special case for id return 'identifier' camel_s = utilities.CamelCase(s) ret = camel_s[0].lower() + camel_s[1:] if s.lower() in ObjCLanguageModel.RESERVED_MEMBER_NAMES: ret = '%sProperty' % ret return ret def DefaultContainerPathForOwner(self, module): return '/'.join(utilities.ReversedDomainComponents( module.owner_domain))
class CSharpLanguageModel(language_model.LanguageModel): """A LanguageModel for C#.""" language = 'csharp' # Allowed '<>' for the usage of Nullable<xxx> # Allowed ',' to enable it in a dictionary allowed_characters = '<>,' # Set up variable naming policy array_of_policy = language_model.NamingPolicy( format_string='System.Collections.Generic.IList<{name}>') map_of_policy = language_model.NamingPolicy( format_string='System.Collections.Generic.IDictionary<string, {name}>') constant_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE) class_name_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, separator='.') member_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE) # TODO(user): Fix these 3 tables _SCHEMA_TYPE_TO_CSHARP_TYPE = { ('any', None): 'object', ('boolean', None): 'System.Nullable<bool>', ('integer', None): 'System.Nullable<int>', ('number', None): 'System.Nullable<double>', ('integer', 'int16'): 'System.Nullable<short>', ('integer', 'int32'): 'System.Nullable<int>', ('integer', 'uint32'): 'System.Nullable<long>', ('number', 'double'): 'System.Nullable<double>', ('number', 'float'): 'System.Nullable<float>', ('string', None): 'string', ('string', 'byte'): 'string', ('string', 'date'): 'string', # Date only in 'yyyy-mm-dd' format ('string', 'date-time'): 'System.Nullable<System.DateTime>', ('string', 'int64'): 'System.Nullable<long>', ('string', 'uint64'): 'System.Nullable<ulong>', ('object', None): 'object', } _CSHARP_KEYWORDS = [ 'abstract', 'as', 'base', 'bool', 'break', 'byte', 'case', 'catch', 'char', 'checked', 'class', 'const', 'continue', 'decimal', 'default', 'delegate', 'do', 'double', 'else', 'enum', 'event', 'explicit', 'extern', 'false', 'finally', 'fixed', 'float', 'for', 'foreach', 'goto', 'if', 'implicit', 'in', 'int', 'interface', 'internal', 'is', 'lock', 'long', 'namespace', 'new', 'null', 'object', 'operator', 'out', 'override', 'params', 'private', 'protected', 'public', 'readonly', 'ref', 'return', 'sbyte', 'sealed', 'short', 'sizeof', 'stackalloc', 'static', 'string', 'struct', 'switch', 'this', 'throw', 'true', 'try', 'typeof', 'uint', 'ulong', 'unchecked', 'unsafe', 'ushort', 'using', 'virtual', 'void', 'volatile', 'while', 'async', 'await' ] RESERVED_CLASS_NAMES = _CSHARP_KEYWORDS reserved_words = RESERVED_CLASS_NAMES def __init__(self): super(CSharpLanguageModel, self).__init__(class_name_delimiter='.') def GetCodeTypeFromDictionary(self, def_dict): """Gets an element's data type from its JSON definition. Overrides the default. Args: def_dict: (dict) The defintion dictionary for this type Returns: A name suitable for use as a C# data type """ json_type = def_dict.get('type', 'string') json_format = def_dict.get('format') native_type = self._SCHEMA_TYPE_TO_CSHARP_TYPE.get((json_type, json_format)) if not native_type: native_type = 'object' return native_type def ApplyPolicy(self, policy_name, variable, value): """Override the default policy applier so we can do special things.""" # We need to look for class members clashing with the name of the container. # TODO(user): This begs for having a more extensible conflict policy # mechanism in LanguageModel. if policy_name == 'member': return self.ToClassMemberName(variable, value) return super(CSharpLanguageModel, self).ApplyPolicy(policy_name, variable, value) def ToClassMemberName(self, variable, name): formatted = super(CSharpLanguageModel, self).ApplyPolicy('member', variable, name) if isinstance(variable, schema.Property): if variable.schema.values.get('className') == formatted: formatted += 'Value' return formatted def ToMemberName(self, s, the_api): """CamelCase a wire format name into a suitable C# variable name.""" camel_s = utilities.CamelCase(s) if s in self.RESERVED_CLASS_NAMES: # Prepend the service name return '%s%s' % (the_api.values['name'], camel_s) return camel_s[0].lower() + camel_s[1:] def DefaultContainerPathForOwner(self, module): """Returns the default path for the module containing this API.""" return '%s/Apis' % utilities.CamelCase(module.owner_name) def ToSafeClassName(self, name, the_api, parent): # pylint:disable=unused-argument # Retrieve the object in question. if parent: for child in parent.children: if child.get('wireName') == name: return child.className.split('.')[-1] # Fall through if it cannot be found if parent: name += '_data' return utilities.CamelCase(name)
class ObjCLanguageModel(language_model.LanguageModel): """A LanguageModel for Objective-C.""" array_of_policy = language_model.NamingPolicy(format_string='NSArray') map_of_policy = language_model.NamingPolicy(format_string='NSDictionary') constant_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, format_string='k{className}_{propertyName}_{name}') query_method_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, format_string='queryFor{name}') _SCHEMA_TYPE_TO_OBJC_TYPE = { ('any', None): 'String', ('boolean', None): 'NSNumber', ('integer', None): 'NSNumber', ('integer', 'int16'): 'NSNumber', ('integer', 'uint16'): 'NSNumber', ('integer', 'int32'): 'NSNumber', ('integer', 'uint32'): 'NSNumber', ('number', None): 'NSNumber', ('number', 'double'): 'NSNumber', ('number', 'float'): 'NSNumber', ('object', None): 'GTLObject', ('string', None): 'NSString', ('string', 'byte'): 'NSString', ('string', 'date'): 'NSString', ('string', 'date-time'): 'NSString', ('string', 'int64'): 'NSNumber', ('string', 'uint64'): 'NSNumber', } # http://www.binpress.com/tutorial/objective-c-reserved-keywords/43 _OBJC_KEYWORDS = [ 'asm', 'auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 'double', 'else', 'enum', 'extern', 'float', 'for', 'goto', 'if', 'inline', 'int', 'long', 'register', 'restrict', 'return', 'short', 'signed', 'sizeof', 'static', 'struct', 'switch', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'while', '_Bool', '_Complex', '_Imaginary', ] _NAMES_TO_AVOID = [ 'bool', 'bycopy', 'byref', 'class', 'id', 'imp', 'in', 'inout', 'nil', 'no', 'null', 'object', 'oneway', 'out', 'protocol', 'sel', 'self', 'string', 'super', 'yes', 'atomic', 'nonatomic', 'retain', ] # These names were things we had reserved in the past. It might be overly # broad _MORE_NAMES_TO_AVOID = [ 'any', 'boolean', 'integer', 'namespace', 'number', 'true', 'false', ] # We can not create classes which match a ObjC keyword or built in object # type. RESERVED_CLASS_NAMES = _OBJC_KEYWORDS + _NAMES_TO_AVOID + _MORE_NAMES_TO_AVOID # We can not create data members which are in GTLObject. RESERVED_MEMBER_NAMES = RESERVED_CLASS_NAMES + ['description', 'id'] reserved_words = RESERVED_MEMBER_NAMES def GetCodeTypeFromDictionary(self, def_dict): """Convert a json primitive type to a suitable ObjC type name. Overrides the default. Args: def_dict: (dict) A dictionary describing Json schema for this Property. Returns: A name suitable for use as a class in the generator's target language. """ json_type = def_dict.get('type', 'string') json_format = def_dict.get('format') native_format = self._SCHEMA_TYPE_TO_OBJC_TYPE.get( (json_type, json_format), json_type) return native_format def ToMemberName(self, s, unused_api): """Convert a wire format name into a suitable ObjC variable name.""" if s.lower() == 'id': # Special case for id return 'identifier' camel_s = utilities.CamelCase(s) ret = camel_s[0].lower() + camel_s[1:] if s.lower() in ObjCLanguageModel.RESERVED_MEMBER_NAMES: ret = '%sProperty' % ret return ret def DefaultContainerPathForOwner(self, module): path = module.owner_name.lower() if module.owner_domain == 'google.com' and not module.package_path: path += '/api/services' return path
class CppLanguageModel(language_model.LanguageModel): """A LanguageModel tuned for C++.""" language = 'cpp' member_policy = language_model.NamingPolicy( language_model.LOWER_UNCAMEL_CASE, '{name}_', '_') getter_policy = language_model.NamingPolicy( language_model.LOWER_UNCAMEL_CASE, 'get_{name}', '_') setter_policy = language_model.NamingPolicy( language_model.LOWER_UNCAMEL_CASE, 'set_{name}', '_') has_policy = language_model.NamingPolicy(language_model.LOWER_UNCAMEL_CASE, 'has_{name}', '_') unset_policy = language_model.NamingPolicy( language_model.LOWER_UNCAMEL_CASE, 'clear_{name}', '_') parameter_name_policy = language_model.NamingPolicy( language_model.LOWER_UNCAMEL_CASE, '{name}', '_', conflict_policy=language_model.NamingPolicy( language_model.LOWER_UNCAMEL_CASE, '{name}__', '_')) # From http://en.cppreference.com/w/cpp/keyword _CPP_KEYWORDS = [ 'alignas', 'alignof', 'and', 'and_eq', 'asm', 'auto', 'bitand', 'bitor', 'bool', 'break', 'case', 'catch', 'char', 'char16_t', 'char32_t', 'class', 'compl', 'const', 'constexpr', 'const_cast', 'continue', 'decltype', 'default', 'delete', 'do', 'double', 'dynamic_cast', 'else', 'enum', 'explicit', 'export', 'extern', 'false', 'float', 'for', 'friend', 'goto', 'if', 'inline', 'int', 'long', 'mutable', 'namespace', 'new', 'noexcept', 'not', 'not_eq', 'nullptr', 'operator', 'or', 'or_eq', 'private', 'protected', 'public', 'register', 'reinterpret_cast', 'return', 'short', 'signed', 'sizeof', 'static', 'static_assert', 'static_cast', 'struct', 'switch', 'template', 'this', 'thread_local', 'throw', 'true', 'try', 'typedef', 'typeid', 'typename', 'union', 'unsigned', 'using', 'virtual', 'void', 'volatile', 'wchar_t', 'while', 'xor', 'xor_eq' ] _SPECIAL_CLASS_NAMES = ['JsonCppData', 'SerializableJson'] # We can not create classes which match a C++ keyword or built in object # type or keyword. However since: # * class names are case-sensitive # * we'll always generate camel-case names (or least starting upper case) # * no C++ keywords are uppercase # We only have to worry about classes built into the generator itself. # And really we do not need to even do that since they are in a different # namespace. But we will for convenience and since it's probably rare. RESERVED_CLASS_NAMES = _SPECIAL_CLASS_NAMES reserved_words = RESERVED_CLASS_NAMES + _CPP_KEYWORDS def __init__(self, options=None): super(CppLanguageModel, self).__init__(class_name_delimiter='::', module_name_delimiter='_') self.type_map = self._BuildTypeMap(options) self._SUPPORTED_TYPES['boolean'] = self._Boolean self._SUPPORTED_TYPES['integer'] = self._Int def _BuildTypeMap(self, options=None): """Builds the map of discovery document types to C++ types. Args: options: (dict) Code generator options. Returns: map of (discovery type, format) keys to (C++ type, import value) values where the import value is header file name to include. """ self.global_namespace_ = '' self.client_namespace_ = 'client' builtin_type_h = None integral_type_h = '"googleapis/base/integral_types.h"' json_type_h = '"googleapis/client/data/jsoncpp_data.h"' # TODO(user): Implement open-source date.h date_time_h = '"googleapis/client/util/date_time.h"' date_h = date_time_h self.date_namespace_ = self.client_namespace_ # Dictionary of json type and format to its corresponding data type and # import definition. The first import in the imports list is the primary # import. return { ('boolean', None): ('bool', ImportDefinition([builtin_type_h])), ('any', None): (self.client_namespace_ + '::JsonCppData', ImportDefinition([json_type_h])), ('integer', None): ('int32', ImportDefinition([integral_type_h])), ('integer', 'int16'): ('int16', ImportDefinition([integral_type_h])), ('integer', 'uint16'): ('uint16', ImportDefinition([integral_type_h])), ('integer', 'int32'): ('int32', ImportDefinition([integral_type_h])), ('integer', 'uint32'): ('uint32', ImportDefinition([integral_type_h])), ('number', None): ('double', ImportDefinition([builtin_type_h])), ('number', 'double'): ('double', ImportDefinition([builtin_type_h])), ('number', 'float'): ('float', ImportDefinition([builtin_type_h])), ('object', None): (self.client_namespace_ + '::JsonCppData', ImportDefinition([json_type_h])), ('string', None): ('string', ImportDefinition(['<string>'])), ('string', 'byte'): ('string', ImportDefinition(['<string>'])), ('string', 'date'): (self.date_namespace_ + '::Date', ImportDefinition([date_h])), ('string', 'date-time'): (self.client_namespace_ + '::DateTime', ImportDefinition([date_time_h])), ('string', 'google-datetime'): ('string', ImportDefinition(['<string>'])), ('string', 'google-duration'): ('string', ImportDefinition(['<string>'])), ('string', 'google-fieldmask'): ('string', ImportDefinition(['<string>'])), ('string', 'int64'): ('int64', ImportDefinition([integral_type_h])), ('string', 'uint64'): ('uint64', ImportDefinition([integral_type_h])), } def _Boolean(self, data_value): """Convert provided boolean to language specific literal.""" return unicode(bool(data_value.value)).lower() def _Int(self, data_value): """Convert provided int to language specific literal.""" # Available types can be found in class variables code_types = { 'int16': '%s', 'uint16': '%s', 'int32': '%s', 'uint32': '%s', 'int64': '%sL', 'uint64': '%sL', } try: return code_types[data_value.code_type] % long(data_value.value) except KeyError: raise ValueError( ('Provided DataValue (%s) does not present an appropriate C++ ' 'annotated code type (%s).') % (data_value.value, data_value.code_type)) def GetCodeTypeFromDictionary(self, def_dict): """Convert a json schema type to a suitable C++ type name. Overrides the default. Args: def_dict: (dict) A dictionary describing Json schema for this Property. Returns: A name suitable for use as a class in the generator's target language. """ json_type = def_dict.get('type', 'string') json_format = def_dict.get('format') datatype_and_imports = self.type_map.get((json_type, json_format)) if datatype_and_imports: # If there is an entry in the type format to datatype and imports # dictionary set it as the native format. native_format = datatype_and_imports[0] else: # Could not find it in the dictionary, set it to the json type. native_format = utilities.CamelCase(json_type) return native_format def ArrayOf(self, unused_variable, type_name): """Take a type name and return the syntax for an array of them. Overrides the default. Args: unused_variable: (DataType) the data we want an array of. type_name: (str) A type name. Returns: A language specific string meaning "an array of type_name". """ # TODO(user): 20120817 # Need to figure out whether the type is a primitive or not, then # return appropriate array type (data, string or primitive). return '%s::JsonCppArray<%s >' % (self.client_namespace_, type_name) def MapOf(self, unused_variable, type_name): """Take a type name and return the syntax for a map of String to them. Overrides the default. Args: unused_variable: (DataType) the data we want an array of. type_name: (str) A type name. Returns: A language specific string meaning "an array of type_name". """ return '%s::JsonCppAssociativeArray<%s >' % (self.client_namespace_, type_name) def ToMemberName(self, s, the_api): """CamelCase a wire format name into a suitable C++ variable name.""" camel_s = utilities.CamelCase(s) if s.lower() in CppLanguageModel.RESERVED_CLASS_NAMES: # Prepend the service name return '%s%s' % (the_api.values['name'], camel_s) return camel_s[0].lower() + camel_s[1:] # pylint: disable=unused-argument def ToSafeClassName(self, s, the_api, parent=None): """Convert a name to a suitable class name in C++. Subclasses should override as appropriate. Args: s: (str) A canonical name for data element. (Usually the API wire format) the_api: (Api) The API this element is part of. For use as a hint when the name cannot be used directly. parent: (schema) The parent we use to get a safe class name. Returns: A name suitable for use as an element in C++. """ safe_class_name = utilities.CamelCase(s) if parent: for ancestor in parent.full_path: if ancestor.class_name == safe_class_name: safe_class_name = '%s%s' % (parent.class_name, safe_class_name) if safe_class_name.lower() in CppLanguageModel.RESERVED_CLASS_NAMES: # Prepend the service name safe_class_name = '%s%s' % (utilities.CamelCase( the_api.values['name']), utilities.CamelCase(s)) return safe_class_name def DefaultContainerPathForOwner(self, module): """Overrides the default implementation.""" result = '' if FLAGS.cpp_generator_add_owner_dir: result = module.owner_name.lower().replace(' ', '_') return result
class PhpLanguageModel(language_model.LanguageModel): """A LanguageModel tunded for PHP.""" language = 'php' _SCHEMA_TYPE_TO_PHP_TYPE = { 'any': 'array', 'boolean': 'bool', 'integer': 'int', 'long': 'string', # PHP doesn't support long integers. 'number': 'double', 'string': 'string', 'uint32': 'string', # PHP doesn't support unsigned integers. 'uint64': 'string', # PHP doesn't support unsigned integers. 'int32': 'int', 'int64': 'string', # Size of an integer is platform-dependent. 'double': 'double', 'float': 'float', } # Populated from http://php.net/manual/en/reserved.keywords.php PHP_KEYWORDS = frozenset(( 'abstract', 'and', 'array', 'as', 'break', 'call', 'callable', 'case', 'catch', 'cfunction', 'class', 'clone', 'const', 'continue', 'declare', 'default', 'do', 'else', 'elseif', 'empty', 'enddeclare', 'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'extends', 'final', 'finally', 'for', 'foreach', 'function', 'global', 'goto', 'if', 'implements', 'interface', 'instanceof', 'list', 'namespace', 'new', 'old_function', 'or', 'parent', 'private', 'protected', 'public', 'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor', 'yield', )) PHP_TYPES = frozenset(( 'bool', 'boolean', 'int', 'integer', 'file', 'float', 'double', 'string', 'array', 'object', 'null', 'resource', )) # We can not create classes which match a PHP keyword or built in object type. RESERVED_CLASS_NAMES = PHP_KEYWORDS | PHP_TYPES array_of_policy = language_model.NamingPolicy(format_string='{name}') map_of_policy = language_model.NamingPolicy(format_string='{name}') member_policy = language_model.NamingPolicy( case_transform=language_model.LOWER_CAMEL_CASE) getter_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, format_string='get{name}') setter_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_CAMEL_CASE, format_string='set{name}') def __init__(self): super(PhpLanguageModel, self).__init__(class_name_delimiter='.') def GetCodeTypeFromDictionary(self, def_dict): """Convert a json primitive type to a suitable PHP type name. Overrides the default. Args: def_dict: (dict) A dictionary describing Json schema for this Property. Returns: A name suitable for use as a class in PHP. """ # Unique identifier for this schema. json_type = def_dict.get('type', 'string') # An additional regular expression or key that helps constrain the value. # See: http://tools.ietf.org/html/draft-zyp-json-schema-03#section-5.23 json_format = def_dict.get('format') # If we know what to do with this format type, then use native type. php_type = (self._SCHEMA_TYPE_TO_PHP_TYPE.get(json_format) or self._SCHEMA_TYPE_TO_PHP_TYPE.get(json_type, json_type)) return php_type def ToMemberName(self, s, unused_api): """Convert a wire format name into a suitable PHP variable name. Overrides the default. Args: s: (string) The wire format name of a member variable. Returns: A name suitable for use as a member in PHP. """ return s.replace('-', '_').replace('.', '_').replace('/', '__')
class JavaLanguageModel(language_model.LanguageModel): """A LanguageModel tuned for Java.""" language = 'java' _JSON_STRING_IMPORT = 'com.google.api.client.json.JsonString' _JSON_STRING_TEMPLATE_VALUE = 'requiresJsonString' member_policy = language_model.NamingPolicy( language_model.LOWER_CAMEL_CASE) getter_policy = language_model.NamingPolicy( language_model.UPPER_CAMEL_CASE, 'get{name}') setter_policy = language_model.NamingPolicy( language_model.UPPER_CAMEL_CASE, 'set{name}') has_policy = language_model.NamingPolicy(language_model.UPPER_CAMEL_CASE, 'has{name}') array_of_policy = language_model.NamingPolicy( format_string='java.util.List<{name}>') map_of_policy = language_model.NamingPolicy( format_string='java.util.Map<String, {name}>') constant_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_UNCAMEL_CASE, separator='_') enum_policy = language_model.NamingPolicy(language_model.UPPER_CAMEL_CASE, format_string='{name}Values') # Dictionary of json type and format to its corresponding data type and # import definition. The first import in the imports list is the primary # import. _TYPE_BOOLEAN = _SimpleType('java.lang.Boolean', primative_type='boolean') _TYPE_DOUBLE = _SimpleType('java.lang.Double', primative_type='double') _TYPE_FLOAT = _SimpleType('java.lang.Float', primative_type='float') _TYPE_INTEGER = _SimpleType('java.lang.Integer', primative_type='int') _TYPE_LONG = _SimpleType('java.lang.Long', primative_type='long') _TYPE_SHORT = _SimpleType('java.lang.Short', primative_type='short') _TYPE_DATETIME = ('com.google.api.client.util.DateTime', ImportDefinition(['com.google.api.client.util.DateTime' ]), None) _TYPE_STRING = _SimpleType('java.lang.String') _TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS = { ('any', None): _SimpleType('java.lang.Object'), ('boolean', None): _TYPE_BOOLEAN, ('integer', None): _TYPE_INTEGER, ('integer', 'int16'): _TYPE_SHORT, ('integer', 'int32'): _TYPE_INTEGER, # We prefer Long here over UnsignedInteger because Long has built-in # support for autoboxing in Java. ('integer', 'uint32'): _TYPE_LONG, # TODO(user): Switch to java.lang.Number in a separate CL. # ('number', None): _SimpleType('java.lang.Number'), ('number', None): ('Number', ImportDefinition(), None), ('number', 'double'): _TYPE_DOUBLE, ('number', 'float'): _TYPE_FLOAT, ('object', None): _SimpleType('java.lang.Object'), ('string', None): _TYPE_STRING, ('string', 'byte'): _TYPE_STRING, ('string', 'date'): _TYPE_DATETIME, ('string', 'date-time'): _TYPE_DATETIME, ('string', 'int64'): ('java.lang.Long', ImportDefinition(['java.lang.Long', _JSON_STRING_IMPORT], [_JSON_STRING_TEMPLATE_VALUE]), 'long'), ('string', 'uint64'): ('java.math.BigInteger', ImportDefinition(['java.math.BigInteger', _JSON_STRING_IMPORT], [_JSON_STRING_TEMPLATE_VALUE]), None), } _JAVA_KEYWORDS = [ 'abstract', 'assert', 'boolean', 'break', 'byte', 'case', 'catch', 'char', 'class', 'const', 'continue', 'default', 'do', 'double', 'else', 'enum', 'extends', 'final', 'finally', 'float', 'for', 'goto', 'if', 'implements', 'import', 'instanceof', 'int', 'interface', 'long', 'native', 'new', 'package', 'private', 'protected', 'public', 'return', 'short', 'static', 'strictfp', 'super', 'switch', 'synchronized', 'this', 'throw', 'throws', 'transient', 'try', 'void', 'volatile', 'while' ] # TODO(user): Remove this. We should instead be using fully qualified names # for models to avoid collisions. This will be fixed in Bug 6448720. _SPECIAL_CLASS_NAMES = [ # Required because GenericData extends AbstractMap<String, Object> 'entry' ] # We can not create classes which match a Java keyword or built in object # type. RESERVED_CLASS_NAMES = _JAVA_KEYWORDS + _SPECIAL_CLASS_NAMES + [ 'float', 'integer', 'object', 'string', 'true', 'false', 'null' ] allowed_characters = '$' reserved_words = RESERVED_CLASS_NAMES def __init__(self, options=None): super(JavaLanguageModel, self).__init__(class_name_delimiter='.') self._type_map = JavaLanguageModel._TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS self._SUPPORTED_TYPES['boolean'] = self._Boolean self._SUPPORTED_TYPES['integer'] = self._Int self._options = options def _Boolean(self, data_value): """Convert provided boolean to language specific literal.""" return unicode(bool(data_value.value)).lower() def _Int(self, data_value): """Convert provided int to language specific literal.""" # Available types can be found in class variables code_types = { 'java.lang.Short': '%s', 'java.lang.Integer': '%s', 'java.lang.Long': '%sL', } try: return code_types[data_value.code_type] % long(data_value.value) except KeyError: raise ValueError(( 'Provided DataValue (%s) does not present an appropriate Java ' 'annotated code type (%s).') % (data_value.value, data_value.code_type)) @property def type_map(self): return self._type_map def _GetTypeInfo(self, def_dict): """Returns a tuple of type information for a json schema data dict. For the dictionary containing {type, [format]}, return the tuple of the form (Java class name, ImportDefinition, Java primitive data type) describing the appropriate Java data type. Args: def_dict: (dict) JSON schema data definition. Returns: tuple of (class name, ImportDefinition, primitive data type). """ json_type = def_dict.get('type', 'string') json_format = def_dict.get('format') result = self.type_map.get((json_type, json_format)) if result: return result # TODO(user): Uncomment this and update golden files. # result = self.type_map.get((json_type, None)) # if result: # return result # # raise ValueError('Unknown type: %s format: %s' % (json_type, json_format)) return (utilities.CamelCase(json_type), None, None) def GetCodeTypeFromDictionary(self, def_dict): """Convert a json schema type to a suitable Java type name. Overrides the default. Args: def_dict: (dict) A dictionary describing Json schema for this Property. Returns: A name suitable for use as a class in the generator's target language. """ return self._GetTypeInfo(def_dict)[0] def GetPrimitiveTypeFromDictionary(self, def_dict): """Convert a json schema type to a suitable Java primitive name or None. Overrides the default. Args: def_dict: (dict) A dictionary describing Json schema for this Property. Returns: A name suitable for use as a primitive in the generator's target language. """ return self._GetTypeInfo(def_dict)[2] def ToMemberName(self, s, the_api): """CamelCase a wire format name into a suitable Java variable name.""" camel_s = utilities.CamelCase(s) if s.lower() in JavaLanguageModel.RESERVED_CLASS_NAMES: # Prepend the service name return '%s%s' % (the_api.values['name'], camel_s) return camel_s[0].lower() + camel_s[1:] def ToSafeClassName(self, s, the_api, parent=None): """Convert a name to a suitable class name in Java. Subclasses should override as appropriate. Args: s: (str) A canonical name for data element. (Usually the API wire format) the_api: (Api) The API this element is part of. For use as a hint when the name cannot be used directly. parent: (schema) The parent we use to get a safe class name. Returns: A name suitable for use as an element in Java. """ safe_class_name = utilities.CamelCase(s) if parent: for ancestor in parent.full_path: if ancestor.safeClassName == safe_class_name: safe_class_name = '%s%s' % (parent.class_name, safe_class_name) if safe_class_name.lower() in JavaLanguageModel.RESERVED_CLASS_NAMES: api_name = utilities.CamelCase(the_api.values['name']) if utilities.CamelCase(the_api.values['canonicalName']): # Use canonical name if specified. api_name = utilities.CamelCase( the_api.values['canonicalName']).replace(' ', '') # Prepend the API name safe_class_name = '%s%s' % (api_name, utilities.CamelCase(s)) return safe_class_name def ToPropertyGetterMethodWithDelim(self, prop_name): """Convert a property name to the name of the getter method that returns it. Args: prop_name: (str) The name of a property. Returns: A Java specific name of the getter method that returns the specified property. Eg: returns .getXyz for a property called xyz. """ return '%sget%s()' % (self._class_name_delimiter, utilities.CamelCase(prop_name)) def CodeTypeForVoid(self): """Return the Java type name for a void. Overrides the default. Returns: (str) 'EmptyResponse' """ return 'Void' def DefaultContainerPathForOwner(self, module): """Overrides the default.""" if module.owner_domain == 'google.com': if ((self._options and self._options.get('google_api')) or not module.package_path): return 'com/google/api/services' return '/'.join(utilities.ReversedDomainComponents( module.owner_domain))
class GwtLanguageModel(java_generator.JavaLanguageModel): """A LanguageModel for GWT.""" language = 'java' member_policy = language_model.NamingPolicy( language_model.LOWER_CAMEL_CASE) getter_policy = language_model.NamingPolicy( language_model.UPPER_CAMEL_CASE, 'get{name}') setter_policy = language_model.NamingPolicy( language_model.UPPER_CAMEL_CASE, 'set{name}') constant_policy = language_model.NamingPolicy( case_transform=language_model.UPPER_UNCAMEL_CASE, separator='_') array_of_policy = language_model.NamingPolicy( format_string='java.util.List<{name}>') map_of_policy = language_model.NamingPolicy( format_string='java.util.Map<String, {name}>') # Dictionary of json type and format to its corresponding import definition. # The first import in the imports list is the primary import. TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS = { ('boolean', None): ('Boolean', ImportDefinition(['java.lang.Boolean'])), # Use String instead of Object for GWT ('any', None): ('String', ImportDefinition(['java.lang.String'])), ('integer', 'int16'): ('Short', ImportDefinition(['java.lang.Short'])), ('integer', 'int32'): ('Integer', ImportDefinition(['java.lang.Integer'])), # Java does not support Unsigned Integers ('integer', 'uint32'): ('Long', ImportDefinition(['java.lang.Long'])), ('number', 'double'): ('Double', ImportDefinition(['java.lang.Double'])), ('number', 'float'): ('Float', ImportDefinition(['java.lang.Float'])), # Use Splittable instead of Object for GWT ('object', None): ('Splittable', ImportDefinition( ['com.google.web.bindery.autobean.shared.Splittable'])), ('string', None): ('String', ImportDefinition(['java.lang.String'])), ('string', 'byte'): ('String', ImportDefinition(['java.lang.String'])), # GWT does not support date-time ('string', 'date-time'): ('String', ImportDefinition(['java.lang.String'])), ('string', 'int64'): ('Long', ImportDefinition(['java.lang.Long'])), # Java does not support Unsigned Integers ('string', 'uint64'): ('BigInteger', ImportDefinition(['java.math.BigInteger'])), } def __init__(self, options=None): super(GwtLanguageModel, self).__init__(options=options) self._type_map = GwtLanguageModel.TYPE_FORMAT_TO_DATATYPE_AND_IMPORTS def CodeTypeForVoid(self): """Return a GWT style void. Overrides the default. Returns: (str) 'EmptyResponse' """ # TODO(user): Handle empty responses in a more graceful way. Instead of # passing the type to use for empty responses, just signal that an empty # response is required, and handle that in the templates. return 'EmptyResponse' def DefaultContainerPathForOwner(self, module): """Overrides the default implementation.""" return '%s/api/gwt/services' % '/'.join( utilities.ReversedDomainComponents(module.owner_domain))