zrb 0.22.0__py3-none-any.whl → 0.23.4__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 (25) hide show
  1. zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/README.md +84 -8
  2. zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/src/routes/+layout.svelte +1 -1
  3. zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/vite.config.ts +7 -1
  4. zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/app/__init__.py +0 -0
  5. zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/{app.py → app/app.py} +2 -1
  6. zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/{app_lifespan.py → app/app_lifespan.py} +1 -1
  7. zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/main.py +1 -3
  8. zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/register_module.py +1 -1
  9. zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/log/register_module.py +1 -1
  10. zrb/builtin/project/add/fastapp/crud/crud.py +15 -3
  11. zrb/builtin/project/add/fastapp/field/_helper.py +15 -29
  12. zrb/builtin/project/add/fastapp/field/field.py +63 -65
  13. zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/src/module/snake_zrb_module_name/register_module.py +1 -1
  14. zrb/helper/file/copy_tree.py +26 -10
  15. zrb/helper/string/parse_replacement.py +7 -0
  16. zrb/task/base_remote_cmd_task.py +5 -1
  17. zrb/task/cmd_task.py +11 -3
  18. zrb/task/docker_compose_task.py +3 -1
  19. zrb/task_input/multiline_input.py +1 -1
  20. {zrb-0.22.0.dist-info → zrb-0.23.4.dist-info}/METADATA +3 -3
  21. {zrb-0.22.0.dist-info → zrb-0.23.4.dist-info}/RECORD +25 -24
  22. /zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/{app_state.py → app/app_state.py} +0 -0
  23. {zrb-0.22.0.dist-info → zrb-0.23.4.dist-info}/LICENSE +0 -0
  24. {zrb-0.22.0.dist-info → zrb-0.23.4.dist-info}/WHEEL +0 -0
  25. {zrb-0.22.0.dist-info → zrb-0.23.4.dist-info}/entry_points.txt +0 -0
@@ -132,12 +132,81 @@ If you want to run PascalZrbAppName on containers, you will also need `Docker` w
132
132
 
133
133
  You will also need `Pulumi` if you want to deploy PascalZrbAppName into your Kubernetes cluster.
134
134
 
135
+ # High Level Architecture
136
+
137
+ PascalZrbAppName heavily uses dependency inversion and avoids dependency injection on the same time.
138
+
139
+ This architecture aims to let the developers define and choose new implementations without breaking any existing part.
140
+
141
+ To achieve this, we use two elements:
142
+
143
+ - __Component__: Containing interface and implementation
144
+ - __Integration__: Instantiation of the components. Here is where you choose which component implementation to use and how we tailor the implementations.
145
+
146
+ Let's see the following example.
147
+
148
+ ```
149
+ ┌────────────────────────────────────────────┐
150
+ │ Component │
151
+ │ ┌───────────────┐ ┌────────────────┐ │
152
+ │ │ Messagebus │ │ RPC Caller │ │
153
+ │ │ ┌────────┐ │ │ ┌──────────┐ │ │
154
+ │ │ │Kafka │ ├─────┼──►│Messagebus├─┼─┼────┐
155
+ │ │ └────────┘ │ │ └──────────┘ │ │ │
156
+ │ │ ┌────────┐ │ │ ┌──────────┐ │ │ │
157
+ ┌──┼───┼───┤Rabbitmq│ │ │ │Grpc │ │ │ │
158
+ │ │ │ └────────┘ │ │ └──────────┘ │ │ │
159
+ │ │ │ ┌────────┐ │ └────────────────┘ │ │
160
+ │ │ │ │Other │ ├──┐ │ │
161
+ │ │ │ └────────┘ │ │ ┌────────────────┐ │ │
162
+ │ │ └───────────────┘ │ │ RPC Server │ │ │
163
+ │ │ │ │ ┌──────────┐ │ │ │
164
+ │ │ └──┼──►│Messagebus├─┼─┼─┐ │
165
+ │ │ │ └──────────┘ │ │ │ │
166
+ │ │ │ ┌──────────┐ │ │ │ │
167
+ │ │ │ │Grpc │ │ │ │ │
168
+ │ │ │ └──────────┘ │ │ │ │
169
+ │ │ └────────────────┘ │ │ │
170
+ │ └────────────────────────────────────────────┘ │ │
171
+ │ │ │
172
+ │ ┌────────────────────────────────────────────┐ │ │
173
+ │ │ Integration │ │ │
174
+ │ │ ┌──────────┐ │ │ │
175
+ └──┼─►│Messagebus├───────┬──────────────┐ │ │ │
176
+ │ └──────────┘ │ │ │ │ │
177
+ │ ┌────▼─────┐ ┌─────▼────┐ │ │ │
178
+ │ │RPC Caller│ │RPC Server│◄─┼─┘ │
179
+ │ └────▲─────┘ └──────────┘ │ │
180
+ └─────────────────────┼──────────────────────┘ │
181
+ └───────────────────────────┘
182
+ ```
183
+
184
+ __Components__
185
+
186
+ In the example, there are three component interfaces:
187
+ - `Messagebus`
188
+ - `RPC Caller`
189
+ - `RPC Server`
190
+
191
+ Each interface has several implementations, for example there are two implementation of `RPC Caller`:
192
+ - `RPCCaller.Messagebus`: RPC Caller implementation that need `Messagebus`.
193
+ - `RPCCaller.Grpc`: RPC Caller through GRPC, doesn't need any other component.
194
+
195
+ __Integration__
196
+
197
+ As for integration, we need to choose particular component implementations.
198
+
199
+ - `Messagebus`: For Messagebus, we choose `Messagebus.Rabbitmq` component.
200
+ - `RPC Caller`: For RPC Caller, we choose `RPCCaller.Messasgebus`. This implementation need a `Messagebus` interface.
201
+ - `RPC Server`: For RPC Server, we choose `RPCServer.Messasgebus`. This implementation need a `Messagebus` interface.
202
+
203
+
135
204
  # Directory Structure
136
205
 
137
206
  - `docker-compose.yml`: A multi-profile docker-compose file. This helps you to run your application as a monolith/microservices.
138
207
  - `all-module-disabled.env`: Feature flags to be used when you deactivate all modules.
139
208
  - `all-module-enabled.env`: Feature flags to be used when you activate all modules.
140
- - `deployment/`: Deployment directory. By default, we put deployment along with the source code to make it easier to maintain/manage. You can later move your deployments to another repository if you think you need to.
209
+ - `deployment/`: Deployment directory. By default, we put deployment along with the source code to make it easier to maintain/manage. You can later move your deployments to another repository if you need to do so.
141
210
  - `/helm-charts`: Helm charts for Rabbitmq, Redpanda, and Postgre.
142
211
  - `__main__.py`: Main Pulumi script.
143
212
  - `template.env`: Default configuration for deployment
@@ -187,12 +256,19 @@ You will also need `Pulumi` if you want to deploy PascalZrbAppName into your Kub
187
256
 
188
257
  # Decisions and Constraints
189
258
 
259
+ ## Dependency Inversion without Dependency Injection
260
+
261
+ We tend to avoid magical dependency inversion unless necessary. We want PascalZrbEntityName to be as explicit as possible. We do this by providing two elements:
262
+
263
+ - Component: Containing all interfaces and implementations
264
+ - Integration: Instantiation of components. This is where we choose and tailor the component's implementation.
265
+
190
266
  ## Frontend
191
- - PascalZrbAppName's Frontend is served as static files and is built before runtime (not SSR/Server Side Rendering). That's mean.
267
+ PascalZrbAppName's front end serves static files built before runtime (not SSR/Server Side Rendering). That's mean.
192
268
  - The SEO is probably not good.
