zou 0.20.38__py3-none-any.whl → 0.20.40__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.
Files changed (42) hide show
  1. zou/__init__.py +1 -1
  2. zou/app/api.py +38 -43
  3. zou/app/blueprints/crud/__init__.py +10 -0
  4. zou/app/blueprints/crud/budget.py +21 -0
  5. zou/app/blueprints/crud/budget_entry.py +15 -0
  6. zou/app/blueprints/crud/plugin.py +13 -0
  7. zou/app/blueprints/crud/salary_scale.py +73 -0
  8. zou/app/blueprints/playlists/resources.py +15 -0
  9. zou/app/blueprints/projects/__init__.py +17 -0
  10. zou/app/blueprints/projects/resources.py +402 -7
  11. zou/app/blueprints/shots/resources.py +1 -0
  12. zou/app/mixin.py +12 -1
  13. zou/app/models/budget.py +39 -0
  14. zou/app/models/budget_entry.py +65 -0
  15. zou/app/models/person.py +17 -1
  16. zou/app/models/plugin.py +21 -0
  17. zou/app/models/salary_scale.py +28 -0
  18. zou/app/services/budget_service.py +195 -0
  19. zou/app/services/comments_service.py +1 -1
  20. zou/app/services/exception.py +8 -0
  21. zou/app/services/plugins_service.py +169 -0
  22. zou/app/services/user_service.py +1 -3
  23. zou/app/utils/commands.py +51 -1
  24. zou/app/utils/fields.py +10 -0
  25. zou/app/utils/plugins.py +88 -0
  26. zou/cli.py +169 -1
  27. zou/event_stream.py +23 -5
  28. zou/migrations/versions/2762a797f1f9_add_people_salary_information.py +52 -0
  29. zou/migrations/versions/45f739ef962a_add_people_salary_scale_table.py +70 -0
  30. zou/migrations/versions/4aab1f84ad72_introduce_plugin_table.py +68 -0
  31. zou/migrations/versions/7a16258f2fab_add_currency_field_to_budgets.py +33 -0
  32. zou/migrations/versions/83e2f33a9b14_add_project_bugdet_table.py +57 -0
  33. zou/migrations/versions/8ab98c178903_add_budget_entry_table.py +123 -0
  34. zou/migrations/versions/d25118cddcaa_modify_salary_scale_model.py +133 -0
  35. zou/plugin_template/__init__.py +39 -0
  36. zou/plugin_template/routes.py +6 -0
  37. {zou-0.20.38.dist-info → zou-0.20.40.dist-info}/METADATA +7 -3
  38. {zou-0.20.38.dist-info → zou-0.20.40.dist-info}/RECORD +42 -22
  39. {zou-0.20.38.dist-info → zou-0.20.40.dist-info}/WHEEL +1 -1
  40. {zou-0.20.38.dist-info → zou-0.20.40.dist-info}/entry_points.txt +0 -0
  41. {zou-0.20.38.dist-info → zou-0.20.40.dist-info}/licenses/LICENSE +0 -0
  42. {zou-0.20.38.dist-info → zou-0.20.40.dist-info}/top_level.txt +0 -0
zou/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.20.38"
1
+ __version__ = "0.20.40"
zou/app/api.py CHANGED
@@ -1,9 +1,9 @@
1
1
  import os
2
2
  import sys
3
+ import importlib
4
+ import traceback
3
5
 
4
- from zou.app.utils import events, api as api_utils
5
-
6
- from flask import Blueprint
6
+ from pathlib import Path
7
7
 
8
8
  from zou.app.blueprints.assets import blueprint as assets_blueprint
9
9
  from zou.app.blueprints.auth import blueprint as auth_blueprint
@@ -29,6 +29,9 @@ from zou.app.blueprints.user import blueprint as user_blueprint
29
29
  from zou.app.blueprints.edits import blueprint as edits_blueprint
30
30
  from zou.app.blueprints.concepts import blueprint as concepts_blueprint
31
31
 
32
+ from zou.app.utils.plugins import PluginManifest
33
+ from zou.app.utils import events
34
+
32
35
 
33
36
  def configure(app):
34
37
  """
@@ -93,44 +96,36 @@ def register_event_handlers(app):
93
96
 
94
97
  def load_plugins(app):
95
98
  """
