port-ocean 0.22.0__tar.gz → 0.22.1__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 port-ocean might be problematic. Click here for more details.
- {port_ocean-0.22.0 → port_ocean-0.22.1}/PKG-INFO +1 -1
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/mixins/entities.py +10 -10
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/defaults/common.py +1 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/defaults/initialize.py +1 -1
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entities_state_applier/port/applier.py +14 -20
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/port_app_config/models.py +1 -1
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/models.py +6 -2
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/utils/utils.py +10 -2
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/clients/port/mixins/test_entities.py +2 -1
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/conftest.py +2 -1
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/entities_state_applier/test_applier.py +68 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/mixins/test_sync_raw.py +24 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/utils/test_resolve_entities_diff.py +52 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/pyproject.toml +1 -1
- {port_ocean-0.22.0 → port_ocean-0.22.1}/LICENSE.md +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/README.md +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/integrations/_infra/Dockerfile.Deb +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/integrations/_infra/Dockerfile.alpine +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/integrations/_infra/Dockerfile.base.builder +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/integrations/_infra/Dockerfile.base.runner +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/integrations/_infra/Dockerfile.dockerignore +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/integrations/_infra/Makefile +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/integrations/_infra/grpcio.sh +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/integrations/_infra/init.sh +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/bootstrap.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cli.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/defaults/__init___.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/defaults/clean.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/defaults/dock.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/defaults/group.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/list_integrations.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/main.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/new.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/pull.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/sail.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/commands/version.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/cookiecutter.json +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/extensions.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.env.example +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.gitignore +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/.gitignore +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/blueprints.json +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/resources/port-app-config.yml +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/.port/spec.yaml +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CHANGELOG.md +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/CONTRIBUTING.md +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/README.md +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/changelog/.gitignore +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/debug.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/main.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/poetry.toml +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/pyproject.toml +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/sonar-project.properties +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/{{cookiecutter.integration_slug}}/tests/test_sample.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/utils.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/auth/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/auth/auth_client.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/auth/oauth_client.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/authentication.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/client.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/mixins/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/mixins/blueprints.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/mixins/integrations.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/mixins/migrations.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/mixins/organization.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/retry_transport.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/types.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/clients/port/utils.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/config/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/config/base.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/config/dynamic.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/config/settings.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/consumers/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/consumers/kafka_consumer.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/context/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/context/event.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/context/ocean.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/context/resource.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/defaults/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/defaults/clean.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/event_listener/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/event_listener/base.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/event_listener/factory.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/event_listener/http.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/event_listener/kafka.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/event_listener/once.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/event_listener/polling.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/event_listener/webhooks_only.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/base.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entities_state_applier/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entities_state_applier/base.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entities_state_applier/port/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entities_state_applier/port/get_related_entities.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entities_state_applier/port/order_by_entities_dependencies.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entity_processor/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entity_processor/base.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entity_processor/jq_entity_processor.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/port_app_config/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/port_app_config/api.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/port_app_config/base.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/queue/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/queue/abstract_queue.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/queue/local_queue.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/resync_state_updater/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/resync_state_updater/updater.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/webhook/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/webhook/abstract_webhook_processor.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/webhook/processor_manager.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/webhook/webhook_event.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/integrations/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/integrations/base.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/integrations/mixins/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/integrations/mixins/events.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/integrations/mixins/handler.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/integrations/mixins/live_events.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/integrations/mixins/sync.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/integrations/mixins/sync_raw.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/integrations/mixins/utils.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/ocean_types.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/utils/entity_topological_sorter.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/debug_cli.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/exceptions/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/exceptions/api.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/exceptions/base.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/exceptions/clients.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/exceptions/context.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/exceptions/core.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/exceptions/port_defaults.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/exceptions/utils.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/exceptions/webhook_processor.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/helpers/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/helpers/async_client.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/helpers/metric/metric.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/helpers/metric/utils.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/helpers/retry.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/log/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/log/handlers.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/log/logger_setup.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/log/sensetive.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/middlewares.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/ocean.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/py.typed +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/run.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/sonar-project.properties +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/clients/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/clients/oauth/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/clients/oauth/test_oauth_client.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/clients/port/mixins/test_organization_mixin.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/conftest.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/defaults/test_common.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/entity_processor/test_jq_entity_processor.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/mixins/test_live_events.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/port_app_config/test_api.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/port_app_config/test_base.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/queue/test_local_queue.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/webhook/test_abstract_webhook_processor.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/webhook/test_processor_manager.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/webhook/test_webhook_event.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/test_utils.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/utils/test_entity_topological_sorter.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/helpers/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/helpers/fake_port_api.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/helpers/fixtures.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/helpers/integration.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/helpers/ocean_app.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/helpers/port_client.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/helpers/smoke_test.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/log/test_handlers.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/test_metric.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/test_ocean.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/test_smoke.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/utils/test_async_iterators.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/utils/test_cache.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/utils/__init__.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/utils/async_http.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/utils/async_iterators.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/utils/cache.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/utils/misc.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/utils/queue_utils.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/utils/repeat.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/utils/signal.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/utils/time.py +0 -0
- {port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/version.py +0 -0
|
@@ -133,7 +133,7 @@ class EntityClientMixin:
|
|
|
133
133
|
request_options: RequestOptions,
|
|
134
134
|
user_agent_type: UserAgentType | None = None,
|
|
135
135
|
should_raise: bool = True,
|
|
136
|
-
) -> list[Entity]:
|
|
136
|
+
) -> list[tuple[bool, Entity]]:
|
|
137
137
|
modified_entities_results = await asyncio.gather(
|
|
138
138
|
*(
|
|
139
139
|
self.upsert_entity(
|
|
@@ -146,17 +146,17 @@ class EntityClientMixin:
|
|
|
146
146
|
),
|
|
147
147
|
return_exceptions=True,
|
|
148
148
|
)
|
|
149
|
-
entity_results = [
|
|
150
|
-
entity for entity in modified_entities_results if isinstance(entity, Entity)
|
|
151
|
-
]
|
|
152
|
-
if not should_raise:
|
|
153
|
-
return entity_results
|
|
154
149
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
150
|
+
entities_results: list[tuple[bool, Entity]] = []
|
|
151
|
+
for original_entity, result in zip(entities, modified_entities_results):
|
|
152
|
+
if isinstance(result, Exception) and should_raise:
|
|
153
|
+
raise result
|
|
154
|
+
elif isinstance(result, Entity):
|
|
155
|
+
entities_results.append((True, result))
|
|
156
|
+
elif result is False:
|
|
157
|
+
entities_results.append((False, original_entity))
|
|
158
158
|
|
|
159
|
-
return
|
|
159
|
+
return entities_results
|
|
160
160
|
|
|
161
161
|
async def delete_entity(
|
|
162
162
|
self,
|
|
@@ -42,8 +42,8 @@ def deconstruct_blueprints_to_creation_steps(
|
|
|
42
42
|
blueprint.pop("mirrorProperties", {})
|
|
43
43
|
blueprint.pop("aggregationProperties", {})
|
|
44
44
|
with_relations.append(blueprint.copy())
|
|
45
|
-
|
|
46
45
|
blueprint.pop("teamInheritance", {})
|
|
46
|
+
blueprint.pop("ownership", {})
|
|
47
47
|
blueprint.pop("relations", {})
|
|
48
48
|
bare_blueprint.append(blueprint)
|
|
49
49
|
|
|
@@ -121,26 +121,20 @@ class HttpEntitiesStateApplier(BaseEntitiesStateApplier):
|
|
|
121
121
|
) -> list[Entity]:
|
|
122
122
|
logger.info(f"Upserting {len(entities)} entities")
|
|
123
123
|
modified_entities: list[Entity] = []
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
)
|
|
139
|
-
if upsertedEntity:
|
|
140
|
-
modified_entities.append(upsertedEntity)
|
|
141
|
-
# condition to false to differentiate from `result_entity.is_using_search_identifier`
|
|
142
|
-
if upsertedEntity is False:
|
|
143
|
-
event.entity_topological_sorter.register_entity(entity)
|
|
124
|
+
upserted_entities: list[tuple[bool, Entity]] = []
|
|
125
|
+
|
|
126
|
+
upserted_entities = await self.context.port_client.batch_upsert_entities(
|
|
127
|
+
entities,
|
|
128
|
+
event.port_app_config.get_port_request_options(),
|
|
129
|
+
user_agent_type,
|
|
130
|
+
should_raise=False,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
for is_upserted, entity in upserted_entities:
|
|
134
|
+
if is_upserted:
|
|
135
|
+
modified_entities.append(entity)
|
|
136
|
+
else:
|
|
137
|
+
event.entity_topological_sorter.register_entity(entity)
|
|
144
138
|
return modified_entities
|
|
145
139
|
|
|
146
140
|
async def delete(
|
|
@@ -22,7 +22,7 @@ class EntityMapping(BaseModel):
|
|
|
22
22
|
identifier: str | IngestSearchQuery
|
|
23
23
|
title: str | None
|
|
24
24
|
blueprint: str
|
|
25
|
-
team: str | None
|
|
25
|
+
team: str | IngestSearchQuery | None
|
|
26
26
|
properties: dict[str, str] = Field(default_factory=dict)
|
|
27
27
|
relations: dict[str, str | IngestSearchQuery] = Field(default_factory=dict)
|
|
28
28
|
|
|
@@ -40,7 +40,7 @@ class Entity(BaseModel):
|
|
|
40
40
|
identifier: Any
|
|
41
41
|
blueprint: Any
|
|
42
42
|
title: Any
|
|
43
|
-
team: str | None | list[Any] = []
|
|
43
|
+
team: str | None | list[Any] | dict[str, Any] = []
|
|
44
44
|
properties: dict[str, Any] = {}
|
|
45
45
|
relations: dict[str, Any] = {}
|
|
46
46
|
|
|
@@ -50,7 +50,11 @@ class Entity(BaseModel):
|
|
|
50
50
|
|
|
51
51
|
@property
|
|
52
52
|
def is_using_search_relation(self) -> bool:
|
|
53
|
-
return any(
|
|
53
|
+
return any(
|
|
54
|
+
isinstance(relation, dict) for relation in self.relations.values()
|
|
55
|
+
) or (
|
|
56
|
+
self.team is not None and any(isinstance(team, dict) for team in self.team)
|
|
57
|
+
)
|
|
54
58
|
|
|
55
59
|
|
|
56
60
|
class BlueprintRelation(BaseModel):
|
|
@@ -110,7 +110,8 @@ def get_port_diff(before: Iterable[Entity], after: Iterable[Entity]) -> EntityPo
|
|
|
110
110
|
|
|
111
111
|
|
|
112
112
|
def are_teams_different(
|
|
113
|
-
first_team: str | None | list[Any]
|
|
113
|
+
first_team: str | None | list[Any] | dict[str, Any],
|
|
114
|
+
second_team: str | None | list[Any] | dict[str, Any],
|
|
114
115
|
) -> bool:
|
|
115
116
|
if isinstance(first_team, list) and isinstance(second_team, list):
|
|
116
117
|
return sorted(first_team) != sorted(second_team)
|
|
@@ -122,6 +123,7 @@ def are_entities_fields_equal(
|
|
|
122
123
|
) -> bool:
|
|
123
124
|
"""
|
|
124
125
|
Compare two entity fields by serializing them to JSON and comparing their SHA-256 hashes.
|
|
126
|
+
Removes keys with None values before comparison if the corresponding key doesn't exist in the other dict.
|
|
125
127
|
|
|
126
128
|
Args:
|
|
127
129
|
first_entity_field: First entity field dictionary to compare
|
|
@@ -130,7 +132,13 @@ def are_entities_fields_equal(
|
|
|
130
132
|
Returns:
|
|
131
133
|
bool: True if the entity fields have identical content
|
|
132
134
|
"""
|
|
133
|
-
|
|
135
|
+
first_entity_field_copy = first_entity_field.copy()
|
|
136
|
+
|
|
137
|
+
for key in list(first_entity_field.keys()):
|
|
138
|
+
if first_entity_field[key] is None and key not in second_entity_field:
|
|
139
|
+
del first_entity_field_copy[key]
|
|
140
|
+
|
|
141
|
+
first_props = json.dumps(first_entity_field_copy, sort_keys=True)
|
|
134
142
|
second_props = json.dumps(second_entity_field, sort_keys=True)
|
|
135
143
|
first_hash = hashlib.sha256(first_props.encode()).hexdigest()
|
|
136
144
|
second_hash = hashlib.sha256(second_props.encode()).hexdigest()
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/clients/port/mixins/test_entities.py
RENAMED
|
@@ -41,8 +41,9 @@ async def test_batch_upsert_entities_read_timeout_should_raise_false(
|
|
|
41
41
|
result_entities = await entity_client.batch_upsert_entities(
|
|
42
42
|
entities=all_entities, request_options=MagicMock(), should_raise=False
|
|
43
43
|
)
|
|
44
|
+
entities_only = [entity for _, entity in result_entities]
|
|
44
45
|
|
|
45
|
-
assert
|
|
46
|
+
assert entities_only == expected_result_entities
|
|
46
47
|
|
|
47
48
|
|
|
48
49
|
async def test_batch_upsert_entities_read_timeout_should_raise_true(
|
|
@@ -177,10 +177,11 @@ def create_entity(
|
|
|
177
177
|
blueprint: str,
|
|
178
178
|
relation: dict[str, str] | None = None,
|
|
179
179
|
is_to_fail: bool = False,
|
|
180
|
+
team: str | list[str] | dict[str, Any] | None = None,
|
|
180
181
|
) -> Entity:
|
|
181
182
|
if relation is None:
|
|
182
183
|
relation = {}
|
|
183
|
-
entity = Entity(identifier=id, blueprint=blueprint)
|
|
184
|
+
entity = Entity(identifier=id, blueprint=blueprint, team=team)
|
|
184
185
|
entity.relations = relation
|
|
185
186
|
entity.properties = {"mock_is_to_fail": is_to_fail}
|
|
186
187
|
return entity
|
|
@@ -130,6 +130,74 @@ async def test_applier_with_mock_context(
|
|
|
130
130
|
assert result[0].identifier == "test_entity"
|
|
131
131
|
|
|
132
132
|
|
|
133
|
+
@pytest.mark.asyncio
|
|
134
|
+
async def test_applier_one_not_upserted(
|
|
135
|
+
mock_ocean: Ocean,
|
|
136
|
+
mock_context: PortOceanContext,
|
|
137
|
+
mock_port_app_config: PortAppConfig,
|
|
138
|
+
) -> None:
|
|
139
|
+
# Create an applier using the mock_context fixture
|
|
140
|
+
applier = HttpEntitiesStateApplier(mock_context)
|
|
141
|
+
|
|
142
|
+
# Create test entities
|
|
143
|
+
entity = Entity(identifier="test_entity", blueprint="test_blueprint")
|
|
144
|
+
|
|
145
|
+
async with event_context(EventType.RESYNC, trigger_type="machine") as event:
|
|
146
|
+
# Mock the register_entity method
|
|
147
|
+
event.entity_topological_sorter.register_entity = Mock() # type: ignore
|
|
148
|
+
event.port_app_config = mock_port_app_config
|
|
149
|
+
|
|
150
|
+
# Test the upsert method with mocked client
|
|
151
|
+
with patch.object(mock_ocean.port_client.client, "post") as mock_post:
|
|
152
|
+
mock_post.return_value = Mock(
|
|
153
|
+
status_code=404,
|
|
154
|
+
json=lambda: {"ok": False, "error": "not_found"},
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
result = await applier.upsert([entity], UserAgentType.exporter)
|
|
158
|
+
|
|
159
|
+
# Assert that the post method was called
|
|
160
|
+
mock_post.assert_called_once()
|
|
161
|
+
assert len(result) == 0
|
|
162
|
+
event.entity_topological_sorter.register_entity.assert_called_once_with(
|
|
163
|
+
entity
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@pytest.mark.asyncio
|
|
168
|
+
async def test_applier_error_upserting(
|
|
169
|
+
mock_ocean: Ocean,
|
|
170
|
+
mock_context: PortOceanContext,
|
|
171
|
+
mock_port_app_config: PortAppConfig,
|
|
172
|
+
) -> None:
|
|
173
|
+
# Create an applier using the mock_context fixture
|
|
174
|
+
applier = HttpEntitiesStateApplier(mock_context)
|
|
175
|
+
|
|
176
|
+
# Create test entities
|
|
177
|
+
entity = Entity(identifier="test_entity", blueprint="test_blueprint")
|
|
178
|
+
|
|
179
|
+
async with event_context(EventType.RESYNC, trigger_type="machine") as event:
|
|
180
|
+
# Mock the register_entity method
|
|
181
|
+
event.entity_topological_sorter.register_entity = Mock() # type: ignore
|
|
182
|
+
event.port_app_config = mock_port_app_config
|
|
183
|
+
|
|
184
|
+
# Test the upsert method with mocked client
|
|
185
|
+
with patch.object(mock_ocean.port_client.client, "post") as mock_post:
|
|
186
|
+
mock_post.return_value = Mock(
|
|
187
|
+
status_code=404,
|
|
188
|
+
json=lambda: {"ok": False, "error": "not_found"},
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
result = await applier.upsert([entity], UserAgentType.exporter)
|
|
192
|
+
|
|
193
|
+
# Assert that the post method was called
|
|
194
|
+
mock_post.assert_called_once()
|
|
195
|
+
assert len(result) == 0
|
|
196
|
+
event.entity_topological_sorter.register_entity.assert_called_once_with(
|
|
197
|
+
entity
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
|
|
133
201
|
@pytest.mark.asyncio
|
|
134
202
|
async def test_using_create_entity_helper(
|
|
135
203
|
mock_ocean: Ocean,
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/mixins/test_sync_raw.py
RENAMED
|
@@ -417,6 +417,30 @@ async def test_map_entities_compared_with_port_no_port_entities_all_entities_are
|
|
|
417
417
|
assert "entity_2" in [e.identifier for e in changed_entities]
|
|
418
418
|
|
|
419
419
|
|
|
420
|
+
@pytest.mark.asyncio
|
|
421
|
+
async def test_map_entities_compared_with_port_returns_original_entities_when_using_team_search_query(
|
|
422
|
+
mock_sync_raw_mixin: SyncRawMixin,
|
|
423
|
+
mock_resource_config: ResourceConfig,
|
|
424
|
+
) -> None:
|
|
425
|
+
|
|
426
|
+
team_search_query = {
|
|
427
|
+
"combinator": "and",
|
|
428
|
+
"rules": [{"property": "$team", "operator": "=", "value": "my-team"}],
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
entities = [
|
|
432
|
+
create_entity("entity_1", "service", {}, False, team=team_search_query),
|
|
433
|
+
create_entity("entity_2", "service", {}, False, team=team_search_query),
|
|
434
|
+
]
|
|
435
|
+
|
|
436
|
+
changed_entities = await mock_sync_raw_mixin._map_entities_compared_with_port(
|
|
437
|
+
entities, mock_resource_config, UserAgentType.exporter
|
|
438
|
+
)
|
|
439
|
+
|
|
440
|
+
assert len(changed_entities) == 2
|
|
441
|
+
assert changed_entities == entities
|
|
442
|
+
|
|
443
|
+
|
|
420
444
|
@pytest.mark.asyncio
|
|
421
445
|
async def test_map_entities_compared_with_port_with_existing_entities_only_changed_third_party_entities_are_mapped(
|
|
422
446
|
mock_sync_raw_mixin: SyncRawMixin,
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/utils/test_resolve_entities_diff.py
RENAMED
|
@@ -246,6 +246,58 @@ def test_are_entities_fields_equal_different_nested_relations_should_be_false()
|
|
|
246
246
|
)
|
|
247
247
|
|
|
248
248
|
|
|
249
|
+
def test_are_entities_fields_equal_null_properties_should_be_true() -> None:
|
|
250
|
+
assert (
|
|
251
|
+
are_entities_fields_equal(
|
|
252
|
+
{
|
|
253
|
+
"team": None,
|
|
254
|
+
"members": ["user1", "user2"],
|
|
255
|
+
"metadata": {"role": "admin"},
|
|
256
|
+
},
|
|
257
|
+
{"members": ["user1", "user2"], "metadata": {"role": "admin"}},
|
|
258
|
+
)
|
|
259
|
+
is True
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def test_are_entities_fields_equal_null_properties_and_real_data_in_other_entity_should_be_false() -> (
|
|
264
|
+
None
|
|
265
|
+
):
|
|
266
|
+
assert (
|
|
267
|
+
are_entities_fields_equal(
|
|
268
|
+
{
|
|
269
|
+
"team": None,
|
|
270
|
+
"members": ["user1", "user2"],
|
|
271
|
+
"metadata": {"role": "admin"},
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"team": "team_id1",
|
|
275
|
+
"members": ["user1", "user2"],
|
|
276
|
+
"metadata": {"role": "admin"},
|
|
277
|
+
},
|
|
278
|
+
)
|
|
279
|
+
is False
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def test_are_entities_fields_equal_null_properties_in_both_should_be_true() -> None:
|
|
284
|
+
assert (
|
|
285
|
+
are_entities_fields_equal(
|
|
286
|
+
{
|
|
287
|
+
"team": None,
|
|
288
|
+
"members": ["user1", "user2"],
|
|
289
|
+
"metadata": {"role": "admin"},
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"team": None,
|
|
293
|
+
"members": ["user1", "user2"],
|
|
294
|
+
"metadata": {"role": "admin"},
|
|
295
|
+
},
|
|
296
|
+
)
|
|
297
|
+
is True
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
|
|
249
301
|
def test_are_entities_different_identical_entities_should_be_false() -> None:
|
|
250
302
|
entity1 = create_test_entity(
|
|
251
303
|
"",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/cli/cookiecutter/hooks/post_gen_project.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entities_state_applier/__init__.py
RENAMED
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entities_state_applier/base.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/entity_processor/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/port_app_config/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/resync_state_updater/__init__.py
RENAMED
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/resync_state_updater/updater.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/core/handlers/webhook/processor_manager.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/mixins/test_live_events.py
RENAMED
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/port_app_config/test_api.py
RENAMED
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/port_app_config/test_base.py
RENAMED
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/queue/test_local_queue.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{port_ocean-0.22.0 → port_ocean-0.22.1}/port_ocean/tests/core/handlers/webhook/test_webhook_event.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|