tjfu


Nametjfu JSON
Version 3.3.0 PyPI version JSON
download
home_pagehttps://github.com/duynguyen02/tjfu
SummaryPython library helps optimize Flask development to be flexible and object-oriented.
upload_time2024-04-27 18:19:08
maintainerNone
docs_urlNone
authorDuy Nguyen
requires_python>=3.9
licenseNone
keywords python flask
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # TJFU
Python library helps optimize Flask development to be flexible and object-oriented.
### Extensions have been integrated
1. [JWT](https://flask-jwt-extended.readthedocs.io/en/stable/)
2. [SocketIO](https://flask-socketio.readthedocs.io/en/latest/)
3. [Limiter](https://flask-limiter.readthedocs.io/en/stable/)
### Installation
```
pip install tjfu
```

### Get started
Basic example:
```Python
from os import path
from tjfu import TJFU
from datetime import timedelta

HERE = path.abspath(path.dirname(__file__))

def error_404(error):
    return "Not Found!!!", 404

def error_500(error):
    return "Error!!!", 500

"""
    The TJFU configuration must be placed
    at the beginning of the main function.
    Absolutely do not define or import any Route
    before calling the build() function because an error may occur.
"""
{
TJFU
    .host_name("0.0.0.0") # required
    .host_port(3100) # required        
    .root_path(HERE) # optinal (default: '.')        
    .template_folder("templates") # optinal (default: 'templates')
    .static_folder("static") # optinal (default: 'static')
    .jwt_secret_key("your_jwt_secret_key")
        # optinal / enter value if you want to use JWT, 
        # Otherwise the jwt_required function will throw an error
    .jwt_access_token_expires(timedelta(days=7)) # optinal (default: 'timedelta(days=7)')
    .jwt_refresh_token_expires(timedelta(days=14)) # optinal (default: 'timedelta(days=14)')
    .socket_root("socket") # optinal (default: 'socket') 
    .ignore_cors(True) # optinal (default: 'True')
    .add_error_handler(404, error_404) # optional
    .add_error_handler(500, error_500) # optional
    .add_status_code_handler(500, error_500) # optional (>=3.2.0)
    .limiter_storage_uri("memory://") # optinal (default: 'memory://')
    .default_limits(["200 per day", "50 per hour"]) # optinal (default: '[]')
    .log_output(False) # optinal (default: 'True')
    .debug(False) # optinal (default: 'True')
    .use_reloader(False) # optinal (default: 'True')
    .allow_unsafe_werkzeug(False) # optinal (default: 'True')
    .app_config('MY_SECRET_KEY', 'my_secret_key') # optional (>=3.2.0): use as app.config['MY_SECRET_KEY'] = 'my_secret_key'
    .app_config('MY_SECRET_KEY_2', 'my_secret_key') # optional (>=3.2.0): use as app.config['MY_SECRET_KEY_2'] = 'my_secret_key'
    .build()
}

from tjfu import Route

app = TJFU.init_app(Route("index", "/"))

IS_PRODUCTION = False

if __name__ == "__main__":
    if IS_PRODUCTION:
        app.run()
    else:
        TJFU.run()
```

Define a Custom Route:
```Python
# OTHER CODE...
from tjfu import Route, SimpleRenderTemplateRoute

class MyCustomRoute(Route):
    def __init__(
        self,
        your_name: str
    ):
        super().__init__("mycustomroute", "/mycustomroute")
        self._your_name = your_name
    
        self._blueprint.route('/')(self._index) # /mycustomroute
        self._blueprint.route('/jwt')(self._jwt) # /mycustomroute/jwt
        self._blueprint.route('/class_variable')(self._class_variable) # /mycustomroute/class_variable
        self._blueprint.route('/limiter')(self._limiter) # /mycustomroute/limiter
    
    # Basic route function
    @staticmethod
    def _index():
        return "Hello World!"
    
    # JWT route function
    @staticmethod
    @jwt_required()
    def _jwt():
        return "Hello From JWT!"
    
    
    # Class variable route function
    def _class_variable(
        self
    ):
        return f"Hello {self._your_name}!"
    
    # Limiter route function
    @staticmethod
    @TJFU.limiter().limit('1/second')
    def _limiter():
        return "Hello from Limiter!"
    

index_route = Route("index", "/")
my_custom_route = MyCustomRoute("John Doe")
another_my_custom_route = MyCustomRoute("Lisa")

# /mycustomroute
index_route.register_route(my_custom_route)

"""
    You can easily define a route to
    render an HTML file
    using the SimpleRenderTemplateRoute class
"""
# /my_html_file
index_route.register_route(
    SimpleRenderTemplateRoute(
        "my_html_file",
        "/my_html_file",
        "my_html_file.html"
    )
)

# /mycustomroute/mycustomroute
my_custom_route.register_route(another_my_custom_route)

# You must register routes and sockets before calling the init_app function
app = TJFU.init_app(index_route)

# OTHER CODE...
```
Register Routes using Dictionary (>=3.1.0):
```Python
# OTHER CODE...

app = TJFU.init_app(
    Route("index", "/"), 
    {
        Route("api", "/api"):{
            
            Route("v1", "/v1"):{
                
                Route("user", "/user"):{
            
                }    
                
            }
            
        },
        Route("tool", "/tool"):{
            SimpleRenderTemplateRoute(
                "my_tool",
                "/my_tool",
                "my_tool.html"
            )
        },
        SimpleRenderTemplateRoute(
            "hello_world",
            "/hello_world",
            "hello_world.html"
        ): None
    }
)

# OTHER CODE...
```
Get Flask App after TJFU.build() (>=3.2.0)
```Python
# Example
from tjfu import TJFU
from flask_mail import Mail, Message
mail = Mail(TJFU.app())
```
Get Extensions (JWT/Limiter/SocketIO) after TJFU.build() (>=3.3.0)
```Python
TJFU.jwt()
TJFU.limiter()
TJFU.socketio()
```
Add custom extensions to TJFU after TJFU.build() (>=3.3.0)
```Python
# OTHER CODE...

from flask_mail import Mail, Message
mail = Mail(TJFU.app())

TJFU.add_extension(
    'send_mail',
    mail
) 

app = TJFU.init_app(index_route)

# OTHER CODE...
```
And then you can take it out and use it in contexts (e.g. Route)
```Python
mail = TJFU.get_extension('send_mail')
```

Define a Socket Handle:
```Python
# OTHER CODE...

from tjfu import SocketEvent, SocketHandle
from flask import request
class MySocketHandle(SocketHandle):
    def __init__(self):
        super().__init__(self._my_handle)
        
    def _my_handle(self, msg):
        print(f"Client id: {request.sid}")
        print(f"Msg from client: {msg}")
        TJFU.emit(
            SocketEvent("chat", "send"),
            "Hello client from socket handle!!!"
        )
        
TJFU.register_socket_event(
    SocketEvent("chat", "send"),
    MySocketHandle()
) 

app = TJFU.init_app(index_route)

# OTHER CODE...
```
You can send data to the client via Socket in places outside the Socket Handle context (such as Route) through the TJFU.no_context_emit function

```Python
class SendMsgRoute(Route):
    def __init__(
        self
    ):
        super().__init__("send_msg", "/send_msg")
        self._blueprint.route('/')(self._index)
        
    @staticmethod
    def _index():
        TJFU.no_context_emit(
            SocketEvent("chat", "send"),
            "Hello client from route!!!"
        )
        return "Hello World!"
```
Simple HTML code to receive and send data from Socket
```HTML
<!DOCTYPE html>
<html>
<head>
    <title>Socket.IO Example</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.3/socket.io.js"></script>
    <script type="text/javascript">
        var socket = io('http://0.0.0.0:3100/socket/chat');
        socket.on('connect', function () {
            console.log('Connected to the server');
        });
        socket.on('send', function (data) {
            console.log('Message received: ' + data);
        });
        socket.on('disconnect', function () {
            console.log('Disconnected from server');
        });
        function sendMessage() {
            var message = document.getElementById('message').value;
            socket.emit('send', message);
        }
    </script>
</head>

<body>
    <h1>Socket.IO Example</h1>
    <input type="text" id="message" placeholder="Enter message">
    <button onclick="sendMessage()">Send</button>
</body>

</html>
```

### Changelog
- `1.0.0`: First version released. There is a problem in Socket implementation.
- `2.0.0`: Edit the Socket structure. There is a problem deploying the application to the production environment.
- `3.0.0`: The version is relatively stable, overcoming the problem of deploying applications in production environments.
- `3.1.0`: Added the function of registering Routes using Routes Map
- `3.1.1`: Fixed an issue where additional variables could not be added when inheriting the _index function in Route.
- `3.2.0`: Assign keys/values to Flask App Config using TJFU.app_config(...,...), add function TJFU.app() to get Flask App after calling TJFU.build(), use the add_status_code_handler function instead of the add_error_handler function.
- `3.3.0`: Build functions that take instances of extensions and add custom extensions.


            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/duynguyen02/tjfu",
    "name": "tjfu",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.9",
    "maintainer_email": null,
    "keywords": "Python, Flask",
    "author": "Duy Nguyen",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/b2/af/7e013d284b2dab79ed3663e387fe7ff8b0da1cba8726a73d8fb58f7e0ed9/tjfu-3.3.0.tar.gz",
    "platform": null,
    "description": "# TJFU\nPython library helps optimize Flask development to be flexible and object-oriented.\n### Extensions have been integrated\n1. [JWT](https://flask-jwt-extended.readthedocs.io/en/stable/)\n2. [SocketIO](https://flask-socketio.readthedocs.io/en/latest/)\n3. [Limiter](https://flask-limiter.readthedocs.io/en/stable/)\n### Installation\n```\npip install tjfu\n```\n\n### Get started\nBasic example:\n```Python\nfrom os import path\nfrom tjfu import TJFU\nfrom datetime import timedelta\n\nHERE = path.abspath(path.dirname(__file__))\n\ndef error_404(error):\n    return \"Not Found!!!\", 404\n\ndef error_500(error):\n    return \"Error!!!\", 500\n\n\"\"\"\n    The TJFU configuration must be placed\n    at the beginning of the main function.\n    Absolutely do not define or import any Route\n    before calling the build() function because an error may occur.\n\"\"\"\n{\nTJFU\n    .host_name(\"0.0.0.0\") # required\n    .host_port(3100) # required        \n    .root_path(HERE) # optinal (default: '.')        \n    .template_folder(\"templates\") # optinal (default: 'templates')\n    .static_folder(\"static\") # optinal (default: 'static')\n    .jwt_secret_key(\"your_jwt_secret_key\")\n        # optinal / enter value if you want to use JWT, \n        # Otherwise the jwt_required function will throw an error\n    .jwt_access_token_expires(timedelta(days=7)) # optinal (default: 'timedelta(days=7)')\n    .jwt_refresh_token_expires(timedelta(days=14)) # optinal (default: 'timedelta(days=14)')\n    .socket_root(\"socket\") # optinal (default: 'socket') \n    .ignore_cors(True) # optinal (default: 'True')\n    .add_error_handler(404, error_404) # optional\n    .add_error_handler(500, error_500) # optional\n    .add_status_code_handler(500, error_500) # optional (>=3.2.0)\n    .limiter_storage_uri(\"memory://\") # optinal (default: 'memory://')\n    .default_limits([\"200 per day\", \"50 per hour\"]) # optinal (default: '[]')\n    .log_output(False) # optinal (default: 'True')\n    .debug(False) # optinal (default: 'True')\n    .use_reloader(False) # optinal (default: 'True')\n    .allow_unsafe_werkzeug(False) # optinal (default: 'True')\n    .app_config('MY_SECRET_KEY', 'my_secret_key') # optional (>=3.2.0): use as app.config['MY_SECRET_KEY'] = 'my_secret_key'\n    .app_config('MY_SECRET_KEY_2', 'my_secret_key') # optional (>=3.2.0): use as app.config['MY_SECRET_KEY_2'] = 'my_secret_key'\n    .build()\n}\n\nfrom tjfu import Route\n\napp = TJFU.init_app(Route(\"index\", \"/\"))\n\nIS_PRODUCTION = False\n\nif __name__ == \"__main__\":\n    if IS_PRODUCTION:\n        app.run()\n    else:\n        TJFU.run()\n```\n\nDefine a Custom Route:\n```Python\n# OTHER CODE...\nfrom tjfu import Route, SimpleRenderTemplateRoute\n\nclass MyCustomRoute(Route):\n    def __init__(\n        self,\n        your_name: str\n    ):\n        super().__init__(\"mycustomroute\", \"/mycustomroute\")\n        self._your_name = your_name\n    \n        self._blueprint.route('/')(self._index) # /mycustomroute\n        self._blueprint.route('/jwt')(self._jwt) # /mycustomroute/jwt\n        self._blueprint.route('/class_variable')(self._class_variable) # /mycustomroute/class_variable\n        self._blueprint.route('/limiter')(self._limiter) # /mycustomroute/limiter\n    \n    # Basic route function\n    @staticmethod\n    def _index():\n        return \"Hello World!\"\n    \n    # JWT route function\n    @staticmethod\n    @jwt_required()\n    def _jwt():\n        return \"Hello From JWT!\"\n    \n    \n    # Class variable route function\n    def _class_variable(\n        self\n    ):\n        return f\"Hello {self._your_name}!\"\n    \n    # Limiter route function\n    @staticmethod\n    @TJFU.limiter().limit('1/second')\n    def _limiter():\n        return \"Hello from Limiter!\"\n    \n\nindex_route = Route(\"index\", \"/\")\nmy_custom_route = MyCustomRoute(\"John Doe\")\nanother_my_custom_route = MyCustomRoute(\"Lisa\")\n\n# /mycustomroute\nindex_route.register_route(my_custom_route)\n\n\"\"\"\n    You can easily define a route to\n    render an HTML file\n    using the SimpleRenderTemplateRoute class\n\"\"\"\n# /my_html_file\nindex_route.register_route(\n    SimpleRenderTemplateRoute(\n        \"my_html_file\",\n        \"/my_html_file\",\n        \"my_html_file.html\"\n    )\n)\n\n# /mycustomroute/mycustomroute\nmy_custom_route.register_route(another_my_custom_route)\n\n# You must register routes and sockets before calling the init_app function\napp = TJFU.init_app(index_route)\n\n# OTHER CODE...\n```\nRegister Routes using Dictionary (>=3.1.0):\n```Python\n# OTHER CODE...\n\napp = TJFU.init_app(\n    Route(\"index\", \"/\"), \n    {\n        Route(\"api\", \"/api\"):{\n            \n            Route(\"v1\", \"/v1\"):{\n                \n                Route(\"user\", \"/user\"):{\n            \n                }    \n                \n            }\n            \n        },\n        Route(\"tool\", \"/tool\"):{\n            SimpleRenderTemplateRoute(\n                \"my_tool\",\n                \"/my_tool\",\n                \"my_tool.html\"\n            )\n        },\n        SimpleRenderTemplateRoute(\n            \"hello_world\",\n            \"/hello_world\",\n            \"hello_world.html\"\n        ): None\n    }\n)\n\n# OTHER CODE...\n```\nGet Flask App after TJFU.build() (>=3.2.0)\n```Python\n# Example\nfrom tjfu import TJFU\nfrom flask_mail import Mail, Message\nmail = Mail(TJFU.app())\n```\nGet Extensions (JWT/Limiter/SocketIO) after TJFU.build() (>=3.3.0)\n```Python\nTJFU.jwt()\nTJFU.limiter()\nTJFU.socketio()\n```\nAdd custom extensions to TJFU after TJFU.build() (>=3.3.0)\n```Python\n# OTHER CODE...\n\nfrom flask_mail import Mail, Message\nmail = Mail(TJFU.app())\n\nTJFU.add_extension(\n    'send_mail',\n    mail\n) \n\napp = TJFU.init_app(index_route)\n\n# OTHER CODE...\n```\nAnd then you can take it out and use it in contexts (e.g. Route)\n```Python\nmail = TJFU.get_extension('send_mail')\n```\n\nDefine a Socket Handle:\n```Python\n# OTHER CODE...\n\nfrom tjfu import SocketEvent, SocketHandle\nfrom flask import request\nclass MySocketHandle(SocketHandle):\n    def __init__(self):\n        super().__init__(self._my_handle)\n        \n    def _my_handle(self, msg):\n        print(f\"Client id: {request.sid}\")\n        print(f\"Msg from client: {msg}\")\n        TJFU.emit(\n            SocketEvent(\"chat\", \"send\"),\n            \"Hello client from socket handle!!!\"\n        )\n        \nTJFU.register_socket_event(\n    SocketEvent(\"chat\", \"send\"),\n    MySocketHandle()\n) \n\napp = TJFU.init_app(index_route)\n\n# OTHER CODE...\n```\nYou can send data to the client via Socket in places outside the Socket Handle context (such as Route) through the TJFU.no_context_emit function\n\n```Python\nclass SendMsgRoute(Route):\n    def __init__(\n        self\n    ):\n        super().__init__(\"send_msg\", \"/send_msg\")\n        self._blueprint.route('/')(self._index)\n        \n    @staticmethod\n    def _index():\n        TJFU.no_context_emit(\n            SocketEvent(\"chat\", \"send\"),\n            \"Hello client from route!!!\"\n        )\n        return \"Hello World!\"\n```\nSimple HTML code to receive and send data from Socket\n```HTML\n<!DOCTYPE html>\n<html>\n<head>\n    <title>Socket.IO Example</title>\n    <script src=\"https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.3/socket.io.js\"></script>\n    <script type=\"text/javascript\">\n        var socket = io('http://0.0.0.0:3100/socket/chat');\n        socket.on('connect', function () {\n            console.log('Connected to the server');\n        });\n        socket.on('send', function (data) {\n            console.log('Message received: ' + data);\n        });\n        socket.on('disconnect', function () {\n            console.log('Disconnected from server');\n        });\n        function sendMessage() {\n            var message = document.getElementById('message').value;\n            socket.emit('send', message);\n        }\n    </script>\n</head>\n\n<body>\n    <h1>Socket.IO Example</h1>\n    <input type=\"text\" id=\"message\" placeholder=\"Enter message\">\n    <button onclick=\"sendMessage()\">Send</button>\n</body>\n\n</html>\n```\n\n### Changelog\n- `1.0.0`: First version released. There is a problem in Socket implementation.\n- `2.0.0`: Edit the Socket structure. There is a problem deploying the application to the production environment.\n- `3.0.0`: The version is relatively stable, overcoming the problem of deploying applications in production environments.\n- `3.1.0`: Added the function of registering Routes using Routes Map\n- `3.1.1`: Fixed an issue where additional variables could not be added when inheriting the _index function in Route.\n- `3.2.0`: Assign keys/values to Flask App Config using TJFU.app_config(...,...), add function TJFU.app() to get Flask App after calling TJFU.build(), use the add_status_code_handler function instead of the add_error_handler function.\n- `3.3.0`: Build functions that take instances of extensions and add custom extensions.\n\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Python library helps optimize Flask development to be flexible and object-oriented.",
    "version": "3.3.0",
    "project_urls": {
        "Homepage": "https://github.com/duynguyen02/tjfu"
    },
    "split_keywords": [
        "python",
        " flask"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "24974f70a51672a06fac715dbed53536e8ff2ed64c41f39e0721a9b2bb994859",
                "md5": "45419a159fcf8358650965b960d04b0c",
                "sha256": "735c72d6b45a563bd31d0057834f3acd11b22c8a09b6a064f5c381da5b59bce9"
            },
            "downloads": -1,
            "filename": "tjfu-3.3.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "45419a159fcf8358650965b960d04b0c",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.9",
            "size": 8007,
            "upload_time": "2024-04-27T18:19:06",
            "upload_time_iso_8601": "2024-04-27T18:19:06.791287Z",
            "url": "https://files.pythonhosted.org/packages/24/97/4f70a51672a06fac715dbed53536e8ff2ed64c41f39e0721a9b2bb994859/tjfu-3.3.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "b2af7e013d284b2dab79ed3663e387fe7ff8b0da1cba8726a73d8fb58f7e0ed9",
                "md5": "18b72ee82190429952839feb3ea2a8ae",
                "sha256": "8d13650ef5a0f2bb93c1b96e43b5f8d09ebccd99ebabce3b31bd6e29ccd97190"
            },
            "downloads": -1,
            "filename": "tjfu-3.3.0.tar.gz",
            "has_sig": false,
            "md5_digest": "18b72ee82190429952839feb3ea2a8ae",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.9",
            "size": 9856,
            "upload_time": "2024-04-27T18:19:08",
            "upload_time_iso_8601": "2024-04-27T18:19:08.781107Z",
            "url": "https://files.pythonhosted.org/packages/b2/af/7e013d284b2dab79ed3663e387fe7ff8b0da1cba8726a73d8fb58f7e0ed9/tjfu-3.3.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-04-27 18:19:08",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "duynguyen02",
    "github_project": "tjfu",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [],
    "lcname": "tjfu"
}
        
Elapsed time: 0.23466s