Skip to content

Commit 6c0d695

Browse files
Merge pull request #299 from claimed-framework/merge-mlx
Merge mlx
2 parents 993fff0 + c89b36f commit 6c0d695

16 files changed

Lines changed: 608 additions & 3 deletions
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
name: Bug report
3+
about: Create a report to help us improve
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
**Describe the bug**
11+
12+
A clear and concise description of what the bug is.
13+
14+
**To Reproduce**
15+
16+
Steps to reproduce the behavior:
17+
1. Go to '...'
18+
2. Click on '....'
19+
3. Scroll down to '....'
20+
4. See error
21+
22+
**Expected behavior**
23+
24+
A clear and concise description of what you expected to happen.
25+
26+
**Screenshots**
27+
28+
If applicable, add screenshots to help explain your problem.
29+
30+
**Environment**
31+
32+
- OS: [e.g. iOS]
33+
- Browser [e.g. chrome, safari]
34+
- MLX Version [e.g. 22]
35+
36+
**Additional context**
37+
38+
Add any other context about the problem here.

.github/workflows/publish-pypi.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Build and publish Python package
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*' # publish only on tag pushes like v1.2.3
7+
8+
jobs:
9+
build-and-publish:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Checkout
13+
uses: actions/checkout@v4
14+
with:
15+
fetch-depth: 0 # necessary for setuptools_scm to see tags
16+
17+
- name: Set up Python
18+
uses: actions/setup-python@v4
19+
with:
20+
python-version: "3.10"
21+
22+
- name: Install build & twine
23+
run: python -m pip install --upgrade pip build twine setuptools_scm
24+
25+
- name: Build sdist and wheel
26+
run: python -m build --sdist --wheel
27+
28+
- name: Check artifacts
29+
run: ls -l dist
30+
31+
- name: Publish to PyPI
32+
env:
33+
TWINE_USERNAME: __token__
34+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
35+
run: |
36+
python -m twine check dist/*
37+
python -m twine upload dist/* --non-interactive

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
venv/
22
.venv/
33
__pycache__
4-
.ipynb_checkpoints/
4+
.ipynb_checkpoints/

MAINTAINERS.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# MAINTAINERS
2+
3+
Following is the current list of maintainers on this project
4+
5+
The maintainers are listed in alphabetical order.
6+
7+
- [@romeokienzler](https://github.com/romeokienzler) (Romeo Kienzler)
8+
- [@GlennVerhaag](https://github.com/GlennVerhaag) (Glenn Verhaag)

OWNERS

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
approvers:
2+
- animeshsingh
3+
- ckadner
4+
- Tomcli
5+
- drewbutlerbb4
6+
- yhwang
7+
reviewers:
8+
- animeshsingh
9+
- ckadner
10+
- Tomcli
11+
- drewbutlerbb4
12+
- yhwang

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,4 @@ Interested in helping make CLAIMED better? We encourage you to take a look at ou
5757
CLAIMED is supported by the EU’s Horizon Europe program under Grant Agreement number 101131841 and also received funding from the Swiss State Secretariat for Education, Research and Innovation (SERI) and the UK Research and Innovation (UKRI).
5858

5959
## License
60-
This software is released under Apache License v2.0.
60+
This software is released under Apache License v2.0.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,4 @@ c3_create_gridwrapper = "c3.create_gridwrapper:main"
4747
where = ["src"]
4848

4949
[tool.setuptools.package-data]
50-
"c3.templates" = ["*"]
50+
"c3.templates" = ["*"]

src/mlx/__init__.py

Whitespace-only changes.

src/mlx/cos_backend.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import json
2+
import boto3
3+
import jsonschema
4+
from jsonschema import validate
5+
import os
6+
7+
class COSKVStore:
8+
def __init__(self, bucket_name, schema, cos_client=None):
9+
"""
10+
Initialize the COS Key-Value store.
11+
:param bucket_name: Name of the COS bucket.
12+
:param schema: JSON Schema to validate values.
13+
:param cos_client: Optional COS client instance (for dependency injection).
14+
"""
15+
self.bucket_name = bucket_name
16+
self.schema = schema
17+
self.cos_client = cos_client or boto3.client('s3')
18+
19+
def put(self, key, value):
20+
"""
21+
Store a value in COS after validating against the JSON schema.
22+
:param key: The key under which the value is stored.
23+
:param value: The value to store (must be JSON-serializable).
24+
"""
25+
try:
26+
validate(instance=value, schema=self.schema)
27+
except jsonschema.exceptions.ValidationError as e:
28+
raise ValueError(f"Validation error: {e.message}")
29+
self.cos_client.put_object(
30+
Bucket=self.bucket_name,
31+
Key=key,
32+
Body=json.dumps(value)
33+
)
34+
35+
def get(self, key):
36+
"""
37+
Retrieve a value from COS.
38+
:param key: The key to retrieve.
39+
:return: The stored value as a dictionary.
40+
"""
41+
try:
42+
response = self.cos_client.get_object(Bucket=self.bucket_name, Key=key)
43+
return json.loads(response['Body'].read().decode('utf-8'))
44+
except self.cos_client.exceptions.NoSuchKey:
45+
raise KeyError(f"Key '{key}' not found in bucket '{self.bucket_name}'")
46+
47+
def delete(self, key):
48+
"""
49+
Delete a key-value pair from COS.
50+
:param key: The key to delete.
51+
"""
52+
self.cos_client.delete_object(Bucket=self.bucket_name, Key=key)
53+
54+
def list_keys(self):
55+
"""
56+
List all keys in the COS bucket.
57+
:return: A list of keys.
58+
"""
59+
response = self.cos_client.list_objects_v2(Bucket=self.bucket_name)
60+
return [obj['Key'] for obj in response.get('Contents', [])]
61+
62+
def load_schemas(schema_folder):
63+
"""
64+
Loads all JSON schemas from the given folder.
65+
:param schema_folder: Path to the folder containing JSON schema files.
66+
:return: A dictionary of schema names and their corresponding JSON objects.
67+
"""
68+
schemas = {}
69+
for filename in os.listdir(schema_folder):
70+
if filename.endswith(".json"):
71+
filepath = os.path.join(schema_folder, filename)
72+
with open(filepath, 'r') as f:
73+
schemas[filename[:-5]] = json.load(f)
74+
return schemas
75+
76+
# Example Usage
77+
if __name__ == "__main__":
78+
schema_folder = "../schemas"
79+
schemas = load_schemas(schema_folder)
80+
81+
if "example_schema" in schemas:
82+
example_schema = schemas["example_schema"]
83+
cos_store = COSKVStore("my-cos-bucket", example_schema)
84+
85+
test_data = {
86+
"id": "model_123",
87+
"name": "MyModel",
88+
"framework": "TensorFlow",
89+
"version": "2.10",
90+
"description": "A simple neural network model.",
91+
"metrics": {
92+
"accuracy": 0.95,
93+
"loss": 0.1
94+
}
95+
}
96+
cos_store.put("model_123", test_data)
97+
print(cos_store.get("model_123"))
98+
99+
#Example data without the metric key, which is not required
100+
test_data_no_metrics = {
101+
"id": "model_456",
102+
"name": "MyOtherModel",
103+
"framework": "PyTorch",
104+
"version": "1.12",
105+
"description": "Another neural network model.",
106+
}
107+
cos_store.put("model_456", test_data_no_metrics)
108+
print(cos_store.get("model_456"))
109+
110+
else:
111+
print("Schema 'example_schema' not found.")

0 commit comments

Comments
 (0)