Skip to content

Commit 82381b6

Browse files
authored
Merge pull request #35 from groundlight/pytest-against-md
Run tests against the python code in our documentation
2 parents 8955c60 + a7a62ff commit 82381b6

File tree

10 files changed

+127
-61
lines changed

10 files changed

+127
-61
lines changed

.github/workflows/publish-docs.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ jobs:
2929
- name: Deploy website
3030
# Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus
3131
uses: peaceiris/actions-gh-pages@v3
32-
# Only run this on pushes to the `docs`
33-
if: github.ref == 'refs/heads/docs'
32+
# Only deploy on pushes to the `main` branch
33+
if: github.ref == 'refs/heads/main'
3434
with:
3535
github_token: ${{ secrets.GITHUB_TOKEN }}
3636
publish_dir: ./docs/build

.github/workflows/publish-pypi.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ jobs:
1111
POETRY_PYPI_TOKEN_PYPI: ${{ secrets.PYPI_PUBLISH_TOKEN }}
1212
steps:
1313
- name: install python
14-
uses: actions/setup-python@v2
14+
uses: actions/setup-python@v3
1515
with:
16-
python-version: 3.9
16+
python-version: 3.10
1717
- name: install poetry
1818
run: |
1919
pip install -U pip

.github/workflows/test-integ.yaml

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ jobs:
2828
]
2929
install_numpy: [true, false]
3030
install_pillow: [true, false]
31-
env:
32-
# This is associated with the "sdk-integ-test" user, credentials on 1password
33-
GROUNDLIGHT_API_TOKEN: ${{ secrets.GROUNDLIGHT_API_TOKEN }}
3431
steps:
3532
- name: get code
3633
uses: actions/checkout@v3
@@ -56,4 +53,12 @@ jobs:
5653
run: |
5754
poetry run pip install pillow
5855
- name: run tests
56+
env:
57+
# This is associated with the "sdk-integ-test" user, credentials on 1password
58+
GROUNDLIGHT_API_TOKEN: ${{ secrets.GROUNDLIGHT_API_TOKEN }}
5959
run: make test-integ
60+
- name: run docs tests
61+
run: make test-docs
62+
env:
63+
# This is associated with the "sdk-test-prod" user, credentials on 1password
64+
GROUNDLIGHT_API_TOKEN: ${{ secrets.GROUNDLIGHT_API_TOKEN_PROD }}

Makefile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
install: ## Install the package from source
44
poetry install
5-
npm install
65

76
generate: install ## Generate the SDK from our public openapi spec
87
node_modules/.bin/openapi-generator-cli generate -i spec/public-api.yaml \
@@ -11,10 +10,11 @@ generate: install ## Generate the SDK from our public openapi spec
1110
poetry run datamodel-codegen --input spec/public-api.yaml --output generated/model.py
1211
poetry run black .
1312

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

18-
1916
test-integ: install ## Run integration tests against the integ API server (needs GROUNDLIGHT_API_TOKEN)
2017
GROUNDLIGHT_ENDPOINT="https://api.integ.groundlight.ai/" poetry run pytest --cov=src test --log-cli-level INFO
18+
19+
test-docs: install ## Run the example code and tests in our docs against the prod API (needs GROUNDLIGHT_API_TOKEN)
20+
poetry run pytest --markdown-docs docs -v

