def list_users(self): """Get a list of user(s) involved in a project.""" # Get user list from API try: response = requests.get( DDSEndpoint.LIST_PROJ_USERS, headers=self.token, params={"project": self.project}, timeout=DDSEndpoint.TIMEOUT, ) except requests.exceptions.RequestException as err: raise exceptions.ApiRequestError( message=( "Failed to get list of users" + ( ": The database seems to be down." if isinstance(err, requests.exceptions.ConnectionError) else "." ) ) ) # Check resposne if not response.ok: raise exceptions.APIError(f"Failed to get any users: {response.text}") # Get result from API try: resp_json = response.json() except simplejson.JSONDecodeError as err: raise exceptions.APIError(f"Could not decode JSON response: {err}") research_users = resp_json.get("research_users") # Print users if not self.json: self.__print_users_table(research_users) return research_users
def update_status(self, new_status, deadline=None, is_aborted=False, no_mail=False): """Update project status""" extra_params = {"new_status": new_status, "send_email": not no_mail} if deadline: extra_params["deadline"] = deadline if is_aborted: extra_params["is_aborted"] = is_aborted try: response = requests.post( DDSEndpoint.UPDATE_PROJ_STATUS, headers=self.token, params={"project": self.project}, json=extra_params, timeout=DDSEndpoint.TIMEOUT, ) except requests.exceptions.RequestException as err: raise exceptions.ApiRequestError( message=( "Failed to update project status" + ( ": The database seems to be down." if isinstance(err, requests.exceptions.ConnectionError) else "." ) ) ) # Check response if not response.ok: raise exceptions.APIError(f"An Error occured: {response.json().get('message')}") # Get result from API try: resp_json = response.json() except simplejson.JSONDecodeError as err: raise exceptions.APIError(f"Could not decode JSON response: {err}") else: dds_cli.utils.console.print(f"Project {resp_json.get('message')}")
def __api_call_list_files(folder: str): # Make call to API try: resp_json = requests.get( DDSEndpoint.LIST_FILES, params={"project": self.project}, json={"subpath": folder, "show_size": show_size}, headers=self.token, timeout=DDSEndpoint.TIMEOUT, ) except requests.exceptions.RequestException as err: raise exceptions.APIError(f"Problem with database response: '{err}'") resp_json = resp_json.json() if not "files_folders" in resp_json: raise exceptions.NoDataError(f"Could not find folder: '{folder}'") sorted_files_folders = sorted(resp_json["files_folders"], key=lambda f: f["name"]) if not sorted_files_folders: raise exceptions.NoDataError(f"Could not find folder: '{folder}'") return sorted_files_folders
def list_projects(self, sort_by="Updated"): """Get a list of project(s) the user is involved in.""" # Get projects from API try: response = requests.get( DDSEndpoint.LIST_PROJ, headers=self.token, json={"usage": self.show_usage}, timeout=DDSEndpoint.TIMEOUT, ) except requests.exceptions.RequestException as err: raise exceptions.ApiRequestError( message=( "Failed to get list of projects" + ( ": The database seems to be down." if isinstance(err, requests.exceptions.ConnectionError) else "." ) ) ) # Check response if not response.ok: raise exceptions.APIError(f"Failed to get any projects: {response.text}") # Get result from API try: resp_json = response.json() except simplejson.JSONDecodeError as err: raise exceptions.APIError(f"Could not decode JSON response: {err}") # Cancel if user not involved in any projects usage_info = resp_json.get("total_usage") total_size = resp_json.get("total_size") project_info = resp_json.get("project_info") always_show = resp_json.get("always_show", False) if not project_info: raise exceptions.NoDataError("No project info was retrieved. No files to list.") for project in project_info: try: last_updated = pytz.timezone("UTC").localize( datetime.datetime.strptime(project["Last updated"], "%a, %d %b %Y %H:%M:%S GMT") ) except ValueError as err: raise exceptions.ApiResponseError( f"Time zone mismatch: Incorrect zone '{project['Last updated'].split()[-1]}'" ) else: project["Last updated"] = last_updated.astimezone(tzlocal.get_localzone()).strftime( "%a, %d %b %Y %H:%M:%S %Z" ) # Sort projects according to chosen or default, first ID sorted_projects = self.__sort_projects(projects=project_info, sort_by=sort_by) if not self.json: self.__print_project_table(sorted_projects, usage_info, total_size, always_show) # Return the list of projects return sorted_projects
def list_files(self, folder: str = None, show_size: bool = False): """Create a tree displaying the files within the project.""" LOG.info(f"Listing files for project '{self.project}'") if folder: LOG.info(f"Showing files in folder '{escape(folder)}'") if folder is None: folder = "" # Make call to API try: response = requests.get( DDSEndpoint.LIST_FILES, params={"project": self.project}, json={"subpath": folder, "show_size": show_size}, headers=self.token, timeout=DDSEndpoint.TIMEOUT, ) except requests.exceptions.RequestException as err: raise exceptions.APIError( message=( f"Failed to get list of files in project '{self.project}'" + ( ": The database seems to be down." if isinstance(err, requests.exceptions.ConnectionError) else "." ) ) ) if not response.ok: raise exceptions.APIError(f"Failed to get list of files: '{response.text}'") # Get response try: resp_json = response.json() except simplejson.JSONDecodeError as err: raise exceptions.APIError(f"Could not decode JSON response: '{err}'") # Check if project empty if "num_items" in resp_json and resp_json["num_items"] == 0: raise exceptions.NoDataError(f"Project '{self.project}' is empty.") # Get files files_folders = resp_json["files_folders"] # Sort the file/folders according to names sorted_files_folders = sorted(files_folders, key=lambda f: f["name"]) # Create tree tree_title = escape(folder) or f"Files / directories in project: [green]{self.project}" tree = Tree(f"[bold magenta]{tree_title}") if not sorted_files_folders: raise exceptions.NoDataError(f"Could not find folder: '{escape(folder)}'") # Get max length of file name max_string = max([len(x["name"]) for x in sorted_files_folders]) # Get max length of size string max_size = max( [ len( dds_cli.utils.format_api_response( response=x["size"], key="Size", binary=self.binary ).split(" ", maxsplit=1)[0] ) for x in sorted_files_folders if show_size and "size" in x ], default=0, ) # Visible folders visible_folders = [] # Add items to tree for x in sorted_files_folders: # Check if string is folder is_folder = x.pop("folder") # Att 1 for folders due to trailing / tab = th.TextHandler.format_tabs( string_len=len(x["name"]) + (1 if is_folder else 0), max_string_len=max_string, ) # Add formatting if folder and set string name line = "" if is_folder: line = "[bold deep_sky_blue3]" visible_folders.append(x["name"]) line += escape(x["name"]) + ("/" if is_folder else "") # Add size to line if option specified if show_size and "size" in x: size = dds_cli.utils.format_api_response( response=x["size"], key="Size", binary=self.binary ) line += f"{tab}{size.split()[0]}" # Define space between number and size format tabs_bf_format = th.TextHandler.format_tabs( string_len=len(size), max_string_len=max_size, tab_len=2 ) line += f"{tabs_bf_format}{size.split()[1]}" tree.add(line) # Print output to stdout if len(files_folders) + 5 > dds_cli.utils.console.height: with dds_cli.utils.console.pager(): dds_cli.utils.console.print(Padding(tree, 1)) else: dds_cli.utils.console.print(Padding(tree, 1)) # Return variable return visible_folders
def get_status(self, show_history): """Get current status and status history of the project.""" try: response = requests.get( DDSEndpoint.UPDATE_PROJ_STATUS, headers=self.token, params={"project": self.project}, json={"history": show_history}, timeout=DDSEndpoint.TIMEOUT, ) except requests.exceptions.RequestException as err: raise exceptions.ApiRequestError( message=( "Failed to get project status" + ( ": The database seems to be down." if isinstance(err, requests.exceptions.ConnectionError) else "." ) ) ) # Check response if not response.ok: raise exceptions.APIError(f"Failed to get any projects: {response.text}") # Get result from API try: resp_json = response.json() except simplejson.JSONDecodeError as err: raise exceptions.APIError(f"Could not decode JSON response: {err}") else: current_status = resp_json.get("current_status") current_deadline = resp_json.get("current_deadline") status_out = f"Current status of {self.project}: {current_status}" deadline_out = "" if current_deadline: try: date = pytz.timezone("UTC").localize( datetime.datetime.strptime(current_deadline, "%a, %d %b %Y %H:%M:%S GMT") ) except ValueError as err: raise exceptions.ApiResponseError( f"Time zone mismatch: Incorrect zone '{current_deadline.split()[-1]}'" ) else: current_deadline = date.astimezone(tzlocal.get_localzone()).strftime( "%a, %d %b %Y %H:%M:%S %Z" ) deadline_out = f" with deadline {current_deadline}" dds_cli.utils.console.print(f"{status_out}{deadline_out}") if show_history: history = "Status history \n" for row in resp_json.get("history"): try: date = pytz.timezone("UTC").localize( datetime.datetime.strptime(row[1], "%a, %d %b %Y %H:%M:%S GMT") ) except ValueError as err: raise exceptions.ApiResponseError( f"Time zone mismatch: Incorrect zone '{row[1].split()[-1]}'" ) else: row[1] = date.astimezone(tzlocal.get_localzone()).strftime( "%a, %d %b %Y %H:%M:%S %Z" ) history += ", ".join(list(row)) + " \n" LOG.info(history)