schemez 1.2.0__tar.gz → 1.2.3__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.
Files changed (27) hide show
  1. schemez-1.2.3/PKG-INFO +340 -0
  2. schemez-1.2.3/README.md +296 -0
  3. {schemez-1.2.0 → schemez-1.2.3}/pyproject.toml +7 -3
  4. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/convert.py +1 -1
  5. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/functionschema.py +18 -20
  6. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/helpers.py +15 -44
  7. schemez-1.2.3/src/schemez/log.py +17 -0
  8. schemez-1.2.3/src/schemez/tool_executor/__init__.py +8 -0
  9. schemez-1.2.3/src/schemez/tool_executor/executor.py +322 -0
  10. schemez-1.2.3/src/schemez/tool_executor/helpers.py +46 -0
  11. schemez-1.2.3/src/schemez/tool_executor/types.py +28 -0
  12. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/typedefs.py +2 -2
  13. schemez-1.2.0/PKG-INFO +0 -86
  14. schemez-1.2.0/README.md +0 -26
  15. {schemez-1.2.0 → schemez-1.2.3}/LICENSE +0 -0
  16. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/__init__.py +0 -0
  17. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/bind_kwargs.py +0 -0
  18. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/code.py +0 -0
  19. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/create_type.py +0 -0
  20. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/docstrings.py +0 -0
  21. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/executable.py +0 -0
  22. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/py.typed +0 -0
  23. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/pydantic_types.py +0 -0
  24. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/schema.py +0 -0
  25. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/schema_generators.py +0 -0
  26. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/schemadef/__init__.py +0 -0
  27. {schemez-1.2.0 → schemez-1.2.3}/src/schemez/schemadef/schemadef.py +0 -0
