google/generativeai/permission.py (104 lines of code) (raw):

# -*- coding: utf-8 -*- # Copyright 2024 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import annotations from typing import Callable import google.ai.generativelanguage as glm from google.generativeai.types import permission_types from google.generativeai.types import retriever_types from google.generativeai.types import model_types _RESOURCE_TYPE: dict[str, str] = { "corpus": "corpora", "corpora": "corpora", "tunedmodel": "tunedModels", "tunedmodels": "tunedModels", } def _to_resource_type(x: str) -> str: if isinstance(x, str): x = x.lower() resource_type = _RESOURCE_TYPE.get(x, None) if not resource_type: raise ValueError(f"Unsupported resource type. Got: `{x}` instead.") return resource_type def _validate_resource_name(x: str, resource_type: str) -> None: if resource_type == "corpora": if not retriever_types.valid_name(x): raise ValueError(retriever_types.NAME_ERROR_MSG.format(length=len(x), name=x)) elif resource_type == "tunedModels": if not model_types.valid_tuned_model_name(x): raise ValueError(model_types.TUNED_MODEL_NAME_ERROR_MSG.format(length=len(x), name=x)) else: raise ValueError(f"Unsupported resource type: {resource_type}") def _validate_permission_id(x: str) -> None: if not permission_types.valid_id(x): raise ValueError(permission_types.INVALID_PERMISSION_ID_MSG.format(permission_id=x)) def _get_valid_name_components(name: str) -> str: # name is of the format: resource_type/resource_name/permissions/permission_id name_path_components = name.split("/") if len(name_path_components) != 4: raise ValueError( f"Invalid name format. Expected format: \ `resource_type/<resource_name>/permissions/<permission_id>`. Got: `{name}` instead." ) resource_type, resource_name, permission_placeholder, permission_id = name_path_components resource_type = _to_resource_type(resource_type) permission_id = "/".join([permission_placeholder, permission_id]) _validate_resource_name(resource_name, resource_type) _validate_permission_id(permission_id) return "/".join([resource_type, resource_name, permission_id]) def _construct_name( name: str | None = None, resource_name: str | None = None, permission_id: str | int | None = None, resource_type: str | None = None, ) -> str: # resource_name is the name of the supported resource (corpus or tunedModel as of now) for which the permission is being created. if not name: # if name is not provided, then try to construct name via provided resource_name and permission_id. if not (resource_name and permission_id): raise ValueError( f"Invalid arguments: Either `name` or both `resource_name` and `permission_id` must be provided. Received name: {name}, resource_name: {resource_name}, permission_id: {permission_id}." ) if resource_type: resource_type = _to_resource_type(resource_type) else: # if resource_type is not provided, then try to infer it from resource_name. resource_path_components = resource_name.split("/") if len(resource_path_components) != 2: raise ValueError( f"Invalid `resource_name` format: Expected format is `resource_type/resource_name` (2 components). Received: `{resource_name}` with {len(resource_path_components)} components." ) resource_type = _to_resource_type(resource_path_components[0]) if f"{resource_type}/" in resource_name: name = f"{resource_name}/" else: name = f"{resource_type}/{resource_name}/" if isinstance(permission_id, int) or "permissions/" not in permission_id: name += f"permissions/{permission_id}" else: name += permission_id # if name is provided, override resource_name and permission_id name = _get_valid_name_components(name) return name def get_permission( name: str | None = None, *, client: glm.PermissionServiceClient | None = None, resource_name: str | None = None, permission_id: str | int | None = None, resource_type: str | None = None, ) -> permission_types.Permission: """Calls the API to retrieve detailed information about a specific permission based on resource type and permission identifiers Args: name: The name of the permission. resource_name: The name of the supported resource for which the permission details are needed. permission_id: The name of the permission. resource_type: The type of the resource (corpus or tunedModel as of now) for which the permission details are needed. If not provided, it will be inferred from `resource_name`. Returns: The permission as an instance of `permission_types.Permission`. """ name = _construct_name( name=name, resource_name=resource_name, permission_id=permission_id, resource_type=resource_type, ) return permission_types.Permission.get(name=name, client=client) async def get_permission_async( name: str | None = None, *, client: glm.PermissionServiceAsyncClient | None = None, resource_name: str | None = None, permission_id: str | int | None = None, resource_type: str | None = None, ) -> permission_types.Permission: """ This is the async version of `permission.get_permission`. """ name = _construct_name( name=name, resource_name=resource_name, permission_id=permission_id, resource_type=resource_type, ) return await permission_types.Permission.get_async(name=name, client=client)