fh-pydantic-form 0.3.9__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.
@@ -0,0 +1,143 @@
1
+ import datetime
2
+ import decimal
3
+ from enum import Enum
4
+ from typing import Literal, get_origin
5
+
6
+ from pydantic import BaseModel
7
+
8
+ from fh_pydantic_form.comparison_form import (
9
+ ComparisonForm,
10
+ comparison_form_js,
11
+ simple_diff_metrics,
12
+ )
13
+ from fh_pydantic_form.defaults import (
14
+ default_dict_for_model,
15
+ default_for_annotation,
16
+ )
17
+ from fh_pydantic_form.field_renderers import (
18
+ BaseModelFieldRenderer,
19
+ BooleanFieldRenderer,
20
+ DateFieldRenderer,
21
+ DecimalFieldRenderer,
22
+ EnumFieldRenderer,
23
+ ListFieldRenderer,
24
+ LiteralFieldRenderer,
25
+ NumberFieldRenderer,
26
+ StringFieldRenderer,
27
+ TimeFieldRenderer,
28
+ )
29
+ from fh_pydantic_form.form_renderer import PydanticForm, list_manipulation_js
30
+ from fh_pydantic_form.registry import FieldRendererRegistry
31
+ from fh_pydantic_form.type_helpers import (
32
+ MetricEntry,
33
+ MetricsDict,
34
+ _get_underlying_type_if_optional,
35
+ )
36
+ from fh_pydantic_form.ui_style import (
37
+ SpacingTheme,
38
+ SpacingValue,
39
+ spacing,
40
+ spacing_many,
41
+ )
42
+
43
+
44
+ def register_default_renderers() -> None:
45
+ """
46
+ Register built-in renderers for common types
47
+
48
+ This method sets up:
49
+ - Simple type renderers (str, bool, int, float, date, time)
50
+ - Special field renderers (Detail)
51
+ - Predicate-based renderers (Literal fields, Enum fields, lists, BaseModels)
52
+ """
53
+ # Import renderers by getting them from globals
54
+
55
+ # Simple types
56
+ FieldRendererRegistry.register_type_renderer(str, StringFieldRenderer)
57
+ FieldRendererRegistry.register_type_renderer(bool, BooleanFieldRenderer)
58
+ FieldRendererRegistry.register_type_renderer(int, NumberFieldRenderer)
59
+ FieldRendererRegistry.register_type_renderer(float, NumberFieldRenderer)
60
+ FieldRendererRegistry.register_type_renderer(decimal.Decimal, DecimalFieldRenderer)
61
+ FieldRendererRegistry.register_type_renderer(datetime.date, DateFieldRenderer)
62
+ FieldRendererRegistry.register_type_renderer(datetime.time, TimeFieldRenderer)
63
+
64
+ # Register Enum field renderer (before Literal to prioritize Enum handling)
65
+ def is_enum_field(field_info):
66
+ """Check if field is an Enum type"""
67
+ annotation = getattr(field_info, "annotation", None)
68
+ if not annotation:
69
+ return False
70
+ underlying_type = _get_underlying_type_if_optional(annotation)
71
+ return isinstance(underlying_type, type) and issubclass(underlying_type, Enum)
72
+
73
+ FieldRendererRegistry.register_type_renderer_with_predicate(
74
+ is_enum_field, EnumFieldRenderer
75
+ )
76
+
77
+ # Register Literal field renderer (after Enum to avoid conflicts)
78
+ def is_literal_field(field_info):
79
+ """Check if field is a Literal type"""
80
+ annotation = getattr(field_info, "annotation", None)
81
+ if not annotation:
82
+ return False
83
+ underlying_type = _get_underlying_type_if_optional(annotation)
84
+ origin = get_origin(underlying_type)
85
+ return origin is Literal
86
+
87
+ FieldRendererRegistry.register_type_renderer_with_predicate(
88
+ is_literal_field, LiteralFieldRenderer
89
+ )
90
+
91
+ # Register list renderer for List[*] types
92
+ def is_list_field(field_info):
93
+ """Check if field is a list type, including Optional[List[...]]"""
94
+ annotation = getattr(field_info, "annotation", None)
95
+ if annotation is None:
96
+ return False
97
+
98
+ # Handle Optional[List[...]] by unwrapping the Optional
99
+ underlying_type = _get_underlying_type_if_optional(annotation)
100
+
101
+ # Check if the underlying type is a list
102
+ return get_origin(underlying_type) is list
103
+
104
+ FieldRendererRegistry.register_type_renderer_with_predicate(
105
+ is_list_field, ListFieldRenderer
106
+ )
107
+
108
+ # Register the BaseModelFieldRenderer for Pydantic models
109
+ def is_basemodel_field(field_info):
110
+ """Check if field is a BaseModel"""
111
+ annotation = getattr(field_info, "annotation", None)
112
+ underlying_type = _get_underlying_type_if_optional(annotation)
113
+
114
+ return (
115
+ isinstance(underlying_type, type)
116
+ and issubclass(underlying_type, BaseModel)
117
+ and not is_list_field(field_info)
118
+ )
119
+
120
+ FieldRendererRegistry.register_type_renderer_with_predicate(
121
+ is_basemodel_field, BaseModelFieldRenderer
122
+ )
123
+
124
+
125
+ register_default_renderers()
126
+
127
+
128
+ __all__ = [
129
+ "PydanticForm",
130
+ "FieldRendererRegistry",
131
+ "list_manipulation_js",
132
+ "SpacingTheme",
133
+ "SpacingValue",
134
+ "spacing",
135
+ "spacing_many",
136
+ "default_dict_for_model",
137
+ "default_for_annotation",
138
+ "ComparisonForm",
139
+ "MetricEntry",
140
+ "MetricsDict",
141
+ "comparison_form_js",
142
+ "simple_diff_metrics",
143
+ ]