Skip to content

API Reference

In development

There is only initial API reference, thats why the provided info may be not full

Pyue

Master of WEB UI

Source code in pyue/core/app.py
class Pyue:
    """Master of WEB UI"""

    def __init__(
        self,
        backend_type: BackendType,
        static_path: str | None = "static",
        template_path: str | None = "templates",
        logger=logger,
    ) -> None:
        """
        Initialize the Pyue application.

        Args:
            backend_type (BackendType): The type of backend to use (e.g., Flask).
            static_path (str | None, optional): Path to the static files directory.
                Defaults to "static".
            template_path (str | None, optional): Path to the templates directory.
                Defaults to "templates".
            logger: Logger instance for logging messages. Defaults to the loguru logger.

        Raises:
            UnsupportedBackendError: If the provided backend_type is not supported.
        """
        self.logger = logger

        # Creating backend
        if not isinstance(backend_type, BackendType):
            self.logger.error(
                f"Failed to create app with backend type `{backend_type}`"
            )
            raise UnsupportedBackendError(backend_type)

        if backend_type == BackendType.Flask:
            self._backend = FlaskBackend(
                static_path=static_path, template_path=template_path, logger=self.logger
            )
        elif backend_type == BackendType.FastAPI:
            raise NotImplementedError()

        self.static_path = static_path
        self.template_path = template_path

    @property
    def router(self) -> Any:
        """
        Returns the framework-specific router object.

        For Flask backend, this is a Blueprint. For other backends, it will be the
        corresponding router object (e.g., APIRouter for FastAPI).

        Returns:
            Any: The router object from the underlying backend.
        """
        return self._backend.router

    def add_page(self, page: Page, url: str, **kwargs) -> None:
        """
        Add a page to the application and write its template file.

        This method registers the page with the backend's router and writes the
        page's content to a file in the template directory.

        Args:
            page (Page): The page object containing the template content and filename.
            url (str): The URL rule for the page (e.g., '/' or '/about').
            **kwargs: Additional keyword arguments passed to the backend's add_page method,
                such as context_func.
        """
        self._backend.add_page(page=page, url=url, **kwargs)
        page.to_file(os.path.join(self.template_path, page.filename))
        self.logger.debug(
            f"Page `{page.filename}` ({page.title[:50]}) successfully built"
        )

    def mount(self, app, **kwargs):
        """
        Mount the backend's router onto the given framework application.

        This method delegates to the underlying backend's mount method to integrate
        the router with the main application instance (e.g., a Flask app).

        Args:
            app: The framework application instance (e.g., Flask, FastAPI).
            **kwargs: Additional keyword arguments passed to the backend's mount method.
        """
        self._backend.mount(app, **kwargs)

router property

Returns the framework-specific router object.

For Flask backend, this is a Blueprint. For other backends, it will be the corresponding router object (e.g., APIRouter for FastAPI).

Returns:

Name Type Description
Any Any

The router object from the underlying backend.

__init__(backend_type, static_path='static', template_path='templates', logger=logger)

Initialize the Pyue application.

Parameters:

Name Type Description Default
backend_type BackendType

The type of backend to use (e.g., Flask).

required
static_path str | None

Path to the static files directory. Defaults to "static".

'static'
template_path str | None

Path to the templates directory. Defaults to "templates".

'templates'
logger

Logger instance for logging messages. Defaults to the loguru logger.

logger

Raises:

Type Description
UnsupportedBackendError

If the provided backend_type is not supported.

Source code in pyue/core/app.py
def __init__(
    self,
    backend_type: BackendType,
    static_path: str | None = "static",
    template_path: str | None = "templates",
    logger=logger,
) -> None:
    """
    Initialize the Pyue application.

    Args:
        backend_type (BackendType): The type of backend to use (e.g., Flask).
        static_path (str | None, optional): Path to the static files directory.
            Defaults to "static".
        template_path (str | None, optional): Path to the templates directory.
            Defaults to "templates".
        logger: Logger instance for logging messages. Defaults to the loguru logger.

    Raises:
        UnsupportedBackendError: If the provided backend_type is not supported.
    """
    self.logger = logger

    # Creating backend
    if not isinstance(backend_type, BackendType):
        self.logger.error(
            f"Failed to create app with backend type `{backend_type}`"
        )
        raise UnsupportedBackendError(backend_type)

    if backend_type == BackendType.Flask:
        self._backend = FlaskBackend(
            static_path=static_path, template_path=template_path, logger=self.logger
        )
    elif backend_type == BackendType.FastAPI:
        raise NotImplementedError()

    self.static_path = static_path
    self.template_path = template_path

add_page(page, url, **kwargs)

Add a page to the application and write its template file.

This method registers the page with the backend's router and writes the page's content to a file in the template directory.

Parameters:

Name Type Description Default
page Page

The page object containing the template content and filename.

required
url str

The URL rule for the page (e.g., '/' or '/about').

required
**kwargs

Additional keyword arguments passed to the backend's add_page method, such as context_func.

{}
Source code in pyue/core/app.py
def add_page(self, page: Page, url: str, **kwargs) -> None:
    """
    Add a page to the application and write its template file.

    This method registers the page with the backend's router and writes the
    page's content to a file in the template directory.

    Args:
        page (Page): The page object containing the template content and filename.
        url (str): The URL rule for the page (e.g., '/' or '/about').
        **kwargs: Additional keyword arguments passed to the backend's add_page method,
            such as context_func.
    """
    self._backend.add_page(page=page, url=url, **kwargs)
    page.to_file(os.path.join(self.template_path, page.filename))
    self.logger.debug(
        f"Page `{page.filename}` ({page.title[:50]}) successfully built"
    )

