statezero 0.1.0b11__tar.gz → 0.1.0b12__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 statezero might be problematic. Click here for more details.

Files changed (54) hide show
  1. {statezero-0.1.0b11 → statezero-0.1.0b12}/PKG-INFO +1 -1
  2. {statezero-0.1.0b11 → statezero-0.1.0b12}/pyproject.toml +1 -1
  3. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/actions.py +25 -0
  4. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/schemas.py +23 -0
  5. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/actions.py +6 -2
  6. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/classes.py +57 -1
  7. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/config.py +4 -0
  8. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero.egg-info/PKG-INFO +1 -1
  9. {statezero-0.1.0b11 → statezero-0.1.0b12}/README.md +0 -0
  10. {statezero-0.1.0b11 → statezero-0.1.0b12}/license.md +0 -0
  11. {statezero-0.1.0b11 → statezero-0.1.0b12}/requirements.txt +0 -0
  12. {statezero-0.1.0b11 → statezero-0.1.0b12}/setup.cfg +0 -0
  13. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/__init__.py +0 -0
  14. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/__init__.py +0 -0
  15. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/__init__.py +0 -0
  16. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/apps.py +0 -0
  17. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/config.py +0 -0
  18. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/context_manager.py +0 -0
  19. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/event_emitters.py +0 -0
  20. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/exception_handler.py +0 -0
  21. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/extensions/__init__.py +0 -0
  22. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/extensions/custom_field_serializers/__init__.py +0 -0
  23. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/extensions/custom_field_serializers/file_fields.py +0 -0
  24. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/extensions/custom_field_serializers/money_field.py +0 -0
  25. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/f_handler.py +0 -0
  26. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/helpers.py +0 -0
  27. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/middleware.py +0 -0
  28. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/migrations/0001_initial.py +0 -0
  29. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/migrations/0002_delete_modelviewsubscription.py +0 -0
  30. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/migrations/__init__.py +0 -0
  31. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/orm.py +0 -0
  32. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/permissions.py +0 -0
  33. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/query_optimizer.py +0 -0
  34. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/search_providers/__init__.py +0 -0
  35. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/search_providers/basic_search.py +0 -0
  36. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/search_providers/postgres_search.py +0 -0
  37. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/serializers.py +0 -0
  38. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/urls.py +0 -0
  39. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/adaptors/django/views.py +0 -0
  40. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/__init__.py +0 -0
  41. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/ast_parser.py +0 -0
  42. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/ast_validator.py +0 -0
  43. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/context_storage.py +0 -0
  44. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/event_bus.py +0 -0
  45. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/event_emitters.py +0 -0
  46. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/exceptions.py +0 -0
  47. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/hook_checks.py +0 -0
  48. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/interfaces.py +0 -0
  49. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/process_request.py +0 -0
  50. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero/core/types.py +0 -0
  51. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero.egg-info/SOURCES.txt +0 -0
  52. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero.egg-info/dependency_links.txt +0 -0
  53. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero.egg-info/requires.txt +0 -0
  54. {statezero-0.1.0b11 → statezero-0.1.0b12}/statezero.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: statezero
3
- Version: 0.1.0b11
3
+ Version: 0.1.0b12
4
4
  Summary: Connect your Python backend to a modern JavaScript SPA frontend with 90% less complexity.
5
5
  Author-email: Robert <robert.herring@statezero.dev>
6
6
  Project-URL: homepage, https://www.statezero.dev
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "statezero"
7
- version = "0.1.0b11"
7
+ version = "0.1.0b12"
8
8
  description = "Connect your Python backend to a modern JavaScript SPA frontend with 90% less complexity."
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -48,6 +48,13 @@ class DjangoActionSchemaGenerator:
48
48
  action_config["response_serializer"]
49
49
  )
50
50
 
51
+ # Serialize display metadata if present
52
+ display_data = None
53
+ if action_config.get("display"):
54
+ display_data = DjangoActionSchemaGenerator._serialize_display_metadata(
55
+ action_config["display"]
56
+ )
57
+
51
58
  schema_info = {
52
59
  "action_name": action_name,
53
60
  "app": app_name,
@@ -62,6 +69,7 @@ class DjangoActionSchemaGenerator:
62
69
  "permissions": [
63
70
  perm.__name__ for perm in action_config.get("permissions", [])
64
71
  ],
72
+ "display": display_data,
65
73
  }
