@classmethod
def from_extra_specs(cls, extra_specs, req=None):
    """Processes resources and traits in numbered groupings in extra_specs.

        Examines extra_specs for items of the following forms:
            "resources:$RESOURCE_CLASS": $AMOUNT
            "resources$N:$RESOURCE_CLASS": $AMOUNT
            "trait:$TRAIT_NAME": "required"
            "trait$N:$TRAIT_NAME": "required"

        Does *not* yet handle member_of[$N].

        :param extra_specs: The extra_specs dict.
        :param req: the ResourceRequest object to add the requirements to or
               None to create a new ResourceRequest
        :return: A ResourceRequest object representing the resources and
                 required traits in the extra_specs.
        """
    if req is not None:
        ret = req
    else:
        ret = cls()
    for key, val in extra_specs.items():
        if key == 'group_policy':
            ret._add_group_policy(val)
            continue
        match = cls.XS_KEYPAT.match(key)
        if not match:
            continue
        prefix, suffix, name = match.groups()
        if prefix == cls.XS_RES_PREFIX:
            ret._add_resource(suffix, name, val)
        elif prefix == cls.XS_TRAIT_PREFIX:
            ret._add_trait(suffix, name, val)
    return ret
