Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .flake8

This file was deleted.

36 changes: 25 additions & 11 deletions .github/workflows/auto-format.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,38 @@ jobs:
# Check if the PR is not from a fork
if: github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
env:
PYTHON_VERSION: "3.10"
POETRY_VERSION: "1.4.0"
steps:
- uses: actions/checkout@v1
- name: get code
uses: actions/checkout@v1
with:
ref: ${{ github.head_ref }}
- name: black
#uses: lgeiger/black-action@v1.0.1
uses: psf/black@stable
- name: install python
uses: actions/setup-python@v4
with:
src: "."
options: "--verbose"
- name: Check for modified files
python-version: ${{ env.PYTHON_VERSION }}
- name: install poetry
uses: snok/install-poetry@v1
with:
version: ${{ env.POETRY_VERSION }}
- name: install linter dependencies
run: |
make install-lint
- name: run formatter
run: |
make format
- name: check for modified files
id: git-check
run: echo ::set-output name=modified::$(if git diff-index --quiet HEAD --; then echo "false"; else echo "true"; fi)
- name: Push changes
run: |
git status
echo ::set-output name=modified::$(if git diff-index --quiet HEAD --; then echo "false"; else echo "true"; fi)
- name: push changes (if needed)
if: steps.git-check.outputs.modified == 'true'
run: |
git config --global user.name 'Auto-format Bot'
git config --global user.email 'autoformatbot@groundlight.ai'
git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
git commit -am "Automatically reformatting code with black"
git commit -am "Automatically reformatting code"
git push

27 changes: 27 additions & 0 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Run our linter on every push to the repository.
name: lint
on: [push]

jobs:
lint:
runs-on: ubuntu-latest
env:
PYTHON_VERSION: "3.10"
POETRY_VERSION: "1.4.0"
steps:
- name: install python
uses: actions/setup-python@v4
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: install poetry
uses: snok/install-poetry@v1
with:
version: ${{ env.POETRY_VERSION }}
- name: get code
uses: actions/checkout@v3
- name: install linter dependencies
run: |
make install-lint
- name: lint
run: |
make lint
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,6 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

# This is a library, so we want clients to have more flexible dependencies. So we don't include a lockfile.
poetry.lock

node_modules/

*.swp
Expand Down
10 changes: 10 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# We call our local formatting script as a pre-commit hook.
# https://pre-commit.com/
repos:
- repo: local
hooks:
- id: format
name: Format Code
entry: ./code-quality/format
language: script
types: [python, toml]
22 changes: 9 additions & 13 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,7 @@
# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code.
extension-pkg-allow-list=

# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code. (This is an alternative name to extension-pkg-allow-list
# for backward compatibility.)
extension-pkg-whitelist=
extension-pkg-allow-list=pydantic

# Return non-zero exit code if any of these messages/categories are detected,
# even if score is above --fail-under value. Syntax same as enable. Messages
Expand All @@ -32,8 +26,7 @@ ignore-patterns=

# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
# This is a workaround until pysrc is its own package!
init-hook='import sys; sys.path.append("./janzu"); sys.path.append("./pysrc")'
init-hook=

# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the
# number of processors available to use.
Expand All @@ -53,7 +46,7 @@ persistent=yes

# Min Python version to use for version dependend checks. Will default to the
# version used to run pylint.
py-version=3.9
py-version=3.7

# When enabled, pylint would attempt to guess common misconfiguration and emit
# user-friendly hints instead of false-positive error messages.
Expand Down Expand Up @@ -95,7 +88,9 @@ disable=raw-checker-failed,
missing-function-docstring,
invalid-name,
too-few-public-methods,
line-too-long
line-too-long,
import-error, # we only install linter dependencies in CI/CD
wrong-import-order, # we use ruff to enforce import order


# Enable the message, report, category or checker with the given id(s). You can
Expand Down Expand Up @@ -181,8 +176,9 @@ spelling-store-unknown-words=no

# List of note tags to take in consideration, separated by a comma.
notes=FIXME,
XXX,
TODO
XXX
# Warnings on TODOs are too noisy.
# TODO