193
269
  - The page load is sensibly good.
194
270
  - We use Svelte for Frontend because it is easier to read/learn compared to React, Vue, or Angular.
195
- - At the moment, the frontend use:
271
+ - At the moment, the front end use:
196
272
  - Sveltekit
197
273
  - TailwindCSS
198
274
  - DaisyUI
@@ -203,7 +279,7 @@ You will also need `Pulumi` if you want to deploy PascalZrbAppName into your Kub
203
279
  - Database connection
204
280
  - Database migration
205
281
  - Data manipulation
206
- - To create a custom database implementation, you need to create an implementation that complies with `core.repo.Repo`.
282
+ - To create a custom database implementation, you must create one that complies with `core.repo.Repo`.
207
283
 
208
284
  ## Messaging
209
285
 
@@ -215,11 +291,11 @@ You will also need `Pulumi` if you want to deploy PascalZrbAppName into your Kub
215
291
  - No messaging platform, a.k.a: in memory. This will only work properly if you run PascalZrbAppName as a monolith.
216
292
  - `APP_BROKER_TYPE=mock`
217
293
  - To create custom event handlers, you need to implement two interfaces:
218
- - `core.messagebus.Publisher`
219
- - `core.messagebus.Server`
294
+ - `component.messagebus.Publisher`
295
+ - `component.messagebus.Server`
220
296
 
221
297
  ## RPC
222
298
 
223
299
  - Currently, RPC implementation depends on the messaging platforms. It is possible to override this behavior by creating you custom implementation. There are two interfaces you need to override:
224
- - `core.rpc.Caller`
225
- - `core.rpc.Server`
300
+ - `component.rpc.Caller`
301
+ - `component.rpc.Server`
@@ -3,7 +3,7 @@
3
3
  import Navigation from '$lib/components/navigation/Navigation.svelte';
4
4
  import { navData } from '$lib/config/navData';
5
5
  import { getBrand, getTitle } from '$lib/config/app';
6
- import logo from '/static/logo.png';
6
+ import logo from '@static/logo.png';
7
7
  import "../app.css";
8
8
 
9
9
  let appBrand = '';
@@ -1,9 +1,15 @@
1
1
  import { sveltekit } from '@sveltejs/kit/vite';
2
2
  import { defineConfig } from 'vitest/config';
3
+ import path from 'path';
3
4
 
4
5
  export default defineConfig({
5
6
  plugins: [sveltekit()],
6
7
  test: {
7
8
  include: ['src/**/*.{test,spec}.{js,ts}']
8
- }
9
+ },
10
+ resolve: {
11
+ alias: {
12
+ '@static': path.resolve(__dirname, 'static'),
13
+ },
14
+ },
9
15
  });
