def test_can_serialize_result(self): successful_outcome = 'correct.' successful_result = Result(Right(successful_outcome)) self.assertEqual(str(successful_result), f'<Result|success[{type(successful_outcome).__name__}]>') unsuccessful_outcome = RuntimeError('incorrect.') unsuccessful_result = Result(Right(unsuccessful_outcome)) self.assertEqual(str(unsuccessful_result), f'<Result|success[{type(unsuccessful_outcome).__name__}]>') confused_result = Result(Left(successful_outcome)) self.assertFalse(confused_result.successful)
def convert(v, u, u2): if u2 is None: return Right(v) else: if u is None: return Left((f"error trying to unitless value {v} without unitful value: {u2}", 403)) else: if u == u2: return Right(v) else: try: return Right((v * ureg.parse_expression(u)).to(ureg.parse_expression(u2)).magnitude) except Exception as e: return Left(str(e))
def get_status(poi_id: str) -> Either: def check_status(ctx: dict) -> Either: response = requests.get( os.getenv('STATUS_URL'), params=dict(uiCity='hongkong', uiLang='zh', poiId=ctx.get('poi_id')), headers={ "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36" }) if not response.status_code == 200: return Left(dict(ctx, error_code='ERROR_FROM_OPENRICE')) return Right(dict(ctx, status_data=response.json())) try: ctx = Right(dict(poi_id=poi_id)) result: Either = ctx | check_status if isinstance(result, Right): return StatusR( status_data=result.value.get('status_data')).__dict__ return StatusR(error_code=result.value.get('error_code')).__dict__ except Exception as e: print(e) return PoiR(error_code='INTERNAL_SERVER_ERROR').__dict__
def calculate_age2(born, timestamp): try: today = strtodate(timestamp) except Exception as e: return Left({"error": str(e)}) return Right(today.year - born.year - ((today.month, today.day) < (born.month, born.day)))
def get_collection(ctx: dict) -> Either: db = ctx.get('db') location = ctx.get('location') collections = db.list_collection_names() if location in collections: return Right(dict(ctx, collection=db[location])) return Left(dict(ctx, error_code='COLLECTION_NOT_FOUND'))
def F(self, path, *args, **kw): _fun = self.f(path) try: _start = time.perf_counter() res = _fun(*args, **kw) _end = time.perf_counter() ftrace = self.V('/sys/traceback/ftrace') if isNothing(ftrace) is not None: ft = self.V('/config/ftrace').value _rec = ft(stamp=time.time(), fun=path, time=_end - _start, args=args, kw=kw) ftrace.value.append(_rec) return Right(res) except: _t, _val, _tb = sys.exc_info() exc = self.V('/config/exception').value if isNothing(exc) is not True: res = exc(type=_t, value=_val, traceback=_tb) else: res = {} res['type'] = _t res['value'] = _val res['traceback'] = _tb tb = self.V('/sys/traceback/tb') if isNothing(tb) is not True: tb.value.append(res) self.V('/sys/traceback/exists', True) print(res) return Left(res)
def create_order(self, myid, symbol, type, side, qty, price, params): self.logger.info( "Requesting to create a new order. symbol:%s, type:%s, side:%s, qty:%s, price:%s" % (symbol, type, side, qty, price)) try: result = Right( self.exchange.create_order(symbol, type, side, qty, price=price, params=params)) order = Dotdict() order.myid = myid order.accepted_at = datetime.utcnow().strftime(DATETIME_FORMAT) order.id = result.value['info']['orderID'] order.status = 'accepted' order.symbol = symbol order.type = type.lower() order.side = side order.price = price if price is not None else 0 order.average_price = 0 order.cost = 0 order.amount = qty order.filled = 0 order.remaining = 0 order.fee = 0 self.om.add_order(order) # self.logger.info("UPDATED ORDER: %s" % order) # self.logger.info("ACTIVE ORDERS: %s" % self.om.get_open_orders()) except Exception as e: result = Left(str(e)) return result.value
def parse_info(ctx: dict): records = list() for res in ctx.get('restaurants'): info = dict( poi_id=res.get('poiId'), name=res.get('name'), district=get_nested_value(res, ['district', 'name']), address=res.get('address'), price=res.get('priceUI'), photo_url=get_nested_value(res, ['doorPhoto', 'url']), geolocaton=[res.get('mapLatitude'), res.get('mapLongitude')], phones=res.get('phones'), dishes=list(), categories=list(), scores=dict(), ) categories = res.get('categories') if categories: info['categories'] = [cat.get('name') for cat in categories] info['scores'] = { 'smile': res.get('scoreSmile'), 'cry': res.get('scoreCry') } tags = res.get('tags') if len(tags) > 0: for tag in tags: info['dishes'].append(tag['name']) info['open_hours'] = res.get('poiHours') records.append(info) return Right(dict(ctx, records=records))
def get_patient(patient_id, plugin): resp = get(pdsdpi_url_base(plugin) + f"/Patient/{patient_id}") if isinstance(resp, Left) and isinstance( resp.value[0], dict) and resp.value[0].get("status_code") == 404: return Right(None) else: return resp
def create_db_conn(ctx: dict) -> Either: try: conn = Cli(os.getenv('MONGO_URL')) db = conn['restaurants'] return Right(dict(ctx, db=db)) except Exception as e: print(e) return Left(dict(ctx, error_code='DB_CONNECTION_ERROR'))
def extract_results(ctx: dict): data = get_json_data(ctx.get('content')) if not isinstance(data, dict): return Left(dict(ctx, error_msg=data)) restaurants = get_nested_value(data, ['searchResult', 'paginationResult', 'results']) if not restaurants: return Left(dict(ctx, error_msg='Empty restaurants list')) return Right(dict(ctx, restaurants=restaurants))
def check(self, key: str) -> "Either": self.counter.ask({ 'action': 'put', 'key': key, 'now': self.__get_now() }) l = self.counter.ask({'action': 'list', 'key': key}) throttle = self.throttle[key] if len(l) < throttle.limit: return Right("Success") elif l[-throttle.limit] + throttle.interval < self.__get_now(): return Right("Success") else: msg = "SystemThrottle is detected. %s times per %s secs." % ( throttle.limit, throttle.interval) self.logger.warning(msg) return Left(msg)
def test_check(self): # setup self.sys_throttle.set_throttle(THROTTLE_KEY, 10, 1) # check for i in range(9): self.assertEqual( Right("Success").value, self.sys_throttle.check(THROTTLE_KEY).value) result = self.sys_throttle.check(THROTTLE_KEY) self.assertEqual("SystemThrottle is detected. 10 times per 1 secs.", str(result.value))
def _get_config(piid=None): url = f"{pds_url_base}/{pds_config}/config" resp = get(url) if isinstance(resp, Left): return resp else: if piid is not None: l = list(filter(lambda x : x["piid"] == piid, resp.value)) if len(l) == 0: return Left(("not found", 404)) else: return Right(l) else: return resp
def age( patient, unit, timestamp ): # if there is an error 'Left' function is returned; correct values-'Right' function is returned if unit is not None and unit != "year": return Left( (f"unsupported unit {unit}", 400) ) # 1st value in 'Left' function is an error message, 2nd value is error code if patient == None: # If no patient record is returned then 'Right' function is executed return Right({ "value": None, "certitude": 0, "calculation": "record not found" }) else: if "birthDate" in patient: birth_date = patient["birthDate"] date_of_birth = strtodate(birth_date) today = strtodate(timestamp).strftime("%Y-%m-%d") mage = calculate_age2(date_of_birth, timestamp) return mage.map( lambda age: { "value": age, "unit": "year", "certitude": 2, "calculation": f"Current date '{today}' minus patient's birthdate (FHIR resource 'Patient' field>'birthDate' = '{birth_date}')" }) else: return Right({ "value": None, "certitude": 0, "calculation": "birthDate not set" })
def check_status(ctx: dict) -> Either: response = requests.get( os.getenv('STATUS_URL'), params=dict(uiCity='hongkong', uiLang='zh', poiId=ctx.get('poi_id')), headers={ "User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36" }) if not response.status_code == 200: return Left(dict(ctx, error_code='ERROR_FROM_OPENRICE')) return Right(dict(ctx, status_data=response.json()))
def sex(patient, unit, timestamp): if patient == None: return Right({ "value": None, "certitude": 0, "calculation": "record not found" }) else: gender = patient.get("gender") if gender is None: return Right({ "value": None, "certitude": 0, "calculation": "gender not set" }) else: return Right({ "value": gender, "certitude": 2, "calculation": f"FHIR resource 'Patient' field>'gender' = {gender}" })
def cfvo_to_cfvo2(cfvo): cfv = cfvo["id"] cfvo2 = { "id": cfv } unit = cfvo.get("units") if unit is not None: cfvo2["units"] = unit elif custom_units is not None: cus = [a for a in custom_units if a["id"] == cfv] if len(cus) != 1: log(syslog.LOG_ERR, f"zeor or more than one default_units for patient variable {cfv}", "pds") if len(cus) > 0: cfvo2["units"] = cus[0]["units"] return Right(cfvo2)
def fetch_restaurants(ctx: dict): resp: dict = requests.get( os.getenv("POI_URL"), params={ "uiLang":"zh", "uiCity":"hongkong", "page":ctx.get('page_num'), "districtId":ctx.get('location_id') }, headers={ "User-Agent":"Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Mobile Safari/537.36" } ).__dict__ status_code = resp.get('status_code') if status_code < 400: return Right(dict(ctx,resp=resp)) else: return Left(dict(ctx, error_msg=f'Received http response status code: {str(status_code)}'))
def edit_order(self, myid, symbol, type, side, qty, price, params): self.logger.info( "Requesting to amend the order. myid:%s, symbol:%s, type:%s, side:%s, qty:%s, price:%s" % (myid, symbol, type, side, qty, price)) try: active_order = self.om.get_open_order(myid) if active_order is None: self.logger.warning("No ActiveOrder exists.") return result = Right( self.exchange.edit_order(active_order.id, symbol, type, side, amount=qty, price=price, params=params)) active_order.myid = myid active_order.accepted_at = datetime.utcnow().strftime( DATETIME_FORMAT) active_order.id = result.value['info']['id'] active_order.status = 'accepted' # order.symbol = symbol active_order.type = type.lower() # order.side = side active_order.price = price if price is not None else 0 active_order.average_price = 0 active_order.cost = 0 active_order.amount = qty active_order.filled = 0 # FIXME active_order.remaining = 0 # FIXME active_order.fee = 0 self.om.add_order(active_order) except ccxt.BadRequest as e: self.logger.warning("Returned BadRequest: %s" % str(e)) result = Left("Returned BadRequest: %s" % str(e)) self.om.cancel_order(myid) except Exception as e: self.logger.warning("Returned Exception: %s" % str(e)) result = Left(str(e)) return result.value
def get_restaurant(location: str = None): def create_db_conn(ctx: dict) -> Either: try: conn = Cli(os.getenv('MONGO_URL')) db = conn['restaurants'] return Right(dict(ctx, db=db)) except Exception as e: print(e) return Left(dict(ctx, error_code='DB_CONNECTION_ERROR')) def get_location(ctx: dict) -> Right: if not ctx.get('location'): return Right(dict(ctx, location=choice(LOCATIONS))) return Right(ctx) def get_collection(ctx: dict) -> Either: db = ctx.get('db') location = ctx.get('location') collections = db.list_collection_names() if location in collections: return Right(dict(ctx, collection=db[location])) return Left(dict(ctx, error_code='COLLECTION_NOT_FOUND')) def pick_poi(ctx: dict) -> Right: collection = ctx.get('collection') pipeline = [{"$sample": dict(size=1)}] poi = list(collection.aggregate(pipeline))[0] poi['_id'] = str(poi['_id']) return Right(dict(ctx, poi=poi)) try: ctx = Right(dict(location=location)) result: Either = ctx | create_db_conn | get_location | get_collection | pick_poi if isinstance(result, Right): return PoiR(poi=result.value.get('poi')).__dict__ return PoiR(error_code=result.value.get('error_code')).__dict__ except Exception as e: print(e) return PoiR(error_code='INTERNAL_SERVER_ERROR').__dict__
def _perform( self, should_raise: bool = False, timestamp_provider: Callable[[], int] = microsecond_timestamp ) -> Result[Outcome]: if not callable(self.instruction): outcome = Left(TypeError(f'Must be callable: {self.instruction}')) else: try: outcome = Right(self.validate().instruction()) if issubclass(type(outcome.value), Exception): raise outcome.value except Exception as e: if should_raise: raise e outcome = Left(e) if self._ActionType__reaction: self._ActionType__reaction.perform( should_raise=should_raise) return Result(outcome, timestamp_provider)
def request(func, method, url, *args, schema=None, **kwargs): resp1 = func(url, *args, **kwargs) status_code = resp1.status_code if status_code != 200: try: resp = resp1.json() except: resp = resp1.text return Left(({ "url": url, "method": method, "status_code": status_code, "response": resp }, 500)) try: resp = resp1.json() except Exception as e: resp = resp1.text return Left(({ "url": url, "method": method, "status_code": status_code, "response": resp, "error": str(e) }, 500)) if schema is not None: try: validate(resp, schema) except Exception as e: return Left(({ "url": url, "method": method, "status_code": status_code, "response": resp, "error": str(e) }, 500)) return Right(resp)
def unbundle(bundle): if isBundle(bundle): return Right( list(map(lambda a: a["resource"], bundle.get("entry", [])))) else: return Left(str(bundle) + " is not a bundle")
def query_records( records, codes, unit, timestamp, clinical_variable, resource_name ): # goes through all the records and finds out the record that user is looking for if records == None: return Right({ "value": None, "certitude": 0, "calculation": "no record found" }) records_filtered = [] for record in records: for c in codes: system = c["system"] code = c["code"] is_regex = c["is_regex"] code2 = record.get("code") if code2 is None: return Left({ "error": f"malformated record: no code", "record": record }) coding2 = code2.get("coding") if coding2 is None: return Left({ "error": f"malformated record: no coding under code", "record": record }) for c2 in coding2: if c2["system"] == system: if (is_regex and re.search(code, "^" + c2["code"] + "$")) or c2["code"] == code: records_filtered.append(record) if len(records_filtered) == 0: from_code = calculation(codes) return Right({ "value": None, "certitude": 0, "calculation": f"no record found code {from_code}" }) else: ts = strtots(timestamp) def key(a): ext_key = extract_key(a) if ext_key is None: return float("inf") else: return abs(strtots(ext_key) - ts) record = min(records_filtered, key=key) keyr = extract_key(record) if keyr is None: ts = None cert = 1 else: ts = extract_key(record) cert = 2 vq = record.get("valueQuantity") if vq is not None: v = vq["value"] from_u = vq.get("unit") if from_u is None: from_u = vq.get("code") mv = convert(v, from_u, unit) if isinstance(mv, Left): return mv else: v = mv.value else: v = True from_u = None c = calculation_template(clinical_variable, resource_name, timestamp, record, unit) return Right({ "value": v, **({ "unit": unit } if unit is not None else { "unit": from_u } if from_u is not None else {}), "certitude": cert, "timestamp": ts, "calculation": c })
def get_location(ctx: dict) -> Right: if not ctx.get('location'): return Right(dict(ctx, location=choice(LOCATIONS))) return Right(ctx)
def pick_poi(ctx: dict) -> Right: collection = ctx.get('collection') pipeline = [{"$sample": dict(size=1)}] poi = list(collection.aggregate(pipeline))[0] poi['_id'] = str(poi['_id']) return Right(dict(ctx, poi=poi))
def get_content(ctx: dict): data = get_nested_value(ctx, ['resp', '_content']) if data: return Right(dict(ctx, content=data.decode('utf-8'))) else: return Left(dict(ctx, error_msg='Response has no content'))
print(justResult) '''In case of type Nothing none function will be apply in the pipeline.''' nothingResult = Nothing() \ .map(lambda word: word + " maybe") \ .map(lambda word: word + " python") \ .map(lambda word: word + " world") \ .map(lambda word: word.upper()) print(nothingResult) ################### # EITHER # ################### '''Using the oslash library we just need to create the Right or Left monad passing the value''' right = Right(1) print(right) left = Left("Error") print(left) '''In case you want to do composition, we need to use [\] [bind] operator and return a Right in the transformation. In case of Left it will not evaluate the lambda and it will pass just the monad''' newValue = right \ .bind(lambda x: Right(x + 1980)) \ .bind(lambda x: x * 10) print(newValue) '''Another way to use composition instead of [bind] it's using [|] operator, less verbose right?''' rightResult = Right("Hello") | \ (lambda word: Right(word + " Functional")) | \ (lambda word: Right(word + " Python")) | \
def test_Result_successful_attribute_is_immutable(self): result = Result(Right('correct.')) with self.assertRaises(AttributeError): del result.successful result.who_cares = 'right?' del result.who_cares # should not raise since not declared immutable