pydantic-ui 0.1.0__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,54 @@
1
+ frontend/coverage/*
2
+ examples/basic/user_input/*
3
+ # Python
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+ *.so
8
+ .Python
9
+ build/
10
+ develop-eggs/
11
+ dist/
12
+ downloads/
13
+ eggs/
14
+ .eggs/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ venv/
25
+ ENV/
26
+ env/
27
+
28
+ # IDE
29
+ .vscode/
30
+ .idea/
31
+ *.swp
32
+ *.swo
33
+
34
+ # Node
35
+ node_modules/
36
+ frontend/dist/
37
+
38
+ # Build artifacts (but keep the static folder structure)
39
+ pydantic_ui/static/*
40
+ !pydantic_ui/static/.gitkeep
41
+
42
+ # OS
43
+ .DS_Store
44
+ Thumbs.db
45
+
46
+ # Test
47
+ .pytest_cache/
48
+ .coverage
49
+ htmlcov/
50
+
51
+ # Misc
52
+ *.log
53
+ .env
54
+ .env.local
@@ -0,0 +1,291 @@
1
+ Metadata-Version: 2.4
2
+ Name: pydantic-ui
3
+ Version: 0.1.0
4
+ Summary: Dynamic UI for editing deeply nested Pydantic models
5
+ Project-URL: Homepage, https://github.com/idling-mind/pydantic-ui
6
+ Project-URL: Documentation, https://github.com/idling-mind/pydantic-ui#readme
7
+ Project-URL: Repository, https://github.com/idling-mind/pydantic-ui
8
+ Project-URL: Issues, https://github.com/idling-mind/pydantic-ui/issues
9
+ Author-email: Najeem Muhammed <najeem@gmail.com>
10
+ License-Expression: MIT
11
+ Keywords: editor,fastapi,form,pydantic,react,ui
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Framework :: FastAPI
14
+ Classifier: Framework :: Pydantic :: 2
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: fastapi>=0.100.0
26
+ Requires-Dist: pydantic>=2.0.0
27
+ Requires-Dist: uvicorn>=0.23.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: coverage>=7.4.0; extra == 'dev'
30
+ Requires-Dist: faker>=22.0.0; extra == 'dev'
31
+ Requires-Dist: httpx>=0.27.0; extra == 'dev'
32
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
35
+ Requires-Dist: pytest-mock>=3.12.0; extra == 'dev'
36
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
37
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
38
+ Description-Content-Type: text/markdown
39
+
40
+ # Pydantic UI
41
+
42
+ A dynamic, modern UI for editing deeply nested Pydantic models with FastAPI integration.
43
+
44
+ ![License](https://img.shields.io/badge/license-MIT-blue.svg)
45
+ ![Python](https://img.shields.io/badge/python-3.10+-blue.svg)
46
+ ![FastAPI](https://img.shields.io/badge/fastapi-0.100+-green.svg)
47
+ ![Pydantic](https://img.shields.io/badge/pydantic-v2-green.svg)
48
+
49
+ ## Features
50
+
51
+ - 🌳 **Tree Navigation**: Sidebar showing hierarchical structure of nested models
52
+ - 🎨 **Dynamic Renderers**: Auto-detect appropriate input components based on field types
53
+ - ⚙️ **Customizable**: Override default renderers with sliders, dropdowns, date pickers, etc.
54
+ - 🌓 **Theme Support**: Light and dark mode with system preference detection
55
+ - ✅ **Validation**: Real-time validation using Pydantic validators
56
+ - 📦 **Easy Integration**: Mount as a FastAPI router in your existing application
57
+
58
+ ## Installation
59
+
60
+ ```bash
61
+ pip install pydantic-ui
62
+ ```
63
+
64
+ ## Quick Start
65
+
66
+ ```python
67
+ from fastapi import FastAPI
68
+ from pydantic import BaseModel, Field
69
+ from typing import Annotated
70
+ from pydantic_ui import create_pydantic_ui, FieldConfig, Renderer
71
+
72
+ # Define your Pydantic model
73
+ class Address(BaseModel):
74
+ street: str
75
+ city: str
76
+ zipcode: str
77
+
78
+ class Person(BaseModel):
79
+ name: str = Field(min_length=1, max_length=100)
80
+ age: Annotated[int, FieldConfig(
81
+ renderer=Renderer.SLIDER,
82
+ props={"min": 0, "max": 120}
83
+ )]
84
+ email: str
85
+ address: Address
86
+ tags: list[str] = []
87
+
88
+ # Create FastAPI app and mount pydantic-ui
89
+ app = FastAPI()
90
+
91
+ app.include_router(
92
+ create_pydantic_ui(Person, prefix="/editor"),
93
+ )
94
+
95
+ if __name__ == "__main__":
96
+ import uvicorn
97
+ uvicorn.run(app, host="0.0.0.0", port=8000)
98
+ ```
99
+
100
+ Then visit `http://localhost:8000/editor` to see the UI.
101
+
102
+ ## UI Configuration
103
+
104
+ ### Global Configuration
105
+
106
+ ```python
107
+ from pydantic_ui import create_pydantic_ui, UIConfig
108
+
109
+ app.include_router(
110
+ create_pydantic_ui(
111
+ Person,
112
+ ui_config=UIConfig(
113
+ title="Person Editor",
114
+ description="Edit person details",
115
+ theme="system", # "light", "dark", or "system"
116
+ read_only=False,
117
+ show_validation=True,
118
+ ),
119
+ prefix="/editor"
120
+ ),
121
+ )
122
+ ```
123
+
124
+ ### Per-Field Configuration
125
+
126
+ Use `Annotated` with `FieldConfig` to customize individual fields:
127
+
128
+ ```python
129
+ from typing import Annotated
130
+ from pydantic_ui import FieldConfig, Renderer
131
+
132
+ class Settings(BaseModel):
133
+ # Slider for numeric values
134
+ volume: Annotated[int, FieldConfig(
135
+ renderer=Renderer.SLIDER,
136
+ label="Volume Level",
137
+ help_text="Adjust the volume",
138
+ props={"min": 0, "max": 100, "step": 5}
139
+ )] = 50
140
+
141
+ # Dropdown for enum-like fields
142
+ theme: Annotated[str, FieldConfig(
143
+ renderer=Renderer.SELECT,
144
+ props={"options": ["light", "dark", "auto"]}
145
+ )] = "auto"
146
+
147
+ # Toggle instead of checkbox
148
+ notifications: Annotated[bool, FieldConfig(
149
+ renderer=Renderer.TOGGLE
150
+ )] = True
151
+
152
+ # Text area for long text
153
+ bio: Annotated[str, FieldConfig(
154
+ renderer=Renderer.TEXT_AREA,
155
+ props={"rows": 5, "placeholder": "Tell us about yourself..."}
156
+ )] = ""
157
+
158
+ # Hidden fields
159
+ internal_id: Annotated[str, FieldConfig(hidden=True)]
160
+
161
+ # Read-only fields
162
+ created_at: Annotated[str, FieldConfig(read_only=True)]
163
+ ```
164
+
165
+ ### Available Renderers
166
+
167
+ | Renderer | Description | Props |
168
+ |----------|-------------|-------|
169
+ | `auto` | Auto-detect based on type | - |
170
+ | `text_input` | Standard text input | `placeholder`, `maxLength` |
171
+ | `text_area` | Multi-line text | `rows`, `placeholder` |
172
+ | `number_input` | Numeric input | `min`, `max`, `step` |
173
+ | `slider` | Slider control | `min`, `max`, `step`, `marks` |
174
+ | `checkbox` | Checkbox | - |
175
+ | `toggle` | Toggle switch | - |
176
+ | `select` | Dropdown select | `options` |
177
+ | `multi_select` | Multi-select | `options` |
178
+ | `date_picker` | Date picker | `format` |
179
+ | `color_picker` | Color picker | - |
180
+ | `password` | Password input | - |
181
+ | `email` | Email input | - |
182
+ | `url` | URL input | - |
183
+
184
+ ## Data Handlers
185
+
186
+ ### Custom Data Loading and Saving
187
+
188
+ ```python
189
+ from pydantic_ui import create_pydantic_ui
190
+
191
+ pydantic_ui = create_pydantic_ui(Person, prefix="/editor")
192
+ app.include_router(pydantic_ui)
193
+
194
+ @pydantic_ui.data_loader
195
+ async def load_person() -> Person:
196
+ """Load data from your database or file."""
197
+ return await database.get_person(id=1)
198
+
199
+ @pydantic_ui.data_saver
200
+ async def save_person(data: Person) -> None:
201
+ """Save data to your database or file."""
202
+ await database.update_person(id=1, data=data)
203
+ ```
204
+
205
+ ### Initial Data
206
+
207
+ ```python
208
+ initial_person = Person(
209
+ name="John Doe",
210
+ age=30,
211
+ email="john@example.com",
212
+ address=Address(street="123 Main St", city="NYC", zipcode="10001"),
213
+ )
214
+
215
+ app.include_router(
216
+ create_pydantic_ui(
217
+ Person,
218
+ initial_data=initial_person,
219
+ prefix="/editor"
220
+ ),
221
+ )
222
+ ```
223
+
224
+ ## API Endpoints
225
+
226
+ When mounted at `/editor`, the following endpoints are available:
227
+
228
+ | Method | Endpoint | Description |
229
+ |--------|----------|-------------|
230
+ | GET | `/editor/` | Serve the React UI |
231
+ | GET | `/editor/api/schema` | Get the model schema |
232
+ | GET | `/editor/api/data` | Get current data |
233
+ | POST | `/editor/api/data` | Update data |
234
+ | PATCH | `/editor/api/data` | Partial update |
235
+ | POST | `/editor/api/validate` | Validate without saving |
236
+ | GET | `/editor/api/config` | Get UI configuration |
237
+
238
+ ## Examples
239
+
240
+ See the [examples](./examples/) directory for more complete examples:
241
+
242
+ - [Basic Usage](./examples/basic/)
243
+ - [Custom Renderers](./examples/custom_renderers/)
244
+ - [Complex Nested Models](./examples/complex_models/)
245
+
246
+ ## Development
247
+
248
+ ### Setup
249
+
250
+ ```bash
251
+ # Clone the repository
252
+ git clone https://github.com/yourusername/pydantic-ui.git
253
+ cd pydantic-ui
254
+
255
+ # Install dependencies
256
+ pip install -e ".[dev]"
257
+
258
+ # Install frontend dependencies
259
+ cd frontend
260
+ npm install
261
+ ```
262
+
263
+ ### Running Tests
264
+
265
+ ```bash
266
+ # Backend tests
267
+ pytest
268
+
269
+ # Frontend tests
270
+ cd frontend
271
+ npm test
272
+ ```
273
+
274
+ ### Building
275
+
276
+ ```bash
277
+ # Build frontend
278
+ cd frontend
279
+ npm run build:package
280
+
281
+ # Build Python package
282
+ python -m build
283
+ ```
284
+
285
+ ## Contributing
286
+
287
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details.
288
+
289
+ ## License
290
+
291
+ MIT License - see [LICENSE](LICENSE) for details.
@@ -0,0 +1,252 @@
1
+ # Pydantic UI
2
+
3
+ A dynamic, modern UI for editing deeply nested Pydantic models with FastAPI integration.
4
+
5
+ ![License](https://img.shields.io/badge/license-MIT-blue.svg)
6
+ ![Python](https://img.shields.io/badge/python-3.10+-blue.svg)
7
+ ![FastAPI](https://img.shields.io/badge/fastapi-0.100+-green.svg)
8
+ ![Pydantic](https://img.shields.io/badge/pydantic-v2-green.svg)
9
+
10
+ ## Features
11
+
12
+ - 🌳 **Tree Navigation**: Sidebar showing hierarchical structure of nested models
13
+ - 🎨 **Dynamic Renderers**: Auto-detect appropriate input components based on field types
14
+ - ⚙️ **Customizable**: Override default renderers with sliders, dropdowns, date pickers, etc.
15
+ - 🌓 **Theme Support**: Light and dark mode with system preference detection
16
+ - ✅ **Validation**: Real-time validation using Pydantic validators
17
+ - 📦 **Easy Integration**: Mount as a FastAPI router in your existing application
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ pip install pydantic-ui
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```python
28
+ from fastapi import FastAPI
29
+ from pydantic import BaseModel, Field
30
+ from typing import Annotated
31
+ from pydantic_ui import create_pydantic_ui, FieldConfig, Renderer
32
+
33
+ # Define your Pydantic model
34
+ class Address(BaseModel):
35
+ street: str
36
+ city: str
37
+ zipcode: str
38
+
39
+ class Person(BaseModel):
40
+ name: str = Field(min_length=1, max_length=100)
41
+ age: Annotated[int, FieldConfig(
42
+ renderer=Renderer.SLIDER,
43
+ props={"min": 0, "max": 120}
44
+ )]
45
+ email: str
46
+ address: Address
47
+ tags: list[str] = []
48
+
49
+ # Create FastAPI app and mount pydantic-ui
50
+ app = FastAPI()
51
+
52
+ app.include_router(
53
+ create_pydantic_ui(Person, prefix="/editor"),
54
+ )
55
+
56
+ if __name__ == "__main__":
57
+ import uvicorn
58
+ uvicorn.run(app, host="0.0.0.0", port=8000)
59
+ ```
60
+
61
+ Then visit `http://localhost:8000/editor` to see the UI.
62
+
63
+ ## UI Configuration
64
+
65
+ ### Global Configuration
66
+
67
+ ```python
68
+ from pydantic_ui import create_pydantic_ui, UIConfig
69
+
70
+ app.include_router(
71
+ create_pydantic_ui(
72
+ Person,
73
+ ui_config=UIConfig(
74
+ title="Person Editor",
75
+ description="Edit person details",
76
+ theme="system", # "light", "dark", or "system"
77
+ read_only=False,
78
+ show_validation=True,
79
+ ),
80
+ prefix="/editor"
81
+ ),
82
+ )
83
+ ```
84
+
85
+ ### Per-Field Configuration
86
+
87
+ Use `Annotated` with `FieldConfig` to customize individual fields:
88
+
89
+ ```python
90
+ from typing import Annotated
91
+ from pydantic_ui import FieldConfig, Renderer
92
+
93
+ class Settings(BaseModel):
94
+ # Slider for numeric values
95
+ volume: Annotated[int, FieldConfig(
96
+ renderer=Renderer.SLIDER,
97
+ label="Volume Level",
98
+ help_text="Adjust the volume",
99
+ props={"min": 0, "max": 100, "step": 5}
100
+ )] = 50
101
+
102
+ # Dropdown for enum-like fields
103
+ theme: Annotated[str, FieldConfig(
104
+ renderer=Renderer.SELECT,
105
+ props={"options": ["light", "dark", "auto"]}
106
+ )] = "auto"
107
+
108
+ # Toggle instead of checkbox
109
+ notifications: Annotated[bool, FieldConfig(
110
+ renderer=Renderer.TOGGLE
111
+ )] = True
112
+
113
+ # Text area for long text
114
+ bio: Annotated[str, FieldConfig(
115
+ renderer=Renderer.TEXT_AREA,
116
+ props={"rows": 5, "placeholder": "Tell us about yourself..."}
117
+ )] = ""
118
+
119
+ # Hidden fields
120
+ internal_id: Annotated[str, FieldConfig(hidden=True)]
121
+
122
+ # Read-only fields
123
+ created_at: Annotated[str, FieldConfig(read_only=True)]
124
+ ```
125
+
126
+ ### Available Renderers
127
+
128
+ | Renderer | Description | Props |
129
+ |----------|-------------|-------|
130
+ | `auto` | Auto-detect based on type | - |
131
+ | `text_input` | Standard text input | `placeholder`, `maxLength` |
132
+ | `text_area` | Multi-line text | `rows`, `placeholder` |
133
+ | `number_input` | Numeric input | `min`, `max`, `step` |
134
+ | `slider` | Slider control | `min`, `max`, `step`, `marks` |
135
+ | `checkbox` | Checkbox | - |
136
+ | `toggle` | Toggle switch | - |
137
+ | `select` | Dropdown select | `options` |
138
+ | `multi_select` | Multi-select | `options` |
139
+ | `date_picker` | Date picker | `format` |
140
+ | `color_picker` | Color picker | - |
141
+ | `password` | Password input | - |
142
+ | `email` | Email input | - |
143
+ | `url` | URL input | - |
144
+
145
+ ## Data Handlers
146
+
147
+ ### Custom Data Loading and Saving
148
+
149
+ ```python
150
+ from pydantic_ui import create_pydantic_ui
151
+
152
+ pydantic_ui = create_pydantic_ui(Person, prefix="/editor")
153
+ app.include_router(pydantic_ui)
154
+
155
+ @pydantic_ui.data_loader
156
+ async def load_person() -> Person:
157
+ """Load data from your database or file."""
158
+ return await database.get_person(id=1)
159
+
160
+ @pydantic_ui.data_saver
161
+ async def save_person(data: Person) -> None:
162
+ """Save data to your database or file."""
163
+ await database.update_person(id=1, data=data)
164
+ ```
165
+
166
+ ### Initial Data
167
+
168
+ ```python
169
+ initial_person = Person(
170
+ name="John Doe",
171
+ age=30,
172
+ email="john@example.com",
173
+ address=Address(street="123 Main St", city="NYC", zipcode="10001"),
174
+ )
175
+
176
+ app.include_router(
177
+ create_pydantic_ui(
178
+ Person,
179
+ initial_data=initial_person,
180
+ prefix="/editor"
181
+ ),
182
+ )
183
+ ```
184
+
185
+ ## API Endpoints
186
+
187
+ When mounted at `/editor`, the following endpoints are available:
188
+
189
+ | Method | Endpoint | Description |
190
+ |--------|----------|-------------|
191
+ | GET | `/editor/` | Serve the React UI |
192
+ | GET | `/editor/api/schema` | Get the model schema |
193
+ | GET | `/editor/api/data` | Get current data |
194
+ | POST | `/editor/api/data` | Update data |
195
+ | PATCH | `/editor/api/data` | Partial update |
196
+ | POST | `/editor/api/validate` | Validate without saving |
197
+ | GET | `/editor/api/config` | Get UI configuration |
198
+
199
+ ## Examples
200
+
201
+ See the [examples](./examples/) directory for more complete examples:
202
+
203
+ - [Basic Usage](./examples/basic/)
204
+ - [Custom Renderers](./examples/custom_renderers/)
205
+ - [Complex Nested Models](./examples/complex_models/)
206
+
207
+ ## Development
208
+
209
+ ### Setup
210
+
211
+ ```bash
212
+ # Clone the repository
213
+ git clone https://github.com/yourusername/pydantic-ui.git
214
+ cd pydantic-ui
215
+
216
+ # Install dependencies
217
+ pip install -e ".[dev]"
218
+
219
+ # Install frontend dependencies
220
+ cd frontend
221
+ npm install
222
+ ```
223
+
224
+ ### Running Tests
225
+
226
+ ```bash
227
+ # Backend tests
228
+ pytest
229
+
230
+ # Frontend tests
231
+ cd frontend
232
+ npm test
233
+ ```
234
+
235
+ ### Building
236
+
237
+ ```bash
238
+ # Build frontend
239
+ cd frontend
240
+ npm run build:package
241
+
242
+ # Build Python package
243
+ python -m build
244
+ ```
245
+
246
+ ## Contributing
247
+
248
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details.
249
+
250
+ ## License
251
+
252
+ MIT License - see [LICENSE](LICENSE) for details.
@@ -0,0 +1,20 @@
1
+ """
2
+ Pydantic UI - Dynamic UI for editing deeply nested Pydantic models.
3
+
4
+ A FastAPI-based package that provides a modern React UI for editing
5
+ Pydantic models with tree navigation and customizable field renderers.
6
+ """
7
+
8
+ from pydantic_ui.app import create_pydantic_ui
9
+ from pydantic_ui.config import ActionButton, FieldConfig, Renderer, UIConfig
10
+ from pydantic_ui.controller import PydanticUIController
11
+
12
+ __version__ = "0.1.0"
13
+ __all__ = [
14
+ "create_pydantic_ui",
15
+ "UIConfig",
16
+ "FieldConfig",
17
+ "Renderer",
18
+ "ActionButton",
19
+ "PydanticUIController",
20
+ ]