future-framework 1.1.2__tar.gz → 2.0.0__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 (115) hide show
  1. {future_framework-1.1.2 → future_framework-2.0.0}/PKG-INFO +11 -9
  2. {future_framework-1.1.2 → future_framework-2.0.0}/README.md +5 -5
  3. future_framework-2.0.0/future/__init__.py +0 -0
  4. {future_framework-1.1.2 → future_framework-2.0.0}/future/application.py +15 -9
  5. future_framework-2.0.0/future/authentication/Auth0Authentication.py +9 -0
  6. future_framework-2.0.0/future/authentication/AzureADAuthentication.py +9 -0
  7. {future_framework-1.1.2 → future_framework-2.0.0}/future/authentication/BasicAuthentication.py +2 -2
  8. future_framework-2.0.0/future/authentication/KerberosAuthentication.py +9 -0
  9. future_framework-2.0.0/future/authentication/KeycloakAuthentication.py +9 -0
  10. future_framework-2.0.0/future/authentication/OAuth2Authentication.py +9 -0
  11. future_framework-2.0.0/future/authentication/OpenIdConnectAuthentication.py +9 -0
  12. future_framework-2.0.0/future/authentication/SAMLAuthentication.py +9 -0
  13. future_framework-2.0.0/future/authentication/__init__.py +0 -0
  14. future_framework-2.0.0/future/cli.py +738 -0
  15. future_framework-1.1.2/future/controllers/builtins.py → future_framework-2.0.0/future/controllers/DebugController.py +3 -17
  16. future_framework-2.0.0/future/controllers/GraphQLController.py +173 -0
  17. future_framework-1.1.2/future/controllers/openapi.py → future_framework-2.0.0/future/controllers/OpenAPIController.py +2 -2
  18. future_framework-2.0.0/future/controllers/WebSocketController.py +13 -0
  19. future_framework-2.0.0/future/controllers/WelcomeController.py +7 -0
  20. future_framework-2.0.0/future/controllers/__init__.py +0 -0
  21. future_framework-1.1.2/future/databases/Connections.py → future_framework-2.0.0/future/database.py +5 -5
  22. future_framework-1.1.2/future/databases/Clickhouse.py → future_framework-2.0.0/future/databases/ClickhouseDatabase.py +78 -56
  23. future_framework-2.0.0/future/databases/ElasticsearchDatabase.py +174 -0
  24. future_framework-1.1.2/future/databases/MongoDB.py → future_framework-2.0.0/future/databases/MongoDBDatabase.py +50 -50
  25. future_framework-1.1.2/future/databases/MySQL.py → future_framework-2.0.0/future/databases/MySQLDatabase.py +73 -72
  26. future_framework-1.1.2/future/databases/Postgres.py → future_framework-2.0.0/future/databases/PostgresDatabase.py +70 -69
  27. future_framework-1.1.2/future/databases/Redis.py → future_framework-2.0.0/future/databases/RedisDatabase.py +36 -36
  28. future_framework-1.1.2/future/databases/SQLite.py → future_framework-2.0.0/future/databases/SQLiteDatabase.py +72 -71
  29. future_framework-2.0.0/future/databases/__init__.py +0 -0
  30. future_framework-2.0.0/future/interfaces/IAuthentication.py +5 -0
  31. future_framework-1.1.2/future/controllers/base.py → future_framework-2.0.0/future/interfaces/IController.py +2 -1
  32. future_framework-1.1.2/future/databases/Database.py → future_framework-2.0.0/future/interfaces/IDatabase.py +20 -18
  33. future_framework-2.0.0/future/interfaces/IMiddleware.py +26 -0
  34. future_framework-1.1.2/future/models/model.py → future_framework-2.0.0/future/interfaces/IModel.py +53 -74
  35. future_framework-2.0.0/future/interfaces/IPlugin.py +5 -0
  36. future_framework-2.0.0/future/interfaces/ITask.py +16 -0
  37. future_framework-2.0.0/future/interfaces/__init__.py +0 -0
  38. future_framework-2.0.0/future/interfacing.py +73 -0
  39. {future_framework-1.1.2 → future_framework-2.0.0}/future/lifespan.py +5 -14
  40. future_framework-2.0.0/future/middleware/BruteforcePreventionMiddleware.py +5 -0
  41. future_framework-2.0.0/future/middleware/CORSMiddleware.py +30 -0
  42. future_framework-2.0.0/future/middleware/CSRFMiddleware.py +35 -0
  43. future_framework-2.0.0/future/middleware/GZipMiddleware.py +25 -0
  44. future_framework-2.0.0/future/middleware/HTAccessConfuserMiddleware.py +5 -0
  45. future_framework-2.0.0/future/middleware/HeaderConfuserMiddleware.py +5 -0
  46. future_framework-2.0.0/future/middleware/RateLimitMiddleware.py +23 -0
  47. future_framework-2.0.0/future/middleware/ResponseCodeConfuserMiddleware.py +22 -0
  48. future_framework-2.0.0/future/middleware/SQLiConfuserMiddleware.py +5 -0
  49. future_framework-2.0.0/future/middleware/ScopeValidationMiddleware.py +27 -0
  50. {future_framework-1.1.2 → future_framework-2.0.0}/future/middleware/SessionMiddleware.py +2 -2
  51. future_framework-2.0.0/future/middleware/TestMiddlewareRequest.py +13 -0
  52. future_framework-2.0.0/future/middleware/TestMiddlewareResponse.py +13 -0
  53. future_framework-2.0.0/future/middleware/WebServerConfuserMiddleware.py +5 -0
  54. future_framework-2.0.0/future/middleware/__init__.py +0 -0
  55. future_framework-2.0.0/future/migrations.py +312 -0
  56. future_framework-2.0.0/future/models/PostModel.py +13 -0
  57. future_framework-2.0.0/future/models/Query.py +40 -0
  58. future_framework-2.0.0/future/models/UserModel.py +10 -0
  59. future_framework-2.0.0/future/models/__init__.py +0 -0
  60. {future_framework-1.1.2 → future_framework-2.0.0}/future/openapi.py +1 -1
  61. {future_framework-1.1.2 → future_framework-2.0.0}/future/plugins/ElasticsearchPlugin.py +93 -91
  62. future_framework-2.0.0/future/plugins/__init__.py +0 -0
  63. {future_framework-1.1.2 → future_framework-2.0.0}/future/request.py +1 -1
  64. {future_framework-1.1.2 → future_framework-2.0.0}/future/response.py +20 -1
  65. {future_framework-1.1.2 → future_framework-2.0.0}/future/routing.py +13 -13
  66. future_framework-1.1.2/future/seeds/SeedGenerator.py → future_framework-2.0.0/future/seeder.py +59 -6
  67. future_framework-2.0.0/future/tasks/CheckDNSTask.py +21 -0
  68. future_framework-2.0.0/future/tasks/CheckDiskUsageTask.py +22 -0
  69. future_framework-2.0.0/future/tasks/CheckHttpStatusTask.py +22 -0
  70. future_framework-2.0.0/future/tasks/CheckMemoryUsageTask.py +20 -0
  71. future_framework-2.0.0/future/tasks/CheckSSHBannerTask.py +25 -0
  72. future_framework-2.0.0/future/tasks/CheckSystemUptimeTask.py +23 -0
  73. future_framework-2.0.0/future/tasks/DailyBackupTask.py +16 -0
  74. future_framework-2.0.0/future/tasks/SyncTaskExample.py +14 -0
  75. future_framework-2.0.0/future/tasks/__init__.py +0 -0
  76. future_framework-2.0.0/future/taskscheduler.py +135 -0
  77. {future_framework-1.1.2 → future_framework-2.0.0}/future/types.py +1 -1
  78. {future_framework-1.1.2 → future_framework-2.0.0}/pyproject.toml +6 -4
  79. future_framework-1.1.2/future/__init__.py +0 -3
  80. future_framework-1.1.2/future/authentication/Auth0Authentication.py +0 -9
  81. future_framework-1.1.2/future/authentication/Authentication.py +0 -11
  82. future_framework-1.1.2/future/authentication/AzureADAuthentication.py +0 -9
  83. future_framework-1.1.2/future/authentication/KerberosAuthentication.py +0 -9
  84. future_framework-1.1.2/future/authentication/KeycloakAuthentication.py +0 -9
  85. future_framework-1.1.2/future/authentication/OAuth2Authentication.py +0 -9
  86. future_framework-1.1.2/future/authentication/OpenIdConnectAuthentication.py +0 -9
  87. future_framework-1.1.2/future/authentication/SAMLAuthentication.py +0 -9
  88. future_framework-1.1.2/future/cli/__init__.py +0 -1
  89. future_framework-1.1.2/future/cli/main.py +0 -607
  90. future_framework-1.1.2/future/cli/stubs.py +0 -114
  91. future_framework-1.1.2/future/controllers/__init__.py +0 -4
  92. future_framework-1.1.2/future/controllers/graphql.py +0 -23
  93. future_framework-1.1.2/future/databases/Elasticsearch.py +0 -146
  94. future_framework-1.1.2/future/graphql/__init__.py +0 -1
  95. future_framework-1.1.2/future/graphql/schema.py +0 -148
  96. future_framework-1.1.2/future/middleware/Middleware.py +0 -201
  97. future_framework-1.1.2/future/middleware/__init__.py +0 -21
  98. future_framework-1.1.2/future/migrations/Blueprint.py +0 -54
  99. future_framework-1.1.2/future/migrations/Column.py +0 -33
  100. future_framework-1.1.2/future/migrations/Migration.py +0 -11
  101. future_framework-1.1.2/future/migrations/MigrationGenerator.py +0 -137
  102. future_framework-1.1.2/future/migrations/Migrator.py +0 -72
  103. future_framework-1.1.2/future/migrations/Schema.py +0 -21
  104. future_framework-1.1.2/future/models/__init__.py +0 -1
  105. future_framework-1.1.2/future/plugins/__init__.py +0 -9
  106. future_framework-1.1.2/future/seeds/SeedRunner.py +0 -42
  107. future_framework-1.1.2/future/seeds/Seeder.py +0 -9
  108. future_framework-1.1.2/future/tasks/__init__.py +0 -14
  109. future_framework-1.1.2/future/tasks/scheduler.py +0 -267
  110. future_framework-1.1.2/future/testing/__init__.py +0 -1
  111. {future_framework-1.1.2 → future_framework-2.0.0}/LICENSE +0 -0
  112. {future_framework-1.1.2 → future_framework-2.0.0}/future/exceptions.py +0 -0
  113. {future_framework-1.1.2 → future_framework-2.0.0}/future/logger.py +0 -0
  114. {future_framework-1.1.2 → future_framework-2.0.0}/future/settings.py +0 -0
  115. /future_framework-1.1.2/future/testing/client.py → /future_framework-2.0.0/future/testclient.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: future-framework
