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
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

# Version 2.5.4 (2021-04-22)
## Added
* User management
* Query for remaining invites and users available to an organization
* Set and update organization roles
* Set / update / revoke project role
* Delete users from organization
* Example notebook added under examples/basics
* Issues and comments export
* Bulk export issues and comments. See `Project.export_labels`
* MAL on Tiled Imagery
* Example notebook added under examples/model_assisted_labeling
* `Dataset.create_data_rows` now allows users to upload tms imagery

# Version 2.5.3 (2021-04-01)
## Added
* Cleanup and add additional example notebooks
Expand Down
3 changes: 3 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
| Labels | [Github](basics/labels.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/basics/labels.ipynb) |
| Ontologies | [Github](basics/ontologies.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/basics/ontologies.ipynb) |
| Projects | [Github](basics/projects.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/basics/projects.ipynb) |
| User Management | [Github](basics/user_management.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/basics/user_management.ipynb) |
------

## [Label Export](label_export)
Expand All @@ -36,6 +37,8 @@
| Named Entity Recognition MAL | [Github](model_assisted_labeling/ner_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/ner_mal.ipynb) |
| 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) |
| 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) |
| 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) |

------

## [Project Configuration](project_configuration)
Expand Down
318 changes: 318 additions & 0 deletions examples/basics/user_management.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "shaped-syria",
"metadata": {},
"source": [
"# User Management\n",
"* This notebook covers the following:\n",
" * create invites\n",
" * query for remaining allowed invites to an organization\n",
" * set and update organization roles\n",
" * assign users to projects\n",
" * set / update / revoke project role\n",
" * delete users from org\n",
"* User invite functions are currently experimental. This means that their interfaces could change."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "limiting-terry",
"metadata": {},
"outputs": [],
"source": "!pip install labelbox"
},
{
"cell_type": "code",
"execution_count": 2,
"id": "hungarian-recipient",
"metadata": {},
"outputs": [],
"source": "from labelbox import Project, Dataset, Client, User\nfrom labelbox.schema.organization import ProjectRole\nfrom getpass import getpass\nimport os"
},
{
"cell_type": "code",
"execution_count": 3,
"id": "intended-course",
"metadata": {},
"outputs": [],
"source": "# If you don't want to give google access to drive you can skip this cell\n# and manually set `API_KEY` below.\n\nCOLAB = \"google.colab\" in str(get_ipython())\nif COLAB:\n !pip install colab-env -qU\n from colab_env import envvar_handler\n envvar_handler.envload()\n\nAPI_KEY = os.environ.get(\"LABELBOX_API_KEY\")\nif not os.environ.get(\"LABELBOX_API_KEY\"):\n API_KEY = getpass(\"Please enter your labelbox api key\")\n if COLAB:\n envvar_handler.add_env(\"LABELBOX_API_KEY\", API_KEY)"
},
{
"cell_type": "markdown",
"id": "raising-nightlife",
"metadata": {},
"source": [
"* You have to specifically enable experimental features to use this functionality. Notice the \n",
"`enable_experimental = True`\n",
" * enables users to send invites and checking the number of seats available via the sdk"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "polished-hampshire",
"metadata": {},
"outputs": [],
"source": "ENDPOINT = \"https://api.labelbox.com/graphql\"\nclient = Client(api_key=API_KEY, endpoint=ENDPOINT, enable_experimental=True)\norganization = client.get_organization()"
},
{
"cell_type": "code",
"execution_count": 5,
"id": "outer-cattle",
"metadata": {},
"outputs": [],
"source": "# Please provide a dummy email here:\n# Preferrably one you can access. If you have a google account you can do email+1@<domain>.com\nDUMMY_EMAIL = \"< SET THIS >\"\n# This should be set to an account that you wan't to change the permissions for.\n# You could invite a new user, accept the invite and use that account if you don't want to effect any active users\nDUMMY_USER_ACCOUNT_ID = \"ckneh4n8c9qvq0706uwwg5i16\""
},
{
"cell_type": "markdown",
"id": "central-performer",
"metadata": {},
"source": [
"### Roles\n",
"* When inviting a new user to an organization, there are various roles to select from.\n",
"* All available roles to your org can be accessed via `client.get_roles()`"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "later-dealing",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"LABELER : cjlvi914y1aa20714372uvzjv\n",
"REVIEWER : cjlvi919b1aa50714k75euii5\n",
"TEAM_MANAGER : cjlvi919q1aa80714b7z3xuku\n",
"ADMIN : cjlvi91a41aab0714677xp87h\n",
"NONE : cjmb6xy80f5vz0780u3mw2rj4\n"
]
}
],
"source": "roles = client.get_roles()\nfor name, role in roles.items():\n print(role.name, \":\", role.uid)"
},
{
"cell_type": "markdown",
"id": "superb-exploration",
"metadata": {},
"source": [
"* Above we printed out all of the roles available to the current org.\n",
"* Notice the `NONE`. That is for project level roles"
]
},
{
"cell_type": "markdown",
"id": "romantic-martin",
"metadata": {},
"source": [
"### Create\n",
"* Users are created by sending an invite\n",
"* An email will be sent to them and they will be asked to join your organization"
]
},
{
"cell_type": "markdown",
"id": "harmful-state",
"metadata": {},
"source": [
"#### Organization Level Permissions\n",
"* Invite a new labeler with labeling permissions on all projects"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "analyzed-partition",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"InviteLimit(remaining=2, used=3, limit=5)"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": "# First make sure that you have enough seats:\norganization.invite_limit()"
},
{
"cell_type": "code",
"execution_count": 8,
"id": "ready-housing",
"metadata": {},
"outputs": [],
"source": "invite = organization.invite_user(DUMMY_EMAIL, roles[\"LABELER\"])"
},
{
"cell_type": "code",
"execution_count": 9,
"id": "touched-quarter",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"2021-04-20 22:11:55.897000+00:00\n",
"Labeler\n",
"< SET THIS >\n"
]
}
],
"source": "print(invite.created_at)\nprint(invite.organization_role_name)\nprint(invite.email)"
},
{
"cell_type": "markdown",
"id": "disabled-evidence",
"metadata": {},
"source": [
"#### Project Level Permissions\n",
"* Invite a new labeler with labeling permissions specific to a set of projects\n",
"* Here we set organization level permissions to Roles.NONE to indicate that the user only has project level permissions"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "nervous-firmware",
"metadata": {},
"outputs": [],
"source": "project = client.create_project(name=\"test_user_management\")\nproject_role = ProjectRole(project=project, role=roles[\"REVIEWER\"])\ninvite = organization.invite_user(DUMMY_EMAIL,\n roles[\"NONE\"],\n project_roles=[project_role])"
},
{
"cell_type": "markdown",
"id": "greatest-halifax",
"metadata": {},
"source": [
"### Read\n",
"* Outstanding invites cannot be queried for at this time. This information can be found in the members tab of the web app.\n",
"* You are able to query for members once they have joined."
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "amateur-egyptian",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<User {'created_at': datetime.datetime(2021, 1, 20, 1, 2, 31, tzinfo=datetime.timezone.utc), 'email': 'msokoloff@labelbox.com', 'intercom_hash': '050b8b292bd66abf88ea9a279c6ee80a530e0f9cf98a06e1d5372ef13697f46b', 'is_external_user': False, 'is_viewer': True, 'nickname': 'msokoloff', 'name': 'Matt Sokoloff', 'picture': 'https://lh6.googleusercontent.com/-gO94Mcw4PGs/AAAAAAAAAAI/AAAAAAAAAAA/AMZuuclv_5P5WICzV1aImhxGADj_OS5c7w/s96-c/photo.jpg', 'uid': 'ckk4q1vgwc0vp0704xhx7m4vk', 'updated_at': datetime.datetime(2021, 4, 1, 15, 48, 27, tzinfo=datetime.timezone.utc)}>\n"
]
}
],
"source": "users = list(organization.users())\nprint(users[0])"
},
{
"cell_type": "markdown",
"id": "bottom-reply",
"metadata": {},
"source": [
"### Update\n",
"* There is no update on invites. Instead you must delete and resend them\n",
"* You can update User roles"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "atlantic-maria",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"<OrgRole {'name': 'Labeler', 'uid': 'cjlvi914y1aa20714372uvzjv'}>\n",
"<OrgRole {'name': 'None', 'uid': 'cjmb6xy80f5vz0780u3mw2rj4'}>\n",
"<OrgRole {'name': 'None', 'uid': 'cjmb6xy80f5vz0780u3mw2rj4'}>\n"
]
}
],
"source": "user = client._get_single(User, DUMMY_USER_ACCOUNT_ID)\n\n# Give the user organization level permissions\nuser.update_org_role(roles[\"LABELER\"])\nprint(user.org_role())\n# Restore project level permissions\nuser.update_org_role(roles[\"NONE\"])\nprint(user.org_role())\n# Make the user a labeler for the current project\nuser.upsert_project_role(project, roles[\"LABELER\"])\nprint(user.org_role())"
},
{
"cell_type": "code",
"execution_count": 13,
"id": "liquid-beast",
"metadata": {},
"outputs": [],
"source": "# Remove the user from a project (Same as setting the project role to `roles.NONE`)\nuser.remove_from_project(project)"
},
{
"cell_type": "markdown",
"id": "portuguese-harvard",
"metadata": {},
"source": [
"### Delete"
]
},
{
"cell_type": "markdown",
"id": "adjacent-partnership",
"metadata": {},
"source": [
"* Invites can only be deleted from the ui at this time. \n",
"* Deleting invites can be done in the members tab of the web app."
]
},
{
"cell_type": "markdown",
"id": "desperate-shield",
"metadata": {},
"source": [
"* Delete the User\n",
"* Make sure you want to remove the user from the org:\n",
"* `>>> organization.remove_user(user)`"
]
},
{
"cell_type": "markdown",
"id": "oriented-demand",
"metadata": {},
"source": [
"### Cleanup\n",
"* We created an extra project. Let's delete it"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "veterinary-repository",
"metadata": {},
"outputs": [],
"source": "project.delete()"
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.2"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading