def test_unicode_pattern_mult_cust(self): assert Unicode(pattern='a').Attributes.pattern == 'a' assert Unicode(pattern='a')(5).Attributes.pattern == 'a'
def test_unicode_nullable_mult_cust_true(self): assert Unicode(nullable=True).Attributes.nullable == True assert Unicode(nullable=True)(5).Attributes.nullable == True
class WFMPortalService(DjangoServiceBase): """WEB API""" __in_header__ = AuthDataHeader """ Создание заявки на аутсорсинг персонала """ @rpc(Unicode(sub_name='guid', min_occurs=1, nillable=False), HeadquaterSoapModel.customize(min_occurs=0, nillable=False), Date(sub_name='start'), Date(sub_name='end'), OrganizationSoapModel, AgencySoapModel, Unicode(sub_name='state', min_occurs=1, nillable=False), Array(ShiftSoapModel), Unicode(sub_name='comments', min_occurs=0, nillable=False), Unicode(sub_name='user_name', min_occurs=0, nillable=False), Unicode(sub_name='email', min_occurs=0, nillable=False), _returns=Unicode, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def setOutsourcingRequest(ctx, guid, headquater, start, end, organization, agency, state, shifts, comments, user_name, email): auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # TODO remove if not headquater: db_headquarter = open_headquarter_by_code('mvideo') # Магазин, сформировавший запрос if headquater: db_headquarter = open_headquarter_by_code(headquater.code) db_organization = open_organization_by_code( organization.code, db_headquarter) else: db_organization = open_organization_by_code( organization.code, None) db_headquarter = db_organization.headquater if not db_headquarter: raise CustomError( f'REQUEST {guid}: no headquater with code {headquater.code}') if not db_organization: raise CustomError( f'REQUEST {guid}: no organiztion with code {organization.code}' ) # Агентство, в котором запрашиваем аутсорсинг db_agency = open_agency_by_code(agency.code, None) if not db_agency: raise CustomError( f'REQUEST {guid}: no agency with code {agency.code}') # Принимаем запросы только в состоянии launched, повторно запросы и запросы без смен не обрабатываем if state != 'launched': raise CustomError( f'REQUEST {guid}: state {state} is differ then launched') out_req = OutsourcingRequest.objects.filter(guid=guid).first() if out_req or not shifts: return {'result': 'ok'} # Создаем объект запроса if not comments: comments = '' if not user_name: user_name = '' if not email: email = '' out_req = OutsourcingRequest.objects.create( guid=guid, headquater=db_headquarter, organization=db_organization, agency=db_agency, state='accepted', start=start, end=end, comments=comments, user_name=user_name, email=email) # Создаем связанные с запросом смены for s in shifts: try: job = Job.objects.get(code=s.job.code) except Job.DoesNotExist: raise CustomError( f'REQUEST {guid}, SHIFT {s.guid}: no job with code {s.job.code}' ) if s.start > s.end: raise CustomError( f'REQUEST {guid}, SHIFT {s.guid}: start > end') if s.worktime < 0: raise CustomError( f'REQUEST {guid}, SHIFT {s.guid}: worktime = {s.worktime} < 0' ) OutsourcingShift.objects.create(guid=s.guid, headquater=db_headquarter, state=s.state, start=s.start, end=s.end, worktime=s.worktime, job=job, request=out_req, agency=db_agency, start_date=s.start) # Создаем и отправляем уведомления о новой заявке make_notify_data(out_req, 'agency', 'wait_req_template') return {'result': 'ok'} """ Получение данных по запросам, чей статус был обновлен раньше определенного времени """ @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False), HeadquaterSoapModel.customize(min_occurs=0, nillable=False), Integer(sub_name='amount', min_occurs=0, nillable=False), _returns=ComplexRequestsResponseSoapModel, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def getOutsourcingRequests(ctx, dt_change, headquater, amount): auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # TODO remove if not headquater: db_headquarter = open_headquarter_by_code('mvideo') else: # Клиент db_headquarter = open_headquarter_by_code(headquater.code) if not db_headquarter: raise CustomError( f'Headquater {headquater.code} is not registered') response = dict() response['requests_list'] = [] # Ограничинваем максимальное количество запросов, возвращаемых за 1 раз if not amount or amount < 0: amount = 100 # Поиск смен out_requests = OutsourcingRequest.objects.filter( headquater=db_headquarter, dt_ready__gt=dt_change, state='ready') out_requests = out_requests.order_by('dt_ready')[:amount] # Формируем результат if not out_requests: response['result'] = len(out_requests) response['timestamp'] = dt_change else: response['result'] = len(out_requests) response['timestamp'] = out_requests.aggregate( timestamp=Max('dt_ready'))['timestamp'] response['requests_list'] = out_requests return response """ Получение данных по запросу и связанным с ним сменам """ @rpc(Unicode(sub_name='guid', min_occurs=1, nillable=False), HeadquaterSoapModel.customize(min_occurs=0, nillable=False), _returns=ComplexOutsourcingRequestSoapModel, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def getOutsourcingRequest(ctx, guid, headquater): auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # TODO remove if not headquater: db_headquarter = open_headquarter_by_code('mvideo') else: # Клиент db_headquarter = open_headquarter_by_code(headquater.code) if not db_headquarter: raise CustomError( f'Headquater {headquater.code} is not registered') try: out_request = OutsourcingRequest.objects.get( guid=guid, headquater=db_headquarter) shifts = OutsourcingShift.objects.filter( request=out_request, headquater=db_headquarter).select_related('job') out_request.shifts = shifts return out_request except: raise CustomError( f'REQUEST {guid}: no OutsourcingRequest is found') """ Получение изменений по сменам на аутсорсинг """ @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False), HeadquaterSoapModel.customize(min_occurs=0, nillable=False), Integer(sub_name='amount', min_occurs=0, nillable=False), _returns=ComplexShiftsResponseSoapModel, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def getOutsourcingShifts(ctx, dt_change, headquater, amount): auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # TODO remove if not headquater: db_headquarter = open_headquarter_by_code('mvideo') else: # Клиент db_headquarter = open_headquarter_by_code(headquater.code) if not db_headquarter: raise CustomError( f'Headquater {headquater.code} is not registered') response = dict() response['shifts_list'] = [] # Ограничинваем максимальное количество смен, возвращаемых за 1 раз if not amount or amount < 0: amount = 100 # Поиск смен out_shifts = OutsourcingShift.objects.filter(headquater=db_headquarter, dt_change__gt=dt_change, state='accept') out_shifts = out_shifts.order_by('dt_change').select_related( 'agency_employee')[:amount] # Получение ТН сотрудника в организации на основе OrgHistory for shift in out_shifts: if shift.agency_employee: shift.agency_employee.oh_number = shift.get_employee_number_in_organization( ) # Формируем результат if not out_shifts: response['result'] = len(out_shifts) response['timestamp'] = dt_change else: response['result'] = len(out_shifts) response['timestamp'] = out_shifts.aggregate( timestamp=Max('dt_change'))['timestamp'] response['shifts_list'] = out_shifts return response """ Получение смен промоутеров """ @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False), HeadquaterSoapModel.customize(min_occurs=0, nillable=False), AgencySoapModel.customize(min_occurs=0, nillable=False), Integer(sub_name='amount', min_occurs=0, nillable=False), _returns=ComplexPromoShiftsResponseSoapModel, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def getPromoShifts(ctx, dt_change, headquater, agency, amount): return _calc_shifts(ctx, dt_change, headquater, agency, amount, party='promo') """ Получение смен брокеров """ @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False), HeadquaterSoapModel.customize(min_occurs=0, nillable=False), AgencySoapModel.customize(min_occurs=0, nillable=False), Integer(sub_name='amount', min_occurs=0, nillable=False), _returns=ComplexPromoShiftsResponseSoapModel, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def getBrokerShifts(ctx, dt_change, headquater, agency, amount): return _calc_shifts(ctx, dt_change, headquater, agency, amount, party='broker') """ Удаление смены из заявки на аутсорсинг по решению управляюего магазином """ @rpc(Array(ShiftDeleteSoapModel), HeadquaterSoapModel.customize(min_occurs=0, nillable=False), _returns=Unicode, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def deleteOutsourcingShifts(ctx, shifts, headquater): auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # TODO remove if not headquater: db_headquarter = open_headquarter_by_code('mvideo') else: # Клиент db_headquarter = open_headquarter_by_code(headquater.code) if not db_headquarter: raise CustomError( f'Headquater {headquater.code} is not registered') # Выходим, если массив смен не задан if not shifts: return {'result': 'ok'} # Помечаем смены как удаленные и формируем уведомления for shift in shifts: # ---------------------------------------------------------- out_shift = OutsourcingShift.objects.filter( guid=shift.guid, headquater=db_headquarter).first() if not out_shift: continue # Создаем и отправляем уведомления об удаленной смене make_notify_data(out_shift, 'agency', 'delete_shift_template') # Меняем состояние на удалена out_shift.state = 'delete' out_shift.save(update_fields=['state']) # ----------------------------------------------------------- return {'result': 'ok'} """ Получение изменений в данных сотрудников """ @rpc(DateTime(sub_name='timestamp', min_occurs=1, nillable=False), HeadquaterSoapModel.customize(min_occurs=0, nillable=False), Integer(sub_name='amount', min_occurs=1, nillable=False), _returns=ComplexEmployeeEventResponseSoapModel, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def getEmployeeEvents(ctx, timestamp, headquater, amount): auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # Ограничинваем максимальное количество событий, возвращаемых за 1 раз if amount <= 0: amount = 100 # TODO remove if not headquater: db_headquarter = open_headquarter_by_code('mvideo') else: # Клиент db_headquarter = open_headquarter_by_code(headquater.code) if not db_headquarter: raise CustomError( f'Headquater {headquater.code} is not registered') # Поиск событий, начиная с заданного в запросе timestamp response = dict() response['events_list'] = [] events = EmployeeEvent.objects.filter(dt_created__gt=timestamp, headquater=db_headquarter). \ select_related('agency_employee', 'agency').order_by('id')[:amount] # Обогощаем найденные события доп. полями for event in events: # Тип агентства event.agency.party = event.agency.headquater.party # Документы сотрудника event.agency_employee.documents = EmployeeDoc.objects.filter( agency_employee=event.agency_employee).order_by('-id') # Обнуляем лишние поля if event.kind != 'recruitment': event.recruitment_date = None if event.kind != 'dismissal': event.dismissal_reason = None event.dismissal_date = None event.blacklist = None # Добавляем возвращемые события в ответное сообщение response['result'] = len(events) if events: response['timestamp'] = events.aggregate( timestamp=Max('dt_created'))['timestamp'] response['events_list'] = events return response """DEPRICATED""" @rpc(HeadquaterSoapModel.customize(min_occurs=1, nillable=False), OrganizationSoapModel.customize(min_occurs=1, nillable=False), AgencySoapModel.customize(min_occurs=1, nillable=False), EmployeeMinSoapModel, EventSoapModel.customize(sub_name='event'), Unicode(sub_name='kind', min_occurs=1, nillable=False), Unicode(sub_name='number', min_occurs=0, nillable=False), Date(sub_name='recruitment_date', min_occurs=0, nillable=False), Date(sub_name='recruitment_state', min_occurs=0, nillable=False), Date(sub_name='dismissal_date', min_occurs=0, nillable=False), Unicode(sub_name='reject_reason', min_occurs=0, nillable=False), Unicode(sub_name='dismissal_reason', min_occurs=0, nillable=False), _returns=Unicode, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def setEventHistory(ctx, headquater, organization, agency, employee, employeeevent, kind, number, recruitment_date, recruitment_state, dismissal_date, reject_reason, dismissal_reason): raise CustomError('Method is deprocated') # TODO изменить проверку доступа с is_superuser auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) headquater_id = get_headquater_id(headquater.code) org = Organization.objects.get(code=organization.code, headquater_id=headquater_id) if not org: raise CustomError('No organiztion') agn = Agency.objects.get(code=agency.code) if not agn: raise CustomError('No agency') emp = AgencyEmployee.objects.get(number=employee.number, agency=agn) if not emp: raise CustomError('No employee') event = EmployeeEvent.objects.get(guid=employeeevent.guid) user = User.objects.get(username=ctx.in_header.login) if kind not in dict(EVENT_HISTORY_KIND_CHOICES): raise CustomError('No kind') elif kind == 'accept_recruitment': if not recruitment_date: raise CustomError('No recruitment_date') if recruitment_state not in ['active', 'inactive']: raise CustomError('No recruitment_state') """Создаем объект внешнего события""" EmployeeHistory.objects.create(user=user, headquater_id=headquater_id, organization=org, event=event, agency_employee=emp, agency=agn, kind=kind, recruitment_date=recruitment_date, recruitment_state=recruitment_state) if recruitment_state == 'active': """Создаем объект назначения""" OrgHistory.objects.create(headquater_id=headquater_id, organization=org, agency_employee=emp, number=number, start=recruitment_date) """Устанавливаем EmployeeEvent флаг, что ответ на него получен""" event.answer_received = True event.save(update_fields=['answer_received']) elif kind == 'reject_recruitment': if not reject_reason: raise CustomError('No reject_reason') """Создаем объект внешнего события""" EmployeeHistory.objects.create(user=user, headquater_id=headquater_id, organization=org, event=event, agency_employee=emp, agency=agn, kind=kind, reject_reason=reject_reason) """Устанавливаем EmployeeEvent флаг, что ответ на него получен""" event.answer_received = True event.save(update_fields=['answer_received']) elif kind == 'dismissal': if not dismissal_date or not dismissal_reason: raise CustomError('No dismissal date or reason') """Ищем назначение и устанавливаем дату увольнения""" org_history = OrgHistory.objects.get(organization=org, agency_employee=emp) if not org_history: raise CustomError('No OrgHistory') org_history.end = dismissal_date - timedelta(days=1) org_history.save(update_fields=['end']) """Ищем смены данного сотрудника после даты увольнения и снимаем назначение""" OutsourcingShift.objects.filter( agency_employee=emp, start_date__gt=dismissal_date - timedelta(days=1), headquater_id=headquater_id).update(agency_employee=None) """Создаем объект внешнего события""" EmployeeHistory.objects.create(user=user, headquater_id=headquater_id, organization=org, event=event, agency_employee=emp, agency=agn, kind=kind, dismissal_date=dismissal_date, dismissal_reason=dismissal_reason) """Устанавливаем EmployeeEvent флаг, что ответ на него получен""" event.answer_received = True event.save(update_fields=['answer_received']) """Устанавливаем сотруднику дату обновления данных по API""" event.agency_employee.last_external_update = timezone.now() event.agency_employee.save(update_fields=['last_external_update']) return "ok" """Подтверждение или отказ в приеме сотрудника из кадровой системы клиента""" @rpc(EventSoapModel2.customize(sub_name='event', min_occurs=1, nillable=False), Unicode(sub_name='status', min_occurs=1, nillable=False), Unicode(sub_name='recruitmentState', min_occurs=0, nillable=False, default='active'), Date(sub_name='recruitmentDate', min_occurs=0, nillable=False), Unicode(sub_name='externalNumber', min_occurs=0, nillable=False), Unicode(sub_name='rejectReason', min_occurs=0, nillable=False), _returns=Unicode, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def setRecruitmentStatus(ctx, employeeevent, status, recruitmentState, recruitmentDate, externalNumber, rejectReason): user = User.objects.get(username=ctx.in_header.login) auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # Проверка параметров event = EmployeeEvent.objects.get(guid=employeeevent.guid) if not event: raise CustomError(f'Event {employeeevent.guid} is undefined') if recruitmentState and recruitmentState not in ['active', 'inactive']: raise CustomError('No recruitmentState') if status not in ['accept', 'reject']: return # Подтверждение регистрации if status == 'accept': error = accept_employee_attach(user, event, recruitmentState, recruitmentDate, externalNumber) # Регистрация отклонена else: error = reject_employee_attach(user, event, rejectReason) # Обработчик ошибок if error: raise CustomError(error) # Устанавливаем сотруднику дату обновления данных по API event.agency_employee.last_external_update = timezone.now() event.agency_employee.save(update_fields=['last_external_update']) return """Открепление сотрудника от клиента по запросу из кадровой системы""" @rpc(HeadquaterSoapModel.customize(min_occurs=1, nillable=False), OrganizationSoapModel, AgencySoapModel.customize(min_occurs=1, nillable=False), Unicode(sub_name='externalNumber', min_occurs=1, nillable=False), Date(sub_name='dismissalDate', min_occurs=1, nillable=False), Unicode(sub_name='dismissalReason', min_occurs=1, nillable=False), Boolean(sub_name='blacklist', min_occurs=1, nillable=False), _returns=Unicode, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def dismissEmployee(ctx, headquater, organization, agency, ext_number, dismissal_date, dismissal_reason, blacklist): user = User.objects.get(username=ctx.in_header.login) auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # Проверка параметров db_headquarter = open_headquarter_by_code(headquater.code) if not db_headquarter: raise CustomError(f'Headquater {headquater.code} is not found') if organization: db_organization = open_organization_by_code( organization.code, db_headquarter) if not db_organization: raise CustomError( f'Organization {organization.code} is not found') else: db_organization = None db_agency = open_agency_by_code(agency.code, None) if not db_agency: raise CustomError(f'Agency {agency.code} is not found') # Определяем увольняемого сотрудника employees = employees_by_ext_number(db_headquarter, db_agency, ext_number) for employee in employees: dismiss_employee(user, employee, dismissal_date, dismissal_reason, blacklist, db_headquarter, db_organization) # Устанавливаем сотруднику дату обновления данных по API employee.last_external_update = timezone.now() employee.save(update_fields=['last_external_update']) return ######## @rpc(HeadquaterSoapModel.customize(min_occurs=1, nillable=False), Array(OrgunitSoapModel.customize(min_occurs=1, nillable=False)), Array(OrglinkSoapModel.customize(min_occurs=0, nillable=False)), _returns=Unicode, _throws=[AuthenticationError, AuthorizationError, CustomError]) @soap_logger @check_auth_data def setOrgunits(ctx, headquater, orgunits, orglinks): """Set Orgunits. Синхронизитрует орг. структуру на основе данных из портала планирования""" auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # Headquarter headquater_id = get_headquater_id(headquater.code) # Organizations orgunits_received = 0 orgunits_created = 0 orgunits_errors = 0 if orgunits: for orgunit in orgunits: orgunits_received += 1 org, org_created = Organization.objects.get_or_create( code=orgunit.code, headquater_id=headquater_id) if org_created: orgunits_created += 1 org.name = orgunit.name org.address = orgunit.address org.kind = 'store' if orgunit.parent and org_created: parent_org = Organization.objects.filter( code=orgunit.parent.code, headquater_id=headquater_id).first() if parent_org: org.parent = parent_org else: default, default_created = Organization.objects.get_or_create( code=headquater.code + '_city_undefined', name='Город не определен', headquater_id=headquater_id, kind='city') org.parent = default org.last_external_update = timezone.now() org.save() # OrgLinks orglinks_received = 0 orglinks_created = 0 orglinks_errors = 0 if orglinks: for orglink_imp in orglinks: orglinks_received += 1 organization = Organization.objects.filter( code=orglink_imp.organization.code).first() if not organization: orglinks_errors += 1 continue agency = Agency.objects.filter( code=orglink_imp.agency.code).first() if not agency: orglinks_errors += 1 continue _, orglink_created = OrgLink.objects.get_or_create( agency=agency, organization=organization, headquater_id=headquater_id) if orglink_created: orglinks_created += 1 return { 'result': 'ok', 'orgunits_received': orgunits_received, 'orgunits_created': orgunits_created, 'orgunits_errors': orgunits_errors, 'orglinks_received': orglinks_received, 'orglinks_created': orglinks_created, 'orglinks_errors': orglinks_errors, } @rpc(HeadquarterSoapModel.customize(min_occurs=1, nillable=False), UserExtSoapModel.customize(sub_name='user', min_occurs=1, nillable=False), Array(AccessProfileSoapModel, sub_name='accessProfiles').customize(min_occurs=1, nillable=False), _throws=[ AuthenticationError, AuthorizationError, error.ResourceNotFoundError ]) @soap_logger @check_auth_data def setUser(ctx, headquarter, user, access_list): auth_and_check_perms(ctx.in_header.login, ctx.in_header.password) # Обновляем или создаем сотрудника user_defaults = { 'first_name': user.first_name, 'last_name': user.last_name, 'email': user.email, 'is_active': user.is_active } db_user, created = User.objects.update_or_create( username=user.username, defaults=user_defaults) db_headquarter = open_headquarter_by_code(headquarter.code) db_access_role = None # Установка прав доступа if access_list is None: access_list = [] for access_profile in access_list: try: db_organization = open_organization_by_code( access_profile.unit.code, db_headquarter) except error.ResourceNotFoundError: continue if access_profile.role is not None: db_access_role = open_role_by_code(access_profile.role.code) if db_access_role is None: raise error.ResourceNotFoundError('accessRole') profile, _ = AccessProfile.objects.update_or_create( user=db_user, unit_type=ContentType.objects.get_for_model(db_organization), unit_id=db_organization.id, role=db_access_role, headquater=db_headquarter)
class SomeOtherClass(NewTableModel): __tablename__ = 'some_class' __table_args__ = {"sqlite_autoincrement": True} id = Integer32(primary_key=True) s = Unicode(64)
class OrgExternalType(SmevModel): Code = Unicode(type_name="Code", pattern="[A-Z0-9]{4}\d{5}") Name = Unicode(type_name="Name")
class HeaderType(SmevModel): NodeId = Unicode(type_name="NodeId") MessageId = Unicode(type_name="MessageId") TimeStamp = DateTime(type_name="TimeStamp") MessageClass = Unicode(type_name="MessageClass", values=["REQUEST", "RESPONSE"])
class SharingService(HydraService): """ The network SOAP service. """ @rpc(Integer, Unicode(max_occurs='unbounded'), Unicode(pattern="[YN]"), Unicode(pattern="[YN]", default='Y'), _returns=Unicode()) def share_network(ctx, network_id, usernames, read_only, share): """ Share a network with a list of users, identified by their usernames. Args: network_id (int): The ID of the network to share usernames (List(Unicode)): THe list of usernames with whom to share the network read_only (string) (Y or N): Can the users edit as well as view the network? share (string) (optional) (Y or N): Can the users share the network with other users? This only goes 1 level deep, so if you share a network with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else. Returns: string: 'OK' Raises: ResourceNotFoundError: If the network is not found ResourceNotFoundError: If one of the usernames is incorrect or does not exist """ sharing.share_network(network_id, usernames, read_only, share, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, Unicode(max_occurs='unbounded'), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), _returns=Unicode) def share_project(ctx, project_id, usernames, read_only, share): """ Share an entire project with a list of users, identifed by their usernames. All the projectt's networks will be shared also. Args: project_id (int): The ID of the project to share usernames (List(Unicode)): The list of usernames with whom to share the project read_only (string) (Y or N): Can the users edit as well as view the project? share (string) (optional) (Y or N): Can the users share the project with other users? This only goes 1 level deep, so if you share a project with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else. Returns: string: 'OK' Raises: ResourceNotFoundError: If the project is not found ResourceNotFoundError: If one of the usernames is incorrect or does not exist """ sharing.share_project(project_id, usernames, read_only, share, **ctx.in_header.__dict__) return "OK" @rpc(Integer, Unicode(max_occurs="unbounded"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), _returns=Unicode) def set_project_permission(ctx, project_id, usernames, read, write, share): """ Set permissions on a project to a list of users, identifed by their usernames. THIS ACTION IS THEN PERFORMED ON ALL THE PROJECT'S NETWORKS! Args: project_id (int): The ID of the project to share usernames (List(Unicode)): The list of usernames with whom to share the project read (string) (Y or N): Can the users read the project? write (string) (Y or N): Can the users edit the project? share (string) (optional) (Y or N): Can the users share the project with other users? This only goes 1 level deep, so if you share a network with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else. Returns: string: 'OK' Raises: ResourceNotFoundError: If the project is not found ResourceNotFoundError: If one of the usernames is incorrect or does not exist """ sharing.set_project_permission(project_id, usernames, read, write, share, **ctx.in_header.__dict__) @rpc(Integer, Unicode(max_occurs="unbounded"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), _returns=Unicode) def set_network_permission(ctx, network_id, usernames, read, write, share): """ Set permissions on a network to a list of users, identifed by their usernames. The read flag ('Y' or 'N') sets read access, the write flag sets write access. If the read flag is 'N', then there is automatically no write access or share access. Args: network_id (int): The ID of the network to share usernames (List(Unicode)): The list of usernames with whom to share the network read (string) (Y or N): Can the users read the network? write (string) (Y or N): Can the users edit the network? share (string) (optional) (Y or N): Can the users share the network with other users? This only goes 1 level deep, so if you share a network with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else. Returns: string: 'OK' Raises: ResourceNotFoundError: If the network is not found ResourceNotFoundError: If one of the usernames is incorrect or does not exist """ sharing.set_network_permission(network_id, usernames, read, write, share, **ctx.in_header.__dict__) return "OK" @rpc(Integer, Unicode(max_occurs="unbounded"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), Unicode(pattern="[YN]"), _returns=Unicode) def hide_dataset(ctx, dataset_id, exceptions, read, write, share): """ Hide a particular piece of data so it can only be seen by its owner. Only an owner can hide (and unhide) data. Data with no owner cannot be hidden. Args: dataset_id (int): The ID of the dataset to be hidden exceptions (List(Unicode)): the usernames of those with permission to view the data read (string) (Y or N): Can the users read the dataset? write (string) (Y or N): Can the users edit the dataset? share (string) (Y or N): Can the users share the dataset with other users? This only goes 1 level deep, so if you share a network with a user and give them sharing ability, they cannot then set the 'share' flag to 'Y' when sharing with someone else. Returns: string: 'OK' Raises: ResourceNotFoundError: If the dataset is not found HydraError: If the request is being made by a non-owner of the dataset """ sharing.hide_dataset(dataset_id, exceptions, read, write, share, **ctx.in_header.__dict__) return "OK" @rpc(Integer, _returns=Unicode) def unhide_dataset(ctx, dataset_id): """ Un Hide a particular piece of data so it can only be seen by its owner. Only an owner can hide (and unhide) data. Args: dataset_id (int): The ID of the dataset to be un-hidden Returns: string: 'OK' Raises: ResourceNotFoundError: If the dataset is not found HydraError: If the request is being made by a non-owner of the dataset """ sharing.unhide_dataset(dataset_id, **ctx.in_header.__dict__) return "OK"
class Passenger(ComplexModelBase): passengerName = Mandatory.Unicode(255) passengerPatronymic = Unicode(255) passengerSurname = Unicode(255) passengerPhone = Mandatory.Unicode(255) passengerDescription = Unicode
class TemplateService(HydraService): """ The template SOAP service """ @rpc(Unicode, _returns=Template) def upload_template_xml(ctx, template_xml): """ Add the template, type and typeattrs described in an XML file. Delete type, typeattr entries in the DB that are not in the XML file The assumption is that they have been deleted and are no longer required. """ tmpl_i = template.upload_template_xml(template_xml, **ctx.in_header.__dict__) return Template(tmpl_i) @rpc(Unicode, Integer, _returns=SpyneArray(TypeSummary)) def get_matching_resource_types(ctx, resource_type, resource_id): """ Get the possible types of a resource by checking its attributes against all available types. @returns A list of TypeSummary objects. """ types = template.get_matching_resource_types(resource_type, resource_id, **ctx.in_header.__dict__) ret_types = [TypeSummary(ts) for ts in types] return ret_types @rpc(SpyneArray(ResourceTypeDef), _returns=SpyneArray(TemplateType)) def assign_types_to_resources(ctx, resource_types): """Assign new types to list of resources. This function checks if the necessary attributes are present and adds them if needed. Non existing attributes are also added when the type is already assigned. This means that this function can also be used to update resources, when a resource type has changed. """ types = template.assign_types_to_resources(resource_types, **ctx.in_header.__dict__) ret_val = [TemplateType(t) for t in types] return ret_val @rpc(Integer, Unicode, Integer, _returns=TypeSummary) def assign_type_to_resource(ctx, type_id, resource_type, resource_id): """Assign new type to a resource. This function checks if the necessary attributes are present and adds them if needed. Non existing attributes are also added when the type is already assigned. This means that this function can also be used to update resources, when a resource type has changed. """ templatetype = template.assign_type_to_resource( type_id, resource_type, resource_id, **ctx.in_header.__dict__) ret_type = TypeSummary() ret_type.name = templatetype.type_name ret_type.id = templatetype.type_id ret_type.template_name = templatetype.template.template_name ret_type.template_id = templatetype.template.template_id return ret_type @rpc(Integer, Integer, _returns=Unicode) def apply_template_to_network(ctx, template_id, network_id): """ Given a template and a network, try to match up and assign all the nodes & links in the network to the types in the template """ template.apply_template_to_network(template_id, network_id, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, Integer, _returns=Unicode) def set_network_template(ctx, template_id, network_id): """ Given a template and a network, try to match up and assign all the nodes & links in the network to the types in the template """ template.set_network_template(template_id, network_id, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, Integer, Unicode(pattern="[YN]", default='N'), _returns=Unicode) def remove_template_from_network(ctx, network_id, template_id, remove_attrs): """ Given a template and a network, try to match up and assign all the nodes & links in the network to the types in the template """ template.remove_template_from_network(network_id, template_id, remove_attrs, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, Unicode, Integer, _returns=Unicode) def remove_type_from_resource(ctx, type_id, resource_type, resource_id): """ Remove a resource type trom a resource """ template.remove_type_from_resource(type_id, resource_type, resource_id, **ctx.in_header.__dict__) return 'OK' @rpc(Template, _returns=Template) def add_template(ctx, tmpl): """ Add template and a type and typeattrs. """ tmpl_i = template.add_template(tmpl, **ctx.in_header.__dict__) return Template(tmpl_i) @rpc(Template, _returns=Template) def update_template(ctx, tmpl): """ Update template and a type and typeattrs. """ tmpl_i = template.update_template(tmpl, **ctx.in_header.__dict__) return Template(tmpl_i) @rpc(Integer, _returns=Template) def delete_template(ctx, template_id): """ Update template and a type and typeattrs. """ template.delete_template(template_id, **ctx.in_header.__dict__) return 'OK' @rpc(_returns=SpyneArray(Template)) def get_templates(ctx): """ Get all resource template templates. """ tmpls = template.get_templates(**ctx.in_header.__dict__) ret_templates = [Template(t) for t in tmpls] return ret_templates @rpc(Integer, Integer, _returns=Unicode) def remove_attr_from_type(ctx, type_id, attr_id): """ Remove an attribute from a type """ success = 'OK' template.remove_attr_from_type(type_id, attr_id, **ctx.in_header.__dict__) return success @rpc(Integer, _returns=Template) def get_template(ctx, template_id): """ Get a specific resource template template, either by ID or name. """ tmpl_i = template.get_template(template_id, **ctx.in_header.__dict__) tmpl = Template(tmpl_i) return tmpl @rpc(Unicode, _returns=Template) def get_template_by_name(ctx, template_name): """ Get a specific resource template, either by ID or name. """ tmpl_i = template.get_template_by_name(template_name, **ctx.in_header.__dict__) if tmpl_i is not None: tmpl = Template(tmpl_i) return tmpl else: return None @rpc(TemplateType, _returns=TemplateType) def add_templatetype(ctx, templatetype): """ Add a template type with typeattrs. """ tmpl_type = template.add_templatetype(templatetype, **ctx.in_header.__dict__) return TemplateType(tmpl_type) @rpc(TemplateType, _returns=TemplateType) def update_templatetype(ctx, templatetype): """ Update a resource type and its typeattrs. New typeattrs will be added. typeattrs not sent will be ignored. To delete typeattrs, call delete_typeattr """ type_i = template.update_templatetype(templatetype, **ctx.in_header.__dict__) return TemplateType(type_i) @rpc(Integer, _returns=Template) def delete_templatetype(ctx, type_id): """ Update template and a type and typeattrs. """ template.delete_templatetype(type_id, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, _returns=TemplateType) def get_templatetype(ctx, type_id): """ Get a specific resource type by ID. """ type_i = template.get_templatetype(type_id, **ctx.in_header.__dict__) templatetype = TemplateType(type_i) return templatetype @rpc(Integer, Unicode, _returns=TemplateType) def get_templatetype_by_name(ctx, template_id, type_name): """ Get a specific resource type by name. """ type_i = template.get_templatetype_by_name(template_id, type_name, **ctx.in_header.__dict__) tmpltype = TemplateType(type_i) return tmpltype @rpc(TypeAttr, _returns=TemplateType) def add_typeattr(ctx, typeattr): """ Add an typeattr to an existing type. """ updated_template_type = template.add_typeattr(typeattr, **ctx.in_header.__dict__) ta = TemplateType(updated_template_type) return ta @rpc(TypeAttr, _returns=Unicode) def delete_typeattr(ctx, typeattr): """ Remove an typeattr from an existing type """ success = 'OK' template.delete_typeattr(typeattr, **ctx.in_header.__dict__) return success @rpc(Integer, _returns=Unicode) def get_network_as_xml_template(ctx, network_id): """ Turn an existing network into an xml template using its attributes. If an optional scenario ID is passed in, default values will be populated from that scenario. """ template_xml = template.get_network_as_xml_template( network_id, **ctx.in_header.__dict__) return template_xml @rpc(Integer, Integer, Integer, _returns=ValidationError) def validate_attr(ctx, resource_attr_id, scenario_id, template_id): """ Validate that the value of a specified resource attribute is valid relative to the data restrictions specified on the template. If no template is specified, (set as null), then validation will be made against every template on the network. """ error_dict = template.validate_attr(resource_attr_id, scenario_id, template_id) if error_dict is None: return None error = ValidationError( ref_key=error_dict.get('ref_key'), ref_id=error_dict.get('ref_id'), ref_name=error_dict.get('ref_name'), resource_attr_id=error_dict.get('resource_attr_id'), attr_id=error_dict.get('attr_id'), attr_name=error_dict.get('attr_name'), dataset_id=error_dict.get('dataset_id'), scenario_id=error_dict.get('scenario_id'), template_id=error_dict.get('template_id'), error_text=error_dict.get('error_text')) return error @rpc(SpyneArray(Integer32), Integer, Integer, _returns=SpyneArray(ValidationError)) def validate_attrs(ctx, resource_attr_ids, scenario_id, template_id): errors = [] error_dicts = template.validate_attrs(resource_attr_ids, scenario_id, template_id) for error_dict in error_dicts: error = ValidationError( ref_key=error_dict.get('ref_key'), ref_id=error_dict.get('ref_id'), ref_name=error_dict.get('ref_name'), resource_attr_id=error_dict.get('resource_attr_id'), attr_id=error_dict.get('attr_id'), attr_name=error_dict.get('attr_name'), dataset_id=error_dict.get('dataset_id'), scenario_id=error_dict.get('scenario_id'), template_id=error_dict.get('template_id'), error_text=error_dict.get('error_text')) errors.append(error) return errors @rpc(Integer, Integer, _returns=SpyneArray(ValidationError)) def validate_scenario(ctx, scenario_id, template_id): errors = [] error_dicts = template.validate_scenario(scenario_id, template_id) for error_dict in error_dicts: error = ValidationError( ref_key=error_dict.get('ref_key'), ref_id=error_dict.get('ref_id'), ref_name=error_dict.get('ref_name'), resource_attr_id=error_dict.get('resource_attr_id'), attr_id=error_dict.get('attr_id'), attr_name=error_dict.get('attr_name'), dataset_id=error_dict.get('dataset_id'), scenario_id=error_dict.get('scenario_id'), template_id=error_dict.get('template_id'), error_text=error_dict.get('error_text')) errors.append(error) return errors @rpc(Integer, Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(Unicode)) def validate_network(ctx, network_id, template_id, scenario_id): errors = template.validate_network(network_id, template_id, scenario_id) return errors @rpc(Integer, Integer, _returns=SpyneArray(Unicode)) def check_type_compatibility(ctx, type_1_id, type_2_id): errors = template.check_type_compatibility(type_1_id, type_2_id) return errors
class MoviesSoapService(spyne.Service): __soap_target_namespace__ = 'MyNS' __soap_server_address__ = '/soap/movies' __service_url_path__ = '/soap/movies' __in_protocol__ = Soap11(validator='lxml') __out_protocol__ = Soap11() @spyne.srpc(Unicode(default=''), Unicode(default=''), _returns=Array(Movie)) def getMovieSoap(option, search): m = [] if option == '' or search == '': for movie in movies: m.append( Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"])) elif option == "ID": for movie in movies: if (movie["ID"] == search): m.append( Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"])) elif option == "Title": for movie in movies: if (re.search(search, movie["Title"], re.IGNORECASE)): m.append( Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"])) else: for movie in movies: m.append( Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"])) return m @spyne.srpc(Unicode, _returns=Array(Movie)) def getMovieByIdSoap(Id): m = [] for movie in movies: if (movie["ID"] == Id): m.append( Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"])) return m @spyne.srpc(Unicode, _returns=Array(Movie)) def getMovieByTitleSoap(Title): m = [] for movie in movies: if (re.search(Title, movie["Title"], re.IGNORECASE)): m.append( Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"])) return m @spyne.srpc(Unicode, _returns=Array(Movie)) def getMovieByGenreSoap(Genre): m = [] for movie in movies: if (movie["Genre"] == Genre): m.append( Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"])) return m @spyne.srpc(Unicode, _returns=Array(Movie)) def getMovieByRatingSoap(Rating): m = [] if (re.search('^[0-9](\.[0-9]*)?$', Rating)): for movie in movies: if (re.search('^[0-9](\.[0-9]*)?$', movie['Rating'])): if (float(movie['Rating']) > float(Rating)): m.append( Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"])) return m @spyne.srpc(_returns=Array(MovieAlbum)) def getMoviesAlbumsSoap(): m = [] for movie in movies: try: r = requests.get('http://web1:81/albums/' + movie['Album_ID']) r = json.loads(r.text) album = r[0] m.append( MovieAlbum(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=Album(ID=album["ID"], Album=album["Album"], Artist=album["Artist"], Genre=album["Genre"], Producer=album["Producer"]))) except: m.append( MovieAlbum(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID="null")) return m @spyne.srpc(Unicode, Unicode, Unicode, Unicode, Unicode, _returns=Movie) def newMovieSoap(Title, Genre, Rating, Release_date, Album_ID): numberOfMovies = len(movies) r = requests.get('http://web1:81/albums/' + Album_ID) if r.status_code == 200: new_Movie = { 'ID': str(numberOfMovies), 'Title': Title, 'Release_date': Release_date, 'Rating': Rating, 'Genre': Genre, 'Album_ID': Album_ID } movies.append(new_Movie) movie = movies[len(movies) - 1] else: new_Movie = { 'ID': str(numberOfMovies), 'Title': Title, 'Release_date': Release_date, 'Rating': Rating, 'Genre': Genre, 'Album_ID': "null" } movies.append(new_Movie) movie = movies[len(movies) - 1] return Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"]) @spyne.srpc(Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode(default=''), _returns=Movie) def newMovieAlbumSoap(Title, Genre, Rating, Release_date, Album, Artist, AlbumGenre, Producer): if Producer != "": try: r = requests.post('http://web1:81/albums', json={ "Album": Album, "Artist": Artist, "Genre": AlbumGenre, "Producer": Producer }) r = json.loads(r.text) numberOfMovies = len(movies) new_Movie = { 'ID': str(numberOfMovies), 'Title': Title, 'Release_date': Release_date, 'Rating': Rating, 'Genre': Genre, 'Album_ID': r.get("ID") } movies.append(new_Movie) movie = movies[len(movies) - 1] return Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=r.get("ID")) except: raise Fault(faultcode='Client', faultstring='', faultactor='', detail={ 'Message': 'Error. Service Albums is not available.' }) @spyne.srpc(Unicode, Unicode, _returns=Movie) def rateMovieSoap(Id, Rating): if (re.search('^[0-9](\.[0-9]*)?$', Rating)): for movie in movies: if (movie["ID"] == Id): movie["Rating"] = Rating return Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"]) @spyne.srpc(Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, _returns=Movie) def changeMovieSoap(Id, Title, Genre, Release_date, Rating, Album_ID): try: r = requests.get('http://web1:81/albums/' + Album_ID) if r.status_code == 200 and re.search('^[0-9]?$', Id): movies[int(Id)]['Title'] = Title movies[int(Id)]['Genre'] = Genre movies[int(Id)]['Rating'] = Rating movies[int(Id)]['Release_date'] = Release_date movies[int(Id)]['Album_ID'] = Album_ID movie = movies[int(Id)] else: raise Fault(faultcode='Client', faultstring='', faultactor='', detail={ 'Message': 'Error. Service Albums status is not 200.' }) return Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"]) except: raise Fault( faultcode='Client', faultstring='', faultactor='', detail={'Message': 'Error. Service Albums is not available.'}) @spyne.srpc(Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, _returns=Movie) def deleteMovieSoap(Id, Title, Genre, Release_date, Rating, Album_ID): deleted = [movie for movie in movies if (movie['ID'] == Id)] if len(deleted) != 0: movies.remove(deleted[0]) movie = deleted[0] return Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"]) @spyne.srpc(Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode, Unicode(default=''), _returns=Movie) def changeMovieAlbumSoap(Id, Title, Genre, Release_date, Rating, Album, AlbumGenre, Producer, Artist): if Artist != '': try: for i in range(0, len(movies)): if movies[i]["ID"] == Id: r = requests.put('http://web1:81/albums/' + movies[i]["Album_ID"], json={ "Album": Album, "Artist": Artist, "Genre": AlbumGenre, "Producer": Producer }) if r.status_code == 200 and re.search('^[0-9]?$', Id): movies[i]['Title'] = Title movies[i]['Genre'] = Genre movies[i]['Rating'] = Rating movies[i]['Release_date'] = Release_date movie = movies[i] else: raise Fault( faultcode='Client', faultstring='', faultactor='', detail={ 'Message': 'Error. Service Albums status is not 200.' }) return Movie(ID=movie["ID"], Title=movie["Title"], Genre=movie["Genre"], Rating=movie["Rating"], Release_date=movie["Release_date"], Album_ID=movie["Album_ID"]) except: raise Fault(faultcode='Client', faultstring='', faultactor='', detail={ 'Message': 'Error. Service Albums is not available.' })
class ProjectService(HydraService): """ The project SOAP service """ @rpc(Project, _returns=Project) def add_project(ctx, project): """ Add a new project Args: project (hydra_complexmodels.Project): The new project to be added. The project does not include networks. Returns: hydra_complexmodels.Project: The project received, but with an ID this time. Raises: """ new_proj = project_lib.add_project(project, **ctx.in_header.__dict__) ret_proj = Project(new_proj) return ret_proj @rpc(Project, _returns=Project) def update_project(ctx, project): """ Update a project Args: project (hydra_complexmodels.Project): The project to be updated. All the attributes of this project will be used to update the existing project Returns: hydra_complexmodels.Project: The updated project Raises: ResourceNotFoundError: If the project is not found. """ proj_i = project_lib.update_project(project, **ctx.in_header.__dict__) return Project(proj_i) @rpc(Integer, _returns=Project) def get_project(ctx, project_id): """ Get an existing Project Args: project_id (int): The ID of the project to retrieve Returns: hydra_complexmodels.Project: The requested project Raises: ResourceNotFoundError: If the project is not found. """ proj_dict = project_lib.get_project(project_id, **ctx.in_header.__dict__) return Project(proj_dict) @rpc(Unicode, _returns=Project) def get_project_by_name(ctx, project_name): """ If you don't know the ID of the project in question, but do know the name, use this function to retrieve it. Args: project_name (string): The name of the project to retrieve Returns: hydra_complexmodels.Project: The requested project Raises: ResourceNotFoundError: If the project is not found. """ proj_dict = project_lib.get_project_by_name(project_name, **ctx.in_header.__dict__) return Project(proj_dict) @rpc(Integer, _returns=SpyneArray(ProjectSummary)) def get_projects(ctx, user_id): """ Get all the projects belonging to a user. Args: user_id (int): The user ID whose projects you want Returns: List(hydra_complexmodels.Project): The requested projects Raises: ResourceNotFoundError: If the User is not found. """ if user_id is None: user_id = ctx.in_header.user_id project_dicts = project_lib.get_projects(user_id, **ctx.in_header.__dict__) projects = [Project(p) for p in project_dicts] return projects @rpc(Integer, _returns=Unicode) def delete_project(ctx, project_id): """ Set the status of a project to 'X'. This does NOT delete the project from the database (which also entails deleting all sub-networks, data etc). For that, use purge_project. Args: project_id (int): The ID of the project to delete. Returns: string: 'OK' Raises: ResourceNotFoundError: If the Project is not found. """ project_lib.set_project_status(project_id, 'X', **ctx.in_header.__dict__) return 'OK' @rpc(Integer, _returns=Unicode) def purge_project(ctx, project_id): """ Delete a project from the DB completely. WARNING: THIS WILL DELETE ALL THE PROJECT'S NETWORKS AND CANNOT BE REVERSED! Args: project_id (int): The ID of the project to purge. Returns: string: 'OK' Raises: ResourceNotFoundError: If the Project is not found. """ project_lib.delete_project(project_id, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, Unicode(pattern="[YN]", default='Y'), _returns=SpyneArray(Network)) def get_networks(ctx, project_id, include_data): """ Get all networks in a project Args: project_id (int): The ID of the project whose networks you want. include_data (string) ('Y' or 'N'): Include data with the networks? Defaults as 'Y' but using 'N' gives a significant performance boost. Returns: List(hydra_complexmodels.Network): All the project's Networks. Raises: ResourceNotFoundError: If the Project is not found. """ net_dicts = project_lib.get_networks(project_id, include_data=include_data, **ctx.in_header.__dict__) networks = [Network(n, summary=True) for n in net_dicts] return networks @rpc(Integer, _returns=Project) def get_network_project(ctx, network_id): """ Get the project of a specified network Args: network_id (int): The ID of the network whose project details you want Returns: hydra_complexmodels.Project: The parent project of the specified Network Raises: ResourceNotFoundError: If the Network is not found. """ proj = project_lib.get_network_project(network_id, **ctx.in_header.__dict__) return Project(proj)
class Permission(ComplexModel): __namespace__ = 'spyne.examples.user_manager' id = UnsignedInteger32 application = Unicode(values=('usermgr', 'accountmgr')) operation = Unicode(values=('read', 'modify', 'delete'))
class SomeComplexModel(ComplexModel): _type_info = [ ('a', Unicode), ('b', Unicode(min_occurs=1, default='default', nillable=True)), ]
def test_new_type(self): """Customized primitives go into namespace based on module name.""" custom_type = Unicode(pattern='123') self.assertEqual(custom_type.get_namespace(), custom_type.__module__)
class C(ComplexModel): e = Unicode(max_occurs='unbounded') a = XmlAttribute(Unicode, attribute_of="e")
class SomeComplexModel(ComplexModel): _type_info = [ ('a', Unicode), ('b', Unicode(default='default')), ]
class cls(ComplexModel): __namespace__ = 'tns' s = Unicode(max_occurs='unbounded')
def test_simple_type_explicit_customization(self): assert Unicode(max_len=5).__extends__ is not None assert Unicode.customize(max_len=5).__extends__ is not None
class SomeService(ServiceBase): @srpc(Unicode(pattern=u'x'), _returns=Unicode) def some_call(s): test(never, reaches, here)
class ServiceType(SmevModel): Mnemonic = Unicode(type_name="Mnemonic", min_occurs=1, max_occurs=1) Version = Unicode(type_name="Version", pattern="\d{1,2}\.\d{2}", min_occurs=1, max_occurs=1)
class AnswerServiceResponse(ComplexModel): __namespace__ = 'tns' dummy_str = Unicode(min_occurs=0, max_occurs=1, nillable=False) dummy_num = Integer(min_occurs=1, max_occurs=1, nillable=True)
class AppDocument(SmevModel): RequestCode = Unicode(type_name="RequestCode") BinaryData = File(type_name="BinaryData", encoding=BINARY_ENCODING_BASE64)
class Include(SchemaBase): schema_location = XmlAttribute(Unicode(sub_name="schemaLocation"))
class SomeService(ServiceBase): @srpc(Unicode(max_occurs=Decimal('inf')), _returns=Unicode(max_occurs=Decimal('inf'))) def some_call(s): return s
class List(SchemaBase): _type_info = [ ('item_type', XmlAttribute(Unicode(sub_name='itemType'))), ]
class SomeOtherClass(ComplexModel): id = Integer32 s = Unicode(64)
class AttributeService(HydraService): """ The attribute SOAP service """ @rpc(Attr, _returns=Attr) def add_attribute(ctx, attr): """ Add a generic attribute, which can then be used in creating a resource attribute, and put into a type. .. code-block:: python (Attr){ name = "Test Attr" dimen = "very big" description = "I am a very big attribute" } Args: attr (hydra_complexmodels.Attr): An attribute object, as described above. Returns: hydra_complexmodels.Attr: An attribute object, similar to the one sent in but with an ID. """ attr = attributes.add_attribute(attr, **ctx.in_header.__dict__) return Attr(attr) @rpc(Attr, _returns=Attr) def update_attribute(ctx, attr): """ Update a generic attribute, which can then be used in creating a resource attribute, and put into a type. .. code-block:: python (Attr){ id = 1020 name = "Test Attr" dimen = "very big" description = "I am a very big attribute" } Args: attr (hydra_complexmodels.Attr): An attribute complex model, as described above. Returns: hydra_complexmodels.Attr: An attribute complex model, reflecting the one sent in. """ attr = attributes.update_attribute(attr, **ctx.in_header.__dict__) return Attr(attr) @rpc(SpyneArray(Attr), _returns=SpyneArray(Attr)) def add_attributes(ctx, attrs): """ Add multiple generic attributes Args: attrs (List[Attr]): A list of attribute complex models, as described above. Returns: List[Attr]: A list of attribute complex models, reflecting the ones sent in. """ attrs = attributes.add_attributes(attrs, **ctx.in_header.__dict__) ret_attrs = [Attr(attr) for attr in attrs] return ret_attrs @rpc(_returns=SpyneArray(Attr)) def get_all_attributes(ctx): """ Get all the attributes in the system Args: None Returns: List[Attr]: A list of attribute complex models """ attrs = attributes.get_attributes(**ctx.in_header.__dict__) ret_attrs = [Attr(attr) for attr in attrs] return ret_attrs @rpc(Integer, _returns=Attr) def get_attribute_by_id(ctx, ID): """ Get a specific attribute by its ID. Args: ID (int): The ID of the attribute Returns: hydra_complexmodels.Attr: An attribute complex model. Returns None if no attribute is found. """ attr = attributes.get_attribute_by_id(ID, **ctx.in_header.__dict__) if attr: return Attr(attr) return None @rpc(Unicode, Unicode, _returns=Attr) def get_attribute(ctx, name, dimension): """ Get a specific attribute by its name and dimension (this combination is unique for attributes in Hydra Platform). Args: name (unicode): The name of the attribute dimension (unicode): The dimension of the attribute Returns: hydra_complexmodels.Attr: An attribute complex model. Returns None if no attribute is found. """ attr = attributes.get_attribute_by_name_and_dimension( name, dimension, **ctx.in_header.__dict__) if attr: return Attr(attr) return None @rpc(Integer, _returns=SpyneArray(Attr)) def get_template_attributes(ctx, template_id): """ Get all the attributes in a template. Args param (int) template_id Returns List(Attr) """ attrs = attributes.get_template_attributes(template_id, **ctx.in_header.__dict__) return [Attr(a) for a in attrs] @rpc(SpyneArray(Attr), _returns=SpyneArray(Attr)) def get_attributes(ctx, attrs): """ Get a list of attribute, by their names and dimension. Takes a list of attribute objects, picks out their name & dimension, finds the appropriate attribute in the DB and updates the incoming attribute with an ID. The same attributes go out that came in, except this time with an ID. If one of the incoming attributes does not match, this attribute is not returned. Args: attrs (List(Attr)): A list of attribute complex models Returns: List(hydra_complexmodels.Attr): List of Attr complex models """ ret_attrs = [] for a in attrs: log.info("Getting attribute %s, %s", a.name, a.dimen) attr = attributes.get_attribute_by_name_and_dimension( a.name, a.dimen, **ctx.in_header.__dict__) if attr: a.id = attr.attr_id a.cr_date = str(attr.cr_date) a.name = attr.attr_name a.dimen = attr.attr_dimen a.description = attr.attr_description ret_attrs.append(a) else: ret_attrs.append(None) return ret_attrs @rpc(Integer, Unicode(pattern="['YN']"), _returns=ResourceAttr) def update_resource_attribute(ctx, resource_attr_id, is_var): """ Update a resource attribute (which means update the is_var flag as this is the only thing you can update on a resource attr) Args: resource_attr_id (int): ID of the complex model to be updated is_var (unicode): 'Y' or 'N' Returns: List(hydra_complexmodels.ResourceAttr): Updated ResourceAttr Raises: ResourceNotFoundError if the resource_attr_id is not in the DB """ updated_ra = attributes.update_resource_attribute( resource_attr_id, is_var, **ctx.in_header.__dict__) return ResourceAttr(updated_ra) @rpc(Integer, _returns=Unicode) def delete_resourceattr(ctx, resource_attr_id): """ Deletes a resource attribute and all associated data. ***WILL BE DEPRECATED*** Args: resource_attr_id (int): ID of the complex model to be deleted Returns: unicode: 'OK' Raises: ResourceNotFoundError if the resource_attr_id is not in the DB """ attributes.delete_resource_attribute(resource_attr_id, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, _returns=Unicode) def delete_resource_attribute(ctx, resource_attr_id): """ Add a resource attribute attribute to a resource (Duplicate of delete_resourceattr) Args: resource_attr_id (int): ID of the complex model to be deleted Returns: unicode: 'OK' Raises: ResourceNotFoundError if the resource_attr_id is not in the DB """ attributes.delete_resource_attribute(resource_attr_id, **ctx.in_header.__dict__) return "OK" @rpc(Integer, Integer, Unicode(pattern="['YN']", default='N'), _returns=ResourceAttr) def add_network_attribute(ctx, network_id, attr_id, is_var): """ Add a resource attribute to a network. Args: network_id (int): ID of the network attr_id (int): ID of the attribute to assign to the network is_var (string) 'Y' or 'N'. Indicates whether this attribute is a variable or not. (a variable is typically the result of a model run, so therefore doesn't need data assigned to it initially) Returns: hydra_complexmodels.ResourceAttr: A complex model of the newly created resource attribute. Raises: ResourceNotFoundError: If the network or attribute are not in the DB. HydraError : If the attribute is already on the network. """ new_ra = attributes.add_resource_attribute('NETWORK', network_id, attr_id, is_var, **ctx.in_header.__dict__) return ResourceAttr(new_ra) @rpc(Integer, Integer, _returns=SpyneArray(ResourceAttr)) def add_network_attrs_from_type(ctx, type_id, network_id): """ Adds all the attributes defined by a type to a network. Args: type_id (int): ID of the type used to get the resource attributes from network_id (int): ID of the network Returns: List(hydra_complexmodels.ResourceAttr): All the newly created network attributes Raises: ResourceNotFoundError if the type_id or network_id are not in the DB """ new_resource_attrs = attributes.add_resource_attrs_from_type( type_id, 'NETWORK', network_id, **ctx.in_header.__dict__) return [ResourceAttr(ra) for ra in new_resource_attrs] @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(ResourceAttr)) def get_network_attributes(ctx, network_id, type_id): """ Get all a network's attributes (not the attributes of the nodes and links. just the network itself). Args: network_id (int): ID of the network type_id (int) (optional): ID of the type. If specified will only return the resource attributes relative to that type Returns: List(hydra_complexmodels.ResourceAttr): All the network attributes Raises: ResourceNotFoundError if the type_id or network_id are not in the DB """ resource_attrs = attributes.get_resource_attributes( 'NETWORK', network_id, type_id) return [ResourceAttr(ra) for ra in resource_attrs] @rpc(Integer, Integer, Unicode(pattern="['YN']", default='N'), _returns=ResourceAttr) def add_node_attribute(ctx, node_id, attr_id, is_var): """ Add a resource attribute to a node. Args: node_id (int): The ID of the Node attr_id (int): THe ID if the attribute being added. is_var (char): Y or N. Indicates whether the attribute is a variable or not. Returns: hydra_complexmodels.ResourceAttr: The newly created node attribute Raises: ResourceNotFoundError: If the node or attribute do not exist HydraError: If this addition causes a duplicate attribute on the node. """ new_ra = attributes.add_resource_attribute('NODE', node_id, attr_id, is_var, **ctx.in_header.__dict__) return ResourceAttr(new_ra) @rpc(Integer, Integer, _returns=SpyneArray(ResourceAttr)) def add_node_attrs_from_type(ctx, type_id, node_id): """ Adds all the attributes defined by a type to a node. Args: type_id (int): ID of the type used to get the resource attributes from node_id (int): ID of the node Returns: List(hydra_complexmodels.ResourceAttr): All the newly created node attributes Raises: ResourceNotFoundError if the type_id or node_id are not in the DB """ new_resource_attrs = attributes.add_resource_attrs_from_type( type_id, 'NODE', node_id, **ctx.in_header.__dict__) return [ResourceAttr(ra) for ra in new_resource_attrs] @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(ResourceAttr)) def get_node_attributes(ctx, node_id, type_id): """ Get all a node's attributes. Args: node_id (int): ID of the node type_id (int) (optional): ID of the type. If specified will only return the resource attributes relative to that type Returns: List(hydra_complexmodels.ResourceAttr): All the node's attributes Raises: ResourceNotFoundError if the type_id or node_id do not exist. """ resource_attrs = attributes.get_resource_attributes( 'NODE', node_id, type_id) return [ResourceAttr(ra) for ra in resource_attrs] @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(ResourceAttr)) def get_all_node_attributes(ctx, network_id, template_id): """ Get all the resource attributes for all the nodes in the network. Args: network_id (int): The ID of the network that you want the node attributes from template_id (int) (optional): If this is specified, then it will only return the attributes in this template. Returns: List(hydra_complexmodels.ResourceAttr): The resource attributes of all the nodes in the network. """ resource_attrs = attributes.get_all_resource_attributes( 'NODE', network_id, template_id) return [ResourceAttr(ra) for ra in resource_attrs] @rpc(Integer, Integer, Unicode(pattern="['YN']", default='N'), _returns=ResourceAttr) def add_link_attribute(ctx, link_id, attr_id, is_var): """ Add a resource attribute to a link. Args: link_id (int): The ID of the Link attr_id (int): THe ID if the attribute being added. is_var (char): Y or N. Indicates whether the attribute is a variable or not. Returns: hydra_complexmodels.ResourceAttr: The newly created link attribute Raises: ResourceNotFoundError: If the link or attribute do not exist HydraError: If this addition causes a duplicate attribute on the link. """ new_ra = attributes.add_resource_attribute('LINK', link_id, attr_id, is_var, **ctx.in_header.__dict__) return ResourceAttr(new_ra) @rpc(Integer, Integer, _returns=SpyneArray(ResourceAttr)) def add_link_attrs_from_type(ctx, type_id, link_id): """ Adds all the attributes defined by a type to a link. Args: type_id (int): ID of the type used to get the resource attributes from link_id (int): ID of the link Returns: List(hydra_complexmodels.ResourceAttr): All the newly created link attributes Raises: ResourceNotFoundError if the type_id or link_id are not in the DB """ new_resource_attrs = attributes.add_resource_attrs_from_type( type_id, 'LINK', link_id, **ctx.in_header.__dict__) return [ResourceAttr(ra) for ra in new_resource_attrs] @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(ResourceAttr)) def get_link_attributes(ctx, link_id, type_id): """ Get all a link's attributes. Args: link_id (int): ID of the link type_id (int) (optional): ID of the type. If specified will only return the resource attributes relative to that type Returns: List(hydra_complexmodels.ResourceAttr): All the link's attributes Raises: ResourceNotFoundError if the type_id or link_id do not exist. """ resource_attrs = attributes.get_resource_attributes( 'LINK', link_id, type_id) return [ResourceAttr(ra) for ra in resource_attrs] @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(ResourceAttr)) def get_all_link_attributes(ctx, network_id, template_id): """ Get all the resource attributes for all the links in the network. Args: network_id (int): The ID of the network that you want the link attributes from template_id (int) (optional): If this is specified, then it will only return the attributes in this template. Returns: List(hydra_complexmodels.ResourceAttr): The resource attributes of all the links in the network. """ resource_attrs = attributes.get_all_resource_attributes( 'LINK', network_id, template_id) return [ResourceAttr(ra) for ra in resource_attrs] @rpc(Integer, Integer, Unicode(pattern="['YN']", default='N'), _returns=ResourceAttr) def add_group_attribute(ctx, group_id, attr_id, is_var): """ Add a resource attribute to a group. Args: group_id (int): The ID of the Group attr_id (int): THe ID if the attribute being added. is_var (char): Y or N. Indicates whether the attribute is a variable or not. Returns: hydra_complexmodels.ResourceAttr: The newly created group attribute Raises: ResourceNotFoundError: If the group or attribute do not exist HydraError: If this addition causes a duplicate attribute on the group. """ new_ra = attributes.add_resource_attribute('GROUP', group_id, attr_id, is_var, **ctx.in_header.__dict__) return ResourceAttr(new_ra) @rpc(Integer, Integer, _returns=SpyneArray(ResourceAttr)) def add_group_attrs_from_type(ctx, type_id, group_id): """ Adds all the attributes defined by a type to a group. Args: type_id (int): ID of the type used to get the resource attributes from group_id (int): ID of the group Returns: List(hydra_complexmodels.ResourceAttr): All the newly created group attributes Raises: ResourceNotFoundError if the type_id or group_id are not in the DB """ new_resource_attrs = attributes.add_resource_attrs_from_type( type_id, 'GROUP', group_id, **ctx.in_header.__dict__) return [ResourceAttr(ra) for ra in new_resource_attrs] @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(ResourceAttr)) def get_group_attributes(ctx, group_id, type_id): """ Get all a group's attributes. Args: group_id (int): ID of the group type_id (int) (optional): ID of the type. If specified will only return the resource attributes relative to that type Returns: List(hydra_complexmodels.ResourceAttr): All the group's attributes Raises: ResourceNotFoundError if the type_id or group_id do not exist. """ resource_attrs = attributes.get_resource_attributes( 'GROUP', group_id, type_id, **ctx.in_header.__dict__) return [ResourceAttr(ra) for ra in resource_attrs] @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(ResourceAttr)) def get_all_group_attributes(ctx, network_id, template_id): """ Get all the resource attributes for all the groups in the network. Args: network_id (int): The ID of the network that you want the group attributes from template_id (int) (optional): If this is specified, then it will only return the attributes in this template. Returns: List(hydra_complexmodels.ResourceAttr): The resource attributes of all the groups in the network. """ resource_attrs = attributes.get_all_resource_attributes( 'GROUP', network_id, template_id, **ctx.in_header.__dict__) return [ResourceAttr(ra) for ra in resource_attrs] @rpc(Integer, _returns=Unicode) def check_attr_dimension(ctx, attr_id): """ Check that the dimension of the resource attribute data is consistent with the definition of the attribute. If the attribute says 'volume', make sure every dataset connected with this attribute via a resource attribute also has a dimension of 'volume'. Args: attr_id (int): The ID of the attribute you want to check Returns: string: 'OK' if all is well. Raises: HydraError: If a dimension mismatch is found. """ attributes.check_attr_dimension(attr_id, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, Integer, _returns=Unicode) def set_attribute_mapping(ctx, resource_attr_a, resource_attr_b): """ Define one resource attribute from one network as being the same as that from another network. Args: resource_attr_a (int): The ID of the source resoure attribute resource_attr_b (int): The ID of the target resoure attribute Returns: string: 'OK' if all is well. Raises: ResourceNotFoundError: If either resource attribute is not found. """ attributes.set_attribute_mapping(resource_attr_a, resource_attr_b, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, Integer, _returns=Unicode) def delete_attribute_mapping(ctx, resource_attr_a, resource_attr_b): """ Delete a mapping which said one resource attribute from one network was the same as the resource attribute in another. Args: resource_attr_a (int): The ID of the source resoure attribute resource_attr_b (int): The ID of the target resoure attribute Returns: string: 'OK' if all is well. If the mapping isn't there, it'll still return 'OK', so make sure the IDs are correct! """ attributes.delete_attribute_mapping(resource_attr_a, resource_attr_b, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(ResourceAttrMap)) def get_mappings_in_network(ctx, network_id, network_2_id): """ Get all the resource attribute mappings in a network (both from and to). If another network is specified, only return the mappings between the two networks. Args: network_id (int): The network you want to check the mappings of (both from and to) network_2_id (int) (optional): The partner network Returns: List(hydra_complexmodels.ResourceAttrMap): All the mappings to and from the network(s) in question. """ mapping_rs = attributes.get_mappings_in_network( network_id, network_2_id, **ctx.in_header.__dict__) mappings = [ResourceAttrMap(m) for m in mapping_rs] return mappings @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=Unicode) def delete_mappings_in_network(ctx, network_id, network_2_id): """ Delete all the resource attribute mappings in a network. If another network is specified, only delete the mappings between the two networks. Args: network_id (int): The network you want to delete the mappings from (both from and to) network_2_id (int) (optional): The partner network Returns: string: 'OK' """ attributes.delete_mappings_in_network(network_id, network_2_id, **ctx.in_header.__dict__) return 'OK' @rpc(Integer, Integer(min_occurs=0, max_occurs=1), _returns=SpyneArray(ResourceAttrMap)) def get_node_mappings(ctx, node_id, node_2_id): """ Get the mappings for all the attributes of a given node. If a second node is specified, return only the mappings between these nodes.. Args: node_id (int): The node you want to delete the mappings from (both from and to) node_2_id (int) (optional): The partner node Returns: List(hydra_complexmodels.ResourceAttrMap): All the mappings to and from the node(s) in question. """ mapping_rs = attributes.get_node_mappings(node_id, node_2_id, **ctx.in_header.__dict__) mappings = [ResourceAttrMap(m) for m in mapping_rs] return mappings @rpc(Integer, Integer, _returns=Unicode) def check_mapping_exists(ctx, resource_attr_id_source, resource_attr_id_target): """ Check whether a mapping exists between two resource attributes This does not check whether a reverse mapping exists, so order is important here. Args: resource_attr_id_source (int): The source resource attribute resource_attr_id_target (int) (optional): The target resource attribute Returns: string: 'Y' if a mapping between the source and target exists. 'N' in every other case. """ is_mapped = attributes.check_attribute_mapping_exists( resource_attr_id_source, resource_attr_id_target, **ctx.in_header.__dict__) return is_mapped
def test_unicode_nullable_mult_cust_false(self): assert Unicode(nullable=False).Attributes.nullable == False assert Unicode(nullable=False)(5).Attributes.nullable == False
class City(ComplexModelBase): cityName = Unicode(255) cityTZDeltaSeconds = Integer(ge=-43200, le=43200)
def test_new_type(self): """Customized primitives go into namespace based on module name.""" custom_type = Unicode(pattern='123') self.assertEqual(custom_type.get_namespace(), custom_type.__module__)
class Address(ComplexModelBase): addressPlace = Place addressStreet = Unicode(255) addressHouse = Unicode(255) addressPorch = Unicode(255) addressInfo = Unicode
def test_simple_type_explicit_customization(self): assert Unicode(max_len=5).__extends__ is not None assert Unicode.customize(max_len=5).__extends__ is not None
# -*- encoding: utf-8 -*- ''' Implementation of the internap authentication token server. ''' from __future__ import print_function import logging from spyne.service import ServiceBase from spyne.decorator import rpc from spyne.model.complex import ComplexModel from spyne.model.primitive import Integer, Unicode from spyne.util.simple import wsgi_soap_application StringType = Unicode.customize(type_name='string', nillable=False) class Authenticate(ComplexModel): strAccount = StringType strToken = StringType strReferrer = StringType strSourceURL = StringType strClientIP = StringType class Attributes(ComplexModel.Attributes): nillable = False min_occurs = 1 class AuthenticateResponse(ComplexModel):