docs/docs/building-applications/working-with-detectors.md

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,44 +19,80 @@ detector = gl.create_detector(name="your_detector_name", query="is this what we
1919

2020
### Retrieve an existing detector
2121

22-
```python
22+
<!-- Don't test because the ID can't be faked -->
23+
24+
```python notest
25+
from groundlight import Groundlight
26+
27+
gl = Groundlight()
28+
# highlight-start
2329
detector = gl.get_detector(id="YOUR_DETECTOR_ID")
30+
# highlight-end
2431
```
2532

2633
### List your detectors
2734

2835
```python
36+
from groundlight import Groundlight
37+
38+
gl = Groundlight()
39+
# highlight-start
2940
# Defaults to 10 results per page
3041
detectors = gl.list_detectors()
3142

32-
# Pagination: 3rd page of 25 results per page
33-
detectors = gl.list_detectors(page=3, page_size=25)
43+
# Pagination: 1st page of 5 results per page
44+
detectors = gl.list_detectors(page=1, page_size=5)
45+
# highlight-end
3446
```
3547

3648
### Retrieve an image query
3749

3850
In practice, you may want to check for a new result on your query. For example, after a cloud reviewer labels your query. For example, you can use the `image_query.id` after the above `submit_image_query()` call.
3951

40-
```python
41-
image_query = gl.get_image_query(id="YOUR_IMAGE_QUERY_ID")
52+
<!-- Don't test because the ID can't be faked -->
53+
54+
```python notest
55+
from groundlight import Groundlight
56+
57+
gl = Groundlight()
58+
# highlight-start
59+
image_query = gl.get_image_query(id="iq_YOUR_IMAGE_QUERY_ID")
60+
# highlight-end
4261
```
4362

4463
### List your previous image queries
4564

4665
```python
66+
from groundlight import Groundlight
67+
68+
gl = Groundlight()
69+
# highlight-start
4770
# Defaults to 10 results per page
4871
image_queries = gl.list_image_queries()
4972

50-
# Pagination: 3rd page of 25 results per page
51-
image_queries = gl.list_image_queries(page=3, page_size=25)
73+
# Pagination: 1st page of 5 results per page
74+
image_queries = gl.list_image_queries(page=1, page_size=5)
75+
# highlight-end
5276
```
5377

5478
### Adding labels to existing image queries
5579

5680
Groundlight lets you start using models by making queries against your very first image, but there are a few situations where you might either have an existing dataset, or you'd like to handle the escalation response programatically in your own code but still include the label to get better responses in the future. With your `image_query` from either `submit_image_query()` or `get_image_query()` you can add the label directly. Note that if the query is already in the escalation queue due to low ML confidence or audit thresholds, it may also receive labels from another source.
5781

5882
```python
59-
add_label(image_query, 'YES'). # or 'NO'
83+
from groundlight import Groundlight
84+
from PIL import Image
85+
import requests
86+
87+
gl = Groundlight()
88+
d = gl.get_or_create_detector(name="doorway", query="Is the doorway open?")
89+
image = Image.open(
90+
requests.get("https://images.selfstorage.com/large-compress/2174925f24362c479b2.jpg", stream=True).raw
91+
)
92+
image_query = gl.submit_image_query(detector=d, image=image)
93+
# highlight-start
94+
gl.add_label(image_query, 'YES') # or 'NO'
95+
# highlight-end
6096
```
6197

62-
The only valid labels at this time are `'YES'` and `'NO'`
98+
The only valid labels at this time are `'YES'` and `'NO'`.

docs/docs/getting-started/getting-started.mdx

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,19 @@
22

33
## Computer Vision powered by Natural Language
44

5-
Build a working computer vision system in just 5 lines of python:
5+
Build a working computer vision system in just a few lines of python:
66

77
```python
88
from groundlight import Groundlight
9+
from PIL import Image
10+
import requests
911

1012
gl = Groundlight()
11-
d = gl.get_or_create_detector(name="door", query="Is the door open?")
12-
image_query = gl.submit_image_query(detector=d, image=jpeg_img)
13+
d = gl.get_or_create_detector(name="doorway", query="Is the doorway open?")
14+
image = Image.open(
15+
requests.get("https://images.selfstorage.com/large-compress/2174925f24362c479b2.jpg", stream=True).raw
16+
)
17+
image_query = gl.submit_image_query(detector=d, image=image)
1318
print(f"The answer is {image_query.result}")
1419
```
1520

@@ -27,33 +32,32 @@ _Note: The SDK is currently in "beta" phase. Interfaces are subject to change in
2732
pip3 install groundlight
2833
```
2934

30-
1. To access the API, you need an API token. You can create one on the
31-
[groundlight web app](https://app.groundlight.ai/reef/my-account/api-tokens). The API token
32-
should be stored securely. You can use it directly in your code to initialize the SDK like:
33-
34-
```python
35-
gl = Groundlight(api_token="<YOUR_API_TOKEN>")
36-
```
37-
38-
This is an easy way to get started, but is NOT a best practice. Please do not commit your API Token to version control! Instead we recommend setting the `GROUNDLIGHT_API_TOKEN` environment variable outside your code so that the SDK can find it automatically.
35+
1. Head over to the [groundlight web
36+
app](https://app.groundlight.ai/reef/my-account/api-tokens) to create an API token. You will
37+
need to set the `GROUNDLIGHT_API_TOKEN` environment variable to access the API.
3938

4039
```shell
4140
export GROUNDLIGHT_API_TOKEN=api_2GdXMflhJi6L_example
4241
```
4342

44-
1. Create a python file.
43+
1. Create a python script.
4544

46-
```python title="hello.py"
45+
```python title="ask.py"
4746
from groundlight import Groundlight
47+
from PIL import Image
48+
import requests
4849

4950
gl = Groundlight()
50-
d = gl.get_or_create_detector(name="door", query="Is the door open?")
51-
image_query = gl.submit_image_query(detector=d, image=jpeg_img)
51+
d = gl.get_or_create_detector(name="doorway", query="Is the doorway open?")
52+
image = Image.open(
53+
requests.get("https://images.selfstorage.com/large-compress/2174925f24362c479b2.jpg", stream=True).raw
54+
)
55+
image_query = gl.submit_image_query(detector=d, image=image)
5256
print(f"The answer is {image_query.result}")
5357
```
5458

5559
1. Run it!
5660

5761
```shell
58-
$ python hello.py
62+
$ python ask.py
5963
```

docs/docs/getting-started/managing-confidence.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,25 @@ The desired confidence level is set as the escalation threshold on your detector
66

77
For example, say you want to set your desired confidence level to 0.95, but that you're willing to wait up to 60 seconds to get a confident response.
88

9-
```python
9+
<!-- TODO: turn on `confidence` parameter, and re-enable tests! -->
10+
11+
```python notest
12+
from groundlight import Groundlight
13+
from PIL import Image
14+
import requests
15+
16+
gl = Groundlight()
17+
image = Image.open(
18+
requests.get("https://www.photos-public-domain.com/wp-content/uploads/2010/11/over_flowing_garbage_can.jpg", stream=True).raw
19+
)
20+
21+
# highlight-start
1022
d = gl.get_or_create_detector(name="trash", query="Is the trash can full?", confidence=0.95)
11-
image_query = gl.submit_image_query(detector=d, image=jpeg_img, wait=60)
23+
1224
# This will wait until either 60 seconds have passed or the confidence reaches 0.95
25+
image_query = gl.submit_image_query(detector=d, image=jpeg_img, wait=60)
26+
# highlight-end
27+
1328
print(f"The answer is {image_query.result}")
1429
```
1530

@@ -22,12 +37,12 @@ Higher confidence will get higher accuracy, but will generally require longer la
2237

2338
Or if you want to run as fast as possible, set `wait=0`. This way you will only get the ML results, without waiting for escalation. Image queries which are below the desired confidence level still be escalated for further analysis, and the results are incorporated as training data to improve your ML model, but your code will not wait for that to happen.
2439

25-
```python
40+
```python notest continuation
2641
image_query = gl.submit_image_query(detector=d, image=jpeg_img, wait=0)
2742
```
2843

2944
If the returned result was generated from an ML model, you can see the confidence score returned for the image query:
3045

31-
```python
46+
```python notest continuation
3247
print(f"The confidence is {image_query.result.confidence}")
3348
```

docs/docusaurus.config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,11 @@ const config = {
7474
position: "left",
7575
label: "Docs",
7676
},
77-
{ to: "/docs/category/building-applications", label: "Applications", position: "left" },
77+
{
78+
to: "/docs/category/building-applications",
79+
label: "Applications",
80+
position: "left",
81+
},
7882
{
7983
href: "https://github.com/groundlight/python-sdk",
8084
label: "GitHub",

pyproject.toml

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,42 @@
11
[tool.poetry]
2-
name = "groundlight"
3-
version = "0.7.3"
4-
license = "MIT"
5-
readme = "README.md"
6-
homepage = "https://www.groundlight.ai"
7-
description = "Build computer vision systems from natural language with Groundlight"
82
authors = ["Groundlight AI <[email protected]>"]
3+
description = "Build computer vision systems from natural language with Groundlight"
4+
homepage = "https://www.groundlight.ai"
5+
license = "MIT"
6+
name = "groundlight"
97
packages = [
10-
{ include = "**/*.py", from = "src" },
11-
{ include = "**/*.py", from = "generated" },
8+
{include = "**/*.py", from = "generated"},
9+
{include = "**/*.py", from = "src"},
1210
]
11+
readme = "README.md"
12+
version = "0.7.4"
1313

1414
[tool.poetry.dependencies]
15-
python = ">=3.7.0,<4.0"
16-
python-dateutil = "^2.8.2"
17-
urllib3 = "^1.26.9"
18-
frozendict = "^2.3.2"
1915
certifi = "^2021.10.8"
16+
frozendict = "^2.3.2"
17+
pillow = "^9.0.0"
2018
pydantic = "^1.7.4"
19+
python = ">=3.7.0,<4.0"
20+
python-dateutil = "^2.8.2"
2121
requests = "^2.28.2"
22+
urllib3 = "^1.26.9"
2223

23-
[tool.poetry.dev-dependencies]
24+
[tool.poetry.group.dev.dependencies]
25+
autoflake = "^1.4"
2426
black = "^22.3.0"
25-
pytest-cov = "^3.0.0"
26-
pylint = "^2.13.9"
27+
datamodel-code-generator = "^0.12.1"
2728
flake8 = "^4.0.1"
29+
isort = "^5.10.1"
2830
mypy = "^0.950"
31+
pylint = "^2.13.9"
2932
pytest = "^7.0.1"
30-
isort = "^5.10.1"
31-
autoflake = "^1.4"
32-
datamodel-code-generator = "^0.12.1"
33+
pytest-cov = "^3.0.0"
34+
pytest-markdown-docs = "^0.4.3"
3335
pytest-mock = "^3.10.0"
3436

3537
[build-system]
36-
requires = ["poetry-core>=1.0.0"]
3738
build-backend = "poetry.core.masonry.api"
39+
requires = ["poetry-core>=1.2.0"]
3840

3941
[tool.black]
4042
line-length = 120

src/groundlight/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ def get_detector(self, id: Union[str, Detector]) -> Detector:
8282

8383
def get_detector_by_name(self, name: str) -> Optional[Detector]:
8484
# TODO: Do this on server.
85-
detector_list = self.list_detectors(page_size=100)
85+
detector_list = self.list_detectors(page_size=250)
8686
for d in detector_list.results:
8787
if d.name == name:
8888
return d

0 commit comments

Comments
 (0)