~ubuntu-branches/debian/stretch/protobuf/stretch

« back to all changes in this revision

Viewing changes to python/google/protobuf/descriptor_pool.py

  • Committer: Package Import Robot
  • Author(s): Robert S. Edmonds
  • Date: 2014-09-11 22:50:10 UTC
  • mfrom: (10.1.9 experimental)
  • Revision ID: package-import@ubuntu.com-20140911225010-wt4yo9dpc1fzuq5g
Tags: 2.6.0-3
Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
49
49
The message descriptor can be used in conjunction with the message_factory
50
50
module in order to create a protocol buffer class that can be encoded and
51
51
decoded.
 
52
 
 
53
If you want to get a Python class for the specified proto, use the
 
54
helper functions inside google.protobuf.message_factory
 
55
directly instead of this class.
52
56
"""
53
57
 
54
58
__author__ = 'matthewtoia@google.com (Matt Toia)'
55
59
 
56
 
from google.protobuf import descriptor_pb2
 
60
import sys
 
61
 
57
62
from google.protobuf import descriptor
58
63
from google.protobuf import descriptor_database
 
64
from google.protobuf import text_encoding
 
65
 
 
66
 
 
67
def _NormalizeFullyQualifiedName(name):
 
68
  """Remove leading period from fully-qualified type name.
 
69
 
 
70
  Due to b/13860351 in descriptor_database.py, types in the root namespace are
 
71
  generated with a leading period. This function removes that prefix.
 
72
 
 
73
  Args:
 
74
    name: A str, the fully-qualified symbol name.
 
75
 
 
76
  Returns:
 
77
    A str, the normalized fully-qualified symbol name.
 
78
  """
 
79
  return name.lstrip('.')
59
80
 
60
81
 
61
82
class DescriptorPool(object):
89
110
 
90
111
    self._internal_db.Add(file_desc_proto)
91
112
 
 
113
  def AddDescriptor(self, desc):
 
114
    """Adds a Descriptor to the pool, non-recursively.
 
115
 
 
116
    If the Descriptor contains nested messages or enums, the caller must
 
117
    explicitly register them. This method also registers the FileDescriptor
 
118
    associated with the message.
 
119
 
 
120
    Args:
 
121
      desc: A Descriptor.
 
122
    """
 
123
    if not isinstance(desc, descriptor.Descriptor):
 
124
      raise TypeError('Expected instance of descriptor.Descriptor.')
 
125
 
 
126
    self._descriptors[desc.full_name] = desc
 
127
    self.AddFileDescriptor(desc.file)
 
128
 
 
129
  def AddEnumDescriptor(self, enum_desc):
 
130
    """Adds an EnumDescriptor to the pool.
 
131
 
 
132
    This method also registers the FileDescriptor associated with the message.
 
133
 
 
134
    Args:
 
135
      enum_desc: An EnumDescriptor.
 
136
    """
 
137
 
 
138
    if not isinstance(enum_desc, descriptor.EnumDescriptor):
 
139
      raise TypeError('Expected instance of descriptor.EnumDescriptor.')
 
140
 
 
141
    self._enum_descriptors[enum_desc.full_name] = enum_desc
 
142
    self.AddFileDescriptor(enum_desc.file)
 
143
 
 
144
  def AddFileDescriptor(self, file_desc):
 
145
    """Adds a FileDescriptor to the pool, non-recursively.
 
146
 
 
147
    If the FileDescriptor contains messages or enums, the caller must explicitly
 
148
    register them.
 
149
 
 
150
    Args:
 
151
      file_desc: A FileDescriptor.
 
152
    """
 
153
 
 
154
    if not isinstance(file_desc, descriptor.FileDescriptor):
 
155
      raise TypeError('Expected instance of descriptor.FileDescriptor.')
 
156
    self._file_descriptors[file_desc.name] = file_desc
 
157
 
92
158
  def FindFileByName(self, file_name):
93
159
    """Gets a FileDescriptor by file name.
94
160
 