mount(app, **kwargs)

Mount the backend's router onto the given framework application.

This method delegates to the underlying backend's mount method to integrate the router with the main application instance (e.g., a Flask app).

Parameters:

Name Type Description Default
app

The framework application instance (e.g., Flask, FastAPI).

required
**kwargs

Additional keyword arguments passed to the backend's mount method.

{}
Source code in pyue/core/app.py
def mount(self, app, **kwargs):
    """
    Mount the backend's router onto the given framework application.

    This method delegates to the underlying backend's mount method to integrate
    the router with the main application instance (e.g., a Flask app).

    Args:
        app: The framework application instance (e.g., Flask, FastAPI).
        **kwargs: Additional keyword arguments passed to the backend's mount method.
    """
    self._backend.mount(app, **kwargs)

Backend (API)

Bases: ABC

Abstract base class for HTTP server backends.

This class defines the interface that all backend implementations must follow.

Source code in pyue/core/backend.py
class Backend(ABC):
    """Abstract base class for HTTP server backends.

    This class defines the interface that all backend implementations
    must follow.
    """

    @property
    def router(self) -> Any:
        """
        Abstract property that returns the framework-specific router object.

        The router contains all registered frontend endpoints. For Flask,
        this is a Blueprint; for FastAPI, it would be an APIRouter.

        Returns:
            Any: The router instance containing the frontend routes.
        """
        raise NotImplementedError()

    @abstractmethod
    def add_page(self, page: Page, url: str, **kwargs) -> None:
        """
        Add a page to the backend's router.

        This method registers a new route for the given URL and associates it
        with the provided page. The page's content will be served when the URL
        is accessed.

        Args:
            page (Page): The page object containing template and content information.
            url (str): The URL path at which the page should be served.
            **kwargs: Additional framework-specific keyword arguments or context function.
        """
        raise NotImplementedError()

    @abstractmethod
    def mount(self, app, **kwargs) -> None:
        """
        Mount the backend's router onto the main application.

        This method integrates the router containing all frontend pages into
        the main application instance (e.g., a Flask or FastAPI app).

        Args:
            app: The main framework application instance.
            **kwargs: Additional framework-specific keyword arguments for mounting.
        """
        raise NotImplementedError()

router property

Abstract property that returns the framework-specific router object.

The router contains all registered frontend endpoints. For Flask, this is a Blueprint; for FastAPI, it would be an APIRouter.

Returns:

Name Type Description
Any Any

The router instance containing the frontend routes.

add_page(page, url, **kwargs) abstractmethod

Add a page to the backend's router.

This method registers a new route for the given URL and associates it with the provided page. The page's content will be served when the URL is accessed.

Parameters:

Name Type Description Default
page Page

The page object containing template and content information.

required
url str

The URL path at which the page should be served.

required
**kwargs

Additional framework-specific keyword arguments or context function.

{}
Source code in pyue/core/backend.py
@abstractmethod
def add_page(self, page: Page, url: str, **kwargs) -> None:
    """
    Add a page to the backend's router.

    This method registers a new route for the given URL and associates it
    with the provided page. The page's content will be served when the URL
    is accessed.

    Args:
        page (Page): The page object containing template and content information.
        url (str): The URL path at which the page should be served.
        **kwargs: Additional framework-specific keyword arguments or context function.
    """
    raise NotImplementedError()

mount(app, **kwargs) abstractmethod

Mount the backend's router onto the main application.

This method integrates the router containing all frontend pages into the main application instance (e.g., a Flask or FastAPI app).

Parameters:

Name Type Description Default
app

The main framework application instance.

required
**kwargs

Additional framework-specific keyword arguments for mounting.

{}
Source code in pyue/core/backend.py
@abstractmethod
def mount(self, app, **kwargs) -> None:
    """
    Mount the backend's router onto the main application.

    This method integrates the router containing all frontend pages into
    the main application instance (e.g., a Flask or FastAPI app).

    Args:
        app: The main framework application instance.
        **kwargs: Additional framework-specific keyword arguments for mounting.
    """
    raise NotImplementedError()

BackendType

Bases: Enum

Available backend frameworks

Source code in pyue/core/backend.py
class BackendType(Enum):
    """Available backend frameworks"""

    Flask = 1
    FastAPI = 2

FlaskBackend

Bases: Backend

Backend for Flask web framework

