Skip to content

Commit fb25784

Browse files
authored
Merge pull request #322 from Labelbox/develop
3.8.0
2 parents 9e195b0 + 89c791c commit fb25784

24 files changed

+366
-125
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,5 @@ docs/build/
137137
# and source files
138138
docs/source/_static
139139
docs/source/_templates
140+
/.graphqlconfig
141+
/schema.graphql

CHANGELOG.md

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
# Changelog
2-
# Version 3.7.0 (2021-11-10)
2+
3+
## Deprecation Notice
4+
| Name | Replacement | Removed After |
5+
| ------------------------------------- | ------------------------------------- | ------------- |
6+
| `ModelRun.delete_annotation_groups()` | `ModelRun.delete_model_run_data_rows()`| 3.9 |
7+
| `ModelRun.annotation_groups()` | `ModelRun.model_run_data_rows()` | 3.9 |
8+
| `DataRowMetadataSchema.id` | `DataRowMetadataSchema.uid` | 3.9 |
9+
-----
10+
11+
# Version 3.8.0 (2021-10-21)
12+
## Added
13+
* `ModelRun.upsert_data_rows()`
14+
* Add data rows to a model run without also attaching labels
15+
* `OperationNotAllowedException`
16+
* raised when users hit resource limits or are not allowed to use a particular operation
17+
18+
## Updated
19+
* `ModelRun.upsert_labels()`
20+
* Blocks until the upsert job is complete. Error messages have been improved
21+
* `Organization.invite_user()` and `Organization.invite_limit()` are no longer experimental
22+
* `AnnotationGroup` was renamed to `ModelRunDataRow`
23+
* `ModelRun.delete_annotation_groups()` was renamed to `ModelRun.delete_model_run_data_rows()`
24+
* `ModelRun.annotation_groups()` was renamed to `ModelRun.model_run_data_rows()`
25+
26+
## Fix
27+
* `DataRowMetadataField` no longer relies on pydantic for field validation and coercion
28+
* This prevents unintended type coercion from occuring
29+
30+
# Version 3.7.0 (2021-10-11)
331
## Added
432
* Search for data row ids from external ids without specifying a dataset
533
* `client.get_data_row_ids_for_external_ids()`
@@ -15,10 +43,10 @@
1543
* `custom_name_index` -> `custom_by_name`
1644

1745

18-
# Version 3.6.1 (2021-07-10)
46+
# Version 3.6.1 (2021-10-07)
1947
* Fix import error that appears when exporting labels
2048

21-
# Version 3.6.0 (2021-04-10)
49+
# Version 3.6.0 (2021-10-04)
2250
## Added
2351
* Bulk export metadata with `DataRowMetadataOntology.bulk_export()`
2452
* Add docstring examples of annotation types and a few helper methods
@@ -32,7 +60,7 @@
3260
* data_row.metadata was removed in favor of bulk exports.
3361

3462

35-
# Version 3.5.0 (2021-15-09)
63+
# Version 3.5.0 (2021-09-15)
3664
## Added
3765
* Diagnostics custom metrics
3866
* Metric annotation types

README.md

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,15 @@ The Labelbox Python API offers a simple, user-friendly way to interact with the
66

77
## Table of Contents
88