66
74
  actions_schema[action_name] = schema_info
67
75
 
@@ -212,4 +220,21 @@ class DjangoActionSchemaGenerator:
212
220
  "class_name": model.__name__,
213
221
  "primary_key_field": model._meta.pk.name,
214
222
  }
223
+ return None
224
+
225
+ @staticmethod
226
+ def _serialize_display_metadata(display):
227
+ """Convert DisplayMetadata dataclass to dict for JSON serialization"""
228
+ from dataclasses import asdict, is_dataclass
229
+
230
+ if display is None:
231
+ return None
232
+
233
+ if is_dataclass(display):
234
+ return asdict(display)
235
+
236
+ # If it's already a dict, return as-is
237
+ if isinstance(display, dict):
238
+ return display
239
+
215
240
  return None
@@ -127,6 +127,11 @@ class DjangoSchemaGenerator(AbstractSchemaGenerator):
127
127
  if hasattr(model._meta, "ordering") and model._meta.ordering:
128
128
  default_ordering = list(model._meta.ordering)
129
129
 
130
+ # Serialize display metadata if present
131
+ display_data = None
132
+ if model_config.display:
133
+ display_data = self._serialize_display_metadata(model_config.display)
134
+
130
135
  schema_meta = ModelSchemaMetadata(
131
136
  model_name=config.orm_provider.get_model_name(model),
132
137
  title=model._meta.verbose_name.title(),
@@ -153,6 +158,7 @@ class DjangoSchemaGenerator(AbstractSchemaGenerator):
153
158
  time_format=getattr(settings, "REST_FRAMEWORK", {}).get(
154
159
  "TIME_FORMAT", "iso-8601"
155
160
  ),
161
+ display=display_data,
156
162
  )
157
163
  return schema_meta
158
164
 
@@ -322,3 +328,20 @@ class DjangoSchemaGenerator(AbstractSchemaGenerator):
322
328
  if isinstance(target_field, (models.UUIDField, models.CharField)):
323
329
  return FieldType.STRING
324
330
  return FieldType.INTEGER
331
+
332
+ @staticmethod
333
+ def _serialize_display_metadata(display) -> Dict[str, Any]:
334
+ """Convert DisplayMetadata dataclass to dict for JSON serialization"""
335
+ from dataclasses import asdict, is_dataclass
336
+
337
+ if display is None:
338
+ return None
339
+
340
+ if is_dataclass(display):
341
+ return asdict(display)
342
+
343
+ # If it's already a dict, return as-is
344
+ if isinstance(display, dict):
345
+ return display
346
+
347
+ return None
@@ -20,8 +20,9 @@ class ActionRegistry:
20
20
  List[AbstractActionPermission], AbstractActionPermission, None
21
21
  ] = None,
22
22
  name: Optional[str] = None,
23
+ display: Optional[Any] = None,
23
24
  ):
24
- """Register an action function with an optional, explicit docstring."""
25
+ """Register an action function with an optional, explicit docstring and display metadata."""
25
26
 
26
27
  def decorator(func: Callable):
27
28
  action_name = name or func.__name__
@@ -47,6 +48,7 @@ class ActionRegistry:
47
48
  "name": action_name,
48
49
  "module": func.__module__,
49
50
  "docstring": final_docstring, # Store the determined docstring
51
+ "display": display, # Store display metadata
50
52
  }
51
53
  return func
52
54
 
@@ -76,8 +78,9 @@ def action(
76
78
  List[AbstractActionPermission], AbstractActionPermission, None
77
79
  ] = None,
78
80
  name: Optional[str] = None,
81
+ display: Optional[Any] = None,
79
82
  ):
