zou 0.20.69__py3-none-any.whl → 0.20.71__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
zou/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.20.69"
1
+ __version__ = "0.20.71"
@@ -326,9 +326,6 @@ class AddAttachmentToCommentResource(Resource):
326
326
  name: reply_id
327
327
  type: uuid
328
328
  example: a24a6ea4-ce75-4665-a070-57453082c25
329
- required: True
330
- format: uuid
331
- example: a24a6ea4-ce75-4665-a070-57453082c25
332
329
  - in: formData
333
330
  name: files
334
331
  type: file
@@ -567,7 +567,12 @@ def is_asset_type(entity_type):
567
567
  """
568
568
  Returns true if given entity type is an asset, not a shot.
569
569
  """
570
- return str(entity_type.id) not in get_temporal_type_ids()
570
+ entity_type_id = ""
571
+ if isinstance(entity_type, dict):
572
+ entity_type_id = entity_type.get("id", "")
573
+ else:
574
+ entity_type_id = str(entity_type.id)
575
+ return entity_type_id not in get_temporal_type_ids()
571
576
 
572
577
 
573
578
  def create_asset_types(asset_type_names):
@@ -79,14 +79,18 @@ def create_comment(
79
79
  files={},
80
80
  created_at="",
81
81
  links=[],
82
+ with_hashtags=True
82
83
  ):
83
84
  """
84
85
  Create a new comment and related: news, notifications and events.
85
86
  """
87
+ related_tasks = []
88
+ author = _get_comment_author(person_id)
86
89
  task = tasks_service.get_task(task_id, relations=True)
87
90
  task_status = tasks_service.get_task_status(task_status_id)
88
- author = _get_comment_author(person_id)
91
+ task_type = tasks_service.get_task_type(task["task_type_id"])
89
92
  _check_retake_capping(task_status, task)
