diff --git a/.mock/definition/__package__.yml b/.mock/definition/__package__.yml index 15b10135d..3bff07c40 100644 --- a/.mock/definition/__package__.yml +++ b/.mock/definition/__package__.yml @@ -187,107 +187,145 @@ types: Serializer get numbers from project queryset annotation, make sure, that you use correct one(Project.objects.with_counts()) properties: + show_ground_truth_first: optional + rejected: string + label_config: + type: optional + docs: Label config in XML format. See more about it in documentation + show_instruction: + type: optional + docs: Show instructions to the annotator before they start + duplication_status: optional + control_weights: optional + workspace: string + finished_task_number: integer + show_skip_button: + type: optional + docs: Show a skip button in interface and allow annotators to skip the task + created_by: + type: optional + docs: Project owner + assignment_settings: AssignmentSettings + reviewed_number: string + model_version: + type: optional + docs: Machine learning model version + data_types: unknown + description_short: string + queue_left: string + annotation_limit_percent: + type: optional + validation: + pattern: ^-?\d{0,3}(?:\.\d{0,2})?$ + config_has_control_tags: + type: boolean + docs: Flag to detect is project ready for labeling + total_predictions_number: integer + useful_annotation_number: string + custom_script: optional + reviewer_queue_total: string + start_training_on_annotation_update: + type: boolean + docs: Start model training after any annotations are submitted or updated + skipped_annotations_number: string + custom_task_lock_ttl: + type: optional + docs: TTL in seconds for task reservations, on new and existing tasks + validation: + min: 1 + max: 86400 workspace_title: string - ready: string - overlap_cohort_percentage: + sampling: optional + reveal_preannotations_interactively: + type: optional + docs: Reveal pre-annotations interactively + id: integer + has_blueprints: string + queue_done: string + total_annotations_number: string + members_count: string + maximum_annotations: type: optional + docs: >- + Maximum number of annotations for one task. If the number of + annotations per task is equal or greater to this value, the task is + completed (is_labeled=True) validation: min: -2147483648 max: 2147483647 - queue_left: string + comment_classification_config: optional + prompts: string + created_at: datetime + ready: string + annotator_evaluation_minimum_tasks: + type: optional + default: 10 + validation: + min: 0 config_suitable_for_bulk_annotation: type: boolean docs: Flag to detect is project ready for bulk annotation - has_blueprints: string + skip_queue: optional + title: + type: optional + docs: Project name. Must be between 3 and 50 characters long. + validation: + minLength: 3 + maxLength: 50 show_overlap_first: optional queue_total: string - enable_empty_annotation: + organization: optional + duplication_done: type: optional - docs: Allow annotators to submit empty annotations - custom_task_lock_ttl: + default: false + ground_truth_number: + type: integer + docs: Honeypot annotation number in project + annotation_limit_count: type: optional - docs: TTL in seconds for task reservations, on new and existing tasks validation: min: 1 - max: 86400 - prompts: string - start_training_on_annotation_update: - type: boolean - docs: Start model training after any annotations are submitted or updated evaluate_predictions_automatically: type: optional docs: Retrieve and display predictions when loading a task - show_instruction: - type: optional - docs: Show instructions to the annotator before they start + blueprints: list color: type: optional validation: maxLength: 16 - sampling: optional - created_by: - type: optional - docs: Project owner - reveal_preannotations_interactively: - type: optional - docs: Reveal pre-annotations interactively + review_settings: ReviewSettings pinned_at: type: optional docs: Pinned date and time - finished_task_number: integer - parsed_label_config: unknown - duplication_done: + members: string + require_comment_on_skip: type: optional default: false - reviewer_queue_total: string - show_ground_truth_first: optional + show_annotation_history: + type: optional + docs: Show annotation history to annotator task_number: type: integer docs: Total task number in project - num_tasks_with_annotations: string - description_short: string - id: integer - allow_stream: string - annotation_limit_percent: - type: optional - validation: - pattern: ^-?\d{0,3}(?:\.\d{0,2})?$ - created_at: datetime - annotation_limit_count: - type: optional - validation: - min: 1 - queue_done: string - control_weights: optional - data_types: unknown - reviewed_number: string - total_annotations_number: string - total_predictions_number: integer - config_has_control_tags: - type: boolean - docs: Flag to detect is project ready for labeling - blueprints: list is_published: type: optional docs: Whether or not the project is published to annotators - duplication_status: optional - review_total_tasks: string - show_skip_button: - type: optional - docs: Show a skip button in interface and allow annotators to skip the task - is_draft: + show_collab_predictions: type: optional - docs: Whether or not the project is in the middle of being created - title: + docs: If set, the annotator can view model predictions + review_total_tasks: string + num_tasks_with_annotations: string + expert_instruction: type: optional - docs: Project name. Must be between 3 and 50 characters long. + docs: Labeling instructions in HTML format + overlap_cohort_percentage: + type: optional validation: - minLength: 3 - maxLength: 50 - show_collab_predictions: + min: -2147483648 + max: 2147483647 + is_draft: type: optional - docs: If set, the annotator can view model predictions - members: string + docs: Whether or not the project is in the middle of being created min_annotations_to_start_training: type: optional docs: >- @@ -296,60 +334,22 @@ types: validation: min: -2147483648 max: 2147483647 - workspace: string - organization: optional - assignment_settings: AssignmentSettings - annotator_evaluation_minimum_tasks: - type: optional - default: 10 - validation: - min: 0 - skipped_annotations_number: string + enable_empty_annotation: + type: optional + docs: Allow annotators to submit empty annotations annotator_evaluation_minimum_score: type: optional default: '95.00' validation: pattern: ^-?\d{0,3}(?:\.\d{0,2})?$ - comment_classification_config: optional description: type: optional docs: Project description - expert_instruction: - type: optional - docs: Labeling instructions in HTML format - show_annotation_history: - type: optional - docs: Show annotation history to annotator - skip_queue: optional - review_settings: ReviewSettings - members_count: string - model_version: - type: optional - docs: Machine learning model version - useful_annotation_number: string - custom_script: optional - require_comment_on_skip: - type: optional - default: false - ground_truth_number: - type: integer - docs: Honeypot annotation number in project pause_on_failed_annotator_evaluation: type: optional default: false - label_config: - type: optional - docs: Label config in XML format. See more about it in documentation - maximum_annotations: - type: optional - docs: >- - Maximum number of annotations for one task. If the number of - annotations per task is equal or greater to this value, the task is - completed (is_labeled=True) - validation: - min: -2147483648 - max: 2147483647 - rejected: string + allow_stream: string + parsed_label_config: unknown source: openapi: openapi/openapi.yaml AnnotatedEnum: @@ -1363,6 +1363,73 @@ types: results: list source: openapi: openapi/openapi.yaml + BillingChecks: + properties: + users: CountLimit + projects: CountLimit + results: CountLimit + trial_days: integer + organization_is_active: boolean + license_issued: + type: optional + validation: + format: date + license_warning: + type: optional + validation: + format: date + is_license_warning: boolean + license_expires: + type: optional + validation: + format: date + is_license_expired: boolean + prompts_enabled: boolean + prompts_status: PromptsStatusEnum + prompts_warning: optional + is_prompts_warning: boolean + prompts_expire: optional + is_prompts_expire: boolean + prompts_api_keys_enabled: boolean + import_storages: CountLimit + export_storages: CountLimit + source: + openapi: openapi/openapi.yaml + BillingFlags: + properties: + activated_at: optional + cloud_instance: boolean + allow_activity_log: boolean + allow_invite_project_experts: boolean + allow_sso: boolean + white_label_id: optional + allow_data_credentials: boolean + allow_organization_webhooks: boolean + disable_members_page: boolean + secure_mode: boolean + manual_workspace_management: boolean + manual_role_management: boolean + hide_storage_settings_for_manager: boolean + disable_project_imports: boolean + automax_token_exists: boolean + automax_enabled: boolean + storage_persistence: boolean + allow_ai: boolean + early_adopter: boolean + allow_ask_ai: boolean + allow_invite_people: boolean + allow_storage_proxy: boolean + embed_enabled: boolean + embed_domains: optional>> + embed_settings: optional> + source: + openapi: openapi/openapi.yaml + BillingInfoResponse: + properties: + billing_checks: BillingChecks + billing_flags: BillingFlags + source: + openapi: openapi/openapi.yaml BlankEnum: literal<""> Blueprint: properties: @@ -1573,6 +1640,14 @@ types: docs: Traceback report in case of errors source: openapi: openapi/openapi.yaml + CountLimit: + properties: + count: integer + limit: integer + reached: boolean + total: optional + source: + openapi: openapi/openapi.yaml CustomScriptsEditableByEnum: enum: - AD @@ -5878,6 +5953,38 @@ types: organization: optional source: openapi: openapi/openapi.yaml + PromptsStatusEnum: + enum: + - Enabled + - value: Cloud license per organization disabled + name: CloudLicensePerOrganizationDisabled + - value: On-premise global license disabled + name: OnPremiseGlobalLicenseDisabled + - Expired + - value: Adala not connected + name: AdalaNotConnected + - value: Disabled for this organization [FF] + name: DisabledForThisOrganizationFf + - unknown + docs: >- + * `Enabled` - Enabled + + * `Cloud license per organization disabled` - Cloud license per + organization disabled + + * `On-premise global license disabled` - On-premise global license + disabled + + * `Expired` - Expired + + * `Adala not connected` - Adala not connected + + * `Disabled for this organization [FF]` - Disabled for this organization + [FF] + + * `unknown` - unknown + source: + openapi: openapi/openapi.yaml ProviderEnum: enum: - OpenAI diff --git a/.mock/definition/billing.yml b/.mock/definition/billing.yml new file mode 100644 index 000000000..8f39d6a46 --- /dev/null +++ b/.mock/definition/billing.yml @@ -0,0 +1,244 @@ +imports: + root: __package__.yml +service: + auth: false + base-path: '' + endpoints: + info: + path: /api/billing/info + method: GET + auth: true + docs: Retrieve billing checks and feature flags for the active organization. + source: + openapi: openapi/openapi.yaml + display-name: Get billing info + response: + docs: Billing information for the active organization + type: root.BillingInfoResponse + examples: + - name: real-sample + response: + body: + billing_checks: + users: + count: 110 + limit: 1000 + reached: false + total: 221 + projects: + count: 2044 + limit: 1000000 + reached: false + total: 1 + results: + count: 42949 + limit: 1000000000 + reached: false + total: 1 + trial_days: 0 + organization_is_active: true + license_issued: '2000-01-01' + license_warning: '2030-01-01' + is_license_warning: false + license_expires: '2030-01-02' + is_license_expired: false + prompts_enabled: true + prompts_status: Enabled + prompts_warning: prompts_warning + is_prompts_warning: false + prompts_expire: prompts_expire + is_prompts_expire: false + prompts_api_keys_enabled: true + import_storages: + count: 0 + limit: 0 + reached: false + total: 1 + export_storages: + count: 0 + limit: 0 + reached: false + total: 1 + billing_flags: + activated_at: '2024-01-15T09:30:00Z' + cloud_instance: true + allow_activity_log: true + allow_invite_project_experts: true + allow_sso: true + white_label_id: white_label_id + allow_data_credentials: false + allow_organization_webhooks: false + disable_members_page: false + secure_mode: false + manual_workspace_management: true + manual_role_management: true + hide_storage_settings_for_manager: false + disable_project_imports: false + automax_token_exists: true + automax_enabled: true + storage_persistence: true + allow_ai: true + early_adopter: true + allow_ask_ai: true + allow_invite_people: true + allow_storage_proxy: true + embed_enabled: true + embed_domains: + - domain: http://localhost:3000 + - domain: https://purple-zoos-flash.loca.lt + embed_settings: + public_verify_alg: + - RS256 + public_verify_key: .... + - name: cloud + response: + body: + billing_checks: + users: + count: 5 + limit: 10 + reached: false + total: 6 + projects: + count: 3 + limit: 50 + reached: false + total: 1 + results: + count: 100 + limit: 1000 + reached: false + total: 1 + trial_days: 14 + organization_is_active: true + license_issued: '2023-01-01' + license_warning: '2024-12-01' + is_license_warning: false + license_expires: '2025-01-01' + is_license_expired: false + prompts_enabled: true + prompts_status: Enabled + prompts_warning: prompts_warning + is_prompts_warning: false + prompts_expire: '2024-12-31' + is_prompts_expire: false + prompts_api_keys_enabled: true + import_storages: + count: 0 + limit: 0 + reached: false + total: 1 + export_storages: + count: 0 + limit: 0 + reached: false + total: 1 + billing_flags: + activated_at: '2023-01-01T00:00:00Z' + cloud_instance: true + allow_activity_log: true + allow_invite_project_experts: true + allow_sso: false + white_label_id: white_label_id + allow_data_credentials: true + allow_organization_webhooks: true + disable_members_page: false + secure_mode: false + manual_workspace_management: false + manual_role_management: false + hide_storage_settings_for_manager: false + disable_project_imports: false + automax_token_exists: false + automax_enabled: true + storage_persistence: true + allow_ai: true + early_adopter: false + allow_ask_ai: true + allow_invite_people: true + allow_storage_proxy: true + embed_enabled: false + embed_domains: + - domain: http://localhost:3000 + - domain: https://example.com + embed_settings: + public_verify_alg: + - RS256 + public_verify_key: .... + - name: enterprise + response: + body: + billing_checks: + users: + count: 20 + limit: 100 + reached: false + total: 22 + projects: + count: 15 + limit: 200 + reached: false + total: 1 + results: + count: 25000 + limit: 100000 + reached: false + total: 1 + trial_days: 0 + organization_is_active: true + license_issued: '2023-01-01' + license_warning: '2024-12-01' + is_license_warning: false + license_expires: '2025-01-01' + is_license_expired: false + prompts_enabled: true + prompts_status: Enabled + prompts_warning: prompts_warning + is_prompts_warning: false + prompts_expire: prompts_expire + is_prompts_expire: false + prompts_api_keys_enabled: true + import_storages: + count: 0 + limit: 0 + reached: false + total: 1 + export_storages: + count: 0 + limit: 0 + reached: false + total: 1 + billing_flags: + activated_at: '2024-01-15T09:30:00Z' + cloud_instance: false + allow_activity_log: true + allow_invite_project_experts: true + allow_sso: true + white_label_id: wl-1 + allow_data_credentials: true + allow_organization_webhooks: true + disable_members_page: false + secure_mode: false + manual_workspace_management: false + manual_role_management: false + hide_storage_settings_for_manager: false + disable_project_imports: false + automax_token_exists: true + automax_enabled: true + storage_persistence: true + allow_ai: false + early_adopter: true + allow_ask_ai: true + allow_invite_people: true + allow_storage_proxy: true + embed_enabled: false + embed_domains: + - domain: http://localhost:3000 + - domain: https://example.com + embed_settings: + public_verify_alg: + - RS256 + public_verify_key: .... + audiences: + - public + source: + openapi: openapi/openapi.yaml diff --git a/.mock/definition/organizations.yml b/.mock/definition/organizations.yml index 9b27c1d91..80d05e163 100644 --- a/.mock/definition/organizations.yml +++ b/.mock/definition/organizations.yml @@ -157,242 +157,6 @@ service: custom_scripts_enabled: custom_scripts_enabled custom_scripts_editable_by: AD email_notification_settings: email_notification_settings - api_organizations_memberships_list: - path: /api/organizations/{id}/memberships - method: GET - auth: true - docs: Retrieve a list of all users and roles in a specific organization. - source: - openapi: openapi/openapi.yaml - path-parameters: - id: - type: integer - docs: A unique integer value identifying this organization. - display-name: Get organization members/roles - request: - name: ApiOrganizationsMembershipsListRequest - query-parameters: - exclude_project_id: - type: optional - docs: >- - Project ID to exclude users who are already associated with this - project (direct members, workspace members, or implicit - admin/owner access). - exclude_workspace_id: - type: optional - docs: >- - Workspace ID to exclude users who are already associated with this - workspace (direct workspace members or implicit admin/owner - access). - ordering: - type: optional - docs: Which field to use when ordering the results. - page: - type: optional - docs: A page number within the paginated result set. - page_size: - type: optional - docs: Number of results to return per page. - search: - type: optional - docs: A search term. - response: - docs: '' - type: root.PaginatedLseOrganizationMemberListList - examples: - - path-parameters: - id: 1 - response: - body: - count: 123 - next: http://api.example.org/accounts/?page=4 - previous: http://api.example.org/accounts/?page=2 - results: - - id: 1 - organization: 1 - user: - id: 1 - username: username - last_activity: '2024-01-15T09:30:00Z' - avatar: avatar - initials: initials - lse_fields: - invite_expired: invite_expired - invite_expired_at: invite_expired_at - email_notification_settings: email_notification_settings - pause: pause - created_projects: created_projects - contributed_to_projects: contributed_to_projects - role: role - api_organizations_memberships_create: - path: /api/organizations/{id}/memberships - method: POST - auth: true - docs: |2- - - Assign a role to a user in an organization. To do so, make the following cURL request: - - ```bash - curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123' \ - -X POST 'https://label-studio-host/api/organizations/{{id}}/memberships' --data '[{{"user_id": Int, "role": "NO|DI|OW|AD|MA|AN|RE" }}]' - ``` - - Enumerate a role with one of the following abbreviations: - - | Role | Full Role Name | - | --- | --- | - | NO | Not Activated | - | DI | Deactivated | - | OW | Owner | - | AD | Administrator | - | MA | Manager | - | AN | Annotator | - | RE | Reviewer | - - For example, to set a user with an ID of 9 as an annotator, make the following cURL request: - ```bash - curl -H 'Content-Type: application/json' -H 'Authorization: Token abc123' \ - -X POST 'https://label-studio-host/api/organizations/{{id}}/memberships' --data '[{{"user_id": 9, "role": "AN" }}]' - ``` - - source: - openapi: openapi/openapi.yaml - path-parameters: - id: - type: integer - docs: A unique integer value identifying this organization. - display-name: Create organization member/role - request: - name: OrganizationMemberCreateUpdateRequest - body: - properties: - user_id: integer - role: root.Role9E7Enum - content-type: application/json - response: - docs: '' - type: root.LseOrganizationMemberList - examples: - - path-parameters: - id: 1 - request: - user_id: 1 - role: OW - response: - body: - id: 1 - organization: 1 - user: - id: 1 - first_name: first_name - last_name: last_name - username: username - email: email - last_activity: '2024-01-15T09:30:00Z' - custom_hotkeys: - key: value - avatar: avatar - initials: initials - phone: phone - active_organization: 1 - allow_newsletters: true - date_joined: '2024-01-15T09:30:00Z' - lse_fields: - invite_expired: invite_expired - invite_expired_at: invite_expired_at - invited_at: '2024-01-15T09:30:00Z' - invite_activated: true - trial_company: trial_company - trial_role: annotator - trial_models_in_production: trial_models_in_production - trial_experience_labeling: trial_experience_labeling - trial_license_enterprise: true - social_auth_finished: true - invited_by: 1 - onboarding_state: not_started - email_notification_settings: email_notification_settings - pause: pause - created_projects: created_projects - contributed_to_projects: contributed_to_projects - role: role - api_organizations_memberships_partial_update: - path: /api/organizations/{id}/memberships - method: PATCH - auth: true - docs: |2- - - Update organization membership or role for a specific user ID. - - **User Rotation Best Practices for API Usage** - - To maintain compliance with our licensing terms and ensure optimal performance of HumanSignal's APIs, please consider the following guidelines when managing user assignments: - - * **Maintain a 7-Day Minimum Assignment**: Once a licensed seat is assigned to a user, maintain that assignment for at least seven consecutive days before rotating it to another user. - - * **Automate, Monitor, and Log Rotations**: Implement automated scheduling and logging mechanisms to track the timing of user rotations. This helps ensure that rotations adhere to the seven-day minimum period. - - * **Adhere to API Update Frequency and Wait Periods**: When updating user assignments via our APIs, follow the recommended frequency and wait period guidelines provided in the HumanSignal API documentation. Avoid sending rapid, successive requests that might overload the endpoint. Instead, incorporate appropriate delays between calls as specified in the documentation. - - * **Avoid Overloading the API Endpoint**: Design your integration to batch or schedule updates where possible, and implement backoff strategies if the API indicates rate limiting. This helps prevent service disruptions and ensures a smooth operation. - - source: - openapi: openapi/openapi.yaml - path-parameters: - id: - type: integer - docs: A unique integer value identifying this organization. - display-name: Update organization member/role - request: - name: PatchedOrganizationMemberCreateUpdateRequest - body: - properties: - user_id: optional - role: optional - content-type: application/json - response: - docs: '' - type: root.LseOrganizationMemberList - examples: - - path-parameters: - id: 1 - request: {} - response: - body: - id: 1 - organization: 1 - user: - id: 1 - first_name: first_name - last_name: last_name - username: username - email: email - last_activity: '2024-01-15T09:30:00Z' - custom_hotkeys: - key: value - avatar: avatar - initials: initials - phone: phone - active_organization: 1 - allow_newsletters: true - date_joined: '2024-01-15T09:30:00Z' - lse_fields: - invite_expired: invite_expired - invite_expired_at: invite_expired_at - invited_at: '2024-01-15T09:30:00Z' - invite_activated: true - trial_company: trial_company - trial_role: annotator - trial_models_in_production: trial_models_in_production - trial_experience_labeling: trial_experience_labeling - trial_license_enterprise: true - social_auth_finished: true - invited_by: 1 - onboarding_state: not_started - email_notification_settings: email_notification_settings - pause: pause - created_projects: created_projects - contributed_to_projects: contributed_to_projects - role: role api_organizations_set_default_role_partial_update: path: /api/organizations/{id}/set-default-role method: PATCH diff --git a/.mock/definition/organizations/members.yml b/.mock/definition/organizations/members.yml index ba50350df..3bfec0a23 100644 --- a/.mock/definition/organizations/members.yml +++ b/.mock/definition/organizations/members.yml @@ -4,6 +4,174 @@ service: auth: false base-path: '' endpoints: + list: + path: /api/organizations/{id}/memberships + method: GET + auth: true + docs: Retrieve a list of all users and roles in a specific organization. + source: + openapi: openapi/openapi.yaml + path-parameters: + id: + type: integer + docs: A unique integer value identifying this organization. + display-name: Get organization members/roles + request: + name: MembersListRequest + query-parameters: + exclude_project_id: + type: optional + docs: >- + Project ID to exclude users who are already associated with this + project (direct members, workspace members, or implicit + admin/owner access). + exclude_workspace_id: + type: optional + docs: >- + Workspace ID to exclude users who are already associated with this + workspace (direct workspace members or implicit admin/owner + access). + ordering: + type: optional + docs: Which field to use when ordering the results. + page: + type: optional + docs: A page number within the paginated result set. + page_size: + type: optional + docs: Number of results to return per page. + search: + type: optional + docs: A search term. + response: + docs: '' + type: root.PaginatedLseOrganizationMemberListList + examples: + - path-parameters: + id: 1 + response: + body: + count: 123 + next: http://api.example.org/accounts/?page=4 + previous: http://api.example.org/accounts/?page=2 + results: + - id: 1 + organization: 1 + user: + id: 1 + username: username + last_activity: '2024-01-15T09:30:00Z' + avatar: avatar + initials: initials + lse_fields: + invite_expired: invite_expired + invite_expired_at: invite_expired_at + email_notification_settings: email_notification_settings + pause: pause + created_projects: created_projects + contributed_to_projects: contributed_to_projects + role: role + audiences: + - public + update: + path: /api/organizations/{id}/memberships + method: PATCH + auth: true + docs: >+ + Update organization membership or role for a specific user ID. + + + **User Rotation Best Practices for API Usage** + + + To maintain compliance with our licensing terms and ensure optimal + performance of HumanSignal's APIs, please consider the following + guidelines when managing user assignments: + + + * **Maintain a 7-Day Minimum Assignment**: Once a licensed seat is + assigned to a user, maintain that assignment for at least seven + consecutive days before rotating it to another user. + + + * **Automate, Monitor, and Log Rotations**: Implement automated + scheduling and logging mechanisms to track the timing of user rotations. + This helps ensure that rotations adhere to the seven-day minimum period. + + + * **Adhere to API Update Frequency and Wait Periods**: When updating + user assignments via our APIs, follow the recommended frequency and wait + period guidelines provided in the HumanSignal API documentation. Avoid + sending rapid, successive requests that might overload the endpoint. + Instead, incorporate appropriate delays between calls as specified in + the documentation. + + + * **Avoid Overloading the API Endpoint**: Design your integration to + batch or schedule updates where possible, and implement backoff + strategies if the API indicates rate limiting. This helps prevent + service disruptions and ensures a smooth operation. + + source: + openapi: openapi/openapi.yaml + path-parameters: + id: + type: integer + docs: A unique integer value identifying this organization. + display-name: Update organization member/role + request: + name: PatchedOrganizationMemberCreateUpdateRequest + body: + properties: + user_id: optional + role: optional + content-type: application/json + response: + docs: '' + type: root.LseOrganizationMemberList + examples: + - path-parameters: + id: 1 + request: {} + response: + body: + id: 1 + organization: 1 + user: + id: 1 + first_name: first_name + last_name: last_name + username: username + email: email + last_activity: '2024-01-15T09:30:00Z' + custom_hotkeys: + key: value + avatar: avatar + initials: initials + phone: phone + active_organization: 1 + allow_newsletters: true + date_joined: '2024-01-15T09:30:00Z' + lse_fields: + invite_expired: invite_expired + invite_expired_at: invite_expired_at + invited_at: '2024-01-15T09:30:00Z' + invite_activated: true + trial_company: trial_company + trial_role: annotator + trial_models_in_production: trial_models_in_production + trial_experience_labeling: trial_experience_labeling + trial_license_enterprise: true + social_auth_finished: true + invited_by: 1 + onboarding_state: not_started + email_notification_settings: email_notification_settings + pause: pause + created_projects: created_projects + contributed_to_projects: contributed_to_projects + role: role + audiences: + - public get: path: /api/organizations/{id}/memberships/{user_pk}/ method: GET diff --git a/.mock/definition/projects.yml b/.mock/definition/projects.yml index 7a45604b3..9597946f4 100644 --- a/.mock/definition/projects.yml +++ b/.mock/definition/projects.yml @@ -160,89 +160,89 @@ service: next: http://api.example.org/accounts/?page=4 previous: http://api.example.org/accounts/?page=2 results: - - workspace_title: workspace_title - ready: ready - overlap_cohort_percentage: 1 - queue_left: queue_left - config_suitable_for_bulk_annotation: true - has_blueprints: has_blueprints - show_overlap_first: true - queue_total: queue_total - enable_empty_annotation: true - custom_task_lock_ttl: 1 - prompts: prompts - start_training_on_annotation_update: true - evaluate_predictions_automatically: true + - show_ground_truth_first: true + rejected: rejected + label_config: label_config show_instruction: true - color: color - sampling: Sequential sampling + duplication_status: duplication_status + control_weights: + key: value + workspace: workspace + finished_task_number: 1 + show_skip_button: true created_by: id: 1 avatar: avatar - reveal_preannotations_interactively: true - pinned_at: '2024-01-15T09:30:00Z' - finished_task_number: 1 - parsed_label_config: + assignment_settings: + id: 1 + reviewed_number: reviewed_number + model_version: model_version + data_types: key: value - duplication_done: true - reviewer_queue_total: reviewer_queue_total - show_ground_truth_first: true - task_number: 1 - num_tasks_with_annotations: num_tasks_with_annotations description_short: description_short - id: 1 - allow_stream: allow_stream + queue_left: queue_left annotation_limit_percent: annotation_limit_percent - created_at: '2024-01-15T09:30:00Z' - annotation_limit_count: 1 + config_has_control_tags: true + total_predictions_number: 1 + useful_annotation_number: useful_annotation_number + custom_script: custom_script + reviewer_queue_total: reviewer_queue_total + start_training_on_annotation_update: true + skipped_annotations_number: skipped_annotations_number + custom_task_lock_ttl: 1 + workspace_title: workspace_title + sampling: Sequential sampling + reveal_preannotations_interactively: true + id: 1 + has_blueprints: has_blueprints queue_done: queue_done - control_weights: - key: value - data_types: - key: value - reviewed_number: reviewed_number total_annotations_number: total_annotations_number - total_predictions_number: 1 - config_has_control_tags: true + members_count: members_count + maximum_annotations: 1 + comment_classification_config: comment_classification_config + prompts: prompts + created_at: '2024-01-15T09:30:00Z' + ready: ready + annotator_evaluation_minimum_tasks: 1 + config_suitable_for_bulk_annotation: true + skip_queue: REQUEUE_FOR_ME + title: title + show_overlap_first: true + queue_total: queue_total + organization: 1 + duplication_done: true + ground_truth_number: 1 + annotation_limit_count: 1 + evaluate_predictions_automatically: true blueprints: - id: 1 share_id: share_id short_url: short_url created_at: '2024-01-15T09:30:00Z' + color: color + review_settings: + id: 1 + requeue_rejected_tasks_to_annotator: true + pinned_at: '2024-01-15T09:30:00Z' + members: members + require_comment_on_skip: true + show_annotation_history: true + task_number: 1 is_published: true - duplication_status: duplication_status + show_collab_predictions: true review_total_tasks: review_total_tasks - show_skip_button: true + num_tasks_with_annotations: num_tasks_with_annotations + expert_instruction: expert_instruction + overlap_cohort_percentage: 1 is_draft: true - title: title - show_collab_predictions: true - members: members min_annotations_to_start_training: 1 - workspace: workspace - organization: 1 - assignment_settings: - id: 1 - annotator_evaluation_minimum_tasks: 1 - skipped_annotations_number: skipped_annotations_number + enable_empty_annotation: true annotator_evaluation_minimum_score: annotator_evaluation_minimum_score - comment_classification_config: comment_classification_config description: description - expert_instruction: expert_instruction - show_annotation_history: true - skip_queue: REQUEUE_FOR_ME - review_settings: - id: 1 - requeue_rejected_tasks_to_annotator: true - members_count: members_count - model_version: model_version - useful_annotation_number: useful_annotation_number - custom_script: custom_script - require_comment_on_skip: true - ground_truth_number: 1 pause_on_failed_annotator_evaluation: true - label_config: label_config - maximum_annotations: 1 - rejected: rejected + allow_stream: allow_stream + parsed_label_config: + key: value audiences: - public create: diff --git a/.mock/definition/prompts.yml b/.mock/definition/prompts.yml index 39429ebb4..537d82924 100644 --- a/.mock/definition/prompts.yml +++ b/.mock/definition/prompts.yml @@ -424,89 +424,89 @@ service: next: http://api.example.org/accounts/?page=4 previous: http://api.example.org/accounts/?page=2 results: - - workspace_title: workspace_title - ready: ready - overlap_cohort_percentage: 1 - queue_left: queue_left - config_suitable_for_bulk_annotation: true - has_blueprints: has_blueprints - show_overlap_first: true - queue_total: queue_total - enable_empty_annotation: true - custom_task_lock_ttl: 1 - prompts: prompts - start_training_on_annotation_update: true - evaluate_predictions_automatically: true + - show_ground_truth_first: true + rejected: rejected + label_config: label_config show_instruction: true - color: color - sampling: Sequential sampling + duplication_status: duplication_status + control_weights: + key: value + workspace: workspace + finished_task_number: 1 + show_skip_button: true created_by: id: 1 avatar: avatar - reveal_preannotations_interactively: true - pinned_at: '2024-01-15T09:30:00Z' - finished_task_number: 1 - parsed_label_config: + assignment_settings: + id: 1 + reviewed_number: reviewed_number + model_version: model_version + data_types: key: value - duplication_done: true - reviewer_queue_total: reviewer_queue_total - show_ground_truth_first: true - task_number: 1 - num_tasks_with_annotations: num_tasks_with_annotations description_short: description_short - id: 1 - allow_stream: allow_stream + queue_left: queue_left annotation_limit_percent: annotation_limit_percent - created_at: '2024-01-15T09:30:00Z' - annotation_limit_count: 1 + config_has_control_tags: true + total_predictions_number: 1 + useful_annotation_number: useful_annotation_number + custom_script: custom_script + reviewer_queue_total: reviewer_queue_total + start_training_on_annotation_update: true + skipped_annotations_number: skipped_annotations_number + custom_task_lock_ttl: 1 + workspace_title: workspace_title + sampling: Sequential sampling + reveal_preannotations_interactively: true + id: 1 + has_blueprints: has_blueprints queue_done: queue_done - control_weights: - key: value - data_types: - key: value - reviewed_number: reviewed_number total_annotations_number: total_annotations_number - total_predictions_number: 1 - config_has_control_tags: true + members_count: members_count + maximum_annotations: 1 + comment_classification_config: comment_classification_config + prompts: prompts + created_at: '2024-01-15T09:30:00Z' + ready: ready + annotator_evaluation_minimum_tasks: 1 + config_suitable_for_bulk_annotation: true + skip_queue: REQUEUE_FOR_ME + title: title + show_overlap_first: true + queue_total: queue_total + organization: 1 + duplication_done: true + ground_truth_number: 1 + annotation_limit_count: 1 + evaluate_predictions_automatically: true blueprints: - id: 1 share_id: share_id short_url: short_url created_at: '2024-01-15T09:30:00Z' + color: color + review_settings: + id: 1 + requeue_rejected_tasks_to_annotator: true + pinned_at: '2024-01-15T09:30:00Z' + members: members + require_comment_on_skip: true + show_annotation_history: true + task_number: 1 is_published: true - duplication_status: duplication_status + show_collab_predictions: true review_total_tasks: review_total_tasks - show_skip_button: true + num_tasks_with_annotations: num_tasks_with_annotations + expert_instruction: expert_instruction + overlap_cohort_percentage: 1 is_draft: true - title: title - show_collab_predictions: true - members: members min_annotations_to_start_training: 1 - workspace: workspace - organization: 1 - assignment_settings: - id: 1 - annotator_evaluation_minimum_tasks: 1 - skipped_annotations_number: skipped_annotations_number + enable_empty_annotation: true annotator_evaluation_minimum_score: annotator_evaluation_minimum_score - comment_classification_config: comment_classification_config description: description - expert_instruction: expert_instruction - show_annotation_history: true - skip_queue: REQUEUE_FOR_ME - review_settings: - id: 1 - requeue_rejected_tasks_to_annotator: true - members_count: members_count - model_version: model_version - useful_annotation_number: useful_annotation_number - custom_script: custom_script - require_comment_on_skip: true - ground_truth_number: 1 pause_on_failed_annotator_evaluation: true - label_config: label_config - maximum_annotations: 1 - rejected: rejected + allow_stream: allow_stream + parsed_label_config: + key: value audiences: - public source: diff --git a/.mock/openapi/openapi.yaml b/.mock/openapi/openapi.yaml index bfc111cc1..2464e83e4 100644 --- a/.mock/openapi/openapi.yaml +++ b/.mock/openapi/openapi.yaml @@ -563,6 +563,238 @@ paths: x-fern-sdk-method-name: create_bulk x-fern-audiences: - public + /api/billing/info: + get: + operationId: api_billing_info_retrieve + description: Retrieve billing checks and feature flags for the active organization. + summary: Get billing info + tags: + - Billing + security: + - Token: [] + responses: + '200': + content: + application/json: + schema: + $ref: '#/components/schemas/BillingInfoResponse' + examples: + Real-sample: + value: + billing_checks: + users: + count: 110 + total: 221 + limit: 1000 + reached: false + trial_days: 0 + projects: + count: 2044 + limit: 1000000 + reached: false + organization_is_active: true + license_issued: '2000-01-01' + license_warning: '2030-01-01' + is_license_warning: false + license_expires: '2030-01-02' + is_license_expired: false + prompts_enabled: true + prompts_status: Enabled + prompts_warning: null + is_prompts_warning: false + prompts_expire: null + is_prompts_expire: false + prompts_api_keys_enabled: true + import_storages: + count: 0 + limit: 0 + reached: false + export_storages: + count: 0 + limit: 0 + reached: false + results: + count: 42949 + limit: 1000000000 + reached: false + billing_flags: + cloud_instance: true + allow_activity_log: true + allow_invite_project_experts: true + allow_sso: true + white_label_id: null + allow_data_credentials: false + allow_organization_webhooks: false + disable_members_page: false + secure_mode: false + manual_workspace_management: true + manual_role_management: true + hide_storage_settings_for_manager: false + disable_project_imports: false + automax_token_exists: true + automax_enabled: true + storage_persistence: true + allow_ai: true + early_adopter: true + allow_ask_ai: true + allow_invite_people: true + allow_storage_proxy: true + embed_enabled: true + embed_domains: + - domain: http://localhost:3000 + - domain: https://purple-zoos-flash.loca.lt + embed_settings: + public_verify_alg: + - RS256 + public_verify_key: '....' + activated_at: null + summary: real-sample + Cloud: + value: + billing_checks: + users: + count: 5 + total: 6 + limit: 10 + reached: false + projects: + count: 3 + limit: 50 + reached: false + results: + count: 100 + limit: 1000 + reached: false + trial_days: 14 + organization_is_active: true + license_issued: '2023-01-01' + license_warning: '2024-12-01' + is_license_warning: false + license_expires: '2025-01-01' + is_license_expired: false + prompts_enabled: true + prompts_status: Enabled + prompts_warning: null + is_prompts_warning: false + prompts_expire: '2024-12-31' + is_prompts_expire: false + prompts_api_keys_enabled: true + import_storages: + count: 0 + limit: 0 + reached: false + export_storages: + count: 0 + limit: 0 + reached: false + billing_flags: + activated_at: '2023-01-01T00:00:00Z' + cloud_instance: true + allow_activity_log: true + allow_invite_project_experts: true + allow_sso: false + white_label_id: null + allow_data_credentials: true + allow_organization_webhooks: true + disable_members_page: false + secure_mode: false + manual_workspace_management: false + manual_role_management: false + hide_storage_settings_for_manager: false + disable_project_imports: false + automax_token_exists: false + automax_enabled: true + storage_persistence: true + allow_ai: true + early_adopter: false + allow_ask_ai: true + allow_invite_people: true + allow_storage_proxy: true + embed_enabled: false + embed_domains: + - domain: http://localhost:3000 + - domain: https://example.com + embed_settings: + public_verify_alg: + - RS256 + public_verify_key: '....' + summary: cloud + Enterprise: + value: + billing_checks: + users: + count: 20 + total: 22 + limit: 100 + reached: false + projects: + count: 15 + limit: 200 + reached: false + results: + count: 25000 + limit: 100000 + reached: false + trial_days: 0 + organization_is_active: true + license_issued: '2023-01-01' + license_warning: '2024-12-01' + is_license_warning: false + license_expires: '2025-01-01' + is_license_expired: false + prompts_enabled: true + prompts_status: Enabled + prompts_warning: null + is_prompts_warning: false + prompts_expire: null + is_prompts_expire: false + prompts_api_keys_enabled: true + import_storages: + count: 0 + limit: 0 + reached: false + export_storages: + count: 0 + limit: 0 + reached: false + billing_flags: + activated_at: null + cloud_instance: false + allow_activity_log: true + allow_invite_project_experts: true + allow_sso: true + white_label_id: wl-1 + allow_data_credentials: true + allow_organization_webhooks: true + disable_members_page: false + secure_mode: false + manual_workspace_management: false + manual_role_management: false + hide_storage_settings_for_manager: false + disable_project_imports: false + automax_token_exists: true + automax_enabled: true + storage_persistence: true + allow_ai: false + early_adopter: true + allow_ask_ai: true + allow_invite_people: true + allow_storage_proxy: true + embed_enabled: false + embed_domains: + - domain: http://localhost:3000 + - domain: https://example.com + embed_settings: + public_verify_alg: + - RS256 + public_verify_key: '....' + summary: enterprise + description: Billing information for the active organization + x-fern-sdk-group-name: + - billing + x-fern-sdk-method-name: info + x-fern-audiences: + - public /api/blueprints/: post: operationId: api_blueprints_create @@ -5184,72 +5416,29 @@ paths: schema: $ref: '#/components/schemas/PaginatedLseOrganizationMemberListList' description: '' - post: - operationId: api_organizations_memberships_create - description: "\n Assign a role to a user in an organization. To do so, make\ - \ the following cURL request:\n\n ```bash\n curl -H 'Content-Type: application/json'\ - \ -H 'Authorization: Token abc123' \\\n -X POST 'https://label-studio-host/api/organizations/{{id}}/memberships'\ - \ --data '[{{\"user_id\": Int, \"role\": \"NO|DI|OW|AD|MA|AN|RE\" }}]'\n \ - \ ```\n \n Enumerate a role with one of the following abbreviations:\n\ - \n | Role | Full Role Name |\n | --- | --- |\n | NO | Not Activated\ - \ |\n | DI | Deactivated |\n | OW | Owner |\n | AD | Administrator\ - \ |\n | MA | Manager |\n | AN | Annotator |\n | RE | Reviewer |\n\ - \n For example, to set a user with an ID of 9 as an annotator, make the\ - \ following cURL request:\n ```bash\n curl -H 'Content-Type: application/json'\ - \ -H 'Authorization: Token abc123' \\\n -X POST 'https://label-studio-host/api/organizations/{{id}}/memberships'\ - \ --data '[{{\"user_id\": 9, \"role\": \"AN\" }}]'\n ```\n " - summary: Create organization member/role - parameters: - - in: path - name: id - schema: - type: integer - description: A unique integer value identifying this organization. - required: true - tags: - - Organizations - requestBody: - content: - application/json: - schema: - $ref: '#/components/schemas/OrganizationMemberCreateUpdateRequest' - application/x-www-form-urlencoded: - schema: - $ref: '#/components/schemas/OrganizationMemberCreateUpdateRequest' - multipart/form-data: - schema: - $ref: '#/components/schemas/OrganizationMemberCreateUpdateRequest' - required: true - security: - - Token: [] - responses: - '200': - content: - application/json: - schema: - $ref: '#/components/schemas/LseOrganizationMemberList' - description: '' + x-fern-sdk-group-name: + - organizations + - members + x-fern-sdk-method-name: list + x-fern-audiences: + - public patch: operationId: api_organizations_memberships_partial_update - description: "\n Update organization membership or role for a specific user\ - \ ID.\n\n **User Rotation Best Practices for API Usage**\n \n To\ - \ maintain compliance with our licensing terms and ensure optimal performance\ - \ of HumanSignal's APIs, please consider the following guidelines when managing\ - \ user assignments:\n \n * **Maintain a 7-Day Minimum Assignment**:\ - \ Once a licensed seat is assigned to a user, maintain that assignment for\ - \ at least seven consecutive days before rotating it to another user.\n\n\ - \ * **Automate, Monitor, and Log Rotations**: Implement automated scheduling\ - \ and logging mechanisms to track the timing of user rotations. This helps\ - \ ensure that rotations adhere to the seven-day minimum period.\n\n * **Adhere\ - \ to API Update Frequency and Wait Periods**: When updating user assignments\ - \ via our APIs, follow the recommended frequency and wait period guidelines\ - \ provided in the HumanSignal API documentation. Avoid sending rapid, successive\ - \ requests that might overload the endpoint. Instead, incorporate appropriate\ - \ delays between calls as specified in the documentation.\n \n * **Avoid\ - \ Overloading the API Endpoint**: Design your integration to batch or schedule\ - \ updates where possible, and implement backoff strategies if the API indicates\ - \ rate limiting. This helps prevent service disruptions and ensures a smooth\ - \ operation.\n " + description: |+ + Update organization membership or role for a specific user ID. + + **User Rotation Best Practices for API Usage** + + To maintain compliance with our licensing terms and ensure optimal performance of HumanSignal's APIs, please consider the following guidelines when managing user assignments: + + * **Maintain a 7-Day Minimum Assignment**: Once a licensed seat is assigned to a user, maintain that assignment for at least seven consecutive days before rotating it to another user. + + * **Automate, Monitor, and Log Rotations**: Implement automated scheduling and logging mechanisms to track the timing of user rotations. This helps ensure that rotations adhere to the seven-day minimum period. + + * **Adhere to API Update Frequency and Wait Periods**: When updating user assignments via our APIs, follow the recommended frequency and wait period guidelines provided in the HumanSignal API documentation. Avoid sending rapid, successive requests that might overload the endpoint. Instead, incorporate appropriate delays between calls as specified in the documentation. + + * **Avoid Overloading the API Endpoint**: Design your integration to batch or schedule updates where possible, and implement backoff strategies if the API indicates rate limiting. This helps prevent service disruptions and ensures a smooth operation. + summary: Update organization member/role parameters: - in: path @@ -5280,6 +5469,12 @@ paths: schema: $ref: '#/components/schemas/LseOrganizationMemberList' description: '' + x-fern-sdk-group-name: + - organizations + - members + x-fern-sdk-method-name: update + x-fern-audiences: + - public /api/organizations/{id}/memberships/{user_pk}/: get: operationId: api_organizations_memberships_retrieve @@ -15576,41 +15771,80 @@ components: Serializer get numbers from project queryset annotation, make sure, that you use correct one(Project.objects.with_counts()) properties: - workspace_title: + show_ground_truth_first: + type: boolean + rejected: type: string readOnly: true - ready: + label_config: + type: string + nullable: true + description: Label config in XML format. See more about it in documentation + show_instruction: + type: boolean + description: Show instructions to the annotator before they start + duplication_status: + type: string + control_weights: + nullable: true + description: 'Dict of weights for each control tag in metric calculation. + Each control tag (e.g. label or choice) will have it''s own key in control + weight dict with weight for each label and overall weight.For example, + if bounding box annotation with control tag named my_bbox should be included + with 0.33 weight in agreement calculation, and the first label Car should + be twice more important than Airplaine, then you have to need the specify: + {''my_bbox'': {''type'': ''RectangleLabels'', ''labels'': {''Car'': 1.0, + ''Airplaine'': 0.5}, ''overall'': 0.33}' + workspace: type: string readOnly: true - overlap_cohort_percentage: + finished_task_number: type: integer - maximum: 2147483647 - minimum: -2147483648 - queue_left: - type: string readOnly: true - config_suitable_for_bulk_annotation: + show_skip_button: type: boolean + description: Show a skip button in interface and allow annotators to skip + the task + created_by: + allOf: + - $ref: '#/components/schemas/UserSimple' + description: Project owner + assignment_settings: + $ref: '#/components/schemas/AssignmentSettings' + reviewed_number: + type: string readOnly: true - description: Flag to detect is project ready for bulk annotation - has_blueprints: + model_version: type: string + nullable: true + description: Machine learning model version + data_types: readOnly: true - show_overlap_first: - type: boolean - queue_total: + nullable: true + description_short: type: string readOnly: true - enable_empty_annotation: + queue_left: + type: string + readOnly: true + annotation_limit_percent: + type: string + format: decimal + pattern: ^-?\d{0,3}(?:\.\d{0,2})?$ + nullable: true + config_has_control_tags: type: boolean - description: Allow annotators to submit empty annotations - custom_task_lock_ttl: + readOnly: true + description: Flag to detect is project ready for labeling + total_predictions_number: type: integer - maximum: 86400 - minimum: 1 - nullable: true - description: TTL in seconds for task reservations, on new and existing tasks - prompts: + readOnly: true + useful_annotation_number: + type: string + readOnly: true + custom_script: + type: string + reviewer_queue_total: type: string readOnly: true start_training_on_annotation_update: @@ -15618,225 +15852,186 @@ components: readOnly: true description: Start model training after any annotations are submitted or updated - evaluate_predictions_automatically: - type: boolean - description: Retrieve and display predictions when loading a task - show_instruction: - type: boolean - description: Show instructions to the annotator before they start - color: + skipped_annotations_number: type: string + readOnly: true + custom_task_lock_ttl: + type: integer + maximum: 86400 + minimum: 1 nullable: true - maxLength: 16 + description: TTL in seconds for task reservations, on new and existing tasks + workspace_title: + type: string + readOnly: true sampling: nullable: true oneOf: - $ref: '#/components/schemas/SamplingEnum' - $ref: '#/components/schemas/NullEnum' - created_by: - allOf: - - $ref: '#/components/schemas/UserSimple' - description: Project owner reveal_preannotations_interactively: type: boolean description: Reveal pre-annotations interactively - pinned_at: - type: string - format: date-time - nullable: true - description: Pinned date and time - finished_task_number: + id: type: integer readOnly: true - parsed_label_config: - readOnly: true - description: JSON-formatted labeling configuration - duplication_done: - type: boolean - default: false - reviewer_queue_total: + has_blueprints: type: string readOnly: true - show_ground_truth_first: - type: boolean - task_number: - type: integer + queue_done: + type: string readOnly: true - description: Total task number in project - num_tasks_with_annotations: + total_annotations_number: type: string readOnly: true - description_short: + members_count: type: string readOnly: true - id: + maximum_annotations: type: integer - readOnly: true - allow_stream: + maximum: 2147483647 + minimum: -2147483648 + title: Maximum annotation number + description: Maximum number of annotations for one task. If the number of + annotations per task is equal or greater to this value, the task is completed + (is_labeled=True) + comment_classification_config: type: string - readOnly: true - annotation_limit_percent: + prompts: type: string - format: decimal - pattern: ^-?\d{0,3}(?:\.\d{0,2})?$ - nullable: true + readOnly: true created_at: type: string format: date-time readOnly: true - annotation_limit_count: - type: integer - minimum: 1 - nullable: true - queue_done: + ready: type: string readOnly: true - control_weights: + annotator_evaluation_minimum_tasks: + type: integer + minimum: 0 nullable: true - description: 'Dict of weights for each control tag in metric calculation. - Each control tag (e.g. label or choice) will have it''s own key in control - weight dict with weight for each label and overall weight.For example, - if bounding box annotation with control tag named my_bbox should be included - with 0.33 weight in agreement calculation, and the first label Car should - be twice more important than Airplaine, then you have to need the specify: - {''my_bbox'': {''type'': ''RectangleLabels'', ''labels'': {''Car'': 1.0, - ''Airplaine'': 0.5}, ''overall'': 0.33}' - data_types: + default: 10 + config_suitable_for_bulk_annotation: + type: boolean readOnly: true + description: Flag to detect is project ready for bulk annotation + skip_queue: nullable: true - reviewed_number: + oneOf: + - $ref: '#/components/schemas/SkipQueueEnum' + - $ref: '#/components/schemas/NullEnum' + title: type: string - readOnly: true - total_annotations_number: + nullable: true + description: Project name. Must be between 3 and 50 characters long. + maxLength: 50 + minLength: 3 + show_overlap_first: + type: boolean + queue_total: type: string readOnly: true - total_predictions_number: + organization: type: integer - readOnly: true - config_has_control_tags: + nullable: true + duplication_done: type: boolean + default: false + ground_truth_number: + type: integer readOnly: true - description: Flag to detect is project ready for labeling + description: Honeypot annotation number in project + annotation_limit_count: + type: integer + minimum: 1 + nullable: true + evaluate_predictions_automatically: + type: boolean + description: Retrieve and display predictions when loading a task blueprints: type: array items: $ref: '#/components/schemas/BlueprintList' readOnly: true - is_published: - type: boolean - title: Published - description: Whether or not the project is published to annotators - duplication_status: + color: type: string - review_total_tasks: + nullable: true + maxLength: 16 + review_settings: + $ref: '#/components/schemas/ReviewSettings' + pinned_at: + type: string + format: date-time + nullable: true + description: Pinned date and time + members: type: string readOnly: true - show_skip_button: + require_comment_on_skip: type: boolean - description: Show a skip button in interface and allow annotators to skip - the task - is_draft: + default: false + show_annotation_history: type: boolean - description: Whether or not the project is in the middle of being created - title: - type: string - nullable: true - description: Project name. Must be between 3 and 50 characters long. - maxLength: 50 - minLength: 3 + description: Show annotation history to annotator + task_number: + type: integer + readOnly: true + description: Total task number in project + is_published: + type: boolean + title: Published + description: Whether or not the project is published to annotators show_collab_predictions: type: boolean title: Show predictions to annotator description: If set, the annotator can view model predictions - members: + review_total_tasks: + type: string + readOnly: true + num_tasks_with_annotations: type: string readOnly: true + expert_instruction: + type: string + nullable: true + description: Labeling instructions in HTML format + overlap_cohort_percentage: + type: integer + maximum: 2147483647 + minimum: -2147483648 + is_draft: + type: boolean + description: Whether or not the project is in the middle of being created min_annotations_to_start_training: type: integer maximum: 2147483647 minimum: -2147483648 description: Minimum number of completed tasks after which model training is started - workspace: - type: string - readOnly: true - organization: - type: integer - nullable: true - assignment_settings: - $ref: '#/components/schemas/AssignmentSettings' - annotator_evaluation_minimum_tasks: - type: integer - minimum: 0 - nullable: true - default: 10 - skipped_annotations_number: - type: string - readOnly: true + enable_empty_annotation: + type: boolean + description: Allow annotators to submit empty annotations annotator_evaluation_minimum_score: type: string format: decimal pattern: ^-?\d{0,3}(?:\.\d{0,2})?$ nullable: true default: '95.00' - comment_classification_config: - type: string description: type: string nullable: true description: Project description - expert_instruction: - type: string - nullable: true - description: Labeling instructions in HTML format - show_annotation_history: - type: boolean - description: Show annotation history to annotator - skip_queue: - nullable: true - oneOf: - - $ref: '#/components/schemas/SkipQueueEnum' - - $ref: '#/components/schemas/NullEnum' - review_settings: - $ref: '#/components/schemas/ReviewSettings' - members_count: - type: string - readOnly: true - model_version: - type: string - nullable: true - description: Machine learning model version - useful_annotation_number: - type: string - readOnly: true - custom_script: - type: string - require_comment_on_skip: - type: boolean - default: false - ground_truth_number: - type: integer - readOnly: true - description: Honeypot annotation number in project pause_on_failed_annotator_evaluation: type: boolean nullable: true default: false - label_config: - type: string - nullable: true - description: Label config in XML format. See more about it in documentation - maximum_annotations: - type: integer - maximum: 2147483647 - minimum: -2147483648 - title: Maximum annotation number - description: Maximum number of annotations for one task. If the number of - annotations per task is equal or greater to this value, the task is completed - (is_labeled=True) - rejected: + allow_stream: type: string readOnly: true + parsed_label_config: + readOnly: true + description: JSON-formatted labeling configuration required: - allow_stream - assignment_settings @@ -17213,6 +17408,169 @@ components: required: - modelrun_id - results + BillingChecks: + type: object + properties: + users: + $ref: '#/components/schemas/CountLimit' + projects: + $ref: '#/components/schemas/CountLimit' + results: + $ref: '#/components/schemas/CountLimit' + trial_days: + type: integer + organization_is_active: + type: boolean + license_issued: + type: string + format: date + nullable: true + license_warning: + type: string + format: date + nullable: true + is_license_warning: + type: boolean + license_expires: + type: string + format: date + nullable: true + is_license_expired: + type: boolean + prompts_enabled: + type: boolean + prompts_status: + $ref: '#/components/schemas/PromptsStatusEnum' + prompts_warning: + type: string + nullable: true + is_prompts_warning: + type: boolean + prompts_expire: + type: string + nullable: true + is_prompts_expire: + type: boolean + prompts_api_keys_enabled: + type: boolean + import_storages: + $ref: '#/components/schemas/CountLimit' + export_storages: + $ref: '#/components/schemas/CountLimit' + required: + - export_storages + - import_storages + - is_license_expired + - is_license_warning + - is_prompts_expire + - is_prompts_warning + - license_expires + - license_issued + - license_warning + - organization_is_active + - projects + - prompts_api_keys_enabled + - prompts_enabled + - prompts_expire + - prompts_status + - prompts_warning + - results + - trial_days + - users + BillingFlags: + type: object + properties: + activated_at: + type: string + format: date-time + nullable: true + cloud_instance: + type: boolean + allow_activity_log: + type: boolean + allow_invite_project_experts: + type: boolean + allow_sso: + type: boolean + white_label_id: + type: string + nullable: true + allow_data_credentials: + type: boolean + allow_organization_webhooks: + type: boolean + disable_members_page: + type: boolean + secure_mode: + type: boolean + manual_workspace_management: + type: boolean + manual_role_management: + type: boolean + hide_storage_settings_for_manager: + type: boolean + disable_project_imports: + type: boolean + automax_token_exists: + type: boolean + automax_enabled: + type: boolean + storage_persistence: + type: boolean + allow_ai: + type: boolean + early_adopter: + type: boolean + allow_ask_ai: + type: boolean + allow_invite_people: + type: boolean + allow_storage_proxy: + type: boolean + embed_enabled: + type: boolean + embed_domains: + type: array + items: + type: object + additionalProperties: {} + embed_settings: + type: object + additionalProperties: {} + required: + - activated_at + - allow_activity_log + - allow_ai + - allow_ask_ai + - allow_data_credentials + - allow_invite_people + - allow_invite_project_experts + - allow_organization_webhooks + - allow_sso + - allow_storage_proxy + - automax_enabled + - automax_token_exists + - cloud_instance + - disable_members_page + - disable_project_imports + - early_adopter + - embed_enabled + - hide_storage_settings_for_manager + - manual_role_management + - manual_workspace_management + - secure_mode + - storage_persistence + - white_label_id + BillingInfoResponse: + type: object + properties: + billing_checks: + $ref: '#/components/schemas/BillingChecks' + billing_flags: + $ref: '#/components/schemas/BillingFlags' + required: + - billing_checks + - billing_flags BlankEnum: enum: - '' @@ -17570,6 +17928,21 @@ components: description: Traceback report in case of errors required: - export_type + CountLimit: + type: object + properties: + count: + type: integer + limit: + type: integer + reached: + type: boolean + total: + type: integer + required: + - count + - limit + - reached CustomScriptsEditableByEnum: enum: - AD @@ -22782,16 +23155,6 @@ components: - created_at - organization - user - OrganizationMemberCreateUpdateRequest: - type: object - properties: - user_id: - type: integer - role: - $ref: '#/components/schemas/Role9e7Enum' - required: - - role - - user_id OrganizationMembership: type: object properties: @@ -25576,6 +25939,24 @@ components: nullable: true required: - name + PromptsStatusEnum: + enum: + - Enabled + - Cloud license per organization disabled + - On-premise global license disabled + - Expired + - Adala not connected + - Disabled for this organization [FF] + - unknown + type: string + description: |- + * `Enabled` - Enabled + * `Cloud license per organization disabled` - Cloud license per organization disabled + * `On-premise global license disabled` - On-premise global license disabled + * `Expired` - Expired + * `Adala not connected` - Adala not connected + * `Disabled for this organization [FF]` - Disabled for this organization [FF] + * `unknown` - unknown ProviderEnum: enum: - OpenAI diff --git a/poetry.lock b/poetry.lock index d836fc38f..52eebb2d5 100644 --- a/poetry.lock +++ b/poetry.lock @@ -612,13 +612,13 @@ cli = ["typer (>=0.7.0)"] [[package]] name = "jsonschema" -version = "4.25.0" +version = "4.25.1" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.9" files = [ - {file = "jsonschema-4.25.0-py3-none-any.whl", hash = "sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716"}, - {file = "jsonschema-4.25.0.tar.gz", hash = "sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f"}, + {file = "jsonschema-4.25.1-py3-none-any.whl", hash = "sha256:3fba0169e345c7175110351d456342c364814cfcf3b964ba4587f22915230a63"}, + {file = "jsonschema-4.25.1.tar.gz", hash = "sha256:e4a9655ce0da0c0b67a085847e00a3a51449e1157f4f75e9fb5aa545e122eb85"}, ] [package.dependencies] @@ -1633,13 +1633,13 @@ files = [ [[package]] name = "requests" -version = "2.32.4" +version = "2.32.5" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" files = [ - {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, - {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, + {file = "requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6"}, + {file = "requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf"}, ] [package.dependencies] diff --git a/pyproject.toml b/pyproject.toml index 544c7faa2..c74418a4c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "label-studio-sdk" [tool.poetry] name = "label-studio-sdk" -version = "2.0.1.dev" +version = "2.0.1" description = "" readme = "README.md" authors = [] diff --git a/reference.md b/reference.md index 793adfc2c..42e97f845 100644 --- a/reference.md +++ b/reference.md @@ -754,6 +754,67 @@ client.annotations.create( + + + + +## Billing +
client.billing.info() +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve billing checks and feature flags for the active organization. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.billing.info() + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ +
@@ -19272,6 +19333,223 @@ client.import_storage.s3s.validate( ## Organizations Members +
client.organizations.members.list(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Retrieve a list of all users and roles in a specific organization. +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.members.list( + id=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` — A unique integer value identifying this organization. + +
+
+ +
+
+ +**exclude_project_id:** `typing.Optional[int]` — Project ID to exclude users who are already associated with this project (direct members, workspace members, or implicit admin/owner access). + +
+
+ +
+
+ +**exclude_workspace_id:** `typing.Optional[int]` — Workspace ID to exclude users who are already associated with this workspace (direct workspace members or implicit admin/owner access). + +
+
+ +
+
+ +**ordering:** `typing.Optional[str]` — Which field to use when ordering the results. + +
+
+ +
+
+ +**page:** `typing.Optional[int]` — A page number within the paginated result set. + +
+
+ +
+
+ +**page_size:** `typing.Optional[int]` — Number of results to return per page. + +
+
+ +
+
+ +**search:** `typing.Optional[str]` — A search term. + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+ +
client.organizations.members.update(...) +
+
+ +#### 📝 Description + +
+
+ +
+
+ +Update organization membership or role for a specific user ID. + +**User Rotation Best Practices for API Usage** + +To maintain compliance with our licensing terms and ensure optimal performance of HumanSignal's APIs, please consider the following guidelines when managing user assignments: + +* **Maintain a 7-Day Minimum Assignment**: Once a licensed seat is assigned to a user, maintain that assignment for at least seven consecutive days before rotating it to another user. + +* **Automate, Monitor, and Log Rotations**: Implement automated scheduling and logging mechanisms to track the timing of user rotations. This helps ensure that rotations adhere to the seven-day minimum period. + +* **Adhere to API Update Frequency and Wait Periods**: When updating user assignments via our APIs, follow the recommended frequency and wait period guidelines provided in the HumanSignal API documentation. Avoid sending rapid, successive requests that might overload the endpoint. Instead, incorporate appropriate delays between calls as specified in the documentation. + +* **Avoid Overloading the API Endpoint**: Design your integration to batch or schedule updates where possible, and implement backoff strategies if the API indicates rate limiting. This helps prevent service disruptions and ensures a smooth operation. + +
+
+
+
+ +#### 🔌 Usage + +
+
+ +
+
+ +```python +from label_studio_sdk import LabelStudio + +client = LabelStudio( + api_key="YOUR_API_KEY", +) +client.organizations.members.update( + id=1, +) + +``` +
+
+
+
+ +#### ⚙️ Parameters + +
+
+ +
+
+ +**id:** `int` — A unique integer value identifying this organization. + +
+
+ +
+
+ +**user_id:** `typing.Optional[int]` + +
+
+ +
+
+ +**role:** `typing.Optional[Role9E7Enum]` + +
+
+ +
+
+ +**request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration. + +
+
+
+
+ + +
+
+
+
client.organizations.members.get(...)
diff --git a/src/label_studio_sdk/__init__.py b/src/label_studio_sdk/__init__.py index 85bcd2939..b04c1571d 100644 --- a/src/label_studio_sdk/__init__.py +++ b/src/label_studio_sdk/__init__.py @@ -20,6 +20,9 @@ AzureBlobImportStorage, BatchFailedPredictions, BatchPredictions, + BillingChecks, + BillingFlags, + BillingInfoResponse, BlankEnum, BlueprintList, BudgetResetPeriodEnum, @@ -29,6 +32,7 @@ CommentSerializerWithExpandedUser, ConvertedFormat, ConvertedFormatRequest, + CountLimit, CustomScriptsEditableByEnum, DefaultRoleEnum, EditionEnum, @@ -57,6 +61,7 @@ LseKeyIndicatorValue, LseOrganization, LseOrganizationCustomScriptsEditableBy, + LseOrganizationMemberList, LseProjectCreate, LseProjectCreateSampling, LseProjectCreateSkipQueue, @@ -88,6 +93,7 @@ LseTaskSerializerForReviewersPredictionsItem, LseUser, LseUserApi, + LseUserOrganizationMemberList, LseapiTokenCreate, LseapiTokenList, LsejwtSettings, @@ -110,6 +116,7 @@ OrganizationMember, OrganizationMembership, PaginatedAllRolesProjectListList, + PaginatedLseOrganizationMemberListList, PaginatedRoleBasedTaskList, Pause, PauseRequest, @@ -122,6 +129,7 @@ ProjectSampling, ProjectSkipQueue, ProjectSubsetEnum, + PromptsStatusEnum, ProviderEnum, ReasonEnum, RedisExportStorage, @@ -136,6 +144,7 @@ ReviewSettingsRequeueRejectedTasksMode, ReviewSettingsReviewCriteria, ReviewedEnum, + Role9E7Enum, RoleBasedTask, S3ExportStorage, S3ImportStorage, @@ -178,6 +187,7 @@ from . import ( actions, annotations, + billing, comments, export_storage, files, @@ -307,6 +317,9 @@ "BadRequestError", "BatchFailedPredictions", "BatchPredictions", + "BillingChecks", + "BillingFlags", + "BillingInfoResponse", "BlankEnum", "BlueprintList", "BudgetResetPeriodEnum", @@ -317,6 +330,7 @@ "CommentSerializerWithExpandedUser", "ConvertedFormat", "ConvertedFormatRequest", + "CountLimit", "CustomScriptsEditableByEnum", "DefaultRoleEnum", "EditionEnum", @@ -351,6 +365,7 @@ "LseKeyIndicatorValue", "LseOrganization", "LseOrganizationCustomScriptsEditableBy", + "LseOrganizationMemberList", "LseProjectCreate", "LseProjectCreateRequestSampling", "LseProjectCreateRequestSkipQueue", @@ -384,6 +399,7 @@ "LseTaskSerializerForReviewersPredictionsItem", "LseUser", "LseUserApi", + "LseUserOrganizationMemberList", "LseapiTokenCreate", "LseapiTokenList", "LsejwtSettings", @@ -412,6 +428,7 @@ "OrganizationMember", "OrganizationMembership", "PaginatedAllRolesProjectListList", + "PaginatedLseOrganizationMemberListList", "PaginatedRoleBasedTaskList", "PatchedLseProjectUpdateRequestSampling", "PatchedLseProjectUpdateRequestSkipQueue", @@ -430,6 +447,7 @@ "ProjectsImportTasksResponse", "ProjectsListRequestFilter", "PromptsCompatibleProjectsRequestProjectType", + "PromptsStatusEnum", "ProviderEnum", "ReasonEnum", "RedisExportStorage", @@ -444,6 +462,7 @@ "ReviewSettingsRequeueRejectedTasksMode", "ReviewSettingsReviewCriteria", "ReviewedEnum", + "Role9E7Enum", "RoleBasedTask", "S3ExportStorage", "S3ImportStorage", @@ -513,6 +532,7 @@ "__version__", "actions", "annotations", + "billing", "comments", "export_storage", "files", diff --git a/src/label_studio_sdk/base_client.py b/src/label_studio_sdk/base_client.py index daf3eec93..19c2e27a5 100644 --- a/src/label_studio_sdk/base_client.py +++ b/src/label_studio_sdk/base_client.py @@ -7,6 +7,7 @@ from .core.api_error import ApiError from .core.client_wrapper import SyncClientWrapper from .annotations.client import AnnotationsClient +from .billing.client import BillingClient from .comments.client import CommentsClient from .users.client import UsersClient from .actions.client import ActionsClient @@ -28,6 +29,7 @@ from .workspaces.client import WorkspacesClient from .core.client_wrapper import AsyncClientWrapper from .annotations.client import AsyncAnnotationsClient +from .billing.client import AsyncBillingClient from .comments.client import AsyncCommentsClient from .users.client import AsyncUsersClient from .actions.client import AsyncActionsClient @@ -112,6 +114,7 @@ def __init__( timeout=_defaulted_timeout, ) self.annotations = AnnotationsClient(client_wrapper=self._client_wrapper) + self.billing = BillingClient(client_wrapper=self._client_wrapper) self.comments = CommentsClient(client_wrapper=self._client_wrapper) self.users = UsersClient(client_wrapper=self._client_wrapper) self.actions = ActionsClient(client_wrapper=self._client_wrapper) @@ -196,6 +199,7 @@ def __init__( timeout=_defaulted_timeout, ) self.annotations = AsyncAnnotationsClient(client_wrapper=self._client_wrapper) + self.billing = AsyncBillingClient(client_wrapper=self._client_wrapper) self.comments = AsyncCommentsClient(client_wrapper=self._client_wrapper) self.users = AsyncUsersClient(client_wrapper=self._client_wrapper) self.actions = AsyncActionsClient(client_wrapper=self._client_wrapper) diff --git a/src/label_studio_sdk/billing/__init__.py b/src/label_studio_sdk/billing/__init__.py new file mode 100644 index 000000000..f3ea2659b --- /dev/null +++ b/src/label_studio_sdk/billing/__init__.py @@ -0,0 +1,2 @@ +# This file was auto-generated by Fern from our API Definition. + diff --git a/src/label_studio_sdk/billing/client.py b/src/label_studio_sdk/billing/client.py new file mode 100644 index 000000000..3384bd56a --- /dev/null +++ b/src/label_studio_sdk/billing/client.py @@ -0,0 +1,112 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.client_wrapper import SyncClientWrapper +import typing +from ..core.request_options import RequestOptions +from ..types.billing_info_response import BillingInfoResponse +from ..core.unchecked_base_model import construct_type +from json.decoder import JSONDecodeError +from ..core.api_error import ApiError +from ..core.client_wrapper import AsyncClientWrapper + + +class BillingClient: + def __init__(self, *, client_wrapper: SyncClientWrapper): + self._client_wrapper = client_wrapper + + def info(self, *, request_options: typing.Optional[RequestOptions] = None) -> BillingInfoResponse: + """ + Retrieve billing checks and feature flags for the active organization. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + BillingInfoResponse + Billing information for the active organization + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.billing.info() + """ + _response = self._client_wrapper.httpx_client.request( + "api/billing/info", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + BillingInfoResponse, + construct_type( + type_=BillingInfoResponse, # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + +class AsyncBillingClient: + def __init__(self, *, client_wrapper: AsyncClientWrapper): + self._client_wrapper = client_wrapper + + async def info(self, *, request_options: typing.Optional[RequestOptions] = None) -> BillingInfoResponse: + """ + Retrieve billing checks and feature flags for the active organization. + + Parameters + ---------- + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + BillingInfoResponse + Billing information for the active organization + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.billing.info() + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + "api/billing/info", + method="GET", + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + BillingInfoResponse, + construct_type( + type_=BillingInfoResponse, # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) diff --git a/src/label_studio_sdk/organizations/members/client.py b/src/label_studio_sdk/organizations/members/client.py index f5eeb8977..4e4604d38 100644 --- a/src/label_studio_sdk/organizations/members/client.py +++ b/src/label_studio_sdk/organizations/members/client.py @@ -1,23 +1,191 @@ # This file was auto-generated by Fern from our API Definition. -from ...core.client_wrapper import SyncClientWrapper import typing +from ...core.client_wrapper import SyncClientWrapper from ...core.request_options import RequestOptions -from ...types.organization_member import OrganizationMember +from ...types.paginated_lse_organization_member_list_list import PaginatedLseOrganizationMemberListList from ...core.jsonable_encoder import jsonable_encoder from ...core.unchecked_base_model import construct_type from json.decoder import JSONDecodeError from ...core.api_error import ApiError +from ...types.role9e7enum import Role9E7Enum +from ...types.lse_organization_member_list import LseOrganizationMemberList +from ...types.organization_member import OrganizationMember from ...errors.forbidden_error import ForbiddenError from ...errors.not_found_error import NotFoundError from ...errors.method_not_allowed_error import MethodNotAllowedError from ...core.client_wrapper import AsyncClientWrapper +# this is used as the default value for optional parameters +OMIT = typing.cast(typing.Any, ...) + class MembersClient: def __init__(self, *, client_wrapper: SyncClientWrapper): self._client_wrapper = client_wrapper + def list( + self, + id: int, + *, + exclude_project_id: typing.Optional[int] = None, + exclude_workspace_id: typing.Optional[int] = None, + ordering: typing.Optional[str] = None, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> PaginatedLseOrganizationMemberListList: + """ + Retrieve a list of all users and roles in a specific organization. + + Parameters + ---------- + id : int + A unique integer value identifying this organization. + + exclude_project_id : typing.Optional[int] + Project ID to exclude users who are already associated with this project (direct members, workspace members, or implicit admin/owner access). + + exclude_workspace_id : typing.Optional[int] + Workspace ID to exclude users who are already associated with this workspace (direct workspace members or implicit admin/owner access). + + ordering : typing.Optional[str] + Which field to use when ordering the results. + + page : typing.Optional[int] + A page number within the paginated result set. + + page_size : typing.Optional[int] + Number of results to return per page. + + search : typing.Optional[str] + A search term. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + PaginatedLseOrganizationMemberListList + + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.members.list( + id=1, + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/memberships", + method="GET", + params={ + "exclude_project_id": exclude_project_id, + "exclude_workspace_id": exclude_workspace_id, + "ordering": ordering, + "page": page, + "page_size": page_size, + "search": search, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + PaginatedLseOrganizationMemberListList, + construct_type( + type_=PaginatedLseOrganizationMemberListList, # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + def update( + self, + id: int, + *, + user_id: typing.Optional[int] = OMIT, + role: typing.Optional[Role9E7Enum] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> LseOrganizationMemberList: + """ + Update organization membership or role for a specific user ID. + + **User Rotation Best Practices for API Usage** + + To maintain compliance with our licensing terms and ensure optimal performance of HumanSignal's APIs, please consider the following guidelines when managing user assignments: + + * **Maintain a 7-Day Minimum Assignment**: Once a licensed seat is assigned to a user, maintain that assignment for at least seven consecutive days before rotating it to another user. + + * **Automate, Monitor, and Log Rotations**: Implement automated scheduling and logging mechanisms to track the timing of user rotations. This helps ensure that rotations adhere to the seven-day minimum period. + + * **Adhere to API Update Frequency and Wait Periods**: When updating user assignments via our APIs, follow the recommended frequency and wait period guidelines provided in the HumanSignal API documentation. Avoid sending rapid, successive requests that might overload the endpoint. Instead, incorporate appropriate delays between calls as specified in the documentation. + + * **Avoid Overloading the API Endpoint**: Design your integration to batch or schedule updates where possible, and implement backoff strategies if the API indicates rate limiting. This helps prevent service disruptions and ensures a smooth operation. + + Parameters + ---------- + id : int + A unique integer value identifying this organization. + + user_id : typing.Optional[int] + + role : typing.Optional[Role9E7Enum] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + LseOrganizationMemberList + + + Examples + -------- + from label_studio_sdk import LabelStudio + + client = LabelStudio( + api_key="YOUR_API_KEY", + ) + client.organizations.members.update( + id=1, + ) + """ + _response = self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/memberships", + method="PATCH", + json={ + "user_id": user_id, + "role": role, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + LseOrganizationMemberList, + construct_type( + type_=LseOrganizationMemberList, # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + def get( self, id: int, user_pk: int, *, request_options: typing.Optional[RequestOptions] = None ) -> OrganizationMember: @@ -148,6 +316,184 @@ class AsyncMembersClient: def __init__(self, *, client_wrapper: AsyncClientWrapper): self._client_wrapper = client_wrapper + async def list( + self, + id: int, + *, + exclude_project_id: typing.Optional[int] = None, + exclude_workspace_id: typing.Optional[int] = None, + ordering: typing.Optional[str] = None, + page: typing.Optional[int] = None, + page_size: typing.Optional[int] = None, + search: typing.Optional[str] = None, + request_options: typing.Optional[RequestOptions] = None, + ) -> PaginatedLseOrganizationMemberListList: + """ + Retrieve a list of all users and roles in a specific organization. + + Parameters + ---------- + id : int + A unique integer value identifying this organization. + + exclude_project_id : typing.Optional[int] + Project ID to exclude users who are already associated with this project (direct members, workspace members, or implicit admin/owner access). + + exclude_workspace_id : typing.Optional[int] + Workspace ID to exclude users who are already associated with this workspace (direct workspace members or implicit admin/owner access). + + ordering : typing.Optional[str] + Which field to use when ordering the results. + + page : typing.Optional[int] + A page number within the paginated result set. + + page_size : typing.Optional[int] + Number of results to return per page. + + search : typing.Optional[str] + A search term. + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + PaginatedLseOrganizationMemberListList + + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.members.list( + id=1, + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/memberships", + method="GET", + params={ + "exclude_project_id": exclude_project_id, + "exclude_workspace_id": exclude_workspace_id, + "ordering": ordering, + "page": page, + "page_size": page_size, + "search": search, + }, + request_options=request_options, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + PaginatedLseOrganizationMemberListList, + construct_type( + type_=PaginatedLseOrganizationMemberListList, # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + + async def update( + self, + id: int, + *, + user_id: typing.Optional[int] = OMIT, + role: typing.Optional[Role9E7Enum] = OMIT, + request_options: typing.Optional[RequestOptions] = None, + ) -> LseOrganizationMemberList: + """ + Update organization membership or role for a specific user ID. + + **User Rotation Best Practices for API Usage** + + To maintain compliance with our licensing terms and ensure optimal performance of HumanSignal's APIs, please consider the following guidelines when managing user assignments: + + * **Maintain a 7-Day Minimum Assignment**: Once a licensed seat is assigned to a user, maintain that assignment for at least seven consecutive days before rotating it to another user. + + * **Automate, Monitor, and Log Rotations**: Implement automated scheduling and logging mechanisms to track the timing of user rotations. This helps ensure that rotations adhere to the seven-day minimum period. + + * **Adhere to API Update Frequency and Wait Periods**: When updating user assignments via our APIs, follow the recommended frequency and wait period guidelines provided in the HumanSignal API documentation. Avoid sending rapid, successive requests that might overload the endpoint. Instead, incorporate appropriate delays between calls as specified in the documentation. + + * **Avoid Overloading the API Endpoint**: Design your integration to batch or schedule updates where possible, and implement backoff strategies if the API indicates rate limiting. This helps prevent service disruptions and ensures a smooth operation. + + Parameters + ---------- + id : int + A unique integer value identifying this organization. + + user_id : typing.Optional[int] + + role : typing.Optional[Role9E7Enum] + + request_options : typing.Optional[RequestOptions] + Request-specific configuration. + + Returns + ------- + LseOrganizationMemberList + + + Examples + -------- + import asyncio + + from label_studio_sdk import AsyncLabelStudio + + client = AsyncLabelStudio( + api_key="YOUR_API_KEY", + ) + + + async def main() -> None: + await client.organizations.members.update( + id=1, + ) + + + asyncio.run(main()) + """ + _response = await self._client_wrapper.httpx_client.request( + f"api/organizations/{jsonable_encoder(id)}/memberships", + method="PATCH", + json={ + "user_id": user_id, + "role": role, + }, + headers={ + "content-type": "application/json", + }, + request_options=request_options, + omit=OMIT, + ) + try: + if 200 <= _response.status_code < 300: + return typing.cast( + LseOrganizationMemberList, + construct_type( + type_=LseOrganizationMemberList, # type: ignore + object_=_response.json(), + ), + ) + _response_json = _response.json() + except JSONDecodeError: + raise ApiError(status_code=_response.status_code, body=_response.text) + raise ApiError(status_code=_response.status_code, body=_response_json) + async def get( self, id: int, user_pk: int, *, request_options: typing.Optional[RequestOptions] = None ) -> OrganizationMember: diff --git a/src/label_studio_sdk/types/__init__.py b/src/label_studio_sdk/types/__init__.py index 3064ecdb3..d45ee28c6 100644 --- a/src/label_studio_sdk/types/__init__.py +++ b/src/label_studio_sdk/types/__init__.py @@ -21,6 +21,9 @@ from .azure_blob_import_storage import AzureBlobImportStorage from .batch_failed_predictions import BatchFailedPredictions from .batch_predictions import BatchPredictions +from .billing_checks import BillingChecks +from .billing_flags import BillingFlags +from .billing_info_response import BillingInfoResponse from .blank_enum import BlankEnum from .blueprint_list import BlueprintList from .budget_reset_period_enum import BudgetResetPeriodEnum @@ -30,6 +33,7 @@ from .comment_serializer_with_expanded_user import CommentSerializerWithExpandedUser from .converted_format import ConvertedFormat from .converted_format_request import ConvertedFormatRequest +from .count_limit import CountLimit from .custom_scripts_editable_by_enum import CustomScriptsEditableByEnum from .default_role_enum import DefaultRoleEnum from .edition_enum import EditionEnum @@ -58,6 +62,7 @@ from .lse_key_indicator_value import LseKeyIndicatorValue from .lse_organization import LseOrganization from .lse_organization_custom_scripts_editable_by import LseOrganizationCustomScriptsEditableBy +from .lse_organization_member_list import LseOrganizationMemberList from .lse_project_create import LseProjectCreate from .lse_project_create_sampling import LseProjectCreateSampling from .lse_project_create_skip_queue import LseProjectCreateSkipQueue @@ -89,6 +94,7 @@ from .lse_task_serializer_for_reviewers_predictions_item import LseTaskSerializerForReviewersPredictionsItem from .lse_user import LseUser from .lse_user_api import LseUserApi +from .lse_user_organization_member_list import LseUserOrganizationMemberList from .lseapi_token_create import LseapiTokenCreate from .lseapi_token_list import LseapiTokenList from .lsejwt_settings import LsejwtSettings @@ -111,6 +117,7 @@ from .organization_member import OrganizationMember from .organization_membership import OrganizationMembership from .paginated_all_roles_project_list_list import PaginatedAllRolesProjectListList +from .paginated_lse_organization_member_list_list import PaginatedLseOrganizationMemberListList from .paginated_role_based_task_list import PaginatedRoleBasedTaskList from .pause import Pause from .pause_request import PauseRequest @@ -123,6 +130,7 @@ from .project_sampling import ProjectSampling from .project_skip_queue import ProjectSkipQueue from .project_subset_enum import ProjectSubsetEnum +from .prompts_status_enum import PromptsStatusEnum from .provider_enum import ProviderEnum from .reason_enum import ReasonEnum from .redis_export_storage import RedisExportStorage @@ -137,6 +145,7 @@ from .review_settings_requeue_rejected_tasks_mode import ReviewSettingsRequeueRejectedTasksMode from .review_settings_review_criteria import ReviewSettingsReviewCriteria from .reviewed_enum import ReviewedEnum +from .role9e7enum import Role9E7Enum from .role_based_task import RoleBasedTask from .s3export_storage import S3ExportStorage from .s3import_storage import S3ImportStorage @@ -188,6 +197,9 @@ "AzureBlobImportStorage", "BatchFailedPredictions", "BatchPredictions", + "BillingChecks", + "BillingFlags", + "BillingInfoResponse", "BlankEnum", "BlueprintList", "BudgetResetPeriodEnum", @@ -197,6 +209,7 @@ "CommentSerializerWithExpandedUser", "ConvertedFormat", "ConvertedFormatRequest", + "CountLimit", "CustomScriptsEditableByEnum", "DefaultRoleEnum", "EditionEnum", @@ -225,6 +238,7 @@ "LseKeyIndicatorValue", "LseOrganization", "LseOrganizationCustomScriptsEditableBy", + "LseOrganizationMemberList", "LseProjectCreate", "LseProjectCreateSampling", "LseProjectCreateSkipQueue", @@ -256,6 +270,7 @@ "LseTaskSerializerForReviewersPredictionsItem", "LseUser", "LseUserApi", + "LseUserOrganizationMemberList", "LseapiTokenCreate", "LseapiTokenList", "LsejwtSettings", @@ -278,6 +293,7 @@ "OrganizationMember", "OrganizationMembership", "PaginatedAllRolesProjectListList", + "PaginatedLseOrganizationMemberListList", "PaginatedRoleBasedTaskList", "Pause", "PauseRequest", @@ -290,6 +306,7 @@ "ProjectSampling", "ProjectSkipQueue", "ProjectSubsetEnum", + "PromptsStatusEnum", "ProviderEnum", "ReasonEnum", "RedisExportStorage", @@ -304,6 +321,7 @@ "ReviewSettingsRequeueRejectedTasksMode", "ReviewSettingsReviewCriteria", "ReviewedEnum", + "Role9E7Enum", "RoleBasedTask", "S3ExportStorage", "S3ImportStorage", diff --git a/src/label_studio_sdk/types/all_roles_project_list.py b/src/label_studio_sdk/types/all_roles_project_list.py index 68b64ca5d..52617c99b 100644 --- a/src/label_studio_sdk/types/all_roles_project_list.py +++ b/src/label_studio_sdk/types/all_roles_project_list.py @@ -3,12 +3,12 @@ from ..core.unchecked_base_model import UncheckedBaseModel import typing import pydantic -from .all_roles_project_list_sampling import AllRolesProjectListSampling from .user_simple import UserSimple -import datetime as dt -from .blueprint_list import BlueprintList from .assignment_settings import AssignmentSettings +from .all_roles_project_list_sampling import AllRolesProjectListSampling +import datetime as dt from .all_roles_project_list_skip_queue import AllRolesProjectListSkipQueue +from .blueprint_list import BlueprintList from .review_settings import ReviewSettings from ..core.pydantic_utilities import IS_PYDANTIC_V2 @@ -19,173 +19,173 @@ class AllRolesProjectList(UncheckedBaseModel): make sure, that you use correct one(Project.objects.with_counts()) """ - workspace_title: str - ready: str - overlap_cohort_percentage: typing.Optional[int] = None - queue_left: str - config_suitable_for_bulk_annotation: bool = pydantic.Field() - """ - Flag to detect is project ready for bulk annotation - """ - - has_blueprints: str - show_overlap_first: typing.Optional[bool] = None - queue_total: str - enable_empty_annotation: typing.Optional[bool] = pydantic.Field(default=None) + show_ground_truth_first: typing.Optional[bool] = None + rejected: str + label_config: typing.Optional[str] = pydantic.Field(default=None) """ - Allow annotators to submit empty annotations + Label config in XML format. See more about it in documentation """ - custom_task_lock_ttl: typing.Optional[int] = pydantic.Field(default=None) + show_instruction: typing.Optional[bool] = pydantic.Field(default=None) """ - TTL in seconds for task reservations, on new and existing tasks + Show instructions to the annotator before they start """ - prompts: str - start_training_on_annotation_update: bool = pydantic.Field() + duplication_status: typing.Optional[str] = None + control_weights: typing.Optional[typing.Optional[typing.Any]] = None + workspace: str + finished_task_number: int + show_skip_button: typing.Optional[bool] = pydantic.Field(default=None) """ - Start model training after any annotations are submitted or updated + Show a skip button in interface and allow annotators to skip the task """ - evaluate_predictions_automatically: typing.Optional[bool] = pydantic.Field(default=None) + created_by: typing.Optional[UserSimple] = pydantic.Field(default=None) """ - Retrieve and display predictions when loading a task + Project owner """ - show_instruction: typing.Optional[bool] = pydantic.Field(default=None) + assignment_settings: AssignmentSettings + reviewed_number: str + model_version: typing.Optional[str] = pydantic.Field(default=None) """ - Show instructions to the annotator before they start + Machine learning model version """ - color: typing.Optional[str] = None - sampling: typing.Optional[AllRolesProjectListSampling] = None - created_by: typing.Optional[UserSimple] = pydantic.Field(default=None) + data_types: typing.Optional[typing.Any] = None + description_short: str + queue_left: str + annotation_limit_percent: typing.Optional[str] = None + config_has_control_tags: bool = pydantic.Field() """ - Project owner + Flag to detect is project ready for labeling """ - reveal_preannotations_interactively: typing.Optional[bool] = pydantic.Field(default=None) + total_predictions_number: int + useful_annotation_number: str + custom_script: typing.Optional[str] = None + reviewer_queue_total: str + start_training_on_annotation_update: bool = pydantic.Field() """ - Reveal pre-annotations interactively + Start model training after any annotations are submitted or updated """ - pinned_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) + skipped_annotations_number: str + custom_task_lock_ttl: typing.Optional[int] = pydantic.Field(default=None) """ - Pinned date and time + TTL in seconds for task reservations, on new and existing tasks """ - finished_task_number: int - parsed_label_config: typing.Optional[typing.Any] = None - duplication_done: typing.Optional[bool] = None - reviewer_queue_total: str - show_ground_truth_first: typing.Optional[bool] = None - task_number: int = pydantic.Field() + workspace_title: str + sampling: typing.Optional[AllRolesProjectListSampling] = None + reveal_preannotations_interactively: typing.Optional[bool] = pydantic.Field(default=None) """ - Total task number in project + Reveal pre-annotations interactively """ - num_tasks_with_annotations: str - description_short: str id: int - allow_stream: str - annotation_limit_percent: typing.Optional[str] = None - created_at: dt.datetime - annotation_limit_count: typing.Optional[int] = None + has_blueprints: str queue_done: str - control_weights: typing.Optional[typing.Optional[typing.Any]] = None - data_types: typing.Optional[typing.Any] = None - reviewed_number: str total_annotations_number: str - total_predictions_number: int - config_has_control_tags: bool = pydantic.Field() + members_count: str + maximum_annotations: typing.Optional[int] = pydantic.Field(default=None) """ - Flag to detect is project ready for labeling + Maximum number of annotations for one task. If the number of annotations per task is equal or greater to this value, the task is completed (is_labeled=True) """ - blueprints: typing.List[BlueprintList] - is_published: typing.Optional[bool] = pydantic.Field(default=None) + comment_classification_config: typing.Optional[str] = None + prompts: str + created_at: dt.datetime + ready: str + annotator_evaluation_minimum_tasks: typing.Optional[int] = None + config_suitable_for_bulk_annotation: bool = pydantic.Field() """ - Whether or not the project is published to annotators + Flag to detect is project ready for bulk annotation """ - duplication_status: typing.Optional[str] = None - review_total_tasks: str - show_skip_button: typing.Optional[bool] = pydantic.Field(default=None) + skip_queue: typing.Optional[AllRolesProjectListSkipQueue] = None + title: typing.Optional[str] = pydantic.Field(default=None) """ - Show a skip button in interface and allow annotators to skip the task + Project name. Must be between 3 and 50 characters long. """ - is_draft: typing.Optional[bool] = pydantic.Field(default=None) + show_overlap_first: typing.Optional[bool] = None + queue_total: str + organization: typing.Optional[int] = None + duplication_done: typing.Optional[bool] = None + ground_truth_number: int = pydantic.Field() """ - Whether or not the project is in the middle of being created + Honeypot annotation number in project """ - title: typing.Optional[str] = pydantic.Field(default=None) + annotation_limit_count: typing.Optional[int] = None + evaluate_predictions_automatically: typing.Optional[bool] = pydantic.Field(default=None) """ - Project name. Must be between 3 and 50 characters long. + Retrieve and display predictions when loading a task """ - show_collab_predictions: typing.Optional[bool] = pydantic.Field(default=None) + blueprints: typing.List[BlueprintList] + color: typing.Optional[str] = None + review_settings: ReviewSettings + pinned_at: typing.Optional[dt.datetime] = pydantic.Field(default=None) """ - If set, the annotator can view model predictions + Pinned date and time """ members: str - min_annotations_to_start_training: typing.Optional[int] = pydantic.Field(default=None) + require_comment_on_skip: typing.Optional[bool] = None + show_annotation_history: typing.Optional[bool] = pydantic.Field(default=None) """ - Minimum number of completed tasks after which model training is started + Show annotation history to annotator """ - workspace: str - organization: typing.Optional[int] = None - assignment_settings: AssignmentSettings - annotator_evaluation_minimum_tasks: typing.Optional[int] = None - skipped_annotations_number: str - annotator_evaluation_minimum_score: typing.Optional[str] = None - comment_classification_config: typing.Optional[str] = None - description: typing.Optional[str] = pydantic.Field(default=None) + task_number: int = pydantic.Field() """ - Project description + Total task number in project """ - expert_instruction: typing.Optional[str] = pydantic.Field(default=None) + is_published: typing.Optional[bool] = pydantic.Field(default=None) """ - Labeling instructions in HTML format + Whether or not the project is published to annotators """ - show_annotation_history: typing.Optional[bool] = pydantic.Field(default=None) + show_collab_predictions: typing.Optional[bool] = pydantic.Field(default=None) """ - Show annotation history to annotator + If set, the annotator can view model predictions """ - skip_queue: typing.Optional[AllRolesProjectListSkipQueue] = None - review_settings: ReviewSettings - members_count: str - model_version: typing.Optional[str] = pydantic.Field(default=None) + review_total_tasks: str + num_tasks_with_annotations: str + expert_instruction: typing.Optional[str] = pydantic.Field(default=None) """ - Machine learning model version + Labeling instructions in HTML format """ - useful_annotation_number: str - custom_script: typing.Optional[str] = None - require_comment_on_skip: typing.Optional[bool] = None - ground_truth_number: int = pydantic.Field() + overlap_cohort_percentage: typing.Optional[int] = None + is_draft: typing.Optional[bool] = pydantic.Field(default=None) """ - Honeypot annotation number in project + Whether or not the project is in the middle of being created """ - pause_on_failed_annotator_evaluation: typing.Optional[bool] = None - label_config: typing.Optional[str] = pydantic.Field(default=None) + min_annotations_to_start_training: typing.Optional[int] = pydantic.Field(default=None) """ - Label config in XML format. See more about it in documentation + Minimum number of completed tasks after which model training is started """ - maximum_annotations: typing.Optional[int] = pydantic.Field(default=None) + enable_empty_annotation: typing.Optional[bool] = pydantic.Field(default=None) """ - Maximum number of annotations for one task. If the number of annotations per task is equal or greater to this value, the task is completed (is_labeled=True) + Allow annotators to submit empty annotations """ - rejected: str + annotator_evaluation_minimum_score: typing.Optional[str] = None + description: typing.Optional[str] = pydantic.Field(default=None) + """ + Project description + """ + + pause_on_failed_annotator_evaluation: typing.Optional[bool] = None + allow_stream: str + parsed_label_config: typing.Optional[typing.Any] = None if IS_PYDANTIC_V2: model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 diff --git a/src/label_studio_sdk/types/billing_checks.py b/src/label_studio_sdk/types/billing_checks.py new file mode 100644 index 000000000..a45a8a158 --- /dev/null +++ b/src/label_studio_sdk/types/billing_checks.py @@ -0,0 +1,39 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +from .count_limit import CountLimit +import typing +from .prompts_status_enum import PromptsStatusEnum +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class BillingChecks(UncheckedBaseModel): + users: CountLimit + projects: CountLimit + results: CountLimit + trial_days: int + organization_is_active: bool + license_issued: typing.Optional[str] = None + license_warning: typing.Optional[str] = None + is_license_warning: bool + license_expires: typing.Optional[str] = None + is_license_expired: bool + prompts_enabled: bool + prompts_status: PromptsStatusEnum + prompts_warning: typing.Optional[str] = None + is_prompts_warning: bool + prompts_expire: typing.Optional[str] = None + is_prompts_expire: bool + prompts_api_keys_enabled: bool + import_storages: CountLimit + export_storages: CountLimit + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/label_studio_sdk/types/billing_flags.py b/src/label_studio_sdk/types/billing_flags.py new file mode 100644 index 000000000..980902f5e --- /dev/null +++ b/src/label_studio_sdk/types/billing_flags.py @@ -0,0 +1,44 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +import typing +import datetime as dt +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class BillingFlags(UncheckedBaseModel): + activated_at: typing.Optional[dt.datetime] = None + cloud_instance: bool + allow_activity_log: bool + allow_invite_project_experts: bool + allow_sso: bool + white_label_id: typing.Optional[str] = None + allow_data_credentials: bool + allow_organization_webhooks: bool + disable_members_page: bool + secure_mode: bool + manual_workspace_management: bool + manual_role_management: bool + hide_storage_settings_for_manager: bool + disable_project_imports: bool + automax_token_exists: bool + automax_enabled: bool + storage_persistence: bool + allow_ai: bool + early_adopter: bool + allow_ask_ai: bool + allow_invite_people: bool + allow_storage_proxy: bool + embed_enabled: bool + embed_domains: typing.Optional[typing.List[typing.Dict[str, typing.Optional[typing.Any]]]] = None + embed_settings: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/label_studio_sdk/types/billing_info_response.py b/src/label_studio_sdk/types/billing_info_response.py new file mode 100644 index 000000000..0bfaf5523 --- /dev/null +++ b/src/label_studio_sdk/types/billing_info_response.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +from .billing_checks import BillingChecks +from .billing_flags import BillingFlags +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing +import pydantic + + +class BillingInfoResponse(UncheckedBaseModel): + billing_checks: BillingChecks + billing_flags: BillingFlags + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/label_studio_sdk/types/count_limit.py b/src/label_studio_sdk/types/count_limit.py new file mode 100644 index 000000000..26a6050fd --- /dev/null +++ b/src/label_studio_sdk/types/count_limit.py @@ -0,0 +1,22 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +import typing +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class CountLimit(UncheckedBaseModel): + count: int + limit: int + reached: bool + total: typing.Optional[int] = None + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/label_studio_sdk/types/lse_organization_member_list.py b/src/label_studio_sdk/types/lse_organization_member_list.py new file mode 100644 index 000000000..bce1303bb --- /dev/null +++ b/src/label_studio_sdk/types/lse_organization_member_list.py @@ -0,0 +1,32 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +import pydantic +from .lse_user_organization_member_list import LseUserOrganizationMemberList +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import typing + + +class LseOrganizationMemberList(UncheckedBaseModel): + """ + A serializer mixin that takes an additional `fields` argument that controls + which fields should be displayed. + """ + + id: int + organization: int = pydantic.Field() + """ + Organization ID + """ + + user: LseUserOrganizationMemberList + role: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/label_studio_sdk/types/lse_user_organization_member_list.py b/src/label_studio_sdk/types/lse_user_organization_member_list.py new file mode 100644 index 000000000..7699d06a8 --- /dev/null +++ b/src/label_studio_sdk/types/lse_user_organization_member_list.py @@ -0,0 +1,48 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +import typing +import datetime as dt +import pydantic +from .lse_fields import LseFields +from ..core.pydantic_utilities import IS_PYDANTIC_V2 + + +class LseUserOrganizationMemberList(UncheckedBaseModel): + """ + A ModelSerializer that takes additional arguments for + "fields", "omit" and "expand" in order to + control which fields are displayed, and whether to replace simple + values with complex, nested serializations + """ + + id: int + first_name: typing.Optional[str] = None + last_name: typing.Optional[str] = None + username: str + email: typing.Optional[str] = None + last_activity: dt.datetime + custom_hotkeys: typing.Optional[typing.Optional[typing.Any]] = None + avatar: str + initials: str + phone: typing.Optional[str] = None + active_organization: typing.Optional[int] = None + allow_newsletters: typing.Optional[bool] = pydantic.Field(default=None) + """ + Allow sending newsletters to user + """ + + date_joined: typing.Optional[dt.datetime] = None + lse_fields: LseFields + pause: str + created_projects: str + contributed_to_projects: str + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/label_studio_sdk/types/paginated_lse_organization_member_list_list.py b/src/label_studio_sdk/types/paginated_lse_organization_member_list_list.py new file mode 100644 index 000000000..4b51fb3fd --- /dev/null +++ b/src/label_studio_sdk/types/paginated_lse_organization_member_list_list.py @@ -0,0 +1,23 @@ +# This file was auto-generated by Fern from our API Definition. + +from ..core.unchecked_base_model import UncheckedBaseModel +import typing +from .lse_organization_member_list import LseOrganizationMemberList +from ..core.pydantic_utilities import IS_PYDANTIC_V2 +import pydantic + + +class PaginatedLseOrganizationMemberListList(UncheckedBaseModel): + count: int + next: typing.Optional[str] = None + previous: typing.Optional[str] = None + results: typing.List[LseOrganizationMemberList] + + if IS_PYDANTIC_V2: + model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2 + else: + + class Config: + frozen = True + smart_union = True + extra = pydantic.Extra.allow diff --git a/src/label_studio_sdk/types/prompts_status_enum.py b/src/label_studio_sdk/types/prompts_status_enum.py new file mode 100644 index 000000000..b38ee4b50 --- /dev/null +++ b/src/label_studio_sdk/types/prompts_status_enum.py @@ -0,0 +1,16 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +PromptsStatusEnum = typing.Union[ + typing.Literal[ + "Enabled", + "Cloud license per organization disabled", + "On-premise global license disabled", + "Expired", + "Adala not connected", + "Disabled for this organization [FF]", + "unknown", + ], + typing.Any, +] diff --git a/src/label_studio_sdk/types/role9e7enum.py b/src/label_studio_sdk/types/role9e7enum.py new file mode 100644 index 000000000..d70569fb2 --- /dev/null +++ b/src/label_studio_sdk/types/role9e7enum.py @@ -0,0 +1,5 @@ +# This file was auto-generated by Fern from our API Definition. + +import typing + +Role9E7Enum = typing.Union[typing.Literal["OW", "AD", "MA", "RE", "AN", "DI", "NO"], typing.Any] diff --git a/tests/organizations/test_members.py b/tests/organizations/test_members.py index 658901506..604e81da4 100644 --- a/tests/organizations/test_members.py +++ b/tests/organizations/test_members.py @@ -6,6 +6,155 @@ from ..utilities import validate_response +async def test_list_(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = { + "count": 123, + "next": "http://api.example.org/accounts/?page=4", + "previous": "http://api.example.org/accounts/?page=2", + "results": [ + { + "id": 1, + "organization": 1, + "user": { + "id": 1, + "username": "username", + "last_activity": "2024-01-15T09:30:00Z", + "avatar": "avatar", + "initials": "initials", + "lse_fields": { + "invite_expired": "invite_expired", + "invite_expired_at": "invite_expired_at", + "email_notification_settings": "email_notification_settings", + }, + "pause": "pause", + "created_projects": "created_projects", + "contributed_to_projects": "contributed_to_projects", + }, + "role": "role", + } + ], + } + expected_types: typing.Any = { + "count": "integer", + "next": None, + "previous": None, + "results": ( + "list", + { + 0: { + "id": "integer", + "organization": "integer", + "user": { + "id": "integer", + "username": None, + "last_activity": "datetime", + "avatar": None, + "initials": None, + "lse_fields": { + "invite_expired": None, + "invite_expired_at": None, + "email_notification_settings": None, + }, + "pause": None, + "created_projects": None, + "contributed_to_projects": None, + }, + "role": None, + } + }, + ), + } + response = client.organizations.members.list(id=1) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.organizations.members.list(id=1) + validate_response(async_response, expected_response, expected_types) + + +async def test_update(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = { + "id": 1, + "organization": 1, + "user": { + "id": 1, + "first_name": "first_name", + "last_name": "last_name", + "username": "username", + "email": "email", + "last_activity": "2024-01-15T09:30:00Z", + "custom_hotkeys": {"key": "value"}, + "avatar": "avatar", + "initials": "initials", + "phone": "phone", + "active_organization": 1, + "allow_newsletters": True, + "date_joined": "2024-01-15T09:30:00Z", + "lse_fields": { + "invite_expired": "invite_expired", + "invite_expired_at": "invite_expired_at", + "invited_at": "2024-01-15T09:30:00Z", + "invite_activated": True, + "trial_company": "trial_company", + "trial_role": "annotator", + "trial_models_in_production": "trial_models_in_production", + "trial_experience_labeling": "trial_experience_labeling", + "trial_license_enterprise": True, + "social_auth_finished": True, + "invited_by": 1, + "onboarding_state": "not_started", + "email_notification_settings": "email_notification_settings", + }, + "pause": "pause", + "created_projects": "created_projects", + "contributed_to_projects": "contributed_to_projects", + }, + "role": "role", + } + expected_types: typing.Any = { + "id": "integer", + "organization": "integer", + "user": { + "id": "integer", + "first_name": None, + "last_name": None, + "username": None, + "email": None, + "last_activity": "datetime", + "custom_hotkeys": None, + "avatar": None, + "initials": None, + "phone": None, + "active_organization": "integer", + "allow_newsletters": None, + "date_joined": "datetime", + "lse_fields": { + "invite_expired": None, + "invite_expired_at": None, + "invited_at": "datetime", + "invite_activated": None, + "trial_company": None, + "trial_role": None, + "trial_models_in_production": None, + "trial_experience_labeling": None, + "trial_license_enterprise": None, + "social_auth_finished": None, + "invited_by": "integer", + "onboarding_state": None, + "email_notification_settings": None, + }, + "pause": None, + "created_projects": None, + "contributed_to_projects": None, + }, + "role": None, + } + response = client.organizations.members.update(id=1) + validate_response(response, expected_response, expected_types) + + async_response = await async_client.organizations.members.update(id=1) + validate_response(async_response, expected_response, expected_types) + + async def test_get(client: LabelStudio, async_client: AsyncLabelStudio) -> None: expected_response: typing.Any = { "user": 1, diff --git a/tests/test_billing.py b/tests/test_billing.py new file mode 100644 index 000000000..dbec9138c --- /dev/null +++ b/tests/test_billing.py @@ -0,0 +1,114 @@ +# This file was auto-generated by Fern from our API Definition. + +from label_studio_sdk import LabelStudio +from label_studio_sdk import AsyncLabelStudio +import typing +from .utilities import validate_response + + +async def test_info(client: LabelStudio, async_client: AsyncLabelStudio) -> None: + expected_response: typing.Any = { + "billing_checks": { + "users": {"count": 110, "limit": 1000, "reached": False, "total": 221}, + "projects": {"count": 2044, "limit": 1000000, "reached": False, "total": 1}, + "results": {"count": 42949, "limit": 1000000000, "reached": False, "total": 1}, + "trial_days": 0, + "organization_is_active": True, + "license_issued": "2000-01-01", + "license_warning": "2030-01-01", + "is_license_warning": False, + "license_expires": "2030-01-02", + "is_license_expired": False, + "prompts_enabled": True, + "prompts_status": "Enabled", + "prompts_warning": "prompts_warning", + "is_prompts_warning": False, + "prompts_expire": "prompts_expire", + "is_prompts_expire": False, + "prompts_api_keys_enabled": True, + "import_storages": {"count": 0, "limit": 0, "reached": False, "total": 1}, + "export_storages": {"count": 0, "limit": 0, "reached": False, "total": 1}, + }, + "billing_flags": { + "activated_at": "2024-01-15T09:30:00Z", + "cloud_instance": True, + "allow_activity_log": True, + "allow_invite_project_experts": True, + "allow_sso": True, + "white_label_id": "white_label_id", + "allow_data_credentials": False, + "allow_organization_webhooks": False, + "disable_members_page": False, + "secure_mode": False, + "manual_workspace_management": True, + "manual_role_management": True, + "hide_storage_settings_for_manager": False, + "disable_project_imports": False, + "automax_token_exists": True, + "automax_enabled": True, + "storage_persistence": True, + "allow_ai": True, + "early_adopter": True, + "allow_ask_ai": True, + "allow_invite_people": True, + "allow_storage_proxy": True, + "embed_enabled": True, + "embed_domains": [{"domain": "http://localhost:3000"}, {"domain": "https://purple-zoos-flash.loca.lt"}], + "embed_settings": {"public_verify_alg": ["RS256"], "public_verify_key": "...."}, + }, + } + expected_types: typing.Any = { + "billing_checks": { + "users": {"count": "integer", "limit": "integer", "reached": None, "total": "integer"}, + "projects": {"count": "integer", "limit": "integer", "reached": None, "total": "integer"}, + "results": {"count": "integer", "limit": "integer", "reached": None, "total": "integer"}, + "trial_days": "integer", + "organization_is_active": None, + "license_issued": None, + "license_warning": None, + "is_license_warning": None, + "license_expires": None, + "is_license_expired": None, + "prompts_enabled": None, + "prompts_status": None, + "prompts_warning": None, + "is_prompts_warning": None, + "prompts_expire": None, + "is_prompts_expire": None, + "prompts_api_keys_enabled": None, + "import_storages": {"count": "integer", "limit": "integer", "reached": None, "total": "integer"}, + "export_storages": {"count": "integer", "limit": "integer", "reached": None, "total": "integer"}, + }, + "billing_flags": { + "activated_at": "datetime", + "cloud_instance": None, + "allow_activity_log": None, + "allow_invite_project_experts": None, + "allow_sso": None, + "white_label_id": None, + "allow_data_credentials": None, + "allow_organization_webhooks": None, + "disable_members_page": None, + "secure_mode": None, + "manual_workspace_management": None, + "manual_role_management": None, + "hide_storage_settings_for_manager": None, + "disable_project_imports": None, + "automax_token_exists": None, + "automax_enabled": None, + "storage_persistence": None, + "allow_ai": None, + "early_adopter": None, + "allow_ask_ai": None, + "allow_invite_people": None, + "allow_storage_proxy": None, + "embed_enabled": None, + "embed_domains": ("list", {0: ("dict", {0: (None, None)}), 1: ("dict", {0: (None, None)})}), + "embed_settings": ("dict", {0: (None, None), 1: (None, None)}), + }, + } + response = client.billing.info() + validate_response(response, expected_response, expected_types) + + async_response = await async_client.billing.info() + validate_response(async_response, expected_response, expected_types) diff --git a/tests/test_prompts.py b/tests/test_prompts.py index 01d8ef2bc..da3aaf9da 100644 --- a/tests/test_prompts.py +++ b/tests/test_prompts.py @@ -213,79 +213,79 @@ async def test_compatible_projects(client: LabelStudio, async_client: AsyncLabel "previous": "http://api.example.org/accounts/?page=2", "results": [ { - "workspace_title": "workspace_title", - "ready": "ready", - "overlap_cohort_percentage": 1, + "show_ground_truth_first": True, + "rejected": "rejected", + "label_config": "label_config", + "show_instruction": True, + "duplication_status": "duplication_status", + "control_weights": {"key": "value"}, + "workspace": "workspace", + "finished_task_number": 1, + "show_skip_button": True, + "created_by": {"id": 1, "avatar": "avatar"}, + "assignment_settings": {"id": 1}, + "reviewed_number": "reviewed_number", + "model_version": "model_version", + "data_types": {"key": "value"}, + "description_short": "description_short", "queue_left": "queue_left", - "config_suitable_for_bulk_annotation": True, - "has_blueprints": "has_blueprints", - "show_overlap_first": True, - "queue_total": "queue_total", - "enable_empty_annotation": True, - "custom_task_lock_ttl": 1, - "prompts": "prompts", + "annotation_limit_percent": "annotation_limit_percent", + "config_has_control_tags": True, + "total_predictions_number": 1, + "useful_annotation_number": "useful_annotation_number", + "custom_script": "custom_script", + "reviewer_queue_total": "reviewer_queue_total", "start_training_on_annotation_update": True, - "evaluate_predictions_automatically": True, - "show_instruction": True, - "color": "color", + "skipped_annotations_number": "skipped_annotations_number", + "custom_task_lock_ttl": 1, + "workspace_title": "workspace_title", "sampling": "Sequential sampling", - "created_by": {"id": 1, "avatar": "avatar"}, "reveal_preannotations_interactively": True, - "pinned_at": "2024-01-15T09:30:00Z", - "finished_task_number": 1, - "parsed_label_config": {"key": "value"}, - "duplication_done": True, - "reviewer_queue_total": "reviewer_queue_total", - "show_ground_truth_first": True, - "task_number": 1, - "num_tasks_with_annotations": "num_tasks_with_annotations", - "description_short": "description_short", "id": 1, - "allow_stream": "allow_stream", - "annotation_limit_percent": "annotation_limit_percent", - "created_at": "2024-01-15T09:30:00Z", - "annotation_limit_count": 1, + "has_blueprints": "has_blueprints", "queue_done": "queue_done", - "control_weights": {"key": "value"}, - "data_types": {"key": "value"}, - "reviewed_number": "reviewed_number", "total_annotations_number": "total_annotations_number", - "total_predictions_number": 1, - "config_has_control_tags": True, + "members_count": "members_count", + "maximum_annotations": 1, + "comment_classification_config": "comment_classification_config", + "prompts": "prompts", + "created_at": "2024-01-15T09:30:00Z", + "ready": "ready", + "annotator_evaluation_minimum_tasks": 1, + "config_suitable_for_bulk_annotation": True, + "skip_queue": "REQUEUE_FOR_ME", + "title": "title", + "show_overlap_first": True, + "queue_total": "queue_total", + "organization": 1, + "duplication_done": True, + "ground_truth_number": 1, + "annotation_limit_count": 1, + "evaluate_predictions_automatically": True, "blueprints": [ {"id": 1, "share_id": "share_id", "short_url": "short_url", "created_at": "2024-01-15T09:30:00Z"} ], + "color": "color", + "review_settings": {"id": 1, "requeue_rejected_tasks_to_annotator": True}, + "pinned_at": "2024-01-15T09:30:00Z", + "members": "members", + "require_comment_on_skip": True, + "show_annotation_history": True, + "task_number": 1, "is_published": True, - "duplication_status": "duplication_status", + "show_collab_predictions": True, "review_total_tasks": "review_total_tasks", - "show_skip_button": True, + "num_tasks_with_annotations": "num_tasks_with_annotations", + "expert_instruction": "expert_instruction", + "overlap_cohort_percentage": 1, "is_draft": True, - "title": "title", - "show_collab_predictions": True, - "members": "members", "min_annotations_to_start_training": 1, - "workspace": "workspace", - "organization": 1, - "assignment_settings": {"id": 1}, - "annotator_evaluation_minimum_tasks": 1, - "skipped_annotations_number": "skipped_annotations_number", + "enable_empty_annotation": True, "annotator_evaluation_minimum_score": "annotator_evaluation_minimum_score", - "comment_classification_config": "comment_classification_config", "description": "description", - "expert_instruction": "expert_instruction", - "show_annotation_history": True, - "skip_queue": "REQUEUE_FOR_ME", - "review_settings": {"id": 1, "requeue_rejected_tasks_to_annotator": True}, - "members_count": "members_count", - "model_version": "model_version", - "useful_annotation_number": "useful_annotation_number", - "custom_script": "custom_script", - "require_comment_on_skip": True, - "ground_truth_number": 1, "pause_on_failed_annotator_evaluation": True, - "label_config": "label_config", - "maximum_annotations": 1, - "rejected": "rejected", + "allow_stream": "allow_stream", + "parsed_label_config": {"key": "value"}, } ], } @@ -297,80 +297,80 @@ async def test_compatible_projects(client: LabelStudio, async_client: AsyncLabel "list", { 0: { - "workspace_title": None, - "ready": None, - "overlap_cohort_percentage": "integer", + "show_ground_truth_first": None, + "rejected": None, + "label_config": None, + "show_instruction": None, + "duplication_status": None, + "control_weights": None, + "workspace": None, + "finished_task_number": "integer", + "show_skip_button": None, + "created_by": {"id": "integer", "avatar": None}, + "assignment_settings": {"id": "integer"}, + "reviewed_number": None, + "model_version": None, + "data_types": None, + "description_short": None, "queue_left": None, - "config_suitable_for_bulk_annotation": None, - "has_blueprints": None, - "show_overlap_first": None, - "queue_total": None, - "enable_empty_annotation": None, - "custom_task_lock_ttl": "integer", - "prompts": None, + "annotation_limit_percent": None, + "config_has_control_tags": None, + "total_predictions_number": "integer", + "useful_annotation_number": None, + "custom_script": None, + "reviewer_queue_total": None, "start_training_on_annotation_update": None, - "evaluate_predictions_automatically": None, - "show_instruction": None, - "color": None, + "skipped_annotations_number": None, + "custom_task_lock_ttl": "integer", + "workspace_title": None, "sampling": None, - "created_by": {"id": "integer", "avatar": None}, "reveal_preannotations_interactively": None, - "pinned_at": "datetime", - "finished_task_number": "integer", - "parsed_label_config": None, - "duplication_done": None, - "reviewer_queue_total": None, - "show_ground_truth_first": None, - "task_number": "integer", - "num_tasks_with_annotations": None, - "description_short": None, "id": "integer", - "allow_stream": None, - "annotation_limit_percent": None, - "created_at": "datetime", - "annotation_limit_count": "integer", + "has_blueprints": None, "queue_done": None, - "control_weights": None, - "data_types": None, - "reviewed_number": None, "total_annotations_number": None, - "total_predictions_number": "integer", - "config_has_control_tags": None, + "members_count": None, + "maximum_annotations": "integer", + "comment_classification_config": None, + "prompts": None, + "created_at": "datetime", + "ready": None, + "annotator_evaluation_minimum_tasks": "integer", + "config_suitable_for_bulk_annotation": None, + "skip_queue": None, + "title": None, + "show_overlap_first": None, + "queue_total": None, + "organization": "integer", + "duplication_done": None, + "ground_truth_number": "integer", + "annotation_limit_count": "integer", + "evaluate_predictions_automatically": None, "blueprints": ( "list", {0: {"id": "integer", "share_id": None, "short_url": None, "created_at": "datetime"}}, ), + "color": None, + "review_settings": {"id": "integer", "requeue_rejected_tasks_to_annotator": None}, + "pinned_at": "datetime", + "members": None, + "require_comment_on_skip": None, + "show_annotation_history": None, + "task_number": "integer", "is_published": None, - "duplication_status": None, + "show_collab_predictions": None, "review_total_tasks": None, - "show_skip_button": None, + "num_tasks_with_annotations": None, + "expert_instruction": None, + "overlap_cohort_percentage": "integer", "is_draft": None, - "title": None, - "show_collab_predictions": None, - "members": None, "min_annotations_to_start_training": "integer", - "workspace": None, - "organization": "integer", - "assignment_settings": {"id": "integer"}, - "annotator_evaluation_minimum_tasks": "integer", - "skipped_annotations_number": None, + "enable_empty_annotation": None, "annotator_evaluation_minimum_score": None, - "comment_classification_config": None, "description": None, - "expert_instruction": None, - "show_annotation_history": None, - "skip_queue": None, - "review_settings": {"id": "integer", "requeue_rejected_tasks_to_annotator": None}, - "members_count": None, - "model_version": None, - "useful_annotation_number": None, - "custom_script": None, - "require_comment_on_skip": None, - "ground_truth_number": "integer", "pause_on_failed_annotator_evaluation": None, - "label_config": None, - "maximum_annotations": "integer", - "rejected": None, + "allow_stream": None, + "parsed_label_config": None, } }, ),