def get_predefined_folder_contents_async(future_session: "FuturesSession", connection: Connection, folder_type: int, project_id: Optional[str] = None, offset: int = 0, limit: int = 5000): """Get contents of a pre-defined folder. Args: future_session(object): `FuturesSession` object to call MicroStrategy REST Server asynchronously connection: MicroStrategy REST API connection object folder_type (int): predefined folder type, from `EnumDSSXMLFolderNames` project_id (string, optional): id of project offset (int, optional): Starting point within the collection of returned results. Used to control paging behavior. Default is 0. limit (int, optional): Maximum number of items returned for a single request. Used to control paging behavior. Use -1 for no limit. Default is 5000. Returns: Complete Future object. """ if project_id is None: connection._validate_project_selected() project_id = connection.project_id url = f"{connection.base_url}/api/folders/preDefined/{folder_type}" headers = {'X-MSTR-ProjectID': project_id} params = {'offset': offset, 'limit': limit} return future_session.get(url=url, headers=headers, params=params)
def delete_inactive_caches(connection: Connection, days_diff: str = 30, nodes: Union[str, List[str]] = None) -> List[CubeCache]: """Delete inactive caches which have `hit_count` equals 0 and their `last_time_updated` was earlier than `days_diff` before from given `nodes`. When `nodes` are `None` (default value) then all nodes are retrieved from the cluster. Args: connection: MicroStrategy connection object returned by `connection.Connection()` days_diff (int, optional): number of days to determine whether to delete cache when its `hit_count` equals 0. Default value is 30. nodes (list of strings or string, optional): names of nodes from which caches will be deleted. By default, it equals `None` and in that case all nodes' names are loaded from the cluster. Return: list with cache objects which were deleted """ connection._validate_project_selected() caches = list_cube_caches(connection, nodes) # delete caches which fulfill requirements to be treated as inactive deleted_caches = [] for cache in caches: today = datetime.now(timezone.utc) if (cache.hit_count == 0 and (today - _get_datetime(cache.last_update_time)).days > days_diff): cache.delete(force=True) deleted_caches.append(cache) return deleted_caches
def __init__(self, connection: Connection, id: str, name: Optional[str] = None, instance_id: Optional[str] = None, parallel: bool = True, progress_bar: bool = True): """Initialize an instance of a cube by its id. Note: Parameter `name` is not used when fetching. `id` is always used to uniquely identify cube. Args: connection: MicroStrategy connection object returned by `connection.Connection()`. id (str): Identifier of a pre-existing cube containing the required data. name (str): Name of a cube. instance_id (str): Identifier of an instance if cube instance has been already initialized, None by default. parallel (bool, optional): If True (default), utilize optimal number of threads to increase the download speed. If False, this feature will be disabled. progress_bar(bool, optional): If True (default), show the download progress bar. """ super().__init__(connection, id, name=name, instance_id=instance_id, parallel=parallel, progress_bar=progress_bar, subtype=self._OBJECT_SUBTYPE) connection._validate_project_selected() self._get_definition()
def get_predefined_folder_contents(connection: Connection, folder_type: int, project_id: Optional[str] = None, offset: int = 0, limit: int = 5000, error_msg: Optional[str] = None): """Get contents of a pre-defined folder. Args: connection: MicroStrategy REST API connection object folder_type (int): predefined folder type, from `EnumDSSXMLFolderNames` project_id (string, optional): id of project offset (int, optional): Starting point within the collection of returned results. Used to control paging behavior. Default is 0. limit (int, optional): Maximum number of items returned for a single request. Used to control paging behavior. Use -1 for no limit. Default is 5000. Returns: Complete HTTP response object. """ if project_id is None: connection._validate_project_selected() project_id = connection.project_id return connection.get( url=f"{connection.base_url}/api/folders/preDefined/{folder_type}", headers={'X-MSTR-ProjectID': project_id}, params={ 'offset': offset, 'limit': limit })
def create_folder(connection: Connection, name: str, parent_id: str, description: Optional[str] = None, project_id: Optional[str] = None): """Create a folder. Note: When `project_id` is provided then folder will be created in this project. Otherwise it will be created in a project selected within `connection` object. Args: connection: MicroStrategy REST API connection object name (string): name of folder to create parent_id (string): id of folder in which new folder will be created description (string, optional): description of folder to create project_id (string, optional): id of project Returns: Complete HTTP response object. """ project_id = project_id if project_id is not None else connection.project_id body = { "name": name, "description": description, "parent": parent_id, } return connection.post(url=connection.base_url + '/api/folders', headers={'X-MSTR-ProjectID': project_id}, json=body)
def list_folders(connection: Connection, project_id: Optional[str] = None, offset: int = 0, limit: int = 5000, error_msg: Optional[str] = None): """Get a list of folders. Args: connection: MicroStrategy REST API connection object project_id (string, optional): id of project offset (int, optional): Starting point within the collection of returned results. Used to control paging behavior. Default is 0. limit (int, optional): Maximum number of items returned for a single request. Used to control paging behavior. Use -1 for no limit. Default is 5000. Returns: Complete HTTP response object. """ return connection.get(url=f"{connection.base_url}/api/folders", headers={'X-MSTR-ProjectID': project_id}, params={ 'offset': offset, 'limit': limit })
def update_package_holder( connection: Connection, body: dict, id: str, project_id: Optional[str] = None, prefer: str = "respond-async", error_msg: Optional[str] = None) -> requests.Response: """Fill the content of the in-memory metadata package holder per supplied specification. Currently, it's only supported when the holder is empty. Args: connection (Connection): Object representation of connection to MSTR Server. body (dict): dictionarized PackageConfig object (with `to_dict()`) id (str): ID of the package to be updated prefer (str, optional): API currently just supports asynchronous mode, not support synchronous mode, so header parameter ‘Prefer’ must be set to ‘respond-async’ in your request. Defaults to "respond-async". project_id (Optional[str]): Optional ID of a project. Defaults to None. error_msg (Optional[str]): Optional error message. Defaults to None. Returns: requests.Response: Response object containing all of the information returned by the server. """ project_id = project_id if project_id is not None else connection.project_id return connection.put(url=f'{connection.base_url}/api/packages/{id}', headers={ 'X-MSTR-ProjectID': project_id, 'Prefer': prefer }, json=body)
def delete_import(connection: Connection, id: str, project_id: Optional[str] = None, error_msg: Optional[str] = None) -> requests.Response: """Closes an existing import process previously created. Args: connection (Connection): Object representation of connection to MSTR Server. id (str): Import process ID. project_id (Optional[str]): Optional ID of a project. Defaults to None. error_msg (Optional[str]): Optional error message. Defaults to None. Returns: requests.Response: Response object containing all of the information returned by the server. """ # TODO: Change to a parameter when any other values are supported prefer = 'respond-async' project_id = project_id if project_id is not None else connection.project_id return connection.delete( url=f'{connection.base_url}/api/packages/imports/{id}', headers={ 'X-MSTR-ProjectID': project_id, 'Prefer': prefer })
def delete_package_holder( connection: Connection, id: str, project_id: Optional[str] = None, prefer: str = 'respond-async', error_msg: Optional[str] = None) -> requests.Response: """Delete the in-memory metadata package holder, releasing associated Intelligence Server resources. Args: connection (Connection): Object representation of connection to MSTR Server. id (str): ID of the package to be deleted. prefer (str, optional): API currently just supports asynchronous mode, not support synchronous mode, so header parameter ‘Prefer’ must be set to ‘respond-async’ in your request. Defaults to "respond-async". project_id (Optional[str]): Optional ID of a project. Defaults to None. error_msg (Optional[str]): Optional error message. Defaults to None. Returns: requests.Response: Response object containing all of the information returned by the server. """ project_id = project_id if project_id is not None else connection.project_id return connection.delete(url=f'{connection.base_url}/api/packages/{id}', headers={ 'X-MSTR-ProjectID': project_id, 'Prefer': prefer })
def get_package_holder(connection: Connection, id: str, project_id: Optional[str] = None, show_content: bool = True, error_msg: Optional[str] = None) -> requests.Response: """Get definition of a package, including package status and its detail content. Args: connection (Connection): Object representation of connection to MSTR Server. id (str): ID of the package to be retrieved. project_id (Optional[str]): Optional ID of a project. Defaults to None. show_content (bool, optional): Show package content or not. Defaults to False. error_msg (Optional[str]): Optional error message. Defaults to None. Returns: requests.Response: Response object containing all of the information returned by the server. """ project_id = project_id if project_id is not None else connection.project_id return connection.get(url=f'{connection.base_url}/api/packages/{id}', headers={'X-MSTR-ProjectID': project_id}, params={'showContent': show_content})
def list_all_cubes(connection: Connection, name_begins: Optional[str] = None, to_dictionary: bool = False, limit: Optional[int] = None, **filters) -> Union[List[Union["OlapCube", "SuperCube"]], List[dict]]: """Get list of Cube objects (OlapCube or SuperCube) or dicts with them. Optionally filter cubes by specifying 'name_begins'. Optionally use `to_dictionary` to choose output format. Wildcards available for 'name_begins': ? - any character * - 0 or more of any characters e.g. name_begins = ?onny will return Sonny and Tonny Args: connection: MicroStrategy connection object returned by `connection.Connection()` name_begins (string, optional): characters that the cube name must begin with to_dictionary (bool, optional): If True returns dict, by default (False) returns SuperCube/OlapCube objects limit (integer, optional): limit the number of elements returned. If None all object are returned. **filters: Available filter parameters: ['id', 'name', 'type', 'subtype', 'date_created', 'date_modified', 'version', 'owner', 'ext_type', 'view_media', 'certified_info'] Returns: list with OlapCubes and SuperCubes or list of dictionaries """ connection._validate_project_selected() objects_ = full_search(connection, project=connection.project_id, name=name_begins, object_types=[ObjectSubTypes.OLAP_CUBE, ObjectSubTypes.SUPER_CUBE], pattern=SearchPattern.BEGIN_WITH, limit=limit, **filters) if to_dictionary: return objects_ else: all_cubes = [] for object_ in objects_: cube_subtype = object_['subtype'] if cube_subtype == int(ObjectSubTypes.OLAP_CUBE): from .olap_cube import OlapCube all_cubes.append(OlapCube.from_dict(object_, connection)) elif cube_subtype == int(ObjectSubTypes.SUPER_CUBE): from .super_cube import SuperCube all_cubes.append(SuperCube.from_dict(object_, connection)) return all_cubes
def get_my_personal_objects_contents(connection: Connection, project_id: Optional[str] = None): """Get contents of My Personal Objects folder. Args: connection: MicroStrategy REST API connection object project_id (string, optional): id of project Returns: Complete HTTP response object. """ if project_id is None: connection._validate_project_selected() project_id = connection.project_id return connection.get( url=f"{connection.base_url}/api/folders/myPersonalObjects", headers={'X-MSTR-ProjectID': project_id})
def list_dossiers_across_projects(connection: Connection, name: Optional[str] = None, to_dictionary: bool = False, to_dataframe: bool = False, limit: Optional[int] = None, **filters) -> List["Dossier"]: """Get all Dossiers stored on the server. Optionally use `to_dictionary` or `to_dataframe` to choose output format. If `to_dictionary` is True, `to_dataframe` is omitted. Args: connection(object): MicroStrategy connection object returned by 'connection.Connection()' name: exact names of the dossiers to list to_dictionary(bool, optional): if True, return Dossiers as list of dicts to_dataframe(bool, optional): if True, return Dossiers as pandas DataFrame limit: limit the number of elements returned. If `None` (default), all objects are returned. **filters: Available filter parameters: ['name', 'id', 'type', 'subtype', 'date_created', 'date_modified', 'version', 'acg', 'owner', 'ext_type', 'view_media', 'certified_info', 'project_id'] Returns: List of documents. """ project_id_before = connection.project_id env = Environment(connection) projects = env.list_projects() output = [] for project in projects: connection.select_project(project_id=project.id) output.extend( Dossier._list_all(connection, to_dictionary=to_dictionary, name=name, limit=limit, to_dataframe=to_dataframe, **filters)) output = list(set(output)) connection.select_project(project_id=project_id_before) return output
def __init__(self, connection: Connection, id: str, instance_id: Optional[str] = None, parallel: bool = True, progress_bar: bool = True): """Initialize an instance of a report. Args: connection: MicroStrategy connection object returned by `connection.Connection()`. id (str): Identifier of a pre-existing report containing the required data. instance_id (str): Identifier of an instance if report instance has been already initialized, NULL by default. parallel (bool, optional): If True (default), utilize optimal number of threads to increase the download speed. If False, this feature will be disabled. progress_bar(bool, optional): If True (default), show the download progress bar. """ connection._validate_project_selected() super().__init__(connection, id, instance_id=instance_id, parallel=parallel, progress_bar=progress_bar)
def get_contact(connection: Connection, id: str, error_msg: Optional[str] = None): """Get contact by a specific id. Args: connection: MicroStrategy REST API connection object id: ID of the contact error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 200. """ url = f"{connection.base_url}/api/contacts/{id}" return connection.get(url=url)
def get_datasource_logins(connection: Connection, error_msg: Optional[str] = None): """Get information for all datasource logins. Args: connection: MicroStrategy REST API connection object error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 200. """ url = f"{connection.base_url}/api/datasources/logins" return connection.get(url=url)
def create_device(connection: Connection, body: dict, error_msg: Optional[str] = None): """Create a new device. Args: connection: MicroStrategy REST API connection object body: Device creation info. error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 201. """ url = f"{connection.base_url}/api/v2/devices/" return connection.post(url=url, json=body)
def delete_device(connection: Connection, id: str, error_msg: Optional[str] = None): """Delete a device. Args: connection: MicroStrategy REST API connection object id: ID of the device error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 204. """ url = f"{connection.base_url}/api/v2/devices/{id}" return connection.delete(url=url)
def update_device(connection: Connection, id: str, body: dict, error_msg: Optional[str] = None): """Update a device. Args: connection: MicroStrategy REST API connection object id: ID of the device body: Device update info. error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 200. """ url = f"{connection.base_url}/api/v2/devices/{id}" return connection.put(url=url, json=body)
def list_reports(connection: Connection, name_begins: Optional[str] = None, to_dictionary: bool = False, limit: Optional[int] = None, **filters) -> Union[List["Report"], List[dict]]: """Get list of Report objects or dicts with them. Optionally filter reports by specifying 'name_begins'. Optionally use `to_dictionary` to choose output format. Wildcards available for 'name_begins': ? - any character * - 0 or more of any characters e.g. name_begins = ?onny will return Sonny and Tonny Args: connection: MicroStrategy connection object returned by `connection.Connection()` name_begins (string, optional): characters that the report name must begin with to_dictionary (bool, optional): If True returns dict, by default (False) returns Report objects limit (integer, optional): limit the number of elements returned. If None all object are returned. **filters: Available filter parameters: ['id', 'name', 'type', 'subtype', 'date_created', 'date_modified', 'version', 'owner', 'ext_type', 'view_media', 'certified_info'] Returns: list with Report objects or list of dictionaries """ connection._validate_project_selected() objects_ = full_search(connection, object_types=ObjectTypes.REPORT_DEFINITION, project=connection.project_id, name=name_begins, pattern=SearchPattern.BEGIN_WITH, limit=limit, **filters) if to_dictionary: return objects_ else: return [Report.from_dict(obj_, connection) for obj_ in objects_]
def delete_datasource_mapping(connection: Connection, id: str, error_msg: Optional[str] = None): """Delete a datasource mapping based on id. Args: connection: MicroStrategy REST API connection object id (string): ID of the mapping meant to be deleted. error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 204. """ url = f"{connection.base_url}/api/datasources/mappings/{id}" return connection.delete(url=url)
def create_datasource_login(connection: Connection, body, error_msg: Optional[str] = None): """Create a new datasource login. Args: connection: MicroStrategy REST API connection object body: Datasource login creation info. error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 201. """ url = f"{connection.base_url}/api/datasources/logins" return connection.post(url=url, json=body)
def delete_folder(connection: Connection, id: str, project_id: Optional[str] = None): """Delete complete folder. Args: connection: MicroStrategy REST API connection object id (string): ID of folder project_id (string, optional): id of project Returns: Complete Future object. """ project_id = project_id if project_id is not None else connection.project_id return connection.delete(url=f"{connection.base_url}/api/folders/{id}", headers={'X-MSTR-ProjectID': project_id})
def update_datasource_login(connection: Connection, id: str, body, error_msg: Optional[str] = None): """Update a datasource login. Args: connection: MicroStrategy REST API connection object id: ID of the login body: Datasource Connection Map creation info. error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 200. """ url = f"{connection.base_url}/api/datasources/logins/{id}" return connection.patch(url=url, json=body)
def get_devices(connection: Connection, device_type: Optional[str] = None, fields: Optional[str] = None, error_msg: Optional[str] = None): """Get information for all devices. Args: connection: MicroStrategy REST API connection object fields(list, optional): Comma separated top-level field whitelist. This allows client to selectively retrieve part of the response model. device_type (str, optional): Device type, Supported values are: email, file, ftp, printer, ipad, iphone, android, all. error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 200. """ url = f"{connection.base_url}/api/v2/devices/" params = {'fields': fields, 'deviceType': device_type} return connection.get(url=url, params=params)
def list_dependents_example(): # Insert valid credentials username = '******' base_url = 'https://env-******.customer.cloud.microstrategy.com/MicroStrategyLibrary' password = '******' project_name = 'MicroStrategy Tutorial' # Just example project_id = 'B7CA92F04B9FAE8D941C3E9B7E0CD754' # Just example metric_id = '08F9966749975B5C1A4980A3FA8CE3E7' # Just example report_id = 'CAEA8BC44296BB6A89849FBD1161703B' # Just example connection = Connection(base_url, username, password, project_name=project_name) # List dependents of a metric metric_dependents = list_dependents_of_metric(connection, project_id, metric_id) # or List dependents of a metric using more capabilities of `full_search()` object_dependents = full_search(connection, project_id, uses_object_id=metric_id, uses_object_type=ObjectTypes.METRIC, name='Graph', pattern=SearchPattern.CONTAINS, results_format=SearchResultsFormat.LIST, to_dictionary=False) # It is also possible to list dependencies of a metric metric_dependencies = full_search(connection, project_id, used_by_object_id=metric_id, used_by_object_type=ObjectTypes.METRIC, results_format=SearchResultsFormat.TREE) # Other objects, that already have dedicated class, can use premade methods report = Report(connection, report_id) rep_dependents = report.list_dependents() rep_dependencies = report.list_dependencies(to_dictionary=False) return (metric_dependents, object_dependents, metric_dependencies, rep_dependents, rep_dependencies)
def create_package_holder( connection: Connection, project_id: Optional[str] = None, error_msg: Optional[str] = None) -> requests.Response: """Create a new in-memory metadata package holder. Args: connection (Connection): Object representation of connection to MSTR Server. project_id (Optional[str]): Optional ID of a project. Defaults to None. error_msg (Optional[str]): Optional error message. Defaults to None. Returns: requests.Response: Response object containing all of the information returned by the server. """ project_id = project_id if project_id is not None else connection.project_id return connection.post(url=f'{connection.base_url}/api/packages', headers={'X-MSTR-ProjectID': project_id})
def get_datasource_mapping(connection: Connection, id=str, default_connection_map: Optional[bool] = False, project_id: Optional[str] = None, error_msg: Optional[str] = None): """Get information about specific datasource_mapping. Args: connection: MicroStrategy REST API connection object id: ID of the mapping default_connection_map (bool, optional): If True will get the default connection map for a project. Requires `project_id` parameter. Default False. project_id: The project_id, required only for default connection map. error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 200. """ url = f"{connection.base_url}/api/datasources/mappings" response = connection.get(url=url, params={ "defaultConnectionMap": default_connection_map, "projectId": project_id }) # Faking get single resource endpoint. Only 'list all' available on REST if response.ok: response_json = response.json() if 'mappings' in response_json.keys(): mappings = [ mapping for mapping in response_json['mappings'] if mapping["id"] == id ] if len(mappings) > 0: response_json = mappings[0] response_json['ds_connection'] = response_json.pop( 'connection') response.encoding, response._content = 'utf-8', json.dumps( response_json).encode('utf-8') return response
def download_package(connection: Connection, id: str, project_id: Optional[str] = None, error_msg: Optional[str] = None) -> requests.Response: """Download a package binary. Args: connection (Connection): Object representation of connection to MSTR Server. id (str): ID of the package to be downloaded. project_id (Optional[str]): Optional ID of a project. Defaults to None. error_msg (Optional[str]): Optional error message. Defaults to None. Returns: requests.Response: Response object containing all of the information returned by the server. """ project_id = project_id if project_id is not None else connection.project_id return connection.get( url=f'{connection.base_url}/api/packages/{id}/binary', headers={'X-MSTR-ProjectID': project_id})
def get_contacts(connection: Connection, offset: int = 0, limit: int = -1, fields: Optional[str] = None, error_msg: Optional[str] = None): """Get information for all contacts. Args: connection: MicroStrategy REST API connection object fields(list, optional): Comma separated top-level field whitelist. This allows client to selectively retrieve part of the response model. offset (integer, optional): Starting point within the collection of returned search results. Used to control paging behavior. limit (integer, optional): Maximum number of items returned for a single search request. Used to control paging behavior. Use -1 for no limit (subject to governing settings). error_msg (string, optional): Custom Error Message for Error Handling Returns: Complete HTTP response object. Expected status is 200. """ url = f"{connection.base_url}/api/contacts/" params = {'fields': fields, 'offset': offset, 'limit': limit} return connection.get(url=url, params=params)