80
- """Framework-agnostic decorator to register an action."""
83
+ """Framework-agnostic decorator to register an action with optional display metadata."""
81
84
  return action_registry.register(
82
85
  func,
83
86
  docstring=docstring,
@@ -85,4 +88,5 @@ def action(
85
88
  response_serializer=response_serializer,
86
89
  permissions=permissions,
87
90
  name=name,
91
+ display=display,
88
92
  )
@@ -131,12 +131,15 @@ class ModelSchemaMetadata(BaseModel):
131
131
  default_ordering: Optional[List[str]] = None
132
132
  # Extra definitions (for schemas referenced via $ref) are merged in if provided.
133
133
  definitions: Dict[str, Any] = field(default_factory=dict)
134
-
134
+
135
135
  # Date / time formatting templates
136
136
  datetime_format: Optional[str] = None
137
137
  date_format: Optional[str] = None
138
138
  time_format: Optional[str] = None
139
139
 
140
+ # Display customization
141
+ display: Optional[Dict[str, Any]] = None
142
+
140
143
  @dataclass
141
144
  class ModelSummaryRepresentation:
142
145
  pk: Any
@@ -165,3 +168,56 @@ class FieldNode:
165
168
  is_relation: bool
166
169
  related_model: Optional[str] = None # The object name of the related model, if any
167
170
  type: str = "field"
171
+
172
+
173
+ @dataclass
174
+ class FieldDisplayConfig:
175
+ """
176
+ Configuration for customizing how a field is displayed in the frontend.
177
+
178
+ Attributes:
179
+ field_name: The name of the field this config applies to
180
+ display_component: Custom UI component name (e.g., "AddressAutocomplete", "DatePicker")
181
+ filter_queryset: Filter options for select/multi-select fields (dict passed to backend)
182
+ display_help_text: Additional help text for the field
183
+ extra: Additional custom metadata for framework-specific or UI-specific extensions
184
+ """
185
+ field_name: str
186
+ display_component: Optional[str] = None
187
+ filter_queryset: Optional[Dict[str, Any]] = None
188
+ display_help_text: Optional[str] = None
189
+ extra: Optional[Dict[str, Any]] = None
190
+
191
+
192
+ @dataclass
193
+ class FieldGroup:
194
+ """
195
+ Group related fields together for better UX.
196
+
197
+ Attributes:
198
+ display_title: Group heading
199
+ display_description: Group description
200
+ field_names: List of field names in this group
201
+ """
202
+ display_title: str
203
+ display_description: Optional[str] = None
204
+ field_names: Optional[List[str]] = None
205
+
206
+
207
+ @dataclass
208
+ class DisplayMetadata:
209
+ """
210
+ Rich display information for models and actions to customize frontend rendering.
211
+
212
+ Attributes:
213
+ display_title: Main heading/title override
214
+ display_description: Explanatory text about the model/action
215
+ field_groups: Logical grouping of fields (e.g., "Contact Info", "Address Details")
216
+ field_display_configs: Per-field customization (custom components, filters, help text)
217
+ extra: Additional custom metadata for framework-specific or UI-specific extensions
218
+ """
219
+ display_title: Optional[str] = None
220
+ display_description: Optional[str] = None
221
+ field_groups: Optional[List[FieldGroup]] = None
222
+ field_display_configs: Optional[List[FieldDisplayConfig]] = None
223
+ extra: Optional[Dict[str, Any]] = None
@@ -162,6 +162,8 @@ class ModelConfig:
162
162
  Fields that can be used for ordering
163
163
  fields: Optional[Optional[Union[Set[str], Literal["__all__"]]]]
164
164
  Expose just a subset of the model fields
165
+ display: Optional[Any], optional
166
+ Display metadata for frontend customization (DisplayMetadata instance)
165
167
  DEBUG: bool, default=False
166
168
  Enable debug mode for this model
167
169
  """
@@ -179,6 +181,7 @@ class ModelConfig:
179
181
  searchable_fields: Optional[Union[Set[str], Literal["__all__"]]] = None,
180
182
  ordering_fields: Optional[Union[Set[str], Literal["__all__"]]] = None,
181
183
  fields: Optional[Union[Set[str], Literal["__all__"]]] = None,
184
+ display: Optional[Any] = None,
182
185
  DEBUG: bool = False,
183
186
  ):
184
187
  self.model = model
@@ -192,6 +195,7 @@ class ModelConfig:
192
195
  self.searchable_fields = searchable_fields or set()
193
196
  self.ordering_fields = ordering_fields or set()
194
197
  self.fields = fields or "__all__"
198
+ self.display = display
195
199
  self.DEBUG = DEBUG or False
196
200
 
197
201
  @property
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: statezero
3
- Version: 0.1.0b11
3
+ Version: 0.1.0b12
4
4
  Summary: Connect your Python backend to a modern JavaScript SPA frontend with 90% less complexity.
5
5
  Author-email: Robert <robert.herring@statezero.dev>
6
6
  Project-URL: homepage, https://www.statezero.dev
File without changes
File without changes
File without changes