def test_on_can_run_whatever_on_success(): def _capture_value(value, _): global on_whatever_value on_whatever_value = value + 1 E.success(1) | E.on | dict(whatever=_capture_value) assert on_whatever_value == 2
def test_on_can_run_on_success(): def _capture_value(x): global on_success_value on_success_value = x + 1 E.success(1) | E.on | dict(success=_capture_value) assert on_success_value == 2
def safely_load_json(filename: str) -> E.Either[CartItem, Exception]: with open(filename) as json_file: try: results = get_json_data(json_file) return E.success(results) except Exception as inst: return E.failure(inst)
def get_all_items( self, page_number: int = 0, page_size: int = 10 ) -> E.Either[List[CartItem], RepositoryException]: try: cursor = self.__db_conn.cursor() cursor.execute( "SELECT id, name, price, manufacturer, updated_at, created_at FROM cart LIMIT %s OFFSET %s", [page_size, page_number * page_size]) rows = cursor.fetchmany(size=page_size) if rows: return E.success(list(map(self.__from_tuple, rows))) return E.success([]) except Exception as inst: return E.failure(UnknownException(list(inst.args)))
def check_connection(self) -> E.Either[str, RepositoryException]: try: cursor = self.__db_conn.cursor() cursor.execute("SELECT 1;") _ = cursor.fetchone() self.__db_conn.commit() return E.success("Success!") except Exception as inst: return E.failure(UnknownException(list(inst.args)))
def create_database(self) -> E.Either[CartItem, RepositoryException]: try: cursor = self.__db_conn.cursor() results = cursor.execute("CREATE DATABASE IF NOT EXISTS cart") self.__db_conn.commit() return E.success(results) except Exception as inst: self.__db_conn.rollback() return E.failure(UnknownException(list(inst.args)))
def chain_func(remaining_items: List[Any], resulting_items: List[Any]) -> Either[Any, Any]: if len(remaining_items) == 0: return E.success(resulting_items) item = remaining_items[0] new_remaining_items = remaining_items[1:] return E.try_catch(lambda: processor(item)) \ | E.then | (lambda result: chain_func(new_remaining_items, resulting_items+[result]))
def chain_func(remaining_items: List[Any], last_result: Optional[Any]) -> E.Either: if len(remaining_items) == 0: return E.success(last_result) item = remaining_items[0] remaining_items = remaining_items[1:] return E.try_catch(lambda: action(item, last_result)) \ | E.then | (lambda next_result: chain_func(remaining_items, next_result))
def __get_all_cart_items_in_db(current_page: int = 0, page_size: int = 20, items: List[CartItem] = []) -> E.Either[List[CartItem], Exception]: def __check_result(items: List[CartItem] = []) -> E.Either[List[CartItem], Exception]: if len(items) <= 0: return E.failure("No more items!") else: return E.success(items) return service.get_items(page_number=current_page, page_size=page_size) \ | E.then | __check_result \ | E.from_either | dict( if_success=(lambda results: __get_all_cart_items_in_db(current_page=current_page + 1, page_size=page_size, items= items + results)), if_failure=(lambda ex: E.success(items)) )
def remove_item_by_id(self, id: str) -> E.Either[str, RepositoryException]: try: cursor = self.__db_conn.cursor() cursor.execute("DELETE FROM cart WHERE id = %s", [id]) rows_deleted = cursor.rowcount self.__db_conn.commit() if rows_deleted == 1: return E.success(id) return E.failure(NotFoundRepositoryException([id])) except Exception as inst: self.__db_conn.rollback() return E.failure(UnknownException(list(inst.args)))
def get_item_by_id(self, id: str) -> E.Either[CartItem, RepositoryException]: try: cursor = self.__db_conn.cursor() cursor.execute( "SELECT id, name, price, manufacturer, updated_at, created_at FROM cart WHERE id = %s", [id]) row = cursor.fetchone() if row: return E.success(self.__from_tuple(row)) return E.failure(NotFoundRepositoryException()) except Exception as inst: return E.failure(UnknownException(list(inst.args)))
def convert_list_to_either( items: List[E.Either[T, Exception]]) -> E.Either[List[U], Exception]: success_results = [] for item in items: success_result, failure_result = item | E.from_either | dict( if_success=(lambda result: (result, None)), if_failure=(lambda ex: (None, ex))) if success_result is not None: success_results.append(success_result) elif failure_result is not None: return E.failure(failure_result) else: return E.failure(Exception("Unexpected error has occurred!")) return E.success(success_results)
def update_item(self, item: CartItem) -> E.Either[CartItem, RepositoryException]: try: cursor = self.__db_conn.cursor() cursor.execute( "UPDATE cart SET name = %s, price = %s, manufacturer = %s, updated_at = %s WHERE id = %s RETURNING id, name, price, manufacturer, updated_at, created_at", [ item.name, item.price, item.manufacturer, datetime.datetime.now().isoformat(), item.id ]) result = cursor.fetchone() self.__db_conn.commit() if result: return E.success(self.__from_tuple(result)) return E.failure(NotFoundRepositoryException()) except Exception as inst: self.__db_conn.rollback() return E.failure(UnknownException(list(inst.args)))
def add_item(self, item: CartItem) -> E.Either[CartItem, RepositoryException]: try: cursor = self.__db_conn.cursor() cursor.execute( "INSERT INTO cart (name, price, manufacturer, updated_at, created_at) VALUES (%s, %s, %s, %s, %s) RETURNING id, name, price, manufacturer, updated_at, created_at", [ item.name, item.price, item.manufacturer, item.updated_at, item.created_at ]) result = cursor.fetchone() self.__db_conn.commit() if result: return E.success(self.__from_tuple(result)) return E.failure( UnknownException(["Unable to add item at this time!"])) except Exception as inst: self.__db_conn.rollback() return E.failure(UnknownException(list(inst.args)))
def validate(item: Dict[str, str]) -> E.Either['CartItem', Exception]: def empty_value(type: str) -> str: return f"'{type}' must not be empty" def get_optional_value(key: str, defaultValue: Any = "") -> str: if key in item: return item[key] else: return defaultValue errors: List[str] = [] if item["name"] is None: errors.append(empty_value("name")) elif len(item["name"]) == 0: errors.append(empty_value("name")) if item["price"] is None: errors.append(empty_value("price")) if int(item["price"]) < 99: errors.append("'price' must be greater than 99") if item["manufacturer"] is None: errors.append(empty_value("manufacturer")) if len(item["manufacturer"]) == 0: errors.append(empty_value("manufacturer")) if len(errors) != 0: return E.failure(InvalidItemException(errors)) else: current_timestamp = datetime.datetime.now().isoformat() return E.success(CartItem( id=get_optional_value("id"), name=item["name"], price=item["price"], manufacturer=item["manufacturer"], created_at=get_optional_value("created_at", defaultValue=current_timestamp), updated_at=get_optional_value("updated_at", defaultValue=current_timestamp) ))
def test_can_chain_success_either(): assert E.success(1) | E.then | (lambda x: E.success(x + 1)) == E.success(2)
def test_from_either_can_return_on_success(): assert E.success(1) \ | E.from_either | dict( if_success=lambda x: x + 1, if_failure=lambda _: "shouldSucceed") == 2
def test_can_make_empty_success_either(): assert E.success() == ("success", None)
def test_can_catch_error_and_return_success(): assert E.failure("someError") | E.catch_error | ( lambda x: E.success(1)) == E.success(1)
def test_can_catch_error_and_default_non_either_result_to_success(): assert E.failure("someError") | E.catch_error | ( lambda _: 1) == E.success(1)
def test_can_chain_success_either_and_fail(): assert E.success(1) | E.then | ( lambda _: E.failure("someError")) == E.failure("someError")
def test_can_map_error_and_ignore_success(): assert E.success(1) | E.map_error | (lambda x: x + "Plus") == E.success(1)
def test_can_make_success_either(): assert E.success(1) == ("success", 1)
def test_can_chain_success_either_and_wrap_non_either_result(): assert E.success(1) | E.then | (lambda x: x + 1) == E.success(2)
def __check_result(items: List[CartItem] = []) -> E.Either[List[CartItem], Exception]: if len(items) <= 0: return E.failure("No more items!") else: return E.success(items)
def test_can_map_success_either(): assert E.success(1) | E.map | (lambda x: x + 1) == E.success(2)
def create_db_conn(database_uri: str) -> E.Either[Connection, RepositoryException]: try: config = parse_db_config(database_uri) return E.success(connect(host=config.host, user=config.username, password=config.password, dbname=config.name, port=config.port)) except Exception as inst: return E.failure(ConnectionFailedRepositoryException(list(inst.args)))