103
169
    """
104
170
 
105
171
    try:
 
172
      return self._file_descriptors[file_name]
 
173
    except KeyError:
 
174
      pass
 
175
 
 
176
    try:
106
177
      file_proto = self._internal_db.FindFileByName(file_name)
107
 
    except KeyError as error:
 
178
    except KeyError:
 
179
      _, error, _ = sys.exc_info()  #PY25 compatible for GAE.
108
180
      if self._descriptor_db:
109
181
        file_proto = self._descriptor_db.FindFileByName(file_name)
110
182
      else:
126
198
      KeyError: if the file can not be found in the pool.
127
199
    """
128
200
 
 
201
    symbol = _NormalizeFullyQualifiedName(symbol)
 
202
    try:
 
203
      return self._descriptors[symbol].file
 
204
    except KeyError:
 
205
      pass
 
206
 
 
207
    try:
 
208
      return self._enum_descriptors[symbol].file
 
209
    except KeyError:
 
210
      pass
 
211
 
129
212
    try:
130
213
      file_proto = self._internal_db.FindFileContainingSymbol(symbol)
131
 
    except KeyError as error:
 
214
    except KeyError:
 
215
      _, error, _ = sys.exc_info()  #PY25 compatible for GAE.
132
216
      if self._descriptor_db:
133
217
        file_proto = self._descriptor_db.FindFileContainingSymbol(symbol)
134
218
      else:
147
231
      The descriptor for the named type.
148
232
    """
149
233
 
150
 
    full_name = full_name.lstrip('.')  # fix inconsistent qualified name formats
 
234
    full_name = _NormalizeFullyQualifiedName(full_name)
151
235
    if full_name not in self._descriptors:
152
236
      self.FindFileContainingSymbol(full_name)
153
237
    return self._descriptors[full_name]
162
246
      The enum descriptor for the named type.
163
247
    """
164
248
 
165
 
    full_name = full_name.lstrip('.')  # fix inconsistent qualified name formats
 
249
    full_name = _NormalizeFullyQualifiedName(full_name)
166
250
    if full_name not in self._enum_descriptors:
167
251
      self.FindFileContainingSymbol(full_name)
168
252
    return self._enum_descriptors[full_name]
