framespec 0.0.1__tar.gz → 0.0.2__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.
@@ -1,8 +1,12 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: framespec
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: Declarative DataFrame specifications for PySpark.
5
- Author: Ryan
5
+ Author: RyPy
6
+ License-Expression: MIT
7
+ Requires-Dist: pyspark>=4.0.0
8
+ Requires-Dist: packaging>=24.0
9
+ Requires-Dist: typing-extensions>=4.10.0
6
10
  Requires-Python: >=3.12
7
11
  Description-Content-Type: text/markdown
8
12
 
@@ -0,0 +1,27 @@
1
+ [project]
2
+ name = "framespec"
3
+ version = "0.0.2"
4
+ description = "Declarative DataFrame specifications for PySpark."
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ license = "MIT"
8
+ dependencies = [
9
+ "pyspark >= 4.0.0",
10
+ "packaging >= 24.0",
11
+ "typing-extensions >= 4.10.0",
12
+ ]
13
+
14
+ [[project.authors]]
15
+ name = "RyPy"
16
+
17
+ [dependency-groups]
18
+ dev = [
19
+ "pytest >= 8.0",
20
+ "pytest-cov >= 5.0",
21
+ "mypy >= 1.10",
22
+ "ruff >= 0.5.0",
23
+ ]
24
+
25
+ [build-system]
26
+ requires = ["uv-build"]
27
+ build-backend = "uv_build"
@@ -0,0 +1,26 @@
1
+ [project]
2
+ name = "framespec"
3
+ version = "0.0.2"
4
+ description = "Declarative DataFrame specifications for PySpark."
5
+ readme = "README.md"
6
+ authors = [{ name = "RyPy" }]
7
+ requires-python = ">=3.12"
8
+ license = "MIT"
9
+
10
+ dependencies = [
11
+ "pyspark >= 4.0.0",
12
+ "packaging >= 24.0",
13
+ "typing-extensions >= 4.10.0",
14
+ ]
15
+
16
+ [dependency-groups]
17
+ dev = [
18
+ "pytest >= 8.0",
19
+ "pytest-cov >= 5.0",
20
+ "mypy >= 1.10",
21
+ "ruff >= 0.5.0",
22
+ ]
23
+
24
+ [build-system]
25
+ requires = ["uv-build"]
26
+ build-backend = "uv_build"
File without changes
@@ -0,0 +1,225 @@
1
+ from dataclasses import dataclass
2
+ from pyspark.sql import types as T
3
+
4
+
5
+ # -- Base Type --------------------------------------------------------------
6
+
7
+ @dataclass(frozen=True, kw_only=True)
8
+ class ColumnType:
9
+ """
10
+ Base class for all framespec column types.
11
+
12
+ Declarative only:
13
+ - immutable
14
+ - engine-agnostic except for .dtype (Spark DataType)
15
+ """
16
+ nullable: bool = True
17
+
18
+ @property
19
+ def dtype(self) -> T.DataType:
20
+ raise NotImplementedError
21
+
22
+
23
+ # -- Integer Types ----------------------------------------------------------
24
+
25
+ @dataclass(frozen=True, kw_only=True)
26
+ class Byte(ColumnType):
27
+ min_value: int | None = None
28
+ max_value: int | None = None
29
+
30
+ @property
31
+ def dtype(self) -> T.ByteType:
32
+ return T.ByteType()
33
+
34
+
35
+ @dataclass(frozen=True, kw_only=True)
36
+ class Short(ColumnType):
37
+ min_value: int | None = None
38
+ max_value: int | None = None
39
+
40
+ @property
41
+ def dtype(self) -> T.ShortType:
42
+ return T.ShortType()
43
+
44
+
45
+ @dataclass(frozen=True, kw_only=True)
46
+ class Int(ColumnType):
47
+ min_value: int | None = None
48
+ max_value: int | None = None
49
+
50
+ @property
51
+ def dtype(self) -> T.IntegerType:
52
+ return T.IntegerType()
53
+
54
+
55
+ @dataclass(frozen=True, kw_only=True)
56
+ class Long(ColumnType):
57
+ min_value: int | None = None
58
+ max_value: int | None = None
59
+
60
+ @property
61
+ def dtype(self) -> T.LongType:
62
+ return T.LongType()
63
+
64
+
65
+ # -- Floating Types ---------------------------------------------------------
66
+
67
+ @dataclass(frozen=True, kw_only=True)
68
+ class Float(ColumnType):
69
+ min_value: float | None = None
70
+ max_value: float | None = None
71
+
72
+ @property
73
+ def dtype(self) -> T.FloatType:
74
+ return T.FloatType()
75
+
76
+
77
+ @dataclass(frozen=True, kw_only=True)
78
+ class Double(ColumnType):
79
+ min_value: float | None = None
80
+ max_value: float | None = None
81
+
82
+ @property
83
+ def dtype(self) -> T.DoubleType:
84
+ return T.DoubleType()
85
+
86
+
87
+ # -- Decimal Type -----------------------------------------------------------
88
+
89
+ @dataclass(frozen=True, kw_only=True)
90
+ class Decimal(ColumnType):
91
+ precision: int
92
+ scale: int = 0
93
+ min_value: float | None = None
94
+ max_value: float | None = None
95
+
96
+ @property
97
+ def dtype(self) -> T.DecimalType:
98
+ return T.DecimalType(self.precision, self.scale)
99
+
100
+
101
+ # -- String & Binary Types --------------------------------------------------
102
+
103
+ @dataclass(frozen=True, kw_only=True)
104
+ class String(ColumnType):
105
+ min_length: int | None = None
106
+ max_length: int | None = None
107
+ pattern: str | None = None
108
+ allowed_values: list[str] | None = None
109
+
110
+ @property
111
+ def dtype(self) -> T.StringType:
112
+ return T.StringType()
113
+
114
+
115
+ @dataclass(frozen=True, kw_only=True)
116
+ class Binary(ColumnType):
117
+ min_length: int | None = None
118
+ max_length: int | None = None
119
+
120
+ @property
121
+ def dtype(self) -> T.BinaryType:
122
+ return T.BinaryType()
123
+
124
+
125
+ # -- Boolean Type -----------------------------------------------------------
126
+
127
+ @dataclass(frozen=True, kw_only=True)
128
+ class Boolean(ColumnType):
129
+ @property
130
+ def dtype(self) -> T.BooleanType:
131
+ return T.BooleanType()
132
+
133
+
134
+ # -- Date & Timestamp Types -------------------------------------------------
135
+
136
+ @dataclass(frozen=True, kw_only=True)
137
+ class Date(ColumnType):
138
+ @property
139
+ def dtype(self) -> T.DateType:
140
+ return T.DateType()
141
+
142
+
143
+ @dataclass(frozen=True, kw_only=True)
144
+ class Timestamp(ColumnType):
145
+ @property
146
+ def dtype(self) -> T.TimestampType:
147
+ return T.TimestampType()
148
+
149
+
150
+ @dataclass(frozen=True, kw_only=True)
151
+ class TimestampNTZ(ColumnType):
152
+ @property
153
+ def dtype(self) -> T.TimestampNTZType:
154
+ return T.TimestampNTZType()
155
+
156
+
157
+ # -- Complex Types: Array, Map, Struct -------------------------------------
158
+
159
+ @dataclass(frozen=True, kw_only=True)
160
+ class Array(ColumnType):
161
+ element_type: ColumnType
162
+ min_items: int | None = None
163
+ max_items: int | None = None
164
+ unique_items: bool = False
165
+
166
+ @property
167
+ def dtype(self) -> T.ArrayType:
168
+ return T.ArrayType(
169
+ elementType=self.element_type.dtype,
170
+ containsNull=self.element_type.nullable,
171
+ )
172
+
173
+
174
+ @dataclass(frozen=True, kw_only=True)
175
+ class Map(ColumnType):
176
+ key_type: ColumnType
177
+ value_type: ColumnType
178
+ min_properties: int | None = None
179
+ max_properties: int | None = None
180
+
181
+ @property
182
+ def dtype(self) -> T.MapType:
183
+ return T.MapType(
184
+ keyType=self.key_type.dtype,
185
+ valueType=self.value_type.dtype,
186
+ valueContainsNull=self.value_type.nullable,
187
+ )
188
+
189
+
190
+ @dataclass(frozen=True, kw_only=True)
191
+ class Struct(ColumnType):
192
+ fields: dict[str, ColumnType]
193
+ required: list[str] | None = None
194
+ min_properties: int | None = None
195
+ max_properties: int | None = None
196
+
197
+ @property
198
+ def dtype(self) -> T.StructType:
199
+ return T.StructType([
200
+ T.StructField(name, type_.dtype, type_.nullable)
201
+ for name, type_ in self.fields.items()
202
+ ])
203
+
204
+
205
+ # -- Special Spark Types ----------------------------------------------------
206
+
207
+ @dataclass(frozen=True, kw_only=True)
208
+ class Null(ColumnType):
209
+ @property
210
+ def dtype(self) -> T.NullType:
211
+ return T.NullType()
212
+
213
+
214
+ @dataclass(frozen=True, kw_only=True)
215
+ class CalendarInterval(ColumnType):
216
+ @property
217
+ def dtype(self) -> T.CalendarIntervalType:
218
+ return T.CalendarIntervalType()
219
+
220
+
221
+ @dataclass(frozen=True, kw_only=True)
222
+ class DayTimeInterval(ColumnType):
223
+ @property
224
+ def dtype(self) -> T.DayTimeIntervalType:
225
+ return T.DayTimeIntervalType()
@@ -1,14 +0,0 @@
1
- [project]
2
- name = "framespec"
3
- version = "0.0.1"
4
- description = "Declarative DataFrame specifications for PySpark."
5
- readme = "README.md"
6
- requires-python = ">=3.12"
7
- dependencies = []
8
-
9
- [[project.authors]]
10
- name = "Ryan"
11
-
12
- [build-system]
13
- requires = ["uv_build>=0.12.5,<0.13.0"]
14
- build-backend = "uv_build"
@@ -1,12 +0,0 @@
1
- [project]
2
- name = "framespec"
3
- version = "0.0.1"
4
- description = "Declarative DataFrame specifications for PySpark."
5
- readme = "README.md"
6
- authors = [{ name = "Ryan" }]
7
- requires-python = ">=3.12"
8
- dependencies = []
9
-
10
- [build-system]
11
- requires = ["uv_build>=0.12.5,<0.13.0"]
12
- build-backend = "uv_build"
File without changes