Metadata-Version: 2.1
Name: pyechonext
Version: 0.7.12
Summary: EchoNext is a lightweight, fast and scalable web framework for Python
License: LGPL-2.1
Author: alexeev-prog
Author-email: alexeev.dev@mail.ru
Requires-Python: >=3.9,<4.0
Classifier: License :: OSI Approved
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Dist: celery (>=5.0.0,<6.0.0)
Requires-Dist: gunicorn (>=22.0.0,<23.0.0)
Requires-Dist: jinja2 (>=3.1.0,<4.0.0)
Requires-Dist: loguru (>=0.7.0,<0.8.0)
Requires-Dist: orjson (>=3.10.12,<4.0.0)
Requires-Dist: parse (>=1.20.2,<2.0.0)
Requires-Dist: pysocks (>=1.7.1,<2.0.0)
Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
Requires-Dist: requests (>=2.32.3,<3.0.0)
Requires-Dist: rich (>=13.8.3,<14.0.0)
Requires-Dist: toml (>=0.10.2,<0.11.0)
Description-Content-Type: text/markdown

# 🌟 **EchoNext: The Future of Web** 🚀
<a id="readme-top"></a> 

<div align="center">  
  <p align="center">
    EchoNext is a lightweight, fast and scalable web framework for Python
    <br />
    <a href="https://alexeev-prog.github.io/pyEchoNext/"><strong>Explore the docs »</strong></a>
    <br />
    <br />
    <a href="#-comparison-with-alternatives">Comparison with Alternatives</a>
    .
    <a href="#-why-choose-pyechonext">Why Choose pyEchoNext</a>
    ·
    <a href="#-key-features">Key Features</a>
    ·
    <a href="#-getting-started">Getting Started</a>
    ·
    <a href="#-usage-examples">Basic Usage</a>
    ·
    <a href="#-specifications">Specification</a>
    ·
    <a href="https://alexeev-prog.github.io/pyEchoNext/">Documentation</a>
    ·
    <a href="https://github.com/alexeev-prog/pyEchoNext/blob/main/LICENSE">License</a>
  </p>
</div>
<br>
<p align="center">
    <img src="https://img.shields.io/github/languages/top/alexeev-prog/pyEchoNext?style=for-the-badge">
    <img src="https://img.shields.io/github/languages/count/alexeev-prog/pyEchoNext?style=for-the-badge">
    <img src="https://img.shields.io/github/license/alexeev-prog/pyEchoNext?style=for-the-badge">
    <img src="https://img.shields.io/github/stars/alexeev-prog/pyEchoNext?style=for-the-badge">
    <img src="https://img.shields.io/github/issues/alexeev-prog/pyEchoNext?style=for-the-badge">
    <img src="https://img.shields.io/github/last-commit/alexeev-prog/pyEchoNext?style=for-the-badge">
</p>

 > EchoNext is a lightweight, fast and scalable web framework for Python

Welcome to **EchoNext**, where innovation meets simplicity! Are you tired of the sluggishness of traditional web frameworks? Want a solution that keeps pace with your ambitious apps? Look no further. EchoNext is your agile companion in the world of web development!

<p align="center">
    <img src="https://raw.githubusercontent.com/alexeev-prog/pyEchoNext/refs/heads/main/docs/logo.jpg" width='600px' height='600px'>
</p>

**Imagine** a lightweight framework that empowers you to create modern web applications with lightning speed and flexibility. With EchoNext, you're not just coding; you're building a masterpiece!

 > Last stable version: 0.7.12 alpha

 > Next Big Update: ASYNC & unicorn support