181
265
    """
182
266
 
183
267
    if file_proto.name not in self._file_descriptors:
 
268
      built_deps = list(self._GetDeps(file_proto.dependency))
 
269
      direct_deps = [self.FindFileByName(n) for n in file_proto.dependency]
 
270
 
184
271
      file_descriptor = descriptor.FileDescriptor(
185
272
          name=file_proto.name,
186
273
          package=file_proto.package,
187
274
          options=file_proto.options,
188
 
          serialized_pb=file_proto.SerializeToString())
 
275
          serialized_pb=file_proto.SerializeToString(),
 
276
          dependencies=direct_deps)
189
277
      scope = {}
190
 
      dependencies = list(self._GetDeps(file_proto))
191
 
 
192
 
      for dependency in dependencies:
193
 
        dep_desc = self.FindFileByName(dependency.name)
194
 
        dep_proto = descriptor_pb2.FileDescriptorProto.FromString(
195
 
            dep_desc.serialized_pb)
196
 
        package = '.' + dep_proto.package
197
 
        package_prefix = package + '.'
198
 
 
199
 
        def _strip_package(symbol):
200
 
          if symbol.startswith(package_prefix):
201
 
            return symbol[len(package_prefix):]
202
 
          return symbol
203
 
 
204
 
        symbols = list(self._ExtractSymbols(dep_proto.message_type, package))
205
 
        scope.update(symbols)
206
 
        scope.update((_strip_package(k), v) for k, v in symbols)
207
 
 
208
 
        symbols = list(self._ExtractEnums(dep_proto.enum_type, package))
209
 
        scope.update(symbols)
210
 
        scope.update((_strip_package(k), v) for k, v in symbols)
 
278
 
 
279
      # This loop extracts all the message and enum types from all the
 
280
      # dependencoes of the file_proto. This is necessary to create the
 
281
      # scope of available message types when defining the passed in
 
282
      # file proto.
 
283
      for dependency in built_deps:
 
284
        scope.update(self._ExtractSymbols(
 
285
            dependency.message_types_by_name.values()))
 
286
        scope.update((_PrefixWithDot(enum.full_name), enum)
 
287
                     for enum in dependency.enum_types_by_name.values())
211
288
 
212
289
      for message_type in file_proto.message_type:
213
290
        message_desc = self._ConvertMessageDescriptor(
214
291
            message_type, file_proto.package, file_descriptor, scope)
215
292
        file_descriptor.message_types_by_name[message_desc.name] = message_desc
 
293
 
216
294
      for enum_type in file_proto.enum_type:
217
 
        self._ConvertEnumDescriptor(enum_type, file_proto.package,
218
 
                                    file_descriptor, None, scope)
219
 
      for desc_proto in self._ExtractMessages(file_proto.message_type):
220
 
        self._SetFieldTypes(desc_proto, scope)
221
 
 
222
 
      for desc_proto in file_proto.message_type:
223
 
        desc = scope[desc_proto.name]
 
295
        file_descriptor.enum_types_by_name[enum_type.name] = (
 
296
            self._ConvertEnumDescriptor(enum_type, file_proto.package,
 
297
                                        file_descriptor, None, scope))
 
298
 
 
299
      for index, extension_proto in enumerate(file_proto.extension):
 
300
        extension_desc = self.MakeFieldDescriptor(
 
301
            extension_proto, file_proto.package, index, is_extension=True)
 
302
        extension_desc.containing_type = self._GetTypeFromScope(
 
303
            file_descriptor.package, extension_proto.extendee, scope)
 
304
        self.SetFieldType(extension_proto, extension_desc,
 
305
                          file_descriptor.package, scope)
 
306
        file_descriptor.extensions_by_name[extension_desc.name] = extension_desc
 
307
 
 
308
      for desc_proto in file_proto.message_type:
 
309
        self.SetAllFieldTypes(file_proto.package, desc_proto, scope)
 
310
 
 
311
      if file_proto.package:
 
312
        desc_proto_prefix = _PrefixWithDot(file_proto.package)
 
313
      else:
 
314
        desc_proto_prefix = ''
 
315
 
 
316
      for desc_proto in file_proto.message_type:
 
317
        desc = self._GetTypeFromScope(desc_proto_prefix, desc_proto.name, scope)
224
318
        file_descriptor.message_types_by_name[desc_proto.name] = desc
225
319
      self.Add(file_proto)
226
320
      self._file_descriptors[file_proto.name] = file_descriptor
260
354
    enums = [
261
355
        self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope)
262
356
        for enum in desc_proto.enum_type]
263
 
    fields = [self._MakeFieldDescriptor(field, desc_name, index)
 
357
    fields = [self.MakeFieldDescriptor(field, desc_name, index)
264
358
              for index, field in enumerate(desc_proto.field)]
265
 
    extensions = [self._MakeFieldDescriptor(extension, desc_name, True)
266
 
                  for index, extension in enumerate(desc_proto.extension)]
 
359
    extensions = [
 
360
        self.MakeFieldDescriptor(extension, desc_name, index, is_extension=True)
 
361
        for index, extension in enumerate(desc_proto.extension)]
 
362
    oneofs = [
 
363
        descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)),
 
364
                                   index, None, [])
 
365
        for index, desc in enumerate(desc_proto.oneof_decl)]
267
366
    extension_ranges = [(r.start, r.end) for r in desc_proto.extension_range]
268
367
    if extension_ranges:
269
368
      is_extendable = True
275
374
        filename=file_name,
276
375
        containing_type=None,
277
376
        fields=fields,
 
377
        oneofs=oneofs,
278
378
        nested_types=nested,
279
379
        enum_types=enums,
280
380
        extensions=extensions,
288
388
      nested.containing_type = desc
289
389
    for enum in desc.enum_types:
290
390
      enum.containing_type = desc
291
 
    scope[desc_proto.name] = desc
292
 
    scope['.' + desc_name] = desc
 
391
    for field_index, field_desc in enumerate(desc_proto.field):
 
392
      if field_desc.HasField('oneof_index'):
 
393
        oneof_index = field_desc.oneof_index
 
394
        oneofs[oneof_index].fields.append(fields[field_index])
 
395
        fields[field_index].containing_oneof = oneofs[oneof_index]
 
396
 
 
397
    scope[_PrefixWithDot(desc_name)] = desc
293
398
    self._descriptors[desc_name] = desc
294
399
    return desc
295
400
 
327
432
                                     values=values,
328
433
                                     containing_type=containing_type,
329
434
                                     options=enum_proto.options)
330
 
    scope[enum_proto.name] = desc
331
435
    scope['.%s' % enum_name] = desc
332
436
    self._enum_descriptors[enum_name] = desc
333
437
    return desc
334
438
 
335
 
  def _MakeFieldDescriptor(self, field_proto, message_name, index,
336
 
                           is_extension=False):
 
439
  def MakeFieldDescriptor(self, field_proto, message_name, index,
 
440
                          is_extension=False):
337
441
    """Creates a field descriptor from a FieldDescriptorProto.
