def test_study_filtering( self, api, account, readonly_study, readonly_study2, ): """Test study list filtering.""" # name in stady2 patient_name = 'AAAA' filt = Filter( field_name='patient_name', condition=FilterCondition.equals, value=patient_name, ) studies = api \ .Study \ .list() \ .only({'study': ['patient_name']}) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, account.account.namespace_id, ), ) \ .filter_by(filt) \ .all() assert len(list(studies[:3])) == 1 assert studies.first().patient_name == patient_name
async def test_study_filtering( self, async_api, async_account, async_readonly_study, async_readonly_study2, ): """Test study list filtering.""" # name in study2 patient_name = 'AAAA' filt = Filter( field_name='patient_name', condition=FilterCondition.equals, value=patient_name, ) studies_iterator = async_api \ .Study \ .list() \ .only({'study': ['patient_name']}) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, async_account.account.namespace_id, ), ) \ .filter_by(filt) \ .all() studies = [] async for study in studies_iterator[:3]: studies.append(study) assert len(study) == 1 assert (await studies_iterator.first()).patient_name == patient_name
async def test_study_sorting( self, async_api, async_account, async_readonly_study, async_readonly_study2, ): """Test study list sorting.""" sorter = Sorter( field_name='patient_name', order=SortingOrder.ascending, ) studies_geneartor = async_api \ .Study \ .list() \ .only({'study': ['uuid']}) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, async_account.account.namespace_id, ), ) \ .sort_by(sorter) \ .all() studies = [] async for study in studies_geneartor: studies.append(study.uuid) r_sorter = Sorter( field_name='patient_name', order=SortingOrder.descending, ) r_studies_geneartor = async_api \ .Study \ .list() \ .only({'study': ['uuid']}) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, async_account.account.namespace_id, ), ) \ .sort_by(r_sorter) \ .all() r_studies = [] async for study in r_studies_geneartor: # NOQA:WPS440 r_studies.append(study.uuid) assert list(reversed(studies)) == r_studies
def test_filter_with_different_timezones(self, query): """Test filter with different timezones.""" mtz = pytz.timezone('Europe/Moscow') value = mtz.localize(datetime(2020, 1, 2, 3, 4, 5)) query.filter_by(Filter('field', FilterCondition.equals, value)) with pytest.raises(ValueError) as exc_info: mtz = pytz.timezone('America/Los_Angeles') value = mtz.localize(datetime(2020, 1, 2, 3, 4, 5)) query.filter_by(Filter('field', FilterCondition.equals, value)) assert str(exc_info.value, ) == 'Use one timezone for all datetimes in requtest'
async def async_account(async_api): """Get account. :param async_api: ambra async_api :yields: test account :raises RuntimeError: On deleted account with existing studies :raises TimeoutError: Time for waiting account deletion is out """ account_name = settings.ASYNC_TEST_ACCOUNT_NAME try: account, user = await async_create_account(async_api, account_name) except DuplicateName: logger.error('Duplicated account: %s', account_name) account = await async_api \ .Account \ .list() \ .filter_by( Filter( 'name', FilterCondition.equals, account_name, ), ).first() if account is None: raise RuntimeError('Account duplicated but not exists') await async_clear_studies(async_api, account) await async_delete_account(async_api, account) account, user = await async_create_account(async_api, account_name) yield UserParams( account=account, user=user, ) await async_delete_account(async_api, account) start = monotonic() while True: if monotonic() - start >= settings.API['account_deletion_timeout']: raise TimeoutError('Account still exists') account = await async_api \ .Account \ .list() \ .filter_by( Filter( 'name', FilterCondition.equals, account_name, ), ).first() if account is None: return await sleep(settings.API['account_deletion_check_interval'])
def test_study_sorting( self, api, account, readonly_study, readonly_study2, ): """Test study list sorting.""" sorter = Sorter( field_name='patient_name', order=SortingOrder.ascending, ) studies = api \ .Study \ .list() \ .only({'study': ['uuid']}) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, account.account.namespace_id, ), ) \ .sort_by(sorter) \ .all() studies = [study.uuid for study in studies] r_sorter = Sorter( field_name='patient_name', order=SortingOrder.descending, ) r_studies = api \ .Study \ .list() \ .only({'study': ['uuid']}) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, account.account.namespace_id, ), ) \ .sort_by(r_sorter) \ .all() r_studies = [study.uuid for study in r_studies] assert list(reversed(studies)) == r_studies
async def test_study_list_only( self, async_api, async_account, async_readonly_study, ): """Test study list sorting.""" studies_query = async_api \ .Study \ .list() \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, async_account.account.namespace_id, ), ) \ .only({'study': ['uuid']}) \ .all() studies = [] async for study_obj in studies_query: studies.append(study_obj) assert len(list(studies)) == 1 study = await studies_query.first() assert 'uuid' in study assert len(study) == 1
async def test_study_list( self, async_api, async_account, async_readonly_study, ): """Test study list.""" query = async_api \ .Study \ .list() \ .set_rows_in_page(5000) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, async_account.account.namespace_id, ), ) \ .all() studies = [] async for study in query: studies.append(study) assert len(studies) == 1 studies = [] async for study in query[:3]: # NOQA:WPS440 studies.append(study) assert len(studies) == 1 studies = [] async for study in query[1:4]: # NOQA:WPS440 studies.append(study) assert len(studies) == 0 # NOQA:WPS507
def account_studies(api, account) -> List[Box]: """List of account studies. :param api: api :param account: account :return: list of studies """ account_namespaces = [account.namespace_id] group_namespaces = [ group.namespace_id for group in api.Group.list(account_id=account.uuid).only(Group.namespace_id).all() ] account_namespaces.extend(group_namespaces) # Method study list does not support in_condition filtering for namespace ! acc_studies = [] for account_namespace in account_namespaces: studies = api \ .Study \ .list() \ .filter_by( Filter( field_name='phi_namespace', condition=FilterCondition.equals, value=account_namespace, ), ).all() acc_studies.extend(list(studies)) return acc_studies
def test_study_list_customfields_filtering( self, api, account, readonly_study, add_customfield, ): """Test study list customfields_filtering.""" add_customfield(name='cfname', object='Study', type='text') study = api \ .Study \ .list() \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, account.account.namespace_id, ), ) \ .first() assert len(study.customfields) == 1 customfields = list(study.customfields.filter_by( {'name': 'cfname'}, ), ) assert len(customfields) == 1 customfield = customfields[0] assert customfield.type == 'text' customfields = study.customfields customfield = customfields.get_by_name('cfname') assert customfield is not None customfield = customfields.get_by_uuid(customfield.uuid) assert customfield is not None
async def async_account_studies(async_api, account) -> List[Box]: """List of account studies. :param async_api: async_api :param account: account :return: list of studies """ account_namespaces = [account.namespace_id] group_namespaces = [] query = async_api \ .Group \ .list(account_id=account.uuid) \ .only(Group.namespace_id).all() async for group in query: group_namespaces.append(group.namespace_id) account_namespaces.extend(group_namespaces) # Method study list does not support in_condition filtering for namespace ! acc_studies = [] for account_namespace in account_namespaces: query = async_api \ .Study \ .list() \ .filter_by( Filter( field_name='phi_namespace', condition=FilterCondition.equals, value=account_namespace, ), ).all() async for study in query: acc_studies.append(study) return acc_studies
def storage_cluster(api, request): """Specific storage cluster. :param api: api :param request: pytest request :raises RuntimeError: Unknown cluster name :return: cluster box """ cluster_name = request.param cluster = None if cluster_name != 'DEFAULT': cluster = QueryOPF( api=api, url='/cluster/list', request_data={}, errors_mapping={}, paginated_field='clusters', required_sid=True, ).filter_by(Filter( 'name', FilterCondition.equals, cluster_name, )).first() if cluster is None: raise RuntimeError( 'Unknown cluster name {name}'.format(name=cluster_name), ) return cluster
async def async_clear_studies(async_api, account): """Delete account studies. :param async_api: async_api :param account: account """ account_namespaces = [account.namespace_id] group_namespaces = [] query = async_api \ .Group \ .list(account_id=account.uuid) \ .only(Group.namespace_id) \ .all() async for group in query: group_namespaces.append(group.namespace_id) account_namespaces.extend(group_namespaces) # Method study list does not support in_condition filtering for namespace ! # So delete studies in loop for account_namespace in account_namespaces: query = async_api \ .Study \ .list() \ .filter_by( Filter( field_name='phi_namespace', condition=FilterCondition.equals, value=account_namespace, ), ).all() async for study in query: study_uid = study.uuid logger.error('Remove undeleted study %s', study_uid) await async_api.Study.delete(uuid=study_uid).get()
def test_filter_by_list(self, query): """Test filter by list value.""" value = ['value', datetime(2000, 1, 2, 3, 4, 5)] query.filter_by(Filter('field', FilterCondition.equals, value)) assert 'filter.field.equals' in query.request_args.data assert query.request_args.data['filter.field.equals'] \ == '["value", "2000-01-02 03:04:05"]'
def _filter_with_seq(self, values, condition, full_name=False): # check value type if not isinstance(values, Iterable): raise ValueError('Value is not iterable') field_name = self._full_name if full_name is True else self._name return Filter( field_name=field_name, condition=condition, value=json.dumps(values), )
def test_study_list_only(self, api, account, readonly_study): """Test study list sorting.""" studies = api \ .Study \ .list() \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, account.account.namespace_id, ), ) \ .only(Study.uuid) \ .all() assert len(list(studies)) == 1 study = studies.first() assert 'uuid' in study assert len(study) == 1 studies = api \ .Study \ .list() \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, account.account.namespace_id, ), ) \ .only( [ Study.uuid, Study.patient_name, ], ) \ .all() assert len(list(studies)) == 1 study = studies.first() assert 'uuid' in study assert 'patient_name' in study assert len(study) == 2
def _standart_filter( self, value, condition, full_name=False, ): value = self._field.for_request(value) field_name = self._full_name if full_name is True else self._name return Filter( field_name=field_name, condition=condition, value=value, )
def test_readonly_study_fixture(self, api, account, readonly_study): """Test readonly fixture.""" study_uid = '1.2.840.10008.1.142353.149743743.367518058.1111111111' # NOQA:E501 assert readonly_study.image_count == 3 assert readonly_study.study_uid == study_uid studies = api \ .Study \ .list() \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, account.account.namespace_id, ), ).all() assert len(list(studies)) == 1
def test_filter_by_dt_with_fixed_timezone_negative_offset(self, query): """Test filter by dt with fixed timezone negative offset. utcoffset = timedelta tzname = None zone = None """ fixed_offset_timezone = pytz.FixedOffset(-60 * 3) value = datetime(2000, 1, 2, 3, 4, 5, tzinfo=fixed_offset_timezone) assert str(value) == '2000-01-02 03:04:05-03:00' query.filter_by(Filter('field', FilterCondition.equals, value)) assert 'filter.field.equals' in query.request_args.data assert query.request_args.data['filter.field.equals'] == str( value.replace(tzinfo=None, ), ) assert 'filter.tz' in query.request_args.data assert query.request_args.data['filter.tz'] == '-03:00'
def test_filter_by_dt_with_offset_from_str(self, query): """Test filter by dt with offset from str. utcoffset = timedelta tzname = UTC+03:00 not zone """ value = datetime.strptime( '2000-01-02 03:04:05+0300', '%Y-%m-%d %H:%M:%S%z', ) query.filter_by(Filter('field', FilterCondition.equals, value)) assert 'filter.field.equals' in query.request_args.data assert query.request_args.data['filter.field.equals'] == str( value.replace(tzinfo=None, ), ) assert 'filter.tz' in query.request_args.data assert query.request_args.data['filter.tz'] == '+03:00'
def like(self, value, full_name=True): """Get like filter. :param value: filtering value :param full_name: use full name for filtering :raises ValueError: value is not string :return: Filter """ if self._field._python_type != str: raise ValueError('Use like for not string field') # check value type str(value) field_name = self._full_name if full_name is True else self._name return Filter( field_name=field_name, condition=FilterCondition.like, value=value, )
def test_filter_by_dt_with_timezone(self, query): """Test filter by dt with offset from str. utcoffset = timedelta tzname = LMT zone = Europe/Moscow timezone have tzname, utcoffset, but not zone """ mtz = pytz.timezone('Europe/Moscow') # Not value datetime(..., tzinfo=mtz) # https://stackoverflow.com/questions/1379740/pytz-localize-vs-datetime-replace value = mtz.localize(datetime(2020, 1, 2, 3, 4, 5)) query.filter_by(Filter('field', FilterCondition.equals, value)) assert 'filter.field.equals' in query.request_args.data assert query.request_args.data['filter.field.equals'] == str( value.replace(tzinfo=None, ), ) assert 'filter.tz' in query.request_args.data assert query.request_args.data['filter.tz'] == '+03:00'
def test_study_list_in( self, api, account, readonly_study, ): """Test study list.""" study = api \ .Study \ .list() \ .filter_by( Filter( 'phi_namespace', FilterCondition.in_condition, [account.account.namespace_id, 'abcdefg'], ), ) \ .first() assert study
def test_study_filtering_boolean_field( self, api, account, readonly_study, ): """Test study list boolean field.""" studies = api \ .Study \ .list() \ .filter_by(Study.phantom == 0) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, account.account.namespace_id, ), ) \ .only({'study': ['patient_name']}) \ .all() assert len(list(studies[:3])) == 1
def test_study_list( self, api, account, readonly_study, ): """Test study list.""" studies = api \ .Study \ .list() \ .set_rows_in_page(5000) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, account.account.namespace_id, ), ) \ .all() assert len(list(studies)) == 1 assert len(list(studies[:3])) == 1 assert len(list(studies[1:4])) == 0 # NOQA:WPS507
async def test_study_list_get( self, async_api, async_account, async_readonly_study, ): """Test study list get.""" get_result = await async_api \ .Study \ .list() \ .set_rows_in_page(5000) \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, async_account.account.namespace_id, ), ) \ .get() assert 'more' in get_result assert 'studies' in get_result assert 'page' in get_result
def test_study_filtering_with_dt( self, api, readonly_study, ): """Test study filtering with dt.""" created_dt = datetime.strptime( # Hack for timezone format readonly_study.created + '00', # NOQA:WPS336 '%Y-%m-%d %H:%M:%S.%f%z', ) # we use tzinfo, but shift dt from utc created_dt = created_dt.replace(tzinfo=None) - timedelta(hours=3) created_dt = pytz.timezone('Europe/Moscow').localize(created_dt) study = api.Study.list() \ .filter_by( Filter( 'created', FilterCondition.equals, created_dt, ), ) \ .first() assert study
async def test_async_readonly_study_fixture( self, async_api, async_account, async_readonly_study, ): """Test readonly fixture.""" study_uid = '1.2.840.10008.1.142353.149743743.367518058.1111111111' # NOQA:E501 assert async_readonly_study.image_count == 3 assert async_readonly_study.study_uid == study_uid studies_generator = async_api \ .Study \ .list() \ .filter_by( Filter( 'phi_namespace', FilterCondition.equals, async_account.account.namespace_id, ), ).all() studies = [] async for study in studies_generator: studies.append(study) assert len(studies) == 1
async def async_create_account( async_api, account_name: str, ) -> Tuple[Box, Box]: """Create new account. :param async_api: async_api :param account_name: account name :raises RuntimeError: Cant find account :return: user params """ # If account exists - raise DuplicateName error await AsyncQueryO( api=async_api, url='/account/add', request_data={ 'name': account_name, }, errors_mapping={ 'DUPLICATE_NAME': DuplicateName(), }, required_sid=True, ).get() account = await async_api \ .Account \ .list() \ .filter_by( Filter( 'name', FilterCondition.equals, account_name, ), ).first() if account is None: raise RuntimeError('Cant find test account') # set role permissions admin_role = await async_api \ .Role \ .list(account_id=account.uuid) \ .filter_by( Filter( 'name', FilterCondition.equals, 'Administrator', ), ).first() if admin_role is None: raise RuntimeError('Cant find admin role') await async_api.Role.set( uuid=admin_role.uuid, permissions=json.dumps( { 'study_delete': 1, 'study_duplicate': 1, 'study_split': 1, 'study_merge': 1, 'study_delete_image': 1, 'customcode_view': 1, 'customcode_edit': 1, 'customcode_deploy': 1, }, ), ).get() user = await async_api.User.get(account_id=account.uuid).get() logger.info('Created account %s', account.name) return (account, user)
def test_filter_by_string_value(self, query): """Test filter by string value.""" value = 'value' query.filter_by(Filter('field', FilterCondition.equals, value)) assert 'filter.field.equals' in query.request_args.data assert query.request_args.data['filter.field.equals'] == 'value'