Skip to content

Commit

Permalink
Add format and linter (#62)
Browse files Browse the repository at this point in the history
format, linter and associated workflow
---------

Co-authored-by: Amogh Joshi <[email protected]>
  • Loading branch information
lalmei and amogh7joshi authored Nov 28, 2024
1 parent ddeca32 commit f0fb6ae
Show file tree
Hide file tree
Showing 128 changed files with 12,189 additions and 9,386 deletions.
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: ci

on: [push, pull_request]

jobs:
test:
name: Test - ${{ matrix.python-version }} - ${{matrix.os}}
runs-on: ${{matrix.os}}

strategy:
matrix:
python-version: ["3.11", "3.12"]
os: [ubuntu-latest, macOs-latest]
fail-fast: false

steps:
- uses: actions/checkout@v4
- name: Install the latest version of uv
uses: astral-sh/setup-uv@v3
with:
version: "latest"
enable-cache: true
cache-dependency-glob: "**/pyproject.toml"

- name: Check if cache used
if: steps.setup-uv.outputs.cache-hit == 'true'
run: echo "Cache was restored"

- name: Set up python env
run: |
uv venv --python ${{ matrix.python-version }}
uv sync --dev
- name: Run pre-commit
continue-on-error: true
run: make pre-commit

- name: Run tests
# For example, using `pytest`
run: make test
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ __MACOSX
# Extra directories/files
/**data*/

**/**test*.*
!tests/*/*
agml/_helios
agml/helios_config.sh
Expand All @@ -161,6 +160,7 @@ agml/models/training/*.log
agml/models/training/*.err
agml/models/training/*.out
agml/models/training/*.csv
.*/
# .*/
/
*.pptx
.ruff_cache
49 changes: 42 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing Guidelines

Thank you for choosing to contribute to AgML!
Thank you for choosing to contribute to AgML!

## Contributing Data

Expand Down Expand Up @@ -29,15 +29,15 @@ Image classification datasets are organized in the following directory tree:
└── <label 2>
├── image1.png
├── image2.png
└── image3.png
└── image3.png
```

The `AgMLDataLoader` generates a mapping between each of the label names "label 1", "label 2", etc.,
and a numerical value.
and a numerical value.

#### Object Detection

Object detection datasets are constructed using COCO JSON formatting. For a general overview, see
Object detection datasets are constructed using COCO JSON formatting. For a general overview, see
[https://cocodataset.org/#format-data](https://cocodataset.org/#format-data).
Another good resource is [https://docs.aws.amazon.com/rekognition/latest/customlabels-dg/cd-transform-coco.html](https://docs.aws.amazon.com/rekognition/latest/customlabels-dg/cd-transform-coco.html).
Once you have the images and the bounding box annotations, this involves generating a dictionary with four keys:
Expand Down Expand Up @@ -75,7 +75,7 @@ The dictionary containing this information should be written to a file called `a
└── images
├── image1.png
├── image2.png
└── image3.png
└── image3.png
```

#### Semantic Segmentation
Expand Down Expand Up @@ -104,7 +104,7 @@ The directory tree should look like follows:
## Contributing a Dataset

If you've found a new dataset that *isn't already being used* in AgML and you want to add it, there's a few things you
need to do.
need to do.

Any preprocessing code being used for the dataset can be kept in `agml/_internal/preprocess.py`, by adding an `elif` statement
to the `preprocess()` method with the dataset name. If there is no preprocessing code, then just put a `pass` statement in the block.
Expand Down Expand Up @@ -164,7 +164,7 @@ then put "worldwide" for both "continent" and "country".
| Dataset Format | `ml_task` | `annotation_format` |
| :------------: | :-------: | :-----------------: |
| Image Classification | `image_classification` | `directory_names` |
| Object Detection | `object_detection` | `coco_json` |
| Object Detection | `object_detection` | `coco_json` |
| Semantic Segmentation | `semantic_segmentation` | `image` |


Expand All @@ -184,3 +184,38 @@ If the dataset has no license or has no citation, leave the corresponding lines
Once you've readied the dataset, create a new pull request on the AgML repository.
We will then review the changes and review next steps for adding the dataset into AgML's public data storage.


## Developement Guidelines


### Installing uv
Dependencies and admin actions are done using `uv`. To Install uv follow the guidelines in https://docs.astral.sh/uv/getting-started/installation/, it is recommended to use the standalone installation.


### Building Project

The build the associated wheels simply run:

```
make build
```

To sync the dependencies simply run:

```
uv sync
```

### Running tests

```
make test
```

### Running scripts

For running scripts or one-offs using the project's installed enviroment

```
uv run python <script>
```
74 changes: 74 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@

SHELL := bash

version := 0.7.0

src.python := $(shell find ./agml -type f -name "*.py" || :)
test.python := $(shell find ./tests -type f -name "*.py" || :)

uv.project.enviroment := .venv
dist.dir := dist
build.wheel := $(dist.dir)/agml-$(version).tar.gz





.PHONY: help
help: ## Print the help screen.
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":|:[[:space:]].*?##"}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

# Setup and Build


install: setup ## Installing dependencies
uv sync

setup: ## Setup the project.
uv venv $(uv.project.enviroment)


$(build.wheel): $(src.python) ## Build wheels
uv build -o $(dist.dir)

build: $(build.wheel) ## Build the distribution wheel.

test: $(test.python) $(src.python) ## Run tests
uv run pytest -c=config/pytest.ini $(test.python)


# Quality Checks

.PHONY: pre-commit
pre-commit: check-format lint check-types docstring-coverage


.PHONY: check-types
check-types: ## Run mypy to check type definitions.
uv run mypy --config=config/mypy.ini $(src.python) $(test.python)


.PHONY: check-format
check-format: ## Check ruff format
uv run ruff format --check --config=config/ruff.toml $(src.python) $(test.python)


.PHONY: lint
lint: ## Run ruff Code Linter
uv run ruff check --config=config/ruff.toml $(src.python) $(test.python)

.PHONY:docstring-coverage
docstring-coverage: ## Compute docstring coverage
uv run interrogate -c config/interrogate.toml .

# Automated Quality fixes

.PHONY: lint-fix
lint-fix: ## Fix ruff Lint issues
uv run ruff check --fix --config=config/ruff.toml $(src.python) $(test.python)


.PHONY: format
format: ## Run ruff format (Includes sorting of imports)
uv run ruff check --select I --config=config/ruff.toml --fix
uv run ruff format --config=config/ruff.toml $(src.python) $(test.python)
30 changes: 17 additions & 13 deletions agml/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,31 @@
# See the License for the specific language governing permissions and
# limitations under the License.

__version__ = '0.7.0'
__all__ = ['data', 'synthetic', 'backend', 'viz', 'io']
__version__ = "0.7.0"
__all__ = ["data", "synthetic", "backend", "viz", "io"]


# If AgML is being imported for the first time, then we need to setup
# the module, namely prepping the config file.
def _setup():
import os as _os
import json as _json
if not _os.path.exists(_os.path.expanduser('~/.agml')):
_os.makedirs(_os.path.expanduser('~/.agml'))
with open(_os.path.join(
_os.path.expanduser('~/.agml/config.json')), 'w') as f:
_json.dump({'data_path': _os.path.expanduser('~/.agml/datasets'),
'viz_backend': 'matplotlib'}, f)
_setup(); del _setup # noqa
import os as _os


# There are no top-level imported functions or classes, only the modules.
from . import data, backend, synthetic, viz, io
if not _os.path.exists(_os.path.expanduser("~/.agml")):
_os.makedirs(_os.path.expanduser("~/.agml"))
with open(_os.path.join(_os.path.expanduser("~/.agml/config.json")), "w") as f:
_json.dump(
{
"data_path": _os.path.expanduser("~/.agml/datasets"),
"viz_backend": "matplotlib",
},
f,
)


_setup()
del _setup # noqa


# There are no top-level imported functions or classes, only the modules.
from . import backend, data, io, synthetic, viz
Loading

0 comments on commit f0fb6ae

Please sign in to comment.