9-
* [Requirements](#requirements)
10-
* [Installation](#installation)
11-
* [Documentation](#documentation)
12-
* [Authentication](#authentication)
13-
* [Contribution](#contribution)
14-
* [Testing](#testing)
9+
- [Labelbox Python SDK](#labelbox-python-sdk)
10+
- [Table of Contents](#table-of-contents)
11+
- [Requirements](#requirements)
12+
- [Installation](#installation)
13+
- [Note for Windows users](#note-for-windows-users)
14+
- [Documentation](#documentation)
15+
- [Authentication](#authentication)
16+
- [Contribution](#contribution)
17+
- [Testing](#testing)
1518

1619
## Requirements
1720

@@ -48,6 +51,37 @@ To install dependencies required for data processing modules use:
4851
```
4952
pip install labelbox[data]
5053
```
54+
### Note for Windows users
55+
The package `rasterio` installed by `labelbox[data]` relies on GDAL which could be difficult to install on Microsoft Windows.
56+
57+
You may see the following error message:
58+
59+
```
60+
INFO:root:Building on Windows requires extra options to setup.py to locate needed GDAL files. More information is available in the README.
61+
62+
ERROR: A GDAL API version must be specified. Provide a path to gdal-config using a GDAL_CONFIG environment variable or use a GDAL_VERSION environment variable.
63+
```
64+
65+
As a workaround:
66+
67+
1. Download the binary files for GDAL and rasterio:
68+
69+
a. From https://www.lfd.uci.edu/~gohlke/pythonlibs/#gdal, download `GDAL‑3.3.2‑cp38‑cp38‑win_amd64.wh`
70+
71+
b. From https://www.lfd.uci.edu/~gohlke/pythonlibs/#rasterio, download `rasterio‑1.2.9‑cp38‑cp38‑win_amd64.whl`
72+
73+
Note: You need to download the right files for your Python version. In the files above `cp38` means CPython 3.8.
74+
75+
2. After downloading the files, please run the following commands, in this particular order.
76+
77+
```
78+
pip install GDAL‑3.3.2‑cp38‑cp38‑win_amd64.wh
79+
pip install rasterio‑1.2.9‑cp38‑cp38‑win_amd64.whl
80+
pip install labelbox[data]
81+
```
82+
83+
This should resolve the error message.
84+
5185

5286
## Documentation
5387

examples/README.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,31 @@
2929
| Video Annotation Export | [Github](label_export/video.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/label_export/video.ipynb) | [Reference](https://docs.labelbox.com/reference/label-output) |
3030
------
3131

32+
## Model Training
33+
34+
Train a model using data annotated on Labelbox
35+
36+
| Notebook | Github | Google Colab |
37+
| --------------------------- | --------------------------------- | ------------ |
38+
| Object Detection (Detectron2) | [Github](coco_object.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/integrations/detectron2/coco_panoptic.ipynb) |
39+
| Panoptic Detection (Detectron2) | [Github](coco_panoptic.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/integrations/detectron2/coco_panoptic.ipynb)
40+
------
41+
42+
## [Annotation Types](annotation_types)
43+
44+
Learn more about annotation types in the [docs](https://docs.labelbox.com/docs/annotation-types-1)
45+
46+
| Notebook | Github | Google Colab |
47+
| --------------------------- | --------------------------------- | ------------ |
48+
| Annotation Type Basics | [Github](annotation_types/basics.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/annotation_types/basics.ipynb) |
49+
| Converters | [Github](annotation_types/converters.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/annotation_types/converters.ipynb) |
50+
| Label Containers | [Github](annotation_types/label_containers.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/annotation_types/label_containers.ipynb) |
51+
| MAL Using Annotation Types | [Github](annotation_types/mal_using_annotation_types.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/annotation_types/mal_using_annotation_types.ipynb) |
52+
53+
3254
## [Model Assisted Labeling](model_assisted_labeling)
3355

56+
3457
| Notebook | Github | Google Colab | Learn more |
3558
| --------------------------- | --------------------------------- | ------------ | ---------- |
3659
| MAL Basics | [Github](model_assisted_labeling/mal_basics.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/model_assisted_labeling/mal_basics.ipynb) | [Docs](https://docs.labelbox.com/docs/model-assisted-labeling) |
@@ -39,7 +62,6 @@
3962
| Debugging MAL | [Github](model_assisted_labeling/debugging_mal.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/model_assisted_labeling/debugging_mal.ipynb) |
4063
| MAL with Subclasses | [Github](model_assisted_labeling/mal_with_subclasses.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/model_assisted_labeling/mal_with_subclasses.ipynb) |
4164
| Tiled Imagery MAL | [Github](model_assisted_labeling/tiled_imagery_mal.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/model_assisted_labeling/tiled_imagery_mal.ipynb) |
42-
4365
------
4466

4567
## [Project Configuration](project_configuration)
@@ -51,14 +73,6 @@
5173
| Webhooks | [Github](project_configuration/webhooks.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/project_configuration/webhooks.ipynb) | [Docs](https://docs.labelbox.com/docs/webhooks) |
5274

5375

54-
## [Annotation Types](annotation_types)
55-
56-
| Notebook | Github | Google Colab |
57-
| --------------------------- | --------------------------------- | ------------ |
58-
| Annotation Type Basics | [Github](annotation_types/basics.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/annotation_types/basics.ipynb) |
59-
| Converters | [Github](annotation_types/converters.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/annotation_types/converters.ipynb) |
60-
| Label Containers | [Github](annotation_types/label_containers.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/annotation_types/label_containers.ipynb) |
61-
| MAL Using Annotation Types | [Github](annotation_types/mal_using_annotation_types.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/annotation_types/mal_using_annotation_types.ipynb) |
6276

6377
## [Model Diagnostics](model_diagnostics)
6478
| Notebook | Github | Google Colab | Learn more |

examples/basics/data_row_metadata.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@
273273
"outputs": [],
274274
"source": [
275275
"field = DataRowMetadataField(\n",
276-
" schema_id=mdo.reserved_by_name[\"captureDateTime\"].id, # specify the schema id\n",
276+
" schema_id=mdo.reserved_by_name[\"captureDateTime\"].uid, # specify the schema id\n",
277277
" value=datetime.now(), # typed inputs\n",
278278
")\n",
279279
"# Completed object ready for upload\n",
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
![Logo](images/detectron-logo.png)
2+
3+
Detectron2 is Facebook AI Research's next generation library that provides state-of-the-art detection and segmentation
4+
algorithms. Check out the official repository [here](https://github.com/facebookresearch/detectron2)
5+
6+
7+
<div align="center">
8+
<img src="https://user-images.githubusercontent.com/1381301/66535560-d3422200-eace-11e9-9123-5535d469db19.png"/>
9+
</div>
10+
11+
# Getting Started
12+
13+
The Labelbox team has created two notebooks to help you train your own Detectron2 model with data you have annotated on
14+
Labelbox.
15+
16+
| Notebook | Github | Google Colab |
17+
| --------------------------- | --------------------------------- | ------------ |
18+
| Object Detection | [Github](coco_object.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/integrations/detectron2/coco_panoptic.ipynb) |
19+
| Panoptic Detection | [Github](coco_panoptic.ipynb) | [![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/Labelbox/labelbox-python/blob/develop/examples/integrations/detectron2/coco_panoptic.ipynb)
20+
------
21+

examples/integrations/detectron2/coco_object.ipynb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@
5151
"source": [
5252
"API_KEY = None\n",
5353
"# For training:\n",
54-
"project_id = \"ckt8uxbul81uh0y7ucd03bye6\"\n",
54+
"project_id = \"\"\n",
5555
"# The model will make predictions on the following dataset \n",
5656
"# and upload predictions to a new project for model assisted labeling.\n",
57-
"mal_dataset_id = \"ckrwmctsr0kik0y2c41uvdb3e\""
57+
"mal_dataset_id = \"\""
5858
]
5959
},
6060
{
@@ -645,10 +645,10 @@
645645
"outputs": [],
646646
"source": [
647647
"\n",
648-
"for idx, annotation_group in enumerate(model_run.annotation_groups()):\n",
648+
"for idx, model_run_data_row in enumerate(model_run.model_run_data_rows()):\n",
649649
" if idx == 5:\n",
650650
" break\n",
651-
" print(annotation_group.url)"
651+
" print(model_run_data_row.url)"
652652
]
653653
},
654654
{

examples/integrations/detectron2/coco_panoptic.ipynb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@
5151
"source": [
5252
"API_KEY = None\n",
5353
"# For training:\n",
54-
"project_id = \"cksnz7llh75xa0z9ocnfkd1db\"\n",
54+
"project_id = \"\"\n",
5555
"# The model will make predictions on the following dataset \n",
5656
"# and upload predictions to a new project for model assisted labeling.\n",
57-
"mal_dataset_id = \"ckm4xyfua04cf0z7a3wz58kgj\""
57+
"mal_dataset_id = \"\""
5858
]
5959
},
6060
{
@@ -1395,10 +1395,10 @@
13951395
],
13961396
"source": [
13971397
"\n",
1398-
"for idx, annotation_group in enumerate(model_run.annotation_groups()):\n",
1398+
"for idx, model_run_data_row in enumerate(model_run.model_run_data_rows()):\n",
13991399
" if idx == 5:\n",
14001400
" break\n",
1401-
" print(annotation_group.url)"
1401+
" print(model_run_data_row.url)"
14021402
]
14031403
},
14041404
{
Loading

examples/model_diagnostics/custom_metrics_demo.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,10 +566,10 @@
566566
},
567567
"outputs": [],
568568
"source": [
569-
"for idx, annotation_group in enumerate(lb_model_run.annotation_groups()):\n",
569+
"for idx, model_run_data_row in enumerate(lb_model_run.model_run_data_rows()):\n",
570570
" if idx == 5:\n",
571571
" break\n",
572-
" print(annotation_group.url)"
572+
" print(model_run_data_row.url)"
573573
]
574574
},
575575
{

examples/model_diagnostics/model_diagnostics_demo.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -527,10 +527,10 @@
527527
},
528528
"outputs": [],
529529
"source": [
530-
"for idx, annotation_group in enumerate(lb_model_run.annotation_groups()):\n",
530+
"for idx, model_run_data_row in enumerate(lb_model_run.model_run_data_rows()):\n",
531531
" if idx == 5:\n",
532532
" break\n",
533-
" print(annotation_group.url)"
533+
" print(model_run_data_row.url)"
534534
]
535535
},
536536
{
@@ -569,4 +569,4 @@
569569
},
570570
"nbformat": 4,
571571
"nbformat_minor": 5
572-
}
572+
}

examples/model_diagnostics/model_diagnostics_guide.ipynb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -392,10 +392,10 @@
392392
"metadata": {},
393393
"outputs": [],
394394
"source": [
395-
"for idx, annotation_group in enumerate(lb_model_run.annotation_groups()):\n",
395+
"for idx, model_run_data_row in enumerate(lb_model_run.model_run_data_rows()):\n",
396396
" if idx == 5:\n",
397397
" break\n",
398-
" print(annotation_group.url)"
398+
" print(model_run_data_row.url)"
399399
]
400400
}
401401
],
@@ -426,4 +426,4 @@
426426
},
427427
"nbformat": 4,
428428
"nbformat_minor": 5
429-
}
429+
}

labelbox/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name = "labelbox"
2-
__version__ = "3.7.0"
2+
__version__ = "3.8.0"
33

44
from labelbox.schema.project import Project
55
from labelbox.client import Client

labelbox/client.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,7 @@ def __init__(self,
7878

7979
logger.info("Initializing Labelbox client at '%s'", endpoint)
8080
self.app_url = app_url
81-
82-
# TODO: Make endpoints non-internal or support them as experimental
83-
self.endpoint = endpoint.replace('/graphql', '/_gql')
81+
self.endpoint = endpoint
8482
self.headers = {
8583
'Accept': 'application/json',
8684
'Content-Type': 'application/json',
@@ -149,9 +147,11 @@ def convert_value(value):
149147
elif data is None:
150148
raise ValueError("query and data cannot both be none")
151149

150+
endpoint = self.endpoint if not experimental else self.endpoint.replace(
151+
"/graphql", "/_gql")
152152
try:
153153
request = {
154-
'url': self.endpoint,
154+
'url': endpoint,
155155
'data': data,
156156
'headers': self.headers,
157157
'timeout': timeout
@@ -255,6 +255,12 @@ def get_error_status_code(error):
255255
else:
256256
raise labelbox.exceptions.InternalServerError(message)
257257

258+
not_allowed_error = check_errors(["OPERATION_NOT_ALLOWED"],
259+
"extensions", "code")
260+
if not_allowed_error is not None:
261+
message = not_allowed_error.get("message")
262+
raise labelbox.exceptions.OperationNotAllowedException(message)
263+
258264
if len(errors) > 0:
259265
logger.warning("Unparsed errors on query execution: %r", errors)
260266
raise labelbox.exceptions.LabelboxError("Unknown error: %s" %

labelbox/data/ontology.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ def get_feature_schema_lookup(
1414

1515
def flatten_classification(classifications):
1616
for classification in classifications:
17+
if classification.feature_schema_id is None:
18+
raise ValueError(
19+
f"feature_schema_id cannot be None for classification `{classification.name}`."
20+
)
1721
if isinstance(classification, ontology.Classification):
1822
classification_lookup[
1923
classification.
@@ -28,6 +32,9 @@ def flatten_classification(classifications):
2832
flatten_classification(classification.options)
2933

3034
for tool in ontology_builder.tools:
35+
if tool.feature_schema_id is None:
36+
raise ValueError(
37+
f"feature_schema_id cannot be None for tool `{tool.name}`.")
3138
tool_lookup[tool.name] = tool.feature_schema_id
3239
flatten_classification(tool.classifications)
3340
flatten_classification(ontology_builder.classifications)

labelbox/exceptions.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,9 @@ class InconsistentOntologyException(Exception):
112112

113113
class MALValidationError(LabelboxError):
114114
"""Raised when user input is invalid for MAL imports."""
115-
...
115+
pass
116+
117+
118+
class OperationNotAllowedException(Exception):
119+
"""Raised when user does not have permissions to a resource or has exceeded usage limit"""
120+
pass

0 commit comments

Comments
 (0)