zou 1.0.5__py3-none-any.whl → 1.0.6__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__ = "1.0.5"
1
+ __version__ = "1.0.6"
@@ -672,7 +672,7 @@ class PersonMonthAllTimeSpentsResource(Resource):
672
672
  )
673
673
  return fields.serialize_list(timespents)
674
674
  except WrongDateFormatException:
675
- abort(404)
675
+ raise WrongParameterException("Invalid month or year.")
676
676
 
677
677
 
678
678
  class PersonWeekTimeSpentsResource(PersonDurationTimeSpentsResource):
@@ -1160,10 +1160,12 @@ class TimeSpentMonthResource(TimeSpentDurationResource):
1160
1160
  schema:
1161
1161
  type: object
1162
1162
  """
1163
-
1164
- return time_spents_service.get_day_table(
1165
- year, month, **self.get_person_project_department_arguments()
1166
- )
1163
+ try:
1164
+ return time_spents_service.get_day_table(
1165
+ year, month, **self.get_person_project_department_arguments()
1166
+ )
1167
+ except WrongDateFormatException:
1168
+ raise WrongParameterException("Invalid month or year.")
1167
1169
 
1168
1170
 
1169
1171
  class TimeSpentYearsResource(TimeSpentDurationResource):
@@ -68,7 +68,7 @@ class BaseCsvImportResource(Resource, ArgsMixin):
68
68
  result = []
69
69
  self.check_permissions(*args)
70
70
  self.prepare_import(*args)
71
- with open(file_path) as csvfile:
71
+ with open(file_path, newline="", encoding="utf-8") as csvfile:
72
72
  reader = csv.DictReader(csvfile, dialect=self.get_dialect(csvfile))
73
73
  line_number = 1
74
74
  for row in reader:
@@ -94,9 +94,10 @@ class BaseCsvImportResource(Resource, ArgsMixin):
94
94
 
95
95
  def get_dialect(self, csvfile):
96
96
  sniffer = csv.Sniffer()
97
- dialect = sniffer.sniff(csvfile.read())
98
- dialect.doublequote = True
97
+ sample = csvfile.read(8192)
99
98
  csvfile.seek(0)
99
+ dialect = sniffer.sniff(sample)
100
+ dialect.doublequote = True
100
101
  return dialect
101
102
 
102
103
  def prepare_import(self, *args):
@@ -42,6 +42,7 @@ from zou.app.services.exception import (
42
42
  CommentNotFoundException,
43
43
  ModelWithRelationsDeletionException,
44
44
  PersonInProtectedAccounts,
45
+ PreviewFileNotFoundException,
45
46
  )
46
47
 
47
48
 
@@ -157,6 +158,8 @@ def remove_task(task_id, force=False):
157
158
 
158
159
  def remove_preview_file_by_id(preview_file_id, force=False):
159
160
  preview_file = PreviewFile.get(preview_file_id)
161
+ if preview_file is None:
162
+ raise PreviewFileNotFoundException
160
163
  return remove_preview_file(preview_file, force=force)
161
164
 
162
165
 
@@ -184,7 +184,10 @@ def get_time_spents_for_month(
184
184
  """
185
185
  Return all time spents for given month.
