surfdataverse 1.1.5__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.
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.3
2
+ Name: surfdataverse
3
+ Version: 1.1.5
4
+ Summary: A Python package for ionysis Microsoft Dataverse integration
5
+ Keywords: dataverse,microsoft,crm,api
6
+ Author: ionysis
7
+ Author-email: ionysis <friedemann.heinz@ionysis.com>
8
+ License: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Requires-Dist: msal>=1.33.0
18
+ Requires-Dist: pandas>=2.3.2
19
+ Requires-Dist: requests>=2.32.5
20
+ Requires-Python: >=3.11
21
+ Project-URL: Bug Tracker, https://github.com/FriedemannHeinz/SurfDataverse/issues
22
+ Project-URL: Documentation, https://github.com/FriedemannHeinz/SurfDataverse#readme
23
+ Project-URL: Homepage, https://github.com/FriedemannHeinz/SurfDataverse
24
+ Project-URL: Repository, https://github.com/FriedemannHeinz/SurfDataverse.git
25
+ Description-Content-Type: text/markdown
26
+
27
+ # SurfDataverse
28
+
29
+ A Python package for Microsoft Dataverse integration, providing a clean, object-oriented interface for connecting to, reading from, and writing to Microsoft Dataverse environments.
30
+
31
+ ## Features
32
+
33
+ - **Easy Authentication**: Simplified MSAL-based authentication with token caching
34
+ - **Object-Oriented Interface**: Work with Dataverse entities as Python objects
35
+ - **Type Safety**: Built-in validation and error handling
36
+ - **Configurable**: Support for multiple environments and configurations
37
+ - **Extensible**: Easy to add new entity types and customize behavior
38
+
39
+ ## Installation
40
+
41
+ ### From Source
42
+ ```bash
43
+ git clone https://github.com/FriedemannHeinz/SurfDataverse.git
44
+ cd SurfDataverse
45
+ pip install -e .
46
+ ```
47
+
48
+ ### Dependencies
49
+ ```bash
50
+ pip install -r requirements.txt
51
+ ```
52
+
53
+ ## Quick Start
54
+
55
+ ### 1. Configuration
56
+
57
+ Create a configuration JSON file with your Dataverse connection details:
58
+
59
+ ```json
60
+ {
61
+ "authorityBase": "https://login.microsoftonline.com/",
62
+ "tenantID": "your-tenant-id",
63
+ "clientID": "your-client-id",
64
+ "environmentURI": "https://yourorg.crm.dynamics.com/",
65
+ "scopeSuffix": "/.default"
66
+ }
67
+ ```
68
+
69
+ ### 2. Basic Usage
70
+
71
+ ```python
72
+ from surf_dataverse import DataverseSession, Article, Recipe
73
+ from pathlib import Path
74
+
75
+ # Initialize session
76
+ config_path = Path("connection_configs/your_config.json")
77
+ session = DataverseSession(config_path=config_path)
78
+
79
+ # Authenticate
80
+ session.get_authenticated_session()
81
+
82
+ # Test connection
83
+ session.test_connection()
84
+
85
+ # Create and work with entities
86
+ article = Article()
87
+ article.name = "My Product"
88
+ article.company = "My Company"
89
+ article.external_article_nr = "EXT-001"
90
+
91
+ # Write to Dataverse
92
+ article.write_to_dataverse()
93
+ print(f"Created article with GUID: {article.guid}")
94
+ ```
95
+
96
+ ## Available Entities
97
+
98
+ The package includes pre-built entity classes for:
99
+
100
+ - **Article**: Product/item management
101
+ - **Recipe**: Production recipes and formulations
102
+ - **Ingredient**: Recipe components and quantities
103
+ - **Process**: Manufacturing processes
104
+ - **Batch**: Production batches and lots
105
+ - **Fabrication**: Manufacturing operations
106
+ - **Consumption**: Resource consumption tracking
107
+ - **Property**: Entity properties and attributes
108
+
109
+ ## Entity Properties
110
+
111
+ Each entity provides property-based access to Dataverse fields:
112
+
113
+ ```python
114
+ # Data properties (simple text/numeric fields)
115
+ article.name = "Product Name"
116
+ article.company = "Company Name"
117
+
118
+ # Lookup properties (relationships to other entities)
119
+ ingredient.article = article_guid # Links to Article entity
120
+ ingredient.recipe = recipe_guid # Links to Recipe entity
121
+
122
+ # Choice properties (option sets)
123
+ recipe.type = "Production" # Maps to numeric choice value
124
+ ```
125
+
126
+ ## Error Handling
127
+
128
+ The package provides comprehensive error handling:
129
+
130
+ ```python
131
+ from surf_dataverse import (
132
+ AuthenticationError,
133
+ ConnectionError,
134
+ DataverseAPIError,
135
+ EntityError,
136
+ ValidationError
137
+ )
138
+
139
+ try:
140
+ session.get_authenticated_session()
141
+ article.write_to_dataverse()
142
+ except AuthenticationError as e:
143
+ print(f"Authentication failed: {e}")
144
+ except DataverseAPIError as e:
145
+ print(f"API error (status {e.status_code}): {e}")
146
+ except ValidationError as e:
147
+ print(f"Data validation error: {e}")
148
+ ```
149
+
150
+ ## Advanced Usage
151
+
152
+ ### Custom Entity Classes
153
+
154
+ Extend `DataverseRow` to create custom entity classes:
155
+
156
+ ```python
157
+ from surf_dataverse import DataverseRow
158
+
159
+ class MyCustomEntity(DataverseRow):
160
+ def __init__(self):
161
+ super().__init__('my_custom_table')
162
+
163
+ # Define properties
164
+ name = DataverseRow.data_property('my_name_field')
165
+ category = DataverseRow.choice_property('my_category_field')
166
+ parent = DataverseRow.lookup_property('my_parent_field')
167
+ ```
168
+
169
+ ### Session Management
170
+
171
+ The `DataverseSession` uses a singleton pattern, so you can access the same session from anywhere:
172
+
173
+ ```python
174
+ # First initialization
175
+ session1 = DataverseSession(config_path="config1.json")
176
+
177
+ # Later access (returns same instance)
178
+ session2 = DataverseSession() # Same as session1
179
+ ```
180
+
181
+ ### Data Retrieval
182
+
183
+ Fetch data from Dataverse tables:
184
+
185
+ ```python
186
+ # Get table data as pandas DataFrame
187
+ df = session.get_table_data(logical_name="iony_article")
188
+
189
+ # Get specific record
190
+ record = session.get_record("articles", "guid-here")
191
+
192
+ # Get table metadata
193
+ metadata = session.get_table_metadata("iony_article")
194
+ ```
195
+
196
+ ## Development
197
+
198
+ ### Project Structure
199
+ ```
200
+ surf_dataverse/
201
+ ├── __init__.py # Package initialization
202
+ ├── core.py # Core session and entity classes
203
+ ├── entities.py # Pre-built entity definitions
204
+ └── exceptions.py # Custom exceptions
205
+
206
+ examples/
207
+ └── basic_usage.py # Usage examples
208
+
209
+ connection_configs/ # Configuration files (not tracked)
210
+ ├── dev.json
211
+ └── production.json
212
+ ```
213
+
214
+ ### Dependencies
215
+
216
+ - `msal`: Microsoft Authentication Library
217
+ - `requests`: HTTP client
218
+ - `pandas`: Data manipulation and analysis
219
+
220
+ ### Testing
221
+
222
+ ```bash
223
+ pytest tests/
224
+ ```
225
+
226
+ ### Code Style
227
+
228
+ ```bash
229
+ black surf_dataverse/
230
+ flake8 surf_dataverse/
231
+ ```
232
+
233
+ ## Contributing
234
+
235
+ 1. Fork the repository
236
+ 2. Create a feature branch
237
+ 3. Make your changes
238
+ 4. Add tests
239
+ 5. Submit a pull request
240
+
241
+ ## License
242
+
243
+ MIT License - see LICENSE file for details.
244
+
245
+ ## Support
246
+
247
+ For issues and questions:
248
+ - GitHub Issues: [https://github.com/FriedemannHeinz/SurfDataverse/issues](https://github.com/FriedemannHeinz/SurfDataverse/issues)
249
+ - Documentation: This README and inline code documentation
@@ -0,0 +1,223 @@
1
+ # SurfDataverse
2
+
3
+ A Python package for Microsoft Dataverse integration, providing a clean, object-oriented interface for connecting to, reading from, and writing to Microsoft Dataverse environments.
4
+
5
+ ## Features
6
+
7
+ - **Easy Authentication**: Simplified MSAL-based authentication with token caching
8
+ - **Object-Oriented Interface**: Work with Dataverse entities as Python objects
9
+ - **Type Safety**: Built-in validation and error handling
10
+ - **Configurable**: Support for multiple environments and configurations
11
+ - **Extensible**: Easy to add new entity types and customize behavior
12
+
13
+ ## Installation
14
+
15
+ ### From Source
16
+ ```bash
17
+ git clone https://github.com/FriedemannHeinz/SurfDataverse.git
18
+ cd SurfDataverse
19
+ pip install -e .
20
+ ```
21
+
22
+ ### Dependencies
23
+ ```bash
24
+ pip install -r requirements.txt
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Configuration
30
+
31
+ Create a configuration JSON file with your Dataverse connection details:
32
+
33
+ ```json
34
+ {
35
+ "authorityBase": "https://login.microsoftonline.com/",
36
+ "tenantID": "your-tenant-id",
37
+ "clientID": "your-client-id",
38
+ "environmentURI": "https://yourorg.crm.dynamics.com/",
39
+ "scopeSuffix": "/.default"
40
+ }
41
+ ```
42
+
43
+ ### 2. Basic Usage
44
+
45
+ ```python
46
+ from surf_dataverse import DataverseSession, Article, Recipe
47
+ from pathlib import Path
48
+
49
+ # Initialize session
50
+ config_path = Path("connection_configs/your_config.json")
51
+ session = DataverseSession(config_path=config_path)
52
+
53
+ # Authenticate
54
+ session.get_authenticated_session()
55
+
56
+ # Test connection
57
+ session.test_connection()
58
+
59
+ # Create and work with entities
60
+ article = Article()
61
+ article.name = "My Product"
62
+ article.company = "My Company"
63
+ article.external_article_nr = "EXT-001"
64
+
65
+ # Write to Dataverse
66
+ article.write_to_dataverse()
67
+ print(f"Created article with GUID: {article.guid}")
68
+ ```
69
+
70
+ ## Available Entities
71
+
72
+ The package includes pre-built entity classes for:
73
+
74
+ - **Article**: Product/item management
75
+ - **Recipe**: Production recipes and formulations
76
+ - **Ingredient**: Recipe components and quantities
77
+ - **Process**: Manufacturing processes
78
+ - **Batch**: Production batches and lots
79
+ - **Fabrication**: Manufacturing operations
80
+ - **Consumption**: Resource consumption tracking
81
+ - **Property**: Entity properties and attributes
82
+
83
+ ## Entity Properties
84
+
85
+ Each entity provides property-based access to Dataverse fields:
86
+
87
+ ```python
88
+ # Data properties (simple text/numeric fields)
89
+ article.name = "Product Name"
90
+ article.company = "Company Name"
91
+
92
+ # Lookup properties (relationships to other entities)
93
+ ingredient.article = article_guid # Links to Article entity
94
+ ingredient.recipe = recipe_guid # Links to Recipe entity
95
+
96
+ # Choice properties (option sets)
97
+ recipe.type = "Production" # Maps to numeric choice value
98
+ ```
99
+
100
+ ## Error Handling
101
+
102
+ The package provides comprehensive error handling:
103
+
104
+ ```python
105
+ from surf_dataverse import (
106
+ AuthenticationError,
107
+ ConnectionError,
108
+ DataverseAPIError,
109
+ EntityError,
110
+ ValidationError
111
+ )
112
+
113
+ try:
114
+ session.get_authenticated_session()
115
+ article.write_to_dataverse()
116
+ except AuthenticationError as e:
117
+ print(f"Authentication failed: {e}")
118
+ except DataverseAPIError as e:
119
+ print(f"API error (status {e.status_code}): {e}")
120
+ except ValidationError as e:
121
+ print(f"Data validation error: {e}")
122
+ ```
123
+
124
+ ## Advanced Usage
125
+
126
+ ### Custom Entity Classes
127
+
128
+ Extend `DataverseRow` to create custom entity classes:
129
+
130
+ ```python
131
+ from surf_dataverse import DataverseRow
132
+
133
+ class MyCustomEntity(DataverseRow):
134
+ def __init__(self):
135
+ super().__init__('my_custom_table')
136
+
137
+ # Define properties
138
+ name = DataverseRow.data_property('my_name_field')
139
+ category = DataverseRow.choice_property('my_category_field')
140
+ parent = DataverseRow.lookup_property('my_parent_field')
141
+ ```
142
+
143
+ ### Session Management
144
+
145
+ The `DataverseSession` uses a singleton pattern, so you can access the same session from anywhere:
146
+
147
+ ```python
148
+ # First initialization
149
+ session1 = DataverseSession(config_path="config1.json")
150
+
151
+ # Later access (returns same instance)
152
+ session2 = DataverseSession() # Same as session1
153
+ ```
154
+
155
+ ### Data Retrieval
156
+
157
+ Fetch data from Dataverse tables:
158
+
159
+ ```python
160
+ # Get table data as pandas DataFrame
161
+ df = session.get_table_data(logical_name="iony_article")
162
+
163
+ # Get specific record
164
+ record = session.get_record("articles", "guid-here")
165
+
166
+ # Get table metadata
167
+ metadata = session.get_table_metadata("iony_article")
168
+ ```
169
+
170
+ ## Development
171
+
172
+ ### Project Structure
173
+ ```
174
+ surf_dataverse/
175
+ ├── __init__.py # Package initialization
176
+ ├── core.py # Core session and entity classes
177
+ ├── entities.py # Pre-built entity definitions
178
+ └── exceptions.py # Custom exceptions
179
+
180
+ examples/
181
+ └── basic_usage.py # Usage examples
182
+
183
+ connection_configs/ # Configuration files (not tracked)
184
+ ├── dev.json
185
+ └── production.json
186
+ ```
187
+
188
+ ### Dependencies
189
+
190
+ - `msal`: Microsoft Authentication Library
191
+ - `requests`: HTTP client
192
+ - `pandas`: Data manipulation and analysis
193
+
194
+ ### Testing
195
+
196
+ ```bash
197
+ pytest tests/
198
+ ```
199
+
200
+ ### Code Style
201
+
202
+ ```bash
203
+ black surf_dataverse/
204
+ flake8 surf_dataverse/
205
+ ```
206
+
207
+ ## Contributing
208
+
209
+ 1. Fork the repository
210
+ 2. Create a feature branch
211
+ 3. Make your changes
212
+ 4. Add tests
213
+ 5. Submit a pull request
214
+
215
+ ## License
216
+
217
+ MIT License - see LICENSE file for details.
218
+
219
+ ## Support
220
+
221
+ For issues and questions:
222
+ - GitHub Issues: [https://github.com/FriedemannHeinz/SurfDataverse/issues](https://github.com/FriedemannHeinz/SurfDataverse/issues)
223
+ - Documentation: This README and inline code documentation
@@ -0,0 +1,75 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.8.18,<0.9.0"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "surfdataverse"
7
+ version = "1.1.5"
8
+ description = "A Python package for ionysis Microsoft Dataverse integration"
9
+ readme = "README.md"
10
+ authors = [
11
+ {name = "ionysis", email = "friedemann.heinz@ionysis.com"}
12
+ ]
13
+ license = {text = "MIT"}
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: MIT License",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3.8",
20
+ "Programming Language :: Python :: 3.9",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ ]
24
+ keywords = ["dataverse", "microsoft", "crm", "api"]
25
+ requires-python = ">=3.11"
26
+ dependencies = [
27
+ "msal>=1.33.0",
28
+ "pandas>=2.3.2",
29
+ "requests>=2.32.5",
30
+ ]
31
+
32
+ [dependency-groups]
33
+ test = [
34
+ "pytest>=6.0",
35
+ "pytest-cov",
36
+ "pytest-mock",
37
+ "responses>=0.23.0"
38
+ ]
39
+ typing = [
40
+ "mypy>=1.0.0",
41
+ "types-requests",
42
+ "pandas-stubs"
43
+ ]
44
+ typing-test = [
45
+ {include-group = "typing"},
46
+ {include-group = "test"}
47
+ ]
48
+ dev = [
49
+ "ruff>=0.0.241",
50
+ "uv-build>=0.8.18",
51
+ ]
52
+
53
+ [project.urls]
54
+ Homepage = "https://github.com/FriedemannHeinz/SurfDataverse"
55
+ Repository = "https://github.com/FriedemannHeinz/SurfDataverse.git"
56
+ Documentation = "https://github.com/FriedemannHeinz/SurfDataverse#readme"
57
+ "Bug Tracker" = "https://github.com/FriedemannHeinz/SurfDataverse/issues"
58
+
59
+ [tool.setuptools.packages.find]
60
+ where = ["."]
61
+ include = ["surfdataverse*"]
62
+
63
+ [tool.ruff]
64
+ line-length = 100
65
+ target-version = "py311"
66
+
67
+ [tool.ruff.lint]
68
+ select = ["E", "F", "W", "I"] # Error, pyflakes, warnings, import sorting
69
+ ignore = ["E501"] # Line too long (handled by formatter)
70
+
71
+ [tool.pytest.ini_options]
72
+ testpaths = ["tests"]
73
+ python_files = ["test_*.py"]
74
+ python_classes = ["Test*"]
75
+ python_functions = ["test_*"]
File without changes
@@ -0,0 +1,38 @@
1
+ """
2
+ SurfDataverse - A Python package for Microsoft Dataverse integration
3
+
4
+ This package provides a clean, object-oriented interface for connecting to,
5
+ reading from, and writing to Microsoft Dataverse environments.
6
+
7
+ Main Components:
8
+ - DataverseClient: Authentication and connection management
9
+ - DataverseRow: Base class for entity operations
10
+ - Entity classes: Article, Recipe, Ingredient, etc.
11
+ """
12
+
13
+ from .core import DataverseClient, DataverseTable
14
+ from .exceptions import (
15
+ AuthenticationError,
16
+ ConfigurationError,
17
+ ConnectionError,
18
+ DataverseAPIError,
19
+ EntityError,
20
+ SurfDataverseError,
21
+ ValidationError,
22
+ )
23
+ from .tables import Tables
24
+
25
+ __author__ = "Friedemann Heinz"
26
+
27
+ __all__ = [
28
+ "DataverseClient",
29
+ "DataverseTable",
30
+ "Tables",
31
+ "SurfDataverseError",
32
+ "AuthenticationError",
33
+ "ConnectionError",
34
+ "ConfigurationError",
35
+ "DataverseAPIError",
36
+ "EntityError",
37
+ "ValidationError",
38
+ ]