3
- Version: 1.1.2
3
+ Version: 2.0.0
4
4
  Summary: ASGI-based framework for web APIs
5
5
  License: LICENSE
6
6
  License-File: LICENSE
@@ -11,14 +11,16 @@ Classifier: Programming Language :: Python :: 3
11
11
  Classifier: Programming Language :: Python :: 3.12
12
12
  Classifier: Programming Language :: Python :: 3.13
13
13
  Classifier: Programming Language :: Python :: 3.14
14
+ Requires-Dist: aiomysql (>=0.2.0,<0.3.0)
15
+ Requires-Dist: aiosqlite (>=0.21.0,<0.22.0)
16
+ Requires-Dist: asynch (>=0.2.5,<0.3.0)
17
+ Requires-Dist: asyncpg (>=0.30.0,<0.31.0)
14
18
  Requires-Dist: clickhouse-driver (>=0.2.11,<0.3.0)
15
- Requires-Dist: elasticsearch (>=9.4.0,<10.0.0)
19
+ Requires-Dist: elasticsearch (>=8.15.0,<9)
16
20
  Requires-Dist: faker (>=40.0.0,<41.0.0)
17
21
  Requires-Dist: httpx (>=0.28.1,<0.29.0)
18
22
  Requires-Dist: inflection (>=0.5.1,<0.6.0)
