How to use enum method in Gherkin-python

Best Python code snippet using gherkin-python

__init__.py

Source:__init__.py Github

copy

Full Screen

1"""Python Enumerations"""2import sys as _sys3__all__ = ['Enum', 'IntEnum', 'unique']4version = 1, 1, 65pyver = float('%s.%s' % _sys.version_info[:2])6try:7 any8except NameError:9 def any(iterable):10 for element in iterable:11 if element:12 return True13 return False14try:15 from collections import OrderedDict16except ImportError:17 OrderedDict = None18try:19 basestring20except NameError:21 # In Python 2 basestring is the ancestor of both str and unicode22 # in Python 3 it's just str, but was missing in 3.123 basestring = str24try:25 unicode26except NameError:27 # In Python 3 unicode no longer exists (it's just str)28 unicode = str29class _RouteClassAttributeToGetattr(object):30 """Route attribute access on a class to __getattr__.31 This is a descriptor, used to define attributes that act differently when32 accessed through an instance and through a class. Instance access remains33 normal, but access to an attribute through a class will be routed to the34 class's __getattr__ method; this is done by raising AttributeError.35 """36 def __init__(self, fget=None):37 self.fget = fget38 def __get__(self, instance, ownerclass=None):39 if instance is None:40 raise AttributeError()41 return self.fget(instance)42 def __set__(self, instance, value):43 raise AttributeError("can't set attribute")44 def __delete__(self, instance):45 raise AttributeError("can't delete attribute")46def _is_descriptor(obj):47 """Returns True if obj is a descriptor, False otherwise."""48 return (49 hasattr(obj, '__get__') or50 hasattr(obj, '__set__') or51 hasattr(obj, '__delete__'))52def _is_dunder(name):53 """Returns True if a __dunder__ name, False otherwise."""54 return (name[:2] == name[-2:] == '__' and55 name[2:3] != '_' and56 name[-3:-2] != '_' and57 len(name) > 4)58def _is_sunder(name):59 """Returns True if a _sunder_ name, False otherwise."""60 return (name[0] == name[-1] == '_' and61 name[1:2] != '_' and62 name[-2:-1] != '_' and63 len(name) > 2)64def _make_class_unpicklable(cls):65 """Make the given class un-picklable."""66 def _break_on_call_reduce(self, protocol=None):67 raise TypeError('%r cannot be pickled' % self)68 cls.__reduce_ex__ = _break_on_call_reduce69 cls.__module__ = '<unknown>'70class _EnumDict(dict):71 """Track enum member order and ensure member names are not reused.72 EnumMeta will use the names found in self._member_names as the73 enumeration member names.74 """75 def __init__(self):76 super(_EnumDict, self).__init__()77 self._member_names = []78 def __setitem__(self, key, value):79 """Changes anything not dundered or not a descriptor.80 If a descriptor is added with the same name as an enum member, the name81 is removed from _member_names (this may leave a hole in the numerical82 sequence of values).83 If an enum member name is used twice, an error is raised; duplicate84 values are not checked for.85 Single underscore (sunder) names are reserved.86 Note: in 3.x __order__ is simply discarded as a not necessary piece87 leftover from 2.x88 """89 if pyver >= 3.0 and key in ('_order_', '__order__'):90 return91 elif key == '__order__':92 key = '_order_'93 if _is_sunder(key):94 if key != '_order_':95 raise ValueError('_names_ are reserved for future Enum use')96 elif _is_dunder(key):97 pass98 elif key in self._member_names:99 # descriptor overwriting an enum?100 raise TypeError('Attempted to reuse key: %r' % key)101 elif not _is_descriptor(value):102 if key in self:103 # enum overwriting a descriptor?104 raise TypeError('Key already defined as: %r' % self[key])105 self._member_names.append(key)106 super(_EnumDict, self).__setitem__(key, value)107# Dummy value for Enum as EnumMeta explicity checks for it, but of course until108# EnumMeta finishes running the first time the Enum class doesn't exist. This109# is also why there are checks in EnumMeta like `if Enum is not None`110Enum = None111class EnumMeta(type):112 """Metaclass for Enum"""113 @classmethod114 def __prepare__(metacls, cls, bases):115 return _EnumDict()116 def __new__(metacls, cls, bases, classdict):117 # an Enum class is final once enumeration items have been defined; it118 # cannot be mixed with other types (int, float, etc.) if it has an119 # inherited __new__ unless a new __new__ is defined (or the resulting120 # class will fail).121 if type(classdict) is dict:122 original_dict = classdict123 classdict = _EnumDict()124 for k, v in original_dict.items():125 classdict[k] = v126 member_type, first_enum = metacls._get_mixins_(bases)127 __new__, save_new, use_args = metacls._find_new_(classdict, member_type,128 first_enum)129 # save enum items into separate mapping so they don't get baked into130 # the new class131 members = dict((k, classdict[k]) for k in classdict._member_names)132 for name in classdict._member_names:133 del classdict[name]134 # py2 support for definition order135 _order_ = classdict.get('_order_')136 if _order_ is None:137 if pyver < 3.0:138 try:139 _order_ = [name for (name, value) in sorted(members.items(), key=lambda item: item[1])]140 except TypeError:141 _order_ = [name for name in sorted(members.keys())]142 else:143 _order_ = classdict._member_names144 else:145 del classdict['_order_']146 if pyver < 3.0:147 _order_ = _order_.replace(',', ' ').split()148 aliases = [name for name in members if name not in _order_]149 _order_ += aliases150 # check for illegal enum names (any others?)151 invalid_names = set(members) & set(['mro'])152 if invalid_names:153 raise ValueError('Invalid enum member name(s): %s' % (154 ', '.join(invalid_names), ))155 # save attributes from super classes so we know if we can take156 # the shortcut of storing members in the class dict157 base_attributes = set([a for b in bases for a in b.__dict__])158 # create our new Enum type159 enum_class = super(EnumMeta, metacls).__new__(metacls, cls, bases, classdict)160 enum_class._member_names_ = [] # names in random order161 if OrderedDict is not None:162 enum_class._member_map_ = OrderedDict()163 else:164 enum_class._member_map_ = {} # name->value map165 enum_class._member_type_ = member_type166 # Reverse value->name map for hashable values.167 enum_class._value2member_map_ = {}168 # instantiate them, checking for duplicates as we go169 # we instantiate first instead of checking for duplicates first in case170 # a custom __new__ is doing something funky with the values -- such as171 # auto-numbering ;)172 if __new__ is None:173 __new__ = enum_class.__new__174 for member_name in _order_:175 value = members[member_name]176 if not isinstance(value, tuple):177 args = (value, )178 else:179 args = value180 if member_type is tuple: # special case for tuple enums181 args = (args, ) # wrap it one more time182 if not use_args or not args:183 enum_member = __new__(enum_class)184 if not hasattr(enum_member, '_value_'):185 enum_member._value_ = value186 else:187 enum_member = __new__(enum_class, *args)188 if not hasattr(enum_member, '_value_'):189 enum_member._value_ = member_type(*args)190 value = enum_member._value_191 enum_member._name_ = member_name192 enum_member.__objclass__ = enum_class193 enum_member.__init__(*args)194 # If another member with the same value was already defined, the195 # new member becomes an alias to the existing one.196 for name, canonical_member in enum_class._member_map_.items():197 if canonical_member.value == enum_member._value_:198 enum_member = canonical_member199 break200 else:201 # Aliases don't appear in member names (only in __members__).202 enum_class._member_names_.append(member_name)203 # performance boost for any member that would not shadow204 # a DynamicClassAttribute (aka _RouteClassAttributeToGetattr)205 if member_name not in base_attributes:206 setattr(enum_class, member_name, enum_member)207 # now add to _member_map_208 enum_class._member_map_[member_name] = enum_member209 try:210 # This may fail if value is not hashable. We can't add the value211 # to the map, and by-value lookups for this value will be212 # linear.213 enum_class._value2member_map_[value] = enum_member214 except TypeError:215 pass216 # If a custom type is mixed into the Enum, and it does not know how217 # to pickle itself, pickle.dumps will succeed but pickle.loads will218 # fail. Rather than have the error show up later and possibly far219 # from the source, sabotage the pickle protocol for this class so220 # that pickle.dumps also fails.221 #222 # However, if the new class implements its own __reduce_ex__, do not223 # sabotage -- it's on them to make sure it works correctly. We use224 # __reduce_ex__ instead of any of the others as it is preferred by225 # pickle over __reduce__, and it handles all pickle protocols.226 unpicklable = False227 if '__reduce_ex__' not in classdict:228 if member_type is not object:229 methods = ('__getnewargs_ex__', '__getnewargs__',230 '__reduce_ex__', '__reduce__')231 if not any(m in member_type.__dict__ for m in methods):232 _make_class_unpicklable(enum_class)233 unpicklable = True234 # double check that repr and friends are not the mixin's or various235 # things break (such as pickle)236 for name in ('__repr__', '__str__', '__format__', '__reduce_ex__'):237 class_method = getattr(enum_class, name)238 obj_method = getattr(member_type, name, None)239 enum_method = getattr(first_enum, name, None)240 if name not in classdict and class_method is not enum_method:241 if name == '__reduce_ex__' and unpicklable:242 continue243 setattr(enum_class, name, enum_method)244 # method resolution and int's are not playing nice245 # Python's less than 2.6 use __cmp__246 if pyver < 2.6:247 if issubclass(enum_class, int):248 setattr(enum_class, '__cmp__', getattr(int, '__cmp__'))249 elif pyver < 3.0:250 if issubclass(enum_class, int):251 for method in (252 '__le__',253 '__lt__',254 '__gt__',255 '__ge__',256 '__eq__',257 '__ne__',258 '__hash__',259 ):260 setattr(enum_class, method, getattr(int, method))261 # replace any other __new__ with our own (as long as Enum is not None,262 # anyway) -- again, this is to support pickle263 if Enum is not None:264 # if the user defined their own __new__, save it before it gets265 # clobbered in case they subclass later266 if save_new:267 setattr(enum_class, '__member_new__', enum_class.__dict__['__new__'])268 setattr(enum_class, '__new__', Enum.__dict__['__new__'])269 return enum_class270 def __bool__(cls):271 """272 classes/types should always be True.273 """274 return True275 def __call__(cls, value, names=None, module=None, type=None, start=1):276 """Either returns an existing member, or creates a new enum class.277 This method is used both when an enum class is given a value to match278 to an enumeration member (i.e. Color(3)) and for the functional API279 (i.e. Color = Enum('Color', names='red green blue')).280 When used for the functional API: `module`, if set, will be stored in281 the new class' __module__ attribute; `type`, if set, will be mixed in282 as the first base class.283 Note: if `module` is not set this routine will attempt to discover the284 calling module by walking the frame stack; if this is unsuccessful285 the resulting class will not be pickleable.286 """287 if names is None: # simple value lookup288 return cls.__new__(cls, value)289 # otherwise, functional API: we're creating a new Enum type290 return cls._create_(value, names, module=module, type=type, start=start)291 def __contains__(cls, member):292 return isinstance(member, cls) and member.name in cls._member_map_293 def __delattr__(cls, attr):294 # nicer error message when someone tries to delete an attribute295 # (see issue19025).296 if attr in cls._member_map_:297 raise AttributeError(298 "%s: cannot delete Enum member." % cls.__name__)299 super(EnumMeta, cls).__delattr__(attr)300 def __dir__(self):301 return (['__class__', '__doc__', '__members__', '__module__'] +302 self._member_names_)303 @property304 def __members__(cls):305 """Returns a mapping of member name->value.306 This mapping lists all enum members, including aliases. Note that this307 is a copy of the internal mapping.308 """309 return cls._member_map_.copy()310 def __getattr__(cls, name):311 """Return the enum member matching `name`312 We use __getattr__ instead of descriptors or inserting into the enum313 class' __dict__ in order to support `name` and `value` being both314 properties for enum members (which live in the class' __dict__) and315 enum members themselves.316 """317 if _is_dunder(name):318 raise AttributeError(name)319 try:320 return cls._member_map_[name]321 except KeyError:322 raise AttributeError(name)323 def __getitem__(cls, name):324 return cls._member_map_[name]325 def __iter__(cls):326 return (cls._member_map_[name] for name in cls._member_names_)327 def __reversed__(cls):328 return (cls._member_map_[name] for name in reversed(cls._member_names_))329 def __len__(cls):330 return len(cls._member_names_)331 __nonzero__ = __bool__332 def __repr__(cls):333 return "<enum %r>" % cls.__name__334 def __setattr__(cls, name, value):335 """Block attempts to reassign Enum members.336 A simple assignment to the class namespace only changes one of the337 several possible ways to get an Enum member from the Enum class,338 resulting in an inconsistent Enumeration.339 """340 member_map = cls.__dict__.get('_member_map_', {})341 if name in member_map:342 raise AttributeError('Cannot reassign members.')343 super(EnumMeta, cls).__setattr__(name, value)344 def _create_(cls, class_name, names=None, module=None, type=None, start=1):345 """Convenience method to create a new Enum class.346 `names` can be:347 * A string containing member names, separated either with spaces or348 commas. Values are auto-numbered from 1.349 * An iterable of member names. Values are auto-numbered from 1.350 * An iterable of (member name, value) pairs.351 * A mapping of member name -> value.352 """353 if pyver < 3.0:354 # if class_name is unicode, attempt a conversion to ASCII355 if isinstance(class_name, unicode):356 try:357 class_name = class_name.encode('ascii')358 except UnicodeEncodeError:359 raise TypeError('%r is not representable in ASCII' % class_name)360 metacls = cls.__class__361 if type is None:362 bases = (cls, )363 else:364 bases = (type, cls)365 classdict = metacls.__prepare__(class_name, bases)366 _order_ = []367 # special processing needed for names?368 if isinstance(names, basestring):369 names = names.replace(',', ' ').split()370 if isinstance(names, (tuple, list)) and isinstance(names[0], basestring):371 names = [(e, i+start) for (i, e) in enumerate(names)]372 # Here, names is either an iterable of (name, value) or a mapping.373 item = None # in case names is empty374 for item in names:375 if isinstance(item, basestring):376 member_name, member_value = item, names[item]377 else:378 member_name, member_value = item379 classdict[member_name] = member_value380 _order_.append(member_name)381 # only set _order_ in classdict if name/value was not from a mapping382 if not isinstance(item, basestring):383 classdict['_order_'] = ' '.join(_order_)384 enum_class = metacls.__new__(metacls, class_name, bases, classdict)385 # TODO: replace the frame hack if a blessed way to know the calling386 # module is ever developed387 if module is None:388 try:389 module = _sys._getframe(2).f_globals['__name__']390 except (AttributeError, ValueError):391 pass392 if module is None:393 _make_class_unpicklable(enum_class)394 else:395 enum_class.__module__ = module396 return enum_class397 @staticmethod398 def _get_mixins_(bases):399 """Returns the type for creating enum members, and the first inherited400 enum class.401 bases: the tuple of bases that was given to __new__402 """403 if not bases or Enum is None:404 return object, Enum405 # double check that we are not subclassing a class with existing406 # enumeration members; while we're at it, see if any other data407 # type has been mixed in so we can use the correct __new__408 member_type = first_enum = None409 for base in bases:410 if (base is not Enum and411 issubclass(base, Enum) and412 base._member_names_):413 raise TypeError("Cannot extend enumerations")414 # base is now the last base in bases415 if not issubclass(base, Enum):416 raise TypeError("new enumerations must be created as "417 "`ClassName([mixin_type,] enum_type)`")418 # get correct mix-in type (either mix-in type of Enum subclass, or419 # first base if last base is Enum)420 if not issubclass(bases[0], Enum):421 member_type = bases[0] # first data type422 first_enum = bases[-1] # enum type423 else:424 for base in bases[0].__mro__:425 # most common: (IntEnum, int, Enum, object)426 # possible: (<Enum 'AutoIntEnum'>, <Enum 'IntEnum'>,427 # <class 'int'>, <Enum 'Enum'>,428 # <class 'object'>)429 if issubclass(base, Enum):430 if first_enum is None:431 first_enum = base432 else:433 if member_type is None:434 member_type = base435 return member_type, first_enum436 if pyver < 3.0:437 @staticmethod438 def _find_new_(classdict, member_type, first_enum):439 """Returns the __new__ to be used for creating the enum members.440 classdict: the class dictionary given to __new__441 member_type: the data type whose __new__ will be used by default442 first_enum: enumeration to check for an overriding __new__443 """444 # now find the correct __new__, checking to see of one was defined445 # by the user; also check earlier enum classes in case a __new__ was446 # saved as __member_new__447 __new__ = classdict.get('__new__', None)448 if __new__:449 return None, True, True # __new__, save_new, use_args450 N__new__ = getattr(None, '__new__')451 O__new__ = getattr(object, '__new__')452 if Enum is None:453 E__new__ = N__new__454 else:455 E__new__ = Enum.__dict__['__new__']456 # check all possibles for __member_new__ before falling back to457 # __new__458 for method in ('__member_new__', '__new__'):459 for possible in (member_type, first_enum):460 try:461 target = possible.__dict__[method]462 except (AttributeError, KeyError):463 target = getattr(possible, method, None)464 if target not in [465 None,466 N__new__,467 O__new__,468 E__new__,469 ]:470 if method == '__member_new__':471 classdict['__new__'] = target472 return None, False, True473 if isinstance(target, staticmethod):474 target = target.__get__(member_type)475 __new__ = target476 break477 if __new__ is not None:478 break479 else:480 __new__ = object.__new__481 # if a non-object.__new__ is used then whatever value/tuple was482 # assigned to the enum member name will be passed to __new__ and to the483 # new enum member's __init__484 if __new__ is object.__new__:485 use_args = False486 else:487 use_args = True488 return __new__, False, use_args489 else:490 @staticmethod491 def _find_new_(classdict, member_type, first_enum):492 """Returns the __new__ to be used for creating the enum members.493 classdict: the class dictionary given to __new__494 member_type: the data type whose __new__ will be used by default495 first_enum: enumeration to check for an overriding __new__496 """497 # now find the correct __new__, checking to see of one was defined498 # by the user; also check earlier enum classes in case a __new__ was499 # saved as __member_new__500 __new__ = classdict.get('__new__', None)501 # should __new__ be saved as __member_new__ later?502 save_new = __new__ is not None503 if __new__ is None:504 # check all possibles for __member_new__ before falling back to505 # __new__506 for method in ('__member_new__', '__new__'):507 for possible in (member_type, first_enum):508 target = getattr(possible, method, None)509 if target not in (510 None,511 None.__new__,512 object.__new__,513 Enum.__new__,514 ):515 __new__ = target516 break517 if __new__ is not None:518 break519 else:520 __new__ = object.__new__521 # if a non-object.__new__ is used then whatever value/tuple was522 # assigned to the enum member name will be passed to __new__ and to the523 # new enum member's __init__524 if __new__ is object.__new__:525 use_args = False526 else:527 use_args = True528 return __new__, save_new, use_args529########################################################530# In order to support Python 2 and 3 with a single531# codebase we have to create the Enum methods separately532# and then use the `type(name, bases, dict)` method to533# create the class.534########################################################535temp_enum_dict = {}536temp_enum_dict['__doc__'] = "Generic enumeration.\n\n Derive from this class to define new enumerations.\n\n"537def __new__(cls, value):538 # all enum instances are actually created during class construction539 # without calling this method; this method is called by the metaclass'540 # __call__ (i.e. Color(3) ), and by pickle541 if type(value) is cls:542 # For lookups like Color(Color.red)543 value = value.value544 #return value545 # by-value search for a matching enum member546 # see if it's in the reverse mapping (for hashable values)547 try:548 if value in cls._value2member_map_:549 return cls._value2member_map_[value]550 except TypeError:551 # not there, now do long search -- O(n) behavior552 for member in cls._member_map_.values():553 if member.value == value:554 return member555 raise ValueError("%s is not a valid %s" % (value, cls.__name__))556temp_enum_dict['__new__'] = __new__557del __new__558def __repr__(self):559 return "<%s.%s: %r>" % (560 self.__class__.__name__, self._name_, self._value_)561temp_enum_dict['__repr__'] = __repr__562del __repr__563def __str__(self):564 return "%s.%s" % (self.__class__.__name__, self._name_)565temp_enum_dict['__str__'] = __str__566del __str__567if pyver >= 3.0:568 def __dir__(self):569 added_behavior = [570 m571 for cls in self.__class__.mro()572 for m in cls.__dict__573 if m[0] != '_' and m not in self._member_map_574 ]575 return (['__class__', '__doc__', '__module__', ] + added_behavior)576 temp_enum_dict['__dir__'] = __dir__577 del __dir__578def __format__(self, format_spec):579 # mixed-in Enums should use the mixed-in type's __format__, otherwise580 # we can get strange results with the Enum name showing up instead of581 # the value582 # pure Enum branch583 if self._member_type_ is object:584 cls = str585 val = str(self)586 # mix-in branch587 else:588 cls = self._member_type_589 val = self.value590 return cls.__format__(val, format_spec)591temp_enum_dict['__format__'] = __format__592del __format__593####################################594# Python's less than 2.6 use __cmp__595if pyver < 2.6:596 def __cmp__(self, other):597 if type(other) is self.__class__:598 if self is other:599 return 0600 return -1601 return NotImplemented602 raise TypeError("unorderable types: %s() and %s()" % (self.__class__.__name__, other.__class__.__name__))603 temp_enum_dict['__cmp__'] = __cmp__604 del __cmp__605else:606 def __le__(self, other):607 raise TypeError("unorderable types: %s() <= %s()" % (self.__class__.__name__, other.__class__.__name__))608 temp_enum_dict['__le__'] = __le__609 del __le__610 def __lt__(self, other):611 raise TypeError("unorderable types: %s() < %s()" % (self.__class__.__name__, other.__class__.__name__))612 temp_enum_dict['__lt__'] = __lt__613 del __lt__614 def __ge__(self, other):615 raise TypeError("unorderable types: %s() >= %s()" % (self.__class__.__name__, other.__class__.__name__))616 temp_enum_dict['__ge__'] = __ge__617 del __ge__618 def __gt__(self, other):619 raise TypeError("unorderable types: %s() > %s()" % (self.__class__.__name__, other.__class__.__name__))620 temp_enum_dict['__gt__'] = __gt__621 del __gt__622def __eq__(self, other):623 if type(other) is self.__class__:624 return self is other625 return NotImplemented626temp_enum_dict['__eq__'] = __eq__627del __eq__628def __ne__(self, other):629 if type(other) is self.__class__:630 return self is not other631 return NotImplemented632temp_enum_dict['__ne__'] = __ne__633del __ne__634def __hash__(self):635 return hash(self._name_)636temp_enum_dict['__hash__'] = __hash__637del __hash__638def __reduce_ex__(self, proto):639 return self.__class__, (self._value_, )640temp_enum_dict['__reduce_ex__'] = __reduce_ex__641del __reduce_ex__642# _RouteClassAttributeToGetattr is used to provide access to the `name`643# and `value` properties of enum members while keeping some measure of644# protection from modification, while still allowing for an enumeration645# to have members named `name` and `value`. This works because enumeration646# members are not set directly on the enum class -- __getattr__ is647# used to look them up.648@_RouteClassAttributeToGetattr649def name(self):650 return self._name_651temp_enum_dict['name'] = name652del name653@_RouteClassAttributeToGetattr654def value(self):655 return self._value_656temp_enum_dict['value'] = value657del value658@classmethod659def _convert(cls, name, module, filter, source=None):660 """661 Create a new Enum subclass that replaces a collection of global constants662 """663 # convert all constants from source (or module) that pass filter() to664 # a new Enum called name, and export the enum and its members back to665 # module;666 # also, replace the __reduce_ex__ method so unpickling works in667 # previous Python versions668 module_globals = vars(_sys.modules[module])669 if source:670 source = vars(source)671 else:672 source = module_globals673 members = dict((name, value) for name, value in source.items() if filter(name))674 cls = cls(name, members, module=module)675 cls.__reduce_ex__ = _reduce_ex_by_name676 module_globals.update(cls.__members__)677 module_globals[name] = cls678 return cls679temp_enum_dict['_convert'] = _convert680del _convert681Enum = EnumMeta('Enum', (object, ), temp_enum_dict)682del temp_enum_dict683# Enum has now been created684###########################685class IntEnum(int, Enum):686 """Enum where members are also (and must be) ints"""687def _reduce_ex_by_name(self, proto):688 return self.name689def unique(enumeration):690 """Class decorator that ensures only unique members exist in an enumeration."""691 duplicates = []692 for name, member in enumeration.__members__.items():693 if name != member.name:694 duplicates.append((name, member.name))695 if duplicates:696 duplicate_names = ', '.join(697 ["%s -> %s" % (alias, name) for (alias, name) in duplicates]698 )699 raise ValueError('duplicate names found in %r: %s' %700 (enumeration, duplicate_names)701 )...

