$42 GRAYBYTE WORDPRESS FILE MANAGER $80

SERVER : vnpttt-amd7f72-h1.vietnix.vn #1 SMP Fri May 24 12:42:50 UTC 2024
SERVER IP : 103.200.23.149 | ADMIN IP 216.73.216.22
OPTIONS : CRL = ON | WGT = ON | SDO = OFF | PKEX = OFF
DEACTIVATED : NONE

/opt/cloudlinux/venv/lib/python3.11/site-packages/clwpos/user/

HOME
Current File : /opt/cloudlinux/venv/lib/python3.11/site-packages/clwpos/user//progress_check.py
# -*- coding: utf-8 -*-

# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT

import functools
import json
from pathlib import Path
from typing import Dict

from clwpos.cl_wpos_exceptions import WposError
from clwpos.constants import USER_WPOS_DIR
from clwpos.logsetup import setup_logging
from clwpos.optimization_features import ALL_OPTIMIZATION_FEATURES
from clwpos.utils import home_dir, is_run_under_user
from secureio import write_file_via_tempfile

logger = setup_logging(__name__)

PROGRESS_STATUS_FILE_NAME = '.progress-status'


def get_progress_file_path() -> Path:
    return Path(home_dir(), USER_WPOS_DIR, PROGRESS_STATUS_FILE_NAME)


class CommandProgress:
    """
    Class to represent user's AccelerateWP utility commands progress.
    """
    total_stages: int

    def __new__(cls, command):
        command_subclass_map = {
            subclass.command: subclass for subclass in cls.__subclasses__()
        }
        if command not in command_subclass_map:
            raise WposError(f'Internal Error: command "{command}" is not allowed, '
                            f'available commands: {list(command_subclass_map.keys())}')
        subclass = command_subclass_map[command]
        instance = super(CommandProgress, subclass).__new__(subclass)
        return instance

    def __init__(self, *args):
        if not is_run_under_user():
            raise WposError('Internal Error: trying to use CommandProgress class as root')
        self.progress_file = get_progress_file_path()
        self.in_progress = False
        self.completed_stages = 0

    def as_dict(self) -> Dict[str, int]:
        """
        Return number of total and completed stages as dict.
        """
        return {
            'total_stages': self.total_stages,
            'completed_stages': self.completed_stages,
        }

    def start(self) -> None:
        """
        Start tracking the progress of the command.
        """
        self.in_progress = True
        self.completed_stages = 0
        self.progress_file.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
        self._update_progress_file()

    def update(self) -> None:
        """
        Update progress status by incrementing
        the number of completed stages by one.
        """
        if not self.in_progress:
            return
        self.completed_stages += 1
        if self.completed_stages > self.total_stages:
            raise WposError(
                'Internal Error: the number of completed stages '
                'is greater than the total number of stages'
            )
        self._update_progress_file()

    def complete(self) -> None:
        """
        Complete progress, delete file with progress status.
        """
        if not self.in_progress:
            return
        self.in_progress = False
        self.completed_stages = self.total_stages
        if self.progress_file.exists():
            self.progress_file.unlink()


    def _update_progress_file(self) -> None:
        # TODO: improve me
        # clcaptain cannot write via tmp file, disable_quota() also does not work as this code is run only under user
        # (get/enable/disable) not that critical now, because feature installing will not work anyway for overquota user
        write_file_via_tempfile(
            json.dumps(self.as_dict()), self.progress_file, 0o644)

    @staticmethod
    def get_status() -> Dict[str, int]:
        """
        Return current progress status of the command execution,
        getting it from from special file.
        """
        progress_file = get_progress_file_path()
        defaults = {'total_stages': 1, 'completed_stages': 0}

        if not progress_file.exists():
            return defaults

        try:
            with open(progress_file, 'r') as f:
                status_from_file = json.loads(f.read())
            return {
                'total_stages': int(status_from_file['total_stages']),
                'completed_stages': int(status_from_file['completed_stages']),
            }
        except Exception as e:
            logger.error('Can\'t parse progress status json: %s', e)
            return defaults


class EnableCommandProgress(CommandProgress):
    """
    Class to represent user's AccelerateWP utility "enable" command progress.
    """
    command: str = 'enable'
    total_stages: int = 9


class DisableCommandProgress(CommandProgress):
    """
    Class to represent user's WPOS utility "disable" command progress.
    """
    command: str = 'disable'
    total_stages: int = 5


class GetCommandProgress(CommandProgress):
    """
    Class to represent user's WPOS utility "get" command progress.
    """
    command: str = 'get'
    total_stages: int = 10

    def recalculate_number_of_total_stages(self, user_info: dict):
        """
        Recalculate and change total number of progress stages depending on
        the number of user's docroots and wordpresses.
        so we could update progress after checking every docroot and wordpress.
        Example of user_info structure:
            {
                'docroot1':
                    {'wps': [{'path': '', 'version': '5.9'},
                             {'path': 'wp2', 'version': '5.9'}], ... },
                'docroot2':
                    {'wps': [{'path': '', 'version': '5.9'}], ... },
            }
        """
        number_of_initial_stages = 3
        number_of_docroots = len(user_info)
        number_of_wordpress = sum(
            len(doc_root_info['wps']) for doc_root_info in user_info.values()
        )
        total_checks_per_module = number_of_docroots + number_of_wordpress
        self.total_stages = number_of_initial_stages \
            + total_checks_per_module * len(ALL_OPTIMIZATION_FEATURES)


def track_command_progress(func):
    """
    Decorator for the WPOS utility commands
    we want to track the progress for.
    """
    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        self.command_progress = CommandProgress(func.__name__.strip('_'))
        self.command_progress.start()
        try:
            return func(self, *args, **kwargs)
        finally:
            self.command_progress.complete()
    return wrapper


def update_command_progress(func):
    """
    Decorator for the WPOS utility methods after which
    the counter of completed operations must be updated.
    """
    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        result = func(self, *args, **kwargs)
        if getattr(self, 'command_progress') is not None:
            self.command_progress.update()
        return result
    return wrapper

Current_dir [ NOT WRITEABLE ] Document_root [ WRITEABLE ]


[ Back ]
NAME
SIZE
LAST TOUCH
USER
CAN-I?
FUNCTIONS
..
--
16 Dec 2025 9.31 PM
root / root
0755
__pycache__
--
16 Dec 2025 9.38 PM
root / root
0755
website_check
--
16 Dec 2025 9.31 PM
root / root
0755
__init__.py
0 KB
29 Sep 2025 8.34 PM
root / root
0644
cache.py
2.574 KB
29 Sep 2025 8.34 PM
root / root
0644
config.py
13.313 KB
29 Sep 2025 8.34 PM
root / root
0644
progress_check.py
6.608 KB
29 Sep 2025 8.34 PM
root / root
0644
redis_lib.py
4.37 KB
29 Sep 2025 8.34 PM
root / root
0644
wpos_user.py
49.783 KB
29 Sep 2025 8.34 PM
root / root
0644

GRAYBYTE WORDPRESS FILE MANAGER @ 2026 CONTACT ME
Static GIF