From 92f1de329d518a0cd3a51a200cd81511b561af43 Mon Sep 17 00:00:00 2001 From: Suyash Kshirsagar Date: Thu, 6 Nov 2025 22:21:55 -0800 Subject: [PATCH 1/2] feat: Complete SDK restructuring Major Changes: - Restructured SDK into modular architecture for better scalability and maintainability - Organized codebase into logical modules: core/, data/, utils/, models/, extensions/ SDK Structure Changes: - core/: Authentication, configuration, HTTP client, and error handling - data/: OData client, CRUD operations, SQL queries, and file uploads - utils/: Pandas adapter and utility functions - models/: Data models and type definitions (extensible) - extensions/: Optional features like CLI and async clients (extensible) Test Organization: - Restructured tests into unit/, integration/, and fixtures/ folders - Added comprehensive test infrastructure with conftest.py and test_data.py - Organized unit tests by module: unit/core/, unit/data/, unit/utils/ - All 25 existing tests pass in new structure Examples Reorganization: - basic/: Getting started examples (quickstart.py) - advanced/: Complex scenarios (pandas_integration.py, file_upload.py) - integrations/: Microsoft service integrations (extensible) - utilities/: Helper scripts and tools (extensible) Import Path Updates: - Updated all import paths to use new modular structure - Maintained clean API surface through __init__.py files - Client.py updated to import from new module locations Benefits: - Improved code organization and separation of concerns - Faster CI/CD with targeted test execution - Better developer experience with logical code grouping - Scalable architecture ready for future SDK expansion - Team-friendly structure for collaborative development --- examples/README.md | 75 +++++++++++++++++++ examples/__init__.py | 4 + examples/advanced/__init__.py | 4 + .../file_upload.py} | 0 .../pandas_integration.py} | 2 +- examples/basic/__init__.py | 4 + examples/{ => basic}/quickstart.py | 2 +- examples/integrations/__init__.py | 4 + examples/utilities/__init__.py | 4 + src/dataverse_sdk/client.py | 6 +- src/dataverse_sdk/core/__init__.py | 32 ++++++++ src/dataverse_sdk/{ => core}/auth.py | 0 src/dataverse_sdk/{ => core}/config.py | 0 src/dataverse_sdk/{ => core}/error_codes.py | 0 src/dataverse_sdk/{ => core}/errors.py | 0 src/dataverse_sdk/{ => core}/http.py | 0 src/dataverse_sdk/data/__init__.py | 14 ++++ src/dataverse_sdk/{ => data}/odata.py | 10 +-- .../{odata_upload_files.py => data/upload.py} | 0 src/dataverse_sdk/extensions/__init__.py | 12 +++ src/dataverse_sdk/models/__init__.py | 12 +++ src/dataverse_sdk/utils/__init__.py | 13 ++++ .../pandas_adapter.py} | 2 +- tests/__init__.py | 4 + tests/conftest.py | 65 ++++++++++++++++ tests/fixtures/test_data.py | 69 +++++++++++++++++ tests/integration/__init__.py | 4 + tests/unit/__init__.py | 4 + tests/unit/core/__init__.py | 4 + tests/{ => unit/core}/test_http_errors.py | 6 +- tests/unit/data/__init__.py | 4 + .../data}/test_enum_optionset_payload.py | 2 +- tests/{ => unit/data}/test_logical_crud.py | 4 +- tests/{ => unit/data}/test_sql_parse.py | 2 +- tests/unit/utils/__init__.py | 4 + 35 files changed, 354 insertions(+), 18 deletions(-) create mode 100644 examples/README.md create mode 100644 examples/__init__.py create mode 100644 examples/advanced/__init__.py rename examples/{quickstart_file_upload.py => advanced/file_upload.py} (100%) rename examples/{quickstart_pandas.py => advanced/pandas_integration.py} (99%) create mode 100644 examples/basic/__init__.py rename examples/{ => basic}/quickstart.py (99%) create mode 100644 examples/integrations/__init__.py create mode 100644 examples/utilities/__init__.py create mode 100644 src/dataverse_sdk/core/__init__.py rename src/dataverse_sdk/{ => core}/auth.py (100%) rename src/dataverse_sdk/{ => core}/config.py (100%) rename src/dataverse_sdk/{ => core}/error_codes.py (100%) rename src/dataverse_sdk/{ => core}/errors.py (100%) rename src/dataverse_sdk/{ => core}/http.py (100%) create mode 100644 src/dataverse_sdk/data/__init__.py rename src/dataverse_sdk/{ => data}/odata.py (99%) rename src/dataverse_sdk/{odata_upload_files.py => data/upload.py} (100%) create mode 100644 src/dataverse_sdk/extensions/__init__.py create mode 100644 src/dataverse_sdk/models/__init__.py create mode 100644 src/dataverse_sdk/utils/__init__.py rename src/dataverse_sdk/{odata_pandas_wrappers.py => utils/pandas_adapter.py} (99%) create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/fixtures/test_data.py create mode 100644 tests/integration/__init__.py create mode 100644 tests/unit/__init__.py create mode 100644 tests/unit/core/__init__.py rename tests/{ => unit/core}/test_http_errors.py (94%) create mode 100644 tests/unit/data/__init__.py rename tests/{ => unit/data}/test_enum_optionset_payload.py (99%) rename tests/{ => unit/data}/test_logical_crud.py (97%) rename tests/{ => unit/data}/test_sql_parse.py (96%) create mode 100644 tests/unit/utils/__init__.py diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..54e9a18 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,75 @@ +# Dataverse SDK Examples + +This directory contains comprehensive examples demonstrating how to use the Microsoft Dataverse SDK for Python. + +## 📁 Directory Structure + +### 🌱 Basic Examples (`basic/`) +Get started quickly with fundamental Dataverse operations: +- **`quickstart.py`** - Basic client setup, authentication, and simple CRUD operations +- Authentication setup with Azure Identity +- Creating, reading, updating, and deleting records +- Basic error handling + +### 🚀 Advanced Examples (`advanced/`) +Explore powerful features for complex scenarios: +- **`file_upload.py`** - File upload to Dataverse file columns with chunking +- **`pandas_integration.py`** - DataFrame-based operations for data analysis +- **`bulk_operations.py`** - Batch processing and bulk data operations +- **`metadata_management.py`** - Creating and managing custom tables +- **`sql_queries.py`** - Advanced SQL queries via Web API + +### 🔗 Integrations (`integrations/`) +Connect Dataverse with other Microsoft services: +- **`power_automate.py`** - Integration patterns with Power Automate +- **`azure_functions.py`** - Using the SDK in Azure Functions +- Power BI integration examples +- Azure Logic Apps patterns + +### 🛠️ Utilities (`utilities/`) +Helper scripts and development tools: +- **`connection_tester.py`** - Test and validate Dataverse connections +- **`data_migration.py`** - Scripts for data migration scenarios +- Development and debugging utilities + +## 🚀 Getting Started + +1. **Install Dependencies**: + ```bash + pip install -r requirements.txt + ``` + +2. **Set Up Authentication**: + Configure Azure Identity credentials (see individual examples for details) + +3. **Run Basic Example**: + ```bash + python examples/basic/quickstart.py + ``` + +## 📋 Prerequisites + +- Python 3.8+ +- Azure Identity credentials configured +- Access to a Dataverse environment +- Required packages installed from `requirements.txt` + +## 🔒 Authentication + +All examples use Azure Identity for authentication. Common patterns: +- `DefaultAzureCredential` for development +- `ClientSecretCredential` for production services +- `InteractiveBrowserCredential` for interactive scenarios + +## 📖 Documentation + +For detailed API documentation, visit: [Dataverse SDK Documentation](link-to-docs) + +## 🤝 Contributing + +When adding new examples: +1. Follow the existing code style and structure +2. Include comprehensive comments and docstrings +3. Add error handling and validation +4. Update this README with your example +5. Test thoroughly before submitting \ No newline at end of file diff --git a/examples/__init__.py b/examples/__init__.py new file mode 100644 index 0000000..87c2ba9 --- /dev/null +++ b/examples/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Examples package for the Dataverse SDK.""" \ No newline at end of file diff --git a/examples/advanced/__init__.py b/examples/advanced/__init__.py new file mode 100644 index 0000000..fc6b584 --- /dev/null +++ b/examples/advanced/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Advanced examples showcasing complex Dataverse SDK features.""" \ No newline at end of file diff --git a/examples/quickstart_file_upload.py b/examples/advanced/file_upload.py similarity index 100% rename from examples/quickstart_file_upload.py rename to examples/advanced/file_upload.py diff --git a/examples/quickstart_pandas.py b/examples/advanced/pandas_integration.py similarity index 99% rename from examples/quickstart_pandas.py rename to examples/advanced/pandas_integration.py index 5f8ac8a..a117ed9 100644 --- a/examples/quickstart_pandas.py +++ b/examples/advanced/pandas_integration.py @@ -9,7 +9,7 @@ sys.path.append(str(Path(__file__).resolve().parents[1] / "src")) from dataverse_sdk import DataverseClient -from dataverse_sdk.odata_pandas_wrappers import PandasODataClient +from dataverse_sdk.utils.pandas_adapter import PandasODataClient from azure.identity import InteractiveBrowserCredential import traceback import requests diff --git a/examples/basic/__init__.py b/examples/basic/__init__.py new file mode 100644 index 0000000..5eff67a --- /dev/null +++ b/examples/basic/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Basic examples for getting started with the Dataverse SDK.""" \ No newline at end of file diff --git a/examples/quickstart.py b/examples/basic/quickstart.py similarity index 99% rename from examples/quickstart.py rename to examples/basic/quickstart.py index 7b6d713..f4da0f9 100644 --- a/examples/quickstart.py +++ b/examples/basic/quickstart.py @@ -10,7 +10,7 @@ sys.path.append(str(Path(__file__).resolve().parents[1] / "src")) from dataverse_sdk import DataverseClient -from dataverse_sdk.errors import MetadataError +from dataverse_sdk.core.errors import MetadataError from enum import IntEnum from azure.identity import InteractiveBrowserCredential import traceback diff --git a/examples/integrations/__init__.py b/examples/integrations/__init__.py new file mode 100644 index 0000000..a560121 --- /dev/null +++ b/examples/integrations/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Integration examples with other Microsoft services and tools.""" \ No newline at end of file diff --git a/examples/utilities/__init__.py b/examples/utilities/__init__.py new file mode 100644 index 0000000..cee65bd --- /dev/null +++ b/examples/utilities/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Utility scripts and helper tools for Dataverse operations.""" \ No newline at end of file diff --git a/src/dataverse_sdk/client.py b/src/dataverse_sdk/client.py index 055622e..99dcbde 100644 --- a/src/dataverse_sdk/client.py +++ b/src/dataverse_sdk/client.py @@ -7,9 +7,9 @@ from azure.core.credentials import TokenCredential -from .auth import AuthManager -from .config import DataverseConfig -from .odata import ODataClient +from .core.auth import AuthManager +from .core.config import DataverseConfig +from .data.odata import ODataClient class DataverseClient: diff --git a/src/dataverse_sdk/core/__init__.py b/src/dataverse_sdk/core/__init__.py new file mode 100644 index 0000000..ccf2a6e --- /dev/null +++ b/src/dataverse_sdk/core/__init__.py @@ -0,0 +1,32 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +""" +Core infrastructure components for the Dataverse SDK. + +This module contains the foundational components including authentication, +configuration, HTTP client, and error handling. +""" + +from .auth import AuthManager, TokenPair +from .config import DataverseConfig +from .errors import ( + DataverseError, + HttpError, + ValidationError, + MetadataError, + SQLParseError, +) +from .http import HttpClient + +__all__ = [ + "AuthManager", + "TokenPair", + "DataverseConfig", + "DataverseError", + "HttpError", + "ValidationError", + "MetadataError", + "SQLParseError", + "HttpClient", +] \ No newline at end of file diff --git a/src/dataverse_sdk/auth.py b/src/dataverse_sdk/core/auth.py similarity index 100% rename from src/dataverse_sdk/auth.py rename to src/dataverse_sdk/core/auth.py diff --git a/src/dataverse_sdk/config.py b/src/dataverse_sdk/core/config.py similarity index 100% rename from src/dataverse_sdk/config.py rename to src/dataverse_sdk/core/config.py diff --git a/src/dataverse_sdk/error_codes.py b/src/dataverse_sdk/core/error_codes.py similarity index 100% rename from src/dataverse_sdk/error_codes.py rename to src/dataverse_sdk/core/error_codes.py diff --git a/src/dataverse_sdk/errors.py b/src/dataverse_sdk/core/errors.py similarity index 100% rename from src/dataverse_sdk/errors.py rename to src/dataverse_sdk/core/errors.py diff --git a/src/dataverse_sdk/http.py b/src/dataverse_sdk/core/http.py similarity index 100% rename from src/dataverse_sdk/http.py rename to src/dataverse_sdk/core/http.py diff --git a/src/dataverse_sdk/data/__init__.py b/src/dataverse_sdk/data/__init__.py new file mode 100644 index 0000000..a5854b8 --- /dev/null +++ b/src/dataverse_sdk/data/__init__.py @@ -0,0 +1,14 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +""" +Data access layer for the Dataverse SDK. + +This module contains OData protocol handling, CRUD operations, metadata management, +SQL query functionality, and file upload capabilities. +""" + +from .odata import ODataClient +from .upload import ODataFileUpload + +__all__ = ["ODataClient", "ODataFileUpload"] \ No newline at end of file diff --git a/src/dataverse_sdk/odata.py b/src/dataverse_sdk/data/odata.py similarity index 99% rename from src/dataverse_sdk/odata.py rename to src/dataverse_sdk/data/odata.py index bf1755c..87551c3 100644 --- a/src/dataverse_sdk/odata.py +++ b/src/dataverse_sdk/data/odata.py @@ -12,10 +12,10 @@ from datetime import datetime, timezone import importlib.resources as ir -from .http import HttpClient -from .odata_upload_files import ODataFileUpload -from .errors import * -from . import error_codes as ec +from ..core.http import HttpClient +from .upload import ODataFileUpload +from ..core.errors import * +from ..core import error_codes as ec _GUID_RE = re.compile(r"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}") @@ -40,7 +40,7 @@ def __init__( if not self.base_url: raise ValueError("base_url is required.") self.api = f"{self.base_url}/api/data/v9.2" - self.config = config or __import__("dataverse_sdk.config", fromlist=["DataverseConfig"]).DataverseConfig.from_env() + self.config = config or __import__("dataverse_sdk.core.config", fromlist=["DataverseConfig"]).DataverseConfig.from_env() self._http = HttpClient( retries=self.config.http_retries, backoff=self.config.http_backoff, diff --git a/src/dataverse_sdk/odata_upload_files.py b/src/dataverse_sdk/data/upload.py similarity index 100% rename from src/dataverse_sdk/odata_upload_files.py rename to src/dataverse_sdk/data/upload.py diff --git a/src/dataverse_sdk/extensions/__init__.py b/src/dataverse_sdk/extensions/__init__.py new file mode 100644 index 0000000..2a69d30 --- /dev/null +++ b/src/dataverse_sdk/extensions/__init__.py @@ -0,0 +1,12 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +""" +Optional extensions for the Dataverse SDK. + +This module contains optional features like CLI interfaces, async clients, +and other extended functionality. +""" + +# Will be populated with extensions as they are created +__all__ = [] \ No newline at end of file diff --git a/src/dataverse_sdk/models/__init__.py b/src/dataverse_sdk/models/__init__.py new file mode 100644 index 0000000..c6c679e --- /dev/null +++ b/src/dataverse_sdk/models/__init__.py @@ -0,0 +1,12 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +""" +Data models and type definitions for the Dataverse SDK. + +This module contains entity models, response models, enums, and other +type definitions used throughout the SDK. +""" + +# Will be populated with models as they are created +__all__ = [] \ No newline at end of file diff --git a/src/dataverse_sdk/utils/__init__.py b/src/dataverse_sdk/utils/__init__.py new file mode 100644 index 0000000..e524cc1 --- /dev/null +++ b/src/dataverse_sdk/utils/__init__.py @@ -0,0 +1,13 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +""" +Utilities and adapters for the Dataverse SDK. + +This module contains helper functions, adapters (like Pandas integration), +logging utilities, and validation helpers. +""" + +from .pandas_adapter import PandasODataClient + +__all__ = ["PandasODataClient"] \ No newline at end of file diff --git a/src/dataverse_sdk/odata_pandas_wrappers.py b/src/dataverse_sdk/utils/pandas_adapter.py similarity index 99% rename from src/dataverse_sdk/odata_pandas_wrappers.py rename to src/dataverse_sdk/utils/pandas_adapter.py index 185a9fc..a98854d 100644 --- a/src/dataverse_sdk/odata_pandas_wrappers.py +++ b/src/dataverse_sdk/utils/pandas_adapter.py @@ -17,7 +17,7 @@ import pandas as pd -from .odata import ODataClient +from ..data.odata import ODataClient @dataclass diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..cdfc326 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Test package for the Dataverse SDK.""" \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..68661e3 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,65 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +""" +Shared pytest fixtures and configuration for Dataverse SDK tests. + +This module provides common test fixtures, mock objects, and configuration +that can be used across all test modules. +""" + +import pytest +from unittest.mock import Mock +from dataverse_sdk.core.config import DataverseConfig + + +@pytest.fixture +def dummy_auth(): + """Mock authentication object for testing.""" + class DummyAuth: + def acquire_token(self, scope): + class Token: + access_token = "test_token_12345" + return Token() + return DummyAuth() + + +@pytest.fixture +def test_config(): + """Test configuration with safe defaults.""" + return DataverseConfig( + language_code=1033, + http_retries=0, + http_backoff=0.1, + http_timeout=5 + ) + + +@pytest.fixture +def mock_http_client(): + """Mock HTTP client for unit tests.""" + mock = Mock() + mock.request.return_value = Mock() + return mock + + +@pytest.fixture +def sample_base_url(): + """Standard test base URL.""" + return "https://org.example.com" + + +@pytest.fixture +def sample_entity_data(): + """Sample entity data for testing.""" + return { + "name": "Test Account", + "telephone1": "555-0100", + "websiteurl": "https://example.com" + } + + +@pytest.fixture +def sample_guid(): + """Sample GUID for testing.""" + return "11111111-2222-3333-4444-555555555555" \ No newline at end of file diff --git a/tests/fixtures/test_data.py b/tests/fixtures/test_data.py new file mode 100644 index 0000000..3e2fc73 --- /dev/null +++ b/tests/fixtures/test_data.py @@ -0,0 +1,69 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +""" +Sample test data and fixtures for Dataverse SDK tests. + +This module contains reusable test data, mock responses, and fixtures +that can be used across different test modules. +""" + +# Sample entity metadata response +SAMPLE_ENTITY_METADATA = { + "value": [ + { + "LogicalName": "account", + "EntitySetName": "accounts", + "PrimaryIdAttribute": "accountid", + "DisplayName": {"UserLocalizedLabel": {"Label": "Account"}} + }, + { + "LogicalName": "contact", + "EntitySetName": "contacts", + "PrimaryIdAttribute": "contactid", + "DisplayName": {"UserLocalizedLabel": {"Label": "Contact"}} + } + ] +} + +# Sample OData response for accounts +SAMPLE_ACCOUNTS_RESPONSE = { + "value": [ + { + "accountid": "11111111-2222-3333-4444-555555555555", + "name": "Contoso Ltd", + "telephone1": "555-0100", + "websiteurl": "https://contoso.com" + }, + { + "accountid": "22222222-3333-4444-5555-666666666666", + "name": "Fabrikam Inc", + "telephone1": "555-0200", + "websiteurl": "https://fabrikam.com" + } + ] +} + +# Sample error responses +SAMPLE_ERROR_RESPONSES = { + "404": { + "error": { + "code": "0x80040217", + "message": "The requested resource was not found." + } + }, + "429": { + "error": { + "code": "0x80072321", + "message": "Too many requests. Please retry after some time." + } + } +} + +# Sample SQL query results +SAMPLE_SQL_RESPONSE = { + "value": [ + {"name": "Account 1", "revenue": 1000000}, + {"name": "Account 2", "revenue": 2000000} + ] +} \ No newline at end of file diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py new file mode 100644 index 0000000..db34dfb --- /dev/null +++ b/tests/integration/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Integration tests for the Dataverse SDK.""" \ No newline at end of file diff --git a/tests/unit/__init__.py b/tests/unit/__init__.py new file mode 100644 index 0000000..bce68aa --- /dev/null +++ b/tests/unit/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Unit tests for the Dataverse SDK.""" \ No newline at end of file diff --git a/tests/unit/core/__init__.py b/tests/unit/core/__init__.py new file mode 100644 index 0000000..b3b8cd6 --- /dev/null +++ b/tests/unit/core/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Unit tests for core infrastructure components.""" \ No newline at end of file diff --git a/tests/test_http_errors.py b/tests/unit/core/test_http_errors.py similarity index 94% rename from tests/test_http_errors.py rename to tests/unit/core/test_http_errors.py index fd08d33..4c3a0e0 100644 --- a/tests/test_http_errors.py +++ b/tests/unit/core/test_http_errors.py @@ -2,9 +2,9 @@ # Licensed under the MIT license. import pytest -from dataverse_sdk.errors import HttpError -from dataverse_sdk import error_codes as ec -from dataverse_sdk.odata import ODataClient +from dataverse_sdk.core.errors import HttpError +from dataverse_sdk.core import error_codes as ec +from dataverse_sdk.data.odata import ODataClient class DummyAuth: def acquire_token(self, scope): diff --git a/tests/unit/data/__init__.py b/tests/unit/data/__init__.py new file mode 100644 index 0000000..c0c3a00 --- /dev/null +++ b/tests/unit/data/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Unit tests for data access components.""" \ No newline at end of file diff --git a/tests/test_enum_optionset_payload.py b/tests/unit/data/test_enum_optionset_payload.py similarity index 99% rename from tests/test_enum_optionset_payload.py rename to tests/unit/data/test_enum_optionset_payload.py index 5d85ddb..ca58a38 100644 --- a/tests/test_enum_optionset_payload.py +++ b/tests/unit/data/test_enum_optionset_payload.py @@ -4,7 +4,7 @@ import pytest from enum import Enum, IntEnum -from dataverse_sdk.odata import ODataClient +from dataverse_sdk.data.odata import ODataClient class DummyAuth: def acquire_token(self, scope): # pragma: no cover - simple stub diff --git a/tests/test_logical_crud.py b/tests/unit/data/test_logical_crud.py similarity index 97% rename from tests/test_logical_crud.py rename to tests/unit/data/test_logical_crud.py index 58ad3f6..c3233ea 100644 --- a/tests/test_logical_crud.py +++ b/tests/unit/data/test_logical_crud.py @@ -3,8 +3,8 @@ import types import pytest -from dataverse_sdk.odata import ODataClient -from dataverse_sdk.errors import MetadataError +from dataverse_sdk.data.odata import ODataClient +from dataverse_sdk.core.errors import MetadataError class DummyAuth: def acquire_token(self, scope): diff --git a/tests/test_sql_parse.py b/tests/unit/data/test_sql_parse.py similarity index 96% rename from tests/test_sql_parse.py rename to tests/unit/data/test_sql_parse.py index 68049f7..5850476 100644 --- a/tests/test_sql_parse.py +++ b/tests/unit/data/test_sql_parse.py @@ -2,7 +2,7 @@ # Licensed under the MIT license. import pytest -from dataverse_sdk.odata import ODataClient +from dataverse_sdk.data.odata import ODataClient class DummyAuth: def acquire_token(self, scope): diff --git a/tests/unit/utils/__init__.py b/tests/unit/utils/__init__.py new file mode 100644 index 0000000..7bed24e --- /dev/null +++ b/tests/unit/utils/__init__.py @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT license. + +"""Unit tests for utility components.""" \ No newline at end of file From c645173259874a8331160565d4137b46347e92d5 Mon Sep 17 00:00:00 2001 From: Suyash Kshirsagar Date: Fri, 7 Nov 2025 14:04:00 -0800 Subject: [PATCH 2/2] clean: Remove placeholder directories from examples - Remove examples/integrations/ folder (was empty placeholder) - Remove examples/utilities/ folder (was empty placeholder) - Keep only examples/basic/ and examples/advanced/ with actual working examples - Maintains cleaner structure focused on real functionality --- examples/README.md | 16 ---------------- examples/integrations/__init__.py | 4 ---- examples/utilities/__init__.py | 4 ---- 3 files changed, 24 deletions(-) delete mode 100644 examples/integrations/__init__.py delete mode 100644 examples/utilities/__init__.py diff --git a/examples/README.md b/examples/README.md index 54e9a18..1976079 100644 --- a/examples/README.md +++ b/examples/README.md @@ -15,22 +15,6 @@ Get started quickly with fundamental Dataverse operations: Explore powerful features for complex scenarios: - **`file_upload.py`** - File upload to Dataverse file columns with chunking - **`pandas_integration.py`** - DataFrame-based operations for data analysis -- **`bulk_operations.py`** - Batch processing and bulk data operations -- **`metadata_management.py`** - Creating and managing custom tables -- **`sql_queries.py`** - Advanced SQL queries via Web API - -### 🔗 Integrations (`integrations/`) -Connect Dataverse with other Microsoft services: -- **`power_automate.py`** - Integration patterns with Power Automate -- **`azure_functions.py`** - Using the SDK in Azure Functions -- Power BI integration examples -- Azure Logic Apps patterns - -### 🛠️ Utilities (`utilities/`) -Helper scripts and development tools: -- **`connection_tester.py`** - Test and validate Dataverse connections -- **`data_migration.py`** - Scripts for data migration scenarios -- Development and debugging utilities ## 🚀 Getting Started diff --git a/examples/integrations/__init__.py b/examples/integrations/__init__.py deleted file mode 100644 index a560121..0000000 --- a/examples/integrations/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. - -"""Integration examples with other Microsoft services and tools.""" \ No newline at end of file diff --git a/examples/utilities/__init__.py b/examples/utilities/__init__.py deleted file mode 100644 index cee65bd..0000000 --- a/examples/utilities/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT license. - -"""Utility scripts and helper tools for Dataverse operations.""" \ No newline at end of file