Full Screen

Full Screen

java_cpp_enum_tests.py

Source:java_cpp_enum_tests.py Github

copy

Full Screen

1#!/usr/bin/env python2# Copyright 2014 The Chromium Authors. All rights reserved.3# Use of this source code is governed by a BSD-style license that can be4# found in the LICENSE file.5"""Tests for enum_preprocess.py.6This test suite contains various tests for the C++ -> Java enum generator.7"""8import collections9from datetime import date10import unittest11import java_cpp_enum12from java_cpp_enum import EnumDefinition, GenerateOutput13from java_cpp_enum import HeaderParser14from util import java_cpp_utils15class TestPreprocess(unittest.TestCase):16 def testOutput(self):17 definition = EnumDefinition(original_enum_name='ClassName',18 enum_package='some.package',19 entries=[('E1', 1), ('E2', '2 << 2')],20 comments=[('E2', 'This is a comment.'),21 ('E1', 'This is a multiple line '22 'comment that is really long. '23 'This is a multiple line '24 'comment that is really '25 'really long.')])26 output = GenerateOutput('path/to/file', definition)27 expected = """28// Copyright %d The Chromium Authors. All rights reserved.29// Use of this source code is governed by a BSD-style license that can be30// found in the LICENSE file.31// This file is autogenerated by32// %s33// From34// path/to/file35package some.package;36import androidx.annotation.IntDef;37import java.lang.annotation.Retention;38import java.lang.annotation.RetentionPolicy;39@IntDef({40 ClassName.E1, ClassName.E241})42@Retention(RetentionPolicy.SOURCE)43public @interface ClassName {44 /**45 * %s46 * really really long.47 */48 int E1 = 1;49 /**50 * This is a comment.51 */52 int E2 = 2 << 2;53}54"""55 long_comment = ('This is a multiple line comment that is really long. '56 'This is a multiple line comment that is')57 self.assertEqual(58 expected % (date.today().year, java_cpp_utils.GetScriptName(),59 long_comment), output)60 def testParseSimpleEnum(self):61 test_data = """62 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace63 enum EnumName {64 VALUE_ZERO,65 VALUE_ONE,66 };67 """.split('\n')68 definitions = HeaderParser(test_data).ParseDefinitions()69 self.assertEqual(1, len(definitions))70 definition = definitions[0]71 self.assertEqual('EnumName', definition.class_name)72 self.assertEqual('test.namespace', definition.enum_package)73 self.assertEqual(collections.OrderedDict([('VALUE_ZERO', 0),74 ('VALUE_ONE', 1)]),75 definition.entries)76 def testParseBitShifts(self):77 test_data = """78 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace79 enum EnumName {80 VALUE_ZERO = 1 << 0,81 VALUE_ONE = 1 << 1,82 };83 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace84 enum EnumName {85 ENUM_NAME_ZERO = 1 << 0,86 ENUM_NAME_ONE = 1 << 1,87 ENUM_NAME_TWO = ENUM_NAME_ZERO | ENUM_NAME_ONE,88 };89 """.split('\n')90 definitions = HeaderParser(test_data).ParseDefinitions()91 self.assertEqual(2, len(definitions))92 definition = definitions[0]93 self.assertEqual('EnumName', definition.class_name)94 self.assertEqual('test.namespace', definition.enum_package)95 self.assertEqual(collections.OrderedDict([('VALUE_ZERO', '1 << 0'),96 ('VALUE_ONE', '1 << 1')]),97 definition.entries)98 definition = definitions[1]99 expected_entries = collections.OrderedDict([100 ('ZERO', '1 << 0'),101 ('ONE', '1 << 1'),102 ('TWO', 'ZERO | ONE')])103 self.assertEqual(expected_entries, definition.entries)104 def testParseMultilineEnumEntry(self):105 test_data = """106 // GENERATED_JAVA_ENUM_PACKAGE: bar.namespace107 enum Foo {108 VALUE_ZERO = 1 << 0,109 VALUE_ONE =110 SymbolKey | FnKey | AltGrKey | MetaKey | AltKey | ControlKey,111 VALUE_TWO = 1 << 18,112 };113 """.split('\n')114 expected_entries = collections.OrderedDict([115 ('VALUE_ZERO', '1 << 0'),116 ('VALUE_ONE', 'SymbolKey | FnKey | AltGrKey | MetaKey | AltKey | '117 'ControlKey'),118 ('VALUE_TWO', '1 << 18')])119 definitions = HeaderParser(test_data).ParseDefinitions()120 self.assertEqual(1, len(definitions))121 definition = definitions[0]122 self.assertEqual('Foo', definition.class_name)123 self.assertEqual('bar.namespace', definition.enum_package)124 self.assertEqual(expected_entries, definition.entries)125 def testParseEnumEntryWithTrailingMultilineEntry(self):126 test_data = """127 // GENERATED_JAVA_ENUM_PACKAGE: bar.namespace128 enum Foo {129 VALUE_ZERO = 1,130 VALUE_ONE =131 SymbolKey | FnKey | AltGrKey | MetaKey |132 AltKey | ControlKey | ShiftKey,133 };134 """.split('\n')135 expected_entries = collections.OrderedDict([136 ('VALUE_ZERO', '1'),137 ('VALUE_ONE', 'SymbolKey | FnKey | AltGrKey | MetaKey | AltKey | '138 'ControlKey | ShiftKey')])139 definitions = HeaderParser(test_data).ParseDefinitions()140 self.assertEqual(1, len(definitions))141 definition = definitions[0]142 self.assertEqual('Foo', definition.class_name)143 self.assertEqual('bar.namespace', definition.enum_package)144 self.assertEqual(expected_entries, definition.entries)145 def testParseNoCommaAfterLastEntry(self):146 test_data = """147 // GENERATED_JAVA_ENUM_PACKAGE: bar.namespace148 enum Foo {149 VALUE_ZERO = 1,150 // This is a multiline151 //152 // comment with an empty line.153 VALUE_ONE = 2154 };155 """.split('\n')156 expected_entries = collections.OrderedDict([157 ('VALUE_ZERO', '1'),158 ('VALUE_ONE', '2')])159 expected_comments = collections.OrderedDict([160 ('VALUE_ONE', 'This is a multiline comment with an empty line.')])161 definitions = HeaderParser(test_data).ParseDefinitions()162 self.assertEqual(1, len(definitions))163 definition = definitions[0]164 self.assertEqual('Foo', definition.class_name)165 self.assertEqual('bar.namespace', definition.enum_package)166 self.assertEqual(expected_entries, definition.entries)167 self.assertEqual(expected_comments, definition.comments)168 def testParseClassNameOverride(self):169 test_data = """170 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace171 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OverrideName172 enum EnumName {173 FOO174 };175 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace176 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OtherOverride177 enum PrefixTest {178 PREFIX_TEST_A,179 PREFIX_TEST_B,180 };181 """.split('\n')182 definitions = HeaderParser(test_data).ParseDefinitions()183 self.assertEqual(2, len(definitions))184 definition = definitions[0]185 self.assertEqual('OverrideName', definition.class_name)186 definition = definitions[1]187 self.assertEqual('OtherOverride', definition.class_name)188 self.assertEqual(collections.OrderedDict([('A', 0),189 ('B', 1)]),190 definition.entries)191 def testParsePreservesCommentsWhenPrefixStripping(self):192 test_data = """193 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace194 enum EnumOne {195 ENUM_ONE_A = 1,196 // Comment there197 ENUM_ONE_B = A,198 };199 enum EnumIgnore {200 C, D, E201 };202 // GENERATED_JAVA_ENUM_PACKAGE: other.package203 // GENERATED_JAVA_PREFIX_TO_STRIP: P_204 enum EnumTwo {205 P_A,206 // This comment spans207 // two lines.208 P_B209 };210 """.split('\n')211 definitions = HeaderParser(test_data).ParseDefinitions()212 self.assertEqual(2, len(definitions))213 definition = definitions[0]214 self.assertEqual('EnumOne', definition.class_name)215 self.assertEqual('test.namespace', definition.enum_package)216 self.assertEqual(collections.OrderedDict([('A', '1'),217 ('B', 'A')]),218 definition.entries)219 self.assertEqual(collections.OrderedDict([('B', 'Comment there')]),220 definition.comments)221 definition = definitions[1]222 self.assertEqual('EnumTwo', definition.class_name)223 self.assertEqual('other.package', definition.enum_package)224 self.assertEqual(collections.OrderedDict(225 [('B', 'This comment spans two lines.')]), definition.comments)226 self.assertEqual(collections.OrderedDict([('A', 0),227 ('B', 1)]),228 definition.entries)229 def testParseTwoEnums(self):230 test_data = """231 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace232 enum AnEnum {233 ENUM_ONE_A = 1,234 ENUM_ONE_B = A,235 };236 enum EnumIgnore {237 C, D, E238 };239 // GENERATED_JAVA_ENUM_PACKAGE: other.package240 enum EnumTwo {241 P_A,242 P_B243 };244 """.split('\n')245 definitions = HeaderParser(test_data).ParseDefinitions()246 self.assertEqual(2, len(definitions))247 definition = definitions[0]248 self.assertEqual('AnEnum', definition.class_name)249 self.assertEqual('test.namespace', definition.enum_package)250 self.assertEqual(collections.OrderedDict([('ENUM_ONE_A', '1'),251 ('ENUM_ONE_B', 'A')]),252 definition.entries)253 definition = definitions[1]254 self.assertEqual('EnumTwo', definition.class_name)255 self.assertEqual('other.package', definition.enum_package)256 self.assertEqual(collections.OrderedDict([('P_A', 0),257 ('P_B', 1)]),258 definition.entries)259 def testParseSingleLineEnum(self):260 test_data = """261 // GENERATED_JAVA_ENUM_PACKAGE: other.package262 // GENERATED_JAVA_PREFIX_TO_STRIP: P_263 enum EnumTwo { P_A, P_B };264 """.split('\n')265 definitions = HeaderParser(test_data).ParseDefinitions()266 definition = definitions[0]267 self.assertEqual('EnumTwo', definition.class_name)268 self.assertEqual('other.package', definition.enum_package)269 self.assertEqual(collections.OrderedDict([('A', 0),270 ('B', 1)]),271 definition.entries)272 def testParseWithStrippingAndRelativeReferences(self):273 test_data = """274 // GENERATED_JAVA_ENUM_PACKAGE: other.package275 // GENERATED_JAVA_PREFIX_TO_STRIP: P_276 enum EnumTwo {277 P_A = 1,278 // P_A is old-don't use P_A.279 P_B = P_A,280 };281 """.split('\n')282 definitions = HeaderParser(test_data).ParseDefinitions()283 definition = definitions[0]284 self.assertEqual('EnumTwo', definition.class_name)285 self.assertEqual('other.package', definition.enum_package)286 self.assertEqual(collections.OrderedDict([('A', '1'),287 ('B', 'A')]),288 definition.entries)289 self.assertEqual(collections.OrderedDict([('B', 'A is old-don\'t use A.')]),290 definition.comments)291 def testParseSingleLineAndRegularEnum(self):292 test_data = """293 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace294 enum EnumOne {295 ENUM_ONE_A = 1,296 // Comment there297 ENUM_ONE_B = A,298 };299 // GENERATED_JAVA_ENUM_PACKAGE: other.package300 enum EnumTwo { P_A, P_B };301 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace302 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OverrideName303 enum EnumName {304 ENUM_NAME_FOO305 };306 """.split('\n')307 definitions = HeaderParser(test_data).ParseDefinitions()308 definition = definitions[0]309 self.assertEqual(310 collections.OrderedDict([('A', '1'), ('B', 'A')]), definition.entries)311 self.assertEqual(collections.OrderedDict([('B', 'Comment there')]),312 definition.comments)313 self.assertEqual(3, len(definitions))314 definition = definitions[1]315 self.assertEqual(316 collections.OrderedDict([('P_A', 0), ('P_B', 1)]), definition.entries)317 definition = definitions[2]318 self.assertEqual(collections.OrderedDict([('FOO', 0)]), definition.entries)319 def testParseWithCamelCaseNames(self):320 test_data = """321 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace322 enum EnumTest {323 EnumTestA = 1,324 // comment for EnumTestB.325 EnumTestB = 2,326 };327 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace328 // GENERATED_JAVA_PREFIX_TO_STRIP: Test329 enum AnEnum {330 TestHTTPOption,331 TestHTTPSOption,332 };333 """.split('\n')334 definitions = HeaderParser(test_data).ParseDefinitions()335 definition = definitions[0]336 self.assertEqual(337 collections.OrderedDict([('A', '1'), ('B', '2')]),338 definition.entries)339 self.assertEqual(340 collections.OrderedDict([('B', 'comment for B.')]),341 definition.comments)342 definition = definitions[1]343 self.assertEqual(344 collections.OrderedDict([('HTTP_OPTION', 0), ('HTTPS_OPTION', 1)]),345 definition.entries)346 def testParseWithKCamelCaseNames(self):347 test_data = """348 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace349 enum EnumOne {350 kEnumOne = 1,351 // comment for kEnumTwo.352 kEnumTwo = 2,353 };354 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace355 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: OverrideName356 enum EnumName {357 kEnumNameFoo,358 kEnumNameBar359 };360 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace361 enum EnumName {362 kEnumNameFoo,363 kEnumBar,364 };365 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace366 enum Keys {367 kSymbolKey = 1 << 0,368 kAltKey = 1 << 1,369 kUpKey = 1 << 2,370 kKeyModifiers = kSymbolKey | kAltKey | kUpKey | kKeyModifiers,371 };372 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace373 enum Mixed {374 kTestVal,375 kCodecMPEG2376 };377 """.split('\n')378 definitions = HeaderParser(test_data).ParseDefinitions()379 definition = definitions[0]380 self.assertEqual(381 collections.OrderedDict([('ENUM_ONE', '1'), ('ENUM_TWO', '2')]),382 definition.entries)383 self.assertEqual(384 collections.OrderedDict([('ENUM_TWO', 'comment for ENUM_TWO.')]),385 definition.comments)386 definition = definitions[1]387 self.assertEqual(388 collections.OrderedDict([('FOO', 0), ('BAR', 1)]),389 definition.entries)390 definition = definitions[2]391 self.assertEqual(392 collections.OrderedDict([('ENUM_NAME_FOO', 0), ('ENUM_BAR', 1)]),393 definition.entries)394 definition = definitions[3]395 expected_entries = collections.OrderedDict([396 ('SYMBOL_KEY', '1 << 0'),397 ('ALT_KEY', '1 << 1'),398 ('UP_KEY', '1 << 2'),399 ('KEY_MODIFIERS', 'SYMBOL_KEY | ALT_KEY | UP_KEY | KEY_MODIFIERS')])400 self.assertEqual(expected_entries, definition.entries)401 definition = definitions[4]402 self.assertEqual(403 collections.OrderedDict([('TEST_VAL', 0), ('CODEC_MPEG2', 1)]),404 definition.entries)405 def testParseThrowsOnUnknownDirective(self):406 test_data = """407 // GENERATED_JAVA_UNKNOWN: Value408 enum EnumName {409 VALUE_ONE,410 };411 """.split('\n')412 with self.assertRaises(Exception):413 HeaderParser(test_data).ParseDefinitions()414 def testParseReturnsEmptyListWithoutDirectives(self):415 test_data = """416 enum EnumName {417 VALUE_ONE,418 };419 """.split('\n')420 self.assertEqual([], HeaderParser(test_data).ParseDefinitions())421 def testParseEnumClass(self):422 test_data = """423 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace424 enum class Foo {425 FOO_A,426 };427 """.split('\n')428 definitions = HeaderParser(test_data).ParseDefinitions()429 self.assertEqual(1, len(definitions))430 definition = definitions[0]431 self.assertEqual('Foo', definition.class_name)432 self.assertEqual('test.namespace', definition.enum_package)433 self.assertEqual(collections.OrderedDict([('A', 0)]),434 definition.entries)435 def testParseEnumClassOneValueSubstringOfAnother(self):436 test_data = """437 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace438 enum class SafeBrowsingStatus {439 kChecking = 0,440 kEnabled = 1,441 kDisabled = 2,442 kDisabledByAdmin = 3,443 kDisabledByExtension = 4,444 kEnabledStandard = 5,445 kEnabledEnhanced = 6,446 // New enum values must go above here.447 kMaxValue = kEnabledEnhanced,448 };449 """.split('\n')450 definitions = HeaderParser(test_data).ParseDefinitions()451 self.assertEqual(1, len(definitions))452 definition = definitions[0]453 self.assertEqual('SafeBrowsingStatus', definition.class_name)454 self.assertEqual('test.namespace', definition.enum_package)455 self.assertEqual(456 collections.OrderedDict([457 ('CHECKING', '0'),458 ('ENABLED', '1'),459 ('DISABLED', '2'),460 ('DISABLED_BY_ADMIN', '3'),461 ('DISABLED_BY_EXTENSION', '4'),462 ('ENABLED_STANDARD', '5'),463 ('ENABLED_ENHANCED', '6'),464 ('MAX_VALUE', 'ENABLED_ENHANCED'),465 ]), definition.entries)466 self.assertEqual(467 collections.OrderedDict([468 ('MAX_VALUE', 'New enum values must go above here.')469 ]), definition.comments)470 def testParseEnumStruct(self):471 test_data = """472 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace473 enum struct Foo {474 FOO_A,475 };476 """.split('\n')477 definitions = HeaderParser(test_data).ParseDefinitions()478 self.assertEqual(1, len(definitions))479 definition = definitions[0]480 self.assertEqual('Foo', definition.class_name)481 self.assertEqual('test.namespace', definition.enum_package)482 self.assertEqual(collections.OrderedDict([('A', 0)]),483 definition.entries)484 def testParseFixedTypeEnum(self):485 test_data = """486 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace487 enum Foo : int {488 FOO_A,489 };490 """.split('\n')491 definitions = HeaderParser(test_data).ParseDefinitions()492 self.assertEqual(1, len(definitions))493 definition = definitions[0]494 self.assertEqual('Foo', definition.class_name)495 self.assertEqual('test.namespace', definition.enum_package)496 self.assertEqual('int', definition.fixed_type)497 self.assertEqual(collections.OrderedDict([('A', 0)]),498 definition.entries)499 def testParseFixedTypeEnumClass(self):500 test_data = """501 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace502 enum class Foo: unsigned short {503 FOO_A,504 };505 """.split('\n')506 definitions = HeaderParser(test_data).ParseDefinitions()507 self.assertEqual(1, len(definitions))508 definition = definitions[0]509 self.assertEqual('Foo', definition.class_name)510 self.assertEqual('test.namespace', definition.enum_package)511 self.assertEqual('unsigned short', definition.fixed_type)512 self.assertEqual(collections.OrderedDict([('A', 0)]),513 definition.entries)514 def testParseUnknownFixedTypeRaises(self):515 test_data = """516 // GENERATED_JAVA_ENUM_PACKAGE: test.namespace517 enum class Foo: foo_type {518 FOO_A,519 };520 """.split('\n')521 with self.assertRaises(Exception):522 HeaderParser(test_data).ParseDefinitions()523 def testParseSimpleMultiLineDirective(self):524 test_data = """525 // GENERATED_JAVA_ENUM_PACKAGE: (526 // test.namespace)527 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: Bar528 enum Foo {529 FOO_A,530 };531 """.split('\n')532 definitions = HeaderParser(test_data).ParseDefinitions()533 self.assertEqual('test.namespace', definitions[0].enum_package)534 self.assertEqual('Bar', definitions[0].class_name)535 def testParseMultiLineDirective(self):536 test_data = """537 // GENERATED_JAVA_ENUM_PACKAGE: (te538 // st.name539 // space)540 enum Foo {541 FOO_A,542 };543 """.split('\n')544 definitions = HeaderParser(test_data).ParseDefinitions()545 self.assertEqual('test.namespace', definitions[0].enum_package)546 def testParseMultiLineDirectiveWithOtherDirective(self):547 test_data = """548 // GENERATED_JAVA_ENUM_PACKAGE: (549 // test.namespace)550 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: (551 // Ba552 // r553 // )554 enum Foo {555 FOO_A,556 };557 """.split('\n')558 definitions = HeaderParser(test_data).ParseDefinitions()559 self.assertEqual('test.namespace', definitions[0].enum_package)560 self.assertEqual('Bar', definitions[0].class_name)561 def testParseMalformedMultiLineDirectiveWithOtherDirective(self):562 test_data = """563 // GENERATED_JAVA_ENUM_PACKAGE: (564 // test.name565 // space566 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: Bar567 enum Foo {568 FOO_A,569 };570 """.split('\n')571 with self.assertRaises(Exception):572 HeaderParser(test_data).ParseDefinitions()573 def testParseMalformedMultiLineDirective(self):574 test_data = """575 // GENERATED_JAVA_ENUM_PACKAGE: (576 // test.name577 // space578 enum Foo {579 FOO_A,580 };581 """.split('\n')582 with self.assertRaises(Exception):583 HeaderParser(test_data).ParseDefinitions()584 def testParseMalformedMultiLineDirectiveShort(self):585 test_data = """586 // GENERATED_JAVA_ENUM_PACKAGE: (587 enum Foo {588 FOO_A,589 };590 """.split('\n')591 with self.assertRaises(Exception):592 HeaderParser(test_data).ParseDefinitions()593 def testParseMalformedMultiLineDirectiveMissingBrackets(self):594 test_data = """595 // GENERATED_JAVA_ENUM_PACKAGE:596 // test.namespace597 enum Foo {598 FOO_A,599 };600 """.split('\n')601 with self.assertRaises(Exception):602 HeaderParser(test_data).ParseDefinitions()603 def testEnumValueAssignmentNoneDefined(self):604 definition = EnumDefinition(original_enum_name='c', enum_package='p')605 definition.AppendEntry('A', None)606 definition.AppendEntry('B', None)607 definition.AppendEntry('C', None)608 definition.Finalize()609 self.assertEqual(collections.OrderedDict([('A', 0),610 ('B', 1),611 ('C', 2)]),612 definition.entries)613 def testEnumValueAssignmentAllDefined(self):614 definition = EnumDefinition(original_enum_name='c', enum_package='p')615 definition.AppendEntry('A', '1')616 definition.AppendEntry('B', '2')617 definition.AppendEntry('C', '3')618 definition.Finalize()619 self.assertEqual(collections.OrderedDict([('A', '1'),620 ('B', '2'),621 ('C', '3')]),622 definition.entries)623 def testEnumValueAssignmentReferences(self):624 definition = EnumDefinition(original_enum_name='c', enum_package='p')625 definition.AppendEntry('A', None)626 definition.AppendEntry('B', 'A')627 definition.AppendEntry('C', None)628 definition.AppendEntry('D', 'C')629 definition.Finalize()630 self.assertEqual(collections.OrderedDict([('A', 0),631 ('B', 0),632 ('C', 1),633 ('D', 1)]),634 definition.entries)635 def testEnumValueAssignmentSet(self):636 definition = EnumDefinition(original_enum_name='c', enum_package='p')637 definition.AppendEntry('A', None)638 definition.AppendEntry('B', '2')639 definition.AppendEntry('C', None)640 definition.Finalize()641 self.assertEqual(collections.OrderedDict([('A', 0),642 ('B', 2),643 ('C', 3)]),644 definition.entries)645 def testEnumValueAssignmentSetReferences(self):646 definition = EnumDefinition(original_enum_name='c', enum_package='p')647 definition.AppendEntry('A', None)648 definition.AppendEntry('B', 'A')649 definition.AppendEntry('C', 'B')650 definition.AppendEntry('D', None)651 definition.Finalize()652 self.assertEqual(collections.OrderedDict([('A', 0),653 ('B', 0),654 ('C', 0),655 ('D', 1)]),656 definition.entries)657 def testEnumValueAssignmentRaises(self):658 definition = EnumDefinition(original_enum_name='c', enum_package='p')659 definition.AppendEntry('A', None)660 definition.AppendEntry('B', 'foo')661 definition.AppendEntry('C', None)662 with self.assertRaises(Exception):663 definition.Finalize()664 def testExplicitPrefixStripping(self):665 definition = EnumDefinition(original_enum_name='c', enum_package='p')666 definition.AppendEntry('P_A', None)667 definition.AppendEntry('B', None)668 definition.AppendEntry('P_C', None)669 definition.AppendEntry('P_LAST', 'P_C')670 definition.prefix_to_strip = 'P_'671 definition.Finalize()672 self.assertEqual(collections.OrderedDict([('A', 0),673 ('B', 1),674 ('C', 2),675 ('LAST', 2)]),676 definition.entries)677 def testImplicitPrefixStripping(self):678 definition = EnumDefinition(original_enum_name='ClassName',679 enum_package='p')680 definition.AppendEntry('CLASS_NAME_A', None)681 definition.AppendEntry('CLASS_NAME_B', None)682 definition.AppendEntry('CLASS_NAME_C', None)683 definition.AppendEntry('CLASS_NAME_LAST', 'CLASS_NAME_C')684 definition.Finalize()685 self.assertEqual(collections.OrderedDict([('A', 0),686 ('B', 1),687 ('C', 2),688 ('LAST', 2)]),689 definition.entries)690 def testImplicitPrefixStrippingRequiresAllConstantsToBePrefixed(self):691 definition = EnumDefinition(original_enum_name='Name',692 enum_package='p')693 definition.AppendEntry('A', None)694 definition.AppendEntry('B', None)695 definition.AppendEntry('NAME_LAST', None)696 definition.Finalize()697 self.assertEqual(['A', 'B', 'NAME_LAST'], list(definition.entries.keys()))698 def testGenerateThrowsOnEmptyInput(self):699 with self.assertRaises(Exception):700 original_do_parse = java_cpp_enum.DoParseHeaderFile701 try:702 java_cpp_enum.DoParseHeaderFile = lambda _: []703 for _ in java_cpp_enum.DoGenerate(['file']):704 pass705 finally:706 java_cpp_enum.DoParseHeaderFile = original_do_parse707if __name__ == '__main__':...

