aird 0.4.23.dev17__tar.gz → 0.4.23.dev18__tar.gz

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 (209) hide show
  1. {aird-0.4.23.dev17/aird.egg-info → aird-0.4.23.dev18}/PKG-INFO +2 -1
  2. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/constants/__init__.py +1 -1
  3. aird-0.4.23.dev18/aird/event_loop.py +34 -0
  4. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/file_op_handlers.py +1 -1
  5. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/main.py +4 -0
  6. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/browse/app.js +5 -6
  7. aird-0.4.23.dev18/aird/static/js/file-transfer-http.js +98 -0
  8. aird-0.4.23.dev18/aird/static/js/file-transfer.js +55 -0
  9. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/browse.html +2 -0
  10. {aird-0.4.23.dev17 → aird-0.4.23.dev18/aird.egg-info}/PKG-INFO +2 -1
  11. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird.egg-info/SOURCES.txt +3 -0
  12. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird.egg-info/requires.txt +3 -0
  13. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/setup.py +2 -1
  14. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/LICENSE +0 -0
  15. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/MANIFEST.in +0 -0
  16. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/README.md +0 -0
  17. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/__init__.py +0 -0
  18. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/__main__.py +0 -0
  19. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/app_context.py +0 -0
  20. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/cli/__init__.py +0 -0
  21. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/cli/__main__.py +0 -0
  22. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/cli/authelia.py +0 -0
  23. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/cli/config.py +0 -0
  24. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/cli/main.py +0 -0
  25. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/cli/session.py +0 -0
  26. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/cloud/__init__.py +0 -0
  27. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/config.py +0 -0
  28. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/constants/admin.py +0 -0
  29. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/constants/file_ops.py +0 -0
  30. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/constants/input_limits.py +0 -0
  31. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/constants/media.py +0 -0
  32. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/__init__.py +0 -0
  33. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/events.py +0 -0
  34. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/file_operations.py +0 -0
  35. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/filter_expression.py +0 -0
  36. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/folder_size.py +0 -0
  37. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/input_validation.py +0 -0
  38. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/mmap_handler.py +0 -0
  39. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/security.py +0 -0
  40. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/share_root.py +0 -0
  41. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/websocket_manager.py +0 -0
  42. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/core/zip_download.py +0 -0
  43. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/database/__init__.py +0 -0
  44. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/database/db.py +0 -0
  45. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/database/feature_flags.py +0 -0
  46. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/database/ldap.py +0 -0
  47. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/__init__.py +0 -0
  48. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/audit.py +0 -0
  49. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/config.py +0 -0
  50. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/favorites.py +0 -0
  51. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/network_shares.py +0 -0
  52. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/policies.py +0 -0
  53. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/policy_decisions.py +0 -0
  54. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/policy_seeds.py +0 -0
  55. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/quota.py +0 -0
  56. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/resource_tags.py +0 -0
  57. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/schema.py +0 -0
  58. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/shares.py +0 -0
  59. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/user_attributes.py +0 -0
  60. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/db/users.py +0 -0
  61. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/domain/__init__.py +0 -0
  62. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/domain/contracts.py +0 -0
  63. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/domain/models.py +0 -0
  64. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/email/__init__.py +0 -0
  65. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/email/brevo.py +0 -0
  66. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/email/resolve.py +0 -0
  67. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/__init__.py +0 -0
  68. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/abac_handlers.py +0 -0
  69. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/admin_handlers.py +0 -0
  70. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/api_handlers.py +0 -0
  71. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/auth_handlers.py +0 -0
  72. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/base_handler.py +0 -0
  73. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/constants.py +0 -0
  74. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/health_handler.py +0 -0
  75. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/p2p_handlers.py +0 -0
  76. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/share_handlers.py +0 -0
  77. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/transfer_ws_handlers.py +0 -0
  78. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/handlers/view_handlers.py +0 -0
  79. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/network_share_manager.py +0 -0
  80. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/server_runtime.py +0 -0
  81. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/__init__.py +0 -0
  82. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/audit_service.py +0 -0
  83. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/config_service.py +0 -0
  84. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/email_service.py +0 -0
  85. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/email_subscriber.py +0 -0
  86. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/event_subscribers.py +0 -0
  87. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/favorites_service.py +0 -0
  88. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/network_share_service.py +0 -0
  89. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/p2p_service.py +0 -0
  90. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/policy_service.py +0 -0
  91. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/quota_service.py +0 -0
  92. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/share_service.py +0 -0
  93. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/tag_service.py +0 -0
  94. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/services/user_service.py +0 -0
  95. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/sql_identifiers.py +0 -0
  96. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/css/app.css +0 -0
  97. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/favicon.png +0 -0
  98. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/favicon.svg +0 -0
  99. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/img/logo-icon.png +0 -0
  100. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/img/logo-mark.svg +0 -0
  101. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/img/logo-text.png +0 -0
  102. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/img/logo.png +0 -0
  103. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/aird-core.js +0 -0
  104. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/bg-canvas.js +0 -0
  105. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/common/command-palette.js +0 -0
  106. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/components/folder-picker.js +0 -0
  107. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/download-manager.js +0 -0
  108. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/feature-flags-live.js +0 -0
  109. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/file-transfer-ws.js +0 -0
  110. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/folder-size-scan.js +0 -0
  111. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/login-ui.js +0 -0
  112. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/media-view.js +0 -0
  113. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/p2p/app.js +0 -0
  114. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/p2p/mediator.js +0 -0
  115. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/p2p/qr-adapter.js +0 -0
  116. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/p2p/signaling-service.js +0 -0
  117. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/p2p/state-machine.js +0 -0
  118. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/p2p/transfer-service.js +0 -0
  119. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/pages/p2p-page.js +0 -0
  120. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/pages/super-search.js +0 -0
  121. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/share/app.js +0 -0
  122. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/theme.js +0 -0
  123. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/transfer-tracker.js +0 -0
  124. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/vendor/pdf.min.js +0 -0
  125. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/vendor/pdf.worker.min.js +0 -0
  126. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/static/js/vendor/qrcode-browser.js +0 -0
  127. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/_admin_tabs.html +0 -0
  128. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/_app_nav_header.html +0 -0
  129. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/_bg_canvas.html +0 -0
  130. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/_theme_early.html +0 -0
  131. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/_theme_login_corner.html +0 -0
  132. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/admin.html +0 -0
  133. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/admin_audit.html +0 -0
  134. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/admin_ldap.html +0 -0
  135. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/admin_login.html +0 -0
  136. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/admin_network_shares.html +0 -0
  137. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/admin_policies.html +0 -0
  138. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/admin_tags.html +0 -0
  139. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/admin_user_attributes.html +0 -0
  140. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/admin_users.html +0 -0
  141. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/directory.html +0 -0
  142. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/edit.html +0 -0
  143. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/error.html +0 -0
  144. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/file.html +0 -0
  145. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/ldap_config_create.html +0 -0
  146. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/ldap_config_edit.html +0 -0
  147. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/login.html +0 -0
  148. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/media_view.html +0 -0
  149. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/p2p_transfer.html +0 -0
  150. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/profile.html +0 -0
  151. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/share.html +0 -0
  152. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/shared_list.html +0 -0
  153. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/super_search.html +0 -0
  154. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/tagged_files.html +0 -0
  155. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/token_verification.html +0 -0
  156. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/user_create.html +0 -0
  157. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/templates/user_edit.html +0 -0
  158. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/utils/__init__.py +0 -0
  159. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird/utils/util.py +0 -0
  160. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird.egg-info/dependency_links.txt +0 -0
  161. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird.egg-info/entry_points.txt +0 -0
  162. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/aird.egg-info/top_level.txt +0 -0
  163. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/setup.cfg +0 -0
  164. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/__init__.py +0 -0
  165. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/conftest.py +0 -0
  166. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/handler_helpers.py +0 -0
  167. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_admin_handlers.py +0 -0
  168. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_api_handlers.py +0 -0
  169. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_architecture_conformance.py +0 -0
  170. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_auth_handlers.py +0 -0
  171. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_auth_handlers_extended.py +0 -0
  172. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_base_handler.py +0 -0
  173. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_base_handler_pep.py +0 -0
  174. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_cli.py +0 -0
  175. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_cloud.py +0 -0
  176. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_config.py +0 -0
  177. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_core_file_operations.py +0 -0
  178. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_database_db.py +0 -0
  179. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_database_feature_flags.py +0 -0
  180. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_database_ldap.py +0 -0
  181. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_database_shares.py +0 -0
  182. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_database_users.py +0 -0
  183. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_database_users_hashing.py +0 -0
  184. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_db.py +0 -0
  185. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_email_service.py +0 -0
  186. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_file_op_handlers.py +0 -0
  187. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_filter_expression.py +0 -0
  188. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_folder_size.py +0 -0
  189. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_main.py +0 -0
  190. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_mmap_handler.py +0 -0
  191. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_multi_user.py +0 -0
  192. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_network_shares.py +0 -0
  193. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_p2p_handlers.py +0 -0
  194. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_password_hashing.py +0 -0
  195. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_policy_service.py +0 -0
  196. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_rate_limit.py +0 -0
  197. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_security.py +0 -0
  198. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_security_comprehensive.py +0 -0
  199. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_server_runtime.py +0 -0
  200. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_share_handlers.py +0 -0
  201. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_share_ownership.py +0 -0
  202. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_super_search_handler.py +0 -0
  203. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_tag_service.py +0 -0
  204. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_transfer_ws_handlers.py +0 -0
  205. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_util.py +0 -0
  206. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_view_handlers.py +0 -0
  207. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_websocket_manager.py +0 -0
  208. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_wheel_static_assets.py +0 -0
  209. {aird-0.4.23.dev17 → aird-0.4.23.dev18}/tests/test_zip_download.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aird