Source code in pyue/backend/flask.py
class FlaskBackend(Backend):
    """
    Backend for Flask web framework
    """

    def __init__(
        self,
        static_path: str,
        template_path: str,
        router: Blueprint | None = None,
        logger=logger,
    ) -> None:
        """
        Initialize the FlaskBackend.

        Args:
            static_path (str): Path to the static files directory.
            template_path (str): Path to the templates directory.
            router (Blueprint | None, optional): An existing Flask Blueprint to use.
                If None, a new Blueprint is created. Defaults to None.
            logger: Logger instance for logging messages. Defaults to the loguru logger.
        """
        super().__init__()
        self.logger = logger
        if router and isinstance(router, Blueprint):
            self._router = router
        else:
            self._router = Blueprint(
                "frontend",
                __name__,
                template_folder=template_path,
                static_folder=static_path,
            )
        self.static_path = static_path
        self.template_path = template_path

    @property
    def router(self) -> Blueprint:
        """
        Blueprint: The Flask Blueprint associated with this backend.
        """
        return self._router

    def add_page(self, page: Page, url: str, context_func=None) -> None:
        """
        Add a page to the backend's Blueprint.

        Args:
            page (Page): The page object containing the template filename and other page data.
            url (str): The URL rule for the page (e.g., '/' or '/about').
            context_func (callable, optional): A function that returns a dictionary of additional context variables.
                The function receives any keyword arguments captured from the URL and should return a dict.
                Defaults to None.

        Raises:
            AddPageError: If adding the page to the Blueprint fails due to an exception.
        """
        try:
            # Handler with context support
            def handler(**kwargs):
                try:
                    context = kwargs
                    if context_func:
                        extra_context = context_func(**kwargs)
                        if isinstance(extra_context, dict):
                            context.update(extra_context)
                    return render_template(page.filename, **context)
                except Exception:
                    self.logger.error(f"Failed to show page: {traceback.format_exc()}")
                    abort(500)

            self._router.add_url_rule(
                url, endpoint=url.replace("/", "_"), view_func=handler, methods=["GET"]
            )
        except Exception as e:
            self.logger.error(f"Failed to add page: {e}")
            raise AddPageError(traceback.format_exc())

    def mount(self, app: Flask) -> None:
        """
        Mount the backend's Blueprint onto a Flask application.

        Args:
            app (Flask): The Flask application instance.

        Raises:
            MountBackendError: If registering the blueprint with the Flask app fails.
        """
        try:
            app.template_folder = self.template_path
            app.static_folder = self.static_path
            app.register_blueprint(self.router)
        except Exception as e:
            self.logger.error(f"Failed to mount backend: {e}")
            raise MountBackendError(traceback.format_exc())

router property

Blueprint: The Flask Blueprint associated with this backend.

__init__(static_path, template_path, router=None, logger=logger)

Initialize the FlaskBackend.

Parameters:

Name Type Description Default
static_path str

Path to the static files directory.

required
template_path str

Path to the templates directory.

required
router Blueprint | None

An existing Flask Blueprint to use. If None, a new Blueprint is created. Defaults to None.

None
logger

Logger instance for logging messages. Defaults to the loguru logger.

logger
Source code in pyue/backend/flask.py
def __init__(
    self,
    static_path: str,
    template_path: str,
    router: Blueprint | None = None,
    logger=logger,
) -> None:
    """
    Initialize the FlaskBackend.

    Args:
        static_path (str): Path to the static files directory.
        template_path (str): Path to the templates directory.
        router (Blueprint | None, optional): An existing Flask Blueprint to use.
            If None, a new Blueprint is created. Defaults to None.
        logger: Logger instance for logging messages. Defaults to the loguru logger.
    """
    super().__init__()
    self.logger = logger
    if router and isinstance(router, Blueprint):
        self._router = router
    else:
        self._router = Blueprint(
            "frontend",
            __name__,
            template_folder=template_path,
            static_folder=static_path,
        )
    self.static_path = static_path
    self.template_path = template_path

add_page(page, url, context_func=None)

Add a page to the backend's Blueprint.

Parameters:

Name Type Description Default
page Page

The page object containing the template filename and other page data.

required
url str

The URL rule for the page (e.g., '/' or '/about').

required
context_func callable

A function that returns a dictionary of additional context variables. The function receives any keyword arguments captured from the URL and should return a dict. Defaults to None.

None

Raises:

Type Description
AddPageError

If adding the page to the Blueprint fails due to an exception.

Source code in pyue/backend/flask.py
def add_page(self, page: Page, url: str, context_func=None) -> None:
    """
    Add a page to the backend's Blueprint.

    Args:
        page (Page): The page object containing the template filename and other page data.
        url (str): The URL rule for the page (e.g., '/' or '/about').
        context_func (callable, optional): A function that returns a dictionary of additional context variables.
            The function receives any keyword arguments captured from the URL and should return a dict.
            Defaults to None.

    Raises:
        AddPageError: If adding the page to the Blueprint fails due to an exception.
    """
    try:
        # Handler with context support
        def handler(**kwargs):
            try:
                context = kwargs
                if context_func:
                    extra_context = context_func(**kwargs)
                    if isinstance(extra_context, dict):
                        context.update(extra_context)
                return render_template(page.filename, **context)
            except Exception:
                self.logger.error(f"Failed to show page: {traceback.format_exc()}")
                abort(500)

        self._router.add_url_rule(
            url, endpoint=url.replace("/", "_"), view_func=handler, methods=["GET"]
        )
    except Exception as e:
        self.logger.error(f"Failed to add page: {e}")
        raise AddPageError(traceback.format_exc())

mount(app)

Mount the backend's Blueprint onto a Flask application.

Parameters:

Name Type Description Default
app Flask

The Flask application instance.

required

Raises:

Type Description
MountBackendError

If registering the blueprint with the Flask app fails.

Source code in pyue/backend/flask.py
def mount(self, app: Flask) -> None:
    """
    Mount the backend's Blueprint onto a Flask application.

    Args:
        app (Flask): The Flask application instance.

    Raises:
        MountBackendError: If registering the blueprint with the Flask app fails.
    """
    try:
        app.template_folder = self.template_path
        app.static_folder = self.static_path
        app.register_blueprint(self.router)
    except Exception as e:
        self.logger.error(f"Failed to mount backend: {e}")
        raise MountBackendError(traceback.format_exc())

