bisslog-flask 0.0.2__py3-none-any.whl → 0.0.3__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.
@@ -8,6 +8,7 @@ configuration, and runtime setup.
8
8
  The generated code is returned as a full Python script and can be written to a file (e.g.,
9
9
  `flask_app.py`).
10
10
  """
11
+
11
12
  from typing import Optional, Callable
12
13
  import json
13
14
 
@@ -17,6 +18,7 @@ from bisslog_schema.schema import UseCaseInfo, TriggerHttp, TriggerWebsocket
17
18
  from bisslog_schema.setup import get_setup_metadata
18
19
  from bisslog_schema.use_case_code_inspector.use_case_code_metadata import UseCaseCodeInfo, \
19
20
  UseCaseCodeInfoClass, UseCaseCodeInfoObject
21
+
20
22
  from .static_python_construct_data import StaticPythonConstructData
21
23
 
22
24
 
@@ -147,6 +149,9 @@ if "JWT_SECRET_KEY" in os.environ:
147
149
  StaticPythonConstructData
148
150
  The generated code for the HTTP trigger.
149
151
  """
152
+ imports = {
153
+ "flask": {"jsonify"}
154
+ }
150
155
  starting_build = ""
151
156
  mapper_code_lines = []
152
157
  if trigger_info.mapper is not None:
@@ -155,7 +160,7 @@ if "JWT_SECRET_KEY" in os.environ:
155
160
  f"base={json.dumps(trigger_info.mapper)})")