@@ -16,7 +16,8 @@ from config import (
16
16
  from fastapi import FastAPI, status
17
17
  from fastapi.middleware.cors import CORSMiddleware
18
18
  from fastapi.responses import JSONResponse
19
- from integration.app_lifespan import app_lifespan, app_state
19
+ from integration.app.app_lifespan import app_lifespan
20
+ from integration.app.app_state import app_state
20
21
  from integration.frontend_index import frontend_index_response
21
22
  from schema.frontend_config import FrontendConfig
22
23
 
@@ -12,7 +12,7 @@ from config import (
12
12
  from fastapi import FastAPI
13
13
  from fastapi.staticfiles import StaticFiles
14
14
  from helper.async_task import create_task
15
- from integration.app_state import app_state, set_not_ready_on_error
15
+ from integration.app.app_state import app_state, set_not_ready_on_error
16
16
  from integration.log import logger
17
17
  from integration.messagebus import consumer
18
18
  from integration.rpc import rpc_server
@@ -1,9 +1,7 @@
1
- from integration.app import app
1
+ from integration.app.app import app
2
2
  from module.auth.register_module import register_auth
3
3
  from module.log.register_module import register_log
4
4
 
5
- # Make sure app is loaded.
6
- # Uvicorn or adny ASGII server you use will pick it up and run the app.
7
5
  assert app
8
6
  register_auth()
9
7
  register_log()
@@ -4,7 +4,7 @@ from config import (
4
4
  app_enable_event_handler,
5
5
  app_enable_rpc_server,
6
6
  )
7
- from integration.app import app
7
+ from integration.app.app import app
8
8
  from integration.log import logger
9
9
  from integration.messagebus import consumer, publisher
10
10
  from integration.rpc import rpc_caller, rpc_server
@@ -4,7 +4,7 @@ from config import (
4
4
  app_enable_log_module,
5
5
  app_enable_rpc_server,
6
6
  )
7
- from integration.app import app
7
+ from integration.app.app import app
8
8
  from integration.log import logger
9
9
  from integration.messagebus import consumer, publisher
10
10
  from integration.rpc import rpc_caller, rpc_server
@@ -113,17 +113,29 @@ async def register_crud(*args: Any, **kwargs: Any):
113
113
  await asyncio.gather(
114
114
  asyncio.create_task(
115
115
  register_api(
116
- task, project_dir, kebab_app_name, snake_module_name, snake_entity_name
116
+ task=task,
117
+ project_dir=project_dir,
118
+ kebab_app_name=kebab_app_name,
119
+ snake_module_name=snake_module_name,
120
+ snake_entity_name=snake_entity_name,
117
121
  )
118
122
  ),
119
123
  asyncio.create_task(
120
124
  register_rpc(
121
- task, project_dir, kebab_app_name, snake_module_name, snake_entity_name
125
+ task=task,
126
+ project_dir=project_dir,
127
+ kebab_app_name=kebab_app_name,
128
+ snake_module_name=snake_module_name,
129
+ snake_entity_name=snake_entity_name,
122
130
  )
123
131
  ),
124
132
  asyncio.create_task(
125
133
  register_permission(
126
- task, project_dir, kebab_app_name, snake_module_name, snake_entity_name
134
+ task=task,
135
+ project_dir=project_dir,
136
+ kebab_app_name=kebab_app_name,
137
+ snake_module_name=snake_module_name,
138
+ snake_entity_name=snake_entity_name,
127
139
  )
128
140
  ),
129
141
  )
@@ -17,7 +17,7 @@ async def add_column_to_insert_page(
17
17
  kebab_entity_name: str,
18
18
  kebab_column_name: str,
19
19
  snake_column_name: str,
20
- capitalized_human_readable_column_name: str,
20
+ column_caption: str,
21
21
  ):
22
22
  list_page_file_path = os.path.join(
23
23
  project_dir,
@@ -45,11 +45,8 @@ async def add_column_to_insert_page(
45
45
  field_subst = "\\n".join(
46
46
  [
47
47
  '\\1<div class="mb-4">',
48
- f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{capitalized_human_readable_column_name}</label>', # noqa
49
- f'\\1 <input type="text" class="input w-full" id="{kebab_column_name}" placeholder="{capitalized_human_readable_column_name}" bind:value='
50
- + "{row."
51
- + snake_column_name
52
- + "} />", # noqa
48
+ f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{column_caption}</label>', # noqa
49
+ f'\\1 <input type="text" class="input w-full" id="{kebab_column_name}" placeholder="{column_caption}" bind:value="{{row.{snake_column_name}}}" />', # noqa
53
50
  "\\1</div>",
54
51
  "\\1\\2",
55
52
  ]
@@ -68,7 +65,7 @@ async def add_column_to_update_page(
68
65
  kebab_entity_name: str,
69
66
  kebab_column_name: str,
70
67
  snake_column_name: str,
71
- capitalized_human_readable_column_name: str,
68
+ column_caption: str,
72
69
  ):
73
70
  list_page_file_path = os.path.join(
74
71
  project_dir,
@@ -91,11 +88,8 @@ async def add_column_to_update_page(
91
88
  subst = "\\n".join(
92
89
  [
93
90
  '\\1<div class="mb-4">',
94
- f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{capitalized_human_readable_column_name}</label>', # noqa
95
- f'\\1 <input type="text" class="input w-full" id="{kebab_column_name}" placeholder="{capitalized_human_readable_column_name}" bind:value='
96
- + "{row."
97
- + snake_column_name
98
- + "} />", # noqa
91
+ f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{column_caption}</label>', # noqa
92
+ f'\\1 <input type="text" class="input w-full" id="{kebab_column_name}" placeholder="{column_caption}" bind:value="{{row.{snake_column_name}}}" />', # noqa
99
93
  "\\1</div>",
100
94
  "\\1\\2",
101
95
  ]
@@ -114,7 +108,7 @@ async def add_column_to_delete_page(
114
108
  kebab_entity_name: str,
115
109
  kebab_column_name: str,
116
110
  snake_column_name: str,
117
- capitalized_human_readable_column_name: str,
111
+ column_caption: str,
118
112
  ):
119
113
  list_page_file_path = os.path.join(
120
114
  project_dir,
@@ -137,11 +131,8 @@ async def add_column_to_delete_page(
137
131
  subst = "\\n".join(
138
132
  [
139
133
  '\\1<div class="mb-4">',
140
- f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{capitalized_human_readable_column_name}</label>', # noqa
141
- f'\\1 <span id="{kebab_column_name}">'
142
- + "{row."
143
- + snake_column_name
144
- + "}</span>", # noqa
134
+ f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{column_caption}</label>', # noqa
135
+ f'\\1 <span id="{kebab_column_name}">{{row.{snake_column_name}}}</span>',
145
136
  "\\1</div>",
146
137
  "\\1\\2",
147
138
  ]
@@ -160,7 +151,7 @@ async def add_column_to_detail_page(
160
151
  kebab_entity_name: str,
161
152
  kebab_column_name: str,
162
153
  snake_column_name: str,
163
- capitalized_human_readable_column_name: str,
154
+ column_caption: str,
164
155
  ):
165
156
  list_page_file_path = os.path.join(
166
157
  project_dir,
@@ -183,11 +174,8 @@ async def add_column_to_detail_page(
183
174
  subst = "\\n".join(
184
175
  [
185
176
  '\\1<div class="mb-4">',
186
- f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{capitalized_human_readable_column_name}</label>', # noqa
187
- f'\\1 <span id="{kebab_column_name}">'
188
- + "{row."
189
- + snake_column_name
190
- + "}</span>", # noqa
177
+ f'\\1 <label class="block text-gray-700 font-bold mb-2" for="{kebab_column_name}">{column_caption}</label>', # noqa
178
+ f'\\1 <span id="{kebab_column_name}">{{row.{snake_column_name}}}</span>',
191
179
  "\\1</div>",
192
180
  "\\1\\2",
193
181
  ]
@@ -205,7 +193,7 @@ async def add_column_to_list_page(
205
193
  kebab_module_name: str,
206
194
  kebab_entity_name: str,
207
195
  snake_column_name: str,
208
- capitalized_human_readable_column_name: str,
196
+ column_caption: str,
209
197
  ):
210
198
  list_page_file_path = os.path.join(
211
199
  project_dir,
@@ -224,14 +212,12 @@ async def add_column_to_list_page(
224
212
  # process header
225
213
  task.print_out("Add column header to table")
226
214
  header_regex = r"(.*)(<!-- DON'T DELETE: insert new column header here-->)"
227
- header_subst = "\\n".join(
228
- [f"\\1<th>{capitalized_human_readable_column_name}</th>", "\\1\\2"]
229
- )
215
+ header_subst = "\\n".join([f"\\1<th>{column_caption}</th>", "\\1\\2"])
230
216
  html_content = re.sub(header_regex, header_subst, html_content, 0, re.MULTILINE)
231
217
  # process column
232
218
  task.print_out("Add column to table")
233
219
  column_regex = r"(.*)(<!-- DON'T DELETE: insert new column here-->)"
234
- column_subst = "\\n".join(["\\1<td>{row." + snake_column_name + "}</td>", "\\1\\2"])
220
+ column_subst = "\\n".join([f"\\1<td>{{row.{snake_column_name}}}</td>", "\\1\\2"])
235
221
  html_content = re.sub(column_regex, column_subst, html_content, 0, re.MULTILINE)
236
222
  task.print_out(f"Write modified HTML to: {list_page_file_path}")
237
223
  await write_text_file_async(list_page_file_path, html_content)
@@ -89,102 +89,100 @@ async def add_fastapp_field(*args: Any, **kwargs: Any):
89
89
  pascal_entity_name = util.to_pascal_case(entity_name)
90
90
  snake_column_name = util.to_snake_case(column_name)
91
91
  kebab_column_name = util.to_kebab_case(column_name)
92
- capitalized_human_readable_column_name = util.to_capitalized_human_readable( # noqa
93
- column_name
94
- )
92
+ column_caption = util.to_capitalized_human_readable(column_name)
95
93
  await asyncio.gather(
96
94
  asyncio.create_task(
97
95
  add_column_to_test(
98
- task,
99
- project_dir,
100
- kebab_app_name,
101
- snake_module_name,
102
- snake_entity_name,
103
- snake_column_name,
104
- column_type,
96
+ task=task,
97
+ project_dir=project_dir,
98
+ kebab_app_name=kebab_app_name,
99
+ snake_module_name=snake_module_name,
100
+ snake_entity_name=snake_entity_name,
101
+ snake_column_name=snake_column_name,
102
+ column_type=column_type,
105
103
  )
106
104
  ),
107
105
  asyncio.create_task(
108
106
  add_column_to_schema(
109
- task,
110
- project_dir,
111
- kebab_app_name,
112
- snake_module_name,
113
- snake_entity_name,
114
- pascal_entity_name,
115
- snake_column_name,
116
- column_type,
107
+ task=task,
108
+ project_dir=project_dir,
109
+ kebab_app_name=kebab_app_name,
110
+ snake_module_name=snake_module_name,
111
+ snake_entity_name=snake_entity_name,
112
+ pascal_entity_name=pascal_entity_name,
113
+ snake_column_name=snake_column_name,
114
+ column_type=column_type,
117
115
  )
118
116
  ),
119
117
  asyncio.create_task(
120
118
  add_column_to_repo(
121
- task,
122
- project_dir,
123
- kebab_app_name,
124
- snake_module_name,
125
- snake_entity_name,
126
- pascal_entity_name,
127
- snake_column_name,
128
- column_type,
119
+ task=task,
120
+ project_dir=project_dir,
121
+ kebab_app_name=kebab_app_name,
122
+ snake_module_name=snake_module_name,
123
+ snake_entity_name=snake_entity_name,
124
+ pascal_entity_name=pascal_entity_name,
125
+ snake_column_name=snake_column_name,
126
+ column_type=column_type,
129
127
  )
130
128
  ),
131
129
  asyncio.create_task(
132
130
  add_column_to_list_page(
133
- task,
134
- project_dir,
135
- kebab_app_name,
136
- kebab_module_name,
137
- kebab_entity_name,
138
- snake_column_name,
139
- capitalized_human_readable_column_name,
131
+ task=task,
132
+ project_dir=project_dir,
133
+ kebab_app_name=kebab_app_name,
134
+ kebab_module_name=kebab_module_name,
135
+ kebab_entity_name=kebab_entity_name,
136
+ snake_column_name=snake_column_name,
137
+ column_caption=column_caption,
140
138
  )
141
139
  ),
142
140
  asyncio.create_task(
143
141
  add_column_to_detail_page(
144
- task,
145
- project_dir,
146
- kebab_app_name,
147
- kebab_module_name,
148
- kebab_entity_name,
149
- kebab_column_name,
150
- snake_column_name,
151
- capitalized_human_readable_column_name,
142
+ task=task,
143
+ project_dir=project_dir,
144
+ kebab_app_name=kebab_app_name,
145
+ kebab_module_name=kebab_module_name,
146
+ kebab_entity_name=kebab_entity_name,
147
+ kebab_column_name=kebab_column_name,
148
+ snake_column_name=snake_column_name,
149
+ column_caption=column_caption,
152
150
  )
153
151
  ),
154
152
  asyncio.create_task(
155
153
  add_column_to_delete_page(
156
- task,
157
- project_dir,
158
- kebab_app_name,
159
- kebab_module_name,
160
- kebab_entity_name,
161
- kebab_column_name,
162
- snake_column_name,
163
- capitalized_human_readable_column_name,
154
+ task=task,
155
+ project_dir=project_dir,
156
+ kebab_app_name=kebab_app_name,
157
+ kebab_module_name=kebab_module_name,
158
+ kebab_entity_name=kebab_entity_name,
159
+ kebab_column_name=kebab_column_name,
160
+ snake_column_name=snake_column_name,
161
+ column_caption=column_caption,
164
162
  )
165
163
  ),
166
164
  asyncio.create_task(
167
165
  add_column_to_update_page(
168
- task,
169
- project_dir,
170
- kebab_app_name,
171
- kebab_module_name,
172
- kebab_entity_name,
173
- kebab_column_name,
174
- snake_column_name,
175
- capitalized_human_readable_column_name,
166
+ task=task,
167
+ project_dir=project_dir,
168
+ kebab_app_name=kebab_app_name,
169
+ kebab_module_name=kebab_module_name,
170
+ kebab_entity_name=kebab_entity_name,
171
+ kebab_column_name=kebab_column_name,
172
+ snake_column_name=snake_column_name,
173
+ column_caption=column_caption,
176
174
  )
177
175
  ),
178
176
  asyncio.create_task(
179
177
  add_column_to_insert_page(
180
- task,
181
- project_dir,
182
- kebab_app_name,
183
- kebab_module_name,
184
- kebab_entity_name,
185
- kebab_column_name,
186
- snake_column_name,
187
- capitalized_human_readable_column_name,
178
+ task=task,
179
+ project_dir=project_dir,
180
+ kebab_app_name=kebab_app_name,
181
+ kebab_module_name=kebab_module_name,
182
+ kebab_entity_name=kebab_entity_name,
183
+ kebab_column_name=kebab_column_name,
184
+ snake_column_name=snake_column_name,
185
+ column_caption=column_caption,
188
186
  )
189
187
  ),
190
188
  )
@@ -4,7 +4,7 @@ from config import (
4
4
  app_enable_rpc_server,
5
5
  app_enable_snake_zrb_module_name_module,
6
6
  )
7
- from integration.app import app
7
+ from integration.app.app import app
8
8
  from integration.log import logger
9
9
  from integration.messagebus import consumer, publisher
10
10
  from integration.rpc import rpc_caller, rpc_server
@@ -26,6 +26,9 @@ async def copy_tree(
26
26
  excludes = []
27
27
  if skip_parsing is None:
28
28
  skip_parsing = []
29
+ if os.path.isfile(src):
30
+ await _copy_file(src, dst, replacements, excludes, skip_parsing)
31
+ return
29
32
  names = os.listdir(src)
30
33
  new_dst = parse_replacement(dst, replacements)
31
34
  if not os.path.exists(new_dst):
@@ -38,13 +41,26 @@ async def copy_tree(
38
41
  if os.path.isdir(src_name):
39
42
  await copy_tree(src_name, dst_name, replacements, excludes, skip_parsing)
40
43
  continue
41
- new_dst_name = parse_replacement(dst_name, replacements)
42
- shutil.copy2(src_name, new_dst_name)
43
- try:
44
- if any(fnmatch.fnmatch(new_dst_name, pattern) for pattern in skip_parsing):
45
- continue
46
- file_content = await read_text_file_async(new_dst_name)
47
- new_file_content = parse_replacement(file_content, replacements)
48
- await write_text_file_async(new_dst_name, new_file_content)
49
- except Exception:
50
- logger.error(f"Cannot parse file: {new_dst_name}")
44
+ await _copy_file(src_name, dst_name, replacements, excludes, skip_parsing)
45
+
46
+
47
+ async def _copy_file(
48
+ src: str,
49
+ dst: str,
50
+ replacements: Optional[Mapping[str, str]] = None,
51
+ excludes: Optional[Iterable[str]] = None,
52
+ skip_parsing: Optional[Iterable[str]] = None,
53
+ ):
54
+ if any(fnmatch.fnmatch(src, pattern) for pattern in excludes):
55
+ return
56
+ new_dst_name = parse_replacement(dst, replacements)
57
+ if new_dst_name != src:
58
+ shutil.copy2(src, new_dst_name)
59
+ if any(fnmatch.fnmatch(new_dst_name, pattern) for pattern in skip_parsing):
60
+ return
61
+ try:
62
+ file_content = await read_text_file_async(new_dst_name)
63
+ new_file_content = parse_replacement(file_content, replacements)
64
+ await write_text_file_async(new_dst_name, new_file_content)
65
+ except Exception:
66
+ logger.error(f"Cannot parse file: {new_dst_name}")
@@ -1,3 +1,5 @@
1
+ import re
2
+
1
3
  from zrb.helper.accessories.color import colored
2
4
  from zrb.helper.log import logger
3
5
  from zrb.helper.typecheck import typechecked
@@ -10,5 +12,10 @@ logger.debug(colored("Loading zrb.helper.string.parse_replacment", attrs=["dark"
10
12
  def parse_replacement(text: str, replacement: Mapping[str, str]):
11
13
  new_text = text
12
14
  for old, new in replacement.items():
15
+ if len(new.strip().split("\n")) > 1:
16
+ pattern = "".join(["^([ \\t]+)", re.escape(old)])
17
+ new_replacement = "".join(["\\1", new.replace("\n", "\n\\1")])
18
+ new_text = re.sub(pattern, new_replacement, new_text, flags=re.MULTILINE)
19
+ continue
13
20
  new_text = new_text.replace(old, new)
14
21
  return new_text
@@ -82,6 +82,7 @@ class SingleBaseRemoteCmdTask(CmdTask):
82
82
  post_cmd: CmdVal = "",
83
83
  post_cmd_path: CmdVal = "",
84
84
  cwd: Optional[Union[str, pathlib.Path]] = None,
85
+ should_render_cwd: bool = True,
85
86
  upstreams: Iterable[AnyTask] = [],
86
87
  fallbacks: Iterable[AnyTask] = [],
87
88
  on_triggered: Optional[OnTriggered] = None,
@@ -118,6 +119,7 @@ class SingleBaseRemoteCmdTask(CmdTask):
118
119
  cmd=cmd,
119
120
  cmd_path=cmd_path,
120
121
  cwd=cwd,
122
+ should_render_cwd=should_render_cwd,
121
123
  upstreams=upstreams,
122
124
  fallbacks=fallbacks,
123
125
  on_triggered=on_triggered,
@@ -226,7 +228,8 @@ class BaseRemoteCmdTask(BaseTask):
226
228
  cmd_path: CmdVal = "",
227
229
  post_cmd: CmdVal = "",
228
230
  post_cmd_path: CmdVal = "",
229
- cwd: Optional[Union[str, pathlib.Path]] = None,
231
+ cwd: Optional[Union[JinjaTemplate, pathlib.Path]] = None,
232
+ should_render_cwd: bool = True,
230
233
  upstreams: Iterable[AnyTask] = [],
231
234
  fallbacks: Iterable[AnyTask] = [],
232
235
  on_triggered: Optional[OnTriggered] = None,
@@ -266,6 +269,7 @@ class BaseRemoteCmdTask(BaseTask):
266
269
  post_cmd=post_cmd,
267
270
  post_cmd_path=post_cmd_path,
268
271
  cwd=cwd,
272
+ should_render_cwd=should_render_cwd,
269
273
  upstreams=upstreams,
270
274
  fallbacks=fallbacks,
271
275
  on_triggered=on_triggered,
zrb/task/cmd_task.py CHANGED
@@ -127,7 +127,8 @@ class CmdTask(BaseTask):
127
127
  executable: Optional[str] = None,
128
128
  cmd: CmdVal = "",
129
129
  cmd_path: CmdVal = "",
130
- cwd: Optional[Union[str, pathlib.Path]] = None,
130
+ cwd: Optional[Union[JinjaTemplate, pathlib.Path]] = None,
131
+ should_render_cwd: bool = True,
131
132
  upstreams: Iterable[AnyTask] = [],
132
133
  fallbacks: Iterable[AnyTask] = [],
133
134
  on_triggered: Optional[OnTriggered] = None,
@@ -181,6 +182,7 @@ class CmdTask(BaseTask):
181
182
  self._cmd = cmd
182
183
  self._cmd_path = cmd_path
183
184
  self.__set_cwd(cwd)
185
+ self._should_render_cwd = should_render_cwd
184
186
  self._max_output_size = max_output_line
185
187
  self._max_error_size = max_error_line
186
188
  self._output_buffer: Iterable[str] = []
@@ -233,13 +235,14 @@ class CmdTask(BaseTask):
233
235
  cmd = self.get_cmd_script(*args, **kwargs)
234
236
  if self._should_show_cmd:
235
237
  self.print_out_dark("Run script: " + self.__get_multiline_repr(cmd))
238
+ cwd = self._get_cwd()
236
239
  if self._should_show_working_directory:
237
- self.print_out_dark("Working directory: " + self._cwd)
240
+ self.print_out_dark("Working directory: " + cwd)
238
241
  self._output_buffer = []
239
242
  self._error_buffer = []
240
243
  process = await asyncio.create_subprocess_shell(
241
244
  cmd,
242
- cwd=self._cwd,
245
+ cwd=cwd,
243
246
  stdout=asyncio.subprocess.PIPE,
244
247
  stderr=asyncio.subprocess.PIPE,
245
248
  env=self.get_env_map(),
@@ -272,6 +275,11 @@ class CmdTask(BaseTask):
272
275
  self.set_task_xcom(key="error", value=error)
273
276
  return CmdResult(output, error)
274
277
 
278
+ def _get_cwd(self) -> Union[str, pathlib.Path]:
279
+ if self._should_render_cwd and isinstance(self._cwd, str):
280
+ return self.render_str(self._cwd)
281
+ return self._cwd
282
+
275
283
  def _should_attempt(self) -> bool:
276
284
  if self._global_state.no_more_attempt:
277
285
  return False
@@ -104,7 +104,8 @@ class DockerComposeTask(CmdTask):
104
104
  compose_env_prefix: str = "",
105
105
  setup_cmd: CmdVal = "",
106
106
  setup_cmd_path: CmdVal = "",
107
- cwd: Optional[Union[str, pathlib.Path]] = None,
107
+ cwd: Optional[Union[JinjaTemplate, pathlib.Path]] = None,
108
+ should_render_cwd: bool = True,
108
109
  upstreams: Iterable[AnyTask] = [],
109
110
  fallbacks: Iterable[AnyTask] = [],
110
111
  on_triggered: Optional[OnTriggered] = None,
@@ -140,6 +141,7 @@ class DockerComposeTask(CmdTask):
140
141
  description=description,
141
142
  executable=executable,
142
143
  cwd=cwd,
144
+ should_render_cwd=should_render_cwd,
143
145
  upstreams=[ensure_zrb_network_task] + upstreams,
144
146
  fallbacks=fallbacks,
145
147
  on_triggered=on_triggered,
@@ -120,6 +120,6 @@ class MultilineInput(BaseInput):
120
120
 
121
121
  def _get_mark_comment(self):
122
122
  prompt = self._prompt if isinstance(self._prompt, str) else self.get_name()
123
- if self._comment_suffix.strip() != "":
123
+ if self._comment_suffix.strip() == "":
124
124
  return " ".join([self._comment_prefix, prompt])
125
125
  return " ".join([self._comment_prefix, prompt, self._comment_suffix])
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zrb
3
- Version: 0.22.0
3
+ Version: 0.23.4
4
4
  Summary: A Framework to Enhance Your Workflow
5
5
  Home-page: https://github.com/state-alchemists/zrb
6
6
  License: AGPL-3.0-or-later
@@ -23,7 +23,7 @@ Requires-Dist: jsons (>=1.6.3,<1.7.0)
23
23
  Requires-Dist: libcst (>=0.4.9,<0.5.0)
24
24
  Requires-Dist: python-dotenv (>=1.0.1,<1.1.0)
25
25
  Requires-Dist: ruamel.yaml (>=0.18.6,<0.19.0)
26
- Requires-Dist: setuptools (>=69.1.1,<69.2.0)
26
+ Requires-Dist: setuptools (>=70.0.0,<70.1.0)
27
27
  Requires-Dist: termcolor (>=2.4.0,<2.5.0)
28
28
  Requires-Dist: tomlkit (>=0.12.4,<0.13.0)
29
29
  Project-URL: Documentation, https://github.com/state-alchemists/zrb
@@ -63,7 +63,7 @@ pip install zrb
63
63
  Alternatively, you can also use our installation script to install Zrb along with some prerequisites:
64
64
 
65
65
  ```bash
66
- source <(curl -s https://raw.githubusercontent.com/state-alchemists/zrb/main/install.sh)
66
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/state-alchemists/zrb/main/install.sh)"
67
67
  ```
68
68
 
69
69
  Check our [installation guide](https://github.com/state-alchemists/zrb/blob/main/docs/installation.md) for more information about the installation methods, including installation as a docker container.
@@ -270,7 +270,7 @@ zrb/builtin/project/add/fastapp/app/template/_automate/snake_zrb_app_name/monoli
270
270
  zrb/builtin/project/add/fastapp/app/template/_automate/snake_zrb_app_name/test.py,sha256=RuZGmP2OTPZcDOuBX5p-j5TizakkDxEClWhB2Fg64M4,1826
271
271
  zrb/builtin/project/add/fastapp/app/template/_automate/snake_zrb_app_name/test.sh,sha256=ibnoS4kV1p-3JREJKlX2UsziP009zHzP9miPxID1tpk,308
272
272
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/.gitignore,sha256=YFrq8n_0yn9FT0XqcPVftHmKj31DSh4ftIY8EvQm0ik,53
273
- zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/README.md,sha256=aFW2zzZMt7wnpBT_vD0cAkPODH2PU7GM4bq8Y38hFQw,10024
273
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/README.md,sha256=mIE-CBlKzx_wEQdGIuiJbzDX_bCC13ckMnOYU8erHpI,15200
274
274
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/all-module-disabled.env,sha256=eIbYiufwRJ-artnA7Cw2y4YzGrPw2XtEb-ih_f4tCuw,56
275
275
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/all-module-enabled.env,sha256=gu-tRFyAuSNRZAsxKTvf4ILnI0jH3bLkMhq0YU_tiyc,54
276
276
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/deployment/.gitignore,sha256=zF-r8EJ_RaTVRxFpy1mapsxVQV6UAnNcK9q57ynRfig,12
@@ -1004,7 +1004,7 @@ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend
1004
1004
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/src/lib/error/helper.ts,sha256=FCTH3-UC7AzlmG2QhuMX7-9ztprj3ne6LQ4neYl8xyM,350
1005
1005
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/src/routes/+error.svelte,sha256=xG4MQsDZos8yOtL5uXfhgPN5CKCbzVS11Hw9gY8Qj1Q,291
1006
1006
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/src/routes/+layout.js,sha256=IepBDK8VpfSwS_akOn9eRqRlv8erCF4VtsBXWvBUlH4,65
1007
- zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/src/routes/+layout.svelte,sha256=aDbWrCUJzf5QuPkGmae6iVwwa163sADsc8Nt_pYtmP4,584
1007
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/src/routes/+layout.svelte,sha256=WS3RLg3zc2_DxILj4LFhVtvDpIjRIYlvJaddEEt8NY4,584
1008
1008
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/src/routes/+page.svelte,sha256=KVlODA_W9yHLBcdDSrMyyWl-j6izvt3Au0X2IYZ9bSs,489
1009
1009
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/src/routes/auth/group/+page.svelte,sha256=smFqwX1tjaQLiyziJP8RjWicDFmk696MYkt1IjKzYFU,6285
1010
1010
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/src/routes/auth/group/delete/[id]/+page.svelte,sha256=kxMaJ9nCxUf3fZ93Z5nx2ehOo-vZhtL-NhSG26AeEPE,3763
@@ -1039,22 +1039,23 @@ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend
1039
1039
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/tailwind.config.js,sha256=qj1dclGOmSgT8IBeBhclrKUY2Z_B5P6OSNSoX1lX_mw,203
1040
1040
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/tests/test.ts,sha256=Zn47gMooUsmXRYTuDvtVajL07cEwPMhL5pOXeolSnEg,224
1041
1041
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/tsconfig.json,sha256=sj7XMYCe4CrB-z91IlhC6-n6PHzM1khXzsAQcWmGR3c,532
1042
- zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/vite.config.ts,sha256=JPM2I54wRSHcwcu527UHgSr9FtUUAWDC-AJerbrzgpI,210
1042
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/frontend/vite.config.ts,sha256=lxK3jXIMlMB9vjXRENS6Xz6JmUm8bTVpdIEQAvOvWQs,317
1043
1043
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1044
1044
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/helper/async_task.py,sha256=n3-UFRQKZRc0UbEBm7tibFrwH-Jasg0xZQKXtA6LzBk,490
1045
1045
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/helper/conversion.py,sha256=NnEF-Wtt7k4rc45KZRM4jY64B2GEk3v3X3nw058Urw8,763
1046
1046
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/helper/migration.py,sha256=LFGwMKRRc9ZzSPNG_pTRewZAzTbOAwdBvFTluzyU_mQ,1858
1047
1047
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/helper/value.py,sha256=YFqIswCCd3hbxYeo907UuY6l76OwJMimThYj8MjXE_I,103
1048
1048
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1049
- zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/app.py,sha256=OWoYkdBfmtJuCMAoS4LTiT3Z7HixEjlJx9Q6EjqA0Vo,3177
1050
- zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/app_lifespan.py,sha256=mYjDwHEkqugU0xJQvi3OLvPav486svTogroSzr0t3Z0,1389
1051
- zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/app_state.py,sha256=7WJYWXaagK6_SxxuIFtQfhxJZsLFDUcYXFw3s0spNbs,870
1049
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1050
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/app/app.py,sha256=yRBTYxJkc2f4Q3tb0kZQz_x1dgwScdA1F2uvHbk3f44,3218
1051
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/app/app_lifespan.py,sha256=E5ng4FJj9Ccbp5cNM-mkbEA-s8ZYjsBhOr2u9f10aO4,1393
1052
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/app/app_state.py,sha256=7WJYWXaagK6_SxxuIFtQfhxJZsLFDUcYXFw3s0spNbs,870
1052
1053
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/db_connection.py,sha256=QxBl1qPX4Fb0t6oQJBmpD1tHGe8EYSu_XeDKDHVNPuo,1062
1053
1054
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/frontend_index.py,sha256=3mYLOH8Uuv_HshgnOK2QB2PeupV1K8DJKbv2UfTOdug,322
1054
1055
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/log.py,sha256=q4dVN43mu0u7u_1bhNwh1YXSR3VX1ZJmZ5tXRc0PZqQ,1838
1055
1056
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/messagebus.py,sha256=qSyO7yMuFVAG7kkQ4ZeY53YZ1ReEoDaZ-3CcdlU7tt8,3460
1056
1057
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/integration/rpc.py,sha256=ZTJip0Z0Xt6V9WOXm53uQIwA63c87yhr6FdGvqkTBGc,1410
1057
- zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/main.py,sha256=SKGDZV2szawzVOhr9Dhm-Bi_doPuQjarODXMoa9RSIk,280
1058
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/main.py,sha256=aduwm41KZ1RyxXrY5yi1YyhaGlBlBKjC7ObXeAIA5tA,185
1058
1059
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/migrate.py,sha256=M_y2Namnz1WphNEwzSMEzeT6Mf6xG3xCifPfj8oqyQc,232
1059
1060
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1060
1061
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1105,7 +1106,7 @@ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/a
1105
1106
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/integration/repo/user_repo.py,sha256=u_YWFpich41mGbPd2EiSNE7v2strIzTFhox9nfC2JkE,313
1106
1107
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/integration/user.py,sha256=F0PO4QUvZbLRQUiccM1GSgnkqnWdNpY03z4kT1zF8vk,805
1107
1108
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/migrate.py,sha256=iNRsDJZHdzmyYEQ0mPsV-yCbNRX8SOk6WbGRucge7pI,576
1108
- zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/register_module.py,sha256=sy1aWm_MAUOOMLcRUO4NcxO6S6GCiMMvrnFdoAXlLho,1154
1109
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/register_module.py,sha256=dyzUT0TQDIH3o6I4JboaQ5OQF5isfM1tyMOxAbsXgVQ,1158
1109
1110
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/register_permission.py,sha256=HgxYbVxXGqiMpmBgwcR8RCeKIzRI7X5GfVrLWc4aZXM,1322
1110
1111
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/rpc.py,sha256=Jy-XBBsxAx6rHvz0a9CohQBQs2YF9LkNAIlVzCR6FrQ,711
1111
1112
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/auth/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1133,7 +1134,7 @@ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/l
1133
1134
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/log/integration/repo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1134
1135
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/log/integration/repo/activity_repo.py,sha256=5arwuyOVrmWs2pNjlpyyKcBpSOOinWIhEZZQBkjTJo0,229
1135
1136
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/log/migrate.py,sha256=0TYLh8WFaaDtBJIyQltw-Qc4ZI-YlgsOEcPQrwaFK8g,429
1136
- zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/log/register_module.py,sha256=EMc0fM0rJUfdd87ol1jiVun6_xGqWBbK8aHyc0aC0hs,1147
1137
+ zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/log/register_module.py,sha256=cditSUV7duNrXRozHJnTpcoQnj6EmeQNZSabzG7PEBg,1151
1137
1138
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/log/rpc.py,sha256=Q1ClGIxzRij8oHrWKDtkb0fC_BeqCjKBi1xP962MGEc,445
1138
1139
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/log/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1139
1140
  zrb/builtin/project/add/fastapp/app/template/src/kebab-zrb-app-name/src/module/log/schema/activity.py,sha256=1Wqitx-6-UjXeFhscrbIystLm-XY2FqbUkxwbJ3sgxA,338
@@ -1155,7 +1156,7 @@ zrb/builtin/project/add/fastapp/crud/__init__.py,sha256=IMTN_eQRAAUW9P_e0RlJFm_-
1155
1156
  zrb/builtin/project/add/fastapp/crud/_helper.py,sha256=8awMQTTLB3wziBrddny60ypGPFSIJ1jeIvUFMogfHbQ,4057
1156
1157
  zrb/builtin/project/add/fastapp/crud/_input.py,sha256=2hdmmwojXl5TKkI5XMKHbHzW3QcYgx33g8hKHRMxHCo,901
1157
1158
  zrb/builtin/project/add/fastapp/crud/_task_factory.py,sha256=xfH5C0KkuhJvilrIzNBJ6LvrcG71lhM3N7ZPm6CW8Js,1481
1158
- zrb/builtin/project/add/fastapp/crud/crud.py,sha256=22jsigh-fnY7oDO6yd794m-WZuNLRPX6o6i_xovTP6c,5197
1159
+ zrb/builtin/project/add/fastapp/crud/crud.py,sha256=PABm97Mz_f99zKjWAF55B7513LvPgM5aKfkWQjlq13Q,5596
1159
1160
  zrb/builtin/project/add/fastapp/crud/nodejs/codemod/.gitignore,sha256=FtMORGIYn7FN1hG9twjFEGMMV2ofNbk4PomkNS2jbJc,13
1160
1161
  zrb/builtin/project/add/fastapp/crud/nodejs/codemod/package-lock.json,sha256=yWd9ww6RHHhAZBi5V01sbSKF6D8owxHoR1ebHGHs-2A,11620
1161
1162
  zrb/builtin/project/add/fastapp/crud/nodejs/codemod/package.json,sha256=uqz8LlyK32NyMkH2rYAgZYi29pymj_zN5j46YiTDJ2w,369
@@ -1181,9 +1182,9 @@ zrb/builtin/project/add/fastapp/crud/template/src/kebab-zrb-app-name/src/module/
1181
1182
  zrb/builtin/project/add/fastapp/crud/template/src/kebab-zrb-app-name/test/snake_zrb_module_name/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1182
1183
  zrb/builtin/project/add/fastapp/crud/template/src/kebab-zrb-app-name/test/snake_zrb_module_name/test_snake_zrb_entity_name.py,sha256=LOQAlq8v4oQbioMfjbJKamG3IPAdWNYAMbBL1eukrow,8206
1183
1184
  zrb/builtin/project/add/fastapp/field/__init__.py,sha256=ahiH_AlkbyDj_OsmyU1DMr3FL2XLe2MZRbuawWaIko4,100
1184
- zrb/builtin/project/add/fastapp/field/_helper.py,sha256=7GkYi9Ud8HW3RoVWSMg2Q78kKDMCWrgipBGQ_8xS7dE,11041
1185
+ zrb/builtin/project/add/fastapp/field/_helper.py,sha256=4PG6jYqtWajkRBguiiuuVDYiwt9eb7XYZtw7zbwJUvg,10544
1185
1186
  zrb/builtin/project/add/fastapp/field/_input.py,sha256=zx0n229UT_Pk1SQfdK7a3DfA8QXVWBRa3hmEfWOU7VM,350
1186
- zrb/builtin/project/add/fastapp/field/field.py,sha256=xN9y4Ovn-kJFzgVUBQfVHVL5lQW49w_yaV2kGMTYKBs,6522
1187
+ zrb/builtin/project/add/fastapp/field/field.py,sha256=W8zWP7NNN3PcoZiGHos3O2c2ztpbTFJv6iNeJ5c5r04,7265
1187
1188
  zrb/builtin/project/add/fastapp/module/__init__.py,sha256=alSeJepmhsb8Op21K_ttP5FIDk84v2KsBpiCKkwVE0A,104
1188
1189
  zrb/builtin/project/add/fastapp/module/_helper.py,sha256=8x9tM_51EzMdle9ri8IaydKXYPLmqZNRNQPRtGXdd4o,10945
1189
1190
  zrb/builtin/project/add/fastapp/module/_input.py,sha256=X13ZS0n4ZgUc3sbJtoEyFWUw8Jpbm2EDKsv0tvE5uZo,201
@@ -1198,7 +1199,7 @@ zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/src/modul
1198
1199
  zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/src/module/snake_zrb_module_name/integration/model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1199
1200
  zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/src/module/snake_zrb_module_name/integration/repo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1200
1201
  zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/src/module/snake_zrb_module_name/migrate.py,sha256=6gJK8aRNBs52IGdSv93-LcIg2O_03AQSCUJ6PIpNjpg,537
1201
- zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/src/module/snake_zrb_module_name/register_module.py,sha256=7DqLVNT1B_RpvZjcIUWE8D9p9NBVAouI2PT0-IaaDI0,1273
1202
+ zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/src/module/snake_zrb_module_name/register_module.py,sha256=_fBdv1aBLKPTk3rNBVUSlVVtx39EnMFLCvkJU6Zy7LU,1277
1202
1203
  zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/src/module/snake_zrb_module_name/rpc.py,sha256=bj2GMybNAkpauhJJhzG2evkHzckBz-cp600EVLFKBpg,313
1203
1204
  zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/src/module/snake_zrb_module_name/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1204
1205
  zrb/builtin/project/add/fastapp/module/template/src/kebab-zrb-app-name/test/snake_zrb_module_name/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1322,7 +1323,7 @@ zrb/helper/docstring.py,sha256=kU3nZFYtCrrxNsLxmx2UofHav09VB5y0VeY_Blux6FQ,4970
1322
1323
  zrb/helper/env_map/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1323
1324
  zrb/helper/env_map/fetch.py,sha256=wzOO58LmhQsgFVsVrUhdGbQmu6igOE1x6SR2SbRnuTA,2335
1324
1325
  zrb/helper/file/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1325
- zrb/helper/file/copy_tree.py,sha256=Tuk4qej7ToZQqEmeiSADiFjWq7xyh-Nfzk1z2fjHZK0,1854
1326
+ zrb/helper/file/copy_tree.py,sha256=Ka0vFJLcUlaQFwhj3ofm6tIAU8Rvzzgw9PDIEhamvew,2312
1326
1327
  zrb/helper/file/match.py,sha256=73uypJq5EnFAhA7kaNodW9vBLZ0MQVwZDh8CD3x52kw,721
1327
1328
  zrb/helper/file/text.py,sha256=7JqNbk8hC7Y4UopEmhiGYkxDAauepvI1tEkbfpzcI84,963
1328
1329
  zrb/helper/git/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1340,7 +1341,7 @@ zrb/helper/string/constant.py,sha256=kAwuNW9hC3xc24t5NoeUX5tautZMvWNzZdREKMMbXm8
1340
1341
  zrb/helper/string/conversion.py,sha256=pnhlhKwvXUR38jvtSo1HZNedl-7KtHoKaWl4OVIaEv0,772
1341
1342
  zrb/helper/string/jinja.py,sha256=FyYtsJjEDqk3atmaU2TdNWtA4qD88x-lmtF5BOa23KY,487
1342
1343
  zrb/helper/string/modification.py,sha256=sYPewGp72l2AhWXr-Wy3FfzO9aTLCULw-JgQzSmXQmI,308
1343
- zrb/helper/string/parse_replacement.py,sha256=DzL1QM3-WCysdXi1qfxTPRudMwW4V1MxuIEIlbT5cq4,459
1344
+ zrb/helper/string/parse_replacement.py,sha256=SJxarINfXgeGeimsM3KC-bKRYS-87XF2WF3ewPPX4is,759
1344
1345
  zrb/helper/string/untyped_conversion.py,sha256=0hxwbyMz4psglAH5KnjfXBmgptJq34P9ltueQntBx4Y,1366
1345
1346
  zrb/helper/task.py,sha256=Z8p2urrTuABCFrsefR3u250Gdi1dtf7bABE4yR3oLZU,394
1346
1347
  zrb/helper/typecheck.py,sha256=Sb5lCiMfxppycj3nqUSxkyRPBdxdTRRnvaCCAb6mGrI,436
@@ -1358,7 +1359,7 @@ zrb/shell-scripts/ssh-util.sh,sha256=9lXDzw6oO8HuA4vdbfps_uQMMwKyNYX9fZkZgpK52g8
1358
1359
  zrb/task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1359
1360
  zrb/task/any_task.py,sha256=nKcCj_RbSC-MUSi4rxcIAC2eEFo7uKwODkgglxp3mj8,39346
1360
1361
  zrb/task/any_task_event_handler.py,sha256=AjTC6lIcprutRusNBGl83EifQe4TbZzxdlVIR4ndWN4,524
1361
- zrb/task/base_remote_cmd_task.py,sha256=q2Kwo5OMahL5gPSxwp_9zZLYouFfFc6Ru_p6ApOI-pk,12124
1362
+ zrb/task/base_remote_cmd_task.py,sha256=SO26Hu3l_chP03XfPF6b0PN3SVyklwSDYf0n5QOXrYA,12316
1362
1363
  zrb/task/base_task/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1363
1364
  zrb/task/base_task/base_task.py,sha256=rPWMIBNnNtwn0q3VEUDw3HfbSPWtww_lyOA3rUh5aq0,20310
1364
1365
  zrb/task/base_task/component/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1368,9 +1369,9 @@ zrb/task/base_task/component/pid_model.py,sha256=RjJIqOpavucDssnd3q3gT4q8QnP8I9S
1368
1369
  zrb/task/base_task/component/renderer.py,sha256=9wP2IW811Ta81IoPWmeQ7yVc7eG-uaSnOVbEyeaOIuk,4439
1369
1370
  zrb/task/base_task/component/trackers.py,sha256=c5xhZ6agICxKPI5Va1sn66_9OqC92ebF5CNhcwVUNUE,2074
1370
1371
  zrb/task/checker.py,sha256=raYNBHgeyEqkyfBRsPPgSV7ukEfMlJOCUn97WQNl6mU,3384
1371
- zrb/task/cmd_task.py,sha256=z20xSsFTjnMToTgORzToKRn8_AwubLC0Sm6b-3z58_c,14526
1372
+ zrb/task/cmd_task.py,sha256=Q9PwVfltBDm2POdbgdxHp7QDrZCwfnINUFrM3b7QCzk,14837
1372
1373
  zrb/task/decorator.py,sha256=stxrl6aXbuUDK83lVf8m8uni3Ii6egLl0TCR0vxslUQ,3064
1373
- zrb/task/docker_compose_task.py,sha256=hUKF7W3GwxFuEWmlPPFxa7h8npEnig2sm7KjlidHFBI,14911
1374
+ zrb/task/docker_compose_task.py,sha256=F5DRAh0p-K2Bsjavf3SxvQphOs_48AF440XVeRIU9Ko,15010
1374
1375
  zrb/task/flow_task.py,sha256=QBOoyIrqc6ToSf3RF8xu8h4yxCWCerUAu2Ba0GxAqgg,5147
1375
1376
  zrb/task/http_checker.py,sha256=y0cWa2t4YtGQr6FWno5sZ6Ej9gQiLDF-Z1kLU1rijRw,5693
1376
1377
  zrb/task/looper.py,sha256=0eM3wEIC_RbThg60MRbK4Az16vt81O5p12cORAYTfnI,1430
@@ -1401,12 +1402,12 @@ zrb/task_input/choice_input.py,sha256=qfrEzbs2g0CZeE2TzvfN0IOla_1B8Tikn-eIgMpLuP
1401
1402
  zrb/task_input/constant.py,sha256=VEsnrI0BDdCJ1Z58EJgxXUhZBe5CA8TfURo0cNu5CaQ,200
1402
1403
  zrb/task_input/float_input.py,sha256=bf2dhmbpmHMQiJFKYQEfTYmqpwyOEFh6CFM1r1dGTuw,4302
1403
1404
  zrb/task_input/int_input.py,sha256=P7lDQ0-x5lP_ZTfFeyc-aybub9oikBN4J13HZvWuw0A,4355
1404
- zrb/task_input/multiline_input.py,sha256=K0qEWRAp3azV9gBH1cGnE2l3-eX7Bue_bQ9GvMdmjHs,5609
1405
+ zrb/task_input/multiline_input.py,sha256=kP2VQ4c42-d6P4RB3AA2eGTrFRLwvFlZxc7vGwjTeZA,5609
1405
1406
  zrb/task_input/password_input.py,sha256=3xxWHKJCDGbyl_5MmyyB2t_yRjwFKpIIbS10aq73ktk,4370
1406
1407
  zrb/task_input/str_input.py,sha256=0BJP3SQ8y0TRYPrwEy5pYv4N7jq8KlmRSVwByIFqIvI,4360
1407
1408
  zrb/task_input/task_input.py,sha256=WTj_qIQyRs-04-VotjNTcVyIuf6b2afInVoCQHoRmr0,2327
1408
- zrb-0.22.0.dist-info/LICENSE,sha256=WfnGCl8G60EYOPAEkuc8C9m9pdXWDe08NsKj3TBbxsM,728
1409
- zrb-0.22.0.dist-info/METADATA,sha256=LqnDhX1dESGPkFwz105U_NsKKViYl0nhqTuM-jd0Ens,17076
1410
- zrb-0.22.0.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
1411
- zrb-0.22.0.dist-info/entry_points.txt,sha256=xTgXc1kBKYhJHEujdaSPHUcJT3-hbyP1mLgwkv-5sSk,40
1412
- zrb-0.22.0.dist-info/RECORD,,
1409
+ zrb-0.23.4.dist-info/LICENSE,sha256=WfnGCl8G60EYOPAEkuc8C9m9pdXWDe08NsKj3TBbxsM,728
1410
+ zrb-0.23.4.dist-info/METADATA,sha256=E2ckuoPzbtgXS_sSM6w9dRuBm9OX38z1JO-1weJzuNA,17082
1411
+ zrb-0.23.4.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
1412
+ zrb-0.23.4.dist-info/entry_points.txt,sha256=xTgXc1kBKYhJHEujdaSPHUcJT3-hbyP1mLgwkv-5sSk,40
1413
+ zrb-0.23.4.dist-info/RECORD,,
File without changes
File without changes