diff --git a/.gitignore b/.gitignore index b15995323..ca9669026 100644 --- a/.gitignore +++ b/.gitignore @@ -131,3 +131,9 @@ dmypy.json # macos files .DS_STORE + +# Sphinx Docs build +docs/build/ +# and source files +docs/source/_static +docs/source/_templates diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 000000000..d0c3cbf10 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 000000000..57cbf138b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,42 @@ +# Labelbox Python SDK API Documentation + +The Labelbox Python API documentation is generated from source code comments +using Sphinx (https://www.sphinx-doc.org/). + +## Preparing the Sphinx environment + +To generate the documentation install Sphinx and Sphinxcontrib-Napoleon. The +easiest way to do it is using a Python virtual env and pip: + +``` +# create a virtual environment +python3 -m venv labelbox_docs_venv + +# activate the venv +source ./labelbox_docs_venv/bin/activate + +# upgrade venv pip and setuptools +pip install --upgrade pip setuptools + +# install Sphinx and necessary contrib from requriements +pip install -r labelbox_root/docs/requirements.txt + +# install Labelbox dependencies +pip install -r labelbox_root/requirements.txt +``` + +There are other ways to do prepare the environment, but we highly recommend +using a Python virtual environment. + +## Generating Labelbox SDK API documentation + +With the Sphinx environment prepared, enter the docs folder: + +``` +cd labelbox_root/docs/ +``` + +Run the make build tool, instructing it to build docs as HTML: +``` +make html +``` diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 000000000..6247f7e23 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +if "%1" == "" goto help + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 000000000..ac42c4269 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,3 @@ +Sphinx==3.4.3 +sphinxcontrib-napoleon==0.7 +sphinx-rtd-theme==0.5.1 diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 000000000..131ae59bc --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,56 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +import sys +sys.path.insert(0, os.path.abspath('../..')) + + +# -- Project information ----------------------------------------------------- + +project = 'Labelbox Python API reference' +copyright = '2021, Labelbox' +author = 'Alexandra Cota' + +release = '2.4' + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.viewcode', + 'sphinxcontrib.napoleon' +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'sphinx_rtd_theme' + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 000000000..4bf477382 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,171 @@ +Labelbox Python API reference +=================================== + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + +Client +---------------------- + +.. automodule:: labelbox.client + :members: + :special-members: __init__ + :exclude-members: upload_data, upload_file + :show-inheritance: + +AssetMetadata +-------------------------------------- + +.. automodule:: labelbox.schema.asset_metadata + :members: + :show-inheritance: + +Benchmark +-------------------------------- + +.. automodule:: labelbox.schema.benchmark + :members: + :show-inheritance: + +BulkImportRequest +-------------------------------------------- + +.. automodule:: labelbox.schema.bulk_import_request + :members: + :exclude-members: create_from_local_file, create_from_objects, create_from_url, from_name + :show-inheritance: + +DataRow +-------------------------------- + +.. automodule:: labelbox.schema.data_row + :members: + :show-inheritance: + +Dataset +------------------------------ + +.. automodule:: labelbox.schema.dataset + :members: + :show-inheritance: + +Label +---------------------------- + +.. automodule:: labelbox.schema.label + :members: + :show-inheritance: + +LabelingFrontend +----------------------------------------- + +.. automodule:: labelbox.schema.labeling_frontend + :members: LabelingFrontend + :exclude-members: LabelingFrontendOptions + :show-inheritance: + +LabelingFrontendOptions +----------------------------------------- +.. automodule:: labelbox.schema.labeling_frontend + :members: LabelingFrontendOptions + :exclude-members: LabelingFrontend + :show-inheritance: + :noindex: + +LabelingParameterOverride +----------------------------------------- +.. automodule:: labelbox.schema.project + :members: LabelingParameterOverride + :show-inheritance: + :noindex: + +Ontology +------------------------------- + +.. automodule:: labelbox.schema.ontology + :members: + :exclude-members: OntologyEntity, Classification, Tool, Option + :show-inheritance: + +Organization +----------------------------------- + +.. automodule:: labelbox.schema.organization + :members: + :show-inheritance: + +Prediction +--------------------------------- + +.. automodule:: labelbox.schema.prediction + :members: Prediction + :exclude-members: PredictionModel + :show-inheritance: + +PredictionModel +--------------------------------- +.. automodule:: labelbox.schema.prediction + :members: PredictionModel + :exclude-members: Prediction + :show-inheritance: + :noindex: + +Project +------------------------------ + +.. automodule:: labelbox.schema.project + :members: + :exclude-members: LabelerPerformance, LabelingParameterOverride + :show-inheritance: + +Review +----------------------------- + +.. automodule:: labelbox.schema.review + :members: + :show-inheritance: + +Task +--------------------------- + +.. automodule:: labelbox.schema.task + :members: + :show-inheritance: + +User +--------------------------- + +.. automodule:: labelbox.schema.user + :members: + :show-inheritance: + +Webhook +------------------------------ + +.. automodule:: labelbox.schema.webhook + :members: + :show-inheritance: + +Exceptions +-------------------------- + +.. automodule:: labelbox.exceptions + :members: + :show-inheritance: + +Pagination +-------------------------- + +.. automodule:: labelbox.pagination + :members: + :special-members: __init__ + :show-inheritance: + +Enums +---------------------------- + +.. automodule:: labelbox.schema.enums + :members: + :show-inheritance: + diff --git a/labelbox/client.py b/labelbox/client.py index 96ba7ccf0..204c763a5 100644 --- a/labelbox/client.py +++ b/labelbox/client.py @@ -26,9 +26,11 @@ class Client: - """ A Labelbox client. Contains info necessary for connecting to - a Labelbox server (URL, authentication key). Provides functions for - querying and creating top-level data objects (Projects, Datasets). + """ A Labelbox client. + + Contains info necessary for connecting to a Labelbox server (URL, + authentication key). Provides functions for querying and creating + top-level data objects (Projects, Datasets). """ def __init__(self, @@ -36,23 +38,20 @@ def __init__(self, endpoint='https://api.labelbox.com/graphql'): """ Creates and initializes a Labelbox Client. - Logging is defaulted to level WARNING. To receive more verbose - output to console, update logging.level to the - appropriate level. + Logging is defaulted to level WARNING. To receive more verbose + output to console, update `logging.level` to the appropriate level. - >>> import logger - >>> logging.basicConfig(level = logging.INFO) - >>> client = Client("") + >>> import logger + >>> logging.basicConfig(level = logging.INFO) + >>> client = Client("") Args: - api_key (str): API key. If None, the key is obtained from - the "LABELBOX_API_KEY" environment variable. + api_key (str): API key. If None, the key is obtained from the "LABELBOX_API_KEY" environment variable. endpoint (str): URL of the Labelbox server to connect to. Raises: labelbox.exceptions.AuthenticationError: If no `api_key` is provided as an argument or via the environment variable. - """ if api_key is None: if _LABELBOX_API_KEY not in os.environ: @@ -74,8 +73,10 @@ def __init__(self, labelbox.exceptions.InternalServerError)) def execute(self, query, params=None, timeout=10.0): """ Sends a request to the server for the execution of the - given query. Checks the response for errors and wraps errors - in appropriate labelbox.exceptions.LabelboxError subtypes. + given query. + + Checks the response for errors and wraps errors + in appropriate `labelbox.exceptions.LabelboxError` subtypes. Args: query (str): The query to execute. @@ -219,7 +220,6 @@ def upload_file(self, path: str) -> str: str, the URL of uploaded data. Raises: labelbox.exceptions.LabelboxError: If upload failed. - """ content_type, _ = mimetypes.guess_type(path) filename = os.path.basename(path) @@ -336,8 +336,8 @@ def get_dataset(self, dataset_id): def get_user(self): """ Gets the current User database object. + >>> user = client.get_user() - """ return self._get_single(User, None) @@ -434,16 +434,15 @@ def _create(self, db_object_type, data): return db_object_type(self, res) def create_dataset(self, **kwargs): - """ Creates a Dataset object on the server. Attribute values are - passed as keyword arguments: + """ Creates a Dataset object on the server. + + Attribute values are passed as keyword arguments. - >>> project = client.get_project("") - >>> dataset = client.create_dataset(name="", projects=project) + >>> project = client.get_project("") + >>> dataset = client.create_dataset(name="", projects=project) - Kwargs: - Keyword arguments with new Dataset attribute values. - Keys are attribute names (in Python, snake-case convention) and - values are desired attribute values. + Args: + **kwargs: Keyword arguments with Dataset attribute values. Returns: A new Dataset object. Raises: @@ -453,15 +452,14 @@ def create_dataset(self, **kwargs): return self._create(Dataset, kwargs) def create_project(self, **kwargs): - """ Creates a Project object on the server. Attribute values are - passed as keyword arguments: + """ Creates a Project object on the server. + + Attribute values are passed as keyword arguments. - >>> project = client.create_project(name="", description="") + >>> project = client.create_project(name="", description="") - Kwargs: - Keyword arguments with new Project attribute values. - Keys are attribute names (in Python, snake-case convention) and - values are desired attribute values. + Args: + **kwargs: Keyword arguments with Project attribute values. Returns: A new Project object. Raises: diff --git a/labelbox/exceptions.py b/labelbox/exceptions.py index 9dc8a75cf..9a7292b33 100644 --- a/labelbox/exceptions.py +++ b/labelbox/exceptions.py @@ -31,6 +31,7 @@ class ResourceNotFoundError(LabelboxError): def __init__(self, db_object_type, params): """ Constructor. + Args: db_object_type (type): A labelbox.schema.DbObject subtype. params (dict): Dict of params identifying the sought resource. diff --git a/labelbox/pagination.py b/labelbox/pagination.py index 566edffa2..5b8b6719a 100644 --- a/labelbox/pagination.py +++ b/labelbox/pagination.py @@ -4,16 +4,17 @@ class PaginatedCollection: """ An iterable collection of database objects (Projects, Labels, etc...). + Implements automatic (transparent to the user) paginated fetching during iteration. Intended for use by library internals and not by the end user. - For a list of attributes see __init__(...) documentation. The params of __init__ map exactly to object attributes. """ def __init__(self, client, query, params, dereferencing, obj_class): """ Creates a PaginatedCollection. - Params: + + Args: client (labelbox.Client): the client used for fetching data from DB. query (str): Base query used for pagination. It must contain two '%d' placeholders, the first for pagination 'skip' clause and diff --git a/labelbox/schema/asset_metadata.py b/labelbox/schema/asset_metadata.py index f0990834f..c5aa0ff9c 100644 --- a/labelbox/schema/asset_metadata.py +++ b/labelbox/schema/asset_metadata.py @@ -3,8 +3,11 @@ class AssetMetadata(DbObject): - """ AssetMetadata is a datatype to provide extra context about an asset - while labeling. + """ Asset metadata (AKA Attachments) provides extra context about an asset while labeling. + + Attributes: + meta_type (str): IMAGE, VIDEO, TEXT, or IMAGE_OVERLAY + meta_value (str): URL to an external file or a string of text """ VIDEO = "VIDEO" IMAGE = "IMAGE" diff --git a/labelbox/schema/benchmark.py b/labelbox/schema/benchmark.py index fe5075fc7..f703c2519 100644 --- a/labelbox/schema/benchmark.py +++ b/labelbox/schema/benchmark.py @@ -3,12 +3,21 @@ class Benchmark(DbObject): - """ Benchmarks (also known as Golden Standard) is a quality assurance tool - for training data. Training data quality is the measure of accuracy and - consistency of the training data. Benchmarks works by interspersing data - to be labeled, for which there is a benchmark label, to each person labeling. - These labeled data are compared against their respective benchmark and an + """ Represents a benchmark label. + + The Benchmarks tool works by interspersing data to be labeled, for + which there is a benchmark label, to each person labeling. These + labeled data are compared against their respective benchmark and an accuracy score between 0 and 100 percent is calculated. + + Attributes: + created_at (datetime) + last_activity (datetime) + average_agreement (float) + completed_count (int) + + created_by (Relationship): `ToOne` relationship to User + reference_label (Relationship): `ToOne` relationship to Label """ created_at = Field.DateTime("created_at") created_by = Relationship.ToOne("User", False, "created_by") diff --git a/labelbox/schema/bulk_import_request.py b/labelbox/schema/bulk_import_request.py index b1ff198ce..a8d54e40b 100644 --- a/labelbox/schema/bulk_import_request.py +++ b/labelbox/schema/bulk_import_request.py @@ -92,6 +92,19 @@ def _send_create_file_command( class BulkImportRequest(DbObject): + """Represents the import job when importing annotations. + + Attributes: + name (str) + state (Enum): FAILED, RUNNING, or FINISHED (Refers to the whole import job) + input_file_url (str): URL to your web-hosted NDJSON file + error_file_url (str): NDJSON that contains error messages for failed annotations + status_file_url (str): NDJSON that contains status for each annotation + created_at (datetime): UTC timestamp for date BulkImportRequest was created + + project (Relationship): `ToOne` relationship to Project + created_by (Relationship): `ToOne` relationship to User + """ name = Field.String("name") state = Field.Enum(BulkImportRequestState, "state") input_file_url = Field.String("input_file_url") @@ -103,8 +116,7 @@ class BulkImportRequest(DbObject): created_by = Relationship.ToOne("User", False, "created_by") def refresh(self) -> None: - """ - Synchronizes values of all fields with the database. + """Synchronizes values of all fields with the database. """ query_str, params = query.get_single(BulkImportRequest, self.uid) res = self.client.execute(query_str, params) @@ -112,7 +124,8 @@ def refresh(self) -> None: self._set_field_values(res) def wait_until_done(self, sleep_time_seconds: int = 30) -> None: - """ + """Blocks import job until certain conditions are met. + Blocks until the BulkImportRequest.state changes either to `BulkImportRequestState.FINISHED` or `BulkImportRequestState.FAILED`, periodically refreshing object's state. @@ -196,8 +209,9 @@ def create_from_url(cls, client, project_id: str, name: str, def create_from_objects(cls, client, project_id: str, name: str, predictions: Iterable[dict]) -> 'BulkImportRequest': """ - Creates a BulkImportRequest from an iterable of dictionaries conforming to - JSON predictions format, e.g.: + Creates a `BulkImportRequest` from an iterable of dictionaries. + + Conforms to JSON predictions format, e.g.: ``{ "uuid": "9fd9a92e-2560-4e77-81d4-b2e955800092", "schemaId": "ckappz7d700gn0zbocmqkwd9i", diff --git a/labelbox/schema/data_row.py b/labelbox/schema/data_row.py index f8d12361c..78c068298 100644 --- a/labelbox/schema/data_row.py +++ b/labelbox/schema/data_row.py @@ -5,8 +5,21 @@ class DataRow(DbObject, Updateable, BulkDeletable): - """ A DataRow represents a single piece of data. For example, if you have - a CSV with 100 rows, you will have 1 Dataset and 100 DataRows. + """ Internal Labelbox representation of a single piece of data (e.g. image, video, text). + + Attributes: + external_id (str): User-generated file name or identifier + row_data (str): Paths to local files are uploaded to Labelbox's server. + Otherwise, it's treated as an external URL. + updated_at (datetime) + created_at (datetime) + + dataset (Relationship): `ToOne` relationship to Dataset + created_by (Relationship): `ToOne` relationship to User + organization (Relationship): `ToOne` relationship to Organization + labels (Relationship): `ToMany` relationship to Label + metadata (Relationship): `ToMany` relationship to AssetMetadata + predictions (Relationship): `ToMany` relationship to Prediction """ external_id = Field.String("external_id") row_data = Field.String("row_data") @@ -36,7 +49,8 @@ def __init__(self, *args, **kwargs): self.metadata.supports_sorting = False def create_metadata(self, meta_type, meta_value): - """ Creates an asset metadata for this DataRow. + """ Attaches asset metadata to a DataRow. + >>> datarow.create_metadata("TEXT", "This is a text message") Args: @@ -44,7 +58,7 @@ def create_metadata(self, meta_type, meta_value): VIDEO, IMAGE, TEXT. meta_value (str): Asset metadata value. Returns: - AssetMetadata DB object. + `AssetMetadata` DB object. """ meta_type_param = "metaType" meta_value_param = "metaValue" diff --git a/labelbox/schema/dataset.py b/labelbox/schema/dataset.py index 750b2e013..7a7f0ecd4 100644 --- a/labelbox/schema/dataset.py +++ b/labelbox/schema/dataset.py @@ -8,8 +8,19 @@ class Dataset(DbObject, Updateable, Deletable): - """ A dataset is a collection of DataRows. For example, if you have a CSV with - 100 rows, you will have 1 Dataset and 100 DataRows. + """ A Dataset is a collection of DataRows. + + Attributes: + name (str) + description (str) + updated_at (datetime) + created_at (datetime) + + projects (Relationship): `ToMany` relationship to Project + data_rows (Relationship): `ToMany` relationship to DataRow + created_by (Relationship): `ToOne` relationship to User + organization (Relationship): `ToOne` relationship to Organization + """ name = Field.String("name") description = Field.String("description") @@ -27,12 +38,10 @@ def create_data_row(self, **kwargs): >>> dataset.create_data_row(row_data="http://my_site.com/photos/img_01.jpg") - Kwargs: - Key-value arguments containing new `DataRow` data. - At a minimum `kwargs` must contain `row_data`. The value for - `row_data` is a string. If it is a path to an existing local - file then it is uploaded to Labelbox's server. Otherwise it is - treated as an external URL. + Args: + **kwargs: Key-value arguments containing new `DataRow` data. At a minimum, + must contain `row_data`. + Raises: InvalidQueryError: If `DataRow.row_data` field value is not provided in `kwargs`. diff --git a/labelbox/schema/enums.py b/labelbox/schema/enums.py index b6943cef9..438fc496a 100644 --- a/labelbox/schema/enums.py +++ b/labelbox/schema/enums.py @@ -2,6 +2,8 @@ class BulkImportRequestState(Enum): + """ State of the import job when importing annotations (RUNNING, FAILED, or FINISHED). + """ RUNNING = "RUNNING" FAILED = "FAILED" FINISHED = "FINISHED" diff --git a/labelbox/schema/label.py b/labelbox/schema/label.py index ef968b15e..f25ae6c76 100644 --- a/labelbox/schema/label.py +++ b/labelbox/schema/label.py @@ -7,6 +7,19 @@ class Label(DbObject, Updateable, BulkDeletable): """ Label represents an assessment on a DataRow. For example one label could contain 100 bounding boxes (annotations). + + Attributes: + label (str) + seconds_to_label (float) + agreement (float) + benchmark_agreement (float) + is_benchmark_reference (bool) + + project (Relationship): `ToOne` relationship to Project + data_row (Relationship): `ToOne` relationship to DataRow + reviews (Relationship): `ToMany` relationship to Review + created_by (Relationship): `ToOne` relationship to User + """ def __init__(self, *args, **kwargs): @@ -36,9 +49,8 @@ def bulk_delete(labels): def create_review(self, **kwargs): """ Creates a Review for this label. - Kwargs: - Review attributes. At a minimum a `Review.score` field - value must be provided. + Args: + **kwargs: Review attributes. At a minimum, a `Review.score` field value must be provided. """ kwargs[Entity.Review.label.name] = self kwargs[Entity.Review.project.name] = self.project() diff --git a/labelbox/schema/labeling_frontend.py b/labelbox/schema/labeling_frontend.py index 2dbbe813c..13fe76635 100644 --- a/labelbox/schema/labeling_frontend.py +++ b/labelbox/schema/labeling_frontend.py @@ -3,9 +3,18 @@ class LabelingFrontend(DbObject): - """ Is a type representing an HTML / JavaScript UI that is used to generate - labels. “Image Labeling” is the default Labeling Frontend that comes in every + """ Label editor. + + Represents an HTML / JavaScript UI that is used to generate + labels. “Editor” is the default Labeling Frontend that comes in every organization. You can create new labeling frontends for an organization. + + Attributes: + name (str) + description (str) + iframe_url_path (str) + + projects (Relationship): `ToMany` relationship to Project """ name = Field.String("name") description = Field.String("description") @@ -16,6 +25,15 @@ class LabelingFrontend(DbObject): class LabelingFrontendOptions(DbObject): + """ Label interface options. + + Attributes: + customization_options (str) + + project (Relationship): `ToOne` relationship to Project + labeling_frontend (Relationship): `ToOne` relationship to LabelingFrontend + organization (Relationship): `ToOne` relationship to Organization + """ customization_options = Field.String("customization_options") project = Relationship.ToOne("Project") diff --git a/labelbox/schema/ontology.py b/labelbox/schema/ontology.py index 301507884..9b28f6d01 100644 --- a/labelbox/schema/ontology.py +++ b/labelbox/schema/ontology.py @@ -1,4 +1,3 @@ -"""Client side object for interacting with the ontology.""" import abc from dataclasses import dataclass @@ -65,15 +64,20 @@ def from_json(cls, json_dict): class Ontology(DbObject): - """ A ontology specifies which tools and classifications are available - to a project. - - NOTE: This is read only for now. - - >>> project = client.get_project(name="") - >>> ontology = project.ontology() - >>> ontology.normalized - + """An ontology specifies which tools and classifications are available + to a project. This is read only for now. + + Attributes: + name (str) + description (str) + updated_at (datetime) + created_at (datetime) + normalized (json) + object_schema_count (int) + classification_schema_count (int) + + projects (Relationship): `ToMany` relationship to Project + created_by (Relationship): `ToOne` relationship to User """ name = Field.String("name") @@ -93,6 +97,7 @@ def __init__(self, *args, **kwargs) -> None: self._classifications: Optional[List[Classification]] = None def tools(self) -> List[Tool]: + """Get list of tools (AKA objects) in an Ontology.""" if self._tools is None: self._tools = [ Tool.from_json(tool) for tool in self.normalized['tools'] @@ -100,6 +105,7 @@ def tools(self) -> List[Tool]: return self._tools # type: ignore def classifications(self) -> List[Classification]: + """Get list of classifications in an Ontology.""" if self._classifications is None: self._classifications = [ Classification.from_json(classification) diff --git a/labelbox/schema/organization.py b/labelbox/schema/organization.py index 5a4465189..c23d72133 100644 --- a/labelbox/schema/organization.py +++ b/labelbox/schema/organization.py @@ -3,9 +3,19 @@ class Organization(DbObject): - """ An Organization is a group of Users associated with data created by - Users within that Organization. Typically all Users within an Organization - have access to data created by any User in the same Organization. + """ An Organization is a group of Users. + + It is associated with data created by Users within that Organization. + Typically all Users within an Organization have access to data created by any User in the same Organization. + + Attributes: + updated_at (datetime) + created_at (datetime) + name (str) + + users (Relationship): `ToMany` relationship to User + projects (Relationship): `ToMany` relationship to Project + webhooks (Relationship): `ToMany` relationship to Webhook """ # RelationshipManagers in Organization use the type in Query (and diff --git a/labelbox/schema/prediction.py b/labelbox/schema/prediction.py index a59e0ca86..309f5928f 100644 --- a/labelbox/schema/prediction.py +++ b/labelbox/schema/prediction.py @@ -3,15 +3,19 @@ class PredictionModel(DbObject): - """ A prediction model represents a specific version of a model. + """ A PredictionModel creates a Prediction. Legacy editor only. - NOTE: This is used for the legacy editor [1], if you wish to - import annotations, refer to [2] + Refer to BulkImportRequest if using the new Editor. + Attributes: + updated_at (datetime) + created_at (datetime) + name (str) + slug (str) + version (int) - [1] https://labelbox.com/docs/legacy/import-model-prediction - [2] https://labelbox.com/docs/automation/model-assisted-labeling - + created_by (Relationship): `ToOne` relationship to User + organization (Relationship): `ToOne` relationship to Organization """ updated_at = Field.DateTime("updated_at") created_at = Field.DateTime("created_at") @@ -27,15 +31,20 @@ class PredictionModel(DbObject): class Prediction(DbObject): - """ A prediction created by a PredictionModel. - - NOTE: This is used for the legacy editor [1], if you wish to - import annotations, refer to [2] - - - [1] https://labelbox.com/docs/legacy/import-model-prediction - [2] https://labelbox.com/docs/automation/model-assisted-labeling - + """ A prediction created by a PredictionModel. Legacy editor only. + + Refer to BulkImportRequest if using the new Editor. + + Attributes: + updated_at (datetime) + created_at (datetime) + label (str) + agreement (float) + + organization (Relationship): `ToOne` relationship to Organization + prediction_model (Relationship): `ToOne` relationship to PredictionModel + data_row (Relationship): `ToOne` relationship to DataRow + project (Relationship): `ToOne` relationship to Project """ updated_at = Field.DateTime("updated_at") created_at = Field.DateTime("created_at") diff --git a/labelbox/schema/project.py b/labelbox/schema/project.py index e2a6927c3..0411add1b 100644 --- a/labelbox/schema/project.py +++ b/labelbox/schema/project.py @@ -27,6 +27,29 @@ class Project(DbObject, Updateable, Deletable): """ A Project is a container that includes a labeling frontend, an ontology, datasets and labels. + + Attributes: + name (str) + description (str) + updated_at (datetime) + created_at (datetime) + setup_complete (datetime) + last_activity_time (datetime) + auto_audit_number_of_labels (int) + auto_audit_percentage (float) + + datasets (Relationship): `ToMany` relationship to Dataset + created_by (Relationship): `ToOne` relationship to User + organization (Relationship): `ToOne` relationship to Organization + reviews (Relationship): `ToMany` relationship to Review + labeling_frontend (Relationship): `ToOne` relationship to LabelingFrontend + labeling_frontend_options (Relationship): `ToMany` relationship to LabelingFrontendOptions + labeling_parameter_overrides (Relationship): `ToMany` relationship to LabelingParameterOverride + webhooks (Relationship): `ToMany` relationship to Webhook + benchmarks (Relationship): `ToMany` relationship to Benchmark + active_prediction_model (Relationship): `ToOne` relationship to PredictionModel + predictions (Relationship): `ToMany` relationship to Prediction + ontology (Relationship): `ToOne` relationship to Ontology """ name = Field.String("name") description = Field.String("description") @@ -55,11 +78,10 @@ class Project(DbObject, Updateable, Deletable): ontology = Relationship.ToOne("Ontology", True) def create_label(self, **kwargs): - """ Creates a label on a Legacy Editor project. Not - supported in the new Editor. + """ Creates a label on a Legacy Editor project. Not supported in the new Editor. - Kwargs: - Label attributes. At the minimum the label `DataRow`. + Args: + **kwargs: Label attributes. At minimum, the label `DataRow`. """ # Copy-paste of Client._create code so we can inject # a connection to Type. Type objects are on their way to being @@ -86,8 +108,7 @@ def create_label(self, **kwargs): return Label(self.client, res["createLabel"]) def labels(self, datasets=None, order_by=None): - """ - Custom relationship expansion method to support limited filtering. + """ Custom relationship expansion method to support limited filtering. Args: datasets (iterable of Dataset): Optional collection of Datasets @@ -129,9 +150,8 @@ def export_labels(self, timeout_seconds=60): Args: timeout_seconds (float): Max waiting time, in seconds. Returns: - URL of the data file with this Project's labels. If the server - didn't generate during the `timeout_seconds` period, None - is returned. + URL of the data file with this Project's labels. If the server didn't + generate during the `timeout_seconds` period, None is returned. """ sleep_time = 2 id_param = "projectId" @@ -186,7 +206,7 @@ def review_metrics(self, net_score): Args: net_score (None or Review.NetScore): Indicates desired metric. Returns: - int, aggregation count of reviews for given net_score. + int, aggregation count of reviews for given `net_score`. """ if net_score not in (None,) + tuple(Entity.Review.NetScore): raise InvalidQueryError( @@ -230,8 +250,8 @@ def setup(self, labeling_frontend, labeling_frontend_options): self.update(setup_complete=timestamp) def set_labeling_parameter_overrides(self, data): - """ Adds labeling parameter overrides to this project. Example: - + """ Adds labeling parameter overrides to this project. + >>> project.set_labeling_parameter_overrides([ >>> (data_row_1, 2, 3), (data_row_2, 1, 4)]) @@ -307,12 +327,12 @@ def extend_reservations(self, queue_type): return res["extendReservations"] def create_prediction_model(self, name, version): - """ Creates a PredictionModel connected to a Legacy Editor - Project. + """ Creates a PredictionModel connected to a Legacy Editor Project. + Args: name (str): The new PredictionModel's name. version (int): The new PredictionModel's version. - Return: + Returns: A newly created PredictionModel. """ PM = Entity.PredictionModel @@ -324,7 +344,8 @@ def create_prediction_model(self, name, version): return model def create_prediction(self, label, data_row, prediction_model=None): - """ Creates a Prediction within a Legacy Editor Project. + """ Creates a Prediction within a Legacy Editor Project. Not supported + in the new Editor. Args: label (str): The `label` field of the new Prediction. @@ -371,11 +392,10 @@ def enable_model_assisted_labeling(self, toggle: bool=True) -> bool: """ Turns model assisted labeling either on or off based on input Args: - toggle (Boolean): True or False boolean + toggle (bool): True or False boolean Returns: True if toggled on or False if toggled off """ - project_param = "project_id" show_param = "show" @@ -403,15 +423,14 @@ def upload_annotations( """ Uploads annotations to a new Editor project. Args: - name: name of the BulkImportRequest job - annotations: + name (str): name of the BulkImportRequest job + annotations (str or Path or Iterable): url that is publicly accessible by Labelbox containing an ndjson file OR local path to an ndjson file OR iterable of annotation rows Returns: BulkImportRequest - """ if isinstance(annotations, str) or isinstance(annotations, Path): @@ -461,6 +480,12 @@ def _is_url_valid(url: Union[str, Path]) -> bool: f'Invalid annotations given of type: {type(annotations)}') class LabelingParameterOverride(DbObject): + """ Customizes the order of assets in the label queue. + + Attributes: + priority (int): A prioritization score. + number_of_labels (int): Number of times an asset should be labeled. + """ priority = Field.Int("priority") number_of_labels = Field.Int("number_of_labels") diff --git a/labelbox/schema/review.py b/labelbox/schema/review.py index 8a4ee5275..10ff904d2 100644 --- a/labelbox/schema/review.py +++ b/labelbox/schema/review.py @@ -6,10 +6,24 @@ class Review(DbObject, Deletable, Updateable): """ Reviewing labeled data is a collaborative quality assurance technique. + A Review object indicates the quality of the assigned Label. The aggregated - review numbers can be obtained on a Project object. """ + review numbers can be obtained on a Project object. + + Attributes: + created_at (datetime) + updated_at (datetime) + score (float) + + created_by (Relationship): `ToOne` relationship to User + organization (Relationship): `ToOne` relationship to Organization + project (Relationship): `ToOne` relationship to Project + label (Relationship): `ToOne` relationship to Label + """ class NetScore(Enum): + """ Negative, Zero, or Positive. + """ Negative = auto() Zero = auto() Positive = auto() diff --git a/labelbox/schema/task.py b/labelbox/schema/task.py index 9af3e6f91..a6ec0f3b8 100644 --- a/labelbox/schema/task.py +++ b/labelbox/schema/task.py @@ -11,6 +11,16 @@ class Task(DbObject): """ Represents a server-side process that might take a longer time to process. Allows the Task state to be updated and checked on the client side. + + Attributes: + updated_at (datetime) + created_at (datetime) + name (str) + status (str) + completion_percentage (float) + + created_by (Relationship): `ToOne` relationship to User + organization (Relationship): `ToOne` relationship to Organization """ updated_at = Field.DateTime("updated_at") created_at = Field.DateTime("created_at") @@ -33,9 +43,9 @@ def refresh(self): def wait_till_done(self, timeout_seconds=60): """ Waits until the task is completed. Periodically queries the server to update the task attributes. + Args: - timeout_seconds (float): Maximum time this method can block, in - seconds. Defaults to one minute. + timeout_seconds (float): Maximum time this method can block, in seconds. Defaults to one minute. """ check_frequency = 2 # frequency of checking, in seconds while True: diff --git a/labelbox/schema/user.py b/labelbox/schema/user.py index 33b15df79..f8487fa52 100644 --- a/labelbox/schema/user.py +++ b/labelbox/schema/user.py @@ -5,6 +5,21 @@ class User(DbObject): """ A User is a registered Labelbox user (for example you) associated with data they create or import and an Organization they belong to. + + Attributes: + updated_at (datetime) + created_at (datetime) + email (str) + name (str) + nickname (str) + intercom_hash (str) + picture (str) + is_viewer (bool) + is_external_viewer (bool) + + organization (Relationship): `ToOne` relationship to Organization + created_tasks (Relationship): `ToMany` relationship to Task + projects (Relationship): `ToMany` relationship to Project """ updated_at = Field.DateTime("updated_at") created_at = Field.DateTime("created_at") diff --git a/labelbox/schema/webhook.py b/labelbox/schema/webhook.py index bb37481ae..a83b93fb1 100644 --- a/labelbox/schema/webhook.py +++ b/labelbox/schema/webhook.py @@ -7,6 +7,14 @@ class Webhook(DbObject, Updateable): """ Represents a server-side rule for sending notifications to a web-server whenever one of several predefined actions happens within a context of a Project or an Organization. + + Attributes: + updated_at (datetime) + created_at (datetime) + url (str) + topics (str): LABEL_CREATED, LABEL_UPDATED, LABEL_DELETED + status (str): ACTIVE, INACTIVE, REVOKED + """ # Status diff --git a/requirements.txt b/requirements.txt index 07429a0ca..d6e1b9c66 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ requests==2.22.0 ndjson==0.3.1 backoff==1.10.0 +google-api-core>=1.22.1