Page

Represents WEB page (root for all components)

Source code in pyue/core/page.py
class Page:
    """Represents WEB page (root for all components)"""

    def __init__(
        self,
        title: str,
        lang: str = "en",
        favicon: str | None = None,
        content: Optional[List[Union[Component, str]]] = None,
        filename: str | None = None,
        static_path: str = "static",
        requirements: set[Resource] | None = None,
    ) -> None:
        """
        Initialize a new Page instance.

        Args:
            title (str): The title of the page, displayed in the browser tab.
            lang (str, optional): The language code for the page (e.g., 'en', 'ru').
                Defaults to "en".
            favicon (str | None, optional): Path or URL to the favicon. Defaults to None.
            content: List of component instances or strings to nest inside this page.
            filename (str | None, optional): Desired filename for the generated HTML file.
                If None, a unique filename is generated from the title. Defaults to None.
            static_path (str | None, optional): Path to the static files directory.
                Defaults to "static".
        """
        self.title = title
        self.lang = lang
        self.favicon = favicon or "favicon.ico"
        self.filename = filename
        if not self.filename:
            hash_object = hashlib.sha256(title.encode())
            hash_hex = hash_object.hexdigest()[:8]
            self.filename = f"page_{hash_hex}.html"
        self.static_path = static_path
        self.content = content or []

        TAILWIND_CSS = ResourceCss(
            "https://cdn.jsdelivr.net/npm/tailwindcss@2/dist/tailwind.min.css"
        )
        self.requirements = requirements or {TAILWIND_CSS}

    def to_string(self) -> str:
        """
        Render the page to an HTML string.

        The method generates HTML template using page data
        (title, language, requirements, and content), and returns the resulting string.

        Returns:
            str: The fully rendered HTML content of the page.

        Raises:
            PageBuildingError: If the template file cannot be read or any other
                rendering error occurs.
        """
        # Using html template
        template_path = os.path.join(__root__, "snippets", "page.html")
        try:
            with open(template_path, "r") as f:
                result = f.read()

            result = result.replace("$TITLE$", self.title)
            result = result.replace("$LANG$", self.lang)
            result = result.replace("$FAVICON$", self.static_path + "/" + self.favicon)

            contents = []
            for content in self.content:
                if isinstance(content, str):
                    contents.append(" " * 4 + content)
                    continue
                elif isinstance(content, Component):
                    contents.extend(content.to_lines(level=1))
            result = result.replace("$CONTENT$", "\n".join(contents))
            reqs = set()
            for req in self.requirements:
                if isinstance(req, ResourceCss):
                    # Include css link here
                    req_file = os.path.basename(req.resource)
                    reqs.add(
                        f'<link rel="stylesheet" href="{self.static_path+'/'+req_file}">'
                    )
                elif isinstance(req, ResourceJs):
                    # Include js link here
                    req_file = os.path.basename(req.resource)
                    reqs.add(f'<script src="{self.static_path+'/'+req_file}"></script>')
            result = result.replace("$REQUIREMENTS$", "\n".join(reqs))
            return result
        except Exception:
            raise PageBuildingError(traceback.format_exc())

    def to_file(self, file_path: str | None) -> None:
        """
        Render the page and save it to a file.

        This method writes the rendered HTML content to the specified file path.
        If no path is provided, the page's filename attribute is used.

        Args:
            file_path (str | None): The full path where the HTML file should be saved.
                If None, the page's internally generated filename is used.

        Raises:
            PageBuildingError: If writing to the file fails due to an I/O error
                or a rendering error.
        """
        try:
            path = file_path or self.filename
            with open(path, "w") as f:
                f.write(self.to_string())
        except Exception:
            raise PageBuildingError(traceback.format_exc())

        for requirement in self.requirements:
            try:
                req_path = os.path.join(
                    self.static_path, os.path.basename(requirement.resource)
                )
                if os.path.exists(req_path):
                    print(f"[@] Found cached requirement `{req_path}`, skipping ...")
                    continue
                print(f"[*] Obtaining {requirement.resource} ...")
                print(
                    f"[*] Downloaded requirement `{download_file(requirement.resource, req_path)}`"
                )
            except Exception:
                raise ResourceDownloadError(requirement.resource)

__init__(title, lang='en', favicon=None, content=None, filename=None, static_path='static', requirements=None)

Initialize a new Page instance.

Parameters:

Name Type Description Default
title str

The title of the page, displayed in the browser tab.

required
lang str

The language code for the page (e.g., 'en', 'ru'). Defaults to "en".

'en'
favicon str | None

Path or URL to the favicon. Defaults to None.

None
content Optional[List[Union[Component, str]]]

List of component instances or strings to nest inside this page.

None
filename str | None

Desired filename for the generated HTML file. If None, a unique filename is generated from the title. Defaults to None.

None
static_path str | None

Path to the static files directory. Defaults to "static".