## Check Other My Projects

 + [SQLSymphony](https://github.com/alexeev-prog/SQLSymphony) - simple and fast ORM in sqlite (and you can add other DBMS)
 + [Burn-Build](https://github.com/alexeev-prog/burn-build) - simple and fast build system written in python for C/C++ and other projects. With multiprocessing, project creation and caches!
 + [OptiArch](https://github.com/alexeev-prog/optiarch) - shell script for fast optimization of Arch Linux
 + [libnumerixpp](https://github.com/alexeev-prog/libnumerixpp) - a Powerful C++ Library for High-Performance Numerical Computing
 + [pycolor-palette](https://github.com/alexeev-prog/pycolor-palette) - display beautiful log messages, logging, debugging.
 + [shegang](https://github.com/alexeev-prog/shegang) - powerful command interpreter (shell) for linux written in C

## 🤔 Why Choose SqlSymphony?

- **🔥 Featherweight Performance**: No bloat, just speed! Our framework is designed to optimize performance, making it a breeze to create and scale your applications without the overhead.
  
- **💼 Unmatched Scalability**: Handle thousands of connections effortlessly! Echonext is built for performance in high-demand environments, making it the perfect choice for startups or enterprise applications.

- **🔧 Customizable Architecture**: Tailor your framework to suit your unique needs. Whether it’s middleware, routing, or authentication, make it yours with minimal effort!

- **🌍 Cross-Platform Compatibility**: Echonext works beautifully on any OS. Whether you’re developing on Windows, macOS, or Linux, you’re covered!

- **💡 User-Friendly Design**: Our intuitive API and comprehensive documentation make it easy for beginners and pros alike. Dive in and start coding right away!

- **📦 Plug-and-Play Components**: Easily integrate with third-party libraries to enhance your application. Don’t reinvent the wheel—leverage existing solutions!

- **🔒 Built-in Authentication**: Simplify your user authentication process with our built-in, easy-to-implement features.

- **📊 Automatic API Documentation**: Create RESTful endpoints that are not just powerful but also well-documented, saving you time and effort.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

## 🌟 Comparison with Alternatives

| Feature                   | **pyEchoNext**      | Flask        | FastAPI      | Django        | Starlette    |
|---------------------------|---------------------|--------------|--------------|---------------|--------------|
| Asynchronous Capabilities | COMING SOON         | ❌           | ✔️           | ❌            | ✔️           |
| Performance               | 🔥 High             | 🐢 Moderate  | 🚀 Very High | 🐢 Moderate   | 🚀 Very High |
| Framework Weight          | ✔️                  | ✔️           | ✔️           | ❌ Heavy      | ✔️           |
| Ecosystem                 | 🛠️ Modular          | 🎨 Flexible  | 🎨 Modular   | ⚙️ Monolithic | ⚙️ Modular   |
| Ease of Use               | ✔️                  | ✔️           | ✔️           | ❌            | ✔️           |
| Configurability           | ✔️                  | ✔️           | ✔️           | ✔️            | ✔️           |
| Documentation Quality     | 📚 Excellent        | 📚 Good      | 📚 Excellent | 📚 Very Good  | 📚 Good      |
| Flexible Deployments      | 🌍 Flexible         | 🌍 Standard  | 🌍 Standard  | 🌍 Standard   | 🌍 Flexible  |
| Testing Support           | ✔️                  | ✔️           | ✔️           | ✔️            | ✔️           |
| Community Size            | 📢 Growing          | 📢 Large     | 📢 Growing   | 📢 Large      | 📢 Emerging  |
| Built-in Template Engine  | ✔️ Jinja2 & builtin | ✔️ Jinja2    | ✔️ Jinja2    | ✔️ Django     | ✔️ Jinja2    |
| Task Queue Integration    | ❌                  | ✔️ Celery    | ✔️ Celery    | ✔️ Celery     | ✔️ Celery    |
| Static File Serving       | 🌍 Manual           | 🌍 Manual    | 🚀 Built-in  | 🚀 Built-in   | 🚀 Built-in  |
| Analytics Integration     | ✔️ Easy             | 🛠️ Manual    | ✔️ Easy      | ❌            | ✔️ Easy      |

📈 Note: Echonext excels in performance while staying lightweight, making it a top-notch choice for your next project!

## 📚 Key Features

- Intuitive API: Pythonic, object-oriented interface for interacting with routes and views.
- Performance Optimization: Lazy loading, eager loading, and other techniques for efficient web queries.
- Comprehensive Documentation: Detailed usage examples and API reference to help you get started.
- Modular Design: Clean, maintainable codebase that follows best software engineering practices.
- Extensive Test Coverage: Robust test suite to ensure the library's reliability and stability.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

## ⚙️ Functionality

 + i18n/l10n localization
 + basic project documentation generator
 + request/response
 + middlewares (with basic session cookie middleware)
 + views and routes
 + settings and config loader
 + built-in template engine and Jinja2
 + basic security and hashing
 + static files management
 + cache response bodies
 + performance
 + slugger
 + permissions

<p align="right">(<a href="#readme-top">back to top</a>)</p>

## 🚀 Getting Started

pyEchoNext is available on [PyPI](https://pypi.org/project/pyechonext). Simply install the package into your project environment with PIP:

```bash
pip install pyechonext
```

Once installed, you can start using the library in your Python projects. Check out the [documentation](https://alexeev-prog.github.io/pyEchoNext) for detailed usage examples and API reference.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

## 💻 Usage Examples
You can view examples at [examples directory](./examples).

### Performance caching

```python
import random
from pyechonext.utils.performance import InMemoryPerformanceCache, SingletonPerformanceCache, performance_cached

memorycache = InMemoryPerformanceCache
perf = SingletonPerformanceCache(memorycache)


@performance_cached(perf)
def example_function(a: int = 10 ** 6):
    inside_circle = 0

    for _ in range(a):
        x = random.uniform(-1, 1)
        y = random.uniform(-1, 1)
        if x ** 2 + y ** 2 <= 1:
            inside_circle += 1

    return (inside_circle / a) * 4


if __name__ == '__main__':
    print('start')
    print(f'{example_function()} - Caching')
    print(f'{example_function()} - Cached')
    print(f'{example_function(10 ** 7)} - Caching new')
```

### Permissions

```python
from pyechonext.permissions import (
    Permission,
    Role,
    Resource,
    AccessControlRule,
    Policy,
    AgeRestrictionsABP,
    User,
    DefaultPermissionChecker,
    UserController,
)

view_users_perm = Permission("view_users")
edit_users_perm = Permission("edit_users")

admin_role = Role("admin")
admin_role.add_permission(view_users_perm)
admin_role.add_permission(edit_users_perm)

user_role = Role("user")
user_role.add_permission(view_users_perm)

user_resource = Resource("UserResource")

policy = Policy()
policy.add_rule(AccessControlRule(admin_role, view_users_perm, user_resource, True))
policy.add_rule(AccessControlRule(admin_role, edit_users_perm, user_resource, True))
policy.add_rule(AccessControlRule(user_role, view_users_perm, user_resource, True))
policy.add_rule(AccessControlRule(user_role, edit_users_perm, user_resource, False))

age_policy = AgeRestrictionsABP(conditions={"age": 18}, rules=policy.rules)
age_policy.add_rule(AccessControlRule(user_role, view_users_perm, user_resource, True))

admin_user = User("admin", attributes={"age": 30})
admin_user.add_role(admin_role)

young_user = User("john_doe", attributes={"age": 17})
young_user.add_role(user_role)

permission_checker = DefaultPermissionChecker(policy)
user_controller = UserController(permission_checker)


def main():
    assert user_controller.view_users(admin_user, user_resource) == (
        "200 OK",
        "User edit form",
    )
    assert user_controller.edit_users(admin_user, user_resource) == (
        "200 OK",
        "User edit form",
    )
    assert user_controller.edit_users(young_user, user_resource) == (
        "403 Forbidden",
        "You do not have permission to edit users.",
    )

    assert age_policy.evaluate(young_user, user_resource, view_users_perm) == False
    assert age_policy.evaluate(admin_user, user_resource, view_users_perm) == True


if __name__ == "__main__":
    main()
```

### FullApp with locale, static files, docs generation
Also see in [examples](./examples/example_locale.py)

```python
from pyechonext.apidoc_ui import APIDocUI, APIDocumentation
from pyechonext.app import ApplicationType, EchoNext
from pyechonext.config import SettingsConfigType, SettingsLoader
from pyechonext.middleware import middlewares
from pyechonext.mvc.controllers import PageController
from pyechonext.static import StaticFile
from pyechonext.template_engine.jinja import render_template
from pyechonext.urls import URL
from pyechonext.utils.exceptions import MethodNotAllow


class UsersView(PageController):
    def get(self, request, response, *args, **kwargs):
        return render_template(
            request,
            "index.html",
            user_name="User",
            session_id=request.session_id,
            friends=["Bob", "Anna", "John"],
        )

    def post(self, request, response, *args, **kwargs):
        raise MethodNotAllow(f"Request {request.path}: method not allow")


url_patterns = [URL(path="/users", controller=UsersView)]
config_loader = SettingsLoader(SettingsConfigType.PYMODULE, "el_config.py")
settings = config_loader.get_settings()
static_files = [StaticFile(settings, "styles.css")]
echonext = EchoNext(
    __name__,
    settings,
    middlewares,
    urls=url_patterns,
    application_type=ApplicationType.HTML,
    static_files=static_files,
)
apidoc = APIDocumentation(echonext)


@echonext.route_page("/api-docs")
def api_docs(request, response):
    ui = APIDocUI(apidoc.generate_spec())
    return ui.generate_html_page()


@echonext.route_page("/book")
class BooksResource(PageController):
    """
    This class describes a books resource.
    """

    def get(self, request, response, **kwargs):
        """
        get queries

        :param      request:   The request
        :type       request:   Request
        :param      response:  The response
        :type       response:  Response
        :param      kwargs:    The keywords arguments
        :type       kwargs:    dictionary

        :returns:   result
        :rtype:     str
        """
        return echonext.i18n_loader.get_string("title %{name}", name=str(request.GET))

    def post(self, request, response, **kwargs):
        """
        post queries

        :param      request:   The request
        :type       request:   Request
        :param      response:  The response
        :type       response:  Response
        :param      kwargs:    The keywords arguments
        :type       kwargs:    dictionary

        :returns:   result
        :rtype:     str
        """
        return echonext.l10n_loader.format_currency(1305.50)

```

Create file `static/styles.css`:

```css
body {
    color: #f8f2f2;
    background: #1f1f1f;
    font-family: monospace;
}
```

Create file `el_config.py`:

```python
import os

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
TEMPLATES_DIR = 'templates'
SECRET_KEY = 'secret-key'
LOCALE = 'RU_RU'
LOCALE_DIR = 'locales'
VERSION = "0.1.0"
DESCRIPTION = 'Example echonext webapp'
STATIC_DIR = 'static'
```

Create file `locales/RU_RU.json`:

```python
{
    "i18n": {
        "title": "pyEchoNext Веб-приложение с локалью",
        "example one": "пример один"
    },
    "l10n": {
        "date_format": "%Y-%m-%d",
        "time_format": "%H:%M",
        "date_time_fromat": "%Y-%m-%d %H:%M",
        "thousands_separator": ",",
        "decimal_separator": ".",
        "currency_symbol": "$",
        "currency_format": "{symbol}{amount}"
    }
}
```

<p align="right">(<a href="#readme-top">back to top</a>)</p>

## 🔧 Specifications

### Security
A security module created for hash functions and crypto-algorithms.

#### Crypts
Simple crypto-algorithms.

##### PSPCAlgorithm
Point Simple Password Crypt Algorithm.

```
Base: AngryPassword
Crypted: 00778.87999.74379.363401.558001.558001.96058.06107.711601.87999.13309.07469.50075
Decrypted: AngryPassword

Base: S0mesd7623tds@&6^@_
Crypted: 51338.82165.83428.85374.62333.82165.558001.00778.237101.72744.05834.85374.53284.00778.558001.77588.39559.69024.19727
Decrypted: S0mesd7623tds@&6^@_

Base: PassWord
Crypted: 00778.87999.74379.99267.558001.558001.96058.06107
Decrypted: PassWord

Base: Pass
Crypted: 558001.558001.96058.06107
Decrypted: Pass
```

Example:

```python
from pyechonext.security.crypts import PSPCAlgorithm


pspc = PSPCAlgorithm()

passwords = ['AngryPassword', 'S0mesd7623tds@&6^@_', 'PassWord', 'Pass']

for password in passwords:
    print('Base:', password)
    print('Crypted:', pspc.crypt(password))
    print('Decrypted:', pspc.decrypt(pspc.crypt(password)))
    print()
```

#### Hashing
 
 + Module: `pyechonext.security.hashing`

##### HashAlgorithm
Enum class with available hashing algorithms

```python
class HashAlgorithm(Enum):
    """
    This class describes a hash algorithms.
    """

    SHA256 = auto()
    SHA512 = auto()
    MD5 = auto()
    BLAKE2B = auto()
    BLAKE2S = auto()
```

##### PlainHasher
A simple class for hashing text. Has no 'salting'.

```python
hasher = PlainHasher(HashAlgorithm.BLAKE2S)
old_hash = hasher.hash("TEXT")
new_hash = hasher.hash("TEXT")

if hasher.verify("TEXT", new_hash): # true
    print('Yes!')

if hasher.verify("TEXT2", old_hash): # false
    print('Yes!')

# Output: one "Yes!"
```

##### SaltedHasher
A simple class for hashing text. Has hash salt.

```python
hasher = SaltedHasher(HashAlgorithm.BLAKE2S, salt='bob')
old_hash = hasher.hash("TEXT")
new_hash = hasher.hash("TEXT")

if hasher.verify("TEXT", new_hash): # true
    print('Yes!')

if hasher.verify("TEXT2", old_hash): # false
    print('Yes!')

# Output: one "Yes!"
```

### View
View is an abstract class, with abstract get and post methods (all descendants must create these methods).

```python
class View(ABC):
    """
    Page view
    """

    @abstractmethod
    def get(self, request: Request, response: Response, *args, **kwargs):
        """
        Get

        :param      request:   The request
        :type       request:   Request
        :param      response:  The response
        :type       response:  Response
        :param      args:      The arguments
        :type       args:      list
        :param      kwargs:    The keywords arguments
        :type       kwargs:    dictionary
        """
        raise NotImplementedError

    @abstractmethod
    def post(self, request: Request, response: Response, *args, **kwargs):
        """
        Post

        :param      request:   The request
        :type       request:   Request
        :param      response:  The response
        :type       response:  Response
        :param      args:      The arguments
        :type       args:      list
        :param      kwargs:    The keywords arguments
        :type       kwargs:    dictionary
        """
        raise NotImplementedError
```

Example of view:

```python
class IndexView(View):
    def get(self, request: Request, response: Response, **kwargs):
        """
        Get

        :param      request:   The request
        :type       request:   Request
        :param      response:  The response
        :type       response:  Response
        :param      args:      The arguments
        :type       args:      list
        :param      kwargs:    The keywords arguments
        :type       kwargs:    dictionary
        """
        return "Hello World!"

    def post(self, request: Request, response: Response, **kwargs):
        """
        Post

        :param      request:   The request
        :type       request:   Request
        :param      response:  The response
        :type       response:  Response
        :param      args:      The arguments
        :type       args:      list
        :param      kwargs:    The keywords arguments
        :type       kwargs:    dictionary
        """
        return "Message has accepted!"
```

Or you can return response:

```python
class IndexView(View):
    def get(self, request: Request, response: Response, **kwargs):
        """
        Get

        :param      request:   The request
        :type       request:   Request
        :param      response:  The response
        :type       response:  Response
        :param      args:      The arguments
        :type       args:      list
        :param      kwargs:    The keywords arguments
        :type       kwargs:    dictionary
        """
        return Response(request, body="Hello World!")

    def post(self, request: Request, response: Response, **kwargs):
        """
        Post

        :param      request:   The request
        :type       request:   Request
        :param      response:  The response
        :type       response:  Response
        :param      args:      The arguments
        :type       args:      list
        :param      kwargs:    The keywords arguments
        :type       kwargs:    dictionary
        """
        return Response(request, body="Message has accepted!")
```

## Tests coverage
To test the web framework, PyTest with the pytest-cov plugin is used. You can look at the tests in [tests directory](./tests)

| Statements | Miss       | Coverage |
|------------|------------|----------|
| 1327       | 936        | 34%      |

## Documentation 🌍
Extended documentation and framework specifications are available at the following links:

### English

1. [Index](./docs/en/index.md)
2. [Web framework design](./docs/en/webframework_design.md)
3. [Creating a web application](./docs/en/webapp_creation.md)
4. [Creating routes (routes&views)](./docs/en/routes_and_views.md)
5. [Request/Response](./docs/en/requests_responses.md)
6. [Localization i18n/l10n](./docs/en/i18n_locales.md)
7. [Security](./docs/en/security.md)
8. [Permissions & rights](./docs/en/permissions.md)

### Russian / Русский

1. [Содержание](./docs/ru/index.md)
2. [Устройство веб-фреймворка](./docs/ru/webframework_design.md)
3. [Создание веб-приложения](./docs/ru/webapp_creation.md)
4. [Создание маршрутов (routes&views)](./docs/ru/routes_and_views.md)
5. [Request/Response](./docs/ru/requests_responses.md)
6. [Локализация i18n/l10n](./docs/ru/i18n_locales.md)
7. [Безопасность](./docs/ru/security.md)
8. [Разрешения и права](./docs/ru/permissions.md)

## 💬 Support
If you encounter any issues or have questions about pyEchoNext, please:

- Check the [documentation](https://alexeev-prog.github.io/pyEchoNext) for answers
- Open an [issue on GitHub](https://github.com/alexeev-prog/pyEchoNext/issues/new)
- Reach out to the project maintainers via the [mailing list](mailto:alexeev.dev@mail.ru)

<p align="right">(<a href="#readme-top">back to top</a>)</p>

## 🤝 Contributing
We welcome contributions from the community! If you'd like to help improve pyEchoNext, please check out the [contributing guidelines](https://github.com/alexeev-prog/pyEchoNext/blob/main/CONTRIBUTING.md) to get started.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

## 👥 Join the Community!
If you find Echonext valuable and want to support the project:

- Star on GitHub ⭐
- Share it with friends and colleagues!
- Donate via cryptocurrency 🙌

Connect with fellow Echonext users: [Join our Telegram Chat](https://t.me/pyEchoNext_Forum)

## 🔮 Roadmap
Our future goals for pyEchoNext include:

- 📚 Improve middlewares
- 🚀 Add async support
- ✅ Improve logging
- 🌍 Add authentication, JWT tokens
- 💻 Depedency Injection
- 🌐 More stability and scalablity

<p align="right">(<a href="#readme-top">back to top</a>)</p>

## 🌟 Get Started Today!
Unlock your potential as a developer with Echonext. Don’t just build applications—craft experiences that resonate with your users! The possibilities are limitless when you harness the power of Echonext. 

**Happy Coding!** 💻✨

This README is designed to grab attention from the very first lines. It emphasizes the framework's strengths and makes a compelling case for why developers should choose Echonext for their projects. Feel free to adjust any specific links or images to fit your project!

## License
Distributed under the GNU LGPL 2.1 License. See [LICENSE](https://github.com/alexeev-prog/pyEchoNext/blob/main/LICENSE) for more information.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

---

EchoNext is a lightweight, fast and scalable web framework for Python
Copyright (C) 2024  Alexeev Bronislav (C) 2024

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
USA

