Beispiel #1
0
    async def on_rebalance(self,
                           assigned: Set[TP],
                           revoked: Set[TP],
                           newly_assigned: Set[TP]) -> None:
        """Call when the cluster is rebalancing."""
        T = traced_from_parent_span()
        # Stop producers for revoked partitions.
        revoked_tids = list(sorted(self._tps_to_transactional_ids(revoked)))
        if revoked_tids:
            self.log.info(
                'Stopping %r transactional %s for %r revoked %s...',
                len(revoked_tids),
                pluralize(len(revoked_tids), 'producer'),
                len(revoked),
                pluralize(len(revoked), 'partition'))
            await T(self._stop_transactions, tids=revoked_tids)(revoked_tids)

        # Start produers for assigned partitions
        assigned_tids = list(sorted(self._tps_to_transactional_ids(assigned)))
        if assigned_tids:
            self.log.info(
                'Starting %r transactional %s for %r assigned %s...',
                len(assigned_tids),
                pluralize(len(assigned_tids), 'producer'),
                len(assigned),
                pluralize(len(assigned), 'partition'))
            await T(self._start_transactions,
                    tids=assigned_tids)(assigned_tids)
Beispiel #2
0
 def validate(self, value: CharacterType) -> Iterable[ValidationError]:
     allow_blank = self.allow_blank
     if not allow_blank and not len(value):
         yield self.validation_error(f"{self.field} cannot be left blank")
     max_ = self.max_length
     length = len(value)
     min_ = self.min_length
     if min_:
         if length < min_:
             chars = pluralize(min_, "character")
             yield self.validation_error(
                 f"{self.field} must have at least {min_} {chars}")
     if max_:
         if length > max_:
             chars = pluralize(max_, "character")
             yield self.validation_error(
                 f"{self.field} must be at least {max_} {chars}")
Beispiel #3
0
    def _contribute_to_options(cls, options: ModelOptions) -> None:
        # Find attributes and their types, and create indexes for these.
        # This only happens once when the class is created, so Faust
        # models are fast at runtime.

        fields, defaults = annotations(
            cls,
            stop=Record,
            skip_classvar=True,
            alias_types=ALIAS_FIELD_TYPES,
            localns={cls.__name__: cls},
        )
        options.fields = cast(Mapping, fields)
        options.fieldset = frozenset(fields)
        options.fieldpos = {i: k for i, k in enumerate(fields.keys())}

        # extract all default values, but only for actual fields.
        options.defaults = {
            k: v.default if isinstance(v, FieldDescriptor) else v
            for k, v in defaults.items() if k in fields
            and not (isinstance(v, FieldDescriptor) and v.required)
        }

        # Raise error if non-defaults are mixed in with defaults
        # like namedtuple/dataclasses do.
        local_defaults = []
        for attr_name in cls.__annotations__:
            if attr_name in cls.__dict__:
                default_value = cls.__dict__[attr_name]
                if isinstance(default_value, FieldDescriptorT):
                    if not default_value.required:
                        local_defaults.append(attr_name)
                else:
                    local_defaults.append(attr_name)
            else:
                if local_defaults:
                    raise TypeError(
                        E_NON_DEFAULT_FOLLOWS_DEFAULT.format(
                            cls_name=cls.__name__,
                            field_name=attr_name,
                            fields=pluralize(len(local_defaults), 'field'),
                            default_names=', '.join(local_defaults),
                        ))

        for field, typ in fields.items():
            if is_optional(typ):
                # Optional[X] also needs to be added to defaults mapping.
                options.defaults.setdefault(field, None)

        # Create frozenset index of default fields.
        options.optionalset = frozenset(options.defaults)
Beispiel #4
0
def test_pluralize(n, s, suffix, expected):
    assert text.pluralize(n, s, suffix=suffix) == expected
Beispiel #5
0
    def _contribute_to_options(cls, options: ModelOptions) -> None:
        # Find attributes and their types, and create indexes for these.
        # This only happens once when the class is created, so Faust
        # models are fast at runtime.

        fields, defaults = annotations(
            cls,
            stop=Record,
            skip_classvar=True,
            alias_types=ALIAS_FIELD_TYPES,
            localns={cls.__name__: cls},
        )
        options.fields = cast(Mapping, fields)
        options.fieldset = frozenset(fields)
        options.fieldpos = {i: k for i, k in enumerate(fields.keys())}

        # extract all default values, but only for actual fields.
        options.defaults = {
            k: v.default if isinstance(v, FieldDescriptor) else v
            for k, v in defaults.items() if k in fields
            and not (isinstance(v, FieldDescriptor) and v.required)
        }

        options.models = {}
        options.polyindex = {}
        modelattrs = options.modelattrs = {}

        def _is_concrete_type(field: str, wanted: IsInstanceArgT) -> bool:
            typeinfo = options.polyindex[field]
            try:
                return issubclass(typeinfo.member_type, wanted)
            except TypeError:
                return False

        # Raise error if non-defaults are mixed in with defaults
        # like namedtuple/dataclasses do.
        local_defaults = []
        for attr_name in cls.__annotations__:
            if attr_name in cls.__dict__:
                default_value = cls.__dict__[attr_name]
                if isinstance(default_value, FieldDescriptorT):
                    if not default_value.required:
                        local_defaults.append(attr_name)
                else:
                    local_defaults.append(attr_name)
            else:
                if local_defaults:
                    raise TypeError(
                        E_NON_DEFAULT_FOLLOWS_DEFAULT.format(
                            cls_name=cls.__name__,
                            field_name=attr_name,
                            fields=pluralize(len(local_defaults), 'field'),
                            default_names=', '.join(local_defaults),
                        ))

        for field, typ in fields.items():
            is_model, member_type, generic_type = _is_model(typ)
            options.polyindex[field] = TypeInfo(generic_type, member_type)
            if is_model:
                # Extract all model fields
                options.models[field] = typ
                # Create mapping of model fields to polymorphic types if
                # available
                modelattrs[field] = generic_type
            if is_optional(typ):
                # Optional[X] also needs to be added to defaults mapping.
                options.defaults.setdefault(field, None)

        # Create frozenset index of default fields.
        options.optionalset = frozenset(options.defaults)

        # extract all fields that we want to coerce to a different type
        # (decimals=True, isodates=True, coercions={MyClass: converter})
        # Then move them to options.field_coerce, which is what the
        # model.__init__ method uses to coerce any fields that need to
        # be coerced.
        options.field_coerce = {}
        if options.isodates:
            options.coercions.setdefault(DATE_TYPES, iso8601.parse)
        if options.decimals:
            options.coercions.setdefault(DECIMAL_TYPES, str_to_decimal)

        for coerce_types, coerce_handler in options.coercions.items():
            options.field_coerce.update({
                field: TypeCoerce(typ, coerce_handler)
                for field, typ in fields.items()
                if (field not in modelattrs
                    and _is_concrete_type(field, coerce_types))
            })