schemez 1.1.1__py3-none-any.whl → 1.2.0__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.
- schemez/__init__.py +21 -0
- schemez/bind_kwargs.py +193 -0
- schemez/create_type.py +340 -0
- schemez/executable.py +211 -0
- schemez/functionschema.py +772 -0
- schemez/schema_generators.py +215 -0
- schemez/typedefs.py +205 -0
- {schemez-1.1.1.dist-info → schemez-1.2.0.dist-info}/METADATA +2 -1
- schemez-1.2.0.dist-info/RECORD +19 -0
- schemez-1.1.1.dist-info/RECORD +0 -13
- {schemez-1.1.1.dist-info → schemez-1.2.0.dist-info}/WHEEL +0 -0
@@ -0,0 +1,215 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from collections.abc import Callable # noqa: TC003
|
4
|
+
import dataclasses
|
5
|
+
import importlib
|
6
|
+
import inspect
|
7
|
+
import types
|
8
|
+
from typing import Any, Literal, get_type_hints
|
9
|
+
|
10
|
+
import pydantic
|
11
|
+
|
12
|
+
from schemez.functionschema import (
|
13
|
+
FunctionSchema,
|
14
|
+
_resolve_type_annotation,
|
15
|
+
create_schema,
|
16
|
+
)
|
17
|
+
from schemez.typedefs import ToolParameters
|
18
|
+
|
19
|
+
|
20
|
+
def create_schemas_from_callables(
|
21
|
+
callables: dict[str, Callable[..., Any]],
|
22
|
+
prefix: str | Literal[False] | None = None,
|
23
|
+
exclude_private: bool = True,
|
24
|
+
) -> dict[str, FunctionSchema]:
|
25
|
+
"""Generate OpenAI function schemas from a dictionary of callables.
|
26
|
+
|
27
|
+
Args:
|
28
|
+
callables: Dictionary mapping names to callable objects
|
29
|
+
prefix: Schema name prefix to prepend to function names.
|
30
|
+
If None, no prefix. If False, use raw name.
|
31
|
+
If string, uses that prefix.
|
32
|
+
exclude_private: Whether to exclude callables starting with underscore
|
33
|
+
|
34
|
+
Returns:
|
35
|
+
Dictionary mapping qualified names to FunctionSchema objects
|
36
|
+
|
37
|
+
Example:
|
38
|
+
>>> def foo(x: int) -> str: ...
|
39
|
+
>>> def bar(y: float) -> int: ...
|
40
|
+
>>> callables = {'foo': foo, 'bar': bar}
|
41
|
+
>>> schemas = create_schemas_from_callables(callables, prefix='math')
|
42
|
+
>>> print(schemas['math.foo'])
|
43
|
+
"""
|
44
|
+
schemas = {}
|
45
|
+
|
46
|
+
for name, callable_obj in callables.items():
|
47
|
+
# Skip private members if requested
|
48
|
+
if exclude_private and name.startswith("_"):
|
49
|
+
continue
|
50
|
+
|
51
|
+
# Generate schema key based on prefix setting
|
52
|
+
key = name if prefix is False else f"{prefix}.{name}" if prefix else name
|
53
|
+
schemas[key] = create_schema(callable_obj)
|
54
|
+
|
55
|
+
return schemas
|
56
|
+
|
57
|
+
|
58
|
+
def create_schemas_from_class(
|
59
|
+
cls: type,
|
60
|
+
prefix: str | Literal[False] | None = None,
|
61
|
+
) -> dict[str, FunctionSchema]:
|
62
|
+
"""Generate OpenAI function schemas for all public methods in a class.
|
63
|
+
|
64
|
+
Args:
|
65
|
+
cls: The class to generate schemas from
|
66
|
+
prefix: Schema name prefix. If None, uses class name.
|
67
|
+
If False, no prefix. If string, uses that prefix.
|
68
|
+
|
69
|
+
Returns:
|
70
|
+
Dictionary mapping qualified method names to FunctionSchema objects
|
71
|
+
|
72
|
+
Example:
|
73
|
+
>>> class MyClass:
|
74
|
+
... def my_method(self, x: int) -> str:
|
75
|
+
... return str(x)
|
76
|
+
>>> schemas = create_schemas_from_class(MyClass)
|
77
|
+
>>> print(schemas['MyClass.my_method'])
|
78
|
+
"""
|
79
|
+
callables: dict[str, Callable[..., Any]] = {}
|
80
|
+
|
81
|
+
# Get all attributes of the class
|
82
|
+
for name, attr in inspect.getmembers(cls):
|
83
|
+
# Handle different method types
|
84
|
+
if inspect.isfunction(attr) or inspect.ismethod(attr):
|
85
|
+
callables[name] = attr
|
86
|
+
elif isinstance(attr, classmethod | staticmethod):
|
87
|
+
callables[name] = attr.__get__(None, cls)
|
88
|
+
|
89
|
+
# Use default prefix of class name if not specified
|
90
|
+
effective_prefix = cls.__name__ if prefix is None else prefix
|
91
|
+
return create_schemas_from_callables(callables, prefix=effective_prefix)
|
92
|
+
|
93
|
+
|
94
|
+
def create_constructor_schema(cls: type) -> FunctionSchema:
|
95
|
+
"""Create OpenAI function schema from class constructor.
|
96
|
+
|
97
|
+
Args:
|
98
|
+
cls: Class to create schema for
|
99
|
+
|
100
|
+
Returns:
|
101
|
+
OpenAI function schema for class constructor
|
102
|
+
"""
|
103
|
+
if isinstance(cls, type) and issubclass(cls, pydantic.BaseModel):
|
104
|
+
properties = {}
|
105
|
+
required = []
|
106
|
+
for name, field in cls.model_fields.items():
|
107
|
+
param_type = field.annotation
|
108
|
+
properties[name] = _resolve_type_annotation(
|
109
|
+
param_type,
|
110
|
+
description=field.description,
|
111
|
+
default=field.default,
|
112
|
+
)
|
113
|
+
if field.is_required():
|
114
|
+
required.append(name)
|
115
|
+
|
116
|
+
# Handle dataclasses
|
117
|
+
elif dataclasses.is_dataclass(cls):
|
118
|
+
properties = {}
|
119
|
+
required = []
|
120
|
+
dc_fields = dataclasses.fields(cls)
|
121
|
+
hints = get_type_hints(cls)
|
122
|
+
|
123
|
+
for dc_field in dc_fields:
|
124
|
+
param_type = hints[dc_field.name]
|
125
|
+
properties[dc_field.name] = _resolve_type_annotation(
|
126
|
+
param_type, default=dc_field.default
|
127
|
+
)
|
128
|
+
if (
|
129
|
+
dc_field.default is dataclasses.MISSING
|
130
|
+
and dc_field.default_factory is dataclasses.MISSING
|
131
|
+
):
|
132
|
+
required.append(dc_field.name)
|
133
|
+
|
134
|
+
# Handle regular classes
|
135
|
+
else:
|
136
|
+
sig = inspect.signature(cls.__init__)
|
137
|
+
hints = get_type_hints(cls.__init__)
|
138
|
+
properties = {}
|
139
|
+
required = []
|
140
|
+
|
141
|
+
for name, param in sig.parameters.items():
|
142
|
+
if name == "self":
|
143
|
+
continue
|
144
|
+
|
145
|
+
param_type = hints.get(name, Any)
|
146
|
+
properties[name] = _resolve_type_annotation(
|
147
|
+
param_type,
|
148
|
+
default=param.default,
|
149
|
+
)
|
150
|
+
|
151
|
+
if param.default is param.empty:
|
152
|
+
required.append(name)
|
153
|
+
|
154
|
+
name = f"create_{cls.__name__}"
|
155
|
+
description = inspect.getdoc(cls) or f"Create {cls.__name__} instance"
|
156
|
+
|
157
|
+
# Create parameters with required list included
|
158
|
+
params = ToolParameters({
|
159
|
+
"type": "object",
|
160
|
+
"properties": properties,
|
161
|
+
"required": required,
|
162
|
+
})
|
163
|
+
|
164
|
+
return FunctionSchema(
|
165
|
+
name=name, description=description, parameters=params, required=required
|
166
|
+
)
|
167
|
+
|
168
|
+
|
169
|
+
def create_schemas_from_module(
|
170
|
+
module: types.ModuleType | str,
|
171
|
+
include_functions: list[str] | None = None,
|
172
|
+
prefix: str | Literal[False] | None = None,
|
173
|
+
) -> dict[str, FunctionSchema]:
|
174
|
+
"""Generate OpenAI function schemas from a Python module's functions.
|
175
|
+
|
176
|
+
Args:
|
177
|
+
module: Either a ModuleType object or string name of module to analyze
|
178
|
+
include_functions: Optional list of function names to specifically include
|
179
|
+
prefix: Schema name prefix. If None, uses module name.
|
180
|
+
If False, no prefix. If string, uses that prefix.
|
181
|
+
|
182
|
+
Returns:
|
183
|
+
Dictionary mapping function names to FunctionSchema objects
|
184
|
+
|
185
|
+
Raises:
|
186
|
+
ImportError: If module string name cannot be imported
|
187
|
+
|
188
|
+
Example:
|
189
|
+
>>> import math
|
190
|
+
>>> schemas = create_schemas_from_module(math, ['sin', 'cos'])
|
191
|
+
>>> print(schemas['math.sin'])
|
192
|
+
"""
|
193
|
+
# Resolve module if string name provided
|
194
|
+
mod = (
|
195
|
+
module
|
196
|
+
if isinstance(module, types.ModuleType)
|
197
|
+
else importlib.import_module(module)
|
198
|
+
)
|
199
|
+
|
200
|
+
# Get all functions from module
|
201
|
+
callables: dict[str, Callable[..., Any]] = {
|
202
|
+
name: func
|
203
|
+
for name, func in inspect.getmembers(mod, predicate=inspect.isfunction)
|
204
|
+
if include_functions is None
|
205
|
+
or (name in include_functions and func.__module__.startswith(mod.__name__))
|
206
|
+
}
|
207
|
+
|
208
|
+
# Use default prefix of module name if not specified
|
209
|
+
effective_prefix = mod.__name__ if prefix is None else prefix
|
210
|
+
return create_schemas_from_callables(callables, prefix=effective_prefix)
|
211
|
+
|
212
|
+
|
213
|
+
if __name__ == "__main__":
|
214
|
+
schemas = create_schemas_from_module(__name__)
|
215
|
+
print(schemas)
|
schemez/typedefs.py
ADDED
@@ -0,0 +1,205 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import inspect
|
4
|
+
from typing import Any, Literal, NotRequired, TypedDict
|
5
|
+
|
6
|
+
|
7
|
+
class PropertyBase(TypedDict, total=False):
|
8
|
+
"""Base schema property with common fields."""
|
9
|
+
|
10
|
+
type: str
|
11
|
+
description: str
|
12
|
+
format: str
|
13
|
+
default: Any
|
14
|
+
enum: NotRequired[list[Any]]
|
15
|
+
|
16
|
+
|
17
|
+
class SimpleProperty(PropertyBase):
|
18
|
+
"""Schema property for primitive types."""
|
19
|
+
|
20
|
+
type: Literal["string", "number", "integer", "boolean"]
|
21
|
+
enum: NotRequired[list[Any]]
|
22
|
+
|
23
|
+
|
24
|
+
class ArrayProperty(PropertyBase):
|
25
|
+
"""Schema property for array types."""
|
26
|
+
|
27
|
+
type: Literal["array"]
|
28
|
+
items: Property
|
29
|
+
|
30
|
+
|
31
|
+
class ObjectProperty(PropertyBase):
|
32
|
+
"""Schema property for nested object types."""
|
33
|
+
|
34
|
+
type: Literal["object"]
|
35
|
+
properties: NotRequired[dict[str, Property]]
|
36
|
+
required: NotRequired[list[str]]
|
37
|
+
additionalProperties: NotRequired[bool]
|
38
|
+
|
39
|
+
|
40
|
+
Property = ArrayProperty | ObjectProperty | SimpleProperty
|
41
|
+
|
42
|
+
|
43
|
+
class ToolParameters(TypedDict):
|
44
|
+
"""Schema for function parameters."""
|
45
|
+
|
46
|
+
type: Literal["object"]
|
47
|
+
properties: dict[str, Property]
|
48
|
+
required: NotRequired[list[str]]
|
49
|
+
|
50
|
+
|
51
|
+
class OpenAIFunctionDefinition(TypedDict):
|
52
|
+
"""Schema for the function definition part of an OpenAI tool.
|
53
|
+
|
54
|
+
This represents the inner "function" object that contains the actual
|
55
|
+
function metadata and parameters.
|
56
|
+
"""
|
57
|
+
|
58
|
+
name: str
|
59
|
+
description: str
|
60
|
+
parameters: ToolParameters
|
61
|
+
|
62
|
+
|
63
|
+
class OpenAIFunctionTool(TypedDict):
|
64
|
+
"""Complete OpenAI tool definition for function calling.
|
65
|
+
|
66
|
+
This represents the top-level tool object that wraps a function definition
|
67
|
+
and identifies it as a function tool type.
|
68
|
+
"""
|
69
|
+
|
70
|
+
type: Literal["function"]
|
71
|
+
function: OpenAIFunctionDefinition
|
72
|
+
|
73
|
+
|
74
|
+
def _create_simple_property(
|
75
|
+
type_str: Literal["string", "number", "integer", "boolean"],
|
76
|
+
description: str | None = None,
|
77
|
+
enum_values: list[Any] | None = None,
|
78
|
+
default: Any = None,
|
79
|
+
fmt: str | None = None,
|
80
|
+
) -> SimpleProperty:
|
81
|
+
"""Create a simple property."""
|
82
|
+
prop: SimpleProperty = {"type": type_str}
|
83
|
+
if description is not None:
|
84
|
+
prop["description"] = description
|
85
|
+
if enum_values is not None:
|
86
|
+
prop["enum"] = enum_values
|
87
|
+
if default is not inspect.Parameter.empty and default is not None:
|
88
|
+
prop["default"] = default
|
89
|
+
if fmt is not None:
|
90
|
+
prop["format"] = fmt
|
91
|
+
return prop
|
92
|
+
|
93
|
+
|
94
|
+
def _create_array_property(
|
95
|
+
items: Property,
|
96
|
+
description: str | None = None,
|
97
|
+
) -> ArrayProperty:
|
98
|
+
"""Create an array property."""
|
99
|
+
prop: ArrayProperty = {
|
100
|
+
"type": "array",
|
101
|
+
"items": items,
|
102
|
+
}
|
103
|
+
if description is not None:
|
104
|
+
prop["description"] = description
|
105
|
+
return prop
|
106
|
+
|
107
|
+
|
108
|
+
def _create_object_property(
|
109
|
+
description: str | None = None,
|
110
|
+
properties: dict[str, Property] | None = None,
|
111
|
+
required: list[str] | None = None,
|
112
|
+
additional_properties: bool | None = None,
|
113
|
+
) -> ObjectProperty:
|
114
|
+
"""Create an object property.
|
115
|
+
|
116
|
+
Args:
|
117
|
+
description: Optional property description
|
118
|
+
properties: Optional dict of property definitions
|
119
|
+
required: Optional list of required property names
|
120
|
+
additional_properties: Whether to allow additional properties
|
121
|
+
|
122
|
+
Returns:
|
123
|
+
Object property definition
|
124
|
+
"""
|
125
|
+
prop: ObjectProperty = {"type": "object"}
|
126
|
+
if description is not None:
|
127
|
+
prop["description"] = description
|
128
|
+
if properties is not None:
|
129
|
+
prop["properties"] = properties
|
130
|
+
if required is not None:
|
131
|
+
prop["required"] = required
|
132
|
+
if additional_properties is not None:
|
133
|
+
prop["additionalProperties"] = additional_properties
|
134
|
+
return prop
|
135
|
+
|
136
|
+
|
137
|
+
def _convert_complex_property(
|
138
|
+
prop: dict[str, Any],
|
139
|
+
description: str | None = None,
|
140
|
+
) -> Property:
|
141
|
+
"""Convert complex schema properties to simple OpenAI-compatible types.
|
142
|
+
|
143
|
+
Args:
|
144
|
+
prop: Complex property definition
|
145
|
+
description: Optional property description
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
Simplified Property compatible with OpenAI
|
149
|
+
"""
|
150
|
+
if "anyOf" in prop or "oneOf" in prop:
|
151
|
+
types = []
|
152
|
+
for subschema in prop.get("anyOf", prop.get("oneOf", [])):
|
153
|
+
if isinstance(subschema, dict):
|
154
|
+
types.append(subschema.get("type")) # noqa: PERF401
|
155
|
+
|
156
|
+
# If null is allowed, treat as optional string
|
157
|
+
if "null" in types:
|
158
|
+
return _create_simple_property(
|
159
|
+
type_str="string",
|
160
|
+
description=description or prop.get("description"),
|
161
|
+
default=None,
|
162
|
+
)
|
163
|
+
|
164
|
+
# Get first non-null type or default to string
|
165
|
+
first_type = next((t for t in types if t != "null"), "string")
|
166
|
+
if first_type not in ("string", "number", "integer", "boolean"):
|
167
|
+
first_type = "string"
|
168
|
+
|
169
|
+
return _create_simple_property(
|
170
|
+
type_str=first_type, # type: ignore # Valid since we checked above
|
171
|
+
description=description or prop.get("description"),
|
172
|
+
default=prop.get("default"),
|
173
|
+
)
|
174
|
+
|
175
|
+
if prop.get("type") == "array":
|
176
|
+
items = prop.get("items", {"type": "string"})
|
177
|
+
if isinstance(items, dict):
|
178
|
+
items = _convert_complex_property(items)
|
179
|
+
return _create_array_property(
|
180
|
+
items=items,
|
181
|
+
description=description or prop.get("description"),
|
182
|
+
)
|
183
|
+
|
184
|
+
if prop.get("type") == "object":
|
185
|
+
sub_props = prop.get("properties", {})
|
186
|
+
cleaned_props = {
|
187
|
+
name: _convert_complex_property(p) for name, p in sub_props.items()
|
188
|
+
}
|
189
|
+
return _create_object_property(
|
190
|
+
description=description or prop.get("description"),
|
191
|
+
properties=cleaned_props,
|
192
|
+
required=prop.get("required"),
|
193
|
+
)
|
194
|
+
|
195
|
+
type_str = prop.get("type", "string")
|
196
|
+
if type_str not in ("string", "number", "integer", "boolean"):
|
197
|
+
type_str = "string"
|
198
|
+
|
199
|
+
return _create_simple_property(
|
200
|
+
type_str=type_str, # type: ignore # Valid since we checked above
|
201
|
+
description=description or prop.get("description"),
|
202
|
+
enum_values=prop.get("enum"),
|
203
|
+
default=prop.get("default"),
|
204
|
+
fmt=prop.get("format"),
|
205
|
+
)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: schemez
|
3
|
-
Version: 1.
|
3
|
+
Version: 1.2.0
|
4
4
|
Summary: Pydantic shim for config stuff
|
5
5
|
Keywords:
|
6
6
|
Author: Philipp Temminghoff
|
@@ -41,6 +41,7 @@ Classifier: Topic :: Documentation
|
|
41
41
|
Classifier: Topic :: Software Development
|
42
42
|
Classifier: Topic :: Utilities
|
43
43
|
Classifier: Typing :: Typed
|
44
|
+
Requires-Dist: docstring-parser>=0.17.0
|
44
45
|
Requires-Dist: griffe>=1.7.3
|
45
46
|
Requires-Dist: pydantic
|
46
47
|
Requires-Dist: universal-pathlib>=0.2.6
|
@@ -0,0 +1,19 @@
|
|
1
|
+
schemez/__init__.py,sha256=KkwJF8pfbzw_4cBxwXuUyXIExqdxS8iumvyAL-JUED4,1669
|
2
|
+
schemez/bind_kwargs.py,sha256=ChyArgNa5R8VdwSJmmrQItMH9Ld6hStWBISw-T1wyws,6228
|
3
|
+
schemez/code.py,sha256=usZLov9i5KpK1W2VJxngUzeetgrINtodiooG_AxN-y4,2072
|
4
|
+
schemez/convert.py,sha256=b6Sz11lq0HvpXfMREOqnnw8rcVg2XzTKhjjPNc4YIoE,4403
|
5
|
+
schemez/create_type.py,sha256=wrdqdzXtfxZfsgp9IroldoYGTJs_Rdli8TiscqhV2bI,11647
|
6
|
+
schemez/docstrings.py,sha256=kmd660wcomXzKac0SSNYxPRNbVCUovrpmE9jwnVRS6c,4115
|
7
|
+
schemez/executable.py,sha256=YM4WcmRyJ9CpzKpNgS0A-Ri0Jd7mAzfHmoaXONI-mIs,7134
|
8
|
+
schemez/functionschema.py,sha256=Z8kL1ckU6pEoRhOsFY6NziLhVudELHyylsFVXrCUcwU,26127
|
9
|
+
schemez/helpers.py,sha256=IVuoFbzPJs3eqJBrr0BA6SIHncoU6BFJGP41zTijzXM,8716
|
10
|
+
schemez/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
|
+
schemez/pydantic_types.py,sha256=8vgSl8i2z9n0fB-8AJj-D3TBByEWE5IxItBxQ0XwXFI,1640
|
12
|
+
schemez/schema.py,sha256=u6SDhYDtfCjgy2Aa-_MDLLNcUfEXbeye4T-W6s3AED8,9558
|
13
|
+
schemez/schema_generators.py,sha256=Gze7S7dQkTsl_1ckeHLXPxx4jQo7RB6hHQM-5fpAsrA,6973
|
14
|
+
schemez/schemadef/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
15
|
+
schemez/schemadef/schemadef.py,sha256=FtD7TOnYxiuYOIfadRHKkkbZn98mWFb0_lKfPsPR-hI,14393
|
16
|
+
schemez/typedefs.py,sha256=kxh-Vc5eKvCShdznJrg5N4_Fr8g1kYlkadEAdzgQ43w,6091
|
17
|
+
schemez-1.2.0.dist-info/WHEEL,sha256=I8-bO5cg2sb8TH6ZM6EgCP87Y1cV_f9UGgWnfAhVOZI,78
|
18
|
+
schemez-1.2.0.dist-info/METADATA,sha256=Nao7AGsQ0CGUiHDXT2nSE0AMOnwqlMybd8KTQSAaIB0,5399
|
19
|
+
schemez-1.2.0.dist-info/RECORD,,
|
schemez-1.1.1.dist-info/RECORD
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
schemez/__init__.py,sha256=iDo1ZpV07BUOmRmISV6QDA8s3viJR5V1NnrBsdw6eVM,985
|
2
|
-
schemez/code.py,sha256=usZLov9i5KpK1W2VJxngUzeetgrINtodiooG_AxN-y4,2072
|
3
|
-
schemez/convert.py,sha256=b6Sz11lq0HvpXfMREOqnnw8rcVg2XzTKhjjPNc4YIoE,4403
|
4
|
-
schemez/docstrings.py,sha256=kmd660wcomXzKac0SSNYxPRNbVCUovrpmE9jwnVRS6c,4115
|
5
|
-
schemez/helpers.py,sha256=IVuoFbzPJs3eqJBrr0BA6SIHncoU6BFJGP41zTijzXM,8716
|
6
|
-
schemez/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
-
schemez/pydantic_types.py,sha256=8vgSl8i2z9n0fB-8AJj-D3TBByEWE5IxItBxQ0XwXFI,1640
|
8
|
-
schemez/schema.py,sha256=u6SDhYDtfCjgy2Aa-_MDLLNcUfEXbeye4T-W6s3AED8,9558
|
9
|
-
schemez/schemadef/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
-
schemez/schemadef/schemadef.py,sha256=FtD7TOnYxiuYOIfadRHKkkbZn98mWFb0_lKfPsPR-hI,14393
|
11
|
-
schemez-1.1.1.dist-info/WHEEL,sha256=I8-bO5cg2sb8TH6ZM6EgCP87Y1cV_f9UGgWnfAhVOZI,78
|
12
|
-
schemez-1.1.1.dist-info/METADATA,sha256=JwgerPl41Wss2TGr4FLUr3tic62ma4lUAN8rTqgJA9I,5359
|
13
|
-
schemez-1.1.1.dist-info/RECORD,,
|
File without changes
|