338
442
 
339
443
    For message and enum type fields, this method will do a look up
374
478
        extension_scope=None,
375
479
        options=field_proto.options)
376
480
 
377
 
  def _SetFieldTypes(self, desc_proto, scope):
378
 
    """Sets the field's type, cpp_type, message_type and enum_type.
 
481
  def SetAllFieldTypes(self, package, desc_proto, scope):
 
482
    """Sets all the descriptor's fields's types.
 
483
 
 
484
    This method also sets the containing types on any extensions.
379
485
 
380
486
    Args:
 
487
      package: The current package of desc_proto.
381
488
      desc_proto: The message descriptor to update.
382
489
      scope: Enclosing scope of available types.
383
490
    """
384
491
 
385
 
    desc = scope[desc_proto.name]
386
 
    for field_proto, field_desc in zip(desc_proto.field, desc.fields):
387
 
      if field_proto.type_name:
388
 
        type_name = field_proto.type_name
389
 
        if type_name not in scope:
390
 
          type_name = '.' + type_name
391
 
        desc = scope[type_name]
392
 
      else:
393
 
        desc = None
394
 
 
395
 
      if not field_proto.HasField('type'):
396
 
        if isinstance(desc, descriptor.Descriptor):
397
 
          field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
398
 
        else:
399
 
          field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
400
 
 
401
 
      field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
402
 
          field_proto.type)
403
 
 
404
 
      if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
405
 
          or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
406
 
        field_desc.message_type = desc
407
 
 
408
 
      if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
409
 
        field_desc.enum_type = desc
410
 
 
411
 
      if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
412
 
        field_desc.has_default = False
413
 
        field_desc.default_value = []
414
 
      elif field_proto.HasField('default_value'):
415
 
        field_desc.has_default = True
416
 
        if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
417
 
            field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
418
 
          field_desc.default_value = float(field_proto.default_value)
419
 
        elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
420
 
          field_desc.default_value = field_proto.default_value
421
 
        elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
422
 
          field_desc.default_value = field_proto.default_value.lower() == 'true'
423
 
        elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
424
 
          field_desc.default_value = field_desc.enum_type.values_by_name[
425
 
              field_proto.default_value].index
426
 
        else:
427
 
          field_desc.default_value = int(field_proto.default_value)
428
 
      else:
429
 
        field_desc.has_default = False
430
 
        field_desc.default_value = None
431
 
 
432
 
      field_desc.type = field_proto.type
 
492
    package = _PrefixWithDot(package)
 
493
 
 
494
    main_desc = self._GetTypeFromScope(package, desc_proto.name, scope)
 
495
 
 
496
    if package == '.':
 
497
      nested_package = _PrefixWithDot(desc_proto.name)
 
498
    else:
 
499
      nested_package = '.'.join([package, desc_proto.name])
 
500
 
 
501
    for field_proto, field_desc in zip(desc_proto.field, main_desc.fields):
 
502
      self.SetFieldType(field_proto, field_desc, nested_package, scope)
 
503
 
 
504
    for extension_proto, extension_desc in (
 
505
        zip(desc_proto.extension, main_desc.extensions)):
 
506
      extension_desc.containing_type = self._GetTypeFromScope(
 
507
          nested_package, extension_proto.extendee, scope)
 
508
      self.SetFieldType(extension_proto, extension_desc, nested_package, scope)
433
509
 
434
510
    for nested_type in desc_proto.nested_type:
435
 
      self._SetFieldTypes(nested_type, scope)
 
511
      self.SetAllFieldTypes(nested_package, nested_type, scope)
 
512
 
 
513
  def SetFieldType(self, field_proto, field_desc, package, scope):
 
514
    """Sets the field's type, cpp_type, message_type and enum_type.
 