3
- Version: 0.4.23.dev17
3
+ Version: 0.4.23.dev18
4
4
  Summary: Aird - A lightweight web-based file browser, editor, and streamer with real-time capabilities
5
5
  Home-page: https://github.com/blinkerbit/aird
6
6
  Author: Viswantha Srinivas P
@@ -13,6 +13,7 @@ Requires-Python: >=3.10
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: tornado>=6.5.1
16
+ Requires-Dist: uvloop>=0.19.0; sys_platform == "linux"
16
17
  Requires-Dist: ldap3>=2.9.1
17
18
  Requires-Dist: aiofiles>=23.0.0
18
19
  Requires-Dist: argon2-cffi>=23.1.0
@@ -63,7 +63,7 @@ UPLOAD_CONFIG = {
63
63
 
64
64
  # File operation constants (derived from UPLOAD_CONFIG at startup)
65
65
  MAX_FILE_SIZE = UPLOAD_CONFIG["max_file_size_mb"] * 1024 * 1024
66
- # HTTP /upload body limit (browser uploads use WebSocket; CLI may POST whole file)
66
+ # HTTP /upload body limit (browser uploads stream POST /upload; CLI may POST whole file)
67
67
  UPLOAD_REQUEST_MAX_BODY_SIZE = MAX_FILE_SIZE + (1024 * 1024)
68
68
  MAX_READABLE_FILE_SIZE = 50 * 1024 * 1024 # 50 MB
69
69
 
@@ -0,0 +1,34 @@
1
+ """Optional asyncio event loop tuning (Linux uvloop)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import sys
7
+
8
+ logger = logging.getLogger(__name__)
9
+
10
+ _uvloop_installed = False
11
+
12
+
13
+ def install_uvloop_if_linux() -> bool:
14
+ """Use libuv-backed asyncio on Linux when uvloop is installed."""
15
+ global _uvloop_installed
16
+ if _uvloop_installed:
17
+ return True
18
+ if not sys.platform.startswith("linux"):
19
+ return False
20
+ try:
21
+ import asyncio
22
+
23
+ import uvloop
24
+
25
+ asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
26
+ _uvloop_installed = True
27
+ logger.info("Using uvloop event loop (Linux)")
28
+ return True
29
+ except ImportError:
30
+ logger.debug("uvloop not installed; using default asyncio loop")
31
+ return False
32
+ except Exception:
33
+ logger.warning("Failed to enable uvloop; using default asyncio loop", exc_info=True)
34
+ return False
@@ -349,7 +349,7 @@ def _process_bulk_action(
349
349
 
350
350
  @tornado.web.stream_request_body
351
351
  class UploadHandler(BaseHandler):
352
- """Single-request HTTP upload (CLI / direct origin). Browser uses WebSocket."""
352
+ """Streamed HTTP upload (browser, CLI, reverse proxy, or direct origin)."""
353
353
 
354
354
  def check_xsrf_cookie(self) -> None:
355
355
  """Streamed uploads send raw body; accept X-XSRFToken header or ?_xsrf= query param."""
@@ -595,6 +595,10 @@ def _start_server(ssl_options, port: int, hostname: str, worker_count: int) -> N
595
595
 
596
596
 
597
597
  def main():
598
+ from aird.event_loop import install_uvloop_if_linux
599
+
600
+ install_uvloop_if_linux()
601
+
598
602
  print_banner()
599
603
  config.init_config()
600
604
 
@@ -258,7 +258,7 @@
258
258
  const raw = (err && err.message) ? String(err.message).trim() : "";
259
259
  if (!raw || raw === "cancelled") return raw;
260
260
  const lower = raw.toLowerCase();
261
- if (lower.includes("network") || lower.includes("websocket")) {
261
+ if (lower.includes("network") || lower.includes("websocket") || lower.includes("http")) {
262
262
  return "Upload interrupted. Check your connection and try again.";
263
263
  }
264
264
  if (lower.includes("403") || lower.includes("access denied")) {
@@ -271,16 +271,15 @@
271
271
  }
272
272
 
273
273
  async function uploadFile(item) {
274
- const FTW = globalThis.AirdFileTransferWs;
275
- if (!FTW?.uploadFile) {
276
- throw new Error("WebSocket upload unavailable. Hard-refresh the page.");
274
+ const FT = globalThis.AirdFileTransfer;
275
+ if (!FT?.uploadFile) {
276
+ throw new Error("Upload unavailable. Hard-refresh the page.");
277
277
  }
278
278
  const dir = item.uploadDir ?? document.getElementById('currentPath')?.value ?? '';
279
279
  const fname = item.uploadName ?? item.file.name;
280
280
  item.uploadSignal = { aborted: false };
281
- const TT = globalThis.AirdTransferTracker;
282
281
  const cancelFn = () => abortActiveUploads(item);
283
- await FTW.uploadFile(item.file, {
282
+ await FT.uploadFile(item.file, {
284
283
  uploadDir: dir,
285
284
  filename: fname,
286
285
  signal: item.uploadSignal,
@@ -0,0 +1,98 @@
1
+ /**
2
+ * HTTP streaming upload (POST /upload). Works via Cloudflare HTTP/3 or direct to origin.
3
+ */
4
+ (function (global) {
5
+ 'use strict';
6
+
7
+ function getXSRFToken() {
8
+ if (global.AirdCore?.getXSRFToken) {
9
+ return global.AirdCore.getXSRFToken();
10
+ }
11
+ const match = document.cookie.match(/\b_xsrf=([^;]*)/);
12
+ return match ? decodeURIComponent(match[1]) : '';
13
+ }
14
+
15
+ /**
16
+ * @param {File|Blob} file
17
+ * @param {{ uploadDir?: string, filename?: string, onProgress?: Function, signal?: { aborted: boolean }, onCancel?: Function }} options
18
+ */
19
+ function uploadFile(file, options) {
20
+ options = options || {};
21
+ const uploadDir = options.uploadDir ?? '';
22
+ const filename = options.filename ?? (file.name || 'upload');
23
+ const onProgress = options.onProgress || function () {};
24
+ const signal = options.signal;
25
+ const totalSize = file.size;
26
+
27
+ const TT = global.AirdTransferTracker;
28
+ const ttId = TT
29
+ ? TT.addTransfer(filename, totalSize, 'upload', { onCancel: options.onCancel })
30
+ : null;
31
+ if (TT && ttId && options.onCancel) {
32
+ TT.setCancelHandler(ttId, options.onCancel);
33
+ }
34
+
35
+ return new Promise((resolve, reject) => {
36
+ const xhr = new XMLHttpRequest();
37
+ let abortPoll = null;
38
+
39
+ function cleanup() {
40
+ if (abortPoll !== null) {
41
+ clearInterval(abortPoll);
42
+ abortPoll = null;
43
+ }
44
+ }
45
+
46
+ function fail(err, httpStatus) {
47
+ cleanup();
48
+ const msg = err?.message || String(err);
49
+ const error = err instanceof Error ? err : new Error(msg);
50
+ error.httpStatus = httpStatus ?? 0;
51
+ if (TT && ttId) TT.failTransfer(ttId, msg);
52
+ reject(error);
53
+ }
54
+
55
+ xhr.upload.addEventListener('progress', (ev) => {
56
+ if (!ev.lengthComputable) return;
57
+ const loaded = ev.loaded;
58
+ const pct = totalSize > 0 ? Math.round((loaded / totalSize) * 100) : 0;
59
+ onProgress(pct, loaded, totalSize);
60
+ if (TT && ttId) TT.updateProgress(ttId, loaded, totalSize);
61
+ });
62
+
63
+ xhr.addEventListener('load', () => {
64
+ cleanup();
65
+ if (xhr.status >= 200 && xhr.status < 300) {
66
+ onProgress(100, totalSize, totalSize);
67
+ if (TT && ttId) TT.completeTransfer(ttId);
68
+ resolve({ message: xhr.responseText || 'Upload successful' });
69
+ return;
70
+ }
71
+ const body = (xhr.responseText || '').trim();
72
+ fail(new Error(body || `Upload failed (HTTP ${xhr.status})`), xhr.status);
73
+ });
74
+
75
+ xhr.addEventListener('error', () => fail(new Error('Network error during upload'), 0));
76
+ xhr.addEventListener('abort', () => fail(new Error('cancelled'), 0));
77
+
78
+ if (signal) {
79
+ abortPoll = setInterval(() => {
80
+ if (signal.aborted) {
81
+ xhr.abort();
82
+ }
83
+ }, 100);
84
+ }
85
+
86
+ xhr.open('POST', '/upload');
87
+ xhr.setRequestHeader('X-Upload-Dir', uploadDir);
88
+ xhr.setRequestHeader('X-Upload-Filename', filename);
89
+ xhr.setRequestHeader('X-XSRFToken', getXSRFToken());
90
+ xhr.setRequestHeader('Content-Type', 'application/octet-stream');
91
+ xhr.send(file);
92
+ });
93
+ }
94
+
95
+ global.AirdFileTransferHttp = {
96
+ uploadFile: uploadFile,
97
+ };
98
+ })(typeof globalThis !== 'undefined' ? globalThis : window);
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Upload facade: HTTP first (CF or direct origin), WebSocket fallback when needed.
3
+ */
4
+ (function (global) {
5
+ 'use strict';
6
+
7
+ function isCancelled(err) {
8
+ const msg = (err && err.message) ? String(err.message).toLowerCase() : '';
9
+ return msg === 'cancelled';
10
+ }
11
+
12
+ /** Use WS when HTTP is blocked, proxied limits apply, or the connection failed. */
13
+ function shouldFallbackToWs(err) {
14
+ if (!err || isCancelled(err)) return false;
15
+ const status = err.httpStatus ?? 0;
16
+ if (status === 401 || status === 403 || status === 400) return false;
17
+ if (status === 413 || status === 0 || status === 502 || status === 503 || status === 504) {
18
+ return true;
19
+ }
20
+ const msg = String(err.message || '').toLowerCase();
21
+ return msg.includes('network error');
22
+ }
23
+
24
+ /**
25
+ * @param {File|Blob} file
26
+ * @param {object} options passed to HTTP/WS upload helpers
27
+ */
28
+ async function uploadFile(file, options) {
29
+ options = options || {};
30
+ const http = global.AirdFileTransferHttp;
31
+ const ws = global.AirdFileTransferWs;
32
+
33
+ if (http?.uploadFile) {
34
+ try {
35
+ return await http.uploadFile(file, options);
36
+ } catch (err) {
37
+ if (ws?.uploadFile && shouldFallbackToWs(err)) {
38
+ return ws.uploadFile(file, options);
39
+ }
40
+ throw err;
41
+ }
42
+ }
43
+
44
+ if (ws?.uploadFile) {
45
+ return ws.uploadFile(file, options);
46
+ }
47
+ throw new Error('No upload transport available. Hard-refresh the page.');
48
+ }
49
+
50
+ global.AirdFileTransfer = {
51
+ uploadFile: uploadFile,
52
+ saveBlob: global.AirdFileTransferWs?.saveBlob,
53
+ downloadFile: global.AirdFileTransferWs?.downloadFile,
54
+ };
55
+ })(typeof globalThis !== 'undefined' ? globalThis : window);
@@ -342,6 +342,8 @@
342
342
  <input type="hidden" id="currentPath" value="{{ current_path or '' }}" />
343
343
  <script src="/static/js/aird-core.js?v={{ static_version }}"></script>
344
344
  <script src="/static/js/file-transfer-ws.js?v={{ static_version }}"></script>
345
+ <script src="/static/js/file-transfer-http.js?v={{ static_version }}"></script>
346
+ <script src="/static/js/file-transfer.js?v={{ static_version }}"></script>
345
347
  <script src="/static/js/download-manager.js?v={{ static_version }}"></script>
346
348
  <script src="/static/js/components/folder-picker.js?v={{ static_version }}"></script>
347
349
  <script nonce="{{ csp_nonce }}">
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aird
3
- Version: 0.4.23.dev17
3
+ Version: 0.4.23.dev18
4
4
  Summary: Aird - A lightweight web-based file browser, editor, and streamer with real-time capabilities
5
5
  Home-page: https://github.com/blinkerbit/aird
6
6
  Author: Viswantha Srinivas P
@@ -13,6 +13,7 @@ Requires-Python: >=3.10
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: tornado>=6.5.1
16
+ Requires-Dist: uvloop>=0.19.0; sys_platform == "linux"
16
17
  Requires-Dist: ldap3>=2.9.1
17
18
  Requires-Dist: aiofiles>=23.0.0
18
19
  Requires-Dist: argon2-cffi>=23.1.0
@@ -6,6 +6,7 @@ aird/__init__.py
6
6
  aird/__main__.py
7
7
  aird/app_context.py
8
8
  aird/config.py
9
+ aird/event_loop.py
9
10
  aird/main.py
10
11
  aird/network_share_manager.py
11
12
  aird/server_runtime.py
@@ -101,7 +102,9 @@ aird/static/js/aird-core.js
101
102
  aird/static/js/bg-canvas.js
102
103
  aird/static/js/download-manager.js
103
104
  aird/static/js/feature-flags-live.js
105
+ aird/static/js/file-transfer-http.js
104
106
  aird/static/js/file-transfer-ws.js
107
+ aird/static/js/file-transfer.js
105
108
  aird/static/js/folder-size-scan.js
106
109
  aird/static/js/login-ui.js
107
110
  aird/static/js/media-view.js
@@ -10,3 +10,6 @@ pyasn1>=0.6.2
10
10
 
11
11
  [:python_version >= "3.13"]
12
12
  pysmbserver>=0.1.0
13
+
14
+ [:sys_platform == "linux"]
15
+ uvloop>=0.19.0
@@ -2,6 +2,7 @@ from setuptools import setup, find_packages
2
2
 
3
3
  install_requires = [
4
4
  "tornado>=6.5.1",
5
+ "uvloop>=0.19.0; sys_platform == 'linux'",
5
6
  "ldap3>=2.9.1",
6
7
  "aiofiles>=23.0.0",
7
8
  "argon2-cffi>=23.1.0",
@@ -15,7 +16,7 @@ install_requires = [
15
16
 
16
17
  setup(
17
18
  name="aird",
18
- version="0.4.23.dev17",
19
+ version="0.4.23.dev18",
19
20
  packages=find_packages(),
20
21
  include_package_data=True,
21
22
  package_data={"aird": [
File without changes
File without changes
File without changes
File without changes
File without changes