def environment(): workspace = os.getenv("WORKSPACE_NAME") admin_token = os.getenv("ADMIN_NEPTUNE_API_TOKEN") user = os.getenv("USER_USERNAME") project_name, project_key = a_project_name(project_slug=fake.slug()) project_identifier = normalize_project_name(name=project_name, workspace=workspace) created_project_identifier = create_project( name=project_name, key=project_key, visibility="priv", workspace=workspace, api_token=admin_token, ) add_project_member( name=created_project_identifier, username=user, # pylint: disable=no-member role="contributor", api_token=admin_token, ) yield Environment( workspace=workspace, project=project_identifier, user_token=os.getenv("NEPTUNE_API_TOKEN"), admin_token=admin_token, admin=os.getenv("ADMIN_USERNAME"), user=user, )
def get_project_list(api_token: Optional[str] = None) -> List[str]: """Get a list of projects you have access to. Args: api_token(str, optional): User’s API token. Defaults to `None`. If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken. .. note:: It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your API token in plain text in your source code. Returns: ``List[str]``: list of project names of a format 'WORKSPACE/PROJECT' Examples: >>> from neptune import management >>> management.get_project_list() You may also want to check `management API reference`_. .. _management API reference: https://docs.neptune.ai/api-reference/management """ verify_type("api_token", api_token, (str, type(None))) backend_client = _get_backend_client(api_token=api_token) params = { "userRelation": "viewerOrHigher", "sortBy": ["lastViewed"], **DEFAULT_REQUEST_KWARGS, } projects = backend_client.api.listProjects( **params).response().result.entries return [ normalize_project_name(name=project.name, workspace=project.organizationName) for project in projects ]
def test_standard_scenario(self, environment: "Environment"): project_name, project_key = a_project_name( project_slug=f"{fake.slug()}-mgmt") project_identifier = normalize_project_name( name=project_name, workspace=environment.workspace) assert project_identifier not in get_project_list( api_token=environment.admin_token) assert environment.user in get_workspace_member_list( name=environment.workspace, api_token=environment.admin_token) assert (get_workspace_member_list( name=environment.workspace, api_token=environment.admin_token).get( environment.user) == "member") created_project_identifier = create_project( name=project_name, key=project_key, visibility="priv", workspace=environment.workspace, api_token=environment.admin_token, ) assert created_project_identifier == project_identifier assert created_project_identifier in get_project_list( api_token=environment.admin_token) assert environment.user not in get_project_member_list( name=created_project_identifier, api_token=environment.admin_token) add_project_member( name=created_project_identifier, username=environment.user, role="contributor", api_token=environment.admin_token, ) assert environment.user in get_project_member_list( name=created_project_identifier, api_token=environment.admin_token) assert (get_project_member_list(name=created_project_identifier, api_token=environment.admin_token).get( environment.user) == "contributor") assert created_project_identifier in get_project_list( api_token=environment.user_token) remove_project_member( name=created_project_identifier, username=environment.user, api_token=environment.admin_token, ) assert environment.user not in get_project_member_list( name=created_project_identifier, api_token=environment.admin_token) delete_project(name=created_project_identifier, api_token=environment.admin_token) assert project_identifier not in get_project_list( api_token=environment.admin_token)
def remove_project_member( name: str, username: str, workspace: Optional[str] = None, api_token: Optional[str] = None, ): """Removes member from the Neptune project. Args: name(str): The name of the project in Neptune in the format 'WORKSPACE/PROJECT'. If workspace argument was set, it should only contain 'PROJECT' instead of 'WORKSPACE/PROJECT'. username(str): name of the user you want to remove from the project. workspace(str, optional): Name of your Neptune workspace. If you specify change the format of the name argument to 'PROJECT' instead of 'WORKSPACE/PROJECT'. If 'None' it will be parsed from the name argument. api_token(str, optional): User’s API token. Defaults to `None`. If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken. .. note:: It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your API token in plain text in your source code. Examples: >>> from neptune import management >>> management.remove_project_member(name="awesome-team/amazing-project", ... username="******") You may also want to check `management API reference`_. .. _management API reference: https://docs.neptune.ai/api-reference/management """ verify_type("name", name, str) verify_type("username", username, str) verify_type("workspace", workspace, (str, type(None))) verify_type("api_token", api_token, (str, type(None))) backend_client = _get_backend_client(api_token=api_token) project_identifier = normalize_project_name(name=name, workspace=workspace) params = { "projectIdentifier": project_identifier, "userId": username, **DEFAULT_REQUEST_KWARGS, } try: backend_client.api.deleteProjectMember(**params).response() except HTTPNotFound as e: raise ProjectNotFound(name=project_identifier) from e except HTTPUnprocessableEntity as e: raise UserNotExistsOrWithoutAccess(user=username, project=project_identifier) from e except HTTPForbidden as e: raise AccessRevokedOnMemberRemoval(user=username, project=project_identifier) from e
def test_normalize_project_name(self): self.assertEqual("jackie/sandbox", normalize_project_name(name="jackie/sandbox")) self.assertEqual( "jackie/sandbox", normalize_project_name(name="sandbox", workspace="jackie")) self.assertEqual( "jackie/sandbox", normalize_project_name(name="jackie/sandbox", workspace="jackie"), ) with self.assertRaises(InvalidProjectName): normalize_project_name(name="nothing/else/matters") with self.assertRaises(MissingWorkspaceName): normalize_project_name(name="sandbox") with self.assertRaises(ConflictingWorkspaceName): normalize_project_name(name="jackie/sandbox", workspace="john")
def get_project_member_list(name: str, workspace: Optional[str] = None, api_token: Optional[str] = None) -> Dict[str, str]: """Get a list of members for a project. Args: name(str): The name of the project in Neptune in the format 'WORKSPACE/PROJECT'. If workspace argument was set it should only contain 'PROJECT' instead of 'WORKSPACE/PROJECT'. workspace(str, optional): Name of your Neptune workspace. If you specify change the format of the name argument to 'PROJECT' instead of 'WORKSPACE/PROJECT'. If 'None' it will be parsed from the name argument. api_token(str, optional): User’s API token. Defaults to `None`. If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken. .. note:: It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your API token in plain text in your source code. Returns: ``Dict[str, str]``: Dictionary with usernames as keys and ProjectMemberRoles ('owner', 'contributor', 'viewer') as values. Examples: >>> from neptune import management >>> management.get_project_member_list(name="awesome-team/amazing-project") You may also want to check `management API reference`_. .. _management API reference: https://docs.neptune.ai/api-reference/management """ verify_type("name", name, str) verify_type("workspace", workspace, (str, type(None))) verify_type("api_token", api_token, (str, type(None))) backend_client = _get_backend_client(api_token=api_token) project_identifier = normalize_project_name(name=name, workspace=workspace) params = { "projectIdentifier": project_identifier, **DEFAULT_REQUEST_KWARGS } try: result = backend_client.api.listProjectMembers( **params).response().result return { f"{m.registeredMemberInfo.username}": ProjectMemberRoleDTO.to_domain(m.role) for m in result } except HTTPNotFound as e: raise ProjectNotFound(name=project_identifier) from e
def add_project_member( name: str, username: str, role: str, workspace: Optional[str] = None, api_token: Optional[str] = None, ): """Adds member to the Neptune project. Args: name(str): The name of the project in Neptune in the format 'WORKSPACE/PROJECT'. If workspace argument was set, it should only contain 'PROJECT' instead of 'WORKSPACE/PROJECT'. username(str): Name of the user you want to add to the project. role(str): level of permissions the user should have in a project. Can be set to: - 'viewer': can only view project content and members - 'contributor': can view and edit project content and only view members - 'owner': can view and edit project content and members For more information, see `user roles in a project docs`_. workspace(str, optional): Name of your Neptune workspace. If you specify it, change the format of the name argument to 'PROJECT' instead of 'WORKSPACE/PROJECT'. If 'None' it will be parsed from the name argument. api_token(str, optional): User’s API token. Defaults to `None`. If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken. .. note:: It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your API token in plain text in your source code. Examples: >>> from neptune import management >>> management.add_project_member(name="awesome-team/amazing-project", ... username="******", ... role="contributor") You may also want to check `management API reference`_. .. _management API reference: https://docs.neptune.ai/api-reference/management .. _user roles in a project docs: https://docs.neptune.ai/administration/user-management#roles-in-a-project """ verify_type("name", name, str) verify_type("username", username, str) verify_type("role", role, str) verify_type("workspace", workspace, (str, type(None))) verify_type("api_token", api_token, (str, type(None))) backend_client = _get_backend_client(api_token=api_token) project_identifier = normalize_project_name(name=name, workspace=workspace) params = { "projectIdentifier": project_identifier, "member": { "userId": username, "role": ProjectMemberRoleDTO.from_str(role).value, }, **DEFAULT_REQUEST_KWARGS, } try: backend_client.api.addProjectMember(**params).response() except HTTPNotFound as e: raise ProjectNotFound(name=project_identifier) from e except HTTPConflict as e: raise UserAlreadyHasAccess(user=username, project=project_identifier) from e
def create_project( name: str, key: str, workspace: Optional[str] = None, visibility: str = ProjectVisibility.PRIVATE, description: Optional[str] = None, api_token: Optional[str] = None, ) -> str: """Creates a new project in your Neptune workspace. Args: name(str): The name of the project in Neptune in the format 'WORKSPACE/PROJECT'. If workspace argument was set, it should only contain 'PROJECT' instead of 'WORKSPACE/PROJECT'. key(str): Project identifier. It has to be contain 1-10 upper case letters or numbers. For example, 'GOOD5' workspace(str, optional): Name of your Neptune workspace. If you specify it, change the format of the name argument to 'PROJECT' instead of 'WORKSPACE/PROJECT'. If 'None' it will be parsed from the `name` argument. visibility(str, optional): level of visibility you want your project to have. Can be set to: - 'pub' for public projects - 'priv' for private projects If 'None' it will be set to 'priv' description(str, optional): Project description. If 'None', it will be left empty. api_token(str, optional): User’s API token. Defaults to `None`. If `None`, the value of `NEPTUNE_API_TOKEN` environment variable will be taken. .. note:: It is strongly recommended to use `NEPTUNE_API_TOKEN` environment variable rather than placing your API token in plain text in your source code. Returns: ``str``: name of the new project you created. Examples: >>> from neptune import management >>> management.create_project(name="awesome-team/amazing-project", ... key="AMA", ... visibility="pub") You may also want to check `management API reference`_. .. _management API reference: https://docs.neptune.ai/api-reference/management """ verify_type("name", name, str) verify_type("key", key, str) verify_type("workspace", workspace, (str, type(None))) verify_type("visibility", visibility, str) verify_type("description", description, (str, type(None))) verify_type("api_token", api_token, (str, type(None))) backend_client = _get_backend_client(api_token=api_token) project_identifier = normalize_project_name(name=name, workspace=workspace) project_spec = re.search(PROJECT_QUALIFIED_NAME_PATTERN, project_identifier) workspace, name = project_spec["workspace"], project_spec["project"] try: workspaces = (backend_client.api.listOrganizations( **DEFAULT_REQUEST_KWARGS).response().result) workspace_name_to_id = {f"{f.name}": f.id for f in workspaces} except HTTPNotFound: raise WorkspaceNotFound(workspace=workspace) if workspace not in workspace_name_to_id: raise WorkspaceNotFound(workspace=workspace) params = { "projectToCreate": { "name": name, "description": description, "projectKey": key, "organizationId": workspace_name_to_id[workspace], "visibility": ProjectVisibilityDTO.from_str(visibility).value, }, **DEFAULT_REQUEST_KWARGS, } try: response = backend_client.api.createProject(**params).response() return normalize_project_name( name=response.result.name, workspace=response.result.organizationName) except HTTPBadRequest as e: validation_errors = parse_validation_errors(error=e) if "ERR_NOT_UNIQUE" in validation_errors: raise ProjectAlreadyExists(name=project_identifier) from e raise BadRequestException(validation_errors=validation_errors) except HTTPUnprocessableEntity as e: raise ProjectsLimitReached() from e