515
 
 
516
    Args:
 
517
      field_proto: Data about the field in proto format.
 
518
      field_desc: The descriptor to modiy.
 
519
      package: The package the field's container is in.
 
520
      scope: Enclosing scope of available types.
 
521
    """
 
522
    if field_proto.type_name:
 
523
      desc = self._GetTypeFromScope(package, field_proto.type_name, scope)
 
524
    else:
 
525
      desc = None
 
526
 
 
527
    if not field_proto.HasField('type'):
 
528
      if isinstance(desc, descriptor.Descriptor):
 
529
        field_proto.type = descriptor.FieldDescriptor.TYPE_MESSAGE
 
530
      else:
 
531
        field_proto.type = descriptor.FieldDescriptor.TYPE_ENUM
 
532
 
 
533
    field_desc.cpp_type = descriptor.FieldDescriptor.ProtoTypeToCppProtoType(
 
534
        field_proto.type)
 
535
 
 
536
    if (field_proto.type == descriptor.FieldDescriptor.TYPE_MESSAGE
 
537
        or field_proto.type == descriptor.FieldDescriptor.TYPE_GROUP):
 
538
      field_desc.message_type = desc
 
539
 
 
540
    if field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
 
541
      field_desc.enum_type = desc
 
542
 
 
543
    if field_proto.label == descriptor.FieldDescriptor.LABEL_REPEATED:
 
544
      field_desc.has_default_value = False
 
545
      field_desc.default_value = []
 
546
    elif field_proto.HasField('default_value'):
 
547
      field_desc.has_default_value = True
 
548
      if (field_proto.type == descriptor.FieldDescriptor.TYPE_DOUBLE or
 
549
          field_proto.type == descriptor.FieldDescriptor.TYPE_FLOAT):
 
550
        field_desc.default_value = float(field_proto.default_value)
 
551
      elif field_proto.type == descriptor.FieldDescriptor.TYPE_STRING:
 
552
        field_desc.default_value = field_proto.default_value
 
553
      elif field_proto.type == descriptor.FieldDescriptor.TYPE_BOOL:
 
554
        field_desc.default_value = field_proto.default_value.lower() == 'true'
 
555
      elif field_proto.type == descriptor.FieldDescriptor.TYPE_ENUM:
 
556
        field_desc.default_value = field_desc.enum_type.values_by_name[
 
557
            field_proto.default_value].index
 
558
      elif field_proto.type == descriptor.FieldDescriptor.TYPE_BYTES:
 
559
        field_desc.default_value = text_encoding.CUnescape(
 
560
            field_proto.default_value)
 
561
      else:
 
562
        field_desc.default_value = int(field_proto.default_value)
 
563
    else:
 
564
      field_desc.has_default_value = False
 
565
      field_desc.default_value = None
 
566
 
 
567
    field_desc.type = field_proto.type
436
568
 
437
569
  def _MakeEnumValueDescriptor(self, value_proto, index):
438
570
    """Creates a enum value descriptor object from a enum value proto.
452
584
        options=value_proto.options,
453
585
        type=None)
454
586
 
455
 
  def _ExtractSymbols(self, desc_protos, package):
 
587
  def _ExtractSymbols(self, descriptors):
456
588
    """Pulls out all the symbols from descriptor protos.
457
589
 
458
590
    Args:
459
 
      desc_protos: The protos to extract symbols from.
460
 
      package: The package containing the descriptor type.
 
591
      descriptors: The messages to extract descriptors from.
461
592
    Yields:
462
593
      A two element tuple of the type name and descriptor object.
463
594
    """
