From 3346bb1364fa9582cbf52953723c76ee315b9f5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Wed, 9 Nov 2016 13:58:46 +0100 Subject: [PATCH] Reworked ShotManager into ShotAssetManager --- attract/__init__.py | 2 +- attract/shots_and_assets/__init__.py | 72 ++++++++++++++++++++++------ attract/shots_and_assets/routes.py | 2 +- tests/test_shots.py | 2 +- 4 files changed, 60 insertions(+), 18 deletions(-) diff --git a/attract/__init__.py b/attract/__init__.py index 79f1776..6c456a9 100644 --- a/attract/__init__.py +++ b/attract/__init__.py @@ -22,7 +22,7 @@ class AttractExtension(PillarExtension): def __init__(self): self._log = logging.getLogger('%s.AttractExtension' % __name__) self.task_manager = attract.tasks.TaskManager() - self.shot_manager = attract.shots_and_assets.ShotManager() + self.shot_manager = attract.shots_and_assets.ShotAssetManager() @property def name(self): diff --git a/attract/shots_and_assets/__init__.py b/attract/shots_and_assets/__init__.py index 6da624a..65bebb9 100644 --- a/attract/shots_and_assets/__init__.py +++ b/attract/shots_and_assets/__init__.py @@ -17,7 +17,7 @@ from pillar.api.nodes.custom import register_patch_handler from pillar.api.utils import node_setattr from pillar import attrs_extra -from attract.node_types import node_type_shot, node_type_task +from attract.node_types import node_type_shot, node_type_task, node_type_asset # From patch operation name to fields that operation may edit. VALID_SHOT_PATCH_FIELDS = { @@ -77,26 +77,28 @@ class ProjectSummary(object): @attr.s -class ShotManager(object): - _log = attrs_extra.log('%s.ShotManager' % __name__) +class ShotAssetManager(object): + _log = attrs_extra.log('%s.ShotAssetManager' % __name__) - def create_shot(self, project): - """Creates a new shot, owned by the current user. + def _create_shot_asset(self, project, node_type_name): + """Creates a new shot or asset, owned by the current user. :rtype: pillarsdk.Node """ - from attract import shortcodes + from .eve_hooks import typenames + + typename = typenames[node_type_name] project_id = project['_id'] - self._log.info('Creating shot for project %s', project_id) + self._log.info('Creating %s for project %s', typename, project_id) api = pillar_api() - node_type = project.get_node_type(node_type_shot['name']) + node_type = project.get_node_type(node_type_name) if not node_type: raise ValueError('Project %s not set up for Attract' % project_id) node_props = dict( - name='New shot', + name='New %s' % typename, project=project_id, user=flask_login.current_user.objectid, node_type=node_type['name'], @@ -105,14 +107,28 @@ class ShotManager(object): }, ) - shot = pillarsdk.Node(node_props) - shot.create(api=api) - return shot + node = pillarsdk.Node(node_props) + node.create(api=api) + return node - def tasks_for_shots(self, shots, known_task_types): + def create_shot(self, project): + """Creates a new shot, owned by the current user. + + :rtype: pillarsdk.Node + """ + return self._create_shot_asset(project, node_type_shot['name']) + + def create_asset(self, project): + """Creates a new asset, owned by the current user. + + :rtype: pillarsdk.Node + """ + return self._create_shot_asset(project, node_type_asset['name']) + + def tasks_for_nodes(self, nodes, known_task_types): """Returns a dict of tasks for each shot. - :param shots: list of shot nodes. + :param nodes: list of shot or asset nodes. :param known_task_types: Collection of task type names. Any task with a type not in this list will map the None key. :returns: a dict {shot id: tasks}, where tasks is a dict in which the keys are the @@ -125,7 +141,7 @@ class ShotManager(object): id_to_shot = {} shot_id_to_tasks = {} - for shot in shots: + for shot in nodes: shot_id = shot['_id'] id_to_shot[shot_id] = shot shot_id_to_tasks[shot_id] = collections.defaultdict(set) @@ -177,6 +193,32 @@ class ShotManager(object): shot.patch(patch, api=api) + def edit_asset(self, asset_id, **fields): + """Edits an asset. + + :type asset_id: str + :type fields: dict + :rtype: pillarsdk.Node + """ + + api = pillar_api() + asset = pillarsdk.Node.find(asset_id, api=api) + + asset._etag = fields.pop('_etag') + asset.name = fields.pop('name') + asset.description = fields.pop('description') or None + asset.properties.notes = fields.pop('notes') or None + asset.properties.status = fields.pop('status') + + self._log.info('Saving asset %s', asset.to_dict()) + + if fields: + self._log.warning('edit_asset(%r, ...) called with unknown fields %r; ignoring them.', + asset_id, fields) + + asset.update(api=api) + return asset + def shot_status_summary(self, project_id): """Returns number of shots per shot status for the given project. diff --git a/attract/shots_and_assets/routes.py b/attract/shots_and_assets/routes.py index fc6a2cf..1475f5f 100644 --- a/attract/shots_and_assets/routes.py +++ b/attract/shots_and_assets/routes.py @@ -50,7 +50,7 @@ def for_project(project, attract_props, task_id=None, shot_id=None): # each project, we can't hard-code a proper height. shot._thumbnail_height = '30px' if shot._thumbnail is thumb_placeholder else 'auto' - tasks_for_shots = current_attract.shot_manager.tasks_for_shots( + tasks_for_shots = current_attract.shot_manager.tasks_for_nodes( shots, attract_props.task_types.attract_shot, ) diff --git a/tests/test_shots.py b/tests/test_shots.py index 582e24b..d46f4d4 100644 --- a/tests/test_shots.py +++ b/tests/test_shots.py @@ -70,7 +70,7 @@ class ShotManagerTest(AbstractShotTest): pillar.auth.login_user(ctd.EXAMPLE_PROJECT_OWNER_ID) self.mock_blenderid_validate_happy() - shot_id_to_task = self.smngr.tasks_for_shots([shot1, shot2], + shot_id_to_task = self.smngr.tasks_for_nodes([shot1, shot2], [u'fx', u'høken', u'effects']) # Just test based on task IDs, as strings are turned into datetimes etc. by the API,