Full Screen

Full Screen

java_cpp_enum.py

Source:java_cpp_enum.py Github

copy

Full Screen

1#!/usr/bin/env python2#3# Copyright 2014 The Chromium Authors. All rights reserved.4# Use of this source code is governed by a BSD-style license that can be5# found in the LICENSE file.6import collections7from datetime import date8import re9import optparse10import os11from string import Template12import sys13import textwrap14import zipfile15from util import build_utils16from util import java_cpp_utils17# List of C++ types that are compatible with the Java code generated by this18# script.19#20# This script can parse .idl files however, at present it ignores special21# rules such as [cpp_enum_prefix_override="ax_attr"].22ENUM_FIXED_TYPE_ALLOWLIST = [23 'char', 'unsigned char', 'short', 'unsigned short', 'int', 'int8_t',24 'int16_t', 'int32_t', 'uint8_t', 'uint16_t'25]26class EnumDefinition(object):27 def __init__(self, original_enum_name=None, class_name_override=None,28 enum_package=None, entries=None, comments=None, fixed_type=None):29 self.original_enum_name = original_enum_name30 self.class_name_override = class_name_override31 self.enum_package = enum_package32 self.entries = collections.OrderedDict(entries or [])33 self.comments = collections.OrderedDict(comments or [])34 self.prefix_to_strip = None35 self.fixed_type = fixed_type36 def AppendEntry(self, key, value):37 if key in self.entries:38 raise Exception('Multiple definitions of key %s found.' % key)39 self.entries[key] = value40 def AppendEntryComment(self, key, value):41 if key in self.comments:42 raise Exception('Multiple definitions of key %s found.' % key)43 self.comments[key] = value44 @property45 def class_name(self):46 return self.class_name_override or self.original_enum_name47 def Finalize(self):48 self._Validate()49 self._AssignEntryIndices()50 self._StripPrefix()51 self._NormalizeNames()52 def _Validate(self):53 assert self.class_name54 assert self.enum_package55 assert self.entries56 if self.fixed_type and self.fixed_type not in ENUM_FIXED_TYPE_ALLOWLIST:57 raise Exception('Fixed type %s for enum %s not in allowlist.' %58 (self.fixed_type, self.class_name))59 def _AssignEntryIndices(self):60 # Enums, if given no value, are given the value of the previous enum + 1.61 if not all(self.entries.values()):62 prev_enum_value = -163 for key, value in self.entries.items():64 if not value:65 self.entries[key] = prev_enum_value + 166 elif value in self.entries:67 self.entries[key] = self.entries[value]68 else:69 try:70 self.entries[key] = int(value)71 except ValueError:72 raise Exception('Could not interpret integer from enum value "%s" '73 'for key %s.' % (value, key))74 prev_enum_value = self.entries[key]75 def _StripPrefix(self):76 prefix_to_strip = self.prefix_to_strip77 if not prefix_to_strip:78 shout_case = self.original_enum_name79 shout_case = re.sub('(?!^)([A-Z]+)', r'_\1', shout_case).upper()80 shout_case += '_'81 prefixes = [shout_case, self.original_enum_name,82 'k' + self.original_enum_name]83 for prefix in prefixes:84 if all([w.startswith(prefix) for w in self.entries.keys()]):85 prefix_to_strip = prefix86 break87 else:88 prefix_to_strip = ''89 def StripEntries(entries):90 ret = collections.OrderedDict()91 for k, v in entries.items():92 stripped_key = k.replace(prefix_to_strip, '', 1)93 if isinstance(v, str):94 stripped_value = v.replace(prefix_to_strip, '')95 else:96 stripped_value = v97 ret[stripped_key] = stripped_value98 return ret99 self.entries = StripEntries(self.entries)100 self.comments = StripEntries(self.comments)101 def _NormalizeNames(self):102 self.entries = _TransformKeys(self.entries, java_cpp_utils.KCamelToShouty)103 self.comments = _TransformKeys(self.comments, java_cpp_utils.KCamelToShouty)104def _TransformKeys(d, func):105 """Normalize keys in |d| and update references to old keys in |d| values."""106 keys_map = {k: func(k) for k in d}107 ret = collections.OrderedDict()108 for k, v in d.items():109 # Need to transform values as well when the entry value was explicitly set110 # (since it could contain references to other enum entry values).111 if isinstance(v, str):112 # First check if a full replacement is available. This avoids issues when113 # one key is a substring of another.114 if v in d:115 v = keys_map[v]116 else:117 for old_key, new_key in keys_map.items():118 v = v.replace(old_key, new_key)119 ret[keys_map[k]] = v120 return ret121class DirectiveSet(object):122 class_name_override_key = 'CLASS_NAME_OVERRIDE'123 enum_package_key = 'ENUM_PACKAGE'124 prefix_to_strip_key = 'PREFIX_TO_STRIP'125 known_keys = [class_name_override_key, enum_package_key, prefix_to_strip_key]126 def __init__(self):127 self._directives = {}128 def Update(self, key, value):129 if key not in DirectiveSet.known_keys:130 raise Exception("Unknown directive: " + key)131 self._directives[key] = value132 @property133 def empty(self):134 return len(self._directives) == 0135 def UpdateDefinition(self, definition):136 definition.class_name_override = self._directives.get(137 DirectiveSet.class_name_override_key, '')138 definition.enum_package = self._directives.get(139 DirectiveSet.enum_package_key)140 definition.prefix_to_strip = self._directives.get(141 DirectiveSet.prefix_to_strip_key)142class HeaderParser(object):143 single_line_comment_re = re.compile(r'\s*//\s*([^\n]*)')144 multi_line_comment_start_re = re.compile(r'\s*/\*')145 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?')146 enum_end_re = re.compile(r'^\s*}\s*;\.*$')147 generator_error_re = re.compile(r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*$')148 generator_directive_re = re.compile(149 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$')150 multi_line_generator_directive_start_re = re.compile(151 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*\(([\.\w]*)$')152 multi_line_directive_continuation_re = re.compile(r'^\s*//\s+([\.\w]+)$')153 multi_line_directive_end_re = re.compile(r'^\s*//\s+([\.\w]*)\)$')154 optional_class_or_struct_re = r'(class|struct)?'155 enum_name_re = r'(\w+)'156 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?'157 enum_start_re = re.compile(r'^\s*(?:\[cpp.*\])?\s*enum\s+' +158 optional_class_or_struct_re + '\s*' + enum_name_re + '\s*' +159 optional_fixed_type_re + '\s*{\s*')160 enum_single_line_re = re.compile(161 r'^\s*(?:\[cpp.*\])?\s*enum.*{(?P<enum_entries>.*)}.*$')162 def __init__(self, lines, path=''):163 self._lines = lines164 self._path = path165 self._enum_definitions = []166 self._in_enum = False167 self._current_definition = None168 self._current_comments = []169 self._generator_directives = DirectiveSet()170 self._multi_line_generator_directive = None171 self._current_enum_entry = ''172 def _ApplyGeneratorDirectives(self):173 self._generator_directives.UpdateDefinition(self._current_definition)174 self._generator_directives = DirectiveSet()175 def ParseDefinitions(self):176 for line in self._lines:177 self._ParseLine(line)178 return self._enum_definitions179 def _ParseLine(self, line):180 if self._multi_line_generator_directive:181 self._ParseMultiLineDirectiveLine(line)182 elif not self._in_enum:183 self._ParseRegularLine(line)184 else:185 self._ParseEnumLine(line)186 def _ParseEnumLine(self, line):187 if HeaderParser.multi_line_comment_start_re.match(line):188 raise Exception('Multi-line comments in enums are not supported in ' +189 self._path)190 enum_comment = HeaderParser.single_line_comment_re.match(line)191 if enum_comment:192 comment = enum_comment.groups()[0]193 if comment:194 self._current_comments.append(comment)195 elif HeaderParser.enum_end_re.match(line):196 self._FinalizeCurrentEnumDefinition()197 else:198 self._AddToCurrentEnumEntry(line)199 if ',' in line:200 self._ParseCurrentEnumEntry()201 def _ParseSingleLineEnum(self, line):202 for entry in line.split(','):203 self._AddToCurrentEnumEntry(entry)204 self._ParseCurrentEnumEntry()205 self._FinalizeCurrentEnumDefinition()206 def _ParseCurrentEnumEntry(self):207 if not self._current_enum_entry:208 return209 enum_entry = HeaderParser.enum_line_re.match(self._current_enum_entry)210 if not enum_entry:211 raise Exception('Unexpected error while attempting to parse %s as enum '212 'entry.' % self._current_enum_entry)213 enum_key = enum_entry.groups()[0]214 enum_value = enum_entry.groups()[2]215 self._current_definition.AppendEntry(enum_key, enum_value)216 if self._current_comments:217 self._current_definition.AppendEntryComment(218 enum_key, ' '.join(self._current_comments))219 self._current_comments = []220 self._current_enum_entry = ''221 def _AddToCurrentEnumEntry(self, line):222 self._current_enum_entry += ' ' + line.strip()223 def _FinalizeCurrentEnumDefinition(self):224 if self._current_enum_entry:225 self._ParseCurrentEnumEntry()226 self._ApplyGeneratorDirectives()227 self._current_definition.Finalize()228 self._enum_definitions.append(self._current_definition)229 self._current_definition = None230 self._in_enum = False231 def _ParseMultiLineDirectiveLine(self, line):232 multi_line_directive_continuation = (233 HeaderParser.multi_line_directive_continuation_re.match(line))234 multi_line_directive_end = (235 HeaderParser.multi_line_directive_end_re.match(line))236 if multi_line_directive_continuation:237 value_cont = multi_line_directive_continuation.groups()[0]238 self._multi_line_generator_directive[1].append(value_cont)239 elif multi_line_directive_end:240 directive_name = self._multi_line_generator_directive[0]241 directive_value = "".join(self._multi_line_generator_directive[1])242 directive_value += multi_line_directive_end.groups()[0]243 self._multi_line_generator_directive = None244 self._generator_directives.Update(directive_name, directive_value)245 else:246 raise Exception('Malformed multi-line directive declaration in ' +247 self._path)248 def _ParseRegularLine(self, line):249 enum_start = HeaderParser.enum_start_re.match(line)250 generator_directive_error = HeaderParser.generator_error_re.match(line)251 generator_directive = HeaderParser.generator_directive_re.match(line)252 multi_line_generator_directive_start = (253 HeaderParser.multi_line_generator_directive_start_re.match(line))254 single_line_enum = HeaderParser.enum_single_line_re.match(line)255 if generator_directive_error:256 raise Exception('Malformed directive declaration in ' + self._path +257 '. Use () for multi-line directives. E.g.\n' +258 '// GENERATED_JAVA_ENUM_PACKAGE: (\n' +259 '// foo.package)')260 elif generator_directive:261 directive_name = generator_directive.groups()[0]262 directive_value = generator_directive.groups()[1]263 self._generator_directives.Update(directive_name, directive_value)264 elif multi_line_generator_directive_start:265 directive_name = multi_line_generator_directive_start.groups()[0]266 directive_value = multi_line_generator_directive_start.groups()[1]267 self._multi_line_generator_directive = (directive_name, [directive_value])268 elif enum_start or single_line_enum:269 if self._generator_directives.empty:270 return271 self._current_definition = EnumDefinition(272 original_enum_name=enum_start.groups()[1],273 fixed_type=enum_start.groups()[3])274 self._in_enum = True275 if single_line_enum:276 self._ParseSingleLineEnum(single_line_enum.group('enum_entries'))277def DoGenerate(source_paths):278 for source_path in source_paths:279 enum_definitions = DoParseHeaderFile(source_path)280 if not enum_definitions:281 raise Exception('No enums found in %s\n'282 'Did you forget prefixing enums with '283 '"// GENERATED_JAVA_ENUM_PACKAGE: foo"?' %284 source_path)285 for enum_definition in enum_definitions:286 output_path = java_cpp_utils.GetJavaFilePath(enum_definition.enum_package,287 enum_definition.class_name)288 output = GenerateOutput(source_path, enum_definition)289 yield output_path, output290def DoParseHeaderFile(path):291 with open(path) as f:292 return HeaderParser(f.readlines(), path).ParseDefinitions()293def GenerateOutput(source_path, enum_definition):294 template = Template("""295// Copyright ${YEAR} The Chromium Authors. All rights reserved.296// Use of this source code is governed by a BSD-style license that can be297// found in the LICENSE file.298// This file is autogenerated by299// ${SCRIPT_NAME}300// From301// ${SOURCE_PATH}302package ${PACKAGE};303import androidx.annotation.IntDef;304import java.lang.annotation.Retention;305import java.lang.annotation.RetentionPolicy;306@IntDef({307${INT_DEF}308})309@Retention(RetentionPolicy.SOURCE)310public @interface ${CLASS_NAME} {311${ENUM_ENTRIES}312}313""")314 enum_template = Template(' int ${NAME} = ${VALUE};')315 enum_entries_string = []316 enum_names = []317 for enum_name, enum_value in enum_definition.entries.items():318 values = {319 'NAME': enum_name,320 'VALUE': enum_value,321 }322 enum_comments = enum_definition.comments.get(enum_name)323 if enum_comments:324 enum_comments_indent = ' * '325 comments_line_wrapper = textwrap.TextWrapper(326 initial_indent=enum_comments_indent,327 subsequent_indent=enum_comments_indent,328 width=100)329 enum_entries_string.append(' /**')330 enum_entries_string.append('\n'.join(331 comments_line_wrapper.wrap(enum_comments)))332 enum_entries_string.append(' */')333 enum_entries_string.append(enum_template.substitute(values))334 if enum_name != "NUM_ENTRIES":335 enum_names.append(enum_definition.class_name + '.' + enum_name)336 enum_entries_string = '\n'.join(enum_entries_string)337 enum_names_indent = ' ' * 4338 wrapper = textwrap.TextWrapper(initial_indent = enum_names_indent,339 subsequent_indent = enum_names_indent,340 width = 100)341 enum_names_string = '\n'.join(wrapper.wrap(', '.join(enum_names)))342 values = {343 'CLASS_NAME': enum_definition.class_name,344 'ENUM_ENTRIES': enum_entries_string,345 'PACKAGE': enum_definition.enum_package,346 'INT_DEF': enum_names_string,347 'SCRIPT_NAME': java_cpp_utils.GetScriptName(),348 'SOURCE_PATH': source_path,349 'YEAR': str(date.today().year)350 }351 return template.substitute(values)352def DoMain(argv):353 usage = 'usage: %prog [options] [output_dir] input_file(s)...'354 parser = optparse.OptionParser(usage=usage)355 parser.add_option('--srcjar',356 help='When specified, a .srcjar at the given path is '357 'created instead of individual .java files.')358 options, args = parser.parse_args(argv)359 if not args:360 parser.error('Need to specify at least one input file')361 input_paths = args362 with build_utils.AtomicOutput(options.srcjar) as f:363 with zipfile.ZipFile(f, 'w', zipfile.ZIP_STORED) as srcjar:364 for output_path, data in DoGenerate(input_paths):365 build_utils.AddToZipHermetic(srcjar, output_path, data=data)366if __name__ == '__main__':...