'static'
Source code in pyue/core/page.py
def __init__(
    self,
    title: str,
    lang: str = "en",
    favicon: str | None = None,
    content: Optional[List[Union[Component, str]]] = None,
    filename: str | None = None,
    static_path: str = "static",
    requirements: set[Resource] | None = None,
) -> None:
    """
    Initialize a new Page instance.

    Args:
        title (str): The title of the page, displayed in the browser tab.
        lang (str, optional): The language code for the page (e.g., 'en', 'ru').
            Defaults to "en".
        favicon (str | None, optional): Path or URL to the favicon. Defaults to None.
        content: List of component instances or strings to nest inside this page.
        filename (str | None, optional): Desired filename for the generated HTML file.
            If None, a unique filename is generated from the title. Defaults to None.
        static_path (str | None, optional): Path to the static files directory.
            Defaults to "static".
    """
    self.title = title
    self.lang = lang
    self.favicon = favicon or "favicon.ico"
    self.filename = filename
    if not self.filename:
        hash_object = hashlib.sha256(title.encode())
        hash_hex = hash_object.hexdigest()[:8]
        self.filename = f"page_{hash_hex}.html"
    self.static_path = static_path
    self.content = content or []

    TAILWIND_CSS = ResourceCss(
        "https://cdn.jsdelivr.net/npm/tailwindcss@2/dist/tailwind.min.css"
    )
    self.requirements = requirements or {TAILWIND_CSS}

to_file(file_path)

Render the page and save it to a file.

This method writes the rendered HTML content to the specified file path. If no path is provided, the page's filename attribute is used.

Parameters:

Name Type Description Default
file_path str | None

The full path where the HTML file should be saved. If None, the page's internally generated filename is used.

required

Raises:

Type Description
PageBuildingError

If writing to the file fails due to an I/O error or a rendering error.

Source code in pyue/core/page.py
def to_file(self, file_path: str | None) -> None:
    """
    Render the page and save it to a file.

    This method writes the rendered HTML content to the specified file path.
    If no path is provided, the page's filename attribute is used.

    Args:
        file_path (str | None): The full path where the HTML file should be saved.
            If None, the page's internally generated filename is used.

    Raises:
        PageBuildingError: If writing to the file fails due to an I/O error
            or a rendering error.
    """
    try:
        path = file_path or self.filename
        with open(path, "w") as f:
            f.write(self.to_string())
    except Exception:
        raise PageBuildingError(traceback.format_exc())

    for requirement in self.requirements:
        try:
            req_path = os.path.join(
                self.static_path, os.path.basename(requirement.resource)
            )
            if os.path.exists(req_path):
                print(f"[@] Found cached requirement `{req_path}`, skipping ...")
                continue
            print(f"[*] Obtaining {requirement.resource} ...")
            print(
                f"[*] Downloaded requirement `{download_file(requirement.resource, req_path)}`"
            )
        except Exception:
            raise ResourceDownloadError(requirement.resource)

to_string()

Render the page to an HTML string.

The method generates HTML template using page data (title, language, requirements, and content), and returns the resulting string.

Returns:

Name Type Description
str str

The fully rendered HTML content of the page.

Raises:

Type Description
PageBuildingError

If the template file cannot be read or any other rendering error occurs.

Source code in pyue/core/page.py
def to_string(self) -> str:
    """
    Render the page to an HTML string.

    The method generates HTML template using page data
    (title, language, requirements, and content), and returns the resulting string.

    Returns:
        str: The fully rendered HTML content of the page.

    Raises:
        PageBuildingError: If the template file cannot be read or any other
            rendering error occurs.
    """
    # Using html template
    template_path = os.path.join(__root__, "snippets", "page.html")
    try:
        with open(template_path, "r") as f:
            result = f.read()

        result = result.replace("$TITLE$", self.title)
        result = result.replace("$LANG$", self.lang)
        result = result.replace("$FAVICON$", self.static_path + "/" + self.favicon)

        contents = []
        for content in self.content:
            if isinstance(content, str):
                contents.append(" " * 4 + content)
                continue
            elif isinstance(content, Component):
                contents.extend(content.to_lines(level=1))
        result = result.replace("$CONTENT$", "\n".join(contents))
        reqs = set()
        for req in self.requirements:
            if isinstance(req, ResourceCss):
                # Include css link here
                req_file = os.path.basename(req.resource)
                reqs.add(
                    f'<link rel="stylesheet" href="{self.static_path+'/'+req_file}">'
                )
            elif isinstance(req, ResourceJs):
                # Include js link here
                req_file = os.path.basename(req.resource)
                reqs.add(f'<script src="{self.static_path+'/'+req_file}"></script>')
        result = result.replace("$REQUIREMENTS$", "\n".join(reqs))
        return result
    except Exception:
        raise PageBuildingError(traceback.format_exc())

Component

Represents a reusable page component that can be rendered to HTML.

Components are the building blocks of Pyue pages, allowing for modular and dynamic HTML generation with Jinja2 template support.

