def test_item_timestamps(app_client, load_test_data): """Test created and updated timestamps (common metadata)""" test_item = load_test_data("test_item.json") start_time = datetime.now(timezone.utc) time.sleep(2) # Confirm `created` timestamp resp = app_client.post(f"/collections/{test_item['collection']}/items", json=test_item) item = resp.json() created_dt = parse_datetime(item["properties"]["created"]) assert resp.status_code == 200 assert start_time < created_dt < datetime.now(timezone.utc) time.sleep(2) # Confirm `updated` timestamp item["properties"]["proj:epsg"] = 4326 resp = app_client.put(f"/collections/{test_item['collection']}/items", json=item) assert resp.status_code == 200 updated_item = resp.json() # Created shouldn't change on update assert item["properties"]["created"] == updated_item["properties"][ "created"] assert parse_datetime(updated_item["properties"]["updated"]) > created_dt
def end_date(self) -> Optional[datetime]: values = self.datetime.split("/") if len(values) == 1: return parse_datetime(values[0]) if values[1] == "..": return None return parse_datetime(values[1])
def end_date(self) -> Optional[datetime]: """Extract the end date from the datetime string.""" if not self.datetime: return values = self.datetime.split("/") if len(values) == 1: return parse_datetime(values[0]) if values[1] == "..": return None return parse_datetime(values[1])
async def _run(self, ws): api = StreamingApi(ws, self._state) try: funcs = self._get_handlers(ServiceEventName.startup) await asyncio.gather(*[Func(func, api)() for func in funcs]) async for msg in ws: if msg.type == aiohttp.WSMsgType.TEXT: data = msg.json() event_name = data['event'] payload = data['payload'] server_time = parse_datetime(data['time']) if event_name in self.schemas: data = self.schemas[event_name].parse_obj(payload) else: data = payload await asyncio.gather(*self._call_handlers( event_name, api, data, server_time)) elif msg.type == aiohttp.WSMsgType.CLOSED: break elif msg.type == aiohttp.WSMsgType.ERROR: break await self._cleanup(api) except asyncio.CancelledError: await self._cleanup(api) raise
def impl_AllergyIntolerance_1(inst): assert inst.category == "food" assert ( inst.extension[0].url == "http://hl7.org/fhir/StructureDefinition/allergyintolerance-reasonRefuted" ) assert inst.extension[0].valueCodeableConcept.coding[0].code == "MED" assert (inst.extension[0].valueCodeableConcept.coding[0].display == "Medical Status Altered") assert (inst.extension[0].valueCodeableConcept.coding[0].system == "http://hl7.org/fhir/v3/ActReason") assert inst.id == "allergyintolerance-example-refuted" assert inst.identifier[0].system == "http://acme.com/ids/patients/risks" assert inst.identifier[0].value == "49476534" assert inst.patient.reference == "Patient/example" assert inst.recordedDate == parse_datetime("2014-10-09T14:58:00+11:00") assert inst.recorder.reference == "Practitioner/example" assert inst.status == "refuted" assert inst.substance.coding[0].code == "227493005" assert inst.substance.coding[0].display == "Cashew nuts" assert inst.substance.coding[0].system == "http://snomed.info/sct" assert ( inst.text.div == "<div><p><b>Generated Narrative with Details</b></p><p><b>id</b>: allergyintolerance-example-refuted</p><p><b>identifier</b>: 49476534</p><p><b>recordedDate</b>: 09/10/2014 2:58:00 PM</p><p><b>recorder</b>: <a>Practitioner/example</a></p><p><b>patient</b>: <a>Patient/example</a></p><p><b>substance</b>: Cashew nuts <span>(Details : {SNOMED CT code '227493005' = '227493005', given as 'Cashew nuts'})</span></p><p><b>status</b>: refuted</p><p><b>category</b>: food</p></div>" ) assert inst.text.status == "generated"
async def store_click(ctx, *, link_id, ip, ts, user_agent): cache_key = f'click-{link_id}-{ip}' with await ctx['redis'] as redis: v = await redis.incr(cache_key) if v > 1: return 'recently_clicked' await redis.expire(cache_key, 60) async with ctx['pg'].acquire() as conn: message_id, target = await conn.fetchrow( 'select message_id, url from links where id=$1', link_id) extra = {'target': target, 'ip': ip, 'user_agent': user_agent} if user_agent: ua_dict = ParseUserAgent(user_agent) platform = ua_dict['device']['family'] if platform in {'Other', None}: platform = ua_dict['os']['family'] extra['user_agent_display'] = (( '{user_agent[family]} {user_agent[major]} on ' '{platform}').format(platform=platform, **ua_dict).strip(' ')) ts = parse_datetime(ts) status = 'click' await conn.execute_b( 'insert into events (:values__names) values :values', values=Values(message_id=message_id, status=status, ts=ts, extra=json.dumps(extra)), )
def parse_last_modified(cls, value: Any) -> Optional[datetime]: """Parse last_modified value.""" if value is None: return None if not isinstance(value, str): raise ValueError("must be a string") if value.strip() == "-": return None try: parsed_datetime = parse_datetime(value) if parsed_datetime.tzinfo is None: parsed_datetime = parsed_datetime.replace(tzinfo=timezone.utc) return parsed_datetime except DateTimeError: # Ignore pass try: date_value = parse_date(value) return datetime.combine(date_value, datetime.min.time(), tzinfo=timezone.utc) except DateError: log.error("Unable to parse last_modified value: %s", value) return None
def impl_Device_5(inst): assert inst.contact[0].system == "phone" assert inst.contact[0].value == "ext 4352" assert inst.id == "example" assert inst.identifier[0].system == "http://goodcare.org/devices/id" assert inst.identifier[0].value == "345675" assert inst.identifier[1].type.coding[0].code == "SNO" assert (inst.identifier[1].type.coding[0].system == "http://hl7.org/fhir/identifier-type") assert inst.identifier[1].type.text == "Serial Number" assert inst.identifier[1].value == "AMID-342135-8464" assert inst.lotNumber == "43453424" assert inst.manufacturer == "Acme Devices, Inc" assert inst.model == "AB 45-J" assert inst.note[0].authorReference.reference == "Practitioner/xcda-author" assert inst.note[0].text == "QA Checked" assert inst.note[0].time == parse_datetime("2015-06-28T14:03:32+10:00") assert inst.status == "available" assert ( inst.text.div == "<div><p><b>Generated Narrative with Details</b></p><p><b>id</b>: example</p><p><b>identifier</b>: 345675, Serial Number = AMID-342135-8464</p><p><b>type</b>: ECG <span>(Details : {SNOMED CT code '86184003' = '86184003', given as 'Electrocardiographic monitor and recorder'})</span></p><p><b>note</b>: QA Checked</p><p><b>status</b>: available</p><p><b>manufacturer</b>: Acme Devices, Inc</p><p><b>model</b>: AB 45-J</p><p><b>lotNumber</b>: 43453424</p><p><b>contact</b>: ph: ext 4352</p></div>" ) assert inst.text.status == "generated" assert inst.type.coding[0].code == "86184003" assert inst.type.coding[ 0].display == "Electrocardiographic monitor and recorder" assert inst.type.coding[0].system == "http://snomed.info/sct" assert inst.type.text == "ECG"
def impl_DocumentManifest_1(inst): assert inst.author[0].reference == "#a1" assert inst.contained[0].id == "a1" assert inst.contained[0].name.family[0] == "Dopplemeyer" assert inst.contained[0].name.given[0] == "Sherry" assert (inst.contained[0].practitionerRole[0].managingOrganization.display == "Cleveland Clinic") assert inst.contained[0].practitionerRole[0].role.text == "Primary Surgon" assert inst.contained[0].practitionerRole[0].specialty[ 0].text == "Orthopedic" assert inst.contained[0].telecom[0].system == "email" assert inst.contained[0].telecom[ 0].value == "*****@*****.**" assert inst.content[0].pReference.reference == "DocumentReference/example" assert inst.created == parse_datetime("2004-12-25T23:50:50-05:00") assert inst.description == "Physical" assert inst.id == "example" assert inst.identifier[0].system == "http://example.org/documents" assert inst.identifier[0].value == "23425234234-2347" assert inst.masterIdentifier.system == "http://example.org/documents" assert inst.masterIdentifier.value == "23425234234-2346" assert inst.recipient[0].reference == "Practitioner/xcda1" assert inst.related[0].identifier.system == "http://example.org/documents" assert inst.related[0].identifier.value == "23425234234-9999" assert inst.related[0].ref.reference == "DocumentReference/example" assert inst.source == "urn:oid:1.3.6.1.4.1.21367.2009.1.2.1" assert inst.status == "current" assert inst.subject.reference == "Patient/xcda" assert inst.text.div == "<div>Text</div>" assert inst.text.status == "generated" assert inst.type.text == "History and Physical"
def impl_Communication_1(inst): assert inst.category.coding[0].code == "Alert" assert inst.category.coding[0].system == "http://acme.org/messagetypes" assert inst.category.text == "Alert" assert ( inst.extension[0].url == "http://hl7.org/fhir/StructureDefinition/communication-reasonNotPerformed" ) assert inst.extension[0].valueCodeableConcept.coding[0].code == "EIE" assert (inst.extension[0].valueCodeableConcept.coding[0].display == "entered in error") assert (inst.extension[0].valueCodeableConcept.coding[0].system == "http://hl7.org/fhir/v3/ActReason") assert inst.id == "communication-example" assert inst.identifier[0].system == "urn:oid:1.3.4.5.6.7" assert inst.identifier[0].type.text == "Paging System" assert inst.identifier[0].value == "2345678901" assert ( inst.payload[0].contentString == "Patient 1 has a very high serum potassium value (7.2 mmol/L on 2014-Dec-12 at 5:55 pm)" ) assert inst.payload[ 1].contentReference.reference == "Observation/643666aa12f" assert inst.recipient[0].reference == "Practitioner/21" assert inst.sender.reference == "Device/f001" assert inst.sent == parse_datetime("2014-12-12T18:01:10-08:00") assert inst.status == "suspended" assert inst.subject.reference == "Patient/1" assert inst.text.div == "<div>Patient has very high serum potassium</div>" assert inst.text.status == "generated"
def validate_datetime(cls, v, values): if v == "null": if not values["start_datetime"] and not values["end_datetime"]: raise ValueError( "start_datetime and end_datetime must be specified when datetime is null" ) if isinstance(v, str): return parse_datetime(v) return v
def __eq__(self, other): self.other = other if not isinstance(other, datetime): try: from pydantic.datetime_parse import parse_datetime except ImportError: # pragma: no cover raise ImportError('pydantic is required to use CloseToNow, please run `pip install pydantic`') other = parse_datetime(other) if other.tzinfo: self.now = self.now.replace(tzinfo=timezone.utc) self.match = -self.delta < (self.now - other).total_seconds() < self.delta return self.match
def convert_to_datetime(val: str) -> datetime: constants = { 'now': datetime.utcnow(), 'day': datetime.utcnow() - timedelta(days=1), 'week': datetime.utcnow() - timedelta(days=7), 'month': datetime.utcnow() - timedelta(days=31), '6month': datetime.utcnow() - timedelta(days=31 * 6), 'year': datetime.utcnow() - timedelta(days=365), } if val in constants: return constants[val] return parse_datetime(val)
async def build(cls, request_body: Union[str, bytes], http_client: AsyncClient) -> Optional['SesWebhookInfo']: payload = await sns.verify_webhook(request_body, http_client) if not payload: # happens legitimately for subscription confirmation webhooks return None try: message = json.loads(payload.message) except ValueError: # this can happen legitimately, e.g. when a new configuration set is setup logger.warning('invalid JSON in SNS notification', extra={'data': { 'request': payload.request_data }}) return None event_type = message['eventType'].lower() if event_type not in { 'send', 'delivery', 'open', 'click', 'bounce', 'complaint' }: logger.warning('unknown aws webhook event %s', event_type, extra={'data': { 'request': payload.request_data }}) message_id = message['mail']['messageId'] logger.info('%s for message %s', event_type, message_id) details = message.get(event_type) or {} mail = message.get('mail') or {} tags = mail.get('tags') or {} timestamp = details.get('timestamp') or mail.get('timestamp') if event_type == 'bounce': unsubscribe = details.get('bounceType') == 'Permanent' elif event_type == 'complaint': unsubscribe = True else: unsubscribe = False return cls( message_id=message_id, event_type=event_type, timestamp=timestamp and parse_datetime(timestamp), unsubscribe=unsubscribe, tags={k: v[0] for k, v in tags.items()}, details=details, full_message=message, request_data=payload.request_data, )
def validate(cls, v: Any) -> datetime: if isinstance(v, datetime): d = v else: d = parse_datetime(v) # MongoDB does not store timezone info # https://docs.python.org/3/library/datetime.html#determining-if-an-object-is-aware-or-naive if d.tzinfo is not None and d.tzinfo.utcoffset(d) is not None: raise ValueError("datetime objects must be naive (no timeone info)") # Round microseconds to the nearest millisecond to comply with Mongo behavior microsecs = round(d.microsecond / 1000) * 1000 return d.replace(microsecond=microsecs)
def validate_datetime(cls, v): if "/" in v: values = v.split("/") else: # Single date is interpreted as end date values = ["..", v] dates = [] for value in values: if value == "..": dates.append(value) continue parse_datetime(value) dates.append(value) if ".." not in dates: if parse_datetime(dates[0]) > parse_datetime(dates[1]): raise ValueError( "Invalid datetime range, must match format (begin_date, end_date)" ) return v
def impl_AllergyIntolerance_3(inst): assert inst.category == "food" assert inst.id == "fishallergy" assert inst.identifier[0].system == "http://acme.com/ids/patients/risks" assert inst.identifier[0].value == "49476535" assert inst.patient.reference == "Patient/example" assert inst.recordedDate == parse_datetime("2015-08-06T15:37:31-06:00") assert inst.recorder.reference == "Practitioner/example" assert inst.substance.coding[0].code == "227037002" assert inst.substance.coding[0].display == "Fish - dietary (substance)" assert inst.substance.coding[0].system == "http://snomed.info/sct" assert inst.substance.text == "Allergic to fresh fish. Tolerates canned fish" assert (inst.text.div == """<div> <p>allergy is to fresh fish. Tolerates canned fish</p> <p>recordedDate:2015-08-06T00:00:00-06:00</p> <p>substance:Fish - dietary (substance)</p> </div>""") assert inst.text.status == "additional"
def impl_AllergyIntolerance_2(inst): assert inst.category == "food" assert inst.criticality == "CRITH" assert inst.id == "allergyintolerance-example" assert inst.identifier[0].system == "http://acme.com/ids/patients/risks" assert inst.identifier[0].value == "49476534" assert inst.lastOccurence == "2012-06" assert inst.patient.reference == "Patient/example" assert inst.reaction[0].certainty == "confirmed" assert ( inst.reaction[0].description == "Challenge Protocol. Severe Reaction to 1/8 cashew. Epinephrine administered" ) assert inst.reaction[0].manifestation[0].coding[0].code == "39579001" assert (inst.reaction[0].manifestation[0].coding[0].display == "Anaphylactic reaction") assert (inst.reaction[0].manifestation[0].coding[0].system == "http://snomed.info/sct") assert inst.reaction[0].onset == parse_date("2012-06-12") assert inst.reaction[0].severity == "severe" assert inst.reaction[0].substance.coding[0].code == "C3214954" assert (inst.reaction[0].substance.coding[0].display == "cashew nut allergenic extract Injectable Product") assert (inst.reaction[0].substance.coding[0].system == "http://www.nlm.nih.gov/research/umls/rxnorm") assert inst.reaction[1].certainty == "likely" assert inst.reaction[1].manifestation[0].coding[0].code == "64305001" assert inst.reaction[1].manifestation[0].coding[0].display == "Urticaria" assert (inst.reaction[1].manifestation[0].coding[0].system == "http://snomed.info/sct") assert inst.reaction[1].onset == "2004" assert inst.reaction[1].severity == "moderate" assert inst.recordedDate == parse_datetime("2014-10-09T14:58:00+11:00") assert inst.recorder.reference == "Practitioner/example" assert inst.status == "confirmed" assert inst.substance.coding[0].code == "227493005" assert inst.substance.coding[0].display == "Cashew nuts" assert inst.substance.coding[0].system == "http://snomed.info/sct" assert ( inst.text.div == "<div><p><b>Generated Narrative with Details</b></p><p><b>id</b>: allergyintolerance-example</p><p><b>identifier</b>: 49476534</p><p><b>recordedDate</b>: 09/10/2014 2:58:00 PM</p><p><b>recorder</b>: <a>Practitioner/example</a></p><p><b>patient</b>: <a>Patient/example</a></p><p><b>substance</b>: Cashew nuts <span>(Details : {SNOMED CT code '227493005' = '227493005', given as 'Cashew nuts'})</span></p><p><b>status</b>: confirmed</p><p><b>criticality</b>: CRITH</p><p><b>type</b>: allergy</p><p><b>category</b>: food</p><p><b>lastOccurence</b>: 01/06/2012</p><blockquote><p><b>reaction</b></p><p><b>substance</b>: cashew nut allergenic extract Injectable Product <span>(Details : {RxNorm code 'C3214954' = '??', given as 'cashew nut allergenic extract Injectable Product'})</span></p><p><b>certainty</b>: confirmed</p><p><b>manifestation</b>: Anaphylactic reaction <span>(Details : {SNOMED CT code '39579001' = '39579001', given as 'Anaphylactic reaction'})</span></p><p><b>description</b>: Challenge Protocol. Severe Reaction to 1/8 cashew. Epinephrine administered</p><p><b>onset</b>: 12/06/2012</p><p><b>severity</b>: severe</p></blockquote><blockquote><p><b>reaction</b></p><p><b>certainty</b>: likely</p><p><b>manifestation</b>: Urticaria <span>(Details : {SNOMED CT code '64305001' = '64305001', given as 'Urticaria'})</span></p><p><b>onset</b>: 01/01/2004</p><p><b>severity</b>: moderate</p></blockquote></div>" ) assert inst.text.status == "generated" assert inst.type == "allergy"
def validate(cls, value) -> datetime: """ Validate/parse the datetime """ if isinstance(value, datetime): # It's already a datetime! return value if not isinstance(value, str): raise ValueError(f"string: str expected not {type(value)}") match = Datetime.regex.match(value) # type: ignore if match: kwargs: Dict[str, Union[int, timezone]] = { k: int(v) for k, v in match.groupdict().items() } return datetime(tzinfo=timezone.utc, **kwargs) # type: ignore return datetime_parse.parse_datetime(value)
def test_datetime_parsing(value, result): if result == errors.DateTimeError: with pytest.raises(errors.DateTimeError): parse_datetime(value) else: assert parse_datetime(value) == result
def init_osm_update(ctx): """ Init osmosis folder with configuration files and latest state.txt file before .pbf timestamp """ logging.info("initializing osm update...") session = requests.Session() class OsmState(BaseModel): """ ConfigParser uses lowercased keys "sequenceNumber" from state.txt is renamed to "sequencenumber" """ sequencenumber: int timestamp: datetime def get_state_url(sequence_number=None): base_url = ctx.osm_update.replication_url if sequence_number is None: # Get last state.txt return f'{base_url}/state.txt' else: return f'{base_url}' \ f'/{sequence_number // 1_000_000 :03d}' \ f'/{sequence_number // 1000 % 1000 :03d}' \ f'/{sequence_number % 1000 :03d}.state.txt' def get_state(sequence_number=None): url = get_state_url(sequence_number) resp = session.get(url) resp.raise_for_status() # state file may contain escaped ':' in the timestamp state_string = resp.text.replace('\:', ':') c = configparser.ConfigParser() c.read_string('[root]\n' + state_string) return OsmState(**c['root']) # Init osmosis working directory ctx.run(f'mkdir -p {ctx.update_tiles_dir}') ctx.run(f'touch {ctx.update_tiles_dir}/download.lock') raw_osm_datetime = ctx.run( f'osmconvert {ctx.osm.file} --out-timestamp').stdout osm_datetime = parse_datetime(raw_osm_datetime) # Rewind 2 hours as a precaution osm_datetime -= timedelta(hours=2) last_state = get_state() sequence_number = last_state.sequencenumber sequence_dt = last_state.timestamp for i in range(ctx.osm_update.max_interations): if sequence_dt < osm_datetime: break sequence_number -= 1 state = get_state(sequence_number) sequence_dt = state.timestamp else: logging.error( "Failed to init osm update. " "Could not find a replication sequence before %s", osm_datetime, ) return state_url = get_state_url(sequence_number) ctx.run(f'wget -q "{state_url}" -O {ctx.update_tiles_dir}/state.txt') with open(f'{ctx.update_tiles_dir}/configuration.txt', 'w') as conf_file: conf_file.write(f'baseUrl={ctx.osm_update.replication_url}\n') conf_file.write(f'maxInterval={ctx.osm_update.max_interval}\n')
async def record_email_event(self, raw_message: str): """ record email events """ message = json.loads(raw_message) msg_id = message['mail']['messageId'] r = await self.pg.fetchrow( 'select id, user_id, update_ts from emails where ext_id=$1', msg_id) if not r: return email_id, user_id, last_updated = r event_type = message.get('eventType') extra = None data = message.get(event_type.lower()) or {} if event_type == 'Send': data = message['mail'] elif event_type == 'Delivery': extra = { 'delivery_time': data.get('processingTimeMillis'), } elif event_type == 'Open': extra = { 'ip': data.get('ipAddress'), 'ua': data.get('userAgent'), } elif event_type == 'Click': extra = { 'link': data.get('link'), 'ip': data.get('ipAddress'), 'ua': data.get('userAgent'), } elif event_type == 'Bounce': extra = { 'bounceType': data.get('bounceType'), 'bounceSubType': data.get('bounceSubType'), 'reportingMTA': data.get('reportingMTA'), 'feedbackId': data.get('feedbackId'), 'unsubscribe': data.get('bounceType') == 'Permanent', } elif event_type == 'Complaint': extra = { 'complaintFeedbackType': data.get('complaintFeedbackType'), 'feedbackId': data.get('feedbackId'), 'ua': data.get('userAgent'), 'unsubscribe': True } else: logger.warning('unknown aws webhooks %s', event_type, extra={'data': { 'message': message }}) values = dict(email=email_id, status=event_type) ts = None if data.get('timestamp'): ts = parse_datetime(data['timestamp']) values['ts'] = ts if extra: values['extra'] = json.dumps({k: v for k, v in extra.items() if v}) async with self.pg.acquire() as conn: await conn.execute_b( 'insert into email_events (:values__names) values :values', values=Values(**values)) if not ts: await conn.execute( 'update emails set status=$1, update_ts=CURRENT_TIMESTAMP where id=$2', event_type, email_id) elif last_updated < ts: await conn.execute( 'update emails set status=$1, update_ts=$2 where id=$3', event_type, ts, email_id) if extra and extra.get('unsubscribe'): await conn.execute( 'update users set receive_emails=false where id=$1', user_id) return event_type
def is_datetime(value: Union[datetime, StrBytesIntFloat]) -> bool: try: parse_datetime(value) return isinstance(value, (str, datetime)) except: return False
def convert_to_datetime(s): return parse_datetime(s).astimezone()
def replace_data(m): dt = parse_datetime(m.group()) # WARNING: this means the output is not valid json, but is more readable return f'{m.group()} ({dt:%a %Y-%m-%d %H:%M})'
def test_datetime_parsing(value, result): if type(result) == type and issubclass(result, Exception): with pytest.raises(result): parse_datetime(value) else: assert parse_datetime(value) == result
def impl_DocumentReference_1(inst): assert inst.authenticator.reference == "Organization/organization-example" assert inst.author[0].reference == "Practitioner/xcda1" assert inst.author[1].reference == "#a2" assert inst.contained[0].id == "a2" assert inst.contained[0].name.family[0] == "Smitty" assert inst.contained[0].name.given[0] == "Gerald" assert ( inst.contained[0].practitionerRole[0].managingOrganization.display == "Cleveland Clinic" ) assert inst.contained[0].practitionerRole[0].role.text == "Attending" assert inst.contained[0].practitionerRole[0].specialty[0].text == "Orthopedic" assert inst.content[0].attachment.contentType == "application/hl7-v3+xml" assert inst.content[0].attachment.hash == b"2jmj7l5rSw0yVb/vlWAYkK/YBwk=" assert inst.content[0].attachment.language == "en-US" assert inst.content[0].attachment.size == 3654 assert ( inst.content[0].attachment.url == "http://example.org/xds/mhd/Binary/07a6483f-732b-461e-86b6-edb665c45510" ) assert inst.content[0].format[0].code == "urn:ihe:pcc:handp:2008" assert inst.content[0].format[0].display == "History and Physical Specification" assert inst.content[0].format[0].system == "urn:oid:1.3.6.1.4.1.19376.1.2.3" assert inst.context.encounter.reference == "Encounter/xcda" assert inst.context.event[0].coding[0].code == "T-D8200" assert inst.context.event[0].coding[0].display == "Arm" assert ( inst.context.event[0].coding[0].system == "http://ihe.net/xds/connectathon/eventCodes" ) assert inst.context.facilityType.coding[0].code == "Outpatient" assert inst.context.facilityType.coding[0].display == "Outpatient" assert ( inst.context.facilityType.coding[0].system == "http://www.ihe.net/xds/connectathon/healthcareFacilityTypeCodes" ) assert inst.context.period.end == parse_datetime("2004-12-23T08:01:00+11:00") assert inst.context.period.start == parse_datetime("2004-12-23T08:00:00+11:00") assert inst.context.practiceSetting.coding[0].code == "General Medicine" assert inst.context.practiceSetting.coding[0].display == "General Medicine" assert ( inst.context.practiceSetting.coding[0].system == "http://www.ihe.net/xds/connectathon/practiceSettingCodes" ) assert inst.context.related[0].identifier.system == "urn:ietf:rfc:3986" assert ( inst.context.related[0].identifier.value == "urn:oid:1.3.6.1.4.1.21367.2005.3.7.2345" ) assert inst.context.related[0].ref.reference == "Patient/xcda" assert inst.context.sourcePatientInfo.reference == "Patient/xcda" assert inst.created == parse_datetime("2005-12-24T09:35:00+11:00") assert inst.custodian.reference == "Organization/organization-example" assert inst.description == "Physical" assert inst.docStatus.coding[0].code == "preliminary" assert inst.docStatus.coding[0].display == "preliminary" assert inst.docStatus.coding[0].system == "http://hl7.org/fhir/composition-status" assert inst.id == "example" assert inst.identifier[0].system == "urn:ietf:rfc:3986" assert inst.identifier[0].value == "urn:oid:1.3.6.1.4.1.21367.2005.3.7.1234" assert inst.indexed == parse_datetime("2005-12-24T09:43:41+11:00") assert inst.masterIdentifier.system == "urn:ietf:rfc:3986" assert inst.masterIdentifier.value == "urn:oid:1.3.6.1.4.1.21367.2005.3.7" assert inst.relatesTo[0].code == "appends" assert inst.relatesTo[0].target.reference == "DocumentReference/example" assert inst.securityLabel[0].coding[0].code == "V" assert inst.securityLabel[0].coding[0].display == "very restricted" assert ( inst.securityLabel[0].coding[0].system == "http://hl7.org/fhir/v3/Confidentiality" ) assert inst.status == "current" assert inst.subject.reference == "Patient/xcda" assert ( inst.text.div == "<div><p><b>Generated Narrative with Details</b></p><p><b>id</b>: example</p><p><b>contained</b>: </p><p><b>masterIdentifier</b>: urn:oid:1.3.6.1.4.1.21367.2005.3.7</p><p><b>identifier</b>: urn:oid:1.3.6.1.4.1.21367.2005.3.7.1234</p><p><b>subject</b>: <a>Patient/xcda</a></p><p><b>type</b>: Outpatient Note <span>(Details : {LOINC code '34108-1' = 'Outpatient Note', given as 'Outpatient Note'})</span></p><p><b>class</b>: History and Physical <span>(Details : {http://ihe.net/xds/connectathon/classCodes code 'History and Physical' = '??', given as 'History and Physical'})</span></p><p><b>author</b>: <a>Practitioner/xcda1</a>, id: a2; Gerald Smitty </p><p><b>custodian</b>: <a>Organization/organization-example</a></p><p><b>authenticator</b>: <a>Organization/organization-example</a></p><p><b>created</b>: 24/12/2005 9:35:00 AM</p><p><b>indexed</b>: 24/12/2005 9:43:41 AM</p><p><b>status</b>: current</p><p><b>docStatus</b>: preliminary <span>(Details : {http://hl7.org/fhir/composition-status code 'preliminary' = 'Preliminary', given as 'preliminary'})</span></p><h3>RelatesTos</h3><table><tr><td>-</td><td><b>Code</b></td><td><b>Target</b></td></tr><tr><td>*</td><td>appends</td><td><a>DocumentReference/example</a></td></tr></table><p><b>description</b>: Physical</p><p><b>securityLabel</b>: very restricted <span>(Details : {http://hl7.org/fhir/v3/Confidentiality code 'V' = 'very restricted', given as 'very restricted'})</span></p><h3>Contents</h3><table><tr><td>-</td><td><b>Attachment</b></td><td><b>Format</b></td></tr><tr><td>*</td><td/><td>History and Physical Specification (Details: urn:oid:1.3.6.1.4.1.19376.1.2.3 code urn:ihe:pcc:handp:2008 = '??', stated as 'History and Physical Specification')</td></tr></table><blockquote><p><b>context</b></p><p><b>encounter</b>: <a>Encounter/xcda</a></p><p><b>event</b>: Arm <span>(Details : {http://ihe.net/xds/connectathon/eventCodes code 'T-D8200' = '??', given as 'Arm'})</span></p><p><b>period</b>: 23/12/2004 8:00:00 AM --> 23/12/2004 8:01:00 AM</p><p><b>facilityType</b>: Outpatient <span>(Details : {http://www.ihe.net/xds/connectathon/healthcareFacilityTypeCodes code 'Outpatient' = '??', given as 'Outpatient'})</span></p><p><b>practiceSetting</b>: General Medicine <span>(Details : {http://www.ihe.net/xds/connectathon/practiceSettingCodes code 'General Medicine' = '??', given as 'General Medicine'})</span></p><p><b>sourcePatientInfo</b>: <a>Patient/xcda</a></p><h3>Relateds</h3><table><tr><td>-</td><td><b>Identifier</b></td><td><b>Ref</b></td></tr><tr><td>*</td><td>urn:oid:1.3.6.1.4.1.21367.2005.3.7.2345</td><td><a>Patient/xcda</a></td></tr></table></blockquote></div>" ) assert inst.text.status == "generated" assert inst.type.coding[0].code == "34108-1" assert inst.type.coding[0].display == "Outpatient Note" assert inst.type.coding[0].system == "http://loinc.org"
async def update_user( user_data: DotDict, update_data: Dict[str, Any], is_new: bool = False, is_registering: bool = False, is_admin: bool = False, is_self: bool = False, no_registration: bool = False, ): if 'sub' in update_data or '_id' in update_data or 'picture' in update_data: raise HTTPException(400, f"Cannot modify 'sub', '_id' or 'picture'") was_active = user_data.get('active', False) reset_user_cache = False if is_new: assert '_id' not in user_data user_data['_id'] = generate_token(48) if 'password' in update_data: if not isinstance(update_data['password'], str): raise HTTPException(400, "'password' must be a string") _validate_property_write('password', is_self, is_admin) if is_self and not is_registering and user_data.get( 'password') is not None: if 'old_password' not in update_data: raise HTTPException( 400, f"Need {repr('old_password')} for setting password") if not isinstance(update_data['old_password'], str): raise HTTPException(400, f"{repr('old_password')} is not a string") is_valid, _ = verify_and_update(update_data['old_password'], user_data['password']) if not is_valid: raise HTTPException(401, "Old password does not match") try: user_data['password'] = create_password(update_data['password']) del update_data['password'] except PasswordLeakedException: raise HTTPException( 400, "Password is leaked and cannot be used. See https://haveibeenpwned.com/" ) async def send_mail(): pass if is_registering and update_data.get( 'email', user_data['email']) == user_data['email']: user_data['email_verified'] = True elif 'email' in update_data: if not isinstance(update_data['email'], str): raise HTTPException(400, "'email' must be a string") _validate_property_write('email', is_self, is_admin) if not is_email(update_data['email'], check_dns=True): raise HTTPException(400, "E-Mail address not accepted") if await async_user_collection.count_documents( {'email': update_data['email']}, limit=1) != 0: raise HTTPException( 400, "E-Mail address already in use, please use existing account") new_mail = update_data['email'] locale = update_data.get( 'locale', user_data.get('locale', config.oauth2.user.properties['locale'].default)) if locale is None: locale = 'en_us' tz = _get_tz(update_data.get('zoneinfo', user_data.get('zoneinfo'))) del update_data['email'] if is_new and not no_registration: user_data['email'] = new_mail user_data['email_verified'] = False token_valid_until = int(time.time() + config.manager.token_valid.registration) user_data['registration_token'] = create_token( user_data['_id'], token_valid_until) async def send_mail(): await async_send_mail_register(user_data, token_valid_until, locale, tz) elif not is_admin: token_valid_until = int(time.time() + config.manager.token_valid.email_set) user_data['email_verification_token'] = create_token( new_mail, token_valid_until) if is_registering: user_data['email'] = new_mail user_data['email_verified'] = False async def send_mail(): await async_send_mail_verify(locale, new_mail, user_data, token_valid_until, tz) else: user_data['email'] = new_mail user_data['email_verified'] = False if 'access_tokens' in update_data: if not isinstance(update_data['access_tokens'], list): raise HTTPException(400, "'access_tokens' must be a list") try: access_tokens = [ ValidateAccessToken.validate(val) for val in update_data['access_tokens'] ] except ValueError as err: raise HTTPException(400, str(err)) _validate_property_write('access_tokens', is_self, is_admin) existing_access_tokens = [ UserPasswordAccessToken.validate(access_token) for access_token in user_data.get('access_tokens', []) ] existing_access_tokens_by_id = { existing_access_token.id: existing_access_token for existing_access_token in existing_access_tokens } new_access_tokens = [] for access_token in access_tokens: if access_token.id is not None: store_token = existing_access_tokens_by_id.get(access_token.id) if store_token is None: raise HTTPException(400, f"Invalid token ID {access_token.id}") store_token.description = access_token.description if access_token.token is not None: store_token.token = access_token.token else: store_token = UserPasswordAccessToken( id=generate_token(24), description=access_token.description, token=access_token.token, ) new_access_tokens.append(store_token) del update_data['access_tokens'] user_data['access_tokens'] = [ access_token.dict() for access_token in new_access_tokens ] if 'groups' in update_data: if await _update_groups( user_data, update_data, property='groups', is_self=is_self, is_admin=is_admin, existence_check_property=None, groups_add_property='members', groups_pull_properties=( 'members', 'email_allowed_forward_members', 'email_forward_members', 'email_postbox_access_members', ), members_pull_properties=( 'email_allowed_forward_members', 'email_forward_members', 'email_postbox_access_members', ), ): reset_user_cache = True if 'email_allowed_forward_groups' in update_data: await _update_groups( user_data, update_data, property='email_allowed_forward_groups', is_self=is_self, is_admin=is_admin, existence_check_property='groups', groups_add_property='email_allowed_forward_members', groups_pull_properties=('email_allowed_forward_members', 'email_forward_members'), members_pull_properties=('email_forward_members', )) if 'email_forward_groups' in update_data: await _update_groups( user_data, update_data, property='email_forward_groups', is_self=is_self, is_admin=is_admin, existence_check_property='email_allowed_forward_groups', groups_add_property='email_forward_members', groups_pull_properties=('email_forward_members', ), ) if 'email_postbox_access_groups' in update_data: await _update_groups( user_data, update_data, property='email_postbox_access_groups', is_self=is_self, is_admin=is_admin, existence_check_property='groups', groups_add_property='email_postbox_access_members', groups_pull_properties=('email_postbox_access_members', ), ) for key, value in update_data.items(): _validate_property_write(key, is_self, is_admin) prop = config.oauth2.user.properties[key] if prop.write_once and user_data.get(key) is not None: raise HTTPException(400, f"{repr(key)} can only be set once") if not value and not prop.required and key in user_data: del user_data[key] if prop.type in (UserPropertyType.str, UserPropertyType.multistr, UserPropertyType.token): if not isinstance(value, str): raise HTTPException( 400, f"{repr(key)}={repr(value)} is not a string") if prop.template is not None: raise HTTPException(400, f"{repr(key)}={repr(value)} is generated") if prop.format is not None: regex = get_regex(prop.format) if not regex.fullmatch(value): raise HTTPException( 400, f"{repr(key)}={repr(value)} does not match pattern {repr(regex.pattern)}" ) user_data[key] = value elif prop.type == UserPropertyType.int: if isinstance(value, float): if not value.is_integer(): raise HTTPException( 400, f"{repr(key)}={repr(value)} is not an integer") value = int(value) if not isinstance(value, int): raise HTTPException( 400, f"{repr(key)}={repr(value)} is not an integer") user_data[key] = value elif prop.type == UserPropertyType.bool: if not isinstance(value, bool): raise HTTPException( 400, f"{repr(key)}={repr(value)} is not a boolean") user_data[key] = value elif prop.type == UserPropertyType.datetime: if not isinstance(value, str): raise HTTPException( 400, f"{repr(key)}={repr(value)} is not a datetime string") try: parse_datetime(value) user_data[key] = value except ValueError: raise HTTPException( 400, f"{repr(key)}={repr(value)} is not a datetime string") elif prop.type == UserPropertyType.date: if not isinstance(value, str): raise HTTPException( 400, f"{repr(key)}={repr(value)} is not a date string") try: parse_date(value) user_data[key] = value except ValueError: raise HTTPException( 400, f"{repr(key)}={repr(value)} is not a datetime string") elif prop.type == UserPropertyType.enum: if not isinstance(value, str): raise HTTPException( 400, f"{repr(key)}={repr(value)} is not a string") assert prop.values is not None values = [enum_value.value for enum_value in prop.values] if value not in values: raise HTTPException( 400, f"{repr(key)}={repr(value)} is not a valid enum value") user_data[key] = value else: raise NotImplementedError(f"{repr(prop.type)}") # Set others to default if is_new or is_registering: for key, value in config.oauth2.user.properties.items(): if value.default is not None and key not in user_data: user_data[key] = value.default # Activate the user after registration if is_registering: user_data['active'] = True # Apply all templates and validate required, when not active if user_data.get('active', False): # Validate that all required variables are present for key, value in config.oauth2.user.properties.items(): if value.required and user_data.get(key) is None: raise HTTPException(400, f"Missing {repr(key)}") # Apply templates (they should not be required) for key, value in config.oauth2.user.properties.items(): if (value.type == UserPropertyType.str and value.template is not None and (not value.write_once or not user_data.get(key))): assert "'''" not in value.template, f"Invalid ''' in template: {value.template}" user_data[key] = eval( f"f'''{value.template}'''", { 'make_username': make_username, 'config': config }, user_data, ) user_data['updated_at'] = int(time.time()) User.validate(user_data) if is_new: await async_user_collection.insert_one(user_data) else: await async_user_collection.replace_one({'_id': user_data['_id']}, user_data) if user_data.get('active', False): if reset_user_cache: await async_client_user_cache_collection.delete_many( {'user_id': user_data['_id']}) else: await async_client_user_cache_collection.update_many( {'user_id': user_data['_id']}, {'$set': { 'last_modified': user_data['updated_at'] }}, ) elif was_active: await async_client_user_cache_collection.delete_many( {'user_id': user_data['_id']}) await async_token_collection.delete_many({'user_id': user_data['_id']}) await async_session_collection.delete_many( {'user_id': user_data['_id']}) await async_authorization_code_collection.delete_many( {'user_id': user_data['_id']}) elif reset_user_cache: await async_client_user_cache_collection.delete_many( {'user_id': user_data['_id']}) # Last: Send the email if there is one await send_mail()
def datetime_verifier(raw_data): return parse_datetime(raw_data)
def validate(cls, v: Any) -> datetime: return datetime.fromtimestamp(parse_datetime(v).timestamp())