def get_prices(self, query: PriceGetterQuery) -> Result[List[PricePoint], Exception]: self.query = query return flow( query, self._generate_query, bind(self._send_query), bind(self._validate_response), bind(self._parse_response) )
def handle_attribute( collection: Union[Dict[str, Any], List[Any]], cfg: dict, ) -> ResultE[MapValue]: """Handle one attribute with mappings, ifs, casting and default value. :param collection: The collection of data to find data in :type collection: Union[Dict[str, Any], List[Any]] :param configuration: :term:`configuration` data to use when mapping :type configuration: Dict[str, Any] :return: Success/Failure containers :rtype: MapValue configuration expected to look like this: .. code-block:: json { "mappings": [], # array of mapping objects "separator": None, "if_statements": [], # array of if statement objects "casting": {} # casting object, for casting types "default": "default value" } flow description: Map all objects in cfg[MAPPINGS] -> Apply separator to values if there are more than 1 Failure -> fix to Success(None) Apply if statements Success -> Cast Value Failure -> apply default value Return Result """ mapped_values = [ mapped.unwrap() for mapped in [ handle_mapping(collection, mapping) for mapping in cfg.get(MAPPINGS, []) ] if is_successful(mapped) ] # partially declare if statement and casting functions ifs = partial(apply_if_statements, if_objects=cfg.get(IF_STATEMENTS, [])) cast = partial(apply_casting, casting=cfg.get(CASTING, {})) return flow( apply_separator(mapped_values, separator=cfg.get(SEPARATOR, '')), fix(lambda _: None), # type: ignore bind(ifs), bind(cast), rescue(lambda _: apply_default(default=cfg.get(DEFAULT)), ), )
def run(self, cluster_spec: ClusterSpec) -> Result[ExecutedJob, InvalidJob]: do_filter_columns = partial(self.df_filter_columns, cluster_spec) do_partition_and_write = partial(self.partition_and_write, cluster_spec) final = flow( df_from(self.input_paths, self.input_format, self.line_terminator), bind(do_filter_columns), bind(do_partition_and_write) ) return final
def handle_mapping( collection: Union[Dict[str, Any], List[Any]], cfg: Dict[str, Any], ) -> ResultE[MapValue]: """Find data in path and apply if statements or default value. .. versionadded:: 0.0.1 :param configuration: :term:`configuration` data to use when mapping :type configuration: Dict[str, Any] :param collection: The collection of data to find data in :type collection: Union[Dict[str, Any], List[Any]] :return: Success/Failure containers :rtype: GoResult configuration expected to look like this: .. code-block:: json { "path": [], "if_statementss": [{}, {}], "default": 'val' } Flow description: find data from path or None -> apply if statements -> return default value if Failure else mapped value """ return flow( collection, partial(fetch_data_by_keys, path=cfg.get(PATH, [])), fix(lambda _: None), # type: ignore bind(partial( apply_regexp, regexp=cfg.get(REGEXP, {}), ), ), fix(lambda _: None), # type: ignore map_(partial( apply_slicing, slicing=cfg.get(SLICING, {}), )), bind( partial( apply_if_statements, if_objects=cfg.get(IF_STATEMENTS, []), )), rescue( # type: ignore lambda _: apply_default(cfg.get(DEFAULT)), ), )
def __call__(self, user_id: int) -> IO[Result[float, Exception]]: """Fetches `UserProfile` TypedDict from foreign API.""" return flow( user_id, self._make_request, IO.lift(bind(self._parse_json)), )
def test_bind_with_result(): """Ensures that functions can be composed and return type is correct.""" bound = bind(_result_function) assert bound(Success(1)) == Success('2') assert bound(Failure('s')) == Failure('s') assert bound(Success(1)) == unify(_result_function)(Success(1))
def apply_casting( value_to_cast: Optional[AnyType], casting: Casting, ) -> ResultE[AnyType]: """Casting one type of code to another. :param casting: :term:`casting` object :type casting: dict :param value_to_cast: The value to cast to casting['to'] :type value_to_cast: AnyType :return: Success/Failure containers :rtype: AnyType Example >>> apply_casting('123', Casting(**{'to': 'integer'})).unwrap() 123 >>> apply_casting('123.12', Casting(**{'to': 'decimal'})).unwrap() Decimal('123.12') """ if value_to_cast is None: return Failure(ValueError('value_to_cast is empty')) return flow( casting.to, get_casting_function, bind( # type: ignore lambda function: function( # type: ignore value_to_cast, casting.original_format, ), ), )
def __call__(self, stream_id: UUID) -> Result[StreamDetails, FailureDetails]: stream = self.__find_stream_by_stream_id(stream_id).bind( self.__verify_if_stream_exist ) partial_projects = partial(stream.bind, self.__find_projects_by_stream) partial_ksql = partial( stream.bind, lambda stream_: self.__get_stream_by_name(stream_.name) ) # TODO: Removes every `type: ignore` after resolution of # https://github.com/dry-python/returns/issues/410 return flow( # type: ignore Result.from_value(StreamDetails.build), # type: ignore stream.apply, bind(self.__call_and_apply(partial_projects)), bind(self.__call_and_apply(partial_ksql)), )
def handle_data_fetcher( collection: Union[Dict[str, Any], List[Any]], cfg: DataFetcher, ) -> ResultE[AnyType]: """Find a data at path or produce a value. return value can be: - value found at path - value found but sliced - value found applied to regular expression - conditional value depending on if statements - default value if all the above still produces `None` Flow description: find data from path or None -> apply regular expression -> apply slicing -> apply if statements -> return default value if Failure else mapped value """ return flow( collection, partial(fetch_data_by_keys, path=cfg.path), fix(lambda _: None), # type: ignore bind(partial( apply_regex, regex=cfg.regex, ), ), fix(lambda _: None), # type: ignore map_(partial( apply_slicing, slicing=cfg.slicing, )), bind(partial( apply_if_statements, statements=cfg.if_statements, )), rescue( # type: ignore lambda _: apply_default(cfg.default), ), )
async def on_startup_override(app: web.Application) -> NoReturn: """ A function linked to signal app.startup(), which combines the startup of all subsystems. :param app: an instance of aiohttp application. """ await flow(_init_nosql_dbs(app), bind(_init_scheduler)) if not app.shared.reach_graceful_startup: # Print a message to the console and graceful call exit _emergency_shutdown(signal.SIGINT)
def _upload(self, library: str, **kwargs) -> Result[str, Exception]: if [kwargs["metadata_query"], kwargs["metadata_source"]].count(None) == 1: if kwargs[ "metadata_source"] is None and self.metadata_source is not None: kwargs["metadata_source"] = self.metadata_source else: raise LibgenUploadException( "Both metadata_source and metadata_query are required to fetch metadata." ) upload_url: Result[str, Exception] = flow( kwargs["file_path"], self._validate_file, bind(partial(self._upload_file, library=library)), bind(check_upload_form_response), map_(lambda *_: self._browser.get_form()), # type: ignore bind( partial( self._fetch_metadata, metadata_query=kwargs["metadata_query"], metadata_source=kwargs["metadata_source"], )), bind(partial( self._update_metadata, metadata=kwargs["metadata"], )), bind(self._validate_metadata), bind(self._submit_and_check_form), lash(self._handle_save_failure), ) return upload_url
def handle_attribute( collection: Union[Dict[str, Any], List[Any]], cfg: Attribute, ) -> ResultE[AnyType]: """Handle one attribute with data fetchers, ifs, casting and default value. flow description: Fetch once for all data in Attribute.data_fetchers -> Apply separator to values if there are more than 1 Failure -> fix to Success(None) Apply if statements Success -> Cast Value Failure -> apply default value Return Result """ fetched_values = [ fetched.unwrap() for fetched in # noqa: WPS361 [ handle_data_fetcher(collection, data_fetcher) for data_fetcher in cfg.data_fetchers ] if is_successful(fetched) ] # partially declare if statement and casting functions ifs = partial(apply_if_statements, statements=cfg.if_statements) cast = safe(lambda the_value: the_value) if cfg.casting: cast = partial(apply_casting, casting=cfg.casting) return flow( apply_separator(fetched_values, separator=cfg.separator), fix(lambda _: None), # type: ignore bind(ifs), bind(cast), rescue(lambda _: apply_default(default=cfg.default), ), )
def __call__( self, value_to_cast: MapValue, original_format: str, ) -> ResultE[MapValue]: r""" purpose: Convert string date into ISO format date. :input value_to_cast: the string to be converted to a date :input original_format: a string describing the format the data string is before convertion. :raises ValueError: when not able to convert or value_to_cast does not match original_format. regex_tips ^ = start of string $ = end of string [^[0-9]] = matches anything not [0-9] [^\d] = matches anything not digits \d = matches digits {n} = matches previous match n amount of times () = grouper, groups up stuff for use in replace. """ date_value: str = str(value_to_cast) return flow( date_value, self._value_is_iso, rescue( # type: ignore lambda _: self._cast_with_millennia( date_value, original_format=original_format, ), ), rescue( # type: ignore lambda _: self._cast_with_no_millennia( date_value, original_format=original_format, ), ), bind(self._validate_date), alt( # type: ignore lambda failure: ValueError( self._error_message.format( value=date_value, failure=failure, ), ), ), )
def apply_casting( value_to_cast: Optional[MapValue], casting: Dict[str, Any], ) -> ResultE[MapValue]: """Cast one type of code to another. :param casting: :term:`casting` object :type casting: dict :param value_to_cast: The value to cast to casting['to'] :type value_to_cast: MapValue :return: Success/Failure containers :rtype: MapValue Example >>> apply_casting('123', {'to': 'integer'}).unwrap() 123 >>> apply_casting('123.12', {'to': 'decimal'}).unwrap() Decimal('123.12') """ if value_to_cast is None: return Failure(ValueError('value_to_cast is empty')) if TO not in casting or casting[TO] is None: return Success(value_to_cast) return flow( casting[TO], get_casting_function, bind( # type: ignore lambda function: function( # type: ignore value_to_cast, casting.get(ORIGINAL_FORMAT), ), ), )
def test_bind_with_context_io_result(): """Ensures that functions can be composed and return type is correct.""" binded = bind(_context_io_result_function) assert binded(RequiresContextIOResult.from_success(3))(5) == IOSuccess(8)
def test_bind_with_context(): """Ensures that functions can be composed and return type is correct.""" binded = bind(_context_function) assert binded(RequiresContext(lambda _: 3))(5) == 8
def test_bind_with_maybe(): """Ensures that functions can be composed and return type is correct.""" binded = bind(_maybe_function) assert binded(Some(1)) == Some('2') assert binded(Nothing) == Nothing
def test_bind_with_ioresult(): """Ensures that functions can be composed and return type is correct.""" binded = bind(_ioresult_function) assert binded(IOSuccess(1)) == IOSuccess('2') assert binded(IOFailure('a')) == IOFailure('a')
def test_bind_with_io(): """Ensures that functions can be composed and return type is correct.""" binded = bind(_io_function) assert binded(IO(1)) == IO('2')
def _submit_and_check_form(self, form: Form) -> Result[str, Exception]: return flow(form, self._submit_form_get_response, bind(check_metadata_form_response))
def test_bind_with_context_result(): """Ensures that functions can be composed and return type is correct.""" bound = bind(_context_result_function) assert bound(RequiresContextResult.from_value(3))(5) == Success(8)
def fetch_blog(blog_id) -> Result['Blog', Exception]: return flow(blog_id, fetch_blog_from_db, bind(blog_to_dict), bind(verify_access))
def run(self): a = flow(self.i, self.regular_function, partial(self.returns_container, 0.0), bind(self.also_returns_container), bind(self.also_returns_container_2)) return a
def run(self, cluster_spec: ClusterSpec) -> Result[ExecutedJob, InvalidJob]: return flow(self.df(), bind(self.query), bind(self.df_to))