Source code in pyue/core/component.py
class Component:
    """Represents a reusable page component that can be rendered to HTML.

    Components are the building blocks of Pyue pages, allowing for modular
    and dynamic HTML generation with Jinja2 template support.
    """

    def __init__(
        self,
        tag: str = "div",
        idx: str | None = None,
        classes: list[str] | None = None,
        extra_classes: list[str] | None = None,
        v_content: str | None = None,
        v_if: str | None = None,
        v_for: str | None = None,
        content: Optional[List[Union["Component", str]]] = None,
        no_closing: bool = False,
        **kwargs,
    ) -> None:
        """Initialize a new Component instance.

        Args:
            tag: HTML tag name for the component (e.g., 'div', 'span', 'section').
                Defaults to "div".
            idx: Optional identifier that becomes the HTML id attribute.
            classes: List of CSS classes to apply to the component.
            extra_classes: Additional CSS classes appended to existing classes.
                Useful for extending component styles without modifying base classes.
            v_content: Variable name for Jinja2 content interpolation. The content
                will be rendered as {{ variable_name }} in the template.
            v_if: Jinja2 conditional expression string. The component renders only
                if this expression evaluates to true. Example: "user.is_authenticated".
            v_for: Jinja2 loop definition string. Enables repetitive rendering.
                Example: "item in items" or "key, value in dict.items()".
            content: List of child Component instances or strings to nest inside
                this component. Children are rendered recursively.
            no_closing: Flag indicating if the tag should be self-closing without
                a closing tag. Use for void elements like <img>, <br>, <hr>.
            **kwargs: Additional HTML attributes and CSS styles:
                - CSS styles: Any keyword argument not prefixed with "attr__" is
                  treated as a CSS style. Underscores in keys are converted to
                  hyphens (e.g., font_size becomes font-size).
                - HTML attributes: Keys prefixed with "attr__" are treated as
                  raw HTML attributes (e.g., attr__data_id="123" becomes data-id="123").

        Raises:
            ComponentBuildingError: May be raised during rendering if template
                syntax is invalid or required variables are missing.
        """
        self.tag = tag
        self.idx = idx
        self.classes = classes or []
        self.extra_classes = extra_classes or []
        self.v_content = v_content
        self.v_if = v_if
        self.v_for = v_for
        self.content = content or []
        self.no_closing = no_closing
        self.additional_attrs = {}
        # Using other args as `style` data
        self.styles = {}
        for k, v in kwargs.items():
            if not v:
                continue
            if k.startswith("attr__"):
                self.additional_attrs[k.split("attr__")[-1]] = v
                continue
            self.styles[k.replace("_", "-")] = v

    def to_lines(self, level: int = 0) -> list[str]:
        """Render the component to a list of HTML strings.

        This method generates a list of the complete HTML representations of the component parts,
        including all child components and applying any Jinja2 template directives
        (v_if, v_for, v_content). The rendering process:
        1. Processes the component's HTML tag and attributes
        2. Recursively renders all child components
        3. Applies Jinja2 template syntax for dynamic content
        4. Combines everything into a final list of HTML strings

        Returns:
            List of fully rendered HTML content of the component as strings.

        Raises:
            ComponentBuildingError: If an error occurs during template strings
                rendering, such as malformed template syntax or missing variables.

        Example:
            ```python
            component = Component(tag="h1", v_content="title")
            html = component.to_lines()
            print(html)
            # ['<h1>', '    {{ title }}', '\n</h1>']
            ```
        """
        try:
            indent = " " * 4 * level
            inner_indent = " " * 4 * (level + 1)
            result = []

            attrs = []
            if self.idx:
                attrs.append(f'id="{self.idx}"')
            if self.classes or self.extra_classes:
                classes = self.classes + self.extra_classes
                attrs.append(f'class="{" ".join(classes)}"')

            if self.additional_attrs:
                additional_attrs = []
                for k, v in self.additional_attrs.items():
                    additional_attrs.append(f'{k}="{v}"')
                attrs.extend(additional_attrs)

            if self.styles:
                styles = []
                for k, v in self.styles.items():
                    styles.append(f"{k}:{v}")

                attrs.append(f'style="{";".join(styles)}"')
            attrs = " " + " ".join(attrs) if attrs else ""

            result.append(f"{indent}<{self.tag}{attrs}>")

            if self.v_content:
                result.append(f"{inner_indent}{{{{ {self.v_content} }}}}")

            for content in self.content:
                if isinstance(content, str):
                    result.append(inner_indent + content)
                    continue
                elif isinstance(content, Component):
                    result.extend(content.to_lines(level=level + 1))

            # For handling tags like <hr>
            if not self.no_closing:
                result.append(f"\n{indent}</{self.tag}>")

            if self.v_if:
                result = (
                    [f"{indent}{{% if {self.v_if} %}}"]
                    + result
                    + [f"{indent}{{% endif %}}"]
                )
            if self.v_for:
                result = (
                    [f"{indent}{{% for {self.v_for} %}}"]
                    + result
                    + [f"{indent}{{% endfor %}}"]
                )

            return result
        except Exception:
            raise ComponentBuildingError(traceback.format_exc())

    def to_string(self, level: int = 0) -> str:
        """Return the component as a single string."""
        return "\n".join(self.to_lines(level))

__init__(tag='div', idx=None, classes=None, extra_classes=None, v_content=None, v_if=None, v_for=None, content=None, no_closing=False, **kwargs)

Initialize a new Component instance.

Parameters:

Name Type Description Default
tag str

HTML tag name for the component (e.g., 'div', 'span', 'section'). Defaults to "div".

'div'
idx str | None

Optional identifier that becomes the HTML id attribute.

None
classes list[str] | None

List of CSS classes to apply to the component.

None
extra_classes list[str] | None

Additional CSS classes appended to existing classes. Useful for extending component styles without modifying base classes.

None
v_content str | None

Variable name for Jinja2 content interpolation. The content will be rendered as {{ variable_name }} in the template.

None
v_if str | None

Jinja2 conditional expression string. The component renders only if this expression evaluates to true. Example: "user.is_authenticated".