93
+
90
94
  comment = new_comment(
91
95
  task_id=task_id,
92
96
  object_type="Task",
@@ -98,6 +102,10 @@ def create_comment(
98
102
  created_at=created_at,
99
103
  links=links,
100
104
  )
105
+
106
+ if with_hashtags:
107
+ _handle_hashtags(author, task_type, task, text)
108
+
101
109
  task, status_changed = _manage_status_change(task_status, task, comment)
102
110
  _manage_subscriptions(task, comment, status_changed)
103
111
  comment["task_status"] = task_status
@@ -108,9 +116,32 @@ def create_comment(
108
116
  )
109
117
  for automation in status_automations:
110
118
  _run_status_automation(automation, task, person_id)
119
+
111
120
  return comment
112
121
 
113
122
 
123
+ def _handle_hashtags(person, task_type, task, text):
124
+ hashtags = get_comment_hashtags(text)
125
+ if len(hashtags) > 0:
126
+ entity = entities_service.get_entity(entity_id=task["entity_id"])
127
+ tasks = entities_service.get_entity_tasks(entity)
128
+ tasks = filter_tasks_by_hashtags(tasks, hashtags, task_type)
129
+ if len(tasks) > 0:
130
+ for _task in tasks:
131
+ task_status = tasks_service.get_task_status(
132
+ _task["task_status_id"]
133
+ )
134
+ create_comment(
135
+ person_id=person["id"],
136
+ task_id=_task["id"],
137
+ text=text + f"\n\n____\nFrom {task_type['name']} task",
138
+ task_status_id=task_status["id"],
139
+ with_hashtags=False
140
+ )
141
+ return hashtags
142
+
143
+
144
+
114
145
  def _check_retake_capping(task_status, task):
115
146
  if task_status["is_retake"]:
116
147
  project = projects_service.get_project(task["project_id"])
@@ -502,6 +533,7 @@ def reply_comment(comment_id, text, person_id=None, files={}):
502
533
  new_attachment_file["reply_id"] = reply["id"]
503
534
  reply["attachment_files"] = new_attachment_files
504
535
  tasks_service.clear_comment_cache(comment_id)
536
+ comment = comment.serialize(relations=True)
505
537
  events.emit(
506
538
  "comment:reply",
507
539
  {
@@ -593,6 +625,45 @@ def get_comment_department_mention_ids(project_id, text):
593
625
  ]
594
626
 
595
627
 
628
+ def get_comment_hashtags(text):
629
+ """
630
+ Check for task type mentions (#full name) in text and returns matching
631
+ tags. If all is present, return only all because it includes everything
632
+ else.
633
+ """
634
+ hashtags = [
635
+ hashtag[1:].lower()
636
+ for hashtag in re.findall("#[a-zA-Z]*", text, re.IGNORECASE)
637
+ ]
638
+ if "all" in hashtags:
639
+ return ["all"]
640
+ return list(set(hashtags))
641
+
642
+
643
+ def filter_tasks_by_hashtags(tasks, hashtags, original_task_type):
644
+ """
645
+ Filter tasks based on hashtags, excluding specified task types.
646
+ """
647
+ if "all" in hashtags:
648
+ return [
649
+ task
650
+ for task in tasks
651
+ if task["task_type_name"].lower() != \
652
+ original_task_type["name"].lower()
653
+ ]
654
+ else:
655
+ hashtag_map = {
656
+ hashtag: True
657
+ for hashtag in hashtags
658
+ if hashtag != original_task_type["name"].lower()
659
+ }
660
+ return [
661
+ task
662
+ for task in tasks
663
+ if hashtag_map.get(task["task_type_name"].lower(), False)
664
+ ]
665
+
666
+
596
667
  def add_attachments_to_comment(comment, files, reply_id=None):
597
668
  """
598
669
  Create an attachment entry and for each given uploaded files and tie it
@@ -118,6 +118,10 @@ def remove_task(task_id, force=False):
118
118
  for subscription in subscriptions:
119
119
  subscription.delete()
120
120
 
121
+ working_files = WorkingFile.query.filter_by(task_id=task_id)
122
+ for working_file in working_files:
123
+ working_file.delete()
124
+
121
125
  preview_files = PreviewFile.query.filter_by(task_id=task_id)
122
126
  for preview_file in preview_files:
123
127
  remove_preview_file(preview_file)
@@ -1,10 +1,12 @@
1
1
  from zou.app.services import (
2
+ assets_service,
2
3
  base_service,
3
4
  projects_service,
4
5
  notifications_service,
5
6
  assets_service,
6
7
  shots_service,
7
8
  edits_service,
9
+ tasks_service,
8
10
  )
9
11
  from zou.app.utils import (
10
12
  date_helpers,
@@ -363,6 +365,20 @@ def get_entities_and_tasks(criterions={}):
363
365
  return list(entity_map.values())
364
366
 
365
367
 
368
+ def get_entity_tasks(entity):
369
+ """
370
+ Get all tasks for a given entity.
371
+ """
372
+ entity_type = get_entity_type(entity_type_id=entity["entity_type_id"])
373
+ entity_type_name = entity_type["name"]
374
+ if assets_service.is_asset_type(entity_type):
375
+ entity_type_name = "Asset"
376
+ get_tasks = getattr(
377
+ tasks_service, "get_tasks_for_" + entity_type_name.lower()
378
+ )
379
+ return get_tasks(entity["id"])
380
+
381
+
366
382
  def remove_entity_link(link_id):
367
383
  try:
368
384
  link = EntityLink.get_by(id=link_id)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zou
3
- Version: 0.20.69
3
+ Version: 0.20.71
4
4
  Summary: API to store and manage the data of your animation production
5
5
  Home-page: https://zou.cg-wire.com
6
6
  Author: CG Wire
@@ -1,4 +1,4 @@
1
- zou/__init__.py,sha256=_tWKS_svbja-_oGQ_O3PAR4H37-jNV4LQdX0iMCPCac,24
1
+ zou/__init__.py,sha256=jpLzACNJQj7ZV-vygNr_yxjdy_Ljanp1xEeYXAHi-QE,24
2
2
  zou/cli.py,sha256=N9FyrL4TDgIiCUa-I3xIzOgiVLM14kz8_QLQ48y51oE,22767
3
3
  zou/debug.py,sha256=1fawPbkD4wn0Y9Gk0BiBFSa-CQe5agFi8R9uJYl2Uyk,520
4
4
  zou/event_stream.py,sha256=9O1PE_vDW8p3yfHJNSZ8w0ybD-660x8oGN0izgJdTjM,8575
@@ -18,7 +18,7 @@ zou/app/blueprints/breakdown/resources.py,sha256=vpE6aTdSPS3KSuGhgFIXxgYf3LXwjUj
18
18
  zou/app/blueprints/chats/__init__.py,sha256=YGmwGvddg3MgSYVIh-hmkX8t2em9_LblxBeJzFqFJD4,558
19
19
  zou/app/blueprints/chats/resources.py,sha256=ekKH8BghL4MAh-ZzT8IDPVy8cYAbCRAYwzjjkIa4DmU,5934
20
20
  zou/app/blueprints/comments/__init__.py,sha256=WqpJ7-_dK1cInGTFJAxQ7syZtPCotwq2oO20UEnk1h4,1532
21
- zou/app/blueprints/comments/resources.py,sha256=FKKfpbnL3MuY5jpK1JgrcLyUlo6_cRLMMDcrOx-JKQ0,19588
21
+ zou/app/blueprints/comments/resources.py,sha256=HOH3tTdNqJZx4goFr1OZqzx9xv6oS2D9TbfwHdA2tPQ,19479
22
22
  zou/app/blueprints/concepts/__init__.py,sha256=sP_P4mfYvfMcgeE6MHZYP3eD0Lz0Lwit5-CFuVnA-Jg,894
23
23
  zou/app/blueprints/concepts/resources.py,sha256=hXVK0ON5vu2VDporVLrQdb5HjyxpVrXLoTq-ObLiO_Y,10114
24
24
  zou/app/blueprints/crud/__init__.py,sha256=bzjCUL2BAYuufiWcP1n83JAp1TKXEMqTeN6wMOha76M,9667
@@ -193,21 +193,21 @@ zou/app/models/task_type.py,sha256=IsixVAfz3pyMf0eQw8x-uFNM9OHNkZpsPLEz_VNQ0hA,1
193
193
  zou/app/models/time_spent.py,sha256=n7i3FO9g1eE_zATkItoCgrGVqq3iMSfdlKSveEZPloc,795
194
194
  zou/app/models/working_file.py,sha256=q0LM3s1ziw_9AmmPDCkwyf1-TJkWTBMgo2LdHyVRwxg,1509
195
195
  zou/app/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
196
- zou/app/services/assets_service.py,sha256=Rnsd2BmHiTzS4qkWeqg3aUoP9IXweH8BCvXk5VVJKLs,24109
196
+ zou/app/services/assets_service.py,sha256=FFdZPIsabggBm9VW8u2QQrTVlWOG0cilAa8l8sflX5o,24272
197
197
  zou/app/services/auth_service.py,sha256=hQpNb21xlr5EiTrXnzpFb4W4GDtglubqA2z_-YIBfnk,22897
198
198
  zou/app/services/backup_service.py,sha256=_ZtZp6wkcVYnHxBosziwLGdrTvsUttXGphiydq53iy8,4840
199
199
  zou/app/services/base_service.py,sha256=OZd0STFh-DyBBdwsmA7DMMnrwv4C8wJUbShvZ1isndU,1383
200
200
  zou/app/services/breakdown_service.py,sha256=-bH1KUq9-No_OKnQtWK4XEU1w7uDPJnzWFMrKNkS1K0,27593
201
201
  zou/app/services/budget_service.py,sha256=uMU1vJr7kyxtkvMz_Nm7DyhW6qvSGYGqRHEQTxsHYCc,5468
202
202
  zou/app/services/chats_service.py,sha256=pqnT-RCltdf9Dp4t-2NtOSawGk0jyNhVPTgERZ_nYvk,8297
203
- zou/app/services/comments_service.py,sha256=-tCJ2BadALwbu9O3SXM1myrcUQW7j9UH-VjEMmsmza0,19968
203
+ zou/app/services/comments_service.py,sha256=BK4tQorV54M_fvsFIUfK3SS8flCleAK1piNkNxWOZ1s,22121
204
204
  zou/app/services/concepts_service.py,sha256=uH0leb23Op48wc1bHlUV2-I97QROsIemKr80F0UwnoM,11213
205
205
  zou/app/services/custom_actions_service.py,sha256=fWISEOOdthadrxeHuacEel5Xj6msn0yWXJQDG1gzvsY,297
206
- zou/app/services/deletion_service.py,sha256=AjLcsb91H8A-lw7j164VG8iX0EkKqwPdNhU5gOCAw_4,17225
206
+ zou/app/services/deletion_service.py,sha256=UPojg4oyyCKjUObfwv9nY6tD0SVDeimpv0xgbcSmyyk,17372
207
207
  zou/app/services/departments_service.py,sha256=7jLKH7ziToc6uHZsZKdBUzN2Ubi2YloHCX7PecE51LU,4596
208
208
  zou/app/services/edits_service.py,sha256=hfg6Fk9J9W41Qyw96UF35cSgbXqCYci6H8OY5rL_cIk,12075
209
209
  zou/app/services/emails_service.py,sha256=i9EP3zw02ZteVt9OZTvkfaoU19_T4kLhRmrhIvYw2SQ,11965
210
- zou/app/services/entities_service.py,sha256=TxQmtz1CTinMIlRS-N9bBGcHKfOoR_coI3uDjUfp1QM,17327
210
+ zou/app/services/entities_service.py,sha256=H9fMuRmrcS_ZxZ7vEo30m93UCRwXCKsIaPU7SYTgoK8,17792
211
211
  zou/app/services/events_service.py,sha256=Ew-bY5hqrWLmpbVj1_xd3E2S3JtyAGzdgw2XjudTZjc,2700
212
212
  zou/app/services/exception.py,sha256=VaQbvvv7yJ-lCFOlvAPKkYPuw7MjCaSAo1F40fS3kZ8,4478
213
213
  zou/app/services/file_tree_service.py,sha256=sz2Eq4S5VqEU7AupmKtRzX2W8ouUheTyYWkgiMf2G6o,33857
@@ -469,9 +469,9 @@ zou/remote/normalize_movie.py,sha256=zNfEY3N1UbAHZfddGONTg2Sff3ieLVWd4dfZa1dpnes
469
469
  zou/remote/playlist.py,sha256=AsDo0bgYhDcd6DfNRV6r6Jj3URWwavE2ZN3VkKRPbLU,3293
470
470
  zou/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
471
471
  zou/utils/movie.py,sha256=d67fIL9dVBKt-E_qCGXRbNNdbJaJR5sHvZeX3hf8ldE,16559
472
- zou-0.20.69.dist-info/licenses/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
473
- zou-0.20.69.dist-info/METADATA,sha256=euoOP9HxSUVc3eLPF6R2VQFAXLrlOO84cwqscoyc8hc,6697
474
- zou-0.20.69.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
475
- zou-0.20.69.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
476
- zou-0.20.69.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
477
- zou-0.20.69.dist-info/RECORD,,
472
+ zou-0.20.71.dist-info/licenses/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
473
+ zou-0.20.71.dist-info/METADATA,sha256=pvPX3HKiuHeJVLe8RDDanCYI9-nJ6Pol8ecJfPVMHFg,6697
474
+ zou-0.20.71.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
475
+ zou-0.20.71.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
476
+ zou-0.20.71.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
477
+ zou-0.20.71.dist-info/RECORD,,
File without changes