schemez-1.2.3/PKG-INFO ADDED
@@ -0,0 +1,340 @@
1
+ Metadata-Version: 2.4
2
+ Name: schemez
3
+ Version: 1.2.3
4
+ Summary: Pydantic shim for config stuff
5
+ Keywords:
6
+ Author: Philipp Temminghoff
7
+ Author-email: Philipp Temminghoff <philipptemminghoff@googlemail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Framework :: Pydantic
12
+ Classifier: Framework :: Pydantic :: 2
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Topic :: Documentation
21
+ Classifier: Topic :: Software Development
22
+ Classifier: Topic :: Utilities
23
+ Classifier: Typing :: Typed
24
+ Requires-Dist: docstring-parser>=0.17.0
25
+ Requires-Dist: griffe>=1.7.3
26
+ Requires-Dist: pydantic
27
+ Requires-Dist: universal-pathlib>=0.2.6
28
+ Requires-Dist: llmling-agent ; extra == 'ai'
29
+ Requires-Dist: anyenv>=0.4.14 ; extra == 'ai'
30
+ Requires-Dist: datamodel-code-generator ; extra == 'codegen'
31
+ Requires-Dist: fastapi>=0.118.2 ; extra == 'tool-execution'
32
+ Requires-Dist: yamling ; extra == 'yaml'
33
+ Requires-Python: >=3.13
34
+ Project-URL: Code coverage, https://app.codecov.io/gh/phil65/schemez
35
+ Project-URL: Discussions, https://github.com/phil65/schemez/discussions
36
+ Project-URL: Documentation, https://phil65.github.io/schemez/
37
+ Project-URL: Issues, https://github.com/phil65/schemez/issues
38
+ Project-URL: Source, https://github.com/phil65/schemez
39
+ Provides-Extra: ai
40
+ Provides-Extra: codegen
41
+ Provides-Extra: tool-execution
42
+ Provides-Extra: yaml
43
+ Description-Content-Type: text/markdown
44
+
45
+ # Schemez
46
+
47
+ [![PyPI License](https://img.shields.io/pypi/l/schemez.svg)](https://pypi.org/project/schemez/)
48
+ [![Package status](https://img.shields.io/pypi/status/schemez.svg)](https://pypi.org/project/schemez/)
49
+ [![Monthly downloads](https://img.shields.io/pypi/dm/schemez.svg)](https://pypi.org/project/schemez/)
50
+ [![Distribution format](https://img.shields.io/pypi/format/schemez.svg)](https://pypi.org/project/schemez/)
51
+ [![Wheel availability](https://img.shields.io/pypi/wheel/schemez.svg)](https://pypi.org/project/schemez/)
52
+ [![Python version](https://img.shields.io/pypi/pyversions/schemez.svg)](https://pypi.org/project/schemez/)
53
+ [![Implementation](https://img.shields.io/pypi/implementation/schemez.svg)](https://pypi.org/project/schemez/)
54
+ [![Releases](https://img.shields.io/github/downloads/phil65/schemez/total.svg)](https://github.com/phil65/schemez/releases)
55
+ [![Github Contributors](https://img.shields.io/github/contributors/phil65/schemez)](https://github.com/phil65/schemez/graphs/contributors)
56
+ [![Github Discussions](https://img.shields.io/github/discussions/phil65/schemez)](https://github.com/phil65/schemez/discussions)
57
+ [![Github Forks](https://img.shields.io/github/forks/phil65/schemez)](https://github.com/phil65/schemez/forks)
58
+ [![Github Issues](https://img.shields.io/github/issues/phil65/schemez)](https://github.com/phil65/schemez/issues)
59
+ [![Github Issues](https://img.shields.io/github/issues-pr/phil65/schemez)](https://github.com/phil65/schemez/pulls)
60
+ [![Github Watchers](https://img.shields.io/github/watchers/phil65/schemez)](https://github.com/phil65/schemez/watchers)
61
+ [![Github Stars](https://img.shields.io/github/stars/phil65/schemez)](https://github.com/phil65/schemez/stars)
62
+ [![Github Repository size](https://img.shields.io/github/repo-size/phil65/schemez)](https://github.com/phil65/schemez)
63
+ [![Github last commit](https://img.shields.io/github/last-commit/phil65/schemez)](https://github.com/phil65/schemez/commits)
64
+ [![Github release date](https://img.shields.io/github/release-date/phil65/schemez)](https://github.com/phil65/schemez/releases)
65
+ [![Github language count](https://img.shields.io/github/languages/count/phil65/schemez)](https://github.com/phil65/schemez)
66
+ [![Github commits this month](https://img.shields.io/github/commit-activity/m/phil65/schemez)](https://github.com/phil65/schemez)
67
+ [![Package status](https://codecov.io/gh/phil65/schemez/branch/main/graph/badge.svg)](https://codecov.io/gh/phil65/schemez/)
68
+ [![PyUp](https://pyup.io/repos/github/phil65/schemez/shield.svg)](https://pyup.io/repos/github/phil65/schemez/)
69
+
70
+ [Read the documentation!](https://phil65.github.io/schemez/)
71
+
72
+
73
+
74
+ # OpenAI Function Schema Generator
75
+
76
+ Convert Python functions to OpenAI-compatible function schemas automatically.
77
+
78
+ ## Installation
79
+
80
+ ```bash
81
+ pip install schemez
82
+ ```
83
+
84
+ ## Basic Usage
85
+
86
+ ```python
87
+ from schemez import create_schema
88
+ from typing import Literal
89
+
90
+ def get_weather(
91
+ location: str,
92
+ unit: Literal["C", "F"] = "C",
93
+ detailed: bool = False,
94
+ ) -> dict[str, str | float]:
95
+ """Get the weather for a location.
96
+
97
+ Args:
98
+ location: City or address to get weather for
99
+ unit: Temperature unit (Celsius or Fahrenheit)
100
+ detailed: Include extended forecast
101
+ """
102
+ return {"temp": 22.5, "conditions": "sunny"}
103
+
104
+ # Create schema
105
+ schema = create_schema(get_weather)
106
+
107
+ # The schema.model_dump_openai() returns a TypedDict with the complete OpenAI tool definition:
108
+ # OpenAIFunctionTool = TypedDict({
109
+ # "type": Literal["function"],
110
+ # "function": OpenAIFunctionDefinition
111
+ # })
112
+
113
+ # Use with OpenAI
114
+ from openai import OpenAI
115
+
116
+ client = OpenAI()
117
+ response = client.chat.completions.create(
118
+ model="gpt-4",
119
+ messages=[{"role": "user", "content": "What's the weather in London?"}],
120
+ tools=[schema.model_dump_openai()], # Schema includes the type: "function" wrapper
121
+ tool_choice="auto"
122
+ )
123
+ ```
124
+
125
+ > **Note**: This library supports the OpenAI API v1 format (openai>=1.0.0). For older
126
+ > versions of the OpenAI package that use the legacy functions API, you'll need to
127
+ > unwrap the function definition using `schema.model_dump_openai()["function"]`.
128
+ ```
129
+
130
+ ## Supported Types
131
+
132
+ ### Basic Types
133
+ ```python
134
+ def func(
135
+ text: str, # -> "type": "string"
136
+ number: int, # -> "type": "integer"
137
+ amount: float, # -> "type": "number"
138
+ enabled: bool, # -> "type": "boolean"
139
+ anything: Any, # -> "type": "string"
140
+ ) -> None: ...
141
+ ```
142
+
143
+ ### Container Types
144
+ ```python
145
+ def func(
146
+ items: list[str], # -> "type": "array", "items": {"type": "string"}
147
+ numbers: set[int], # -> same as list
148
+ mapping: dict[str, Any], # -> "type": "object", "additionalProperties": true
149
+ nested: list[dict[str, int]], # -> nested array/object types
150
+ sequence: Sequence[str], # -> "type": "array"
151
+ collection: Collection[int], # -> "type": "array"
152
+ ) -> None: ...
153
+ ```
154
+
155
+ ### Enums and Literals
156
+ ```python
157
+ class Color(Enum):
158
+ RED = "red"
159
+ BLUE = "blue"
160
+
161
+ def func(
162
+ color: Color, # -> "type": "string", "enum": ["red", "blue"]
163
+ mode: Literal["fast", "slow"], # -> "type": "string", "enum": ["fast", "slow"]
164
+ ) -> None: ...
165
+ ```
166
+
167
+ ### Optional and Union Types
168
+ ```python
169
+ def func(
170
+ opt1: str | None, # -> "type": "string"
171
+ opt2: int | None, # -> "type": "integer"
172
+ union: str | int, # -> "type": "string" (first type)
173
+ ) -> None: ...
174
+ ```
175
+
176
+ ### Custom Types
177
+ ```python
178
+ @dataclass
179
+ class User:
180
+ name: str
181
+ age: int
182
+
183
+ def func(
184
+ user: User, # -> "type": "object"
185
+ data: JsonDict, # -> "type": "object"
186
+ ) -> None: ...
187
+ ```
188
+
189
+ ### Type Aliases
190
+ ```python
191
+ JsonValue = dict[str, Any] | list[Any] | str | int | float | bool | None
192
+ JsonDict = dict[str, JsonValue]
193
+
194
+ def func(
195
+ data: JsonDict, # -> "type": "object"
196
+ values: list[JsonValue], # -> "type": "array"
197
+ ) -> None: ...
198
+ ```
199
+
200
+ ### Recursive Types
201
+ ```python
202
+ def func(
203
+ tree: dict[str, "dict[str, Any] | str"], # -> "type": "object"
204
+ nested: dict[str, list["dict[str, Any]"]], # -> "type": "object"
205
+ ) -> None: ...
206
+ ```
207
+
208
+ ## Generated Schema Example
209
+
210
+ ```python
211
+ {
212
+ "type": "function",
213
+ "function": {
214
+ "name": "get_weather",
215
+ "description": "Get the weather for a location.",
216
+ "parameters": {
217
+ "type": "object",
218
+ "properties": {
219
+ "location": {
220
+ "type": "string",
221
+ "description": "City or address to get weather for"
222
+ },
223
+ "unit": {
224
+ "type": "string",
225
+ "enum": ["C", "F"],
226
+ "description": "Temperature unit (Celsius or Fahrenheit)",
227
+ "default": "C"
228
+ },
229
+ "detailed": {
230
+ "type": "boolean",
231
+ "description": "Include extended forecast",
232
+ "default": false
233
+ }
234
+ },
235
+ "required": ["location"]
236
+ }
237
+ }
238
+ }
239
+ ```
240
+
241
+ ## Schema Generators
242
+
243
+ ### Module Schemas
244
+
245
+ You can generate schemas for all public functions in a module using `create_schemas_from_module`:
246
+
247
+ ```python
248
+ from schemez import create_schemas_from_module
249
+ import math
250
+
251
+ # Generate schemas for all public functions
252
+ schemas = create_schemas_from_module(math)
253
+
254
+ # Generate schemas for specific functions only
255
+ schemas = create_schemas_from_module(math, include_functions=['sin', 'cos'])
256
+
257
+ # Import module by string name
258
+ schemas = create_schemas_from_module('math')
259
+ ```
260
+
261
+ ### Class Schemas
262
+
263
+ Generate schemas for all public methods in a class using `create_schemas_from_class`:
264
+
265
+ ```python
266
+ from schemez import create_schemas_from_class
267
+
268
+ class Calculator:
269
+ def add(self, x: int, y: int) -> int:
270
+ """Add two numbers.
271
+
272
+ Args:
273
+ x: First number
274
+ y: Second number
275
+
276
+ Returns:
277
+ Sum of x and y
278
+ """
279
+ return x + y
280
+
281
+ @classmethod
282
+ def multiply(cls, x: int, y: int) -> int:
283
+ """Multiply two numbers.
284
+
285
+ Args:
286
+ x: First number
287
+ y: Second number
288
+
289
+ Returns:
290
+ Product of x and y
291
+ """
292
+ return x * y
293
+
294
+ @staticmethod
295
+ def divide(x: float, y: float) -> float:
296
+ """Divide two numbers.
297
+
298
+ Args:
299
+ x: Numerator
300
+ y: Denominator
301
+
302
+ Returns:
303
+ Result of x divided by y
304
+ """
305
+ return x / y
306
+
307
+ # Generate schemas for all public methods
308
+ schemas = create_schemas_from_class(Calculator)
309
+
310
+ # Access individual method schemas
311
+ add_schema = schemas['Calculator.add']
312
+ multiply_schema = schemas['Calculator.multiply']
313
+ divide_schema = schemas['Calculator.divide']
314
+ ```
315
+
316
+ The schema generators support:
317
+
318
+ - Regular functions
319
+ - Regular instance methods (bound and unbound)
320
+ - Class methods
321
+ - Static methods
322
+ - Decorated functions / methods
323
+ - Async functions / methods
324
+ - Property methods
325
+ - Basically all stdlib typing features as well as many stdlib types
326
+ - Method docstrings for descriptions
327
+ - Default values
328
+ - Return type hints
329
+
330
+
331
+ ## Diferences to pydantic schema generation
332
+
333
+ While Pydantics schema generation preserves detailed type information, `schema.model_dump_openai()`
334
+ simplifies types to match OpenAI's function calling format. Most special types
335
+ (datetime, UUID, Path, etc.) are handled similarly by both (we only strip unused information), but we handle enums
336
+ differently: Instead of preserving enum class information, we extract just the values
337
+ as a string enum. Union types and Optionals are also handled differently - we typically
338
+ pick the first type to keep the schema simple and practical for AI interaction.
339
+ This ensures compatibility with OpenAI's function calling API while maintaining enough
340
+ type information for the AI to understand the function signature.
@@ -0,0 +1,296 @@
1
+ # Schemez
2
+
3
+ [![PyPI License](https://img.shields.io/pypi/l/schemez.svg)](https://pypi.org/project/schemez/)
4
+ [![Package status](https://img.shields.io/pypi/status/schemez.svg)](https://pypi.org/project/schemez/)
5
+ [![Monthly downloads](https://img.shields.io/pypi/dm/schemez.svg)](https://pypi.org/project/schemez/)
6
+ [![Distribution format](https://img.shields.io/pypi/format/schemez.svg)](https://pypi.org/project/schemez/)
7
+ [![Wheel availability](https://img.shields.io/pypi/wheel/schemez.svg)](https://pypi.org/project/schemez/)
8
+ [![Python version](https://img.shields.io/pypi/pyversions/schemez.svg)](https://pypi.org/project/schemez/)
9
+ [![Implementation](https://img.shields.io/pypi/implementation/schemez.svg)](https://pypi.org/project/schemez/)
10
+ [![Releases](https://img.shields.io/github/downloads/phil65/schemez/total.svg)](https://github.com/phil65/schemez/releases)
11
+ [![Github Contributors](https://img.shields.io/github/contributors/phil65/schemez)](https://github.com/phil65/schemez/graphs/contributors)
12
+ [![Github Discussions](https://img.shields.io/github/discussions/phil65/schemez)](https://github.com/phil65/schemez/discussions)
13
+ [![Github Forks](https://img.shields.io/github/forks/phil65/schemez)](https://github.com/phil65/schemez/forks)
14
+ [![Github Issues](https://img.shields.io/github/issues/phil65/schemez)](https://github.com/phil65/schemez/issues)
15
+ [![Github Issues](https://img.shields.io/github/issues-pr/phil65/schemez)](https://github.com/phil65/schemez/pulls)
16
+ [![Github Watchers](https://img.shields.io/github/watchers/phil65/schemez)](https://github.com/phil65/schemez/watchers)
17
+ [![Github Stars](https://img.shields.io/github/stars/phil65/schemez)](https://github.com/phil65/schemez/stars)
18
+ [![Github Repository size](https://img.shields.io/github/repo-size/phil65/schemez)](https://github.com/phil65/schemez)
19
+ [![Github last commit](https://img.shields.io/github/last-commit/phil65/schemez)](https://github.com/phil65/schemez/commits)
20
+ [![Github release date](https://img.shields.io/github/release-date/phil65/schemez)](https://github.com/phil65/schemez/releases)
21
+ [![Github language count](https://img.shields.io/github/languages/count/phil65/schemez)](https://github.com/phil65/schemez)
22
+ [![Github commits this month](https://img.shields.io/github/commit-activity/m/phil65/schemez)](https://github.com/phil65/schemez)
23
+ [![Package status](https://codecov.io/gh/phil65/schemez/branch/main/graph/badge.svg)](https://codecov.io/gh/phil65/schemez/)
24
+ [![PyUp](https://pyup.io/repos/github/phil65/schemez/shield.svg)](https://pyup.io/repos/github/phil65/schemez/)
25
+
26
+ [Read the documentation!](https://phil65.github.io/schemez/)
27
+
28
+
29
+
30
+ # OpenAI Function Schema Generator
31
+
32
+ Convert Python functions to OpenAI-compatible function schemas automatically.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install schemez
38
+ ```
39
+
40
+ ## Basic Usage
41
+
42
+ ```python
43
+ from schemez import create_schema
44
+ from typing import Literal
45
+
46
+ def get_weather(
47
+ location: str,
48
+ unit: Literal["C", "F"] = "C",
49
+ detailed: bool = False,
50
+ ) -> dict[str, str | float]:
51
+ """Get the weather for a location.
52
+
53
+ Args:
54
+ location: City or address to get weather for
55
+ unit: Temperature unit (Celsius or Fahrenheit)
56
+ detailed: Include extended forecast
57
+ """
58
+ return {"temp": 22.5, "conditions": "sunny"}
59
+
60
+ # Create schema
61
+ schema = create_schema(get_weather)
62
+
63
+ # The schema.model_dump_openai() returns a TypedDict with the complete OpenAI tool definition:
64
+ # OpenAIFunctionTool = TypedDict({
65
+ # "type": Literal["function"],
66
+ # "function": OpenAIFunctionDefinition
67
+ # })
68
+
69
+ # Use with OpenAI
70
+ from openai import OpenAI
71
+
72
+ client = OpenAI()
73
+ response = client.chat.completions.create(
74
+ model="gpt-4",
75
+ messages=[{"role": "user", "content": "What's the weather in London?"}],
76
+ tools=[schema.model_dump_openai()], # Schema includes the type: "function" wrapper
77
+ tool_choice="auto"
78
+ )
79
+ ```
80
+
81
+ > **Note**: This library supports the OpenAI API v1 format (openai>=1.0.0). For older
82
+ > versions of the OpenAI package that use the legacy functions API, you'll need to
83
+ > unwrap the function definition using `schema.model_dump_openai()["function"]`.
84
+ ```
85
+
86
+ ## Supported Types
87
+
88
+ ### Basic Types
89
+ ```python
90
+ def func(
91
+ text: str, # -> "type": "string"
92
+ number: int, # -> "type": "integer"
93
+ amount: float, # -> "type": "number"
94
+ enabled: bool, # -> "type": "boolean"
95
+ anything: Any, # -> "type": "string"
96
+ ) -> None: ...
97
+ ```
98
+
99
+ ### Container Types
100
+ ```python
101
+ def func(
102
+ items: list[str], # -> "type": "array", "items": {"type": "string"}
103
+ numbers: set[int], # -> same as list
104
+ mapping: dict[str, Any], # -> "type": "object", "additionalProperties": true
105
+ nested: list[dict[str, int]], # -> nested array/object types
106
+ sequence: Sequence[str], # -> "type": "array"
107
+ collection: Collection[int], # -> "type": "array"
108
+ ) -> None: ...
109
+ ```
110
+
111
+ ### Enums and Literals
112
+ ```python
113
+ class Color(Enum):
114
+ RED = "red"
115
+ BLUE = "blue"
116
+
117
+ def func(
118
+ color: Color, # -> "type": "string", "enum": ["red", "blue"]
119
+ mode: Literal["fast", "slow"], # -> "type": "string", "enum": ["fast", "slow"]
120
+ ) -> None: ...
121
+ ```
122
+
123
+ ### Optional and Union Types
124
+ ```python
125
+ def func(
126
+ opt1: str | None, # -> "type": "string"
127
+ opt2: int | None, # -> "type": "integer"
128
+ union: str | int, # -> "type": "string" (first type)
129
+ ) -> None: ...
130
+ ```
131
+
132
+ ### Custom Types
133
+ ```python
134
+ @dataclass
135
+ class User:
136
+ name: str
137
+ age: int
138
+
139
+ def func(
140
+ user: User, # -> "type": "object"
141
+ data: JsonDict, # -> "type": "object"
142
+ ) -> None: ...
143
+ ```
144
+
145
+ ### Type Aliases
146
+ ```python
147
+ JsonValue = dict[str, Any] | list[Any] | str | int | float | bool | None
148
+ JsonDict = dict[str, JsonValue]
149
+
150
+ def func(
151
+ data: JsonDict, # -> "type": "object"
152
+ values: list[JsonValue], # -> "type": "array"
153
+ ) -> None: ...
154
+ ```
155
+
156
+ ### Recursive Types
157
+ ```python
158
+ def func(
159
+ tree: dict[str, "dict[str, Any] | str"], # -> "type": "object"
160
+ nested: dict[str, list["dict[str, Any]"]], # -> "type": "object"
161
+ ) -> None: ...
162
+ ```
163
+
164
+ ## Generated Schema Example
165
+
166
+ ```python
167
+ {
168
+ "type": "function",
169
+ "function": {
170
+ "name": "get_weather",
171
+ "description": "Get the weather for a location.",
172
+ "parameters": {
173
+ "type": "object",
174
+ "properties": {
175
+ "location": {
176
+ "type": "string",
177
+ "description": "City or address to get weather for"
178
+ },
179
+ "unit": {
180
+ "type": "string",
181
+ "enum": ["C", "F"],
182
+ "description": "Temperature unit (Celsius or Fahrenheit)",
183
+ "default": "C"
184
+ },
185
+ "detailed": {
186
+ "type": "boolean",
187
+ "description": "Include extended forecast",
188
+ "default": false
189
+ }
190
+ },
191
+ "required": ["location"]
192
+ }
193
+ }
194
+ }
195
+ ```
196
+
197
+ ## Schema Generators
198
+
199
+ ### Module Schemas
200
+
201
+ You can generate schemas for all public functions in a module using `create_schemas_from_module`:
202
+
203
+ ```python
204
+ from schemez import create_schemas_from_module
205
+ import math
206
+
207
+ # Generate schemas for all public functions
208
+ schemas = create_schemas_from_module(math)
209
+
210
+ # Generate schemas for specific functions only
211
+ schemas = create_schemas_from_module(math, include_functions=['sin', 'cos'])
212
+
213
+ # Import module by string name
214
+ schemas = create_schemas_from_module('math')
215
+ ```
216
+
217
+ ### Class Schemas
218
+
219
+ Generate schemas for all public methods in a class using `create_schemas_from_class`:
220
+
221
+ ```python
222
+ from schemez import create_schemas_from_class
223
+
224
+ class Calculator:
225
+ def add(self, x: int, y: int) -> int:
226
+ """Add two numbers.
227
+
228
+ Args:
229
+ x: First number
230
+ y: Second number
231
+
232
+ Returns:
233
+ Sum of x and y
234
+ """
235
+ return x + y
236
+
237
+ @classmethod
238
+ def multiply(cls, x: int, y: int) -> int:
239
+ """Multiply two numbers.
240
+
241
+ Args:
242
+ x: First number
243
+ y: Second number
244
+
245
+ Returns:
246
+ Product of x and y
247
+ """
248
+ return x * y
249
+
250
+ @staticmethod
251
+ def divide(x: float, y: float) -> float:
252
+ """Divide two numbers.
253
+
254
+ Args:
255
+ x: Numerator
256
+ y: Denominator
257
+
258
+ Returns:
259
+ Result of x divided by y
260
+ """
261
+ return x / y
262
+
263
+ # Generate schemas for all public methods
264
+ schemas = create_schemas_from_class(Calculator)
265
+
266
+ # Access individual method schemas
267
+ add_schema = schemas['Calculator.add']
268
+ multiply_schema = schemas['Calculator.multiply']
269
+ divide_schema = schemas['Calculator.divide']
270
+ ```
271
+
272
+ The schema generators support:
273
+
274
+ - Regular functions
275
+ - Regular instance methods (bound and unbound)
276
+ - Class methods
277
+ - Static methods
278
+ - Decorated functions / methods
279
+ - Async functions / methods
280
+ - Property methods
281
+ - Basically all stdlib typing features as well as many stdlib types
282
+ - Method docstrings for descriptions
283
+ - Default values
284
+ - Return type hints
285
+
286
+
287
+ ## Diferences to pydantic schema generation
288
+
289
+ While Pydantics schema generation preserves detailed type information, `schema.model_dump_openai()`
290
+ simplifies types to match OpenAI's function calling format. Most special types
291
+ (datetime, UUID, Path, etc.) are handled similarly by both (we only strip unused information), but we handle enums
292
+ differently: Instead of preserving enum class information, we extract just the values
293
+ as a string enum. Union types and Optionals are also handled differently - we typically
294
+ pick the first type to keep the schema simple and practical for AI interaction.
295
+ This ensures compatibility with OpenAI's function calling API while maintaining enough
296
+ type information for the AI to understand the function signature.
@@ -1,10 +1,11 @@
1
1
  [project]
2
2
  name = "schemez"
3
- version = "1.2.0"
3
+ version = "1.2.3"
4
4
  description = "Pydantic shim for config stuff"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
7
- license = { file = "LICENSE" }
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
8
9
  authors = [
9
10
  { name = "Philipp Temminghoff", email = "philipptemminghoff@googlemail.com" },
10
11
  ]
@@ -42,6 +43,8 @@ Source = "https://github.com/phil65/schemez"
42
43
 
43
44
  [project.optional-dependencies]
44
45
  ai = ["llmling-agent", "anyenv>=0.4.14"]
46
+ codegen = ["datamodel-code-generator"]
47
+ tool_execution = ["fastapi>=0.118.2"]
45
48
  yaml = ["yamling"]
46
49
 
47
50
  [dependency-groups]
@@ -258,13 +261,14 @@ combine-as-imports = true
258
261
  [tool.ruff.lint.per-file-ignores]
259
262
  "__init__.py" = ["E402", "I001"]
260
263
  "scripts/*" = ["INP001"]
264
+ "*tests/*" = ["D100"]
261
265
 
262
266
  [tool.ruff.format]
263
- # Enable preview style formatting.
264
267
  preview = true
265
268
 
266
269
  [tool.ty.environment]
267
270
  python-version = "3.13"
271
+ python-platform = "all"
268
272
 
269
273
  [tool.uv]
270
274
  default-groups = ["dev", "lint", "docs"]
@@ -64,7 +64,7 @@ def get_function_model(func: AnyCallable, *, name: str | None = None) -> type[Sc
64
64
 
65
65
  for param_name, param in sig.parameters.items():
66
66
  # Skip self/cls for methods
67
- if param_name in ("self", "cls"):
67
+ if param_name in {"self", "cls"}:
68
68
  continue
69
69
 
70
70
  type_hint = hints.get(param_name, Any)