Skip to content

Commit e8fddc9

Browse files
Merge pull request #3 from plexe-ai/chore/add-linting-and-formatting
Chore/add linting and formatting
2 parents 0125aa5 + 9f0ccb7 commit e8fddc9

File tree

12 files changed

+448
-32
lines changed

12 files changed

+448
-32
lines changed

.github/workflows/integration.yml

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,30 @@ on:
1111
- synchronize
1212
- reopened
1313

14-
1514
jobs:
15+
linting:
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout Code
19+
uses: actions/checkout@v4
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v4
23+
with:
24+
python-version: '3.12'
25+
26+
- name: Install Dependencies
27+
run: |
28+
python -m pip install --upgrade pip
29+
pip install poetry
30+
poetry install
31+
32+
- name: Format Code with Black
33+
run: poetry run black --check .
34+
35+
- name: Lint Code with Ruff
36+
run: poetry run ruff check .
37+
1638
run-tests:
1739
runs-on: ubuntu-latest
1840
steps:

.pre-commit-config.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
repos:
2+
- repo: https://github.com/psf/black
3+
rev: 24.10.0
4+
hooks:
5+
- id: black
6+
- repo: https://github.com/astral-sh/ruff-pre-commit
7+
rev: v0.9.1
8+
hooks:
9+
- id: ruff
10+

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,34 @@
11
# smolmodels
22
✨ build specialised ml models from natural language
3+
4+
## 1. Setup Instructions
5+
This project uses `poetry` for dependency management. To set up your development environment, follow these steps:
6+
7+
### 1.1. Install Poetry
8+
Install `poetry` using `pip`:
9+
```bash
10+
pip install poetry
11+
```
12+
Alternatively, you can follow the [official Poetry installation guide](https://python-poetry.org/docs/#installation)
13+
for other methods.
14+
15+
### 1.2. [Optional] Configure Poetry
16+
If you prefer to create the virtual environment inside the project directory, run this command:
17+
```bash
18+
poetry config virtualenvs.in-project true
19+
```
20+
This step is optional. By default, `poetry` manages virtual environments centrally in `~/.cache/pypoetry/virtualenvs`.
21+
22+
### 1.3. Install Dependencies
23+
Run the `setup.py` script to install all dependencies and initialise the pre-commit hooks:
24+
```bash
25+
python setup.py
26+
```
27+
We use a Python setup script to be platform-agnostic.
28+
29+
### 1.4. [Optional] Activate Virtual Environment
30+
To activate the virtual environment manually, run:
31+
```bash
32+
poetry shell
33+
```
34+
This step is optional as `poetry run` or `python setup.py` will handle the environment automatically.

poetry.lock

Lines changed: 287 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,34 @@ python = "^3.12"
1414

1515
[tool.poetry.group.dev.dependencies]
1616
pytest = "^8.3.4"
17+
black = "^24.10.0"
18+
pre-commit = "^4.0.1"
19+
ruff = "^0.9.1"
1720

1821
[build-system]
1922
requires = ["poetry-core"]
2023
build-backend = "poetry.core.masonry.api"
24+
25+
[tool.black]
26+
line-length = 120
27+
target-version = ["py312"]
28+
exclude = '''
29+
/(
30+
\.git
31+
| \.venv
32+
| __pycache__
33+
| build
34+
| dist
35+
)/
36+
'''
37+
38+
[tool.ruff]
39+
line-length = 120
40+
target-version = "py312"
41+
42+
[tool.ruff.lint]
43+
ignore = [
44+
"E203", # Whitespace before ':'
45+
"E501", # Line length
46+
"E402", # Imports not at top of file
47+
]

setup.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import subprocess
2+
import sys
3+
4+
5+
def run_command(command):
6+
try:
7+
subprocess.run(command, check=True, shell=True)
8+
except subprocess.CalledProcessError:
9+
print(f"Failed to run: {command}")
10+
sys.exit(1)
11+
12+
13+
def main():
14+
print("Installing dependencies...")
15+
run_command("poetry install")
16+
17+
print("Installing pre-commit hooks...")
18+
run_command("pre-commit install")
19+
20+
print("Setup complete!")
21+
22+
23+
if __name__ == "__main__":
24+
main()

smolmodels/constraints.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,8 @@ def __init__(self, condition: Callable[[Any, Any], bool], description: Optional[
8989
# Validate that condition is a callable
9090
if not callable(condition):
9191
raise TypeError(
92-
"Condition must be a callable that takes two arguments (inputs, outputs) and returns a boolean.")
92+
"Condition must be a callable that takes two arguments (inputs, outputs) and returns a boolean."
93+
)
9394

9495
# Optionally, check the callable signature (if you want stricter validation)
9596
signature = inspect.signature(condition)
@@ -125,7 +126,7 @@ def __and__(self, other: "Constraint") -> "Constraint":
125126
"""
126127
return Constraint(
127128
condition=lambda inputs, outputs: self.evaluate(inputs, outputs) and other.evaluate(inputs, outputs),
128-
description=f"({self.description}) AND ({other.description})"
129+
description=f"({self.description}) AND ({other.description})",
129130
)
130131

131132
def __or__(self, other: "Constraint") -> "Constraint":
@@ -137,7 +138,7 @@ def __or__(self, other: "Constraint") -> "Constraint":
137138
"""
138139
return Constraint(
139140
condition=lambda inputs, outputs: self.evaluate(inputs, outputs) or other.evaluate(inputs, outputs),
140-
description=f"({self.description}) OR ({other.description})"
141+
description=f"({self.description}) OR ({other.description})",
141142
)
142143

143144
def __invert__(self) -> "Constraint":
@@ -148,5 +149,5 @@ def __invert__(self) -> "Constraint":
148149
"""
149150
return Constraint(
150151
condition=lambda inputs, outputs: not self.evaluate(inputs, outputs),
151-
description=f"NOT ({self.description})"
152+
description=f"NOT ({self.description})",
152153
)

smolmodels/exceptions.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ class SmolmodelsError(Exception):
2121
"""
2222
Base class for all errors in the smolmodels library.
2323
"""
24+
2425
pass
2526

2627

@@ -29,27 +30,31 @@ class SpecificationError(SmolmodelsError):
2930
"""
3031
Base class for errors related to model specification.
3132
"""
33+
3234
pass
3335

3436

3537
class InsufficientSpecificationError(SpecificationError):
3638
"""
3739
Raised when the natural language specification is insufficiently detailed.
3840
"""
41+
3942
pass
4043

4144

4245
class AmbiguousSpecificationError(SpecificationError):
4346
"""
4447
Raised when the natural language specification is ambiguous or contradictory.
4548
"""
49+
4650
pass
4751

4852

4953
class InvalidSchemaError(SpecificationError):
5054
"""
5155
Raised when the input or output schema is invalid.
5256
"""
57+
5358
pass
5459

5560

@@ -58,31 +63,37 @@ class InstructionError(SmolmodelsError):
5863
"""
5964
Base class for errors related to instructions provided for model building.
6065
"""
66+
6167
pass
6268

6369

6470
# todo: add more specific instruction-related errors once we have a better idea of what instructions are
6571

72+
6673
# Constraint-related errors
6774
class ConstraintError(SmolmodelsError):
6875
"""
6976
Base class for errors related to constraints.
7077
"""
78+
7179
pass
7280

7381

7482
# todo: add more specific constraint-related errors once we have a better idea of how constraints are used
7583

84+
7685
# Runtime-related errors
7786
class SmolmodelsRuntimeError(SmolmodelsError, RuntimeError):
7887
"""
7988
Base class for runtime errors during model execution or training.
8089
"""
90+
8191
pass
8292

8393

8494
class CodeExecutionError(SmolmodelsRuntimeError):
8595
"""
8696
Raised when code execution fails for reasons other than timeout.
8797
"""
98+
8899
pass

smolmodels/function.py

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,14 @@
55
from .constraints import Constraint
66
from .callbacks import Callback
77
from .instructions import Instruction
8-
from .exceptions import *
8+
from .exceptions import InsufficientSpecificationError
99

1010

1111
class Function:
1212
# A model is a function that is defined by its input and output domain/ranges, and its behaviour. These
1313
# aspects of a model are not 'mutable' in the sense that changing these means creating a new model, as
1414
# two models with a different description are not the same model.
15-
def __init__(
16-
self,
17-
behaviour: str,
18-
output_schema: dict,
19-
input_schema: dict,
20-
constraints: List[Constraint] = None
21-
):
15+
def __init__(self, behaviour: str, output_schema: dict, input_schema: dict, constraints: List[Constraint] = None):
2216
self.behaviour = behaviour
2317
self.output_schema = output_schema
2418
self.input_schema = input_schema
@@ -32,11 +26,11 @@ def __init__(
3226
# Note: we do not consider the dataset to be a property of the model itself
3327
# Note: there would also be an async version of this method
3428
def build(
35-
self,
36-
dataset: Union[str, Generator] = None,
37-
instructions: List[Instruction] = None, # these are "hints" that can be followed during training
38-
callbacks: List[Callback] = None, # these are functions that are called during training
39-
isolation: Literal['local', 'subprocess', 'docker'] = 'local' # this controls the sandboxing of training
29+
self,
30+
dataset: Union[str, Generator] = None,
31+
instructions: List[Instruction] = None, # these are "hints" that can be followed during training
32+
callbacks: List[Callback] = None, # these are functions that are called during training
33+
isolation: Literal["local", "subprocess", "docker"] = "local", # this controls the sandboxing of training
4034
) -> None:
4135
pass
4236

@@ -55,4 +49,4 @@ def describe(self) -> str:
5549

5650
# Returns a list of "instruction" objects that could be followed to further improve the model
5751
def suggest(self) -> List[Instruction]:
58-
pass
52+
pass

smolmodels/instructions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
# and the class once we find it
33
# todo: we also need to figure out what an instruction really is 😂?
44

5+
56
class Instruction:
6-
pass
7+
pass

0 commit comments

Comments
 (0)