186
186
  """
187
- date = datetime.datetime(int(year), int(month), 1)
187
+ month_int = int(month)
188
+ if month_int < 1 or month_int > 12:
189
+ raise WrongDateFormatException
190
+ date = datetime.datetime(int(year), month_int, 1)
188
191
  next_month = date + relativedelta.relativedelta(months=1)
189
192
  query = TimeSpent.query.filter(TimeSpent.date >= date).filter(
190
193
  TimeSpent.date < next_month
@@ -1336,6 +1336,8 @@ def update_notification(notification_id, read):
1336
1336
  notification = Notification.get_by(
1337
1337
  id=notification_id, person_id=current_user["id"]
1338
1338
  )
1339
+ if notification is None:
1340
+ raise NotificationNotFoundException
1339
1341
  notification.update({"read": read})
1340
1342
  if read:
1341
1343
  events.emit(
@@ -47,11 +47,38 @@ def make_key(prefix, id):
47
47
 
48
48
 
49
49
  def make_read_generator(bucket, key):
50
+ """
51
+ Create a generator that yields chunks from the storage bucket.
52
+ This function ensures proper cleanup of the underlying stream to avoid
53
+ reentrant call errors when the stream is accessed concurrently.
54
+ """
50
55
  read_stream = bucket.read_chunks(key)
51
56
 
52
57
  def read_generator(read_stream):
53
- for chunk in read_stream:
54
- yield chunk
58
+ try:
59
+ for chunk in read_stream:
60
+ yield chunk
61
+ except GeneratorExit:
62
+ try:
63
+ if hasattr(read_stream, 'close'):
64
+ read_stream.close()
65
+ except Exception:
66
+ pass
67
+ raise
68
+ except StopIteration:
69
+ try:
70
+ if hasattr(read_stream, 'close'):
71
+ read_stream.close()
72
+ except Exception:
73
+ pass
74
+ raise
75
+ except Exception:
76
+ try:
77
+ if hasattr(read_stream, 'close'):
78
+ read_stream.close()
79
+ except Exception:
80
+ pass
81
+ raise
55
82
 
56
83
  return read_generator(read_stream)
57
84
 
zou/app/utils/fs.py CHANGED
@@ -57,20 +57,42 @@ def get_file_path_and_file(
57
57
  exception = None
58
58
  try:
59
59
  with open(file_path, "wb") as tmp_file:
60
- for chunk in open_file(prefix, instance_id):
61
- tmp_file.write(chunk)
62
- except:
60
+ file_generator = open_file(prefix, instance_id)
61
+ try:
62
+ for chunk in file_generator:
63
+ tmp_file.write(chunk)
64
+ finally:
65
+ try:
66
+ file_generator.close()
67
+ except StopIteration:
68
+ # Normal end of iteration, expected
69
+ pass
70
+ except Exception:
71
+ pass
72
+ except Exception as e:
63
73
  download_failed = True
74
+ exception = e
64
75
 
65
76
  if is_unvalid_file(
66
77
  file_path, file_size, download_failed
67
78
  ): # download failed
68
79
  time.sleep(3)
69
80
  download_failed = False
81
+ exception = None
70
82
  try:
71
83
  with open(file_path, "wb") as tmp_file:
72
- for chunk in open_file(prefix, instance_id):
73
- tmp_file.write(chunk)
84
+ file_generator = open_file(prefix, instance_id)
85
+ try:
86
+ for chunk in file_generator:
87
+ tmp_file.write(chunk)
88
+ finally:
89
+ try:
90
+ file_generator.close()
91
+ except StopIteration:
92
+ # Normal end of iteration, expected
93
+ pass
94
+ except Exception:
95
+ pass
74
96
  except Exception as e:
75
97
  download_failed = True
76
98
  exception = e
zou/app/utils/plugins.py CHANGED
@@ -371,7 +371,14 @@ def install_plugin_files(files_path, installation_path):
371
371
  installation_path.mkdir(parents=True, exist_ok=True)
372
372
 
373
373
  if files_path.is_dir():
374
- shutil.copytree(files_path, installation_path, dirs_exist_ok=True)
374
+ def ignore_git(dir, names):
375
+ ignored = []
376
+ if ".git" in names:
377
+ ignored.append(".git")
378
+ return ignored
379
+ shutil.copytree(
380
+ files_path, installation_path, dirs_exist_ok=True, ignore=ignore_git
381
+ )
375
382
  elif zipfile.is_zipfile(files_path):
376
383
  shutil.unpack_archive(files_path, installation_path, format="zip")
377
384
  else:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: zou
3
- Version: 1.0.5
3
+ Version: 1.0.6
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=B9kKWJLln1i8LjtkcYecvNWGLTrez4gCUOHtnPlInFo,22
1
+ zou/__init__.py,sha256=mqMuQB3aqJVPrHHqJMLjqiMKUiJjozc7EPLcX5DpKHg,22
2
2
  zou/cli.py,sha256=m2TcWtyPiPqBxTms3ndeLZ8L8tz3s74VKrB7NKga0ks,23141
3
3
  zou/debug.py,sha256=1fawPbkD4wn0Y9Gk0BiBFSa-CQe5agFi8R9uJYl2Uyk,520
4
4
  zou/event_stream.py,sha256=9O1PE_vDW8p3yfHJNSZ8w0ybD-660x8oGN0izgJdTjM,8575
@@ -95,7 +95,7 @@ zou/app/blueprints/index/resources.py,sha256=vCyW-LkLZacx3-E3kfbNfPTMHkgn7Tmhoha
95
95
  zou/app/blueprints/news/__init__.py,sha256=HxBXjC15dVbotNAZ0CLf02iwUjxJr20kgf8_kT_9nwM,505
96
96
  zou/app/blueprints/news/resources.py,sha256=FfYLp4PprTBZmpZ_vNV0K5RnBr2oAO49Llwr6InBaKA,12806
97
97
  zou/app/blueprints/persons/__init__.py,sha256=0cnHHw3K_8OEMm0qOi3wKVomSAg9IJSnVjAXabMeHks,3893
98
- zou/app/blueprints/persons/resources.py,sha256=-2FV1rDkMDtEvrUkbHdHFC7lTCoWRkxjIvSzAviwlwY,60634
98
+ zou/app/blueprints/persons/resources.py,sha256=ERYNS-B6m_O0h85BRz014zK6kQOjlMD2dCkDgIdin6w,60812
99
99
  zou/app/blueprints/playlists/__init__.py,sha256=gI6dV102RwsztOnUDk53BErYd9zrjA43gfNgGeYwfFU,1700
100
100
  zou/app/blueprints/playlists/resources.py,sha256=Ol0bQKcX4dtlduBaBD5OQm0jXMu-kqvO-YTLjw13a4A,29303
101
101
  zou/app/blueprints/previews/__init__.py,sha256=ihC6OQ9AUjnZ2JeMnjRh_tKGO0UmAjOwhZnOivc3BnQ,4460
@@ -111,7 +111,7 @@ zou/app/blueprints/source/kitsu.py,sha256=agVjvFh7isPpZJZgHVKebLQrD07YYm2yJo_ubf
111
111
  zou/app/blueprints/source/otio.py,sha256=7lpBO-WUZyBpR9l583Odlfjrm8XJG4emmB43T37mE-4,21161
112
112
  zou/app/blueprints/source/csv/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
113
113
  zou/app/blueprints/source/csv/assets.py,sha256=HiX3S1Qk-AJh8PGKc_BOUuxJc0sXkyqNSgRlnPuMV4Q,12421
114
- zou/app/blueprints/source/csv/base.py,sha256=1WcvpQv5FrJvE5nyRbJ1Nqrye4OgoTEBItYbHga-Uj4,4373
114
+ zou/app/blueprints/source/csv/base.py,sha256=o-DxUXgPmQpOU7fKdWnLrTsaFyWBJIDtKQ6iYAco004,4431
115
115
  zou/app/blueprints/source/csv/casting.py,sha256=jtNLJh_TMVjgZTW75oTzC_VfJVZerSSUxBiwGYzdFzU,7044
116
116
  zou/app/blueprints/source/csv/edits.py,sha256=aodUtzbPqmmf5GrB_06Ns-X4dEVybGDjUjeAGeEPHKE,9906
117
117
  zou/app/blueprints/source/csv/persons.py,sha256=uFyL2MR-M_eA7vpj2W4PChFJ-gnHED-3C-wyqz-hTjU,4043
@@ -203,7 +203,7 @@ zou/app/services/chats_service.py,sha256=pqnT-RCltdf9Dp4t-2NtOSawGk0jyNhVPTgERZ_
203
203
  zou/app/services/comments_service.py,sha256=cJ4K0GI8_VkCIBw4CLBW8bOrBOaG8Qj4EI4AcOZKAR8,22310
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=Wr0pcwvaT2PPGYwtv9Sd7dvTucvRsl7EWBaoIchDW-I,17929
206
+ zou/app/services/deletion_service.py,sha256=a2b7SFbkyAp1Ubl3HG5OAUt23dj0YnNqeeOGeAuX8IY,18035
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=6Ye4dUB_04XItdH6mynCERYP2Jj5wYTYrJQfir7slDA,14993
@@ -230,11 +230,11 @@ zou/app/services/sync_service.py,sha256=iWxx1kOGEXympHmSBBQWtDZWNtumdxp8kppee0Oe
230
230
  zou/app/services/tasks_service.py,sha256=34ozKuBjSKkirJJk3Wf6J-U3LrOWb3Oo1TqKvmAIJI8,70014
231
231
  zou/app/services/telemetry_services.py,sha256=xQm1h1t_JxSFW59zQGf4NuNdUi1UfMa_6pQ-ytRbmGA,1029
232
232
  zou/app/services/templates_service.py,sha256=vz4ACtLW-NZcLB-2uisQgGvU9vGFeIL9fUEaCULX8W0,38070
233
- zou/app/services/time_spents_service.py,sha256=CO3CXpGCNqOtBRxPo_H9tqEIrhCG7crFvgSkhAl1Vys,18634
234
- zou/app/services/user_service.py,sha256=h5SUU-Y6KJzAgEukWFCl8q8lpT1MKXtWp5yXXEl7eMk,54124
233
+ zou/app/services/time_spents_service.py,sha256=E-seu2vqmJJCyrZ2c1q4Q_ADEyV263lJmVGBvPHOv9E,18739
234
+ zou/app/services/user_service.py,sha256=Bv9o0L-WGu2nHFrMCh6vDZEHlkClw5Uk1xtJljHr1mM,54197
235
235
  zou/app/stores/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
236
236
  zou/app/stores/auth_tokens_store.py,sha256=-qOJPybLHvnMOq3PWk073OW9HJwOHGhFLZeOIlX1UVw,1290
237
- zou/app/stores/file_store.py,sha256=yLQDM6mNbj9oe0vsWdBqun7D8Dw-eSjD1yHCCftX0OI,4045
237
+ zou/app/stores/file_store.py,sha256=U_0YDIfvSvdA3fpsvEbavwQyT8cDCuORVhioBe33zQI,4906
238
238
  zou/app/stores/publisher_store.py,sha256=ggpb68i_wCfcuWicmxv8B1YPLXwHmcZo2reqcLnfV3E,1076
239
239
  zou/app/stores/queue_store.py,sha256=udbZSm3Rfwi-zwSRzVz-0qjdrVYbUWA8WwuIsdQikn8,669
240
240
  zou/app/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -253,12 +253,12 @@ zou/app/utils/events.py,sha256=czvaA4QeWIgroshpmonQCMmuq5O1XzIz08HfyLUq5T8,3213
253
253
  zou/app/utils/fido.py,sha256=Tlv5V4mDIbWiz93-gLh6i5p4PXBJWTLR3djR4ysT-PA,460
254
254
  zou/app/utils/fields.py,sha256=GTG6249Dz5pJUI1pcDPilzZqGkyPkAEyLpT3Gu2CfB0,3707
255
255
  zou/app/utils/flask.py,sha256=t0sC6yEDyzn-vCsijWzI9lpNWoxAYWfui25QtjQi_64,1822
256
- zou/app/utils/fs.py,sha256=EIRfKJXtHubVVi8FlDd9s9TcUok91LvRgU0l_B3Fq3w,3356
256
+ zou/app/utils/fs.py,sha256=pKDmMh0Tbz8XeStTxF83Ob7RS9aW8CNrO-auLssu0mE,4298
257
257
  zou/app/utils/git.py,sha256=MhmAYvEY-bXsnLvcHUW_NY5V636lJL3H-cdNrTHgLGk,114
258
258
  zou/app/utils/logs.py,sha256=lB6kyFmeANxCILUULLqGN8fuq9IY5FcbrVWmLdqWs2U,1404
259
259
  zou/app/utils/monitoring.py,sha256=XCpl0QshKD_tSok1vrIu9lB97JsvKLhvxJo3UyeqEoQ,2153
260
260
  zou/app/utils/permissions.py,sha256=Oq91C_lN6aGVCtCVUqQhijMQEjXOiMezbngpjybzzQk,3426
261
- zou/app/utils/plugins.py,sha256=BnLKQdExVt_LHhJreIQEIN_ntreZOBXDKh0AIrEfm6A,12834
261
+ zou/app/utils/plugins.py,sha256=Lie0Lm6Ax94m3o35vs_3xbYwDcFGPYwwuHXi1JxAuw0,13034
262
262
  zou/app/utils/query.py,sha256=q8ETGPAqnz0Pt9xWoQt5o7FFAVYUKVCJiWpwefIr-iU,4592
263
263
  zou/app/utils/redis.py,sha256=xXEh9pl-3qPbr89dKHvcXSUTC6hd77vv_N8PVcRRZTE,377
264
264
  zou/app/utils/remote_job.py,sha256=QPxcCWEv-NM1Q4IQawAyJAiSORwkMeOlByQb9OCShEw,2522
@@ -478,9 +478,9 @@ zou/remote/normalize_movie.py,sha256=zNfEY3N1UbAHZfddGONTg2Sff3ieLVWd4dfZa1dpnes
478
478
  zou/remote/playlist.py,sha256=AsDo0bgYhDcd6DfNRV6r6Jj3URWwavE2ZN3VkKRPbLU,3293
479
479
  zou/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
480
480
  zou/utils/movie.py,sha256=d67fIL9dVBKt-E_qCGXRbNNdbJaJR5sHvZeX3hf8ldE,16559
481
- zou-1.0.5.dist-info/licenses/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
482
- zou-1.0.5.dist-info/METADATA,sha256=GZdobpPCjsFUmKZk8nq-Vzcl3qKh7RK8wvnndW3q48E,6695
483
- zou-1.0.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
484
- zou-1.0.5.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
485
- zou-1.0.5.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
486
- zou-1.0.5.dist-info/RECORD,,
481
+ zou-1.0.6.dist-info/licenses/LICENSE,sha256=dql8h4yceoMhuzlcK0TT_i-NgTFNIZsgE47Q4t3dUYI,34520
482
+ zou-1.0.6.dist-info/METADATA,sha256=LdI3qxAVDqImAgb-fZY_A3jfQLGR7WR71T2wacVYx3Y,6695
483
+ zou-1.0.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
484
+ zou-1.0.6.dist-info/entry_points.txt,sha256=PelQoIx3qhQ_Tmne7wrLY-1m2izuzgpwokoURwSohy4,130
485
+ zou-1.0.6.dist-info/top_level.txt,sha256=4S7G_jk4MzpToeDItHGjPhHx_fRdX52zJZWTD4SL54g,4
486
+ zou-1.0.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5