Full Screen

Full Screen

parser.py

Source:parser.py Github

copy

Full Screen

1#!/usr/bin/env python32#3# Copyright (C) 2017 The Android Open Source Project4#5# Licensed under the Apache License, Version 2.0 (the "License");6# you may not use this file except in compliance with the License.7# You may obtain a copy of the License at8#9# http://www.apache.org/licenses/LICENSE-2.010#11# Unless required by applicable law or agreed to in writing, software12# distributed under the License is distributed on an "AS IS" BASIS,13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.14# See the License for the specific language governing permissions and15# limitations under the License.16#17# A parser for enum types defined in HIDL.18# This script can parse HIDL files and generate a parse tree.19# To use, import and call parse("path/to/file.hal")20# It will return a Python dictionary with three keys:21# - header: an instance of Header22# - enums: a dictionary of EnumDecl objects by name23# - structs: a dictionary of StructDecl objects by name24# It requires 'ply' (Python Lex/Yacc).25from __future__ import print_function26import ply27tokens = ('package', 'import', 'enum', 'struct',28 'COLON', 'IDENTIFIER', 'COMMENT', 'NUMBER', 'HEX', 'OR', 'EQUALS',29 'LPAREN', 'RPAREN', 'LBRACE', 'RBRACE', 'DOT', 'SEMICOLON', 'VERSION',30 'COMMA', 'SHIFT', 'LESSTHAN', 'GREATERTHAN')31t_COLON = r':'32t_NUMBER = r'[0-9]+'33t_HEX = r'0x[0-9A-Fa-f]+'34t_OR = r'\|'35t_EQUALS = r'='36t_LPAREN = r'\('37t_RPAREN = r'\)'38t_SHIFT = r'<<'39t_LESSTHAN = r'<'40t_GREATERTHAN = r'>'41def t_COMMENT(t):42 r'(/\*(.|\n)*?\*/)|(//.*)'43 pass44t_LBRACE = r'{'45t_RBRACE = r'}'46t_DOT = r'\.'47t_SEMICOLON = r';'48t_VERSION = r'@[0-9].[0-9]'49t_COMMA = r','50t_ignore = ' \n\t'51def t_IDENTIFIER(t):52 r'[a-zA-Z_][a-zA-Z_0-9]*'53 if t.value == 'package':54 t.type = 'package'55 elif t.value == 'import':56 t.type = 'import'57 elif t.value == 'enum':58 t.type = 'enum'59 elif t.value == 'struct':60 t.type = 'struct'61 return t62def t_error(t):63 t.type = t.value[0]64 t.value = t.value[0]65 t.lexer.skip(1)66 return t67import ply.lex as lex68lexer = lex.lex()69class Typename(object):70 pass71class SimpleTypename(Typename):72 def __init__(self, name):73 self.name = name74 def __str__(self):75 return self.name76class GenericTypename(Typename):77 def __init__(self, name, arg):78 self.name = name79 self.arg = arg80 def __str__(self):81 return '%s<%s>' % (self.name, self.arg)82class EnumHeader(object):83 def __init__(self, name, base):84 self.name = name85 self.base = base86 def __str__(self):87 return '%s%s' % (self.name, ' %s' % self.base if self.base else '')88class StructHeader(object):89 def __init__(self, name):90 self.name = name91 def __str__(self):92 return 'struct %s' % self.name93class EnumDecl(object):94 def __init__(self, header, cases):95 self.header = header96 self.cases = cases97 self.fillInValues()98 def fillInValues(self):99 # if no cases, we're done100 if len(self.cases) < 1: return101 # then, if case 0 has no value, set it to 0102 if self.cases[0].value is None:103 self.cases[0].value = EnumValueConstant("0")104 # then for all other cases...105 for i in range(1,len(self.cases)):106 # ...if there's no value107 if self.cases[i].value is None:108 # set to previous case + 1109 self.cases[i].value = EnumValueSuccessor(110 EnumValueLocalRef(self.cases[i-1].name))111 def __str__(self):112 return '%s {\n%s\n}' % (self.header,113 '\n'.join(str(x) for x in self.cases))114 def __repr__(self):115 return self.__str__()116class StructDecl(object):117 def __init__(self, header, items):118 self.header = header119 self.items = items120 def __str__(self):121 return '%s {\n%s\n}' % (self.header,122 '\n'.join(str(x) for x in self.items))123 def __repr__(self):124 return self.__str__()125class StructElement(object):126 pass127class StructElementIVar(StructElement):128 def __init__(self, typename, name):129 self.typename = typename130 self.name = name131 def __str__(self):132 return '%s %s' % (self.typename, self.name)133class StructElementStruct(StructElement):134 def __init__(self, struct):135 self.name = struct.header.name136 self.struct = struct137 def __str__(self):138 return self.struct.__str__()139class EnumCase(object):140 def __init__(self, name, value):141 self.name = name142 self.value = value143 def __str__(self):144 return '%s = %s' % (self.name, self.value)145class PackageID(object):146 def __init__(self, name, version):147 self.name = name148 self.version = version149 def __str__(self):150 return '%s%s' % (self.name, self.version)151class Package(object):152 def __init__(self, package):153 self.package = package154 def __str__(self):155 return 'package %s' % self.package156class Import(object):157 def __init__(self, package):158 self.package = package159 def __str__(self):160 return 'import %s' % self.package161class Header(object):162 def __init__(self, package, imports):163 self.package = package164 self.imports = imports165 def __str__(self):166 return str(self.package) + "\n" + \167 '\n'.join(str(x) for x in self.imports)168class EnumValue(object):169 def resolve(self, enum, document):170 pass171class EnumValueConstant(EnumValue):172 def __init__(self, value):173 self.value = value174 def __str__(self):175 return self.value176 def resolve(self, enum, document):177 if self.value.startswith("0x"):178 return int(self.value, 16)179 else:180 return int(self.value, 10)181class EnumValueSuccessor(EnumValue):182 def __init__(self, value):183 self.value = value184 def __str__(self):185 return '%s + 1' % self.value186 def resolve(self, enum, document):187 return self.value.resolve(enum, document) + 1188class EnumValueLocalRef(EnumValue):189 def __init__(self, ref):190 self.ref = ref191 def __str__(self):192 return self.ref193 def resolve(self, enum, document):194 for case in enum.cases:195 if case.name == self.ref: return case.value.resolve(enum, document)196class EnumValueLShift(EnumValue):197 def __init__(self, base, offset):198 self.base = base199 self.offset = offset200 def __str__(self):201 return '%s << %s' % (self.base, self.offset)202 def resolve(self, enum, document):203 base = self.base.resolve(enum, document)204 offset = self.offset.resolve(enum, document)205 return base << offset206class EnumValueOr(EnumValue):207 def __init__(self, param1, param2):208 self.param1 = param1209 self.param2 = param2210 def __str__(self):211 return '%s | %s' % (self.param1, self.param2)212 def resolve(self, enum, document):213 param1 = self.param1.resolve(enum, document)214 param2 = self.param2.resolve(enum, document)215 return param1 | param2216class EnumValueExternRef(EnumValue):217 def __init__(self, where, ref):218 self.where = where219 self.ref = ref220 def __str__(self):221 return '%s:%s' % (self.where, self.ref)222 def resolve(self, enum, document):223 enum = document['enums'][self.where]224 return EnumValueLocalRef(self.ref).resolve(enum, document)225# Error rule for syntax errors226def p_error(p):227 print("Syntax error in input: %s" % p)228 try:229 while True:230 print(p.lexer.next().value, end=' ')231 except:232 pass233def p_document(t):234 'document : header type_decls'235 enums = {}236 structs = {}237 for enum in t[2]:238 if not isinstance(enum, EnumDecl): continue239 enums[enum.header.name] = enum240 for struct in t[2]:241 if not isinstance(struct, StructDecl): continue242 structs[struct.header.name] = struct243 t[0] = {'header' : t[1], 'enums' : enums, 'structs' : structs}244def p_type_decls_1(t):245 'type_decls : type_decl'246 t[0] = [t[1]]247def p_type_decls_2(t):248 'type_decls : type_decls type_decl'249 t[0] = t[1] + [t[2]]250def p_type_decl_e(t):251 'type_decl : enum_decl'252 t[0] = t[1]253def p_type_decl_s(t):254 'type_decl : struct_decl'255 t[0] = t[1]256def p_enum_cases_1(t):257 'enum_cases : enum_case'258 t[0] = [t[1]]259def p_enum_cases_2(t):260 'enum_cases : enum_cases COMMA enum_case'261 t[0] = t[1] + [t[3]]262def p_struct_elements_1(t):263 'struct_elements : struct_element'264 t[0] = [t[1]]265def p_struct_elements_2(t):266 'struct_elements : struct_elements struct_element'267 t[0] = t[1] + [t[2]]268def p_enum_base_1(t):269 'enum_base : VERSION COLON COLON IDENTIFIER'270 t[0] = '%s::%s' % (t[1], t[4])271def p_enum_base_2(t):272 'enum_base : IDENTIFIER'273 t[0] = t[1]274def p_struct_header(t):275 'struct_header : struct IDENTIFIER'276 t[0] = StructHeader(t[2])277def p_enum_header_1(t):278 'enum_header : enum IDENTIFIER'279 t[0] = EnumHeader(t[2], None)280def p_enum_header_2(t):281 'enum_header : enum IDENTIFIER COLON enum_base'282 t[0] = EnumHeader(t[2], t[4])283def p_struct_decl(t):284 'struct_decl : struct_header LBRACE struct_elements RBRACE SEMICOLON'285 t[0] = StructDecl(t[1], t[3])286def p_enum_decl_1(t):287 'enum_decl : enum_header LBRACE enum_cases RBRACE SEMICOLON'288 t[0] = EnumDecl(t[1], t[3])289def p_enum_decl_2(t):290 'enum_decl : enum_header LBRACE enum_cases COMMA RBRACE SEMICOLON'291 t[0] = EnumDecl(t[1], t[3])292def p_enum_value_1(t):293 '''enum_value : NUMBER294 | HEX'''295 t[0] = EnumValueConstant(t[1])296def p_enum_value_2(t):297 'enum_value : enum_value SHIFT NUMBER'298 t[0] = EnumValueLShift(t[1], EnumValueConstant(t[3]))299def p_enum_value_3(t):300 'enum_value : enum_value OR enum_value'301 t[0] = EnumValueOr(t[1], t[3])302def p_enum_value_4(t):303 'enum_value : LPAREN enum_value RPAREN'304 t[0] = t[2]305def p_enum_value_5(t):306 'enum_value : IDENTIFIER COLON IDENTIFIER'307 t[0] = EnumValueExternRef(t[1],t[3])308def p_enum_value_6(t):309 'enum_value : IDENTIFIER'310 t[0] = EnumValueLocalRef(t[1])311def p_typename_v(t):312 'typename : IDENTIFIER'313 t[0] = SimpleTypename(t[1])314def p_typename_g(t):315 'typename : IDENTIFIER LESSTHAN IDENTIFIER GREATERTHAN'316 t[0] = GenericTypename(t[1], t[3])317def p_struct_element_ivar(t):318 'struct_element : typename IDENTIFIER SEMICOLON'319 t[0] = StructElementIVar(t[1], t[2])320def p_struct_element_struct(t):321 'struct_element : struct_decl'322 t[0] = StructElementStruct(t[1])323def p_enum_case_v(t):324 'enum_case : IDENTIFIER EQUALS enum_value'325 t[0] = EnumCase(t[1], t[3])326def p_enum_case_b(t):327 'enum_case : IDENTIFIER'328 t[0] = EnumCase(t[1], None)329def p_header_1(t):330 'header : package_decl'331 t[0] = Header(t[1], [])332def p_header_2(t):333 'header : package_decl import_decls'334 t[0] = Header(t[1], t[2])335def p_import_decls_1(t):336 'import_decls : import_decl'337 t[0] = [t[1]]338def p_import_decls_2(t):339 'import_decls : import_decls import_decl'340 t[0] = t[1] + [t[2]]341def p_package_decl(t):342 'package_decl : package package_ID SEMICOLON'343 t[0] = Package(t[2])344def p_import_decl(t):345 'import_decl : import package_ID SEMICOLON'346 t[0] = Import(t[2])347def p_package_ID(t):348 'package_ID : dotted_identifier VERSION'349 t[0] = PackageID(t[1], t[2])350def p_dotted_identifier_1(t):351 'dotted_identifier : IDENTIFIER'352 t[0] = t[1]353def p_dotted_identifier_2(t):354 'dotted_identifier : dotted_identifier DOT IDENTIFIER'355 t[0] = t[1] + '.' + t[3]356class SilentLogger(object):357 def warning(*args):358 pass359import ply.yacc as yacc360parser = yacc.yacc(debug=False, write_tables=False, errorlog=SilentLogger())361import sys362def parse(filename):...

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Gherkin-python automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful