uipath 2.0.75__tar.gz → 2.0.77__tar.gz
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.
Potentially problematic release.
This version of uipath might be problematic. Click here for more details.
- {uipath-2.0.75 → uipath-2.0.77}/PKG-INFO +1 -1
- uipath-2.0.77/docs/index.md +34 -0
- {uipath-2.0.75 → uipath-2.0.77}/pyproject.toml +1 -1
- uipath-2.0.77/src/uipath/_cli/_utils/_constants.py +58 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/cli_pack.py +168 -56
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/test_pack.py +147 -0
- uipath-2.0.77/uv.lock +3528 -0
- uipath-2.0.75/docs/index.md +0 -22
- uipath-2.0.75/src/uipath/_cli/_utils/_constants.py +0 -1
- uipath-2.0.75/uv.lock +0 -3765
- {uipath-2.0.75 → uipath-2.0.77}/.cursorrules +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.editorconfig +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.gitattributes +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.github/workflows/cd.yml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.github/workflows/ci.yml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.github/workflows/commitlint.yml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.github/workflows/lint.yml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.github/workflows/publish-dev.yml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.github/workflows/publish-docs.yml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.github/workflows/slack.yml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.github/workflows/test.yml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.gitignore +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.pre-commit-config.yaml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.python-version +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.vscode/extensions.json +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.vscode/launch.json +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/.vscode/settings.json +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/CONTRIBUTING.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/LICENSE +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/README.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/CONTRIBUTING.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/FAQ.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/assets/env-preparation-failed-dark.png +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/assets/env-preparation-failed-light.png +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/assets/favicon.png +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/assets/logo-dark.svg +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/assets/logo-light.svg +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/cli/index.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/actions.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/assets/cloud_env_var_dark.gif +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/assets/cloud_env_var_light.gif +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/assets/cloud_env_var_secret_dark.png +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/assets/cloud_env_var_secret_light.png +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/assets/copy_path_dark.png +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/assets/copy_path_light.png +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/assets.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/attachments.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/buckets.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/connections.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/context_grounding.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/environment_variables.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/getting_started.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/jobs.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/processes.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/queues.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/core/traced.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/hooks.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/javascripts/extra.js +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/overrides/main.html +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/overrides/partials/actions.html +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/overrides/partials/logo.html +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/release_policy.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/docs/stylesheets/extra.css +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/justfile +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/mkdocs.yml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/py.typed +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/__init__.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/README.md +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/__init__.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/_auth_server.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/_client_credentials.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/_models.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/_oidc_utils.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/_portal_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/_utils.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/auth_config.json +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/index.html +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/localhost.crt +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_auth/localhost.key +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_runtime/_contracts.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_runtime/_escalation.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_runtime/_hitl.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_runtime/_logging.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_runtime/_runtime.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_templates/.psmdcp.template +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_templates/.rels.template +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_templates/[Content_Types].xml.template +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_templates/main.py.template +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_templates/package.nuspec.template +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_utils/_common.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_utils/_console.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_utils/_debug.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_utils/_folders.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_utils/_input_args.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_utils/_parse_ast.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_utils/_processes.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/_utils/_tracing.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/cli_auth.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/cli_deploy.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/cli_init.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/cli_invoke.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/cli_new.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/cli_publish.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/cli_run.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/middlewares.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_cli/spinner.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_config.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_execution_context.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_folder_context.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/__init__.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/_base_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/actions_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/api_client.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/assets_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/attachments_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/buckets_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/connections_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/context_grounding_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/folder_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/jobs_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/llm_gateway_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/processes_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_services/queues_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_uipath.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/__init__.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/_endpoint.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/_infer_bindings.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/_logs.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/_read_overwrites.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/_request_override.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/_request_spec.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/_ssl_context.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/_url.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/_user_agent.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/_utils/constants.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/__init__.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/action_schema.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/actions.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/assets.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/attachment.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/buckets.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/connections.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/context_grounding.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/context_grounding_index.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/errors.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/exceptions.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/interrupt_models.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/job.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/llm_gateway.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/processes.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/models/queues.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/py.typed +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/telemetry/__init__.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/telemetry/_constants.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/telemetry/_track.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/tracing/__init__.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/tracing/_otel_exporters.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/tracing/_traced.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/tracing/_utils.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/utils/__init__.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/src/uipath/utils/_endpoints_manager.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/__init__.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/conftest.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/mocks/bindings_script.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/mocks/pyproject.toml +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/mocks/simple_script.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/mocks/uipath-mock.json +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/mocks/uipath-simple-script-mock.json +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/test_hitl.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/test_init.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/test_invoke.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/test_new.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/test_publish.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/test_run.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/test_utils.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/utils/project_details.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/cli/utils/uipath_json.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/conftest.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/conftest.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_actions_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_api_client.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_assets_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_attachments_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_base_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_buckets_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_connections_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_context_grounding_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_folder_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_jobs_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_llm_integration.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_llm_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_processes_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_queues_service.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/services/test_uipath_llm_integration.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/test_bindings_inference.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/test_config.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/sdk/test_overwrites.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/tracing/test_otel_exporters.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/tracing/test_span_utils.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/tracing/test_traced.py +0 -0
- {uipath-2.0.75 → uipath-2.0.77}/tests/tracing/test_tracing_manager.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: uipath
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.77
|
|
4
4
|
Summary: Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools.
|
|
5
5
|
Project-URL: Homepage, https://uipath.com
|
|
6
6
|
Project-URL: Repository, https://github.com/UiPath/uipath-python
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Getting Started
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<div class="grid cards" markdown>
|
|
6
|
+
- __UiPath SDK__
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Code with full UiPath context to build custom automations and agents from the ground up.
|
|
11
|
+
|
|
12
|
+
[Start Building](./core/getting_started.md)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<h2> Extensions </h2>
|
|
17
|
+
<div class="grid cards" markdown>
|
|
18
|
+
- __UiPath Langchain SDK__
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
Build enterprise-grade UiPath agents using the LangChain framework, with seamless integration from build to run.
|
|
23
|
+
|
|
24
|
+
[Get Started](./langchain/quick_start.md)
|
|
25
|
+
|
|
26
|
+
- __UiPath LLamaIndex SDK__
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
Build enterprise-grade UiPath agents using the LLamaIndex framework, with seamless integration from build to run.
|
|
31
|
+
|
|
32
|
+
[Get Started](./llamaindex/quick_start.md)
|
|
33
|
+
|
|
34
|
+
</div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "uipath"
|
|
3
|
-
version = "2.0.
|
|
3
|
+
version = "2.0.77"
|
|
4
4
|
description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools."
|
|
5
5
|
readme = { file = "README.md", content-type = "text/markdown" }
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
BINDINGS_VERSION = "2.2"
|
|
2
|
+
|
|
3
|
+
# Binary file extension categories
|
|
4
|
+
IMAGE_EXTENSIONS = {
|
|
5
|
+
".png",
|
|
6
|
+
".jpg",
|
|
7
|
+
".jpeg",
|
|
8
|
+
".gif",
|
|
9
|
+
".bmp",
|
|
10
|
+
".ico",
|
|
11
|
+
".tiff",
|
|
12
|
+
".webp",
|
|
13
|
+
".svg",
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
DOCUMENT_EXTENSIONS = {".pdf", ".docx", ".pptx", ".xlsx", ".xls"}
|
|
17
|
+
|
|
18
|
+
ARCHIVE_EXTENSIONS = {".zip", ".tar", ".gz", ".rar", ".7z", ".bz2", ".xz"}
|
|
19
|
+
|
|
20
|
+
MEDIA_EXTENSIONS = {
|
|
21
|
+
".mp3",
|
|
22
|
+
".wav",
|
|
23
|
+
".flac",
|
|
24
|
+
".aac",
|
|
25
|
+
".mp4",
|
|
26
|
+
".avi",
|
|
27
|
+
".mov",
|
|
28
|
+
".mkv",
|
|
29
|
+
".wmv",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
FONT_EXTENSIONS = {".woff", ".woff2", ".ttf", ".otf", ".eot"}
|
|
33
|
+
|
|
34
|
+
EXECUTABLE_EXTENSIONS = {".exe", ".dll", ".so", ".dylib", ".bin"}
|
|
35
|
+
|
|
36
|
+
DATABASE_EXTENSIONS = {".db", ".sqlite", ".sqlite3"}
|
|
37
|
+
|
|
38
|
+
PYTHON_BINARY_EXTENSIONS = {".pickle", ".pkl"}
|
|
39
|
+
|
|
40
|
+
SPECIAL_EXTENSIONS = {""} # Extensionless binary files
|
|
41
|
+
|
|
42
|
+
# Pre-compute the union for optimal performance
|
|
43
|
+
BINARY_EXTENSIONS = (
|
|
44
|
+
IMAGE_EXTENSIONS
|
|
45
|
+
| DOCUMENT_EXTENSIONS
|
|
46
|
+
| ARCHIVE_EXTENSIONS
|
|
47
|
+
| MEDIA_EXTENSIONS
|
|
48
|
+
| FONT_EXTENSIONS
|
|
49
|
+
| EXECUTABLE_EXTENSIONS
|
|
50
|
+
| DATABASE_EXTENSIONS
|
|
51
|
+
| PYTHON_BINARY_EXTENSIONS
|
|
52
|
+
| SPECIAL_EXTENSIONS
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def is_binary_file(file_extension: str) -> bool:
|
|
57
|
+
"""Determine if a file should be treated as binary."""
|
|
58
|
+
return file_extension.lower() in BINARY_EXTENSIONS
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# type: ignore
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
|
+
import re
|
|
4
5
|
import subprocess
|
|
5
6
|
import uuid
|
|
6
7
|
import zipfile
|
|
7
8
|
from string import Template
|
|
9
|
+
from typing import Dict, Tuple
|
|
8
10
|
|
|
9
11
|
import click
|
|
10
12
|
|
|
@@ -15,6 +17,7 @@ except ImportError:
|
|
|
15
17
|
|
|
16
18
|
from ..telemetry import track
|
|
17
19
|
from ._utils._console import ConsoleLogger
|
|
20
|
+
from ._utils._constants import is_binary_file
|
|
18
21
|
|
|
19
22
|
console = ConsoleLogger()
|
|
20
23
|
|
|
@@ -50,6 +53,7 @@ def check_config(directory):
|
|
|
50
53
|
"entryPoints": config_data["entryPoints"],
|
|
51
54
|
"version": toml_data["version"],
|
|
52
55
|
"authors": toml_data["authors"],
|
|
56
|
+
"dependencies": toml_data.get("dependencies", {}),
|
|
53
57
|
}
|
|
54
58
|
|
|
55
59
|
|
|
@@ -113,7 +117,7 @@ def handle_uv_operations(directory):
|
|
|
113
117
|
run_uv_lock(directory)
|
|
114
118
|
|
|
115
119
|
|
|
116
|
-
def generate_operate_file(entryPoints):
|
|
120
|
+
def generate_operate_file(entryPoints, dependencies=None):
|
|
117
121
|
project_id = str(uuid.uuid4())
|
|
118
122
|
|
|
119
123
|
first_entry = entryPoints[0]
|
|
@@ -130,6 +134,10 @@ def generate_operate_file(entryPoints):
|
|
|
130
134
|
"runtimeOptions": {"requiresUserInteraction": False, "isAttended": False},
|
|
131
135
|
}
|
|
132
136
|
|
|
137
|
+
# Add dependencies if provided
|
|
138
|
+
if dependencies:
|
|
139
|
+
operate_json_data["dependencies"] = dependencies
|
|
140
|
+
|
|
133
141
|
return operate_json_data
|
|
134
142
|
|
|
135
143
|
|
|
@@ -149,40 +157,6 @@ def generate_bindings_content():
|
|
|
149
157
|
return bindings_content
|
|
150
158
|
|
|
151
159
|
|
|
152
|
-
def get_proposed_version(directory):
|
|
153
|
-
output_dir = os.path.join(directory, ".uipath")
|
|
154
|
-
if not os.path.exists(output_dir):
|
|
155
|
-
return None
|
|
156
|
-
|
|
157
|
-
# Get all .nupkg files
|
|
158
|
-
nupkg_files = [f for f in os.listdir(output_dir) if f.endswith(".nupkg")]
|
|
159
|
-
if not nupkg_files:
|
|
160
|
-
return None
|
|
161
|
-
|
|
162
|
-
# Sort by modification time to get most recent
|
|
163
|
-
latest_file = max(
|
|
164
|
-
nupkg_files, key=lambda f: os.path.getmtime(os.path.join(output_dir, f))
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
# Extract version from filename
|
|
168
|
-
# Remove .nupkg extension first
|
|
169
|
-
name_version = latest_file[:-6]
|
|
170
|
-
# Find 3rd last occurrence of . by splitting and joining parts
|
|
171
|
-
parts = name_version.split(".")
|
|
172
|
-
if len(parts) >= 3:
|
|
173
|
-
version = ".".join(parts[-3:])
|
|
174
|
-
else:
|
|
175
|
-
version = name_version
|
|
176
|
-
|
|
177
|
-
# Increment patch version by 1
|
|
178
|
-
try:
|
|
179
|
-
major, minor, patch = version.split(".")
|
|
180
|
-
new_version = f"{major}.{minor}.{int(patch) + 1}"
|
|
181
|
-
return new_version
|
|
182
|
-
except Exception:
|
|
183
|
-
return "0.0.1"
|
|
184
|
-
|
|
185
|
-
|
|
186
160
|
def generate_content_types_content():
|
|
187
161
|
templates_path = os.path.join(
|
|
188
162
|
os.path.dirname(__file__), "_templates", "[Content_Types].xml.template"
|
|
@@ -278,9 +252,10 @@ def pack_fn(
|
|
|
278
252
|
version,
|
|
279
253
|
authors,
|
|
280
254
|
directory,
|
|
255
|
+
dependencies=None,
|
|
281
256
|
include_uv_lock=True,
|
|
282
257
|
):
|
|
283
|
-
operate_file = generate_operate_file(entryPoints)
|
|
258
|
+
operate_file = generate_operate_file(entryPoints, dependencies)
|
|
284
259
|
entrypoints_file = generate_entrypoints_file(entryPoints)
|
|
285
260
|
|
|
286
261
|
# Get bindings from uipath.json if available
|
|
@@ -291,8 +266,6 @@ def pack_fn(
|
|
|
291
266
|
# Define the allowlist of file extensions to include
|
|
292
267
|
file_extensions_included = [".py", ".mermaid", ".json", ".yaml", ".yml"]
|
|
293
268
|
files_included = []
|
|
294
|
-
# Binary files that should be read in binary mode
|
|
295
|
-
binary_extensions = [".exe", "", ".xlsx", ".xls"]
|
|
296
269
|
|
|
297
270
|
with open(config_path, "r") as f:
|
|
298
271
|
config_data = json.load(f)
|
|
@@ -354,7 +327,7 @@ def pack_fn(
|
|
|
354
327
|
if file_extension in file_extensions_included or file in files_included:
|
|
355
328
|
file_path = os.path.join(root, file)
|
|
356
329
|
rel_path = os.path.relpath(file_path, directory)
|
|
357
|
-
if file_extension
|
|
330
|
+
if is_binary_file(file_extension):
|
|
358
331
|
# Read binary files in binary mode
|
|
359
332
|
with open(file_path, "rb") as f:
|
|
360
333
|
z.writestr(f"content/{rel_path}", f.read())
|
|
@@ -389,28 +362,166 @@ def pack_fn(
|
|
|
389
362
|
z.writestr(f"content/{file}", f.read())
|
|
390
363
|
|
|
391
364
|
|
|
392
|
-
def
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
365
|
+
def parse_dependency_string(dependency: str) -> Tuple[str, str]:
|
|
366
|
+
"""Parse a dependency string into package name and version specifier.
|
|
367
|
+
|
|
368
|
+
Handles PEP 508 dependency specifications including:
|
|
369
|
+
- Simple names: "requests"
|
|
370
|
+
- Version specifiers: "requests>=2.28.0"
|
|
371
|
+
- Complex specifiers: "requests>=2.28.0,<3.0.0"
|
|
372
|
+
- Extras: "requests[security]>=2.28.0"
|
|
373
|
+
- Environment markers: "requests>=2.28.0; python_version>='3.8'"
|
|
374
|
+
|
|
375
|
+
Args:
|
|
376
|
+
dependency: Raw dependency string from pyproject.toml
|
|
377
|
+
|
|
378
|
+
Returns:
|
|
379
|
+
Tuple of (package_name, version_specifier)
|
|
380
|
+
|
|
381
|
+
Examples:
|
|
382
|
+
"requests" -> ("requests", "*")
|
|
383
|
+
"requests>=2.28.0" -> ("requests", ">=2.28.0")
|
|
384
|
+
"requests>=2.28.0,<3.0.0" -> ("requests", ">=2.28.0,<3.0.0")
|
|
385
|
+
"requests[security]>=2.28.0" -> ("requests", ">=2.28.0")
|
|
386
|
+
"""
|
|
387
|
+
# Remove whitespace
|
|
388
|
+
dependency = dependency.strip()
|
|
389
|
+
|
|
390
|
+
# Handle environment markers (everything after semicolon)
|
|
391
|
+
if ";" in dependency:
|
|
392
|
+
dependency = dependency.split(";")[0].strip()
|
|
393
|
+
|
|
394
|
+
# Pattern to match package name with optional extras and version specifiers
|
|
395
|
+
# Matches: package_name[extras] version_specs
|
|
396
|
+
pattern = r"^([a-zA-Z0-9]([a-zA-Z0-9._-]*[a-zA-Z0-9])?)(\[[^\]]+\])?(.*)"
|
|
397
|
+
match = re.match(pattern, dependency)
|
|
398
|
+
|
|
399
|
+
if not match:
|
|
400
|
+
# Fallback for edge cases
|
|
401
|
+
return dependency, "*"
|
|
402
|
+
|
|
403
|
+
package_name = match.group(1)
|
|
404
|
+
version_part = match.group(4).strip() if match.group(4) else ""
|
|
405
|
+
|
|
406
|
+
# If no version specifier, return wildcard
|
|
407
|
+
if not version_part:
|
|
408
|
+
return package_name, "*"
|
|
409
|
+
|
|
410
|
+
# Clean up version specifier
|
|
411
|
+
version_spec = version_part.strip()
|
|
412
|
+
|
|
413
|
+
# Validate that version specifier starts with a valid operator
|
|
414
|
+
valid_operators = [">=", "<=", "==", "!=", "~=", ">", "<"]
|
|
415
|
+
if not any(version_spec.startswith(op) for op in valid_operators):
|
|
416
|
+
# If it doesn't start with an operator, treat as exact version
|
|
417
|
+
if version_spec:
|
|
418
|
+
version_spec = f"=={version_spec}"
|
|
419
|
+
else:
|
|
420
|
+
version_spec = "*"
|
|
421
|
+
|
|
422
|
+
return package_name, version_spec
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def extract_dependencies_from_toml(project_data: Dict) -> Dict[str, str]:
|
|
426
|
+
"""Extract and parse dependencies from pyproject.toml project data.
|
|
427
|
+
|
|
428
|
+
Args:
|
|
429
|
+
project_data: The "project" section from pyproject.toml
|
|
430
|
+
|
|
431
|
+
Returns:
|
|
432
|
+
Dictionary mapping package names to version specifiers
|
|
433
|
+
"""
|
|
434
|
+
dependencies = {}
|
|
435
|
+
|
|
436
|
+
if "dependencies" not in project_data:
|
|
437
|
+
return dependencies
|
|
438
|
+
|
|
439
|
+
deps_list = project_data["dependencies"]
|
|
440
|
+
if not isinstance(deps_list, list):
|
|
441
|
+
console.warning("dependencies should be a list in pyproject.toml")
|
|
442
|
+
return dependencies
|
|
443
|
+
|
|
444
|
+
for dep in deps_list:
|
|
445
|
+
if not isinstance(dep, str):
|
|
446
|
+
console.warning(f"Skipping non-string dependency: {dep}")
|
|
447
|
+
continue
|
|
448
|
+
|
|
449
|
+
try:
|
|
450
|
+
name, version_spec = parse_dependency_string(dep)
|
|
451
|
+
if name: # Only add if we got a valid name
|
|
452
|
+
dependencies[name] = version_spec
|
|
453
|
+
except Exception as e:
|
|
454
|
+
console.warning(f"Failed to parse dependency '{dep}': {e}")
|
|
455
|
+
continue
|
|
456
|
+
|
|
457
|
+
return dependencies
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
def read_toml_project(file_path: str) -> dict:
|
|
461
|
+
"""Read and parse pyproject.toml file with improved error handling and validation.
|
|
462
|
+
|
|
463
|
+
Args:
|
|
464
|
+
file_path: Path to pyproject.toml file
|
|
465
|
+
|
|
466
|
+
Returns:
|
|
467
|
+
Dictionary containing project metadata and dependencies
|
|
468
|
+
"""
|
|
469
|
+
try:
|
|
470
|
+
with open(file_path, "rb") as f:
|
|
471
|
+
content = tomllib.load(f)
|
|
472
|
+
except Exception as e:
|
|
473
|
+
console.error(f"Failed to read or parse pyproject.toml: {e}")
|
|
474
|
+
|
|
475
|
+
# Validate required sections
|
|
476
|
+
if "project" not in content:
|
|
477
|
+
console.error("pyproject.toml is missing the required field: project.")
|
|
478
|
+
|
|
479
|
+
project = content["project"]
|
|
480
|
+
|
|
481
|
+
# Validate required fields with better error messages
|
|
482
|
+
required_fields = {
|
|
483
|
+
"name": "Project name is required in pyproject.toml",
|
|
484
|
+
"description": "Project description is required in pyproject.toml",
|
|
485
|
+
"version": "Project version is required in pyproject.toml",
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
for field, error_msg in required_fields.items():
|
|
489
|
+
if field not in project:
|
|
400
490
|
console.error(
|
|
401
|
-
"pyproject.toml is missing the required field: project.
|
|
491
|
+
f"pyproject.toml is missing the required field: project.{field}. {error_msg}"
|
|
402
492
|
)
|
|
403
|
-
|
|
493
|
+
|
|
494
|
+
# Check for empty values only if field exists
|
|
495
|
+
if field in project and (
|
|
496
|
+
not project[field]
|
|
497
|
+
or (isinstance(project[field], str) and not project[field].strip())
|
|
498
|
+
):
|
|
404
499
|
console.error(
|
|
405
|
-
"
|
|
500
|
+
f"Project {field} cannot be empty. Please specify a {field} in pyproject.toml."
|
|
406
501
|
)
|
|
407
502
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
503
|
+
# Extract author information safely
|
|
504
|
+
authors = project.get("authors", [])
|
|
505
|
+
author_name = ""
|
|
506
|
+
|
|
507
|
+
if authors and isinstance(authors, list) and len(authors) > 0:
|
|
508
|
+
first_author = authors[0]
|
|
509
|
+
if isinstance(first_author, dict):
|
|
510
|
+
author_name = first_author.get("name", "")
|
|
511
|
+
elif isinstance(first_author, str):
|
|
512
|
+
# Handle case where authors is a list of strings
|
|
513
|
+
author_name = first_author
|
|
514
|
+
|
|
515
|
+
# Extract dependencies with improved parsing
|
|
516
|
+
dependencies = extract_dependencies_from_toml(project)
|
|
517
|
+
|
|
518
|
+
return {
|
|
519
|
+
"name": project["name"].strip(),
|
|
520
|
+
"description": project["description"].strip(),
|
|
521
|
+
"version": project["version"].strip(),
|
|
522
|
+
"authors": author_name.strip(),
|
|
523
|
+
"dependencies": dependencies,
|
|
524
|
+
}
|
|
414
525
|
|
|
415
526
|
|
|
416
527
|
def get_project_version(directory):
|
|
@@ -492,6 +603,7 @@ def pack(root, nolock):
|
|
|
492
603
|
version or config["version"],
|
|
493
604
|
config["authors"],
|
|
494
605
|
root,
|
|
606
|
+
config.get("dependencies"),
|
|
495
607
|
include_uv_lock=not nolock,
|
|
496
608
|
)
|
|
497
609
|
display_project_info(config)
|
|
@@ -324,3 +324,150 @@ class TestPack:
|
|
|
324
324
|
}
|
|
325
325
|
assert f"Authors : {', '.join(authors_dict.keys())}" in result.output
|
|
326
326
|
assert "Project successfully packaged." in result.output
|
|
327
|
+
|
|
328
|
+
def test_dependencies_version_formats(
|
|
329
|
+
self,
|
|
330
|
+
runner: CliRunner,
|
|
331
|
+
temp_dir: str,
|
|
332
|
+
project_details: ProjectDetails,
|
|
333
|
+
uipath_json: UiPathJson,
|
|
334
|
+
) -> None:
|
|
335
|
+
"""Test that all dependency version formats are parsed correctly and included in operate.json."""
|
|
336
|
+
|
|
337
|
+
# Update project details with comprehensive dependency examples
|
|
338
|
+
project_details.dependencies = [
|
|
339
|
+
# Simple package name
|
|
340
|
+
"click",
|
|
341
|
+
# Single version constraints
|
|
342
|
+
"django>=4.0",
|
|
343
|
+
"flask==2.3.0",
|
|
344
|
+
"numpy>1.20.0",
|
|
345
|
+
"pandas<=2.0.0",
|
|
346
|
+
"scipy<1.11.0",
|
|
347
|
+
"matplotlib~=3.5.0",
|
|
348
|
+
"pytest!=7.1.0",
|
|
349
|
+
# Complex version constraints
|
|
350
|
+
"tensorflow>=2.10.0,<2.13.0",
|
|
351
|
+
"torch>=1.12.0,<=1.13.1",
|
|
352
|
+
# Package with extras
|
|
353
|
+
"requests[security]>=2.28.0",
|
|
354
|
+
"sqlalchemy[postgresql,mysql]>=1.4.0",
|
|
355
|
+
# Environment markers (should be stripped)
|
|
356
|
+
"pywin32>=227; sys_platform=='win32'",
|
|
357
|
+
"uvloop>=0.17.0; python_version>='3.8' and sys_platform!='win32'",
|
|
358
|
+
# Complex combination
|
|
359
|
+
"cryptography[ssh]>=3.4.8,<4.0.0; python_version>='3.7'",
|
|
360
|
+
# Edge cases
|
|
361
|
+
"some-package_with.dots_and-dashes>=1.0.0",
|
|
362
|
+
"CamelCasePackage==2.1.0",
|
|
363
|
+
]
|
|
364
|
+
|
|
365
|
+
with runner.isolated_filesystem(temp_dir=temp_dir):
|
|
366
|
+
# Create necessary files
|
|
367
|
+
with open("uipath.json", "w") as f:
|
|
368
|
+
f.write(uipath_json.to_json())
|
|
369
|
+
with open("pyproject.toml", "w") as f:
|
|
370
|
+
f.write(project_details.to_toml())
|
|
371
|
+
|
|
372
|
+
# Create entry point files
|
|
373
|
+
for entry in uipath_json.entry_points:
|
|
374
|
+
with open(f"{entry.file_path}.py", "w") as f:
|
|
375
|
+
f.write("# agent content")
|
|
376
|
+
|
|
377
|
+
# Run pack command
|
|
378
|
+
result = runner.invoke(pack, ["./"])
|
|
379
|
+
|
|
380
|
+
# Assert pack was successful
|
|
381
|
+
assert result.exit_code == 0, f"Pack failed with output: {result.output}"
|
|
382
|
+
assert "Project successfully packaged." in result.output
|
|
383
|
+
|
|
384
|
+
# Verify package was created
|
|
385
|
+
package_path = (
|
|
386
|
+
f".uipath/{project_details.name}.{project_details.version}.nupkg"
|
|
387
|
+
)
|
|
388
|
+
assert os.path.exists(package_path)
|
|
389
|
+
|
|
390
|
+
# Extract and verify operate.json content
|
|
391
|
+
with zipfile.ZipFile(package_path, "r") as z:
|
|
392
|
+
# Read operate.json
|
|
393
|
+
operate_content = z.read("content/operate.json").decode("utf-8")
|
|
394
|
+
operate_data = json.loads(operate_content)
|
|
395
|
+
|
|
396
|
+
# Verify dependencies exist in operate.json
|
|
397
|
+
assert "dependencies" in operate_data, (
|
|
398
|
+
"Dependencies should be present in operate.json"
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
dependencies = operate_data["dependencies"]
|
|
402
|
+
|
|
403
|
+
# Expected parsed dependencies (name -> version_spec)
|
|
404
|
+
expected_dependencies = {
|
|
405
|
+
# Simple package name
|
|
406
|
+
"click": "*",
|
|
407
|
+
# Single version constraints
|
|
408
|
+
"django": ">=4.0",
|
|
409
|
+
"flask": "==2.3.0",
|
|
410
|
+
"numpy": ">1.20.0",
|
|
411
|
+
"pandas": "<=2.0.0",
|
|
412
|
+
"scipy": "<1.11.0",
|
|
413
|
+
"matplotlib": "~=3.5.0",
|
|
414
|
+
"pytest": "!=7.1.0",
|
|
415
|
+
# Complex version constraints
|
|
416
|
+
"tensorflow": ">=2.10.0,<2.13.0",
|
|
417
|
+
"torch": ">=1.12.0,<=1.13.1",
|
|
418
|
+
# Package with extras (extras should be stripped)
|
|
419
|
+
"requests": ">=2.28.0",
|
|
420
|
+
"sqlalchemy": ">=1.4.0",
|
|
421
|
+
# Environment markers (markers should be stripped)
|
|
422
|
+
"pywin32": ">=227",
|
|
423
|
+
"uvloop": ">=0.17.0",
|
|
424
|
+
# Complex combination (extras and markers stripped)
|
|
425
|
+
"cryptography": ">=3.4.8,<4.0.0",
|
|
426
|
+
# Edge cases
|
|
427
|
+
"some-package_with.dots_and-dashes": ">=1.0.0",
|
|
428
|
+
"CamelCasePackage": "==2.1.0",
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
# Verify all expected dependencies are present
|
|
432
|
+
for package_name, expected_version in expected_dependencies.items():
|
|
433
|
+
assert package_name in dependencies, (
|
|
434
|
+
f"Package '{package_name}' should be in dependencies"
|
|
435
|
+
)
|
|
436
|
+
actual_version = dependencies[package_name]
|
|
437
|
+
assert actual_version == expected_version, (
|
|
438
|
+
f"Package '{package_name}' should have version '{expected_version}', "
|
|
439
|
+
f"but got '{actual_version}'"
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
# Verify no unexpected dependencies
|
|
443
|
+
for package_name in dependencies:
|
|
444
|
+
assert package_name in expected_dependencies, (
|
|
445
|
+
f"Unexpected package '{package_name}' found in dependencies"
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
# Verify specific edge cases
|
|
449
|
+
assert len(dependencies) == len(expected_dependencies), (
|
|
450
|
+
f"Expected {len(expected_dependencies)} dependencies, "
|
|
451
|
+
f"but got {len(dependencies)}"
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
# Test that environment markers were properly stripped
|
|
455
|
+
assert "pywin32" in dependencies
|
|
456
|
+
assert dependencies["pywin32"] == ">=227"
|
|
457
|
+
|
|
458
|
+
# Test that extras were properly stripped but version preserved
|
|
459
|
+
assert "sqlalchemy" in dependencies
|
|
460
|
+
assert dependencies["sqlalchemy"] == ">=1.4.0"
|
|
461
|
+
|
|
462
|
+
# Test complex version constraints are preserved
|
|
463
|
+
assert "tensorflow" in dependencies
|
|
464
|
+
assert dependencies["tensorflow"] == ">=2.10.0,<2.13.0"
|
|
465
|
+
|
|
466
|
+
# Verify operate.json structure is still correct
|
|
467
|
+
assert (
|
|
468
|
+
operate_data["$schema"]
|
|
469
|
+
== "https://cloud.uipath.com/draft/2024-12/entry-point"
|
|
470
|
+
)
|
|
471
|
+
assert "projectId" in operate_data
|
|
472
|
+
assert operate_data["targetRuntime"] == "python"
|
|
473
|
+
assert operate_data["targetFramework"] == "Portable"
|