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
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
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