Пример #1
0
    def _apply_filter(value, filter_, failure_message):
        # type: (dict, Optional[f.BaseFilter], Text) -> dict
        """
    Applies a filter to a value.  If the value does not pass the
    filter, an exception will be raised with lots of contextual info
    attached to it.
    """
        if filter_:
            runner = f.FilterRunner(filter_, value)

            if runner.is_valid():
                return runner.cleaned_data
            else:
                raise with_context(
                    exc=ValueError(
                        '{message} ({error_codes}) '
                        '(`exc.context["filter_errors"]` '
                        'contains more information).'.format(
                            message=failure_message,
                            error_codes=runner.error_codes,
                        ), ),
                    context={
                        'filter_errors': runner.get_errors(with_context=True),
                    },
                )

        return value
Пример #2
0
    def execute(self, api, **arguments):
        # type: (Iota, ...) -> int
        channel_key_index = arguments['channel_key_index']  # type: int
        count = arguments['count']  # type: int
        depth = arguments['depth']  # type: int
        dry_run = arguments['dry_run']  # type: bool
        mam_encrypt_path = arguments['mam_encrypt_path']  # type: Text
        min_weight_magnitude = arguments['min_weight_magnitude']  # type: int
        message_encoding = arguments['message_encoding']  # type: Text
        message_file = arguments['message_file']  # type: Optional[Text]
        security_level = arguments['security_level']  # type: int
        start = arguments['start']  # type: int

        if message_file:
            with codecs.open(
                    message_file, 'r',
                    message_encoding) as f_:  # type: codecs.StreamReaderWriter
                message = f_.read()

        else:
            self.stdout.write(
                'Enter message to send.  Press Ctrl-D on a blank line when done.\n\n',
            )

            message = self.stdin.read().strip()
            self.stdout.write('\n')

        # Generating the encrypted message may take a little while, so we
        # should provide some feedback to the user so that they know that
        # their input is being processed (this is especially important if
        # the user typed in their message, so that they don't press ^D
        # again, thinking that the program didn't register the first one).
        self.stdout.write('Encrypting message...\n')

        proc =\
          run(
            args = [
              # mam_encrypt.js
              mam_encrypt_path,

              # Required arguments
              binary_type(api.seed),
              message,

              # Options
              '--channel-key-index', text_type(channel_key_index),
              '--start', text_type(start),
              '--count', text_type(count),
              '--security-level', text_type(security_level),
            ],

            check   = True,
            stdout  = PIPE,
            stderr  = self.stderr,
          )

        # The output of the JS script is a collection of transaction
        # trytes, encoded as JSON.
        filter_ =\
          f.FilterRunner(
            starting_filter =
                f.Required
              | f.Unicode
              | f.JsonDecode
              | f.Array
              | f.FilterRepeater(
                    f.ByteString(encoding='ascii')
                  | Trytes(result_type=TransactionTrytes)
                ),

            incoming_data = proc.stdout,
          )

        if not filter_.is_valid():
            self.stderr.write(
                'Invalid output from {mam_encrypt_path}:\n'
                '\n'
                'Output:\n'
                '{output}\n'
                '\n'
                'Errors:\n'
                '{errors}\n'.format(
                    errors=pformat(filter_.get_errors(with_context=True)),
                    mam_encrypt_path=mam_encrypt_path,
                    output=proc.stdout,
                ), )

            return 2

        transaction_trytes = filter_.cleaned_data  # type: List[TransactionTrytes]

        bundle = Bundle.from_tryte_strings(transaction_trytes)

        if dry_run:
            self.stdout.write('Transactions:\n\n')
            self.stdout.write(json.dumps(bundle, cls=JsonEncoder, indent=2))
        else:
            api.send_trytes(
                depth=depth,
                trytes=transaction_trytes,
                min_weight_magnitude=min_weight_magnitude,
            )

            self.stdout.write('Message broadcast successfully!\n')
            self.stdout.write(
                'Bundle ID: {bundle_hash}\n'.format(
                    bundle_hash=bundle.hash, ), )

        return 0
Пример #3
0
    def filter_kwargs(self, filters):
        # type: (Dict[Text, Dict[Text, f.FilterCompatible]]) -> Dict[Text, dict]
        """
        Extracts and filters values from the trigger kwargs.

        :param filters:
            Keys are the names of triggers to extract params from.
            Values are dicts used to configure FilterMapper instances.

            Note: The FilterMapper instances are configured with:
            - ``allow_missing_keys = True``
            - ``allow_extra_keys = True``

        Example::

           task_params =
             context.filter_kwargs({
               't_createApplicant': {
                 'eflId': f.Required | f.ext.Model(Questionnaire),
               },

               'scoring': {
                  'model'; f.Required | f.Unicode,
               },
             })

        :raise:
          - ``ValueError`` if the trigger kwargs fail validation.
        """
        # Configure the inner filters, used to process each value
        # inside ``trigger_kwargs``.
        map_ = {
            item_key: f.Optional(default={}) | f.FilterMapper(filter_map)
            for item_key, filter_map in iteritems(filters)
        }

        filter_ =\
            f.FilterRunner(
                # Configure the outer filter, used to apply the inner
                # filters to the ``trigger_kwargs`` dict.
                starting_filter =
                    f.FilterMapper(
                        filter_map          = map_,
                        allow_missing_keys  = True,
                        allow_extra_keys    = True,
                    ),

                incoming_data = self.trigger_kwargs or {},
            )

        if not filter_.is_valid():
            raise with_context(
                exc=ValueError(
                    'Invalid trigger kwargs: {errors}'.format(
                        errors=filter_.errors, ), ),
                context={
                    'filter_errors': filter_.get_errors(with_context=True),
                },
            )

        return filter_.cleaned_data