dmart 0.1.0__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 (106) hide show
  1. alembic/__init__.py +0 -0
  2. alembic/env.py +91 -0
  3. api/__init__.py +0 -0
  4. api/info/__init__.py +0 -0
  5. api/info/router.py +109 -0
  6. api/managed/__init__.py +0 -0
  7. api/managed/router.py +1541 -0
  8. api/managed/utils.py +1850 -0
  9. api/public/__init__.py +0 -0
  10. api/public/router.py +758 -0
  11. api/qr/__init__.py +0 -0
  12. api/qr/router.py +108 -0
  13. api/user/__init__.py +0 -0
  14. api/user/router.py +1401 -0
  15. api/user/service.py +270 -0
  16. bundler.py +44 -0
  17. config/__init__.py +0 -0
  18. config/channels.json +11 -0
  19. config/notification.json +17 -0
  20. data_adapters/__init__.py +0 -0
  21. data_adapters/adapter.py +16 -0
  22. data_adapters/base_data_adapter.py +467 -0
  23. data_adapters/file/__init__.py +0 -0
  24. data_adapters/file/adapter.py +2043 -0
  25. data_adapters/file/adapter_helpers.py +1013 -0
  26. data_adapters/file/archive.py +150 -0
  27. data_adapters/file/create_index.py +331 -0
  28. data_adapters/file/create_users_folders.py +52 -0
  29. data_adapters/file/custom_validations.py +68 -0
  30. data_adapters/file/drop_index.py +40 -0
  31. data_adapters/file/health_check.py +560 -0
  32. data_adapters/file/redis_services.py +1110 -0
  33. data_adapters/helpers.py +27 -0
  34. data_adapters/sql/__init__.py +0 -0
  35. data_adapters/sql/adapter.py +3210 -0
  36. data_adapters/sql/adapter_helpers.py +491 -0
  37. data_adapters/sql/create_tables.py +451 -0
  38. data_adapters/sql/create_users_folders.py +53 -0
  39. data_adapters/sql/db_to_json_migration.py +482 -0
  40. data_adapters/sql/health_check_sql.py +232 -0
  41. data_adapters/sql/json_to_db_migration.py +454 -0
  42. data_adapters/sql/update_query_policies.py +101 -0
  43. data_generator.py +81 -0
  44. dmart-0.1.0.dist-info/METADATA +27 -0
  45. dmart-0.1.0.dist-info/RECORD +106 -0
  46. dmart-0.1.0.dist-info/WHEEL +5 -0
  47. dmart-0.1.0.dist-info/entry_points.txt +2 -0
  48. dmart-0.1.0.dist-info/top_level.txt +23 -0
  49. dmart.py +513 -0
  50. get_settings.py +7 -0
  51. languages/__init__.py +0 -0
  52. languages/arabic.json +15 -0
  53. languages/english.json +16 -0
  54. languages/kurdish.json +14 -0
  55. languages/loader.py +13 -0
  56. main.py +506 -0
  57. migrate.py +24 -0
  58. models/__init__.py +0 -0
  59. models/api.py +203 -0
  60. models/core.py +597 -0
  61. models/enums.py +255 -0
  62. password_gen.py +8 -0
  63. plugins/__init__.py +0 -0
  64. pytests/__init__.py +0 -0
  65. pytests/api_user_models_erros_test.py +16 -0
  66. pytests/api_user_models_requests_test.py +98 -0
  67. pytests/archive_test.py +72 -0
  68. pytests/base_test.py +300 -0
  69. pytests/get_settings_test.py +14 -0
  70. pytests/json_to_db_migration_test.py +237 -0
  71. pytests/service_test.py +26 -0
  72. pytests/test_info.py +55 -0
  73. pytests/test_status.py +15 -0
  74. run_notification_campaign.py +98 -0
  75. scheduled_notification_handler.py +121 -0
  76. schema_migration.py +208 -0
  77. schema_modulate.py +192 -0
  78. set_admin_passwd.py +55 -0
  79. sync.py +202 -0
  80. utils/__init__.py +0 -0
  81. utils/access_control.py +306 -0
  82. utils/async_request.py +8 -0
  83. utils/exporter.py +309 -0
  84. utils/firebase_notifier.py +57 -0
  85. utils/generate_email.py +38 -0
  86. utils/helpers.py +352 -0
  87. utils/hypercorn_config.py +12 -0
  88. utils/internal_error_code.py +60 -0
  89. utils/jwt.py +124 -0
  90. utils/logger.py +167 -0
  91. utils/middleware.py +99 -0
  92. utils/notification.py +75 -0
  93. utils/password_hashing.py +16 -0
  94. utils/plugin_manager.py +215 -0
  95. utils/query_policies_helper.py +112 -0
  96. utils/regex.py +44 -0
  97. utils/repository.py +529 -0
  98. utils/router_helper.py +19 -0
  99. utils/settings.py +165 -0
  100. utils/sms_notifier.py +21 -0
  101. utils/social_sso.py +67 -0
  102. utils/templates/activation.html.j2 +26 -0
  103. utils/templates/reminder.html.j2 +17 -0
  104. utils/ticket_sys_utils.py +203 -0
  105. utils/web_notifier.py +29 -0
  106. websocket.py +231 -0
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env -S BACKEND_ENV=config.env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import asyncio
6
+ from typing import Sequence
7
+
8
+ from sqlalchemy import URL, select, update as sa_update
9
+ from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
10
+ # AsyncSession
11
+ from sqlalchemy.orm import sessionmaker
12
+ from sqlmodel import col
13
+
14
+ from utils.settings import settings
15
+ from utils.query_policies_helper import generate_query_policies
16
+ from data_adapters.sql.create_tables import Entries
17
+
18
+
19
+ async def update_all_entries(batch_size: int = 1000) -> int:
20
+ postgresql_url = URL.create(
21
+ drivername=settings.database_driver.replace('+asyncpg', '+psycopg'),
22
+ host=settings.database_host,
23
+ port=settings.database_port,
24
+ username=settings.database_username,
25
+ password=settings.database_password,
26
+ database=settings.database_name,
27
+ )
28
+
29
+ engine = create_async_engine(
30
+ postgresql_url,
31
+ echo=False,
32
+ pool_size=settings.database_pool_size,
33
+ max_overflow=settings.database_max_overflow,
34
+ pool_timeout=settings.database_pool_timeout,
35
+ pool_recycle=settings.database_pool_recycle,
36
+ )
37
+ async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) # type: ignore
38
+
39
+ updated = 0
40
+ offset = 0
41
+
42
+ async with async_session() as session: # type: ignore
43
+ while True:
44
+ result = await session.execute(
45
+ select(Entries).order_by(Entries.space_name, Entries.subpath, Entries.shortname).offset(offset).limit(batch_size)
46
+ )
47
+ rows: Sequence[Entries] = [row[0] if not isinstance(row, Entries) else row for row in result.fetchall()]
48
+ if not rows:
49
+ break
50
+ print(f"Processing {len(rows)} entries...")
51
+ for row in rows:
52
+ try:
53
+ new_policies = generate_query_policies(
54
+ space_name=row.space_name,
55
+ subpath=row.subpath,
56
+ resource_type=row.resource_type,
57
+ is_active=row.is_active,
58
+ owner_shortname=getattr(row, 'owner_shortname', 'dmart') or 'dmart',
59
+ owner_group_shortname=getattr(row, 'owner_group_shortname', None),
60
+ entry_shortname=row.shortname if row.resource_type == 'folder' else None,
61
+ )
62
+ except Exception as e:
63
+ print(f"Error while computing query_policies for {row.space_name}/{row.subpath}/{row.shortname}")
64
+ print(f"| {e}\n")
65
+ continue
66
+
67
+ if row.query_policies != new_policies:
68
+ await session.execute(
69
+ sa_update(Entries)
70
+ .where(col(Entries.space_name) == row.space_name)
71
+ .where(col(Entries.subpath) == row.subpath)
72
+ .where(col(Entries.shortname) == row.shortname)
73
+ .values(query_policies=new_policies)
74
+ )
75
+ updated += 1
76
+ try:
77
+ await session.commit()
78
+ except Exception:
79
+ await session.rollback()
80
+ raise
81
+
82
+ offset += len(rows)
83
+
84
+ await engine.dispose()
85
+ return updated
86
+
87
+
88
+ async def amain(batch_size: int) -> None:
89
+ updated = await update_all_entries(batch_size=batch_size)
90
+ print(f"Updated query_policies for {updated} entries.")
91
+
92
+
93
+ def main():
94
+ parser = argparse.ArgumentParser(description="Recompute query_policies for all Entries")
95
+ parser.add_argument("--batch-size", type=int, default=1000, help="Batch size for processing entries")
96
+ args = parser.parse_args()
97
+ asyncio.run(amain(args.batch_size))
98
+
99
+
100
+ if __name__ == "__main__":
101
+ main()
data_generator.py ADDED
@@ -0,0 +1,81 @@
1
+ import argparse
2
+ import asyncio
3
+ from pathlib import Path
4
+ from uuid import uuid4
5
+ from models.core import Content, Payload
6
+ from models.enums import ContentType
7
+ from jsf import JSF # type: ignore
8
+ from data_adapters.adapter import data_adapter as db
9
+
10
+
11
+ async def main(
12
+ space: str,
13
+ subpath: str,
14
+ schema_path: str,
15
+ num: int
16
+ ):
17
+
18
+ if not Path(schema_path).is_file():
19
+ print("Invalid schema file path")
20
+
21
+
22
+ faker = JSF.from_json(Path(schema_path)) # type: ignore
23
+ for i in range(0, num):
24
+ payload = faker.generate()
25
+ uuid = uuid4()
26
+ shortname = str(uuid)[:8]
27
+ meta = Content(
28
+ uuid = uuid,
29
+ shortname = shortname,
30
+ is_active=True,
31
+ owner_shortname="generator_script",
32
+ payload=Payload(
33
+ content_type=ContentType.json,
34
+ schema_shortname=schema_path.split("/")[-1].split(".")[0],
35
+ body=f"{shortname}.json"
36
+ )
37
+ )
38
+ await db.internal_save_model(
39
+ space_name=space,
40
+ subpath=subpath,
41
+ meta=meta,
42
+ payload=payload
43
+ )
44
+ print(f"Generated new doc with shortname: {shortname}")
45
+
46
+ print("====================================================")
47
+ print(f"The generator script is finished, {num} of records generated")
48
+ print("====================================================")
49
+
50
+
51
+
52
+
53
+ if __name__ == "__main__":
54
+ parser = argparse.ArgumentParser(
55
+ description="Generate fake records based on a specific schema,\
56
+ it only creates resources of type Content.\
57
+ Stores the data in the flat-file DB and Redis",
58
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter
59
+ )
60
+
61
+ parser.add_argument(
62
+ "-p", "--space", help="Store records under this space"
63
+ )
64
+ parser.add_argument(
65
+ "-s", "--subpath", help="Store records under this subpath"
66
+ )
67
+ parser.add_argument(
68
+ "-c", "--schema-path", help="Generate records according to this schema (path)"
69
+ )
70
+ parser.add_argument(
71
+ "-n", "--num", help="Number of records to be generated", type=int
72
+ )
73
+
74
+ args = parser.parse_args()
75
+
76
+ asyncio.run(main(
77
+ args.space,
78
+ args.subpath,
79
+ args.schema_path,
80
+ args.num
81
+ ))
@@ -0,0 +1,27 @@
1
+ Metadata-Version: 2.4
2
+ Name: dmart
3
+ Version: 0.1.0
4
+ Requires-Python: >=3.10
5
+ Requires-Dist: hypercorn
6
+ Requires-Dist: fastapi
7
+ Requires-Dist: uvicorn
8
+ Requires-Dist: pydantic
9
+ Requires-Dist: starlette
10
+ Requires-Dist: python-multipart
11
+ Requires-Dist: orjson
12
+ Requires-Dist: asgi-correlation-id
13
+ Requires-Dist: jsonschema
14
+ Requires-Dist: sqlmodel
15
+ Requires-Dist: sqlalchemy
16
+ Requires-Dist: alembic
17
+ Requires-Dist: asyncpg
18
+ Requires-Dist: redis
19
+ Requires-Dist: httpx
20
+ Requires-Dist: jinja2
21
+ Requires-Dist: python-jose[cryptography]
22
+ Requires-Dist: passlib[bcrypt]
23
+ Requires-Dist: python-dotenv
24
+ Requires-Dist: aiofiles
25
+ Requires-Dist: requests
26
+ Dynamic: requires-dist
27
+ Dynamic: requires-python
@@ -0,0 +1,106 @@
1
+ bundler.py,sha256=8gEQputdVfI8vda5Lkzw12blv7kYkmPLVbEWr_itLe0,1522
2
+ data_generator.py,sha256=CnE-VHEeX7-lAXtqCgbRqR9WHjTuOgeiZcviYrHAmho,2287
3
+ dmart.py,sha256=VgNH7vpzHBO2FcMztdwZBLq1TovzbkBFkXrZwn6dKjI,19712
4
+ get_settings.py,sha256=Sbe2WCoiK398E7HY4SNLfDN_GmE8knR4M-YJWF31jcg,153
5
+ main.py,sha256=XqKHlgFy_S_EtvbGsSxiCMSApSU33BlTpv8T4UWX0yc,17351
6
+ migrate.py,sha256=hn1MZoVby_Jjqhc7y3CrLcGD619QmVZv3PONNvO7VKQ,665
7
+ password_gen.py,sha256=xjx8wi105ZYvhLBBQj7_rugACpxifGXHse6f7YlGXWQ,196
8
+ run_notification_campaign.py,sha256=wKo8B79eiATOmAnxXsOJkSvb5BGwZTAQuxN6-HfA7Ws,2907
9
+ scheduled_notification_handler.py,sha256=m26TryqHuvXR5PUPvzY9nFnpJpfbsuRjc_Q6wHdxvE8,4643
10
+ schema_migration.py,sha256=a1w3c-fSm95MVWFzobgy0AxIbhbzMDSfD46easTmwKE,6132
11
+ schema_modulate.py,sha256=U1OqtnXycskyf1DrUyVVgVs0sDpGWu60ogEqHRkod_Q,6455
12
+ set_admin_passwd.py,sha256=Ei8wnoJ_UDHIXmMb-E_dd_NqyM6Gt5AgJPJ4fAxARXI,1950
13
+ sync.py,sha256=FlmubtlnFaxtZkbRV1-eyS_Sx5KBRvWyIZjvd0Tiar4,7339
14
+ websocket.py,sha256=Q8WUTvOTBHKP5xy5wim8yn0t-BfjrPwx7J_6vbzAm1A,7576
15
+ alembic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ alembic/env.py,sha256=z12UKhorKSOKEovOCQOwRjfR_tup4VeRlhcB1UPk3Xw,2700
17
+ api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ api/info/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
+ api/info/router.py,sha256=sQZZor7A-uDzsJX39aqEA7bMZOJ-WTitYeFvVNWfaHw,3938
20
+ api/managed/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
+ api/managed/router.py,sha256=0xfJ3NXV3XHyG8yWLEECBJt-XppymOxYuMDvQJdO1MI,50865
22
+ api/managed/utils.py,sha256=OZgqqWAKMXqhFOloBcm85KiE4BpZ8h0CNffK8O7Pc7c,72639
23
+ api/public/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ api/public/router.py,sha256=TrraWs2LGL_c_JRDbvS8OHm3fJ-ZKF7o4El7wvjV4Mk,24753
25
+ api/qr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
+ api/qr/router.py,sha256=Ru7UT_iQS6mFwE1bCPPrusSQfFgoV_u6pjZJ0gArE7g,3870
27
+ api/user/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ api/user/router.py,sha256=FwuxM04niGlls-V1MPzHH5A4jHJ0g5NNIFZBE6bJ9Fc,51302
29
+ api/user/service.py,sha256=-iQpcBVPTDiLE_xOf87Ni0oSQDtmALAXEwU4IgSvnJk,8463
30
+ config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
+ config/channels.json,sha256=GepystGi0h_1fuakC_gdIc-YYxyy-a4TI619ygIpyyM,156
32
+ config/notification.json,sha256=esrOaMUIqfcCHB0Tawp3t4cu7DQAA15X12OS-Gyenb0,361
33
+ data_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ data_adapters/adapter.py,sha256=zR_yFd5ZI9vIQuUB6AUcF-LHgxOaxoREV2hogasivjQ,443
35
+ data_adapters/base_data_adapter.py,sha256=vG9WeHyw_c_BnH0EmudwPSNS6iMb5buQJiZS_9cm9p8,12055
36
+ data_adapters/helpers.py,sha256=0ySEDnQBMgFVXstFnPjXLtZ_-8IC4Q8oPXXrWokpFB8,660
37
+ data_adapters/file/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
+ data_adapters/file/adapter.py,sha256=SPVVfRIlyQDYfZJv4J8LmrDGtrVWddu76SvpnkXY3jM,77671
39
+ data_adapters/file/adapter_helpers.py,sha256=ExA_fAnRaPOLDuEY3hsLNR2BvvCscnS5Du6lWRtCvh0,34321
40
+ data_adapters/file/archive.py,sha256=B4VV6HNB3Bqd4tlqZ3jUQps8oqht_xOdBNOi9cLuo8Q,5423
41
+ data_adapters/file/create_index.py,sha256=lUcUkepo9QUIQDDDgoPAL74_n16cZ_q0NKnITGmbF6I,11888
42
+ data_adapters/file/create_users_folders.py,sha256=zOBgxMnqgEskYP4pgkmE6VYMca-ADLz8mXKPHJPYpys,1670
43
+ data_adapters/file/custom_validations.py,sha256=ziOERgTr-eY_zrN0C41B2FYmpEyoKiV4holh8an-p2c,1754
44
+ data_adapters/file/drop_index.py,sha256=OK3wXwaO9tUcHcJjqyLeBnkElzK35MZMi8YLGWdrXRw,1417
45
+ data_adapters/file/health_check.py,sha256=cMvwsXhjEykjrTyB3HtUn8QqKdtB_h5w8mGOEYPepzU,24221
46
+ data_adapters/file/redis_services.py,sha256=83STcca5fYFaEVLRYAxfUQXeUQZqJOT8XH-GBSbkR-E,39914
47
+ data_adapters/sql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ data_adapters/sql/adapter.py,sha256=xdd5EcZU1fF4GTBxSg4BUyKvd8o95kcf1FqtPHUN2u8,154514
49
+ data_adapters/sql/adapter_helpers.py,sha256=Eu22NElz2fMu6zyOsGsGrnAZcyWhHz9I__RJ9z6cwK0,15076
50
+ data_adapters/sql/create_tables.py,sha256=KqaXHTDOD8YaqGNc_e0iHHotd0WE3Kad_tBevtoGA20,17427
51
+ data_adapters/sql/create_users_folders.py,sha256=fm3P-CMcPX4b4DqXHKWMOtfX4RHdaev2nCDhYrS5cIs,1911
52
+ data_adapters/sql/db_to_json_migration.py,sha256=mHMaD2tTsXaNPTd6nGuMb4TQheklYNWNvgszOZKM22E,20850
53
+ data_adapters/sql/health_check_sql.py,sha256=2Z0mN5IMrjF72ZAiafBLkHklbXXWJzLp1K2TzjzPI1s,8569
54
+ data_adapters/sql/json_to_db_migration.py,sha256=KaubDrRZ3MfPLc-CNGPpsEccPELKr1V4GoBEBt1BNZo,21131
55
+ data_adapters/sql/update_query_policies.py,sha256=LUpkyzDAkiwwVWnXxPdVAU6atehW72ECAazj3mEYHK0,3857
56
+ languages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
+ languages/arabic.json,sha256=UL61rP9_M42CGfU94G5-1bXVUVnsJWXzoqhaXTXTJuM,910
58
+ languages/english.json,sha256=Y7eZ2X8c427_97qYrHOeGb2d725T-YlNNFVSi8FB7Kw,649
59
+ languages/kurdish.json,sha256=GgPLkVKyhIQjT7h3cPfDh0oyzg26znvBUe5X_Zz2TWI,864
60
+ languages/loader.py,sha256=yaBJHGVRxi8Z-H8x4MOQcwyhiY0zD9UY-m0AjLi4eq8,393
61
+ models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
62
+ models/api.py,sha256=f5X56dudyEysPmDuI5grM2RRCXuIQoehaAB6wMAGG28,6473
63
+ models/core.py,sha256=tEb7cbnC71yE9SDluynj7dE3U8Ed-EbF3uRJizy-uuU,16880
64
+ models/enums.py,sha256=y2G5EKIc8FusVW4JvEozGFKL2GxjtuOK7k3zSguP4dc,5395
65
+ plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
+ pytests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
+ pytests/api_user_models_erros_test.py,sha256=6VWLIhazYjz7avXIMIDpT6doiBO5FVzGsGJ3Cv8cXyg,583
68
+ pytests/api_user_models_requests_test.py,sha256=1AYZcMwa-AVeGrhTgwIkwqw3w7_CDPkbaJ0YDxLLKdY,3859
69
+ pytests/archive_test.py,sha256=rk6jEZf-Ud7ReyH4_xJD-9SzNRz8p2Sg0qQX04VCw9M,2347
70
+ pytests/base_test.py,sha256=d8prlME29tBnirW-3_HUtixcxUMPiLfJHRDiNkxOCRM,9902
71
+ pytests/get_settings_test.py,sha256=AEqjnHsQjkVDqwVqtn2rN6mep4sAC_apDCgiZT4YQ28,281
72
+ pytests/json_to_db_migration_test.py,sha256=JXO0knKPccXVIbKmyuD0yOi5fSBHmXm_NgVdO1_U7AE,9411
73
+ pytests/service_test.py,sha256=92lqzKQoVMkj9XliPBjkGBxXb4zXsobb2WPfW5buQfc,807
74
+ pytests/test_info.py,sha256=IOKtcEPM_03byhp5dSt2YbhTC5u_ORPahQLifZWBpjg,2074
75
+ pytests/test_status.py,sha256=YFuBTsSd5hkpHp16GAbQ_I03RL_o2_yW-92ZNgKJry0,453
76
+ utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
+ utils/access_control.py,sha256=8cCKr-6bL-Shl8j8xtfjEykMPGy6wkbNz-NRwLCdx-Y,11757
78
+ utils/async_request.py,sha256=Lm2xGXLeph7P1_fLhhNJDhPubKT2ncFn_Ueft4JVoeI,255
79
+ utils/exporter.py,sha256=HjcZCzcuH6N6f7Gn2hkTEeEFyo-MfrsiZUYAE-9kkVQ,9718
80
+ utils/firebase_notifier.py,sha256=nAeCUo5Mtwxygwj8ONlw8ZAtL_ekdJBabvU0z2dZ3NY,2391
81
+ utils/generate_email.py,sha256=_yHJiYp9dd1IT2lL2N2VmPrsCuKN30YTmE0votM9It8,1132
82
+ utils/helpers.py,sha256=gNxLg09cclRWrKNBy2pwGZsxGA0iFS5iZ_nyra3SmnI,9928
83
+ utils/hypercorn_config.py,sha256=q28HGRLWo9wjOVF183WwFPs3HQo4Nexc7q_7dmSVHRI,311
84
+ utils/internal_error_code.py,sha256=KGlXPC5YruPmb0ORVY7U3EEVpBgSLuU4lHdXgwUVN2M,1637
85
+ utils/jwt.py,sha256=Y7Gp3imvNwAtWOg8V0etvsEFtswmCYKK_U4ljZ15Pps,4590
86
+ utils/logger.py,sha256=peejQnq9B0eaHwdLynBHT7FUCq7jCX_DhkX6BcxrLkA,5274
87
+ utils/middleware.py,sha256=PAVwnLzs0cyT_ZIgc1slqadEOJNCPliLhOTjaYx0Waw,3399
88
+ utils/notification.py,sha256=O9oOeU9cRm3e9UAc-VJONWx-TzqbCMddFNaTQilE6ks,2479
89
+ utils/password_hashing.py,sha256=NZZsmtPG9Vkocipk3DlDKKHKUdxRKA4yOhCurD8dUhg,356
90
+ utils/plugin_manager.py,sha256=nIu99A8BWDhGerL880o5K9pCVQZbnjHJPNo1wQ_UbfU,7900
91
+ utils/query_policies_helper.py,sha256=jBcNI_15P6LqVeWz6w9UMreLuNIc50GxqAf17KzxE84,4392
92
+ utils/regex.py,sha256=cv9b_l_e8tz42mKckeeyDgypKqh2e71E28co2iuEVxA,2286
93
+ utils/repository.py,sha256=9L-IvQ0Js0SQ5OR-Rh0i2Wdu4H9H06r8eE84hfBIu7Q,18313
94
+ utils/router_helper.py,sha256=Tgoq3oakejdEeyeVieTNk38JsPZ8x5RuR0kw2THc1mI,604
95
+ utils/settings.py,sha256=jKesIr67J9RP-QwrzsUQzXRAGjqpvYGUhmPuGY_GNpI,5639
96
+ utils/sms_notifier.py,sha256=04D6D_ldk3S9SojI7_381pqLc8v9lligeNHAysohz7w,550
97
+ utils/social_sso.py,sha256=Dm1W6U9OwKbAeUwM-kwJBHFEoreeoN-s-RHdOZ1-cNg,2216
98
+ utils/ticket_sys_utils.py,sha256=9QAlW2iiy8KyxQRBDj_WmzS5kKb0aYJmGwd4qzmGVqo,7005
99
+ utils/web_notifier.py,sha256=QM87VVid2grC5lK3NdS1yzz0z1wXljr4GChJOeK86W4,843
100
+ utils/templates/activation.html.j2,sha256=XAMKCdoqONoc4ZQucD0yV-Pg5DlHHASZrTVItNS-iBE,640
101
+ utils/templates/reminder.html.j2,sha256=aoS8bTs56q4hjAZKsb0jV9c-PIURBELuBOpT_qPZNVU,639
102
+ dmart-0.1.0.dist-info/METADATA,sha256=rm_Na57-78i5hLWFnXurWbuYeB0xqxZbOzoN2xRbKPU,665
103
+ dmart-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
104
+ dmart-0.1.0.dist-info/entry_points.txt,sha256=GjfoGh1bpxuU9HHGJzbtCFPNptHv9TryxHMN3uBSKpg,37
105
+ dmart-0.1.0.dist-info/top_level.txt,sha256=JTypu1r5v9v7ru-60JSSbnSMEESHFRMacpcz-rPJx_U,262
106
+ dmart-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ dmart = dmart:main
@@ -0,0 +1,23 @@
1
+ alembic
2
+ api
3
+ bundler
4
+ config
5
+ data_adapters
6
+ data_generator
7
+ dmart
8
+ get_settings
9
+ languages
10
+ main
11
+ migrate
12
+ models
13
+ password_gen
14
+ plugins
15
+ pytests
16
+ run_notification_campaign
17
+ scheduled_notification_handler
18
+ schema_migration
19
+ schema_modulate
20
+ set_admin_passwd
21
+ sync
22
+ utils
23
+ websocket