156
161
  mapper_code_lines.append(f"""
157
162
  res_map = {mapper_name}.map({{
158
- "path_query": request.view_args or {{}},
163
+ "path_query": route_vars,
159
164
  "body": request.get_json(silent=True) or {{}},
160
165
  "params": request.args.to_dict(),
161
166
  "headers": request.headers,
@@ -166,20 +171,33 @@ if "JWT_SECRET_KEY" in os.environ:
166
171
 
167
172
  lines = [
168
173
  f'@app.route("{flask_path}", methods=["{method}"])',
169
- f'def {handler_name}():',
170
174
  ]
175
+
176
+ if use_case_code_info.is_coroutine:
177
+ lines.append(f"async def {handler_name}(**route_vars):")
178
+ else:
179
+ lines.append(f"def {handler_name}(**route_vars):")
180
+
171
181
  if not mapper_code_lines:
172
182
  lines.append(" kwargs = {}")
173
- lines.append(" kwargs.update(request.view_args or {})")
183
+ lines.append(" kwargs.update(route_vars)")
174
184
  lines.append(" kwargs.update(request.get_json(silent=True) or {})")
175
185
  lines.append(" kwargs.update(request.args.to_dict())")
176
186
  lines.append(" kwargs.update(dict(request.headers))")
177
- lines.append(f" return {uc_callable}(**kwargs)\n")
187
+ var_to_unpack = "kwargs"
178
188
  else:
179
189
  lines.extend(mapper_code_lines)
180
- lines.append(f' return {uc_callable}(**res_map)\n')
190
+ var_to_unpack = "res_map"
191
+
192
+ if use_case_code_info.is_coroutine:
193
+ lines.append(f' result = await {uc_callable}(**{var_to_unpack})')
194
+ else:
195
+ lines.append(f' result = {uc_callable}(**{var_to_unpack})\n')
196
+
197
+ lines.append(' return jsonify(result)\n')
181
198
 
182
- return StaticPythonConstructData(build=starting_build, body="\n".join(lines))
199
+ return StaticPythonConstructData(build=starting_build,
200
+ body="\n".join(lines), importing=imports)
183
201
 
184
202
  @staticmethod
185
203
  def _generate_use_case_code_websocket_trigger(
@@ -217,7 +235,7 @@ if "JWT_SECRET_KEY" in os.environ:
217
235
  imports = {
218
236
  use_case_code_info.module: {use_case_code_info.name},
219
237
  "flask_sock": {"Sock"},
220
- "flask": {"request"},
238
+ "flask": {"request", "jsonify"},
221
239
  "bisslog.utils.mapping": {"Mapper"},
222
240
  "json": None
223
241
  }
@@ -1,10 +1,11 @@
1
+ """Command-line interface for the `bisslog_flask` package."""
2
+ import argparse
1
3
  import os
2
4
  import sys
3
- import argparse
4
5
  import traceback
5
6
 
6
- from .commands.run import run
7
7
  from .commands.build import build_boiler_plate_flask
8
+ from .commands.run import run
8
9
 
9
10
 
10
11
  def main():
@@ -62,7 +63,8 @@ def main():
62
63
  build_parser.add_argument("--encoding", type=str, default="utf-8",
63
64
  help="File encoding (default: utf-8).")
64
65
  build_parser.add_argument("--target-filename", type=str, default="flask_app.py",
65
- help="Filename to write the generated boilerplate (default: flask_app.py)")
66
+ help="Filename to write the generated "
67
+ "boilerplate (default: flask_app.py)")
66
68
 
67
69
  args = parser.parse_args()
68
70
 
@@ -82,7 +84,7 @@ def main():
82
84
  encoding=args.encoding,
83
85
  target_filename=args.target_filename
84
86
  )
85
- except Exception as e:
87
+ except Exception as e: # pylint: disable=broad-except
86
88
  traceback.print_exc()
87
89
  print(e)
88
90
  sys.exit(1)
@@ -10,8 +10,10 @@ The generated code supports HTTP and WebSocket routes, environment-based securit
10
10
  configuration, and respects the Bisslog runtime setup defined via decorators.
11
11
  """
12
12
  from typing import Optional
13
+
13
14
  from ...builder.builder_flask_app_manager import bisslog_flask_builder
14
15
 
16
+
15
17
  def build_boiler_plate_flask(
16
18
  metadata_file: Optional[str] = None,
17
19
  use_cases_folder_path: Optional[str] = None,
@@ -18,7 +18,7 @@ def run(metadata_file: Optional[str] = None,
18
18
  secret_key: Optional[str] = None,
19
19
  jwt_secret_key: Optional[str] = None):
20
20
  """
21
- Run a Flask application using metadata and use case source.
21
+ Run a Flask application using metadata and use-case source.
22
22
 
23
23
  This function creates and runs a Flask app configured through the
24
24
  BisslogFlask integration layer. It loads metadata definitions,
@@ -16,10 +16,12 @@ Dependencies
16
16
  - bisslog_schema
17
17
  - bisslog.utils.mapping
18
18
  """
19
+ import inspect
19
20
  from copy import deepcopy
20
- from typing import Callable, Optional, Dict
21
+ from typing import Callable, Optional, Dict, Union, Awaitable, Any
21
22
 
22
23
  from flask import Flask, request, jsonify
24
+
23
25
  try:
24
26
  from flask_cors import cross_origin
25
27
  except ImportError:
@@ -82,10 +84,10 @@ class BisslogFlaskHttpResolver(BisslogFlaskResolver):
82
84
 
83
85
  @staticmethod
84
86
  def _use_case_factory(
85
- use_case_name: str,
86
- fn: Callable,
87
- mapper: Optional[Dict[str, str]] = None,
88
- trigger: Optional[TriggerHttp] = None
87
+ use_case_name: str,
88
+ fn: Callable,
89
+ mapper: Optional[Dict[str, str]] = None,
90
+ trigger: Optional[TriggerHttp] = None
89
91
  ):
90
92
  """
91
93
  Factory to produce a Flask view function with optional mapping and CORS.
@@ -109,10 +111,49 @@ class BisslogFlaskHttpResolver(BisslogFlaskResolver):
109
111
  use_case_fn_copy = deepcopy(fn)
110
112
  __mapper__ = Mapper(name=f"Mapper {use_case_name}", base=mapper) if mapper else None
111
113
 
112
- def uc(*args, **kwargs):
113
- return BisslogFlaskHttpResolver._lambda_fn(
114
- *args, fn=use_case_fn_copy, __mapper__=__mapper__, **kwargs
115
- )
114
+ is_async = (
115
+ inspect.iscoroutinefunction(fn)
116
+ or inspect.iscoroutinefunction(getattr(fn, "__call__", None))
117
+ )
118
+
119
+ if is_async:
120
+ async def uc(*args, **kwargs):
121
+ if __mapper__ is None:
122
+ more_kwargs = {}
123
+ if request.method.lower() != "get":
124
+ more_kwargs.update(request.get_json(silent=True) or {})
125
+ res = await use_case_fn_copy(*args, **kwargs, **more_kwargs)
126
+ return jsonify(res)
127
+
128
+ res_map = __mapper__.map({
129
+ "path_query": request.view_args or {},
130
+ "body": request.get_json(silent=True) or {},
131
+ "params": request.args.to_dict(),
132
+ "headers": request.headers,
133
+ })
134
+ res = await use_case_fn_copy(**res_map)
135
+ return jsonify(res)
136
+
137
+ view = uc
138
+ else:
139
+ def uc(*args, **kwargs):
140
+ if __mapper__ is None:
141
+ more_kwargs = {}
142
+ if request.method.lower() != "get":
143
+ more_kwargs.update(request.get_json(silent=True) or {})
144
+ res = use_case_fn_copy(*args, **kwargs, **more_kwargs)
145
+ return jsonify(res)
146
+
147
+ res_map = __mapper__.map({
148
+ "path_query": request.view_args or {},
149
+ "body": request.get_json(silent=True) or {},
150
+ "params": request.args.to_dict(),
151
+ "headers": request.headers,
152
+ })
153
+ res = use_case_fn_copy(**res_map)
154
+ return jsonify(res)
155
+
156
+ view = uc
116
157
 
117
158
  # Apply CORS dynamically if allowed
118
159
  if trigger and trigger.allow_cors:
@@ -124,13 +165,13 @@ class BisslogFlaskHttpResolver(BisslogFlaskResolver):
124
165
  "allow_headers": ["Content-Type", "Authorization"],
125
166
  "supports_credentials": True
126
167
  }
127
- return cross_origin(**cors_kwargs)(uc)
168
+ return cross_origin(**cors_kwargs)(view)
128
169
 
129
- return uc
170
+ return view
130
171
 
131
172
  @classmethod
132
173
  def _add_use_case(cls, app: Flask, use_case_info: UseCaseInfo, trigger: TriggerInfo,
133
- use_case_function):
174
+ use_case_function: Union[Callable[..., Any], Callable[..., Awaitable[Any]]]):
134
175
  """
135
176
  Adds an HTTP endpoint to the Flask app for a given use case.
136
177
 
@@ -9,7 +9,6 @@ from abc import ABC, abstractmethod
9
9
  from typing import Callable
10
10
 
11
11
  from bisslog_schema.schema import UseCaseInfo, TriggerInfo
12
-
13
12
  from flask import Flask
14
13
 
15
14
 
@@ -5,7 +5,9 @@ This module defines the `BisslogFlaskWebSocketResolver` class, which dynamically
5
5
  WebSocket-based use case triggers in a Flask app. The class uses metadata definitions to
6
6
  configure event routes (via `route_key`) and binds them to corresponding use case functions.
7
7
  """
8
+ import inspect
8
9
  from typing import Callable
10
+
9
11
  from flask import Flask, request
10
12
 
11
13
  try:
@@ -64,13 +66,27 @@ class BisslogFlaskWebSocketResolver(BisslogFlaskResolver):
64
66
  base=trigger_info.options.mapper
65
67
  ) if trigger_info.options.mapper else None
66
68
 
67
- @socket_io_obj.on(route_key)
68
- def on_event(data):
69
- mapped_data = mapper.map({
70
- "route_key": route_key,
71
- "connection_id": request.sid,
72
- "body": data,
73
- "headers": dict(request.headers)
74
- }) if mapper else data
69
+ is_async = inspect.iscoroutinefunction(use_case_callable)
70
+
71
+ if is_async:
72
+ @socket_io_obj.on(route_key)
73
+ async def on_event(data):
74
+ mapped_data = mapper.map({
75
+ "route_key": route_key,
76
+ "connection_id": request.sid,
77
+ "body": data,
78
+ "headers": dict(request.headers)
79
+ }) if mapper else data
80
+
81
+ return await use_case_callable(**mapped_data) if mapper else use_case_callable(data)
82
+ else:
83
+ @socket_io_obj.on(route_key)
84
+ def on_event(data):
85
+ mapped_data = mapper.map({
86
+ "route_key": route_key,
87
+ "connection_id": request.sid,
88
+ "body": data,
89
+ "headers": dict(request.headers)
90
+ }) if mapper else data
75
91
 
76
- return use_case_callable(**mapped_data) if mapper else use_case_callable(data)
92
+ return use_case_callable(**mapped_data) if mapper else use_case_callable(data)
@@ -19,8 +19,8 @@ from typing import Optional, Callable
19
19
 
20
20
  from bisslog_schema import read_service_info_with_code
21
21
  from bisslog_schema.eager_import_module_or_package import EagerImportModulePackage
22
- from bisslog_schema.setup import run_setup
23
22
  from bisslog_schema.schema import UseCaseInfo, TriggerHttp, TriggerWebsocket
23
+ from bisslog_schema.setup import run_setup
24
24
  from flask import Flask
25
25
 
26
26
  from .bisslog_flask_http_resolver import BisslogFlaskHttpResolver
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bisslog_flask
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: It is an extension of the bisslog library to support processes with flask
5
5
  Author-email: Darwin Stiven Herrera Cartagena <darwinsherrerac@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/darwinhc/bisslog-flask
@@ -10,13 +10,15 @@ Classifier: Operating System :: OS Independent
10
10
  Requires-Python: >=3.7
11
11
  Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
- Requires-Dist: bisslog>=0.0.7
14
- Requires-Dist: bisslog-schema>=0.0.6
13
+ Requires-Dist: bisslog>=0.0.9
14
+ Requires-Dist: bisslog-schema>=0.0.10
15
15
  Requires-Dist: flask
16
16
  Provides-Extra: websocket
17
17
  Requires-Dist: flask-socketio; extra == "websocket"
18
18
  Provides-Extra: cors
19
19
  Requires-Dist: flask-cors>=6.0.0; extra == "cors"
20
+ Provides-Extra: async
21
+ Requires-Dist: Flask[async]>=2.2; extra == "async"
20
22
  Dynamic: license-file
21
23
 
22
24
  # bisslog-flask
@@ -0,0 +1,21 @@
1
+ bisslog_flask/__init__.py,sha256=BEf_UxFtcMfaM-Smh_bwc6Xn8pR8LcEjby3nCs0hdXE,758
2
+ bisslog_flask/builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ bisslog_flask/builder/builder_flask_app_manager.py,sha256=HffxWfMRRlrfmYSojCdH563bJgQGa3vF2GB9rOYnINw,14777
4
+ bisslog_flask/builder/static_python_construct_data.py,sha256=p8QcXUAXZRXtNlghWv-husw9hByGTp53_g0RxhmzoNc,5735
5
+ bisslog_flask/cli/__init__.py,sha256=DlqqUfYI3e3Q6wY7xg7X-Ux9_6gTNQAAClAe2aI2-tg,3792
6
+ bisslog_flask/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ bisslog_flask/cli/commands/build.py,sha256=uI-aH8HvW7UPdqGJvtQ2p5tw5nEFcUAzvicLCGuKccY,2341
8
+ bisslog_flask/cli/commands/run.py,sha256=gUfgpLzPxQ-hB2DApA-BcxpkPaI_QCNH7OUUpkl8D34,1953
9
+ bisslog_flask/initializer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ bisslog_flask/initializer/bisslog_flask_http_resolver.py,sha256=nxAZFyl_7akpMzgDQsURVAbJmTxuFKlpCu3SfYioh44,7890
11
+ bisslog_flask/initializer/bisslog_flask_resolver.py,sha256=pt7EC-WqfsBp7w3Z0SE378hfwWTLfRDM6fGMfF3_sb8,1707
12
+ bisslog_flask/initializer/bisslog_flask_ws_resolver.py,sha256=wcG8iPky2PYyRUovHJg5woX1vLJ-fmLRmgUW-PLU_Jc,3572
13
+ bisslog_flask/initializer/init_flask_app_manager.py,sha256=gwu6cg6RLh5UMT4GGiIFJx8cD385j7EvUnGfk9S6aC0,5389
14
+ bisslog_flask/socket_helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
+ bisslog_flask/socket_helper/socket_helper.py,sha256=HHENwYT-qdrJlwmGszYqFM1MA1g6naRurUp6sYCHRRQ,2967
16
+ bisslog_flask-0.0.3.dist-info/licenses/LICENSE,sha256=TSlM1hRIXc6yR3xpGzy2DMSSbds0svqHSetfNfQqCEk,1074
17
+ bisslog_flask-0.0.3.dist-info/METADATA,sha256=8X8f3Lsko5s7NX8iZwkP1gFpVNoOdRVUSjKinqaaVyk,4251
18
+ bisslog_flask-0.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ bisslog_flask-0.0.3.dist-info/entry_points.txt,sha256=A2_A5lZt973oUBpuOCC78aTm7dGyHk6cemnn5_jOXHw,57
20
+ bisslog_flask-0.0.3.dist-info/top_level.txt,sha256=Xk85d0SIhkUP1HjsXOtq2vlU7yQT3mFApyb5IVgtG6w,14
21
+ bisslog_flask-0.0.3.dist-info/RECORD,,
@@ -1,21 +0,0 @@
1
- bisslog_flask/__init__.py,sha256=BEf_UxFtcMfaM-Smh_bwc6Xn8pR8LcEjby3nCs0hdXE,758
2
- bisslog_flask/builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- bisslog_flask/builder/builder_flask_app_manager.py,sha256=cJtbkT21lydm2tEQr3V3-7wm5ilJfJP0qFl9Oa3TpkA,14302
4
- bisslog_flask/builder/static_python_construct_data.py,sha256=p8QcXUAXZRXtNlghWv-husw9hByGTp53_g0RxhmzoNc,5735
5
- bisslog_flask/cli/__init__.py,sha256=Qd9zgdNKb6lAFb7Nsf8USrO_NNuemtOIfJAm8hOZXqc,3660
6
- bisslog_flask/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- bisslog_flask/cli/commands/build.py,sha256=QiXQvI3tHCS4i8Xbq6ucdx5lwkWg6yzsvQKqV6y4-p8,2339
8
- bisslog_flask/cli/commands/run.py,sha256=6RDEDw8HrwDupii9e-O-Q2bfrIqGmDuMYa3wUvRCW5E,1953
9
- bisslog_flask/initializer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- bisslog_flask/initializer/bisslog_flask_http_resolver.py,sha256=d-KFQwMXeRyq3_Cu5bxCF7CpnetfnKainChEbdxDk2c,6257
11
- bisslog_flask/initializer/bisslog_flask_resolver.py,sha256=QWjft6HZbBplbP1vVMNoPhGoSZBJubAotwLR76HVttw,1708
12
- bisslog_flask/initializer/bisslog_flask_ws_resolver.py,sha256=s-eDdk5HA6E_D8iZC6IN7RSW-96mzu8m8VGL3Xqm9PQ,2974
13
- bisslog_flask/initializer/init_flask_app_manager.py,sha256=55lb2WoKBHyD2_XSO1svMLZY0tP-yIm8XKLOVZBIogk,5389
14
- bisslog_flask/socket_helper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- bisslog_flask/socket_helper/socket_helper.py,sha256=HHENwYT-qdrJlwmGszYqFM1MA1g6naRurUp6sYCHRRQ,2967
16
- bisslog_flask-0.0.2.dist-info/licenses/LICENSE,sha256=TSlM1hRIXc6yR3xpGzy2DMSSbds0svqHSetfNfQqCEk,1074
17
- bisslog_flask-0.0.2.dist-info/METADATA,sha256=oKpJICdabwz2vtIG70DyJEQVZQTNksX-teABr-dz8KQ,4177
18
- bisslog_flask-0.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
- bisslog_flask-0.0.2.dist-info/entry_points.txt,sha256=A2_A5lZt973oUBpuOCC78aTm7dGyHk6cemnn5_jOXHw,57
20
- bisslog_flask-0.0.2.dist-info/top_level.txt,sha256=Xk85d0SIhkUP1HjsXOtq2vlU7yQT3mFApyb5IVgtG6w,14
21
- bisslog_flask-0.0.2.dist-info/RECORD,,