None
v_for str | None

Jinja2 loop definition string. Enables repetitive rendering. Example: "item in items" or "key, value in dict.items()".

None
content Optional[List[Union[Component, str]]]

List of child Component instances or strings to nest inside this component. Children are rendered recursively.

None
no_closing bool

Flag indicating if the tag should be self-closing without a closing tag. Use for void elements like ,
,


.

False
**kwargs

Additional HTML attributes and CSS styles: - CSS styles: Any keyword argument not prefixed with "attr__" is treated as a CSS style. Underscores in keys are converted to hyphens (e.g., font_size becomes font-size). - HTML attributes: Keys prefixed with "attr__" are treated as raw HTML attributes (e.g., attr__data_id="123" becomes data-id="123").

{}

Raises:

Type Description
ComponentBuildingError

May be raised during rendering if template syntax is invalid or required variables are missing.

Source code in pyue/core/component.py
def __init__(
    self,
    tag: str = "div",
    idx: str | None = None,
    classes: list[str] | None = None,
    extra_classes: list[str] | None = None,
    v_content: str | None = None,
    v_if: str | None = None,
    v_for: str | None = None,
    content: Optional[List[Union["Component", str]]] = None,
    no_closing: bool = False,
    **kwargs,
) -> None:
    """Initialize a new Component instance.

    Args:
        tag: HTML tag name for the component (e.g., 'div', 'span', 'section').
            Defaults to "div".
        idx: Optional identifier that becomes the HTML id attribute.
        classes: List of CSS classes to apply to the component.
        extra_classes: Additional CSS classes appended to existing classes.
            Useful for extending component styles without modifying base classes.
        v_content: Variable name for Jinja2 content interpolation. The content
            will be rendered as {{ variable_name }} in the template.
        v_if: Jinja2 conditional expression string. The component renders only
            if this expression evaluates to true. Example: "user.is_authenticated".
        v_for: Jinja2 loop definition string. Enables repetitive rendering.
            Example: "item in items" or "key, value in dict.items()".
        content: List of child Component instances or strings to nest inside
            this component. Children are rendered recursively.
        no_closing: Flag indicating if the tag should be self-closing without
            a closing tag. Use for void elements like <img>, <br>, <hr>.
        **kwargs: Additional HTML attributes and CSS styles:
            - CSS styles: Any keyword argument not prefixed with "attr__" is
              treated as a CSS style. Underscores in keys are converted to
              hyphens (e.g., font_size becomes font-size).
            - HTML attributes: Keys prefixed with "attr__" are treated as
              raw HTML attributes (e.g., attr__data_id="123" becomes data-id="123").

    Raises:
        ComponentBuildingError: May be raised during rendering if template
            syntax is invalid or required variables are missing.
    """
    self.tag = tag
    self.idx = idx
    self.classes = classes or []
    self.extra_classes = extra_classes or []
    self.v_content = v_content
    self.v_if = v_if
    self.v_for = v_for
    self.content = content or []
    self.no_closing = no_closing
    self.additional_attrs = {}
    # Using other args as `style` data
    self.styles = {}
    for k, v in kwargs.items():
        if not v:
            continue
        if k.startswith("attr__"):
            self.additional_attrs[k.split("attr__")[-1]] = v
            continue
        self.styles[k.replace("_", "-")] = v

to_lines(level=0)

Render the component to a list of HTML strings.

    This method generates a list of the complete HTML representations of the component parts,
    including all child components and applying any Jinja2 template directives
    (v_if, v_for, v_content). The rendering process:
    1. Processes the component's HTML tag and attributes
    2. Recursively renders all child components
    3. Applies Jinja2 template syntax for dynamic content
    4. Combines everything into a final list of HTML strings

    Returns:
        List of fully rendered HTML content of the component as strings.

    Raises:
        ComponentBuildingError: If an error occurs during template strings
            rendering, such as malformed template syntax or missing variables.

    Example:
        ```python
        component = Component(tag="h1", v_content="title")
        html = component.to_lines()
        print(html)
        # ['<h1>', '    {{ title }}', '

'] ```

Source code in pyue/core/component.py
def to_lines(self, level: int = 0) -> list[str]:
    """Render the component to a list of HTML strings.

    This method generates a list of the complete HTML representations of the component parts,
    including all child components and applying any Jinja2 template directives
    (v_if, v_for, v_content). The rendering process:
    1. Processes the component's HTML tag and attributes
    2. Recursively renders all child components
    3. Applies Jinja2 template syntax for dynamic content
    4. Combines everything into a final list of HTML strings

    Returns:
        List of fully rendered HTML content of the component as strings.

    Raises:
        ComponentBuildingError: If an error occurs during template strings
            rendering, such as malformed template syntax or missing variables.

    Example:
        ```python
        component = Component(tag="h1", v_content="title")
        html = component.to_lines()
        print(html)
        # ['<h1>', '    {{ title }}', '\n</h1>']
        ```
    """
    try:
        indent = " " * 4 * level
        inner_indent = " " * 4 * (level + 1)
        result = []

        attrs = []
        if self.idx:
            attrs.append(f'id="{self.idx}"')
        if self.classes or self.extra_classes:
            classes = self.classes + self.extra_classes
            attrs.append(f'class="{" ".join(classes)}"')

        if self.additional_attrs:
            additional_attrs = []
            for k, v in self.additional_attrs.items():
                additional_attrs.append(f'{k}="{v}"')
            attrs.extend(additional_attrs)

        if self.styles:
            styles = []
            for k, v in self.styles.items():
                styles.append(f"{k}:{v}")

            attrs.append(f'style="{";".join(styles)}"')
        attrs = " " + " ".join(attrs) if attrs else ""

        result.append(f"{indent}<{self.tag}{attrs}>")

        if self.v_content:
            result.append(f"{inner_indent}{{{{ {self.v_content} }}}}")

        for content in self.content:
            if isinstance(content, str):
                result.append(inner_indent + content)
                continue
            elif isinstance(content, Component):
                result.extend(content.to_lines(level=level + 1))

        # For handling tags like <hr>
        if not self.no_closing:
            result.append(f"\n{indent}</{self.tag}>")

        if self.v_if:
            result = (
                [f"{indent}{{% if {self.v_if} %}}"]
                + result
                + [f"{indent}{{% endif %}}"]
            )
        if self.v_for:
            result = (
                [f"{indent}{{% for {self.v_for} %}}"]
                + result
                + [f"{indent}{{% endfor %}}"]
            )

        return result
    except Exception:
        raise ComponentBuildingError(traceback.format_exc())