# Regular expression of note tags to take in consideration.
#notes-rgx=
Expand Down
20 changes: 7 additions & 13 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
{
"python.formatting.blackArgs": [
"--line-length",
"120"
],
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
},
"python.analysis.extraPaths": [
"./generated"
],
"python.formatting.provider": "black",
}
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
},
"python.analysis.extraPaths": ["./generated"],
"python.formatting.provider": "black"
}
97 changes: 71 additions & 26 deletions DEVELOPING.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,90 @@
# Python SDK Developer Guide

The raw API is generated using an OpenAPI spec. The SDK adds commonly used functionality
like polling for blocking submits and configuration of tokens and endpoints.
The raw API is generated using an [OpenAPI spec](spec/public-api.yaml). The SDK adds commonly used
functionality like polling for blocking submits and configuration of tokens and endpoints.

## Local Development

The auto-generated SDK code is in the `generated/` directory. To
re-generate the client code, you'll need to install
[openapi-generator](https://openapi-generator.tech/docs/installation#homebrew)
(I recommend homebrew if you're on a mac). Then you can run it with:
### Install dependencies

```Bash
$ make generate
First, make sure you have [poetry installed](https://python-poetry.org/docs/#installation). Then,
you can install the package dependencies by running:

```shell
make install
```

## Testing
Most tests need an API endpoint to run. This can be the public API endpoint `https://api.groundlight.ai`,
or a local endpoint with an edge client or development environment.
Note: We support Python 3.7+ for clients of the SDK, but we recommend developing with Python 3.10+.

### Run tests

### Getting the tests to use your current code.
Most tests need an API endpoint and an API token to run. The default endpoint is the public API
endpoint (`https://api.groundlight.ai`). But you can also test against other endpoints (like
localhost or integ).

(This needs to be updated.)
```shell
# Run tests against the public API
GROUNDLIGHT_API_TOKEN="api_YOUR_PROD_TOKEN_HERE" make test
```

You kinda want to do a `pip install -e .` equivalent but I don't know how to do that with poetry. The ugly version is this...
But you can also test against other endpoints (like localhost or integ). Make sure the API token
comes from the same environment as the API endpoint you're testing against!

Find the directory where `groundlight` is installed:
```shell
# Run tests against a local API
GROUNDLIGHT_API_TOKEN="api_YOUR_LOCALHOST_TOKEN_HERE" make test-local

# Run tests against the integ API
GROUNDLIGHT_API_TOKEN="api_YOUR_INTEG_TOKEN_HERE" make test-integ
```
$ python
Python 3.7.4 (default, Aug 13 2019, 20:35:49)
[GCC 7.3.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import groundlight
>>> groundlight
<module 'groundlight' from '/home/ubuntu/anaconda3/lib/python3.7/site-packages/groundlight/__init__.py'>

### Install auto-formatter pre-commit hook

We use [pre-commit](https://pre-commit.com/) to run some auto-formatters before committing code. You
can install the pre-commit hooks by running:

```shell
make install-pre-commit
```

Then blow this away and set up a symlink from that directory to your source.
This will check to see whether any formatters need to be run every time you do `git commit`. If so,
it will run them, add the changes, and then ask you to try committing again with the new changes.

### Generating code based on the latest API spec

The auto-generated SDK code is in the [generated/](generated) directory. Most of the time, you won't
need to generate code. But if the API specification changes, you may need to generate SDK code. To
re-generate the client code, you'll need to [install npm](https://github.com/nvm-sh/nvm#intro)
first. Then you can install the code generator by running:

```shell
make install-generator
```
cd /home/ubuntu/anaconda3/lib/python3.7/site-packages/
rm -rf groundlight
ln -s ~/dev/python-sdk/src/groundlight groundlight

Then you can generate the code by running:

```shell
make generate
```

### Linters

Linters help us find issues before runtime. We're currently using:

- [ruff](https://beta.ruff.rs/docs/) and
[pylint](https://pylint.readthedocs.io/en/latest/index.html) for general python linting.
- [mypy](https://mypy.readthedocs.io/en/stable/index.html) for type checking.
- [black](https://black.readthedocs.io/en/stable/index.html) for standardizing code formatting.
- [toml-sort](https://toml-sort.readthedocs.io/en/latest/) for linting the `pyproject.toml` file.

Most of these linters are configured in [pyproject.toml](pyproject.toml) (except for `pylint` in
[.pylintrc](.pylintrc)). Sometimes the linters are wrong or not useful, so we can add overrides. We
prefer to make the smallest possible override:

- single line override with a specific rule (e.g., `# pylint: disable=some-rule` or `# ruff: noqa: F403`)
- single file override with a specific rule
- single file override with a whole class of rules
- global override for a specific rule

Note: `pylint` is usually the strictest and slowest, so we may end up turning it off - but we'll try
it for a while and see how it goes!
42 changes: 34 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,20 +1,46 @@
.PHONY: all test clean

install: ## Install the package from source
poetry install

generate: install ## Generate the SDK from our public openapi spec
install-lint: ## Only install the linter dependencies
poetry install --only lint

install-pre-commit: install ## Install pre-commit hooks
poetry run pre-commit install

install-generator: install ## Install dependencies for SDK code generator
npm install

generate: install-generator ## Generate the SDK from our public openapi spec
node_modules/.bin/openapi-generator-cli generate -i spec/public-api.yaml \
-g python \
-o ./generated
poetry run datamodel-codegen --input spec/public-api.yaml --output generated/model.py
poetry run black .

test-local: install ## Run integration tests against an API server running at http://localhost:8000/device-api (needs GROUNDLIGHT_API_TOKEN)
GROUNDLIGHT_ENDPOINT="http://localhost:8000/" poetry run pytest --cov=src test --log-cli-level INFO
PYTEST=poetry run pytest -v --cov=src

# You can pass extra arguments to pytest by setting the TEST_ARGS environment variable.
# For example:
# `make test TEST_ARGS="-k some_filter"`
TEST_ARGS=

test-integ: install ## Run integration tests against the integ API server (needs GROUNDLIGHT_API_TOKEN)
GROUNDLIGHT_ENDPOINT="https://api.integ.groundlight.ai/" poetry run pytest --cov=src test --log-cli-level INFO
test: install ## Run tests against the prod API (needs GROUNDLIGHT_API_TOKEN)
${PYTEST} ${TEST_ARGS} test

test-local: install ## Run tests against a localhost API (needs GROUNDLIGHT_API_TOKEN and a local API server)
GROUNDLIGHT_ENDPOINT="http://localhost:8000/" ${PYTEST} ${TEST_ARGS} test

test-integ: install ## Run tests against the integ API server (needs GROUNDLIGHT_API_TOKEN)
GROUNDLIGHT_ENDPOINT="https://api.integ.groundlight.ai/" ${PYTEST} ${TEST_ARGS} test

test-docs: install ## Run the example code and tests in our docs against the prod API (needs GROUNDLIGHT_API_TOKEN)
poetry run pytest --markdown-docs docs -v
poetry run pytest -v --markdown-docs ${TEST_ARGS} docs

# Adjust which paths we lint
LINT_PATHS="src test bin samples"

lint: install-lint ## Run linter to check formatting and style
./code-quality/lint ${LINT_PATHS}

format: install-lint ## Run standard python formatting
./code-quality/format ${LINT_PATHS}
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Groundlight Python SDK

Groundlight makes it simple to build reliable visual applications. Read the [full documentation here](https://code.groundlight.ai/python-sdk/).
Groundlight makes it simple to build reliable visual applications. Read the [full documentation here](https://code.groundlight.ai/python-sdk/).

## Computer Vision powered by Natural Language

Expand Down Expand Up @@ -29,8 +29,7 @@ _Note: The SDK is currently in "beta" phase. Interfaces are subject to change in

Some more resources you might like:

* [Code Documentation](https://code.groundlight.ai/)
* [Python SDK](https://pypi.org/project/groundlight/)
* [Company](https://www.groundlight.ai/)
* [Login to Groundlight](https://app.groundlight.ai/)

- [Code Documentation](https://code.groundlight.ai/)
- [Python SDK](https://pypi.org/project/groundlight/)
- [Company](https://www.groundlight.ai/)
- [Login to Groundlight](https://app.groundlight.ai/)
Loading