demo_uc_setup 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -0,0 +1,49 @@
1
+ import logging
2
+ from typing import TypeVar, Generic
3
+ from databricks.sdk import WorkspaceClient
4
+
5
+ from demo_uc_setup.config import Config
6
+
7
+ # Example of a type variable bound to our Config class
8
+ T = TypeVar("T", bound=Config)
9
+
10
+ class Task(Generic[T]):
11
+ """
12
+ A reusable Task base class that works both locally and in Databricks notebooks.
13
+ When running locally, requires databricks_host and databricks_token.
14
+ When running in a notebook, these parameters are optional.
15
+ """
16
+
17
+ def __init__(self, config_class: type[T]):
18
+ # Instantiate the typed configuration
19
+ self.config: T = config_class()
20
+ # Setup a basic logger
21
+ self.logger = logging.getLogger(self.__class__.__name__)
22
+ logging.basicConfig(level=logging.INFO)
23
+
24
+ # Create a Databricks workspace client with or without credentials
25
+ if self.config.databricks_host and self.config.databricks_token:
26
+ # Local execution with credentials
27
+ self.workspace_client = WorkspaceClient(
28
+ host=self.config.databricks_host,
29
+ token=self.config.databricks_token
30
+ )
31
+ else:
32
+ # Notebook execution - no credentials needed
33
+ self.workspace_client = WorkspaceClient()
34
+
35
+ @classmethod
36
+ def entrypoint(cls, *args, **kwargs):
37
+ """
38
+ Creates an instance of the task and runs it. If you
39
+ want a consistent run pattern, place it here.
40
+ """
41
+ instance = cls(*args, **kwargs)
42
+ instance.run()
43
+
44
+ def run(self):
45
+ """
46
+ The main entrypoint for the task's execution.
47
+ Override this in subclasses to implement custom logic.
48
+ """
49
+ self.logger.info("Base Task run method. Override in subclasses.")
@@ -0,0 +1,23 @@
1
+ from pydantic_settings import BaseSettings
2
+ from typing import Optional
3
+
4
+ class Config(BaseSettings):
5
+ """
6
+ Configuration class using Pydantic BaseSettings.
7
+ By default, each field can be overridden by environment
8
+ variables matching the field name (in uppercase).
9
+ For example, DATABRICKS_HOST, DATABRICKS_TOKEN, etc.
10
+ """
11
+
12
+ # Databricks connection settings - optional for notebook execution
13
+ databricks_host: Optional[str] = None
14
+ databricks_token: Optional[str] = None
15
+
16
+ # Default names for Unity Catalog demo objects
17
+ demo_catalog_name: str = "demo_catalog"
18
+ demo_schemas: list[str] = ["demo_schema_1", "demo_schema_2"] # List of schemas
19
+ demo_volume_name: str = "demo_volume" # This could also be a list if needed
20
+
21
+ class Config:
22
+ env_file = ".env" # or any custom file, if desired
23
+ env_file_encoding = "utf-8"
@@ -0,0 +1,82 @@
1
+ from typing import Type
2
+ from databricks.sdk.service import catalog
3
+ from demo_uc_setup.common import Task, T
4
+ from demo_uc_setup.config import Config
5
+
6
+ class UnityCatalogSetupTask(Task[Config]):
7
+ """
8
+ A task to ensure catalogs, schemas, and volumes exist
9
+ in the Databricks workspace. Uses typed config for
10
+ resource names, credentials, etc.
11
+ """
12
+
13
+ def __init__(self, config_class: Type[T] = Config):
14
+ super().__init__(config_class)
15
+
16
+ def run(self):
17
+ self.logger.info("Starting Unity Catalog setup...")
18
+
19
+ # 1) Ensure the catalog exists
20
+ catalog_name = self.config.demo_catalog_name
21
+ self.logger.info(f"Ensuring catalog '{catalog_name}'")
22
+ try:
23
+ self.workspace_client.catalogs.get(name=catalog_name)
24
+ self.logger.info(f"Catalog '{catalog_name}' already exists.")
25
+ except Exception:
26
+ self.logger.info(f"Catalog '{catalog_name}' not found; creating it.")
27
+ self.workspace_client.catalogs.create(
28
+ name=catalog_name,
29
+ comment="Demo Catalog for Databricks demos"
30
+ )
31
+
32
+ # 2) Ensure all schemas exist and create volumes within each schema
33
+ for schema_name in self.config.demo_schemas:
34
+ # Create schema
35
+ self.logger.info(f"Ensuring schema '{catalog_name}.{schema_name}'")
36
+ try:
37
+ self.workspace_client.schemas.get(
38
+ name=schema_name,
39
+ catalog_name=catalog_name
40
+ )
41
+ self.logger.info(f"Schema '{catalog_name}.{schema_name}' already exists.")
42
+ except Exception:
43
+ try:
44
+ self.logger.info(f"Schema '{catalog_name}.{schema_name}' not found; creating it.")
45
+ self.workspace_client.schemas.create(
46
+ name=schema_name,
47
+ catalog_name=catalog_name,
48
+ comment=f"Demo Schema {schema_name} for Databricks demos"
49
+ )
50
+ except Exception as e:
51
+ if "already exists" in str(e):
52
+ self.logger.info(f"Schema '{catalog_name}.{schema_name}' already exists (caught during creation).")
53
+ else:
54
+ raise e
55
+
56
+ # Create volume within this schema
57
+ volume_name = self.config.demo_volume_name
58
+ self.logger.info(f"Ensuring volume '{catalog_name}.{schema_name}.{volume_name}'")
59
+ try:
60
+ self.workspace_client.volumes.get(
61
+ name=volume_name,
62
+ catalog_name=catalog_name,
63
+ schema_name=schema_name
64
+ )
65
+ self.logger.info(f"Volume '{catalog_name}.{schema_name}.{volume_name}' already exists.")
66
+ except Exception:
67
+ try:
68
+ self.logger.info(f"Volume '{catalog_name}.{schema_name}.{volume_name}' not found; creating it.")
69
+ self.workspace_client.volumes.create(
70
+ name=volume_name,
71
+ catalog_name=catalog_name,
72
+ schema_name=schema_name,
73
+ volume_type=catalog.VolumeType.MANAGED,
74
+ comment=f"Demo Volume for schema {schema_name}"
75
+ )
76
+ except Exception as e:
77
+ if "already exists" in str(e):
78
+ self.logger.info(f"Volume '{catalog_name}.{schema_name}.{volume_name}' already exists (caught during creation).")
79
+ else:
80
+ raise e
81
+
82
+ self.logger.info("Unity Catalog setup complete!")
@@ -0,0 +1,28 @@
1
+ from typing import Type
2
+ from databricks.sdk import WorkspaceClient
3
+ from demo_uc_setup.common import Task, T
4
+ from demo_uc_setup.config import Config
5
+
6
+ class UnityCatalogTeardownTask(Task[Config]):
7
+ """
8
+ A task to delete (teardown) the Unity Catalog resources in
9
+ the configured Databricks workspace. Uses typed config for
10
+ resource names, credentials, etc.
11
+ """
12
+
13
+ def __init__(self, config_class: Type[T] = Config):
14
+ super().__init__(config_class)
15
+
16
+ def run(self):
17
+ self.logger.info("Starting teardown of Unity Catalog resources...")
18
+
19
+ catalog_name = self.config.demo_catalog_name
20
+ self.logger.info(f"Deleting catalog '{catalog_name}' and its dependencies (force=True).")
21
+
22
+ try:
23
+ self.workspace_client.catalogs.delete(name=catalog_name, force=True)
24
+ self.logger.info(f"Catalog '{catalog_name}' (and its contents) successfully deleted.")
25
+ except Exception as e:
26
+ self.logger.error(f"Failed to delete catalog '{catalog_name}'. Reason: {e}")
27
+
28
+ self.logger.info("Unity Catalog teardown complete!")
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: demo_uc_setup
3
+ Version: 0.1.0
4
+ Summary: A reusable task-based framework for managing Unity Catalog in Databricks
5
+ Requires-Python: >=3.11
6
+ Requires-Dist: databricks-connect>=16.1.1
7
+ Requires-Dist: databricks-sdk>=0.44.1
8
+ Requires-Dist: pydantic-settings>=2.8.0
9
+ Requires-Dist: pydantic>=2.10.6
10
+ Description-Content-Type: text/markdown
11
+
12
+ # Databricks Unity Catalog Setup Demo
13
+
14
+ A Python package that demonstrates automated setup and teardown of Databricks Unity Catalog resources using the Databricks SDK. This package provides a reusable framework for managing Unity Catalog resources programmatically, both from local environments and within Databricks notebooks.
15
+
16
+ ## Features
17
+
18
+ - Automated creation of Unity Catalog resources:
19
+ - Catalogs
20
+ - Schemas
21
+ - Volumes
22
+ - Configurable resource naming via environment variables
23
+ - Support for both local execution and Databricks notebook execution
24
+ - Type-safe configuration management using Pydantic
25
+ - Clean teardown functionality
26
+
27
+ ## Prerequisites
28
+
29
+ - Python 3.8+
30
+ - A Databricks workspace with Unity Catalog enabled
31
+ - Appropriate permissions to create/manage Unity Catalog resources
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ pip install demo-uc-setup
37
+ ```
38
+
39
+ ## Configuration
40
+
41
+ The package uses environment variables for configuration. You can set these either in your environment or in a `.env` file:
42
+
43
+ ```env
44
+ # Required for local execution (optional in Databricks notebooks)
45
+ DATABRICKS_HOST=your-workspace-url
46
+ DATABRICKS_TOKEN=your-pat-token
47
+
48
+ # Optional - override default resource names
49
+ DEMO_CATALOG_NAME=custom_catalog_name
50
+ DEMO_SCHEMAS=["schema1", "schema2"]
51
+ DEMO_VOLUME_NAME=custom_volume_name
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ### Local Execution
57
+
58
+ ```python
59
+ from demo_uc_setup.unity_catalog_setup import UnityCatalogSetupTask
60
+ from demo_uc_setup.unity_catalog_teardown import UnityCatalogTeardownTask
61
+
62
+ # Setup Unity Catalog resources
63
+ UnityCatalogSetupTask.entrypoint()
64
+
65
+ # Teardown Unity Catalog resources
66
+ UnityCatalogTeardownTask.entrypoint()
67
+ ```
68
+
69
+ ### Databricks Notebook Execution
70
+
71
+ ```python
72
+ %pip install demo-uc-setup
73
+
74
+ from demo_uc_setup.unity_catalog_setup import UnityCatalogSetupTask
75
+ UnityCatalogSetupTask.entrypoint()
76
+ ```
77
+
78
+ ## Default Resource Names
79
+
80
+ If not overridden via environment variables, the package will create:
81
+ - A catalog named `demo_catalog`
82
+ - Two schemas: `demo_schema_1` and `demo_schema_2`
83
+ - A volume named `demo_volume` in each schema
84
+
85
+ ## Extending the Framework
86
+
87
+ The package provides a reusable `Task` base class that can be extended for custom Unity Catalog operations:
88
+
89
+ ```python
90
+ from demo_uc_setup.common import Task
91
+ from demo_uc_setup.config import Config
92
+
93
+ class CustomTask(Task[Config]):
94
+ def run(self):
95
+ self.logger.info("Starting custom task...")
96
+ # Your custom logic here
97
+ ```
98
+
99
+ ## Contributing
100
+
101
+ Contributions are welcome! Please feel free to submit a Pull Request.
102
+
103
+ ## License
104
+
105
+ This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,8 @@
1
+ demo_uc_setup/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ demo_uc_setup/common.py,sha256=r5v-nUh7EoGsR4ecQi-pA9NJVRyJlRgOtc_9JxQWjxs,1754
3
+ demo_uc_setup/config.py,sha256=Jwl5anXQ6Ceq-hRyjZ9gUtBaC3iqqJXZCkLjNYjny1o,873
4
+ demo_uc_setup/unity_catalog_setup.py,sha256=3jfIlS9_nxJpXcoGbXJ2Pj4EefqAlpo-GTV8MShoa1w,3680
5
+ demo_uc_setup/unity_catalog_teardown.py,sha256=jHcT4iWeyUIlFDhvUGSfTW2RAYL7d-0sW4VU_uLuRd4,1095
6
+ demo_uc_setup-0.1.0.dist-info/METADATA,sha256=aVkYiBtNuljFYng3CL2JPMLbzkBupHhFYMRiEBDLRjc,2934
7
+ demo_uc_setup-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
8
+ demo_uc_setup-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any