19
- Requires-Dist: psycopg2-binary (>=2.9.12,<3.0.0)
20
23
  Requires-Dist: pymongo (>=4.17.0,<5.0.0)
21
- Requires-Dist: pymysql (>=1.2.0,<2.0.0)
22
24
  Requires-Dist: python-dotenv (>=1.2.2,<2.0.0)
23
25
  Requires-Dist: redis (>=8.0.0,<9.0.0)
24
26
  Requires-Dist: rich (>=15.0.0,<16.0.0)
@@ -32,11 +34,11 @@ Project-URL: Repository, https://github.com/nicolaipre/future-framework
32
34
  Description-Content-Type: text/markdown
33
35
 
34
36
  # Future
35
- Minimal, decorator-free [ASGI](https://asgi.readthedocs.io/)-based framework for web APIs — routing, middleware, Active Record, migrations, seeds, OpenAPI, and interval tasks.
37
+ [ASGI](https://asgi.readthedocs.io/)-based framework for web APIs — routing, middleware, Active Record, migrations, seeds, OpenAPI, and interval tasks.
36
38
 
37
39
  [![Build Status](https://github.com/nicolaipre/future-framework/actions/workflows/ci.yml/badge.svg)](https://github.com/nicolaipre/future-framework/actions)
38
- [![Package version](https://badge.fury.io/py/future-framework.svg)](https://pypi.org/project/future-framework/)
39
- [![codecov](https://codecov.io/gh/nicolaipre/future-framework/branch/master/graph/badge.svg)](https://codecov.io/gh/nicolaipre/future-framework)
40
+ [![Package Version](https://img.shields.io/pypi/v/future-framework)](https://pypi.org/project/future-framework/)
41
+ [![Coverage](https://codecov.io/gh/nicolaipre/future-framework/branch/master/graph/badge.svg)](https://codecov.io/gh/nicolaipre/future-framework)
40
42
 
41
43
  ## Documentation
42
44
  Published at **[nicolaipre.github.io/future-framework](https://nicolaipre.github.io/future-framework/)**. To preview locally: `poetry install --with docs && poetry run mkdocs serve`.
@@ -52,12 +54,12 @@ Import name is `future` (`from future.application import Future`).
52
54
  ## Hello
53
55
  ```python
54
56
  from future.application import Future
55
- from future.controllers import Controller
57
+ from future.interfaces.IController import IController
56
58
  from future.lifespan import Lifespan
57
59
  from future.response import Response
58
60
  from future.routing import Get, RouteGroup
59
61
 
60
- class HomeController(Controller):
62
+ class HomeController(IController):
61
63
  async def index(self) -> Response:
62
64
  return self.response.json({"ok": True})
63
65
 
@@ -1,9 +1,9 @@
1
1
  # Future
2
- Minimal, decorator-free [ASGI](https://asgi.readthedocs.io/)-based framework for web APIs — routing, middleware, Active Record, migrations, seeds, OpenAPI, and interval tasks.
2
+ [ASGI](https://asgi.readthedocs.io/)-based framework for web APIs — routing, middleware, Active Record, migrations, seeds, OpenAPI, and interval tasks.
3
3
 
4
4
  [![Build Status](https://github.com/nicolaipre/future-framework/actions/workflows/ci.yml/badge.svg)](https://github.com/nicolaipre/future-framework/actions)
5
- [![Package version](https://badge.fury.io/py/future-framework.svg)](https://pypi.org/project/future-framework/)
6
- [![codecov](https://codecov.io/gh/nicolaipre/future-framework/branch/master/graph/badge.svg)](https://codecov.io/gh/nicolaipre/future-framework)
5
+ [![Package Version](https://img.shields.io/pypi/v/future-framework)](https://pypi.org/project/future-framework/)
6
+ [![Coverage](https://codecov.io/gh/nicolaipre/future-framework/branch/master/graph/badge.svg)](https://codecov.io/gh/nicolaipre/future-framework)
7
7
 
8
8
  ## Documentation
9
9
  Published at **[nicolaipre.github.io/future-framework](https://nicolaipre.github.io/future-framework/)**. To preview locally: `poetry install --with docs && poetry run mkdocs serve`.
@@ -19,12 +19,12 @@ Import name is `future` (`from future.application import Future`).
19
19
  ## Hello
20
20
  ```python
21
21
  from future.application import Future
22
- from future.controllers import Controller
22
+ from future.interfaces.IController import IController
23
23
  from future.lifespan import Lifespan
24
24
  from future.response import Response
25
25
  from future.routing import Get, RouteGroup
26
26
 
27
- class HomeController(Controller):
27
+ class HomeController(IController):
28
28
  async def index(self) -> Response:
29
29
  return self.response.json({"ok": True})
30
30
 
File without changes
@@ -17,7 +17,7 @@ from rich.text import Text
17
17
 
18
18
  from future.exceptions import ErrorHandler, HTTPException
19
19
  from future.logger import log
20
- from future.middleware import Middleware
20
+ from future.interfaces.IMiddleware import IMiddleware
21
21
  from future.openapi import get_openapi_config, is_docs_path, openapi_routes, rebuild_spec_from_routes, set_openapi_config, spec_path
22
22
  from future.request import Request
23
23
  from future.response import Response, WebSocketResponse
@@ -80,8 +80,8 @@ class Future:
80
80
  self.config = config or {}
81
81
  self.databases = self.config.get("DATABASES")
82
82
  if self.databases:
83
- from future.databases.Connections import Connections
84
- Connections().set_connection_details(self.databases)
83
+ from future.database import Database
84
+ Database().set_connection_details(self.databases)
85
85
 
86
86
  domain = self.config.get("APP_DOMAIN", "")
87
87
 
@@ -133,7 +133,7 @@ class Future:
133
133
  return cls, endpoint.__name__
134
134
  return None, None
135
135
 
136
- def _add_route(self, route: Route, subdomain: str = "", parent_middlewares: Optional[list[Middleware]] = None, group: Optional[dict[str, str]] = None) -> None:
136
+ def _add_route(self, route: Route, subdomain: str = "", parent_middlewares: Optional[list[IMiddleware]] = None, group: Optional[dict[str, str]] = None) -> None:
137
137
  """Internal method to add single routes to the application.
138
138
 
139
139
  Args:
@@ -165,7 +165,7 @@ class Future:
165
165
  group=group or {"name": "", "prefix": "", "subdomain": ""},
166
166
  )
167
167
 
168
- self._check_route_conflicts(route, key)
168
+ self._check_route_conflicts(route, key, group)
169
169
  # Path + methods so Get("/x") and Post("/x") can coexist
170
170
  self.routes[key][f"{','.join(route.methods)} {route.path}"] = route_config
171
171
 
@@ -211,7 +211,7 @@ class Future:
211
211
  route_group: RouteGroup,
212
212
  parent_subdomain: str = "",
213
213
  parent_prefix: str = "",
214
- parent_middlewares: Optional[list[Middleware]] = None,
214
+ parent_middlewares: Optional[list[IMiddleware]] = None,
215
215
  nesting_depth: int = 0,
216
216
  parent_group_names: Optional[list[str]] = None,
217
217
  ) -> None:
@@ -310,7 +310,7 @@ class Future:
310
310
 
311
311
  return full_prefix
312
312
 
313
- def _check_route_conflicts(self, route: Route, domain: str) -> None:
313
+ def _check_route_conflicts(self, route: Route, domain: str, group: Optional[dict[str, str]] = None) -> None:
314
314
  """Conflict only when the same path shares an HTTP method."""
315
315
  existing_routes = self.routes.get(domain, {})
316
316
  for existing in existing_routes.values():
@@ -318,8 +318,14 @@ class Future:
318
318
  if other is None or getattr(other, "path", None) != route.path:
319
319
  continue
320
320
  overlap = set(other.methods) & set(route.methods)
321
- if overlap:
322
- raise ValueError(f"Route conflict detected: {','.join(sorted(overlap))} {route.path} already exists in domain {domain}")
321
+ if not overlap:
322
+ continue
323
+ methods = ",".join(sorted(overlap))
324
+ incoming_sub = (group or {}).get("subdomain") or ""
325
+ existing_sub = (existing.get("group") or {}).get("subdomain") or ""
326
+ if getattr(self, "domainless_mode", False) and incoming_sub != existing_sub and (incoming_sub or existing_sub):
327
+ raise ValueError(f"Route conflict detected: {methods} {route.path} already exists. In domainless mode (APP_DOMAIN is empty), RouteGroup subdomains are ignored, so {existing_sub!r} and {incoming_sub!r} both register {route.path}. Set APP_DOMAIN to enable subdomain routing, or use different prefixes.")
328
+ raise ValueError(f"Route conflict detected: {methods} {route.path} already exists in domain {domain}")
323
329
 
324
330
  def _validate_domain_access(self, host_domain: str) -> bool:
325
331
  """Validate if the host domain is allowed to access routes."""
@@ -0,0 +1,9 @@
1
+ """
2
+ Auth0 authentication.
3
+ """
4
+
5
+ from future.interfaces.IAuthentication import IAuthentication
6
+
7
+
8
+ class Auth0Authentication(IAuthentication):
9
+ auth_type = "oauth"
@@ -0,0 +1,9 @@
1
+ """
2
+ Azure AD authentication.
3
+ """
4
+
5
+ from future.interfaces.IAuthentication import IAuthentication
6
+
7
+
8
+ class AzureADAuthentication(IAuthentication):
9
+ auth_type = "basic"
@@ -2,8 +2,8 @@
2
2
  Regular username & password authentication (check against SQL database, generating a JWT).
3
3
  """
4
4
 
5
- from future.authentication.Authentication import Authentication
5
+ from future.interfaces.IAuthentication import IAuthentication
6
6
 
7
7
 
8
- class BasicAuthentication(Authentication):
8
+ class BasicAuthentication(IAuthentication):
9
9
  auth_type = "basic"
@@ -0,0 +1,9 @@
1
+ """
2
+ Kerberos Single Sign-On authentication.
3
+ """
4
+
5
+ from future.interfaces.IAuthentication import IAuthentication
6
+
7
+
8
+ class KerberosAuthentication(IAuthentication):
9
+ auth_type = "sso"
@@ -0,0 +1,9 @@
1
+ """
2
+ Keycloak authentication.
3
+ """
4
+
5
+ from future.interfaces.IAuthentication import IAuthentication
6
+
7
+
8
+ class KeycloakAuthentication(IAuthentication):
9
+ auth_type = "oauth"
@@ -0,0 +1,9 @@
1
+ """
2
+ OAuth 2 authentication.
3
+ """
4
+
5
+ from future.interfaces.IAuthentication import IAuthentication
6
+
7
+
8
+ class OAuth2Authentication(IAuthentication):
9
+ auth_type = "oauth"
@@ -0,0 +1,9 @@
1
+ """
2
+ OpenID Connect authentication.
3
+ """
4
+
5
+ from future.interfaces.IAuthentication import IAuthentication
6
+
7
+
8
+ class OpenIdConnectAuthentication(IAuthentication):
9
+ auth_type = "oidc"
@@ -0,0 +1,9 @@
1
+ """
2
+ SAML Single Sign-On authentication.
3
+ """
4
+
5
+ from future.interfaces.IAuthentication import IAuthentication
6
+
7
+
8
+ class SAMLAuthentication(IAuthentication):
9
+ auth_type = "sso"