dmart 1.4.0__py3-none-any.whl → 1.4.2__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.
bundler.py CHANGED
@@ -2,7 +2,7 @@
2
2
  import json
3
3
  import subprocess
4
4
  import PyInstaller.__main__
5
-
5
+ import os
6
6
 
7
7
  branch_cmd = "git rev-parse --abbrev-ref HEAD"
8
8
  result, _ = subprocess.Popen(branch_cmd.split(" "), stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
@@ -29,8 +29,7 @@ info = {
29
29
 
30
30
  json.dump(info, open('info.json', 'w'))
31
31
 
32
-
33
- PyInstaller.__main__.run([
32
+ args = [
34
33
  'dmart.py',
35
34
  '--name=dmart',
36
35
  '--onefile',
@@ -41,4 +40,13 @@ PyInstaller.__main__.run([
41
40
  '--collect-submodules=concurrent_log_handler',
42
41
  '--collect-submodules=pythonjsonlogger',
43
42
  '--clean',
44
- ])
43
+ ]
44
+
45
+ cxb_path = 'cxb'
46
+ if not os.path.isdir(cxb_path):
47
+ cxb_path = '../cxb/dist/client'
48
+
49
+ if os.path.isdir(cxb_path):
50
+ args.append(f'--add-data={cxb_path}:cxb')
51
+
52
+ PyInstaller.__main__.run(args)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dmart
3
- Version: 1.4.0
3
+ Version: 1.4.2
4
4
  Requires-Python: >=3.11
5
5
  Requires-Dist: fastapi
6
6
  Requires-Dist: pydantic
@@ -1,8 +1,8 @@
1
- bundler.py,sha256=8gEQputdVfI8vda5Lkzw12blv7kYkmPLVbEWr_itLe0,1522
1
+ bundler.py,sha256=so8ZJResb1PcOH5vboa_mpFAdYr_T8u8DbbFXd570Lg,1704
2
2
  data_generator.py,sha256=CnE-VHEeX7-lAXtqCgbRqR9WHjTuOgeiZcviYrHAmho,2287
3
- dmart.py,sha256=VgNH7vpzHBO2FcMztdwZBLq1TovzbkBFkXrZwn6dKjI,19712
3
+ dmart.py,sha256=WugBannLMtYISbGPfK5Lak-2BPm14cFHNyJwkD-26RM,21711
4
4
  get_settings.py,sha256=Sbe2WCoiK398E7HY4SNLfDN_GmE8knR4M-YJWF31jcg,153
5
- main.py,sha256=XqKHlgFy_S_EtvbGsSxiCMSApSU33BlTpv8T4UWX0yc,17351
5
+ main.py,sha256=3UqzJUoiaZmcoL4yFInka5DMfh_-Agl-gHRCHELL2UM,19551
6
6
  migrate.py,sha256=hn1MZoVby_Jjqhc7y3CrLcGD619QmVZv3PONNvO7VKQ,665
7
7
  password_gen.py,sha256=xjx8wi105ZYvhLBBQj7_rugACpxifGXHse6f7YlGXWQ,196
8
8
  run_notification_campaign.py,sha256=ZCvHfaimK4W6q4XuHs2r6wavMGipYYw4aUkNlxmGUd8,2652
@@ -135,15 +135,15 @@ utils/query_policies_helper.py,sha256=jBcNI_15P6LqVeWz6w9UMreLuNIc50GxqAf17KzxE8
135
135
  utils/regex.py,sha256=cv9b_l_e8tz42mKckeeyDgypKqh2e71E28co2iuEVxA,2286
136
136
  utils/repository.py,sha256=9L-IvQ0Js0SQ5OR-Rh0i2Wdu4H9H06r8eE84hfBIu7Q,18313
137
137
  utils/router_helper.py,sha256=Tgoq3oakejdEeyeVieTNk38JsPZ8x5RuR0kw2THc1mI,604
138
- utils/settings.py,sha256=SIunwTJF0Ac9fUWRt3sUsgWzMkWk0RUryEANYuOJQ9k,5660
138
+ utils/settings.py,sha256=eWsIKxyFzeCO7Jte0U5SR8SiCLSXz0dD0vO0x-R-y2k,5686
139
139
  utils/sms_notifier.py,sha256=04D6D_ldk3S9SojI7_381pqLc8v9lligeNHAysohz7w,550
140
140
  utils/social_sso.py,sha256=Dm1W6U9OwKbAeUwM-kwJBHFEoreeoN-s-RHdOZ1-cNg,2216
141
141
  utils/ticket_sys_utils.py,sha256=9QAlW2iiy8KyxQRBDj_WmzS5kKb0aYJmGwd4qzmGVqo,7005
142
142
  utils/web_notifier.py,sha256=QM87VVid2grC5lK3NdS1yzz0z1wXljr4GChJOeK86W4,843
143
143
  utils/templates/activation.html.j2,sha256=XAMKCdoqONoc4ZQucD0yV-Pg5DlHHASZrTVItNS-iBE,640
144
144
  utils/templates/reminder.html.j2,sha256=aoS8bTs56q4hjAZKsb0jV9c-PIURBELuBOpT_qPZNVU,639
145
- dmart-1.4.0.dist-info/METADATA,sha256=vxNYgfiH0Y8TWKyFOmiXTx69CA-SOILtIqnt2Mj-7kY,2068
146
- dmart-1.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
147
- dmart-1.4.0.dist-info/entry_points.txt,sha256=GjfoGh1bpxuU9HHGJzbtCFPNptHv9TryxHMN3uBSKpg,37
148
- dmart-1.4.0.dist-info/top_level.txt,sha256=JTypu1r5v9v7ru-60JSSbnSMEESHFRMacpcz-rPJx_U,262
149
- dmart-1.4.0.dist-info/RECORD,,
145
+ dmart-1.4.2.dist-info/METADATA,sha256=Kyjoer4hkgh3VhudnHtnbyuJO5ZJzjfheq2QihC6sPI,2068
146
+ dmart-1.4.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
147
+ dmart-1.4.2.dist-info/entry_points.txt,sha256=GjfoGh1bpxuU9HHGJzbtCFPNptHv9TryxHMN3uBSKpg,37
148
+ dmart-1.4.2.dist-info/top_level.txt,sha256=JTypu1r5v9v7ru-60JSSbnSMEESHFRMacpcz-rPJx_U,262
149
+ dmart-1.4.2.dist-info/RECORD,,
dmart.py CHANGED
@@ -11,6 +11,7 @@ import subprocess
11
11
  import sys
12
12
  import time
13
13
  import warnings
14
+ import webbrowser
14
15
  from multiprocessing import freeze_support
15
16
  from pathlib import Path
16
17
 
@@ -29,6 +30,7 @@ from utils.settings import settings
29
30
  freeze_support()
30
31
 
31
32
  commands = """ server
33
+ serve
32
34
  hyper
33
35
  health-check
34
36
  create-index
@@ -49,7 +51,10 @@ sentinel = object()
49
51
  def hypercorn_main() -> int:
50
52
  parser = argparse.ArgumentParser()
51
53
  parser.add_argument(
52
- "application", help="The application to dispatch to as path.to.module:instance.path"
54
+ "application",
55
+ help="The application to dispatch to as path.to.module:instance.path",
56
+ nargs="?",
57
+ default="main:app"
53
58
  )
54
59
  parser.add_argument("--access-log", help="Deprecated, see access-logfile", default=sentinel)
55
60
  parser.add_argument(
@@ -83,7 +88,7 @@ def hypercorn_main() -> int:
83
88
  "-c",
84
89
  "--config",
85
90
  help="Location of a TOML config file, or when prefixed with `file:` a Python file, or when prefixed with `python:` a Python module.", # noqa: E501
86
- default=None,
91
+ default="hypercorn_config.toml",
87
92
  )
88
93
  parser.add_argument(
89
94
  "--debug",
@@ -210,6 +215,17 @@ def hypercorn_main() -> int:
210
215
  parser.add_argument(
211
216
  "-u", "--user", help="User to own any unix sockets.", default=sentinel, type=int
212
217
  )
218
+ parser.add_argument(
219
+ "--open-cxb",
220
+ help="Open CXB page in browser after server starts",
221
+ action="store_true",
222
+ default=False,
223
+ )
224
+ parser.add_argument(
225
+ "--cxb-config",
226
+ help="Path to CXB config.json",
227
+ default=sentinel,
228
+ )
213
229
 
214
230
  def _convert_verify_mode(value: str) -> ssl.VerifyMode:
215
231
  try:
@@ -314,6 +330,9 @@ def hypercorn_main() -> int:
314
330
  config.websocket_ping_interval = args.websocket_ping_interval
315
331
  if args.workers is not sentinel:
316
332
  config.workers = args.workers
333
+
334
+ if args.cxb_config is not sentinel:
335
+ os.environ["DMART_CXB_CONFIG"] = args.cxb_config
317
336
 
318
337
  if len(args.binds) > 0:
319
338
  config.bind = args.binds
@@ -323,6 +342,32 @@ def hypercorn_main() -> int:
323
342
  config.quic_bind = args.quic_binds
324
343
  if len(args.server_names) > 0:
325
344
  config.server_names = args.server_names
345
+
346
+ if args.open_cxb:
347
+ # Assuming default port 8282 if not specified in binds
348
+ port = 8282
349
+ host = "127.0.0.1"
350
+
351
+ # Try to parse bind address if available
352
+ if len(args.binds) > 0:
353
+ try:
354
+ bind_parts = args.binds[0].split(":")
355
+ if len(bind_parts) == 2:
356
+ host = bind_parts[0]
357
+ port = int(bind_parts[1])
358
+ elif len(bind_parts) == 1:
359
+ host = bind_parts[0]
360
+ except:
361
+ pass
362
+
363
+ url = f"http://{host}:{port}{settings.cxb_url}/"
364
+
365
+ def open_browser():
366
+ time.sleep(2) # Give server a moment to start
367
+ webbrowser.open(url)
368
+
369
+ import threading
370
+ threading.Thread(target=open_browser, daemon=True).start()
326
371
 
327
372
  return run(config)
328
373
 
@@ -336,13 +381,30 @@ def main():
336
381
 
337
382
  match sys.argv[0]:
338
383
  case "hyper":
339
- if len(sys.argv) == 1:
340
- print("Running Hypercorn with default settings")
341
- default_params = "main:app --config hypercorn_config.toml"
342
- print(f">{default_params}")
343
- sys.argv = ["hyper"] + default_params.split(" ")
344
384
  hypercorn_main()
345
- case "server":
385
+ case "server" | "serve":
386
+ # Check for --open-cxb flag in server command arguments
387
+ open_cxb = False
388
+ if "--open-cxb" in sys.argv:
389
+ open_cxb = True
390
+ sys.argv.remove("--open-cxb")
391
+
392
+ if "--cxb-config" in sys.argv:
393
+ idx = sys.argv.index("--cxb-config")
394
+ if idx + 1 < len(sys.argv):
395
+ os.environ["DMART_CXB_CONFIG"] = sys.argv[idx + 1]
396
+ sys.argv.pop(idx + 1)
397
+ sys.argv.pop(idx)
398
+
399
+ if open_cxb:
400
+ url = f"http://{settings.listening_host}:{settings.listening_port}{settings.cxb_url}/"
401
+ def open_browser():
402
+ time.sleep(2) # Give server a moment to start
403
+ webbrowser.open(url)
404
+
405
+ import threading
406
+ threading.Thread(target=open_browser, daemon=True).start()
407
+
346
408
  asyncio.run(server())
347
409
  case "health-check":
348
410
  parser = argparse.ArgumentParser(
main.py CHANGED
@@ -5,6 +5,7 @@ from starlette.datastructures import UploadFile
5
5
  from contextlib import asynccontextmanager
6
6
  import asyncio
7
7
  import json
8
+ import os
8
9
  from os import getpid
9
10
  import sys
10
11
  import time
@@ -24,11 +25,12 @@ from fastapi.logger import logger
24
25
  from fastapi.encoders import jsonable_encoder
25
26
  from fastapi.exceptions import RequestValidationError
26
27
  from utils.access_control import access_control
27
- from fastapi.responses import ORJSONResponse
28
+ from fastapi.responses import ORJSONResponse, FileResponse
28
29
  from hypercorn.asyncio import serve
29
30
  from hypercorn.config import Config
30
31
  from starlette.concurrency import iterate_in_threadpool
31
32
  from starlette.exceptions import HTTPException as StarletteHTTPException
33
+ from starlette.staticfiles import StaticFiles
32
34
  import models.api as api
33
35
  from utils.settings import settings
34
36
  from asgi_correlation_id import CorrelationIdMiddleware
@@ -462,6 +464,51 @@ app.include_router(
462
464
  # load plugins
463
465
  asyncio.run(plugin_manager.load_plugins(app, capture_body))
464
466
 
467
+ # Serve CXB
468
+ cxb_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cxb")
469
+ if not os.path.exists(cxb_path):
470
+ # Try relative to project root (development mode)
471
+ project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
472
+ cxb_dist_path = os.path.join(project_root, "cxb", "dist", "client")
473
+ if os.path.isdir(cxb_dist_path):
474
+ cxb_path = cxb_dist_path
475
+
476
+ if os.path.isdir(cxb_path):
477
+ @app.get(f"{settings.cxb_url}/config.json", include_in_schema=False)
478
+ async def get_cxb_config():
479
+ # Priority 0: Explicit path from flag
480
+ cxb_config = os.getenv("DMART_CXB_CONFIG")
481
+ if cxb_config and os.path.exists(cxb_config):
482
+ return FileResponse(cxb_config)
483
+
484
+ # Priority 1: Check in current directory (where dmart is run)
485
+ if os.path.exists("config.json"):
486
+ return FileResponse("config.json")
487
+
488
+ # Priority 2: Check in spaces folder (user directory)
489
+ user_config = settings.spaces_folder / "config.json"
490
+ if user_config.exists():
491
+ return FileResponse(user_config)
492
+
493
+ # Priority 3: Check in bundled CXB directory
494
+ bundled_config = os.path.join(cxb_path, "config.json")
495
+ if os.path.exists(bundled_config):
496
+ return FileResponse(bundled_config)
497
+
498
+ # Fallback to defaults generated from settings
499
+ return {
500
+ "title": "DMART Unified Data Platform",
501
+ "footer": "dmart.cc unified data platform",
502
+ "short_name": "dmart",
503
+ "display_name": "dmart",
504
+ "description": "dmart unified data platform",
505
+ "default_language": "en",
506
+ "languages": { "ar": "العربية", "en": "English" },
507
+ "backend": f"{settings.app_url}" if settings.app_url else f"http://{settings.listening_host}:{settings.listening_port}",
508
+ "websocket": settings.websocket_url if settings.websocket_url else f"ws://{settings.listening_host}:{settings.websocket_port}/ws"
509
+ }
510
+
511
+ app.mount(settings.cxb_url, StaticFiles(directory=cxb_path, html=True), name="cxb")
465
512
 
466
513
  @app.options("/{x:path}", include_in_schema=False)
467
514
  async def myoptions():
@@ -503,4 +550,3 @@ if __name__ == "__main__":
503
550
  asyncio.run(main())
504
551
  except Exception as e:
505
552
  print("[!1server]", e)
506
-
utils/settings.py CHANGED
@@ -16,6 +16,7 @@ class Settings(BaseSettings):
16
16
  """Main settings class"""
17
17
 
18
18
  app_url: str = ""
19
+ cxb_url: str = "/cxb"
19
20
  public_app_url: str = ""
20
21
  app_name: str = "dmart"
21
22
  websocket_url: str = "" #"http://127.0.0.1:8484"
File without changes