spatialflow 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- spatialflow/__init__.py +91 -0
- spatialflow/_generated/.github/workflows/python.yml +31 -0
- spatialflow/_generated/.gitignore +66 -0
- spatialflow/_generated/.gitlab-ci.yml +31 -0
- spatialflow/_generated/.openapi-generator/FILES +390 -0
- spatialflow/_generated/.openapi-generator/VERSION +1 -0
- spatialflow/_generated/.openapi-generator-ignore +23 -0
- spatialflow/_generated/.spec-hash +1 -0
- spatialflow/_generated/.travis.yml +17 -0
- spatialflow/_generated/README.md +537 -0
- spatialflow/_generated/__init__.py +1 -0
- spatialflow/_generated/docs/APIUsageStats.md +32 -0
- spatialflow/_generated/docs/AccountApi.md +1751 -0
- spatialflow/_generated/docs/ActionDeliverySuccessMetrics.md +32 -0
- spatialflow/_generated/docs/ActionResponse.md +32 -0
- spatialflow/_generated/docs/ActionRetryConfigSchema.md +32 -0
- spatialflow/_generated/docs/ActivitySummary.md +30 -0
- spatialflow/_generated/docs/AdminApi.md +1787 -0
- spatialflow/_generated/docs/ApiKeyCreateRequest.md +31 -0
- spatialflow/_generated/docs/ApiKeyCreateResponse.md +31 -0
- spatialflow/_generated/docs/ApiKeyResponse.md +38 -0
- spatialflow/_generated/docs/ApiKeyUpdateRequest.md +33 -0
- spatialflow/_generated/docs/AsyncUploadGeofencesResponse.md +33 -0
- spatialflow/_generated/docs/AuthTypeEnum.md +17 -0
- spatialflow/_generated/docs/AuthenticationApi.md +1289 -0
- spatialflow/_generated/docs/BatchLocationUpdateIn.md +30 -0
- spatialflow/_generated/docs/BillingApi.md +925 -0
- spatialflow/_generated/docs/BulkGeofenceRequest.md +29 -0
- spatialflow/_generated/docs/ChangePasswordSchema.md +30 -0
- spatialflow/_generated/docs/CheckoutSessionRequest.md +32 -0
- spatialflow/_generated/docs/CheckoutSessionResponse.md +31 -0
- spatialflow/_generated/docs/CircuitBreakerSchema.md +33 -0
- spatialflow/_generated/docs/ConfigFieldDefinitionRequest.md +41 -0
- spatialflow/_generated/docs/ConfigFieldDefinitionResponse.md +43 -0
- spatialflow/_generated/docs/ConfirmPasswordResetSchema.md +31 -0
- spatialflow/_generated/docs/CreateFromTemplateIn.md +30 -0
- spatialflow/_generated/docs/CreateGeofenceRequest.md +36 -0
- spatialflow/_generated/docs/CreateIntegrationSchema.md +33 -0
- spatialflow/_generated/docs/CreateUserSchema.md +35 -0
- spatialflow/_generated/docs/CreateWebhookRequest.md +43 -0
- spatialflow/_generated/docs/DashboardComparisonMetrics.md +32 -0
- spatialflow/_generated/docs/DashboardMetricsResponse.md +36 -0
- spatialflow/_generated/docs/DefaultApi.md +585 -0
- spatialflow/_generated/docs/DeleteFileResponse.md +30 -0
- spatialflow/_generated/docs/DeliveryStatusEnum.md +15 -0
- spatialflow/_generated/docs/DeviceIn.md +32 -0
- spatialflow/_generated/docs/DeviceOut.md +37 -0
- spatialflow/_generated/docs/DevicesApi.md +1213 -0
- spatialflow/_generated/docs/E2ETestApi.md +271 -0
- spatialflow/_generated/docs/EmailApi.md +541 -0
- spatialflow/_generated/docs/EmailHealthResponse.md +31 -0
- spatialflow/_generated/docs/EmailQueueStats.md +34 -0
- spatialflow/_generated/docs/EmailStats.md +31 -0
- spatialflow/_generated/docs/EmailStatusResponse.md +36 -0
- spatialflow/_generated/docs/ErrorResponse.md +32 -0
- spatialflow/_generated/docs/ExecutionOut.md +38 -0
- spatialflow/_generated/docs/ExportIntegrationSchema.md +35 -0
- spatialflow/_generated/docs/FileListResponse.md +31 -0
- spatialflow/_generated/docs/ForgotPasswordSchema.md +29 -0
- spatialflow/_generated/docs/GPXPlaybackOut.md +42 -0
- spatialflow/_generated/docs/GPXRouteOut.md +40 -0
- spatialflow/_generated/docs/GPXSimulatorApi.md +883 -0
- spatialflow/_generated/docs/GeoJSONPoint.md +31 -0
- spatialflow/_generated/docs/GeofenceListResponse.md +31 -0
- spatialflow/_generated/docs/GeofenceResponse.md +43 -0
- spatialflow/_generated/docs/GeofenceStats.md +30 -0
- spatialflow/_generated/docs/GeofenceTestResult.md +33 -0
- spatialflow/_generated/docs/GeofencesApi.md +1524 -0
- spatialflow/_generated/docs/HealthCheckResponse.md +31 -0
- spatialflow/_generated/docs/HealthResponse.md +32 -0
- spatialflow/_generated/docs/ImportIntegrationSchema.md +32 -0
- spatialflow/_generated/docs/ImportResultSchema.md +33 -0
- spatialflow/_generated/docs/IntegrationDetailSchema.md +44 -0
- spatialflow/_generated/docs/IntegrationResponseSchema.md +42 -0
- spatialflow/_generated/docs/IntegrationStatsSchema.md +36 -0
- spatialflow/_generated/docs/IntegrationTypeListResponse.md +34 -0
- spatialflow/_generated/docs/IntegrationTypeRequest.md +40 -0
- spatialflow/_generated/docs/IntegrationTypeResponse.md +45 -0
- spatialflow/_generated/docs/IntegrationsApi.md +2008 -0
- spatialflow/_generated/docs/InvoiceLineItem.md +33 -0
- spatialflow/_generated/docs/InvoiceListResponse.md +31 -0
- spatialflow/_generated/docs/InvoiceResponse.md +40 -0
- spatialflow/_generated/docs/LocationBatchIn.md +31 -0
- spatialflow/_generated/docs/LocationImportResponse.md +41 -0
- spatialflow/_generated/docs/LocationIngestResponse.md +35 -0
- spatialflow/_generated/docs/LocationPointIn.md +38 -0
- spatialflow/_generated/docs/LocationUpdateIn.md +36 -0
- spatialflow/_generated/docs/LocationUpdateOut.md +32 -0
- spatialflow/_generated/docs/LoginResponse.md +33 -0
- spatialflow/_generated/docs/LoginSchema.md +30 -0
- spatialflow/_generated/docs/MemberActionResponse.md +33 -0
- spatialflow/_generated/docs/MemberSummary.md +36 -0
- spatialflow/_generated/docs/MethodEnum.md +17 -0
- spatialflow/_generated/docs/OAuthAuthorizeResponse.md +29 -0
- spatialflow/_generated/docs/OAuthCallbackQuery.md +32 -0
- spatialflow/_generated/docs/OAuthLinkResponse.md +31 -0
- spatialflow/_generated/docs/OAuthProvidersResponse.md +29 -0
- spatialflow/_generated/docs/OnboardingProgressResponse.md +37 -0
- spatialflow/_generated/docs/PaymentMethodResponse.md +37 -0
- spatialflow/_generated/docs/PingResponse.md +31 -0
- spatialflow/_generated/docs/PlanChangePreviewResponse.md +35 -0
- spatialflow/_generated/docs/PlanFeatures.md +36 -0
- spatialflow/_generated/docs/PlanLimits.md +34 -0
- spatialflow/_generated/docs/PlanResponse.md +37 -0
- spatialflow/_generated/docs/PortalSessionRequest.md +30 -0
- spatialflow/_generated/docs/PortalSessionResponse.md +30 -0
- spatialflow/_generated/docs/PresignedUrlRequest.md +31 -0
- spatialflow/_generated/docs/PresignedUrlResponse.md +35 -0
- spatialflow/_generated/docs/PrivacyErasureRequest.md +35 -0
- spatialflow/_generated/docs/PrivacyErasureResponse.md +36 -0
- spatialflow/_generated/docs/PublicApi.md +389 -0
- spatialflow/_generated/docs/PublicLocationIngestApi.md +249 -0
- spatialflow/_generated/docs/RateLimitResponse.md +32 -0
- spatialflow/_generated/docs/RecentActivity.md +31 -0
- spatialflow/_generated/docs/RefreshTokenSchema.md +29 -0
- spatialflow/_generated/docs/RegisterSchema.md +37 -0
- spatialflow/_generated/docs/ResendVerificationSchema.md +29 -0
- spatialflow/_generated/docs/ResetPasswordSchema.md +31 -0
- spatialflow/_generated/docs/RetryPolicyResponseSchema.md +32 -0
- spatialflow/_generated/docs/RetryPolicySchema.md +35 -0
- spatialflow/_generated/docs/RetryStrategyEnum.md +14 -0
- spatialflow/_generated/docs/SeedDataResponseSchema.md +31 -0
- spatialflow/_generated/docs/SendEmailRequest.md +33 -0
- spatialflow/_generated/docs/SetupIntentResponse.md +30 -0
- spatialflow/_generated/docs/SignupRequest.md +40 -0
- spatialflow/_generated/docs/StartPlaybackRequest.md +30 -0
- spatialflow/_generated/docs/StorageApi.md +494 -0
- spatialflow/_generated/docs/SubscriptionActionResponse.md +32 -0
- spatialflow/_generated/docs/SubscriptionResponse.md +36 -0
- spatialflow/_generated/docs/SubscriptionsApi.md +677 -0
- spatialflow/_generated/docs/SuccessResponse.md +31 -0
- spatialflow/_generated/docs/SystemApi.md +137 -0
- spatialflow/_generated/docs/TemplateOut.md +35 -0
- spatialflow/_generated/docs/TestEventRequest.md +29 -0
- spatialflow/_generated/docs/TestIntegrationResponseSchema.md +31 -0
- spatialflow/_generated/docs/TestPointRequest.md +34 -0
- spatialflow/_generated/docs/TestPointResponse.md +33 -0
- spatialflow/_generated/docs/TestWebhookRequest.md +32 -0
- spatialflow/_generated/docs/TestWorkflowIn.md +29 -0
- spatialflow/_generated/docs/TileMetadata.md +36 -0
- spatialflow/_generated/docs/TilesApi.md +462 -0
- spatialflow/_generated/docs/UnsubscribeRequest.md +29 -0
- spatialflow/_generated/docs/UnsubscribeResponse.md +31 -0
- spatialflow/_generated/docs/UpdateGeofenceRequest.md +37 -0
- spatialflow/_generated/docs/UpdateIntegrationSchema.md +33 -0
- spatialflow/_generated/docs/UpdateMemberRoleRequest.md +30 -0
- spatialflow/_generated/docs/UpdateOnboardingProgressRequest.md +30 -0
- spatialflow/_generated/docs/UpdateProfileRequest.md +45 -0
- spatialflow/_generated/docs/UpdateUserWorkspaceRequest.md +31 -0
- spatialflow/_generated/docs/UpdateWebhookRequest.md +43 -0
- spatialflow/_generated/docs/UploadGeofencesRequest.md +31 -0
- spatialflow/_generated/docs/UploadJobStatus.md +42 -0
- spatialflow/_generated/docs/UsageMetrics.md +33 -0
- spatialflow/_generated/docs/UsageResponse.md +36 -0
- spatialflow/_generated/docs/UsageStats.md +32 -0
- spatialflow/_generated/docs/UserActionResponse.md +35 -0
- spatialflow/_generated/docs/UserApprovalRequest.md +30 -0
- spatialflow/_generated/docs/UserInviteRequest.md +33 -0
- spatialflow/_generated/docs/UserInviteResponse.md +36 -0
- spatialflow/_generated/docs/UserListResponse.md +34 -0
- spatialflow/_generated/docs/UserProfileResponse.md +55 -0
- spatialflow/_generated/docs/UserRejectionRequest.md +30 -0
- spatialflow/_generated/docs/UserResponse.md +44 -0
- spatialflow/_generated/docs/UserSummary.md +41 -0
- spatialflow/_generated/docs/UserUsageResponse.md +38 -0
- spatialflow/_generated/docs/UserWorkspaceResponse.md +34 -0
- spatialflow/_generated/docs/WebhookDeliveryDetailResponse.md +49 -0
- spatialflow/_generated/docs/WebhookDeliveryListResponse.md +31 -0
- spatialflow/_generated/docs/WebhookDeliveryResponse.md +46 -0
- spatialflow/_generated/docs/WebhookListResponse.md +31 -0
- spatialflow/_generated/docs/WebhookMetricsResponse.md +31 -0
- spatialflow/_generated/docs/WebhookResponse.md +50 -0
- spatialflow/_generated/docs/WebhookTestResponse.md +36 -0
- spatialflow/_generated/docs/WebhooksApi.md +1384 -0
- spatialflow/_generated/docs/WorkflowImportSchema.md +30 -0
- spatialflow/_generated/docs/WorkflowIn.md +32 -0
- spatialflow/_generated/docs/WorkflowListOut.md +39 -0
- spatialflow/_generated/docs/WorkflowListResponse.md +32 -0
- spatialflow/_generated/docs/WorkflowOut.md +42 -0
- spatialflow/_generated/docs/WorkflowRetryPolicyUpdateSchema.md +32 -0
- spatialflow/_generated/docs/WorkflowStepRetrySchema.md +33 -0
- spatialflow/_generated/docs/WorkflowUpdate.md +33 -0
- spatialflow/_generated/docs/WorkflowsApi.md +2599 -0
- spatialflow/_generated/docs/WorkspaceDeleteResponse.md +33 -0
- spatialflow/_generated/docs/WorkspaceDetail.md +37 -0
- spatialflow/_generated/docs/WorkspaceDetailResponse.md +41 -0
- spatialflow/_generated/docs/WorkspaceIn.md +34 -0
- spatialflow/_generated/docs/WorkspaceListItem.md +39 -0
- spatialflow/_generated/docs/WorkspaceListResponse.md +34 -0
- spatialflow/_generated/docs/WorkspaceMembersResponse.md +35 -0
- spatialflow/_generated/docs/WorkspaceOut.md +38 -0
- spatialflow/_generated/docs/WorkspaceSummary.md +32 -0
- spatialflow/_generated/docs/WorkspaceUpdateRequest.md +34 -0
- spatialflow/_generated/docs/WorkspaceUpdateResponse.md +33 -0
- spatialflow/_generated/docs/WorkspacesApi.md +241 -0
- spatialflow/_generated/git_push.sh +57 -0
- spatialflow/_generated/pyproject.toml +91 -0
- spatialflow/_generated/requirements.txt +6 -0
- spatialflow/_generated/setup.cfg +2 -0
- spatialflow/_generated/setup.py +51 -0
- spatialflow/_generated/spatialflow_generated/__init__.py +216 -0
- spatialflow/_generated/spatialflow_generated/api/__init__.py +24 -0
- spatialflow/_generated/spatialflow_generated/api/account_api.py +5675 -0
- spatialflow/_generated/spatialflow_generated/api/admin_api.py +6173 -0
- spatialflow/_generated/spatialflow_generated/api/authentication_api.py +4753 -0
- spatialflow/_generated/spatialflow_generated/api/billing_api.py +3151 -0
- spatialflow/_generated/spatialflow_generated/api/default_api.py +2157 -0
- spatialflow/_generated/spatialflow_generated/api/devices_api.py +3965 -0
- spatialflow/_generated/spatialflow_generated/api/e2_e_test_api.py +1049 -0
- spatialflow/_generated/spatialflow_generated/api/email_api.py +1879 -0
- spatialflow/_generated/spatialflow_generated/api/geofences_api.py +4899 -0
- spatialflow/_generated/spatialflow_generated/api/gpx_simulator_api.py +2824 -0
- spatialflow/_generated/spatialflow_generated/api/integrations_api.py +6952 -0
- spatialflow/_generated/spatialflow_generated/api/public_api.py +1506 -0
- spatialflow/_generated/spatialflow_generated/api/public_location_ingest_api.py +845 -0
- spatialflow/_generated/spatialflow_generated/api/storage_api.py +1642 -0
- spatialflow/_generated/spatialflow_generated/api/subscriptions_api.py +2356 -0
- spatialflow/_generated/spatialflow_generated/api/system_api.py +529 -0
- spatialflow/_generated/spatialflow_generated/api/tiles_api.py +1626 -0
- spatialflow/_generated/spatialflow_generated/api/webhooks_api.py +4579 -0
- spatialflow/_generated/spatialflow_generated/api/workflows_api.py +8334 -0
- spatialflow/_generated/spatialflow_generated/api/workspaces_api.py +813 -0
- spatialflow/_generated/spatialflow_generated/api_client.py +800 -0
- spatialflow/_generated/spatialflow_generated/api_response.py +21 -0
- spatialflow/_generated/spatialflow_generated/configuration.py +599 -0
- spatialflow/_generated/spatialflow_generated/exceptions.py +199 -0
- spatialflow/_generated/spatialflow_generated/models/__init__.py +180 -0
- spatialflow/_generated/spatialflow_generated/models/action_delivery_success_metrics.py +96 -0
- spatialflow/_generated/spatialflow_generated/models/action_response.py +96 -0
- spatialflow/_generated/spatialflow_generated/models/action_retry_config_schema.py +114 -0
- spatialflow/_generated/spatialflow_generated/models/activity_summary.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/api_key_create_request.py +95 -0
- spatialflow/_generated/spatialflow_generated/models/api_key_create_response.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/api_key_response.py +109 -0
- spatialflow/_generated/spatialflow_generated/models/api_key_update_request.py +114 -0
- spatialflow/_generated/spatialflow_generated/models/api_usage_stats.py +98 -0
- spatialflow/_generated/spatialflow_generated/models/async_upload_geofences_response.py +93 -0
- spatialflow/_generated/spatialflow_generated/models/auth_type_enum.py +39 -0
- spatialflow/_generated/spatialflow_generated/models/batch_location_update_in.py +97 -0
- spatialflow/_generated/spatialflow_generated/models/bulk_geofence_request.py +95 -0
- spatialflow/_generated/spatialflow_generated/models/change_password_schema.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/checkout_session_request.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/checkout_session_response.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/circuit_breaker_schema.py +94 -0
- spatialflow/_generated/spatialflow_generated/models/config_field_definition_request.py +134 -0
- spatialflow/_generated/spatialflow_generated/models/config_field_definition_response.py +138 -0
- spatialflow/_generated/spatialflow_generated/models/confirm_password_reset_schema.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/create_from_template_in.py +94 -0
- spatialflow/_generated/spatialflow_generated/models/create_geofence_request.py +125 -0
- spatialflow/_generated/spatialflow_generated/models/create_integration_schema.py +106 -0
- spatialflow/_generated/spatialflow_generated/models/create_user_schema.py +99 -0
- spatialflow/_generated/spatialflow_generated/models/create_webhook_request.py +136 -0
- spatialflow/_generated/spatialflow_generated/models/dashboard_comparison_metrics.py +96 -0
- spatialflow/_generated/spatialflow_generated/models/dashboard_metrics_response.py +108 -0
- spatialflow/_generated/spatialflow_generated/models/delete_file_response.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/delivery_status_enum.py +38 -0
- spatialflow/_generated/spatialflow_generated/models/device_in.py +98 -0
- spatialflow/_generated/spatialflow_generated/models/device_out.py +114 -0
- spatialflow/_generated/spatialflow_generated/models/email_health_response.py +92 -0
- spatialflow/_generated/spatialflow_generated/models/email_queue_stats.py +97 -0
- spatialflow/_generated/spatialflow_generated/models/email_stats.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/email_status_response.py +112 -0
- spatialflow/_generated/spatialflow_generated/models/error_response.py +101 -0
- spatialflow/_generated/spatialflow_generated/models/execution_out.py +126 -0
- spatialflow/_generated/spatialflow_generated/models/export_integration_schema.py +97 -0
- spatialflow/_generated/spatialflow_generated/models/file_list_response.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/forgot_password_schema.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/geo_json_point.py +97 -0
- spatialflow/_generated/spatialflow_generated/models/geofence_list_response.py +97 -0
- spatialflow/_generated/spatialflow_generated/models/geofence_response.py +139 -0
- spatialflow/_generated/spatialflow_generated/models/geofence_stats.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/geofence_test_result.py +98 -0
- spatialflow/_generated/spatialflow_generated/models/gpx_playback_out.py +128 -0
- spatialflow/_generated/spatialflow_generated/models/gpx_route_out.py +119 -0
- spatialflow/_generated/spatialflow_generated/models/health_check_response.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/health_response.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/import_integration_schema.py +100 -0
- spatialflow/_generated/spatialflow_generated/models/import_result_schema.py +103 -0
- spatialflow/_generated/spatialflow_generated/models/integration_detail_schema.py +125 -0
- spatialflow/_generated/spatialflow_generated/models/integration_response_schema.py +123 -0
- spatialflow/_generated/spatialflow_generated/models/integration_stats_schema.py +116 -0
- spatialflow/_generated/spatialflow_generated/models/integration_type_list_response.py +103 -0
- spatialflow/_generated/spatialflow_generated/models/integration_type_request.py +117 -0
- spatialflow/_generated/spatialflow_generated/models/integration_type_response.py +128 -0
- spatialflow/_generated/spatialflow_generated/models/invoice_line_item.py +93 -0
- spatialflow/_generated/spatialflow_generated/models/invoice_list_response.py +97 -0
- spatialflow/_generated/spatialflow_generated/models/invoice_response.py +120 -0
- spatialflow/_generated/spatialflow_generated/models/location_batch_in.py +102 -0
- spatialflow/_generated/spatialflow_generated/models/location_import_response.py +120 -0
- spatialflow/_generated/spatialflow_generated/models/location_ingest_response.py +117 -0
- spatialflow/_generated/spatialflow_generated/models/location_point_in.py +129 -0
- spatialflow/_generated/spatialflow_generated/models/location_update_in.py +132 -0
- spatialflow/_generated/spatialflow_generated/models/location_update_out.py +93 -0
- spatialflow/_generated/spatialflow_generated/models/login_response.py +95 -0
- spatialflow/_generated/spatialflow_generated/models/login_schema.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/member_action_response.py +98 -0
- spatialflow/_generated/spatialflow_generated/models/member_summary.py +114 -0
- spatialflow/_generated/spatialflow_generated/models/method_enum.py +39 -0
- spatialflow/_generated/spatialflow_generated/models/o_auth_authorize_response.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/o_auth_callback_query.py +103 -0
- spatialflow/_generated/spatialflow_generated/models/o_auth_link_response.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/o_auth_providers_response.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/onboarding_progress_response.py +112 -0
- spatialflow/_generated/spatialflow_generated/models/payment_method_response.py +116 -0
- spatialflow/_generated/spatialflow_generated/models/ping_response.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/plan_change_preview_response.py +104 -0
- spatialflow/_generated/spatialflow_generated/models/plan_features.py +109 -0
- spatialflow/_generated/spatialflow_generated/models/plan_limits.py +95 -0
- spatialflow/_generated/spatialflow_generated/models/plan_response.py +114 -0
- spatialflow/_generated/spatialflow_generated/models/portal_session_request.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/portal_session_response.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/presigned_url_request.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/presigned_url_response.py +99 -0
- spatialflow/_generated/spatialflow_generated/models/privacy_erasure_request.py +118 -0
- spatialflow/_generated/spatialflow_generated/models/privacy_erasure_response.py +110 -0
- spatialflow/_generated/spatialflow_generated/models/rate_limit_response.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/recent_activity.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/refresh_token_schema.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/register_schema.py +133 -0
- spatialflow/_generated/spatialflow_generated/models/resend_verification_schema.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/reset_password_schema.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/retry_policy_response_schema.py +95 -0
- spatialflow/_generated/spatialflow_generated/models/retry_policy_schema.py +99 -0
- spatialflow/_generated/spatialflow_generated/models/retry_strategy_enum.py +38 -0
- spatialflow/_generated/spatialflow_generated/models/seed_data_response_schema.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/send_email_request.py +100 -0
- spatialflow/_generated/spatialflow_generated/models/setup_intent_response.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/signup_request.py +164 -0
- spatialflow/_generated/spatialflow_generated/models/start_playback_request.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/subscription_action_response.py +100 -0
- spatialflow/_generated/spatialflow_generated/models/subscription_response.py +113 -0
- spatialflow/_generated/spatialflow_generated/models/success_response.py +94 -0
- spatialflow/_generated/spatialflow_generated/models/template_out.py +104 -0
- spatialflow/_generated/spatialflow_generated/models/test_event_request.py +92 -0
- spatialflow/_generated/spatialflow_generated/models/test_integration_response_schema.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/test_point_request.py +125 -0
- spatialflow/_generated/spatialflow_generated/models/test_point_response.py +101 -0
- spatialflow/_generated/spatialflow_generated/models/test_webhook_request.py +106 -0
- spatialflow/_generated/spatialflow_generated/models/test_workflow_in.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/tile_metadata.py +99 -0
- spatialflow/_generated/spatialflow_generated/models/unsubscribe_request.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/unsubscribe_response.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/update_geofence_request.py +142 -0
- spatialflow/_generated/spatialflow_generated/models/update_integration_schema.py +121 -0
- spatialflow/_generated/spatialflow_generated/models/update_member_role_request.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/update_onboarding_progress_request.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/update_profile_request.py +208 -0
- spatialflow/_generated/spatialflow_generated/models/update_user_workspace_request.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/update_webhook_request.py +186 -0
- spatialflow/_generated/spatialflow_generated/models/upload_geofences_request.py +95 -0
- spatialflow/_generated/spatialflow_generated/models/upload_job_status.py +137 -0
- spatialflow/_generated/spatialflow_generated/models/usage_metrics.py +93 -0
- spatialflow/_generated/spatialflow_generated/models/usage_response.py +105 -0
- spatialflow/_generated/spatialflow_generated/models/usage_stats.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/user_action_response.py +119 -0
- spatialflow/_generated/spatialflow_generated/models/user_approval_request.py +92 -0
- spatialflow/_generated/spatialflow_generated/models/user_invite_request.py +110 -0
- spatialflow/_generated/spatialflow_generated/models/user_invite_response.py +99 -0
- spatialflow/_generated/spatialflow_generated/models/user_list_response.py +110 -0
- spatialflow/_generated/spatialflow_generated/models/user_profile_response.py +158 -0
- spatialflow/_generated/spatialflow_generated/models/user_rejection_request.py +87 -0
- spatialflow/_generated/spatialflow_generated/models/user_response.py +142 -0
- spatialflow/_generated/spatialflow_generated/models/user_summary.py +140 -0
- spatialflow/_generated/spatialflow_generated/models/user_usage_response.py +152 -0
- spatialflow/_generated/spatialflow_generated/models/user_workspace_response.py +110 -0
- spatialflow/_generated/spatialflow_generated/models/webhook_delivery_detail_response.py +182 -0
- spatialflow/_generated/spatialflow_generated/models/webhook_delivery_list_response.py +97 -0
- spatialflow/_generated/spatialflow_generated/models/webhook_delivery_response.py +161 -0
- spatialflow/_generated/spatialflow_generated/models/webhook_list_response.py +97 -0
- spatialflow/_generated/spatialflow_generated/models/webhook_metrics_response.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/webhook_response.py +148 -0
- spatialflow/_generated/spatialflow_generated/models/webhook_test_response.py +114 -0
- spatialflow/_generated/spatialflow_generated/models/workflow_import_schema.py +89 -0
- spatialflow/_generated/spatialflow_generated/models/workflow_in.py +98 -0
- spatialflow/_generated/spatialflow_generated/models/workflow_list_out.py +118 -0
- spatialflow/_generated/spatialflow_generated/models/workflow_list_response.py +101 -0
- spatialflow/_generated/spatialflow_generated/models/workflow_out.py +129 -0
- spatialflow/_generated/spatialflow_generated/models/workflow_retry_policy_update_schema.py +109 -0
- spatialflow/_generated/spatialflow_generated/models/workflow_step_retry_schema.py +103 -0
- spatialflow/_generated/spatialflow_generated/models/workflow_update.py +120 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_delete_response.py +93 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_detail.py +116 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_detail_response.py +143 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_in.py +122 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_list_item.py +130 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_list_response.py +103 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_members_response.py +109 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_out.py +132 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_summary.py +91 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_update_request.py +120 -0
- spatialflow/_generated/spatialflow_generated/models/workspace_update_response.py +93 -0
- spatialflow/_generated/spatialflow_generated/py.typed +0 -0
- spatialflow/_generated/spatialflow_generated/rest.py +215 -0
- spatialflow/_generated/test-requirements.txt +6 -0
- spatialflow/_generated/tox.ini +9 -0
- spatialflow/client.py +137 -0
- spatialflow/exceptions.py +234 -0
- spatialflow/jobs.py +204 -0
- spatialflow/pagination.py +142 -0
- spatialflow/uploads.py +166 -0
- spatialflow/webhooks.py +126 -0
- spatialflow-0.1.0.dist-info/METADATA +249 -0
- spatialflow-0.1.0.dist-info/RECORD +404 -0
- spatialflow-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
# coding: utf-8
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
SpatialFlow API
|
|
5
|
+
|
|
6
|
+
Real-time geospatial automation platform API. ## Authentication **API Key:** Include `X-API-Key` header **JWT Token:** Include `Authorization: Bearer <token>` header ## Rate Limits - Per API Key: 200 rps sustained, 1,000 rps burst - Per Organization: 1,000 rps aggregate ## Webhook Verification Outbound webhooks include HMAC-SHA256 signatures in `X-SF-Signature` header. ## Support - Documentation: https://docs.spatialflow.io - GitHub: https://github.com/spatialflow/spatialflow - Email: support@spatialflow.io
|
|
7
|
+
|
|
8
|
+
The version of the OpenAPI document: 1.0.0
|
|
9
|
+
Generated by OpenAPI Generator (https://openapi-generator.tech)
|
|
10
|
+
|
|
11
|
+
Do not edit the class manually.
|
|
12
|
+
""" # noqa: E501
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
import io
|
|
16
|
+
import json
|
|
17
|
+
import re
|
|
18
|
+
import ssl
|
|
19
|
+
from typing import Optional, Union
|
|
20
|
+
|
|
21
|
+
import aiohttp
|
|
22
|
+
import aiohttp_retry
|
|
23
|
+
|
|
24
|
+
from .exceptions import ApiException, ApiValueError
|
|
25
|
+
|
|
26
|
+
RESTResponseType = aiohttp.ClientResponse
|
|
27
|
+
|
|
28
|
+
ALLOW_RETRY_METHODS = frozenset({'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PUT', 'TRACE'})
|
|
29
|
+
|
|
30
|
+
class RESTResponse(io.IOBase):
|
|
31
|
+
|
|
32
|
+
def __init__(self, resp) -> None:
|
|
33
|
+
self.response = resp
|
|
34
|
+
self.status = resp.status
|
|
35
|
+
self.reason = resp.reason
|
|
36
|
+
self.data = None
|
|
37
|
+
|
|
38
|
+
async def read(self):
|
|
39
|
+
if self.data is None:
|
|
40
|
+
self.data = await self.response.read()
|
|
41
|
+
return self.data
|
|
42
|
+
|
|
43
|
+
def getheaders(self):
|
|
44
|
+
"""Returns a CIMultiDictProxy of the response headers."""
|
|
45
|
+
return self.response.headers
|
|
46
|
+
|
|
47
|
+
def getheader(self, name, default=None):
|
|
48
|
+
"""Returns a given response header."""
|
|
49
|
+
return self.response.headers.get(name, default)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class RESTClientObject:
|
|
53
|
+
|
|
54
|
+
def __init__(self, configuration) -> None:
|
|
55
|
+
|
|
56
|
+
# maxsize is number of requests to host that are allowed in parallel
|
|
57
|
+
maxsize = configuration.connection_pool_maxsize
|
|
58
|
+
|
|
59
|
+
ssl_context = ssl.create_default_context(
|
|
60
|
+
cafile=configuration.ssl_ca_cert
|
|
61
|
+
)
|
|
62
|
+
if configuration.cert_file:
|
|
63
|
+
ssl_context.load_cert_chain(
|
|
64
|
+
configuration.cert_file, keyfile=configuration.key_file
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
if not configuration.verify_ssl:
|
|
68
|
+
ssl_context.check_hostname = False
|
|
69
|
+
ssl_context.verify_mode = ssl.CERT_NONE
|
|
70
|
+
|
|
71
|
+
connector = aiohttp.TCPConnector(
|
|
72
|
+
limit=maxsize,
|
|
73
|
+
ssl=ssl_context
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
self.proxy = configuration.proxy
|
|
77
|
+
self.proxy_headers = configuration.proxy_headers
|
|
78
|
+
|
|
79
|
+
# https pool manager
|
|
80
|
+
self.pool_manager = aiohttp.ClientSession(
|
|
81
|
+
connector=connector,
|
|
82
|
+
trust_env=True
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
retries = configuration.retries
|
|
86
|
+
self.retry_client: Optional[aiohttp_retry.RetryClient]
|
|
87
|
+
if retries is not None:
|
|
88
|
+
self.retry_client = aiohttp_retry.RetryClient(
|
|
89
|
+
client_session=self.pool_manager,
|
|
90
|
+
retry_options=aiohttp_retry.ExponentialRetry(
|
|
91
|
+
attempts=retries,
|
|
92
|
+
factor=2.0,
|
|
93
|
+
start_timeout=0.1,
|
|
94
|
+
max_timeout=120.0
|
|
95
|
+
)
|
|
96
|
+
)
|
|
97
|
+
else:
|
|
98
|
+
self.retry_client = None
|
|
99
|
+
|
|
100
|
+
async def close(self):
|
|
101
|
+
await self.pool_manager.close()
|
|
102
|
+
if self.retry_client is not None:
|
|
103
|
+
await self.retry_client.close()
|
|
104
|
+
|
|
105
|
+
async def request(
|
|
106
|
+
self,
|
|
107
|
+
method,
|
|
108
|
+
url,
|
|
109
|
+
headers=None,
|
|
110
|
+
body=None,
|
|
111
|
+
post_params=None,
|
|
112
|
+
_request_timeout=None
|
|
113
|
+
):
|
|
114
|
+
"""Execute request
|
|
115
|
+
|
|
116
|
+
:param method: http request method
|
|
117
|
+
:param url: http request url
|
|
118
|
+
:param headers: http request headers
|
|
119
|
+
:param body: request json body, for `application/json`
|
|
120
|
+
:param post_params: request post parameters,
|
|
121
|
+
`application/x-www-form-urlencoded`
|
|
122
|
+
and `multipart/form-data`
|
|
123
|
+
:param _request_timeout: timeout setting for this request. If one
|
|
124
|
+
number provided, it will be total request
|
|
125
|
+
timeout. It can also be a pair (tuple) of
|
|
126
|
+
(connection, read) timeouts.
|
|
127
|
+
"""
|
|
128
|
+
method = method.upper()
|
|
129
|
+
assert method in [
|
|
130
|
+
'GET',
|
|
131
|
+
'HEAD',
|
|
132
|
+
'DELETE',
|
|
133
|
+
'POST',
|
|
134
|
+
'PUT',
|
|
135
|
+
'PATCH',
|
|
136
|
+
'OPTIONS'
|
|
137
|
+
]
|
|
138
|
+
|
|
139
|
+
if post_params and body:
|
|
140
|
+
raise ApiValueError(
|
|
141
|
+
"body parameter cannot be used with post_params parameter."
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
post_params = post_params or {}
|
|
145
|
+
headers = headers or {}
|
|
146
|
+
# url already contains the URL query string
|
|
147
|
+
timeout = _request_timeout or 5 * 60
|
|
148
|
+
|
|
149
|
+
if 'Content-Type' not in headers:
|
|
150
|
+
headers['Content-Type'] = 'application/json'
|
|
151
|
+
|
|
152
|
+
args = {
|
|
153
|
+
"method": method,
|
|
154
|
+
"url": url,
|
|
155
|
+
"timeout": timeout,
|
|
156
|
+
"headers": headers
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
if self.proxy:
|
|
160
|
+
args["proxy"] = self.proxy
|
|
161
|
+
if self.proxy_headers:
|
|
162
|
+
args["proxy_headers"] = self.proxy_headers
|
|
163
|
+
|
|
164
|
+
# For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE`
|
|
165
|
+
if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']:
|
|
166
|
+
if re.search('json', headers['Content-Type'], re.IGNORECASE):
|
|
167
|
+
if body is not None:
|
|
168
|
+
body = json.dumps(body)
|
|
169
|
+
args["data"] = body
|
|
170
|
+
elif headers['Content-Type'] == 'application/x-www-form-urlencoded':
|
|
171
|
+
args["data"] = aiohttp.FormData(post_params)
|
|
172
|
+
elif headers['Content-Type'] == 'multipart/form-data':
|
|
173
|
+
# must del headers['Content-Type'], or the correct
|
|
174
|
+
# Content-Type which generated by aiohttp
|
|
175
|
+
del headers['Content-Type']
|
|
176
|
+
data = aiohttp.FormData()
|
|
177
|
+
for param in post_params:
|
|
178
|
+
k, v = param
|
|
179
|
+
if isinstance(v, tuple) and len(v) == 3:
|
|
180
|
+
data.add_field(
|
|
181
|
+
k,
|
|
182
|
+
value=v[1],
|
|
183
|
+
filename=v[0],
|
|
184
|
+
content_type=v[2]
|
|
185
|
+
)
|
|
186
|
+
else:
|
|
187
|
+
# Ensures that dict objects are serialized
|
|
188
|
+
if isinstance(v, dict):
|
|
189
|
+
v = json.dumps(v)
|
|
190
|
+
elif isinstance(v, int):
|
|
191
|
+
v = str(v)
|
|
192
|
+
data.add_field(k, v)
|
|
193
|
+
args["data"] = data
|
|
194
|
+
|
|
195
|
+
# Pass a `bytes` or `str` parameter directly in the body to support
|
|
196
|
+
# other content types than Json when `body` argument is provided
|
|
197
|
+
# in serialized form
|
|
198
|
+
elif isinstance(body, str) or isinstance(body, bytes):
|
|
199
|
+
args["data"] = body
|
|
200
|
+
else:
|
|
201
|
+
# Cannot generate the request from given parameters
|
|
202
|
+
msg = """Cannot prepare a request message for provided
|
|
203
|
+
arguments. Please check that your arguments match
|
|
204
|
+
declared content type."""
|
|
205
|
+
raise ApiException(status=0, reason=msg)
|
|
206
|
+
|
|
207
|
+
pool_manager: Union[aiohttp.ClientSession, aiohttp_retry.RetryClient]
|
|
208
|
+
if self.retry_client is not None and method in ALLOW_RETRY_METHODS:
|
|
209
|
+
pool_manager = self.retry_client
|
|
210
|
+
else:
|
|
211
|
+
pool_manager = self.pool_manager
|
|
212
|
+
|
|
213
|
+
r = await pool_manager.request(**args)
|
|
214
|
+
|
|
215
|
+
return RESTResponse(r)
|
spatialflow/client.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SpatialFlow Python SDK Client
|
|
3
|
+
|
|
4
|
+
The main entry point for the SpatialFlow API.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
# Import from the generated package using relative imports
|
|
10
|
+
# The generated code now uses relative imports internally
|
|
11
|
+
from ._generated.spatialflow_generated.api_client import ApiClient
|
|
12
|
+
from ._generated.spatialflow_generated.configuration import Configuration
|
|
13
|
+
from ._generated.spatialflow_generated.api.geofences_api import GeofencesApi
|
|
14
|
+
from ._generated.spatialflow_generated.api.workflows_api import WorkflowsApi
|
|
15
|
+
from ._generated.spatialflow_generated.api.webhooks_api import WebhooksApi
|
|
16
|
+
from ._generated.spatialflow_generated.api.devices_api import DevicesApi
|
|
17
|
+
from ._generated.spatialflow_generated.api.account_api import AccountApi
|
|
18
|
+
|
|
19
|
+
__all__ = ["SpatialFlow"]
|
|
20
|
+
|
|
21
|
+
# Host only - generated paths include /api/v1 prefix
|
|
22
|
+
DEFAULT_BASE_URL = "https://api.spatialflow.io"
|
|
23
|
+
DEFAULT_TIMEOUT = 30 # seconds
|
|
24
|
+
DEFAULT_MAX_RETRIES = 3
|
|
25
|
+
VERSION = "0.1.0"
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class SpatialFlow:
|
|
29
|
+
"""
|
|
30
|
+
SpatialFlow API client.
|
|
31
|
+
|
|
32
|
+
Provides access to geofences, workflows, webhooks, and devices.
|
|
33
|
+
|
|
34
|
+
Example:
|
|
35
|
+
>>> client = SpatialFlow(api_key="sf_xxx")
|
|
36
|
+
>>> geofences = await client.geofences.apps_geofences_api_list_geofences()
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
api_key: SpatialFlow API key (starts with "sf_")
|
|
40
|
+
access_token: JWT access token (alternative to api_key)
|
|
41
|
+
base_url: API base URL (default: https://api.spatialflow.io)
|
|
42
|
+
timeout: Request timeout in seconds (default: 30)
|
|
43
|
+
max_retries: Maximum retry attempts for failed requests (default: 3)
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
*,
|
|
49
|
+
api_key: Optional[str] = None,
|
|
50
|
+
access_token: Optional[str] = None,
|
|
51
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
52
|
+
timeout: int = DEFAULT_TIMEOUT,
|
|
53
|
+
max_retries: int = DEFAULT_MAX_RETRIES,
|
|
54
|
+
) -> None:
|
|
55
|
+
if not api_key and not access_token:
|
|
56
|
+
raise ValueError("Either api_key or access_token must be provided")
|
|
57
|
+
|
|
58
|
+
if api_key and access_token:
|
|
59
|
+
raise ValueError("Provide either api_key or access_token, not both")
|
|
60
|
+
|
|
61
|
+
# Build configuration
|
|
62
|
+
config = Configuration(host=base_url)
|
|
63
|
+
|
|
64
|
+
# Configure authentication
|
|
65
|
+
if api_key:
|
|
66
|
+
config.api_key = {"APIKeyBearer": api_key}
|
|
67
|
+
elif access_token:
|
|
68
|
+
config.access_token = access_token
|
|
69
|
+
|
|
70
|
+
# Configure timeouts and retries
|
|
71
|
+
config.retries = max_retries
|
|
72
|
+
|
|
73
|
+
# Create API client
|
|
74
|
+
self._api_client = ApiClient(configuration=config)
|
|
75
|
+
|
|
76
|
+
# Set User-Agent
|
|
77
|
+
self._api_client.user_agent = f"spatialflow-python/{VERSION}"
|
|
78
|
+
|
|
79
|
+
# Store config for reference
|
|
80
|
+
self._base_url = base_url
|
|
81
|
+
self._timeout = timeout
|
|
82
|
+
self._max_retries = max_retries
|
|
83
|
+
|
|
84
|
+
# Initialize resource APIs (lazy initialization)
|
|
85
|
+
self._geofences: Optional[GeofencesApi] = None
|
|
86
|
+
self._workflows: Optional[WorkflowsApi] = None
|
|
87
|
+
self._webhooks: Optional[WebhooksApi] = None
|
|
88
|
+
self._devices: Optional[DevicesApi] = None
|
|
89
|
+
self._account: Optional[AccountApi] = None
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
def geofences(self) -> GeofencesApi:
|
|
93
|
+
"""Access geofence operations."""
|
|
94
|
+
if self._geofences is None:
|
|
95
|
+
self._geofences = GeofencesApi(self._api_client)
|
|
96
|
+
return self._geofences
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def workflows(self) -> WorkflowsApi:
|
|
100
|
+
"""Access workflow operations."""
|
|
101
|
+
if self._workflows is None:
|
|
102
|
+
self._workflows = WorkflowsApi(self._api_client)
|
|
103
|
+
return self._workflows
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def webhooks(self) -> WebhooksApi:
|
|
107
|
+
"""Access webhook operations."""
|
|
108
|
+
if self._webhooks is None:
|
|
109
|
+
self._webhooks = WebhooksApi(self._api_client)
|
|
110
|
+
return self._webhooks
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def devices(self) -> DevicesApi:
|
|
114
|
+
"""Access device operations."""
|
|
115
|
+
if self._devices is None:
|
|
116
|
+
self._devices = DevicesApi(self._api_client)
|
|
117
|
+
return self._devices
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def account(self) -> AccountApi:
|
|
121
|
+
"""Access account operations."""
|
|
122
|
+
if self._account is None:
|
|
123
|
+
self._account = AccountApi(self._api_client)
|
|
124
|
+
return self._account
|
|
125
|
+
|
|
126
|
+
async def close(self) -> None:
|
|
127
|
+
"""Close the API client and release resources."""
|
|
128
|
+
if self._api_client:
|
|
129
|
+
await self._api_client.close()
|
|
130
|
+
|
|
131
|
+
async def __aenter__(self) -> "SpatialFlow":
|
|
132
|
+
"""Async context manager entry."""
|
|
133
|
+
return self
|
|
134
|
+
|
|
135
|
+
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
|
|
136
|
+
"""Async context manager exit."""
|
|
137
|
+
await self.close()
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SpatialFlow SDK Exceptions
|
|
3
|
+
|
|
4
|
+
Provides a clean exception hierarchy for handling API errors.
|
|
5
|
+
These wrap the generated exceptions with more user-friendly interfaces.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Any, Optional
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SpatialFlowError(Exception):
|
|
12
|
+
"""Base exception for all SpatialFlow SDK errors."""
|
|
13
|
+
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
message: str,
|
|
17
|
+
*,
|
|
18
|
+
status_code: Optional[int] = None,
|
|
19
|
+
detail: Optional[str] = None,
|
|
20
|
+
error_code: Optional[str] = None,
|
|
21
|
+
headers: Optional[dict[str, str]] = None,
|
|
22
|
+
) -> None:
|
|
23
|
+
super().__init__(message)
|
|
24
|
+
self.message = message
|
|
25
|
+
self.status_code = status_code
|
|
26
|
+
self.detail = detail
|
|
27
|
+
self.error_code = error_code
|
|
28
|
+
self.headers = headers or {}
|
|
29
|
+
|
|
30
|
+
def __str__(self) -> str:
|
|
31
|
+
parts = [self.message]
|
|
32
|
+
if self.status_code:
|
|
33
|
+
parts.insert(0, f"[{self.status_code}]")
|
|
34
|
+
if self.detail and self.detail != self.message:
|
|
35
|
+
parts.append(f"- {self.detail}")
|
|
36
|
+
return " ".join(parts)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class AuthenticationError(SpatialFlowError):
|
|
40
|
+
"""
|
|
41
|
+
Raised when authentication fails (401 Unauthorized).
|
|
42
|
+
|
|
43
|
+
This typically means:
|
|
44
|
+
- API key is invalid or expired
|
|
45
|
+
- JWT token is invalid or expired
|
|
46
|
+
- No authentication credentials provided
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
pass
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class PermissionError(SpatialFlowError):
|
|
53
|
+
"""
|
|
54
|
+
Raised when the authenticated user lacks permission (403 Forbidden).
|
|
55
|
+
|
|
56
|
+
This typically means:
|
|
57
|
+
- User doesn't have access to this resource
|
|
58
|
+
- API key doesn't have the required scope
|
|
59
|
+
- Organization limits exceeded
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
pass
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class NotFoundError(SpatialFlowError):
|
|
66
|
+
"""
|
|
67
|
+
Raised when a resource is not found (404 Not Found).
|
|
68
|
+
|
|
69
|
+
Check that:
|
|
70
|
+
- The resource ID is correct
|
|
71
|
+
- The resource hasn't been deleted
|
|
72
|
+
- You have access to the resource
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class ValidationError(SpatialFlowError):
|
|
79
|
+
"""
|
|
80
|
+
Raised when request validation fails (400 Bad Request or 422 Unprocessable Entity).
|
|
81
|
+
|
|
82
|
+
Check that:
|
|
83
|
+
- Required fields are provided
|
|
84
|
+
- Field values match expected types/formats
|
|
85
|
+
- Geometry is valid GeoJSON
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
def __init__(
|
|
89
|
+
self,
|
|
90
|
+
message: str,
|
|
91
|
+
*,
|
|
92
|
+
status_code: Optional[int] = None,
|
|
93
|
+
detail: Optional[str] = None,
|
|
94
|
+
error_code: Optional[str] = None,
|
|
95
|
+
headers: Optional[dict[str, str]] = None,
|
|
96
|
+
errors: Optional[list[dict[str, Any]]] = None,
|
|
97
|
+
) -> None:
|
|
98
|
+
super().__init__(
|
|
99
|
+
message,
|
|
100
|
+
status_code=status_code,
|
|
101
|
+
detail=detail,
|
|
102
|
+
error_code=error_code,
|
|
103
|
+
headers=headers,
|
|
104
|
+
)
|
|
105
|
+
self.errors = errors or []
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class RateLimitError(SpatialFlowError):
|
|
109
|
+
"""
|
|
110
|
+
Raised when rate limit is exceeded (429 Too Many Requests).
|
|
111
|
+
|
|
112
|
+
The `retry_after` property indicates when you can retry.
|
|
113
|
+
"""
|
|
114
|
+
|
|
115
|
+
def __init__(
|
|
116
|
+
self,
|
|
117
|
+
message: str,
|
|
118
|
+
*,
|
|
119
|
+
status_code: int = 429,
|
|
120
|
+
detail: Optional[str] = None,
|
|
121
|
+
error_code: Optional[str] = None,
|
|
122
|
+
headers: Optional[dict[str, str]] = None,
|
|
123
|
+
retry_after: Optional[int] = None,
|
|
124
|
+
) -> None:
|
|
125
|
+
super().__init__(
|
|
126
|
+
message,
|
|
127
|
+
status_code=status_code,
|
|
128
|
+
detail=detail,
|
|
129
|
+
error_code=error_code,
|
|
130
|
+
headers=headers,
|
|
131
|
+
)
|
|
132
|
+
self.retry_after = retry_after or self._parse_retry_after(headers)
|
|
133
|
+
|
|
134
|
+
def _parse_retry_after(self, headers: Optional[dict[str, str]]) -> Optional[int]:
|
|
135
|
+
if not headers:
|
|
136
|
+
return None
|
|
137
|
+
retry_after = headers.get("Retry-After") or headers.get("retry-after")
|
|
138
|
+
if retry_after:
|
|
139
|
+
try:
|
|
140
|
+
return int(retry_after)
|
|
141
|
+
except ValueError:
|
|
142
|
+
pass
|
|
143
|
+
return None
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class ServerError(SpatialFlowError):
|
|
147
|
+
"""
|
|
148
|
+
Raised when the server encounters an error (5xx status codes).
|
|
149
|
+
|
|
150
|
+
This is typically a temporary issue. Retry with exponential backoff.
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
pass
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class ConflictError(SpatialFlowError):
|
|
157
|
+
"""
|
|
158
|
+
Raised when there's a resource conflict (409 Conflict).
|
|
159
|
+
|
|
160
|
+
This typically means:
|
|
161
|
+
- Resource already exists with that name/identifier
|
|
162
|
+
- Concurrent modification conflict
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
pass
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
class TimeoutError(SpatialFlowError):
|
|
169
|
+
"""Raised when a request times out."""
|
|
170
|
+
|
|
171
|
+
pass
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class ConnectionError(SpatialFlowError):
|
|
175
|
+
"""Raised when unable to connect to the API."""
|
|
176
|
+
|
|
177
|
+
pass
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
def raise_for_status(
|
|
181
|
+
status_code: int,
|
|
182
|
+
message: str = "API request failed",
|
|
183
|
+
*,
|
|
184
|
+
detail: Optional[str] = None,
|
|
185
|
+
error_code: Optional[str] = None,
|
|
186
|
+
headers: Optional[dict[str, str]] = None,
|
|
187
|
+
body: Optional[Any] = None,
|
|
188
|
+
) -> None:
|
|
189
|
+
"""
|
|
190
|
+
Raise the appropriate exception based on HTTP status code.
|
|
191
|
+
|
|
192
|
+
Args:
|
|
193
|
+
status_code: HTTP status code
|
|
194
|
+
message: Error message
|
|
195
|
+
detail: Additional error detail
|
|
196
|
+
error_code: Machine-readable error code
|
|
197
|
+
headers: Response headers
|
|
198
|
+
body: Response body (for extracting validation errors)
|
|
199
|
+
"""
|
|
200
|
+
# Extract detail from body if not provided
|
|
201
|
+
if body and not detail:
|
|
202
|
+
if isinstance(body, dict):
|
|
203
|
+
detail = body.get("detail")
|
|
204
|
+
if isinstance(detail, list):
|
|
205
|
+
# Django Ninja validation error format
|
|
206
|
+
detail = "; ".join(str(e) for e in detail)
|
|
207
|
+
error_code = error_code or body.get("error_code")
|
|
208
|
+
|
|
209
|
+
kwargs = {
|
|
210
|
+
"status_code": status_code,
|
|
211
|
+
"detail": detail,
|
|
212
|
+
"error_code": error_code,
|
|
213
|
+
"headers": headers,
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
if status_code == 400 or status_code == 422:
|
|
217
|
+
errors = []
|
|
218
|
+
if isinstance(body, dict) and isinstance(body.get("detail"), list):
|
|
219
|
+
errors = body["detail"]
|
|
220
|
+
raise ValidationError(message, errors=errors, **kwargs)
|
|
221
|
+
elif status_code == 401:
|
|
222
|
+
raise AuthenticationError(message, **kwargs)
|
|
223
|
+
elif status_code == 403:
|
|
224
|
+
raise PermissionError(message, **kwargs)
|
|
225
|
+
elif status_code == 404:
|
|
226
|
+
raise NotFoundError(message, **kwargs)
|
|
227
|
+
elif status_code == 409:
|
|
228
|
+
raise ConflictError(message, **kwargs)
|
|
229
|
+
elif status_code == 429:
|
|
230
|
+
raise RateLimitError(message, **kwargs)
|
|
231
|
+
elif 500 <= status_code < 600:
|
|
232
|
+
raise ServerError(message, **kwargs)
|
|
233
|
+
elif status_code >= 400:
|
|
234
|
+
raise SpatialFlowError(message, **kwargs)
|