464
595
 
465
 
    for desc_proto in desc_protos:
466
 
      if package:
467
 
        message_name = '.'.join((package, desc_proto.name))
468
 
      else:
469
 
        message_name = desc_proto.name
470
 
      message_desc = self.FindMessageTypeByName(message_name)
471
 
      yield (message_name, message_desc)
472
 
      for symbol in self._ExtractSymbols(desc_proto.nested_type, message_name):
473
 
        yield symbol
474
 
      for symbol in self._ExtractEnums(desc_proto.enum_type, message_name):
475
 
        yield symbol
476
 
 
477
 
  def _ExtractEnums(self, enum_protos, package):
478
 
    """Pulls out all the symbols from enum protos.
479
 
 
480
 
    Args:
481
 
      enum_protos: The protos to extract symbols from.
482
 
      package: The package containing the enum type.
483
 
 
484
 
    Yields:
485
 
      A two element tuple of the type name and enum descriptor object.
486
 
    """
487
 
 
488
 
    for enum_proto in enum_protos:
489
 
      if package:
490
 
        enum_name = '.'.join((package, enum_proto.name))
491
 
      else:
492
 
        enum_name = enum_proto.name
493
 
      enum_desc = self.FindEnumTypeByName(enum_name)
494
 
      yield (enum_name, enum_desc)
495
 
 
496
 
  def _ExtractMessages(self, desc_protos):
497
 
    """Pulls out all the message protos from descriptos.
498
 
 
499
 
    Args:
500
 
      desc_protos: The protos to extract symbols from.
501
 
 
502
 
    Yields:
503
 
      Descriptor protos.
504
 
    """
505
 
 
506
 
    for desc_proto in desc_protos:
507
 
      yield desc_proto
508
 
      for message in self._ExtractMessages(desc_proto.nested_type):
509
 
        yield message
510
 
 
511
 
  def _GetDeps(self, file_proto):
 
596
    for desc in descriptors:
 
597
      yield (_PrefixWithDot(desc.full_name), desc)
 
598
      for symbol in self._ExtractSymbols(desc.nested_types):
 
599
        yield symbol
 
600
      for enum in desc.enum_types:
 
601
        yield (_PrefixWithDot(enum.full_name), enum)
 
602
 
 
603
  def _GetDeps(self, dependencies):
512
604
    """Recursively finds dependencies for file protos.
513
605
 
514
606
    Args:
515
 
      file_proto: The proto to get dependencies from.
 
607
      dependencies: The names of the files being depended on.
516
608
 
517
609
    Yields:
518
610
      Each direct and indirect dependency.
519
611
    """
520
612
 
521
 
    for dependency in file_proto.dependency:
 
613
    for dependency in dependencies:
522
614
      dep_desc = self.FindFileByName(dependency)
523
 
      dep_proto = descriptor_pb2.FileDescriptorProto.FromString(
524
 
          dep_desc.serialized_pb)
525
 
      yield dep_proto
526
 
      for parent_dep in self._GetDeps(dep_proto):
 
615
      yield dep_desc
 
616
      for parent_dep in dep_desc.dependencies:
527
617
        yield parent_dep
 
618
 
 
619
  def _GetTypeFromScope(self, package, type_name, scope):
 
620
    """Finds a given type name in the current scope.
 
621
 
 
622
    Args:
 
623
      package: The package the proto should be located in.
 
624
      type_name: The name of the type to be found in the scope.
 
625
      scope: Dict mapping short and full symbols to message and enum types.
 
626
 
 
627
    Returns:
 
628
      The descriptor for the requested type.
 
629
    """
 
630
    if type_name not in scope:
 
631
      components = _PrefixWithDot(package).split('.')
 
632
      while components:
 
633
        possible_match = '.'.join(components + [type_name])
 
634
        if possible_match in scope:
 
635
          type_name = possible_match
 
636
          break
 
637
        else:
 
638
          components.pop(-1)
 
639
    return scope[type_name]
 
640
 
 
641
 
 
642
def _PrefixWithDot(name):
 
643
  return name if name.startswith('.') else '.%s' % name