to_string(level=0)

Return the component as a single string.

Source code in pyue/core/component.py
def to_string(self, level: int = 0) -> str:
    """Return the component as a single string."""
    return "\n".join(self.to_lines(level))

Stack

Bases: Component

A container that stacks its children vertically or horizontally with consistent spacing. Uses flexbox with flex-col (vertical) or flex-row (horizontal) and configurable gap.

Source code in pyue/components/layouts/stack.py
class Stack(Component):
    """
    A container that stacks its children vertically or horizontally with consistent spacing.
    Uses flexbox with flex-col (vertical) or flex-row (horizontal) and configurable gap.
    """

    def __init__(
        self,
        direction: str = "vertical",
        spacing: Union[int, str, None] = None,
        align: Optional[str] = None,
        justify: Optional[str] = None,
        **kwargs,
    ):
        """
        Args:
            direction: "vertical" (column) or "horizontal" (row).
            spacing: gap between children (int for Tailwind gap-{n} or custom class).
            align: Tailwind class for align-items (e.g., "items-center").
            justify: Tailwind class for justify-content (e.g., "justify-between").

        Example:
            ```python

            # Vertical stack with spacing 4
            Stack(direction="vertical", spacing=4,
                content=[
                    H1("Title"),
                    P("Some description"),
                    Button("Click me")
                ]
            )

            # Horizontal stack with centered alignment
            Stack(direction="horizontal", spacing=2, align="items-center",
                content=[
                    Icon("home"),
                    Span("Home"),
                    Span("/"),
                    Span("Products")
                ]
            )
            ```
        """
        classes = ["flex"]
        if direction == "vertical":
            classes.append("flex-col")
        else:
            classes.append("flex-row")
        if spacing is not None:
            if isinstance(spacing, int):
                classes.append(f"gap-{spacing}")
            else:
                classes.append(spacing)
        if align:
            classes.append(align)
        if justify:
            classes.append(justify)

        super().__init__(tag="div", classes=classes, **kwargs)

__init__(direction='vertical', spacing=None, align=None, justify=None, **kwargs)

Parameters:

Name Type Description Default
direction str

"vertical" (column) or "horizontal" (row).

'vertical'
spacing Union[int, str, None]

gap between children (int for Tailwind gap-{n} or custom class).

None
align Optional[str]

Tailwind class for align-items (e.g., "items-center").

None
justify Optional[str]

Tailwind class for justify-content (e.g., "justify-between").

None
Example
# Vertical stack with spacing 4
Stack(direction="vertical", spacing=4,
    content=[
        H1("Title"),
        P("Some description"),
        Button("Click me")
    ]
)

# Horizontal stack with centered alignment
Stack(direction="horizontal", spacing=2, align="items-center",
    content=[
        Icon("home"),
        Span("Home"),
        Span("/"),
        Span("Products")
    ]
)
Source code in pyue/components/layouts/stack.py
def __init__(
    self,
    direction: str = "vertical",
    spacing: Union[int, str, None] = None,
    align: Optional[str] = None,
    justify: Optional[str] = None,
    **kwargs,
):
    """
    Args:
        direction: "vertical" (column) or "horizontal" (row).
        spacing: gap between children (int for Tailwind gap-{n} or custom class).
        align: Tailwind class for align-items (e.g., "items-center").
        justify: Tailwind class for justify-content (e.g., "justify-between").

    Example:
        ```python

        # Vertical stack with spacing 4
        Stack(direction="vertical", spacing=4,
            content=[
                H1("Title"),
                P("Some description"),
                Button("Click me")
            ]
        )

        # Horizontal stack with centered alignment
        Stack(direction="horizontal", spacing=2, align="items-center",
            content=[
                Icon("home"),
                Span("Home"),
                Span("/"),
                Span("Products")
            ]
        )
        ```
    """
    classes = ["flex"]
    if direction == "vertical":
        classes.append("flex-col")
    else:
        classes.append("flex-row")
    if spacing is not None:
        if isinstance(spacing, int):
            classes.append(f"gap-{spacing}")
        else:
            classes.append(spacing)
    if align:
        classes.append(align)
    if justify:
        classes.append(justify)

    super().__init__(tag="div", classes=classes, **kwargs)