diff --git a/gazu/entity.py b/gazu/entity.py index 20c35a7..2f23f04 100644 --- a/gazu/entity.py +++ b/gazu/entity.py @@ -114,6 +114,18 @@ def new_entity_type(name, client=default): return raw.create("entity-types", data, client=client) +def remove_entity_type(entity_type, client=default): + """ + Remove given entity type from database. + + Args: + entity_type (dict / str): Entity type to remove. + """ + entity_type = normalize_model_parameter(entity_type) + path = "data/entity-types/%s" % entity_type["id"] + return raw.delete(path, client=client) + + def remove_entity(entity, force=False, client=default): """ Remove given entity from database. diff --git a/gazu/events.py b/gazu/events.py index 1e8d002..13592e6 100644 --- a/gazu/events.py +++ b/gazu/events.py @@ -60,7 +60,7 @@ def init( params.update(kwargs) event_client = socketio.Client(**params) event_client.on("connect_error", connect_error) - event_client.register_namespace(EventsNamespace("/")) + event_client.register_namespace(EventsNamespace("/events")) event_client.connect(get_event_host(client), make_auth_header()) return event_client diff --git a/gazu/person.py b/gazu/person.py index 1dc3bfe..873d3c4 100644 --- a/gazu/person.py +++ b/gazu/person.py @@ -446,3 +446,211 @@ def invite_person(person, client=default): "actions/persons/%s/invite" % (person["id"]), client=client, ) + + +@cache +def get_time_spents_by_date(person, date, client=default): + """ + Get time spents for a person on a specific date. + + Args: + person (dict / ID): The person dict or id. + date (str): Date in YYYY-MM-DD format. + + Returns: + list: Time spents for the date. + """ + person = normalize_model_parameter(person) + return raw.get( + "data/persons/%s/time-spents/by-date" % person["id"], + params={"date": date}, + client=client, + ) + + +@cache +def get_week_time_spents(person, year, week, client=default): + """ + Get time spents for a person for a specific week. + + Args: + person (dict / ID): The person dict or id. + year (int): Year. + week (int): Week number. + + Returns: + list: Time spents for the week. + """ + person = normalize_model_parameter(person) + return raw.get( + "data/persons/%s/time-spents/week/%s/%s" % (person["id"], year, week), + client=client, + ) + + +@cache +def get_year_time_spents(person, year, client=default): + """ + Get time spents for a person for a specific year. + + Args: + person (dict / ID): The person dict or id. + year (int): Year. + + Returns: + list: Time spents for the year. + """ + person = normalize_model_parameter(person) + return raw.get( + "data/persons/%s/time-spents/year/%s" % (person["id"], year), + client=client, + ) + + +@cache +def get_day_offs(person, client=default): + """ + Get day offs for a person. + + Args: + person (dict / ID): The person dict or id. + + Returns: + list: Day offs for the person. + """ + person = normalize_model_parameter(person) + return raw.fetch_all( + "persons/%s/day-offs" % person["id"], client=client + ) + + +@cache +def get_week_day_offs(person, year, week, client=default): + """ + Get day offs for a person for a specific week. + + Args: + person (dict / ID): The person dict or id. + year (int): Year. + week (int): Week number. + + Returns: + list: Day offs for the week. + """ + person = normalize_model_parameter(person) + return raw.get( + "data/persons/%s/day-offs/week/%s/%s" % (person["id"], year, week), + client=client, + ) + + +@cache +def get_month_day_offs(person, year, month, client=default): + """ + Get day offs for a person for a specific month. + + Args: + person (dict / ID): The person dict or id. + year (int): Year. + month (int): Month number. + + Returns: + list: Day offs for the month. + """ + person = normalize_model_parameter(person) + return raw.get( + "data/persons/%s/day-offs/month/%s/%s" + % (person["id"], year, str(month).zfill(2)), + client=client, + ) + + +@cache +def get_year_day_offs(person, year, client=default): + """ + Get day offs for a person for a specific year. + + Args: + person (dict / ID): The person dict or id. + year (int): Year. + + Returns: + list: Day offs for the year. + """ + person = normalize_model_parameter(person) + return raw.get( + "data/persons/%s/day-offs/year/%s" % (person["id"], year), + client=client, + ) + + +def add_person_to_department(person, department, client=default): + """ + Add a person to a department. + + Args: + person (dict / ID): The person dict or id. + department (dict / ID): The department dict or id. + + Returns: + dict: Response information. + """ + person = normalize_model_parameter(person) + department = normalize_model_parameter(department) + return raw.post( + "data/persons/%s/departments" % person["id"], + {"department_id": department["id"]}, + client=client, + ) + + +def remove_person_from_department(person, department, client=default): + """ + Remove a person from a department. + + Args: + person (dict / ID): The person dict or id. + department (dict / ID): The department dict or id. + + Returns: + Response: Request response object. + """ + person = normalize_model_parameter(person) + department = normalize_model_parameter(department) + return raw.delete( + "data/persons/%s/departments/%s" % (person["id"], department["id"]), + client=client, + ) + + +def disable_two_factor_authentication(person, client=default): + """ + Disable two factor authentication for a person. + + Args: + person (dict / ID): The person dict or id. + + Returns: + Response: Request response object. + """ + person = normalize_model_parameter(person) + return raw.delete( + "data/persons/%s/two-factor-authentication" % person["id"], + client=client, + ) + + +def clear_person_avatar(person, client=default): + """ + Clear avatar for a person. + + Args: + person (dict / ID): The person dict or id. + + Returns: + Response: Request response object. + """ + person = normalize_model_parameter(person) + return raw.delete( + "data/persons/%s/avatar" % person["id"], client=client + ) diff --git a/gazu/playlist.py b/gazu/playlist.py index 03ae0cb..edd1e02 100644 --- a/gazu/playlist.py +++ b/gazu/playlist.py @@ -253,3 +253,169 @@ def update_entity_preview( if persist: update_playlist(playlist, client=client) return playlist + + +@cache +def delete_playlist(playlist, client=default): + """ + Delete a playlist. + + Args: + playlist (dict / ID): The playlist dict or id. + + Returns: + Response: Request response object. + """ + playlist = normalize_model_parameter(playlist) + return raw.delete("data/playlists/%s" % playlist["id"], client=client) + + +@cache +def get_entity_previews(playlist, client=default): + """ + Get entity previews for a playlist. + + Args: + playlist (dict / ID): The playlist dict or id. + + Returns: + list: Entity previews for the playlist. + """ + playlist = normalize_model_parameter(playlist) + return raw.fetch_all( + "playlists/%s/entity-previews" % playlist["id"], client=client + ) + + +@cache +def get_build_job(build_job, client=default): + """ + Get a build job. + + Args: + build_job (dict / ID): The build job dict or id. + + Returns: + dict: Build job information. + """ + build_job = normalize_model_parameter(build_job) + return raw.fetch_one("playlists/build-jobs", build_job["id"], client=client) + + +def remove_build_job(build_job, client=default): + """ + Delete a build job. + + Args: + build_job (dict / ID): The build job dict or id. + + Returns: + Response: Request response object. + """ + build_job = normalize_model_parameter(build_job) + return raw.delete( + "data/playlists/build-jobs/%s" % build_job["id"], client=client + ) + + +@cache +def all_build_jobs_for_project(project, client=default): + """ + Get all build jobs for a project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + list: All build jobs for the project. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/build-jobs" % project["id"], client=client + ) + + +def build_playlist_movie(playlist, client=default): + """ + Build a movie for a playlist. + + Args: + playlist (dict / ID): The playlist dict or id. + + Returns: + dict: Build job information. + """ + playlist = normalize_model_parameter(playlist) + return raw.post( + "data/playlists/%s/build-movie" % playlist["id"], {}, client=client + ) + + +def download_playlist_build(playlist, build_job, file_path, client=default): + """ + Download a playlist build. + + Args: + playlist (dict / ID): The playlist dict or id. + build_job (dict / ID): The build job dict or id. + file_path (str): The location to store the file on the hard drive. + + Returns: + Response: Request response object. + """ + playlist = normalize_model_parameter(playlist) + build_job = normalize_model_parameter(build_job) + path = "data/playlists/%s/build-jobs/%s/download" % ( + playlist["id"], + build_job["id"], + ) + return raw.download(path, file_path, client=client) + + +def download_playlist_zip(playlist, file_path, client=default): + """ + Download a playlist as a zip file. + + Args: + playlist (dict / ID): The playlist dict or id. + file_path (str): The location to store the file on the hard drive. + + Returns: + Response: Request response object. + """ + playlist = normalize_model_parameter(playlist) + path = "data/playlists/%s/download/zip" % playlist["id"] + return raw.download(path, file_path, client=client) + + +def generate_temp_playlist(project, data, client=default): + """ + Generate a temporary playlist. + + Args: + project (dict / ID): The project dict or id. + data (dict): Playlist generation data. + + Returns: + dict: Generated temporary playlist. + """ + project = normalize_model_parameter(project) + return raw.post( + "data/projects/%s/playlists/temp" % project["id"], data, client=client + ) + + +def notify_clients_playlist_ready(playlist, client=default): + """ + Notify clients that a playlist is ready. + + Args: + playlist (dict / ID): The playlist dict or id. + + Returns: + dict: Notification response. + """ + playlist = normalize_model_parameter(playlist) + return raw.post( + "data/playlists/%s/notify" % playlist["id"], {}, client=client + ) diff --git a/gazu/project.py b/gazu/project.py index 110faf5..441b2c8 100644 --- a/gazu/project.py +++ b/gazu/project.py @@ -446,3 +446,408 @@ def remove_person_from_team(project, person, client=default): "data/projects/%s/team/%s" % (project["id"], person["id"]), client=client, ) + + +@cache +def get_project_task_types(project, client=default): + """ + Get task types configured for a project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + list: The task types. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/settings/task-types" % project["id"], client=client + ) + + +@cache +def get_project_task_statuses(project, client=default): + """ + Get task statuses configured for a project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + list: The task statuses. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/settings/task-status" % project["id"], client=client + ) + + +@cache +def all_status_automations(project, client=default): + """ + Get status automations configured for a project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + list: The status automations. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/settings/status-automations" % project["id"], + client=client, + ) + + +def add_status_automation(project, automation, client=default): + """ + Add a status automation to the project. + + Args: + project (dict / ID): The project dict or id. + automation (dict): The automation payload (e.g. from/to status, task_type, rules). + """ + project = normalize_model_parameter(project) + return raw.post( + "data/projects/%s/settings/status-automations" % project["id"], + automation, + client=client, + ) + + +def remove_status_automation(project, automation, client=default): + """ + Remove a status automation from the project. + + Args: + project (dict / ID): The project dict or id. + automation (dict / ID): The automation dict or id. + """ + project = normalize_model_parameter(project) + automation = normalize_model_parameter(automation) + return raw.delete( + "data/projects/%s/settings/status-automations/%s" + % (project["id"], automation["id"]), + client=client, + ) + + +@cache +def get_preview_background_files(project, client=default): + """ + Get preview background files configured for a project. + + Args: + project (dict / ID): The project dict or id. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/preview-background-files" % project["id"], client=client + ) + + +def add_preview_background_file(project, background_file, client=default): + """ + Add a preview background file to a project. + + Args: + project (dict / ID): The project dict or id. + background_file (dict): Payload describing the background file to add. + """ + project = normalize_model_parameter(project) + return raw.post( + "data/projects/%s/preview-background-files" % project["id"], + background_file, + client=client, + ) + + +def remove_preview_background_file(project, background_file, client=default): + """ + Remove a preview background file from a project. + + Args: + project (dict / ID): The project dict or id. + background_file (dict / ID): The background file dict or id. + """ + project = normalize_model_parameter(project) + background_file = normalize_model_parameter(background_file) + return raw.delete( + "data/projects/%s/preview-background-files/%s" + % (project["id"], background_file["id"]), + client=client, + ) + + +@cache +def get_milestones(project, client=default): + """ + Get production milestones for a project. + + Args: + project (dict / ID): The project dict or id. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/milestones" % project["id"], client=client + ) + + +@cache +def get_project_quotas(project, client=default): + """ + Get quotas for a project. + + Args: + project (dict / ID): The project dict or id. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/quotas" % project["id"], client=client + ) + + +@cache +def get_project_person_quotas(project, person, client=default): + """ + Get quotas for a person within a project. + + Args: + project (dict / ID): The project dict or id. + person (dict / ID): The person dict or id. + """ + project = normalize_model_parameter(project) + person = normalize_model_parameter(person) + return raw.fetch_all( + "projects/%s/person-quotas" % project["id"], + params={"person_id": person["id"]}, + client=client, + ) + + +@cache +def get_budgets(project, client=default): + """ + Get budgets for a project. + + Args: + project (dict / ID): The project dict or id. + """ + project = normalize_model_parameter(project) + return raw.fetch_all("projects/%s/budgets" % project["id"], client=client) + + +def create_budget( + project, + name, + description=None, + currency=None, + start_date=None, + end_date=None, + amount=None, + client=default, +): + """ + Create a budget for a project. + + Args: + project (dict / ID): The project dict or id. + name (str): Budget name. Required. + description (str, optional): Human description. + currency (str, optional): Currency code (e.g. "USD", "EUR"). + start_date (str, optional): Start date ISO format (YYYY-MM-DD). + end_date (str, optional): End date ISO format (YYYY-MM-DD). + amount (number, optional): Overall budget amount. + """ + project = normalize_model_parameter(project) + data = {"name": name} + if description is not None: + data["description"] = description + if currency is not None: + data["currency"] = currency + if start_date is not None: + data["start_date"] = start_date + if end_date is not None: + data["end_date"] = end_date + if amount is not None: + data["amount"] = amount + return raw.post( + "data/projects/%s/budgets" % project["id"], data, client=client + ) + + +@cache +def get_budget(project, budget, client=default): + """ + Get a specific budget. + + Args: + project (dict / ID): The project dict or id. + budget (dict / ID): The budget dict or id. + """ + project = normalize_model_parameter(project) + budget = normalize_model_parameter(budget) + return raw.fetch_one( + "projects/%s/budgets" % project["id"], budget["id"], client=client + ) + + +def update_budget(project, budget, data, client=default): + """ + Update a specific budget. + + Args: + project (dict / ID): The project dict or id. + budget (dict / ID): The budget dict or id. + data (dict): The updated budget payload. + """ + project = normalize_model_parameter(project) + budget = normalize_model_parameter(budget) + return raw.put( + "data/projects/%s/budgets/%s" % (project["id"], budget["id"]), + data, + client=client, + ) + + +def remove_budget(project, budget, client=default): + """ + Delete a specific budget. + + Args: + project (dict / ID): The project dict or id. + budget (dict / ID): The budget dict or id. + """ + project = normalize_model_parameter(project) + budget = normalize_model_parameter(budget) + return raw.delete( + "data/projects/%s/budgets/%s" % (project["id"], budget["id"]), + client=client, + ) + + +@cache +def get_budget_entries(project, budget, client=default): + """ + Get entries for a specific budget. + + Args: + project (dict / ID): The project dict or id. + budget (dict / ID): The budget dict or id. + """ + project = normalize_model_parameter(project) + budget = normalize_model_parameter(budget) + return raw.fetch_all( + "projects/%s/budgets/%s/entries" % (project["id"], budget["id"]), + client=client, + ) + + +def create_budget_entry( + project, + budget, + name, + date=None, + amount=None, + quantity=None, + unit_price=None, + description=None, + category=None, + client=default, +): + """ + Create a budget entry for a specific budget. + + Args: + project (dict / ID): The project dict or id. + budget (dict / ID): The budget dict or id. + name (str): Entry name. Required. + date (str, optional): Entry date in ISO format (YYYY-MM-DD). + amount (number, optional): Total amount for the entry. + quantity (number, optional): Quantity used to compute amount. + unit_price (number, optional): Unit price used with quantity. + description (str, optional): Human description for the entry. + category (str, optional): Category label for the entry. + """ + project = normalize_model_parameter(project) + budget = normalize_model_parameter(budget) + data = {"name": name} + if date is not None: + data["date"] = date + if amount is not None: + data["amount"] = amount + if quantity is not None: + data["quantity"] = quantity + if unit_price is not None: + data["unit_price"] = unit_price + if description is not None: + data["description"] = description + if category is not None: + data["category"] = category + return raw.post( + "data/projects/%s/budgets/%s/entries" + % (project["id"], budget["id"]), + data, + client=client, + ) + + +@cache +def get_budget_entry(project, budget, entry, client=default): + """ + Get a specific budget entry. + + Args: + project (dict / ID): The project dict or id. + budget (dict / ID): The budget dict or id. + entry (dict / ID): The budget entry dict or id. + """ + project = normalize_model_parameter(project) + budget = normalize_model_parameter(budget) + entry = normalize_model_parameter(entry) + return raw.fetch_one( + "projects/%s/budgets/%s/entries" % (project["id"], budget["id"]), + entry["id"], + client=client, + ) + + +def update_budget_entry(project, budget, entry, data, client=default): + """ + Update a specific budget entry. + + Args: + project (dict / ID): The project dict or id. + budget (dict / ID): The budget dict or id. + entry (dict / ID): The budget entry dict or id. + data (dict): The updated budget entry payload. + """ + project = normalize_model_parameter(project) + budget = normalize_model_parameter(budget) + entry = normalize_model_parameter(entry) + return raw.put( + "data/projects/%s/budgets/%s/entries/%s" + % (project["id"], budget["id"], entry["id"]), + data, + client=client, + ) + + +def remove_budget_entry(project, budget, entry, client=default): + """ + Delete a specific budget entry. + + Args: + project (dict / ID): The project dict or id. + budget (dict / ID): The budget dict or id. + entry (dict / ID): The budget entry dict or id. + """ + project = normalize_model_parameter(project) + budget = normalize_model_parameter(budget) + entry = normalize_model_parameter(entry) + return raw.delete( + "data/projects/%s/budgets/%s/entries/%s" + % (project["id"], budget["id"], entry["id"]), + client=client, + ) diff --git a/gazu/task.py b/gazu/task.py index f08f22e..2a69fbd 100644 --- a/gazu/task.py +++ b/gazu/task.py @@ -429,15 +429,6 @@ def get_task_by_entity(entity, task_type, name="main", client=default): ) -@deprecated( - version="0.9.17", - reason="You should use another function: gazu.task.get_task_by_entity, it will be removed in a future version of Gazu (0.10.0).", -) -@cache -def get_task_by_name(entity, task_type, name="main", client=default): - return get_task_by_entity(entity, task_type, name=name, client=client) - - @cache def get_task_type(task_type_id, client=default): """ @@ -1345,3 +1336,406 @@ def update_comment(comment, client=default): dict: Updated comment. """ return raw.put("data/comments/%s" % comment["id"], comment, client=client) + + +@cache +def all_open_tasks(client=default): + """ + Get all open tasks. + + Returns: + list: Open tasks. + """ + return raw.fetch_all("tasks/open", client=client) + + +@cache +def get_open_tasks_stats(client=default): + """ + Get statistics for open tasks. + + Returns: + dict: Open tasks statistics. + """ + return raw.get("data/tasks/open/stats", client=client) + + +@cache +def all_previews_for_task(task, client=default): + """ + Get all previews for a task. + + Args: + task (dict / ID): The task dict or id. + + Returns: + list: Previews for the task. + """ + task = normalize_model_parameter(task) + return raw.fetch_all("tasks/%s/previews" % task["id"], client=client) + + +@cache +def all_open_tasks_for_person(person, client=default): + """ + Get all open tasks for a person. + + Args: + person (dict / ID): The person dict or id. + + Returns: + list: Open tasks for the person. + """ + person = normalize_model_parameter(person) + return raw.fetch_all("persons/%s/tasks/open" % person["id"], client=client) + + +@cache +def all_tasks_for_person_and_type(person, task_type, client=default): + """ + Get all tasks for a person and task type. + + Args: + person (dict / ID): The person dict or id. + task_type (dict / ID): The task type dict or id. + + Returns: + list: Tasks for the person and task type. + """ + person = normalize_model_parameter(person) + task_type = normalize_model_parameter(task_type) + return raw.fetch_all( + "persons/%s/task-types/%s/tasks" % (person["id"], task_type["id"]), + client=client, + ) + + +@cache +def all_comments_for_project(project, client=default): + """ + Get all comments for a project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + list: Comments for the project. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/comments" % project["id"], client=client + ) + + +@cache +def all_notifications_for_project(project, client=default): + """ + Get all notifications for a project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + list: Notifications for the project. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/notifications" % project["id"], client=client + ) + + +@cache +def all_preview_files_for_project(project, client=default): + """ + Get all preview files for a project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + list: Preview files for the project. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/preview-files" % project["id"], client=client + ) + + +@cache +def all_subscriptions_for_project(project, client=default): + """ + Get all subscriptions for a project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + list: Subscriptions for the project. + """ + project = normalize_model_parameter(project) + return raw.fetch_all( + "projects/%s/subscriptions" % project["id"], client=client + ) + + +@cache +def get_persons_tasks_dates(project, client=default): + """ + Get tasks dates for persons in a project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + dict: Tasks dates for persons. + """ + project = normalize_model_parameter(project) + return raw.get( + "data/projects/%s/persons/tasks/dates" % project["id"], client=client + ) + + +def remove_tasks_for_type(project, task_type, client=default): + """ + Delete all tasks for a task type in a project. + + Args: + project (dict / ID): The project dict or id. + task_type (dict / ID): The task type dict or id. + + Returns: + Response: Request response object. + """ + project = normalize_model_parameter(project) + task_type = normalize_model_parameter(task_type) + return raw.delete( + "data/projects/%s/task-types/%s/tasks" + % (project["id"], task_type["id"]), + client=client, + ) + + +def remove_tasks_batch(tasks, client=default): + """ + Delete multiple tasks in batch. + + Args: + tasks (list): List of task dicts or IDs to delete. + + Returns: + Response: Request response object. + """ + task_ids = [ + normalize_model_parameter(task)["id"] for task in tasks + ] + return raw.post( + "data/tasks/delete-batch", {"task_ids": task_ids}, client=client + ) + + +def assign_tasks_to_person(tasks, person, client=default): + """ + Assign multiple tasks to a person. + + Args: + tasks (list): List of task dicts or IDs. + person (dict / ID): The person dict or id. + + Returns: + dict: Response information. + """ + person = normalize_model_parameter(person) + task_ids = [ + normalize_model_parameter(task)["id"] for task in tasks + ] + return raw.put( + "data/tasks/assign", + {"person_id": person["id"], "task_ids": task_ids}, + client=client, + ) + + +@cache +def get_task_time_spent_for_date(task, date, client=default): + """ + Get time spent for a task on a specific date. + + Args: + task (dict / ID): The task dict or id. + date (str): Date in YYYY-MM-DD format. + + Returns: + dict: Time spent information. + """ + task = normalize_model_parameter(task) + return raw.get( + "data/tasks/%s/time-spent/for-date" % task["id"], + params={"date": date}, + client=client, + ) + + +def remove_time_spent(time_spent, client=default): + """ + Delete a time spent entry. + + Args: + time_spent (dict / ID): The time spent dict or id. + + Returns: + Response: Request response object. + """ + time_spent = normalize_model_parameter(time_spent) + return raw.delete( + "data/time-spents/%s" % time_spent["id"], client=client + ) + + +def add_preview_to_comment(comment, preview_file, client=default): + """ + Add a preview to a comment. + + Args: + comment (dict / ID): The comment dict or id. + preview_file (dict / ID): The preview file dict or id. + + Returns: + dict: Updated comment. + """ + comment = normalize_model_parameter(comment) + preview_file = normalize_model_parameter(preview_file) + return raw.post( + "data/comments/%s/preview-files" % comment["id"], + {"preview_file_id": preview_file["id"]}, + client=client, + ) + + +def remove_preview_from_comment(comment, preview_file, client=default): + """ + Remove a preview from a comment. + + Args: + comment (dict / ID): The comment dict or id. + preview_file (dict / ID): The preview file dict or id. + + Returns: + Response: Request response object. + """ + comment = normalize_model_parameter(comment) + preview_file = normalize_model_parameter(preview_file) + return raw.delete( + "data/comments/%s/preview-files/%s" + % (comment["id"], preview_file["id"]), + client=client, + ) + + +def create_shot_tasks(shot, task_types, client=default): + """ + Create tasks for a shot. + + Args: + shot (dict / ID): The shot dict or id. + task_types (list): List of task type dicts or IDs. + + Returns: + list: Created tasks. + """ + shot = normalize_model_parameter(shot) + task_type_ids = [ + normalize_model_parameter(task_type)["id"] for task_type in task_types + ] + return raw.post( + "data/shots/%s/tasks" % shot["id"], + {"task_type_ids": task_type_ids}, + client=client, + ) + + +def create_asset_tasks(asset, task_types, client=default): + """ + Create tasks for an asset. + + Args: + asset (dict / ID): The asset dict or id. + task_types (list): List of task type dicts or IDs. + + Returns: + list: Created tasks. + """ + asset = normalize_model_parameter(asset) + task_type_ids = [ + normalize_model_parameter(task_type)["id"] for task_type in task_types + ] + return raw.post( + "data/assets/%s/tasks" % asset["id"], + {"task_type_ids": task_type_ids}, + client=client, + ) + + +def create_edit_tasks(edit, task_types, client=default): + """ + Create tasks for an edit. + + Args: + edit (dict / ID): The edit dict or id. + task_types (list): List of task type dicts or IDs. + + Returns: + list: Created tasks. + """ + edit = normalize_model_parameter(edit) + task_type_ids = [ + normalize_model_parameter(task_type)["id"] for task_type in task_types + ] + return raw.post( + "data/edits/%s/tasks" % edit["id"], + {"task_type_ids": task_type_ids}, + client=client, + ) + + +def create_concept_tasks(concept, task_types, client=default): + """ + Create tasks for a concept. + + Args: + concept (dict / ID): The concept dict or id. + task_types (list): List of task type dicts or IDs. + + Returns: + list: Created tasks. + """ + concept = normalize_model_parameter(concept) + task_type_ids = [ + normalize_model_parameter(task_type)["id"] for task_type in task_types + ] + return raw.post( + "data/concepts/%s/tasks" % concept["id"], + {"task_type_ids": task_type_ids}, + client=client, + ) + + +def create_entity_tasks(entity, task_types, client=default): + """ + Create tasks for an entity. + + Args: + entity (dict / ID): The entity dict or id. + task_types (list): List of task type dicts or IDs. + + Returns: + list: Created tasks. + """ + entity = normalize_model_parameter(entity) + task_type_ids = [ + normalize_model_parameter(task_type)["id"] for task_type in task_types + ] + return raw.post( + "data/entities/%s/tasks" % entity["id"], + {"task_type_ids": task_type_ids}, + client=client, + ) diff --git a/gazu/user.py b/gazu/user.py index 2a1252a..58e6900 100644 --- a/gazu/user.py +++ b/gazu/user.py @@ -352,3 +352,319 @@ def update_filter(filter, client=default): return raw.put( "data/user/filters/%s" % filter["id"], filter, client=client ) + + +@cache +def get_context(client=default): + """ + Get user context. + + Returns: + dict: User context information. + """ + return raw.get("data/user/context", client=client) + + +@cache +def all_project_assets(project, client=default): + """ + Get assets for which user has tasks assigned for given project. + + Args: + project (dict / ID): The project dict or id. + + Returns: + list: Assets for the project. + """ + project = normalize_model_parameter(project) + path = "user/projects/%s/assets" % project["id"] + return raw.fetch_all(path, client=client) + + +@cache +def all_tasks_requiring_feedback(client=default): + """ + Get tasks requiring feedback from the current user. + + Returns: + list: Tasks requiring feedback. + """ + return raw.fetch_all("user/tasks-requiring-feedback", client=client) + + +@cache +def all_filter_groups(client=default): + """ + Get all filter groups for current user. + + Returns: + list: Filter groups. + """ + return raw.fetch_all("user/filter-groups", client=client) + + +def new_filter_group(name, project=None, client=default): + """ + Create a new filter group for current user. + + Args: + name (str): The filter group name. + project (dict / ID): The project dict or id. + + Returns: + dict: Created filter group. + """ + project_id = ( + normalize_model_parameter(project)["id"] + if project is not None + else None + ) + return raw.post( + "data/user/filter-groups", + {"name": name, "project_id": project_id}, + client=client, + ) + + +@cache +def get_filter_group(filter_group, client=default): + """ + Get a filter group. + + Args: + filter_group (dict / ID): The filter group dict or id. + + Returns: + dict: Filter group. + """ + filter_group = normalize_model_parameter(filter_group) + return raw.fetch_one( + "user/filter-groups", filter_group["id"], client=client + ) + + +def update_filter_group(filter_group, client=default): + """ + Update a filter group. + + Args: + filter_group (dict): Filter group to save. + + Returns: + dict: Updated filter group. + """ + return raw.put( + "data/user/filter-groups/%s" % filter_group["id"], + filter_group, + client=client, + ) + + +def remove_filter_group(filter_group, client=default): + """ + Remove given filter group from database. + + Args: + filter_group (dict / ID): The filter group dict or id. + """ + filter_group = normalize_model_parameter(filter_group) + return raw.delete( + "data/user/filter-groups/%s" % filter_group["id"], client=client + ) + + +@cache +def all_desktop_login_logs(client=default): + """ + Get desktop login logs for current user. + + Returns: + list: Desktop login logs. + """ + return raw.fetch_all("user/desktop-login-logs", client=client) + + +@cache +def get_time_spents_by_date(date, client=default): + """ + Get time spents for a specific date. + + Args: + date (str): Date in YYYY-MM-DD format. + + Returns: + list: Time spents for the date. + """ + return raw.get("data/user/time-spents/by-date", params={"date": date}, client=client) + + +@cache +def get_task_time_spent(task, client=default): + """ + Get time spent for a specific task. + + Args: + task (dict / ID): The task dict or id. + + Returns: + dict: Time spent information for the task. + """ + task = normalize_model_parameter(task) + path = "data/user/tasks/%s/time-spent" % task["id"] + return raw.get(path, client=client) + + +@cache +def get_day_off(client=default): + """ + Get day off information for current user. + + Returns: + dict: Day off information. + """ + return raw.get("data/user/day-off", client=client) + + +@cache +def all_notifications(client=default): + """ + Get all notifications for current user. + + Returns: + list: Notifications. + """ + return raw.fetch_all("user/notifications", client=client) + + +@cache +def get_notification(notification, client=default): + """ + Get a specific notification. + + Args: + notification (dict / ID): The notification dict or id. + + Returns: + dict: Notification. + """ + notification = normalize_model_parameter(notification) + return raw.fetch_one( + "user/notifications", notification["id"], client=client + ) + + +def update_notification(notification, client=default): + """ + Update a notification. + + Args: + notification (dict): Notification to save. + + Returns: + dict: Updated notification. + """ + return raw.put( + "data/user/notifications/%s" % notification["id"], + notification, + client=client, + ) + + +@cache +def check_task_subscription(task, client=default): + """ + Check if user is subscribed to a task. + + Args: + task (dict / ID): The task dict or id. + + Returns: + dict: Subscription status. + """ + task = normalize_model_parameter(task) + path = "data/user/tasks/%s/subscription" % task["id"] + return raw.get(path, client=client) + + +def subscribe_to_task(task, client=default): + """ + Subscribe to a task. + + Args: + task (dict / ID): The task dict or id. + + Returns: + dict: Subscription information. + """ + task = normalize_model_parameter(task) + path = "data/user/tasks/%s/subscribe" % task["id"] + return raw.post(path, {}, client=client) + + +def unsubscribe_from_task(task, client=default): + """ + Unsubscribe from a task. + + Args: + task (dict / ID): The task dict or id. + """ + task = normalize_model_parameter(task) + path = "data/user/tasks/%s/unsubscribe" % task["id"] + return raw.delete(path, client=client) + + +@cache +def all_chats(client=default): + """ + Get all chats for current user. + + Returns: + list: Chats. + """ + return raw.fetch_all("user/chats", client=client) + + +def join_chat(chat, client=default): + """ + Join a chat. + + Args: + chat (dict / ID): The chat dict or id. + + Returns: + dict: Chat information. + """ + chat = normalize_model_parameter(chat) + path = "data/user/chats/%s/join" % chat["id"] + return raw.post(path, {}, client=client) + + +def leave_chat(chat, client=default): + """ + Leave a chat. + + Args: + chat (dict / ID): The chat dict or id. + """ + chat = normalize_model_parameter(chat) + path = "data/user/chats/%s/leave" % chat["id"] + return raw.delete(path, client=client) + + +def clear_avatar(client=default): + """ + Clear user avatar. + + Returns: + Response: Request response object. + """ + return raw.delete("data/user/avatar", client=client) + +def mark_all_notifications_as_read(client=default): + """ + Mark all notifications as read for current user. + + Returns: + dict: Response information. + """ + return raw.post("data/user/notifications/read-all", {}, client=client) diff --git a/tests/test_entity.py b/tests/test_entity.py index 488b402..fd9aaa4 100644 --- a/tests/test_entity.py +++ b/tests/test_entity.py @@ -131,3 +131,13 @@ def test_remove_entity(self): status_code=204, ) gazu.entity.remove_entity(fakeid("entity-1"), True) + + def test_remove_entity_type(self): + with requests_mock.mock() as mock: + mock.delete( + gazu.client.get_full_url( + "data/entity-types/%s" % fakeid("entity-type-1") + ), + status_code=204, + ) + gazu.entity.remove_entity_type(fakeid("entity-type-1")) diff --git a/tests/test_person.py b/tests/test_person.py index 5817bc5..5adf9df 100644 --- a/tests/test_person.py +++ b/tests/test_person.py @@ -355,3 +355,141 @@ def test_invite_person(self): gazu.person.invite_person(person_id), {"success": True}, ) + + def test_get_time_spents_by_date(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + mock_route( + mock, + "GET", + "data/persons/%s/time-spents/by-date?date=2025-01-15" + % person_id, + text=[{"id": fakeid("ts-1")}, {"id": fakeid("ts-2")}], + ) + time_spents = gazu.person.get_time_spents_by_date( + person_id, "2025-01-15" + ) + self.assertEqual(len(time_spents), 2) + + def test_get_week_time_spents(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + mock_route( + mock, + "GET", + "data/persons/%s/time-spents/week/2025/3" % person_id, + text=[{"id": fakeid("ts-1")}], + ) + time_spents = gazu.person.get_week_time_spents(person_id, 2025, 3) + self.assertEqual(len(time_spents), 1) + + def test_get_year_time_spents(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + mock_route( + mock, + "GET", + "data/persons/%s/time-spents/year/2025" % person_id, + text=[{"id": fakeid("ts-1")}, {"id": fakeid("ts-2")}], + ) + time_spents = gazu.person.get_year_time_spents(person_id, 2025) + self.assertEqual(len(time_spents), 2) + + def test_get_day_offs(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + mock_route( + mock, + "GET", + "data/persons/%s/day-offs" % person_id, + text=[{"id": fakeid("dayoff-1")}, {"id": fakeid("dayoff-2")}], + ) + day_offs = gazu.person.get_day_offs(person_id) + self.assertEqual(len(day_offs), 2) + + def test_get_week_day_offs(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + mock_route( + mock, + "GET", + "data/persons/%s/day-offs/week/2025/3" % person_id, + text=[{"id": fakeid("dayoff-1")}], + ) + day_offs = gazu.person.get_week_day_offs(person_id, 2025, 3) + self.assertEqual(len(day_offs), 1) + + def test_get_month_day_offs(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + mock_route( + mock, + "GET", + "data/persons/%s/day-offs/month/2025/01" % person_id, + text=[{"id": fakeid("dayoff-1")}], + ) + day_offs = gazu.person.get_month_day_offs(person_id, 2025, 1) + self.assertEqual(len(day_offs), 1) + + def test_get_year_day_offs(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + mock_route( + mock, + "GET", + "data/persons/%s/day-offs/year/2025" % person_id, + text=[{"id": fakeid("dayoff-1")}, {"id": fakeid("dayoff-2")}], + ) + day_offs = gazu.person.get_year_day_offs(person_id, 2025) + self.assertEqual(len(day_offs), 2) + + def test_add_person_to_department(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + dept_id = fakeid("department-1") + mock_route( + mock, + "POST", + "data/persons/%s/departments" % person_id, + text={"id": person_id, "departments": [dept_id]}, + ) + result = gazu.person.add_person_to_department( + person_id, {"id": dept_id} + ) + self.assertEqual(result["id"], person_id) + + def test_remove_person_from_department(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + dept_id = fakeid("department-1") + mock_route( + mock, + "DELETE", + "data/persons/%s/departments/%s" % (person_id, dept_id), + status_code=204, + ) + gazu.person.remove_person_from_department( + person_id, {"id": dept_id} + ) + + def test_disable_two_factor_authentication(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + mock_route( + mock, + "DELETE", + "data/persons/%s/two-factor-authentication" % person_id, + status_code=204, + ) + gazu.person.disable_two_factor_authentication(person_id) + + def test_clear_person_avatar(self): + with requests_mock.mock() as mock: + person_id = fakeid("person-1") + mock_route( + mock, + "DELETE", + "data/persons/%s/avatar" % person_id, + status_code=204, + ) + gazu.person.clear_person_avatar(person_id) diff --git a/tests/test_playlist.py b/tests/test_playlist.py index 7f5a6fc..eaa2dd4 100644 --- a/tests/test_playlist.py +++ b/tests/test_playlist.py @@ -219,3 +219,174 @@ def test_add_entity_to_playlist(self): playlist, shot ) self.assertEqual(playlist["shots"], []) + + def test_delete_playlist(self): + with requests_mock.mock() as mock: + mock.delete( + gazu.client.get_full_url( + "data/playlists/%s" % fakeid("playlist-1") + ), + status_code=204, + ) + gazu.playlist.delete_playlist(fakeid("playlist-1")) + + def test_get_entity_previews(self): + with requests_mock.mock() as mock: + mock.get( + gazu.client.get_full_url( + "data/playlists/%s/entity-previews" + % fakeid("playlist-1") + ), + text=json.dumps( + [ + {"id": fakeid("preview-1"), "name": "preview-1"}, + {"id": fakeid("preview-2"), "name": "preview-2"}, + ] + ), + ) + previews = gazu.playlist.get_entity_previews( + fakeid("playlist-1") + ) + self.assertEqual(len(previews), 2) + self.assertEqual(previews[0]["name"], "preview-1") + + def test_get_build_job(self): + with requests_mock.mock() as mock: + mock.get( + gazu.client.get_full_url( + "data/playlists/build-jobs/%s" % fakeid("build-job-1") + ), + text=json.dumps( + {"id": fakeid("build-job-1"), "status": "done"} + ), + ) + build_job = gazu.playlist.get_build_job(fakeid("build-job-1")) + self.assertEqual(build_job["id"], fakeid("build-job-1")) + self.assertEqual(build_job["status"], "done") + + def test_remove_build_job(self): + with requests_mock.mock() as mock: + mock.delete( + gazu.client.get_full_url( + "data/playlists/build-jobs/%s" % fakeid("build-job-1") + ), + status_code=204, + ) + gazu.playlist.remove_build_job(fakeid("build-job-1")) + + def test_all_build_jobs_for_project(self): + with requests_mock.mock() as mock: + mock.get( + gazu.client.get_full_url( + "data/projects/%s/build-jobs" % fakeid("project-1") + ), + text=json.dumps( + [ + {"id": fakeid("build-job-1"), "status": "done"}, + {"id": fakeid("build-job-2"), "status": "running"}, + ] + ), + ) + build_jobs = gazu.playlist.all_build_jobs_for_project( + fakeid("project-1") + ) + self.assertEqual(len(build_jobs), 2) + self.assertEqual(build_jobs[0]["id"], fakeid("build-job-1")) + + def test_build_playlist_movie(self): + with requests_mock.mock() as mock: + mock.post( + gazu.client.get_full_url( + "data/playlists/%s/build-movie" % fakeid("playlist-1") + ), + text=json.dumps( + {"id": fakeid("build-job-1"), "status": "running"} + ), + ) + build_job = gazu.playlist.build_playlist_movie( + fakeid("playlist-1") + ) + self.assertEqual(build_job["id"], fakeid("build-job-1")) + self.assertEqual(build_job["status"], "running") + + def test_download_playlist_build(self): + import tempfile + import os + + with requests_mock.mock() as mock: + mock.get( + gazu.client.get_full_url( + "data/playlists/%s/build-jobs/%s/download" + % (fakeid("playlist-1"), fakeid("build-job-1")) + ), + content=b"mock movie content", + ) + with tempfile.NamedTemporaryFile(delete=False) as tmp_file: + tmp_path = tmp_file.name + try: + gazu.playlist.download_playlist_build( + fakeid("playlist-1"), + fakeid("build-job-1"), + tmp_path, + ) + with open(tmp_path, "rb") as f: + self.assertEqual(f.read(), b"mock movie content") + finally: + if os.path.exists(tmp_path): + os.unlink(tmp_path) + + def test_download_playlist_zip(self): + import tempfile + import os + + with requests_mock.mock() as mock: + mock.get( + gazu.client.get_full_url( + "data/playlists/%s/download/zip" % fakeid("playlist-1") + ), + content=b"mock zip content", + ) + with tempfile.NamedTemporaryFile(delete=False) as tmp_file: + tmp_path = tmp_file.name + try: + gazu.playlist.download_playlist_zip( + fakeid("playlist-1"), tmp_path + ) + with open(tmp_path, "rb") as f: + self.assertEqual(f.read(), b"mock zip content") + finally: + if os.path.exists(tmp_path): + os.unlink(tmp_path) + + def test_generate_temp_playlist(self): + with requests_mock.mock() as mock: + mock.post( + gazu.client.get_full_url( + "data/projects/%s/playlists/temp" % fakeid("project-1") + ), + text=json.dumps( + { + "id": fakeid("playlist-temp-1"), + "name": "temp-playlist", + } + ), + ) + temp_playlist = gazu.playlist.generate_temp_playlist( + fakeid("project-1"), + {"shots": [fakeid("shot-1"), fakeid("shot-2")]}, + ) + self.assertEqual(temp_playlist["id"], fakeid("playlist-temp-1")) + self.assertEqual(temp_playlist["name"], "temp-playlist") + + def test_notify_clients_playlist_ready(self): + with requests_mock.mock() as mock: + mock.post( + gazu.client.get_full_url( + "data/playlists/%s/notify" % fakeid("playlist-1") + ), + text=json.dumps({"status": "notified"}), + ) + response = gazu.playlist.notify_clients_playlist_ready( + fakeid("playlist-1") + ) + self.assertEqual(response["status"], "notified") diff --git a/tests/test_project.py b/tests/test_project.py index e90db6b..65bfcba 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -478,3 +478,260 @@ def test_remove_person_from_team(self): path = "data/projects/%s/team/%s" % (project_id, person_id) mock_route(mock, "DELETE", path, text="") gazu.project.remove_person_from_team(project_id, person_id) + + def test_get_project_task_types(self): + with requests_mock.mock() as mock: + project_id = fakeid("project-1") + path = "data/projects/%s/settings/task-types" % project_id + mock_route( + mock, + "GET", + path, + text=[ + {"id": fakeid("task-type-1"), "name": "Anim"}, + {"id": fakeid("task-type-2"), "name": "Comp"}, + ], + ) + items = gazu.project.get_project_task_types(project_id) + self.assertEqual(len(items), 2) + self.assertEqual(items[0]["id"], fakeid("task-type-1")) + + def test_get_project_task_statuses(self): + with requests_mock.mock() as mock: + project_id = fakeid("project-1") + path = "data/projects/%s/settings/task-status" % project_id + mock_route( + mock, + "GET", + path, + text=[ + {"id": fakeid("task-status-1"), "name": "WIP"}, + {"id": fakeid("task-status-2"), "name": "Done"}, + ], + ) + items = gazu.project.get_project_task_statuses(project_id) + self.assertEqual(len(items), 2) + self.assertEqual(items[1]["name"], "Done") + + def test_status_automations(self): + with requests_mock.mock() as mock: + project_id = fakeid("project-1") + get_path = "data/projects/%s/settings/status-automations" % project_id + mock_route( + mock, + "GET", + get_path, + text=[{"id": fakeid("auto-1")}, {"id": fakeid("auto-2")}], + ) + items = gazu.project.all_status_automations(project_id) + self.assertEqual(len(items), 2) + + post_payload = {"from_status_id": fakeid("task-status-1"), "to_status_id": fakeid("task-status-2")} + mock_route( + mock, + "POST", + get_path, + text={"id": fakeid("auto-3"), **post_payload}, + ) + created = gazu.project.add_status_automation(project_id, post_payload) + self.assertEqual(created["id"], fakeid("auto-3")) + + del_path = "data/projects/%s/settings/status-automations/%s" % ( + project_id, + fakeid("auto-3"), + ) + mock_route(mock, "DELETE", del_path, text="") + gazu.project.remove_status_automation( + project_id, {"id": fakeid("auto-3")} + ) + + def test_preview_background_files(self): + with requests_mock.mock() as mock: + project_id = fakeid("project-1") + base_path = "data/projects/%s/preview-background-files" % project_id + + mock_route( + mock, + "GET", + base_path, + text=[{"id": fakeid("bg-1")}, {"id": fakeid("bg-2")}], + ) + items = gazu.project.get_preview_background_files(project_id) + self.assertEqual(len(items), 2) + + mock_route( + mock, + "POST", + base_path, + text={"id": fakeid("bg-3"), "name": "grid"}, + ) + created = gazu.project.add_preview_background_file( + project_id, {"name": "grid"} + ) + self.assertEqual(created["id"], fakeid("bg-3")) + + del_path = base_path + "/%s" % fakeid("bg-3") + mock_route(mock, "DELETE", del_path, text="") + gazu.project.remove_preview_background_file( + project_id, {"id": fakeid("bg-3")} + ) + + def test_get_milestones(self): + with requests_mock.mock() as mock: + project_id = fakeid("project-1") + path = "data/projects/%s/milestones" % project_id + mock_route( + mock, + "GET", + path, + text=[{"id": fakeid("milestone-1")}, {"id": fakeid("milestone-2")}], + ) + milestones = gazu.project.get_milestones(project_id) + self.assertEqual(len(milestones), 2) + + def test_project_quotas(self): + with requests_mock.mock() as mock: + project_id = fakeid("project-1") + quotas_path = "data/projects/%s/quotas" % project_id + mock_route( + mock, + "GET", + quotas_path, + text=[{"id": fakeid("quota-1")}, {"id": fakeid("quota-2")}], + ) + quotas = gazu.project.get_project_quotas(project_id) + self.assertEqual(len(quotas), 2) + + person_id = fakeid("person-1") + person_path = ( + "data/projects/%s/person-quotas?person_id=%s" + % (project_id, person_id) + ) + mock_route( + mock, + "GET", + person_path, + text=[{"id": fakeid("pquota-1")}], + ) + pquotas = gazu.project.get_project_person_quotas( + project_id, person_id + ) + self.assertEqual(len(pquotas), 1) + + def test_budgets(self): + with requests_mock.mock() as mock: + project_id = fakeid("project-1") + + path = "data/projects/%s/budgets" % project_id + mock_route( + mock, "GET", path, text=[{"id": fakeid("budget-1")}] + ) + budgets = gazu.project.get_budgets(project_id) + self.assertEqual(len(budgets), 1) + + mock_route( + mock, + "POST", + path, + text={"id": fakeid("budget-2"), "name": "Budget 2"}, + ) + created = gazu.project.create_budget( + project_id, + name="Budget 2", + description="Desc", + currency="EUR", + start_date="2025-01-01", + end_date="2025-12-31", + amount=1000, + ) + self.assertEqual(created["id"], fakeid("budget-2")) + + get_one_path = path + "/%s" % fakeid("budget-2") + mock_route( + mock, + "GET", + get_one_path, + text={"id": fakeid("budget-2"), "name": "Budget 2"}, + ) + budget = gazu.project.get_budget(project_id, {"id": fakeid("budget-2")}) + self.assertEqual(budget["id"], fakeid("budget-2")) + + mock_route( + mock, + "PUT", + get_one_path, + text={"id": fakeid("budget-2"), "name": "Budget 2 Updated"}, + ) + updated = gazu.project.update_budget( + project_id, {"id": fakeid("budget-2")}, {"name": "Budget 2 Updated"} + ) + self.assertEqual(updated["name"], "Budget 2 Updated") + + mock_route(mock, "DELETE", get_one_path, text="") + gazu.project.remove_budget(project_id, {"id": fakeid("budget-2")}) + + def test_budget_entries(self): + with requests_mock.mock() as mock: + project_id = fakeid("project-1") + budget_id = fakeid("budget-1") + base = "data/projects/%s/budgets/%s" % (project_id, budget_id) + + list_path = base + "/entries" + mock_route( + mock, + "GET", + list_path, + text=[{"id": fakeid("entry-1")}, {"id": fakeid("entry-2")}], + ) + entries = gazu.project.get_budget_entries(project_id, {"id": budget_id}) + self.assertEqual(len(entries), 2) + + mock_route( + mock, + "POST", + list_path, + text={"id": fakeid("entry-3"), "name": "Rent"}, + ) + created = gazu.project.create_budget_entry( + project_id, + {"id": budget_id}, + name="Rent", + date="2025-02-01", + amount=500, + quantity=1, + unit_price=500, + description="Studio rent", + category="overhead", + ) + self.assertEqual(created["id"], fakeid("entry-3")) + + one_path = base + "/entries/%s" % fakeid("entry-3") + mock_route( + mock, + "GET", + one_path, + text={"id": fakeid("entry-3"), "name": "Rent"}, + ) + entry = gazu.project.get_budget_entry( + project_id, {"id": budget_id}, {"id": fakeid("entry-3")} + ) + self.assertEqual(entry["id"], fakeid("entry-3")) + + mock_route( + mock, + "PUT", + one_path, + text={"id": fakeid("entry-3"), "name": "Rent Updated"}, + ) + updated = gazu.project.update_budget_entry( + project_id, + {"id": budget_id}, + {"id": fakeid("entry-3")}, + {"name": "Rent Updated"}, + ) + self.assertEqual(updated["name"], "Rent Updated") + + mock_route(mock, "DELETE", one_path, text="") + gazu.project.remove_budget_entry( + project_id, {"id": budget_id}, {"id": fakeid("entry-3")} + ) diff --git a/tests/test_task.py b/tests/test_task.py index 1be1829..bbf02e6 100644 --- a/tests/test_task.py +++ b/tests/test_task.py @@ -1092,3 +1092,276 @@ def test_update_comment(self): ) self.assertEqual(comment["id"], fakeid("comment-1")) self.assertEqual(comment["text"], "test-comment") + + def test_all_open_tasks(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/tasks/open", + text=[{"id": fakeid("task-1")}, {"id": fakeid("task-2")}], + ) + tasks = gazu.task.all_open_tasks() + self.assertEqual(len(tasks), 2) + + def test_get_open_tasks_stats(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/tasks/open/stats", + text={"total": 10, "by_status": {}}, + ) + stats = gazu.task.get_open_tasks_stats() + self.assertEqual(stats["total"], 10) + + def test_all_previews_for_task(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/tasks/%s/previews" % fakeid("task-1"), + text=[{"id": fakeid("preview-1")}, {"id": fakeid("preview-2")}], + ) + previews = gazu.task.all_previews_for_task(fakeid("task-1")) + self.assertEqual(len(previews), 2) + + def test_all_open_tasks_for_person(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/persons/%s/tasks/open" % fakeid("person-1"), + text=[{"id": fakeid("task-1")}], + ) + tasks = gazu.task.all_open_tasks_for_person(fakeid("person-1")) + self.assertEqual(len(tasks), 1) + + def test_all_tasks_for_person_and_type(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/persons/%s/task-types/%s/tasks" + % (fakeid("person-1"), fakeid("task-type-1")), + text=[{"id": fakeid("task-1")}], + ) + tasks = gazu.task.all_tasks_for_person_and_type( + fakeid("person-1"), fakeid("task-type-1") + ) + self.assertEqual(len(tasks), 1) + + def test_all_comments_for_project(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/projects/%s/comments" % fakeid("project-1"), + text=[{"id": fakeid("comment-1")}, {"id": fakeid("comment-2")}], + ) + comments = gazu.task.all_comments_for_project(fakeid("project-1")) + self.assertEqual(len(comments), 2) + + def test_all_notifications_for_project(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/projects/%s/notifications" % fakeid("project-1"), + text=[{"id": fakeid("notif-1")}], + ) + notifications = gazu.task.all_notifications_for_project( + fakeid("project-1") + ) + self.assertEqual(len(notifications), 1) + + def test_all_preview_files_for_project(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/projects/%s/preview-files" % fakeid("project-1"), + text=[{"id": fakeid("preview-1")}], + ) + previews = gazu.task.all_preview_files_for_project( + fakeid("project-1") + ) + self.assertEqual(len(previews), 1) + + def test_all_subscriptions_for_project(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/projects/%s/subscriptions" % fakeid("project-1"), + text=[{"id": fakeid("sub-1")}], + ) + subscriptions = gazu.task.all_subscriptions_for_project( + fakeid("project-1") + ) + self.assertEqual(len(subscriptions), 1) + + def test_get_persons_tasks_dates(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/projects/%s/persons/tasks/dates" % fakeid("project-1"), + text={"person-1": ["2025-01-15"]}, + ) + dates = gazu.task.get_persons_tasks_dates(fakeid("project-1")) + self.assertIn("person-1", dates) + + def test_remove_tasks_for_type(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "DELETE", + "data/projects/%s/task-types/%s/tasks" + % (fakeid("project-1"), fakeid("task-type-1")), + status_code=204, + ) + gazu.task.remove_tasks_for_type( + fakeid("project-1"), fakeid("task-type-1") + ) + + def test_remove_tasks_batch(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "POST", + "data/tasks/delete-batch", + text={"deleted": 2}, + ) + result = gazu.task.remove_tasks_batch( + [fakeid("task-1"), fakeid("task-2")] + ) + self.assertEqual(result["deleted"], 2) + + def test_assign_tasks_to_person(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "PUT", + "data/tasks/assign", + text={"assigned": 2}, + ) + result = gazu.task.assign_tasks_to_person( + [fakeid("task-1"), fakeid("task-2")], fakeid("person-1") + ) + self.assertEqual(result["assigned"], 2) + + def test_get_task_time_spent_for_date(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/tasks/%s/time-spent/for-date?date=2025-01-15" + % fakeid("task-1"), + text={"duration": 3600}, + ) + time_spent = gazu.task.get_task_time_spent_for_date( + fakeid("task-1"), "2025-01-15" + ) + self.assertEqual(time_spent["duration"], 3600) + + def test_remove_time_spent(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "DELETE", + "data/time-spents/%s" % fakeid("time-spent-1"), + status_code=204, + ) + gazu.task.remove_time_spent(fakeid("time-spent-1")) + + def test_add_preview_to_comment(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "POST", + "data/comments/%s/preview-files" % fakeid("comment-1"), + text={"id": fakeid("comment-1"), "preview_files": [fakeid("preview-1")]}, + ) + result = gazu.task.add_preview_to_comment( + fakeid("comment-1"), fakeid("preview-1") + ) + self.assertEqual(result["id"], fakeid("comment-1")) + + def test_remove_preview_from_comment(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "DELETE", + "data/comments/%s/preview-files/%s" + % (fakeid("comment-1"), fakeid("preview-1")), + status_code=204, + ) + gazu.task.remove_preview_from_comment( + fakeid("comment-1"), fakeid("preview-1") + ) + + def test_create_shot_tasks(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "POST", + "data/shots/%s/tasks" % fakeid("shot-1"), + text=[{"id": fakeid("task-1")}, {"id": fakeid("task-2")}], + ) + tasks = gazu.task.create_shot_tasks( + fakeid("shot-1"), [fakeid("task-type-1"), fakeid("task-type-2")] + ) + self.assertEqual(len(tasks), 2) + + def test_create_asset_tasks(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "POST", + "data/assets/%s/tasks" % fakeid("asset-1"), + text=[{"id": fakeid("task-1")}], + ) + tasks = gazu.task.create_asset_tasks( + fakeid("asset-1"), [fakeid("task-type-1")] + ) + self.assertEqual(len(tasks), 1) + + def test_create_edit_tasks(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "POST", + "data/edits/%s/tasks" % fakeid("edit-1"), + text=[{"id": fakeid("task-1")}], + ) + tasks = gazu.task.create_edit_tasks( + fakeid("edit-1"), [fakeid("task-type-1")] + ) + self.assertEqual(len(tasks), 1) + + def test_create_concept_tasks(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "POST", + "data/concepts/%s/tasks" % fakeid("concept-1"), + text=[{"id": fakeid("task-1")}], + ) + tasks = gazu.task.create_concept_tasks( + fakeid("concept-1"), [fakeid("task-type-1")] + ) + self.assertEqual(len(tasks), 1) + + def test_create_entity_tasks(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "POST", + "data/entities/%s/tasks" % fakeid("entity-1"), + text=[{"id": fakeid("task-1")}], + ) + tasks = gazu.task.create_entity_tasks( + fakeid("entity-1"), [fakeid("task-type-1")] + ) + self.assertEqual(len(tasks), 1) diff --git a/tests/test_user.py b/tests/test_user.py index ca0e33a..69d28ec 100644 --- a/tests/test_user.py +++ b/tests/test_user.py @@ -311,3 +311,242 @@ def test_is_authenticated(self): status_code=401, ) self.assertFalse(gazu.user.is_authenticated()) + + def test_get_context(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/user/context", + text={"user": {"id": fakeid("user-1")}}, + ) + context = gazu.user.get_context() + self.assertEqual(context["user"]["id"], fakeid("user-1")) + + def test_all_project_assets(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/user/projects/%s/assets" % fakeid("project-1"), + text=[{"id": fakeid("asset-1")}, {"id": fakeid("asset-2")}], + ) + assets = gazu.user.all_project_assets(fakeid("project-1")) + self.assertEqual(len(assets), 2) + + def test_all_tasks_requiring_feedback(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/user/tasks-requiring-feedback", + text=[{"id": fakeid("task-1")}, {"id": fakeid("task-2")}], + ) + tasks = gazu.user.all_tasks_requiring_feedback() + self.assertEqual(len(tasks), 2) + + def test_filter_groups(self): + with requests_mock.mock() as mock: + # get all filter groups + mock_route( + mock, + "GET", + "data/user/filter-groups", + text=[{"id": fakeid("fg-1")}, {"id": fakeid("fg-2")}], + ) + groups = gazu.user.all_filter_groups() + self.assertEqual(len(groups), 2) + + # create filter group + mock_route( + mock, + "POST", + "data/user/filter-groups", + text={"id": fakeid("fg-3"), "name": "My Group"}, + ) + created = gazu.user.new_filter_group("My Group", {"id": fakeid("project-1")}) + self.assertEqual(created["id"], fakeid("fg-3")) + + # get filter group + mock_route( + mock, + "GET", + "data/user/filter-groups/%s" % fakeid("fg-3"), + text={"id": fakeid("fg-3"), "name": "My Group"}, + ) + group = gazu.user.get_filter_group(fakeid("fg-3")) + self.assertEqual(group["id"], fakeid("fg-3")) + + # update filter group + mock_route( + mock, + "PUT", + "data/user/filter-groups/%s" % fakeid("fg-3"), + text={"id": fakeid("fg-3"), "name": "Updated Group"}, + ) + updated = gazu.user.update_filter_group( + {"id": fakeid("fg-3"), "name": "Updated Group"} + ) + self.assertEqual(updated["name"], "Updated Group") + + # remove filter group + mock_route( + mock, + "DELETE", + "data/user/filter-groups/%s" % fakeid("fg-3"), + status_code=204, + ) + gazu.user.remove_filter_group(fakeid("fg-3")) + + def test_all_desktop_login_logs(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/user/desktop-login-logs", + text=[{"id": fakeid("log-1")}, {"id": fakeid("log-2")}], + ) + logs = gazu.user.all_desktop_login_logs() + self.assertEqual(len(logs), 2) + + def test_get_time_spents_by_date(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/user/time-spents/by-date?date=2025-01-15", + text=[{"id": fakeid("ts-1")}, {"id": fakeid("ts-2")}], + ) + time_spents = gazu.user.get_time_spents_by_date("2025-01-15") + self.assertEqual(len(time_spents), 2) + + def test_get_task_time_spent(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/user/tasks/%s/time-spent" % fakeid("task-1"), + text={"id": fakeid("ts-1"), "duration": 3600}, + ) + time_spent = gazu.user.get_task_time_spent(fakeid("task-1")) + self.assertEqual(time_spent["duration"], 3600) + + def test_get_day_off(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/user/day-off", + text={"days": 5}, + ) + day_off = gazu.user.get_day_off() + self.assertEqual(day_off["days"], 5) + + def test_notifications(self): + with requests_mock.mock() as mock: + mock_route( + mock, + "GET", + "data/user/notifications", + text=[{"id": fakeid("notif-1")}, {"id": fakeid("notif-2")}], + ) + notifications = gazu.user.all_notifications() + self.assertEqual(len(notifications), 2) + + mock_route( + mock, + "GET", + "data/user/notifications/%s" % fakeid("notif-1"), + text={"id": fakeid("notif-1"), "read": False}, + ) + notif = gazu.user.get_notification(fakeid("notif-1")) + self.assertFalse(notif["read"]) + + mock_route( + mock, + "PUT", + "data/user/notifications/%s" % fakeid("notif-1"), + text={"id": fakeid("notif-1"), "read": True}, + ) + updated = gazu.user.update_notification( + {"id": fakeid("notif-1"), "read": True} + ) + self.assertTrue(updated["read"]) + + mock_route( + mock, + "POST", + "data/user/notifications/read-all", + text={"status": "ok"}, + ) + result = gazu.user.mark_all_notifications_as_read() + self.assertEqual(result["status"], "ok") + + def test_task_subscriptions(self): + with requests_mock.mock() as mock: + + mock_route( + mock, + "GET", + "data/user/tasks/%s/subscription" % fakeid("task-1"), + text={"subscribed": True}, + ) + sub = gazu.user.check_task_subscription(fakeid("task-1")) + self.assertTrue(sub["subscribed"]) + + mock_route( + mock, + "POST", + "data/user/tasks/%s/subscribe" % fakeid("task-1"), + text={"subscribed": True}, + ) + result = gazu.user.subscribe_to_task(fakeid("task-1")) + self.assertTrue(result["subscribed"]) + + mock_route( + mock, + "DELETE", + "data/user/tasks/%s/unsubscribe" % fakeid("task-1"), + status_code=204, + ) + gazu.user.unsubscribe_from_task(fakeid("task-1")) + + def test_chats(self): + with requests_mock.mock() as mock: + + mock_route( + mock, + "GET", + "data/user/chats", + text=[{"id": fakeid("chat-1")}, {"id": fakeid("chat-2")}], + ) + chats = gazu.user.all_chats() + self.assertEqual(len(chats), 2) + + mock_route( + mock, + "POST", + "data/user/chats/%s/join" % fakeid("chat-1"), + text={"id": fakeid("chat-1"), "joined": True}, + ) + chat = gazu.user.join_chat(fakeid("chat-1")) + self.assertTrue(chat["joined"]) + + mock_route( + mock, + "DELETE", + "data/user/chats/%s/leave" % fakeid("chat-1"), + status_code=204, + ) + gazu.user.leave_chat(fakeid("chat-1")) + + def test_clear_avatar(self): + + with requests_mock.mock() as mock: + mock_route( + mock, + "DELETE", + "data/user/avatar", + status_code=204, + ) + gazu.user.clear_avatar() \ No newline at end of file