96
- Load plugin, (bunch of resources dedicated to a specific usage).
97
- """
98
- if os.path.exists(app.config["PLUGIN_FOLDER"]):
99
- plugins = load_plugin_modules(app.config["PLUGIN_FOLDER"])
100
- for plugin in plugins:
101
- load_plugin(app, plugin)
102
-
103
-
104
- def load_plugin_modules(plugin_folder):
105
- """
106
- Run Python import on all plugin listed in plugin folder. It returns the
107
- imported module.
108
- """
109
- sys.path.insert(0, plugin_folder)
110
- return [
111
- __import__(file_name)
112
- for file_name in os.listdir(plugin_folder)
113
- if os.path.isdir(os.path.join(plugin_folder, file_name))
114
- and file_name != "__pycache__"
115
- ]
116
-
117
-
118
- def load_plugin(app, plugin):
119
- """
120
- Load a given plugin as an API plugin: add configured routes to the API. It
121
- assumes that the plugin is already loaded in memory has a blueprint
122
- structure.
99
+ Load plugins from the plugin folder.
123
100
  """
124
- routes = [
125
- ("/plugins%s" % route_path, resource)
126
- for (route_path, resource) in plugin.routes
127
- if len(route_path) > 0 and route_path[0] == "/"
128
- ]
129
- plugin.routes = routes
130
- plugin.blueprint = Blueprint(plugin.name, plugin.name)
131
- plugin.api = api_utils.configure_api_from_blueprint(
132
- plugin.blueprint, plugin.routes
133
- )
134
- app.register_blueprint(plugin.blueprint)
135
- app.logger.info("Plugin %s loaded." % plugin.name)
136
- return plugin
101
+ plugin_folder = app.config["PLUGIN_FOLDER"]
102
+ abs_plugin_path = os.path.abspath(plugin_folder)
103
+ if abs_plugin_path not in sys.path:
104
+ sys.path.insert(0, abs_plugin_path)
105
+
106
+ if os.path.exists(plugin_folder):
107
+ for plugin_id in os.listdir(plugin_folder):
108
+ try:
109
+ load_plugin(app, plugin_id)
110
+ app.logger.info(f"Plugin {plugin_id} loaded.")
111
+ except ImportError as e:
112
+ app.logger.error(f"Plugin {plugin_id} failed to import: {e}")
113
+ except Exception as e:
114
+ app.logger.error(
115
+ f"Plugin {plugin_id} failed to initialize: {e}"
116
+ )
117
+ app.logger.debug(traceback.format_exc())
118
+
119
+ if abs_plugin_path in sys.path:
120
+ sys.path.remove(abs_plugin_path)
121
+
122
+
123
+ def load_plugin(app, plugin_id):
124
+ plugin_path = Path(app.config["PLUGIN_FOLDER"]) / plugin_id
125
+ manifest = PluginManifest.from_file(plugin_path / "manifest.toml")
126
+
127
+ plugin_module = importlib.import_module(plugin_id)
128
+ if hasattr(plugin_module, "init_plugin"):
129
+ plugin_module.init_plugin(app, manifest)
130
+
131
+ return plugin_module
@@ -129,6 +129,12 @@ from zou.app.blueprints.crud.chat_message import (
129
129
  ChatMessagesResource,
130
130
  )
131
131
  from zou.app.blueprints.crud.studio import StudioResource, StudiosResource
132
+ from zou.app.blueprints.crud.salary_scale import (
133
+ SalaryScalesResource,
134
+ SalaryScaleResource,
135
+ )
136
+
137
+ from zou.app.blueprints.crud.plugin import PluginResource, PluginsResource
132
138
 
133
139
  routes = [
134
140
  ("/data/persons", PersonsResource),
@@ -212,6 +218,10 @@ routes = [
212
218
  ),
213
219
  ("/data/studios", StudiosResource),
214
220
  ("/data/studios/<instance_id>", StudioResource),
221
+ ("/data/salary-scales", SalaryScalesResource),
222
+ ("/data/salary-scales/<instance_id>", SalaryScaleResource),
223
+ ("/data/plugins/<instance_id>", PluginResource),
224
+ ("/data/plugins", PluginsResource),
215
225
  ]
216
226
 
217
227
  blueprint = Blueprint("/data", "data")
@@ -0,0 +1,21 @@
1
+ from zou.app.blueprints.crud.base import BaseModelsResource, BaseModelResource
2
+
3
+ from zou.app.models.salary_scale import Budget
4
+
5
+
6
+ class BudgetsResource(BaseModelsResource):
7
+ def __init__(self):
8
+ BaseModelsResource.__init__(self, Budget)
9
+
10
+
11
+ class BudgetResource(BaseModelResource):
12
+ protected_fields = [
13
+ "id",
14
+ "created_at",
15
+ "updated_at",
16
+ "project_id",
17
+ "revision",
18
+ ]
19
+
20
+ def __init__(self):
21
+ BaseModelResource.__init__(self, Budget)
@@ -0,0 +1,15 @@
1
+ from zou.app.blueprints.crud.base import BaseModelsResource, BaseModelResource
2
+
3
+ from zou.app.models.salary_scale import BudgetEntry
4
+
5
+
6
+ class BudgetEntriesResource(BaseModelsResource):
7
+
8
+ def __init__(self):
9
+ BaseModelsResource.__init__(self, BudgetEntry)
10
+
11
+
12
+ class BudgetEntryResource(BaseModelResource):
13
+
14
+ def __init__(self):
15
+ BaseModelResource.__init__(self, BudgetEntry)
@@ -0,0 +1,13 @@
1
+ from zou.app.models.plugin import Plugin
2
+
3
+ from zou.app.blueprints.crud.base import BaseModelsResource, BaseModelResource
4
+
5
+
6
+ class PluginsResource(BaseModelsResource):
7
+ def __init__(self):
8
+ BaseModelsResource.__init__(self, Plugin)
9
+
10
+
11
+ class PluginResource(BaseModelResource):
12
+ def __init__(self):
13
+ BaseModelResource.__init__(self, Plugin)
@@ -0,0 +1,73 @@
1
+ from flask_jwt_extended import jwt_required
2
+
3
+ from zou.app.blueprints.crud.base import BaseModelsResource, BaseModelResource
4
+
5
+ from zou.app.services.exception import WrongParameterException
6
+
7
+ from zou.app.models.department import Department
8
+ from zou.app.models.salary_scale import SalaryScale
9
+
10
+
11
+ from zou.app.models.person import POSITION_TYPES, SENIORITY_TYPES
12
+
13
+
14
+ class SalaryScalesResource(BaseModelsResource):
15
+ def __init__(self):
16
+ BaseModelsResource.__init__(self, SalaryScale)
17
+
18
+ def check_creation_integrity(self, data):
19
+ raise WrongParameterException("Salary scales cannot be created")
20
+
21
+ @jwt_required()
22
+ def get(self):
23
+ """
24
+ Retrieve all salary scale entries.
25
+ ---
26
+ tags:
27
+ - Crud
28
+ description: Retrieve all salary scale entries.
29
+ responses:
30
+ 200:
31
+ description: All salary scale entries
32
+ 403:
33
+ description: Permission denied
34
+ """
35
+ self.check_read_permissions()
36
+ query = self.model.query
37
+
38
+ position_types = [position for position, _ in POSITION_TYPES]
39
+ seniority_types = [seniority for seniority, _ in SENIORITY_TYPES]
40
+
41
+ departments = Department.query.all()
42
+ salary_scales = SalaryScale.query.all()
43
+ salary_scale_map = {}
44
+ for salary_scale in salary_scales:
45
+ key = (
46
+ f"{salary_scale.department_id}-"
47
+ + f"{salary_scale.position.value.lower()}-"
48
+ + f"{salary_scale.seniority.value.lower()}"
49
+ )
50
+ salary_scale_map[key] = True
51
+
52
+ for department in departments:
53
+ for position in position_types:
54
+ for seniority in seniority_types:
55
+ key = (
56
+ f"{department.id}-"
57
+ + f"{position.lower()}-"
58
+ + f"{seniority.lower()}"
59
+ )
60
+ if key not in salary_scale_map:
61
+ SalaryScale.create(
62
+ department_id=department.id,
63
+ position=position,
64
+ seniority=seniority,
65
+ )
66
+ return self.all_entries(query)
67
+
68
+
69
+ class SalaryScaleResource(BaseModelResource):
70
+ protected_fields = ["id", "created_at", "updated_at", "department_id"]
71
+
72
+ def __init__(self):
73
+ BaseModelResource.__init__(self, SalaryScale)
@@ -42,6 +42,21 @@ class ProjectPlaylistsResource(Resource, ArgsMixin):
42
42
  type: string
43
43
  format: UUID
44
44
  x-example: a24a6ea4-ce75-4665-a070-57453082c25
45
+ - in: query
46
+ name: page
47
+ required: False
48
+ type: integer
49
+ x-example: 1
50
+ - in: query
51
+ name: sort_by
52
+ required: False
53
+ type: string
54
+ x-example: udpdated_at
55
+ - in: query
56
+ name: task_type_id
57
+ required: False
58
+ type: string
59
+ x-example: a24a6ea4-ce75-4665-a070-57453082c25
45
60
  responses:
46
61
  200:
47
62
  description: All playlists related to given project
@@ -26,6 +26,10 @@ from zou.app.blueprints.projects.resources import (
26
26
  ProductionEpisodesScheduleItemsResource,
27
27
  ProductionSequencesScheduleItemsResource,
28
28
  ProductionTimeSpentsResource,
29
+ ProductionBudgetsResource,
30
+ ProductionBudgetResource,
31
+ ProductionBudgetEntriesResource,
32
+ ProductionBudgetEntryResource,
29
33
  )
30
34
 
31
35
  routes = [
@@ -110,6 +114,19 @@ routes = [
110
114
  ProductionSequencesScheduleItemsResource,
111
115
  ),
112
116
  ("/data/projects/<project_id>/time-spents", ProductionTimeSpentsResource),
117
+ ("/data/projects/<project_id>/budgets", ProductionBudgetsResource),
118
+ (
119
+ "/data/projects/<project_id>/budgets/<budget_id>",
120
+ ProductionBudgetResource,
121
+ ),
122
+ (
123
+ "/data/projects/<project_id>/budgets/<budget_id>/entries",
124
+ ProductionBudgetEntriesResource,
125
+ ),
126
+ (
127
+ "/data/projects/<project_id>/budgets/<budget_id>/entries/<entry_id>",
128
+ ProductionBudgetEntryResource,
129
+ ),
113
130
  ]
114
131
 
115
132
  blueprint = Blueprint("projects", "projects")