5
5
from django .forms .widgets import TextInput
6
6
7
7
from collections .abc import Iterable
8
+ from typing import TypeVarTuple , NoReturn , Any , TYPE_CHECKING
9
+
10
+ if TYPE_CHECKING :
11
+ from django_ltree .models import TreeModel
8
12
9
13
path_label_validator = RegexValidator (
10
14
r"^(?P<root>[a-zA-Z][a-zA-Z0-9_]*|\d+)(?:\.[a-zA-Z0-9_]+)*$" ,
13
17
)
14
18
15
19
16
- class PathValue (UserList ):
17
- def __init__ (self , value ):
20
+ class PathValue (UserList [ str ] ):
21
+ def __init__ (self , value : str | int | Iterable [ str ] ):
18
22
if isinstance (value , str ):
19
23
split_by = "/" if "/" in value else "."
20
24
value = value .strip ().split (split_by ) if value else []
@@ -27,18 +31,20 @@ def __init__(self, value):
27
31
28
32
super ().__init__ (initlist = value )
29
33
30
- def __repr__ (self ):
34
+ def __repr__ (self ) -> str :
31
35
return str (self )
32
36
33
- def __str__ (self ):
37
+ def __str__ (self ) -> str :
34
38
return "." .join (self )
35
39
36
40
37
41
class PathValueProxy :
38
- def __init__ (self , field_name ) :
42
+ def __init__ (self , field_name : str ) -> None :
39
43
self .field_name = field_name
40
44
41
- def __get__ (self , instance , owner ):
45
+ def __get__ (
46
+ self , instance : "PathValueProxy" | None , * args : TypeVarTuple
47
+ ) -> "PathValueProxy" | "PathValue" | None :
42
48
if instance is None :
43
49
return self
44
50
@@ -49,7 +55,9 @@ def __get__(self, instance, owner):
49
55
50
56
return PathValue (instance .__dict__ [self .field_name ])
51
57
52
- def __set__ (self , instance , value ):
58
+ def __set__ (
59
+ self , instance : "PathValueProxy" | None , value : str
60
+ ) -> NoReturn | "PathValueProxy" :
53
61
if instance is None :
54
62
return self
55
63
@@ -63,15 +71,17 @@ class PathFormField(forms.CharField):
63
71
class PathField (TextField ):
64
72
default_validators = [path_label_validator ]
65
73
66
- def db_type (self , connection ) :
74
+ def db_type (self , * args : TypeVarTuple ) -> str :
67
75
return "ltree"
68
76
69
- def formfield (self , ** kwargs ) :
77
+ def formfield (self , ** kwargs : Any ) -> Any :
70
78
kwargs ["form_class" ] = PathFormField
71
79
kwargs ["widget" ] = TextInput (attrs = {"class" : "vTextField" })
72
80
return super ().formfield (** kwargs )
73
81
74
- def contribute_to_class (self , cls , name , private_only = False ):
82
+ def contribute_to_class (
83
+ self , cls : type ["TreeModel" ], name : str , private_only : bool = False
84
+ ) -> None :
75
85
super ().contribute_to_class (cls , name )
76
86
setattr (cls , self .name , PathValueProxy (self .name ))
77
87
@@ -80,20 +90,22 @@ def from_db_value(self, value, expression, connection, *args):
80
90
return value
81
91
return PathValue (value )
82
92
83
- def get_prep_value (self , value ) :
93
+ def get_prep_value (self , value : str | None ) -> str | None :
84
94
if value is None :
85
95
return value
86
96
return str (PathValue (value ))
87
97
88
- def to_python (self , value ) :
98
+ def to_python (self , value : str | None | PathValue ) -> PathValue | None :
89
99
if value is None :
90
100
return value
91
101
elif isinstance (value , PathValue ):
92
102
return value
93
103
94
104
return PathValue (value )
95
105
96
- def get_db_prep_value (self , value , connection , prepared = False ):
106
+ def get_db_prep_value (
107
+ self , value : str | None | PathValue , connection : str , prepared : bool = False
108
+ ) -> str | None :
97
109
if value is None :
98
110
return value
99
111
elif isinstance (value , PathValue ):
0 commit comments