Metadata-Version: 2.4
Name: simpleworkernet
Version: 0.0.3b29
Summary: Python клиент для API WorkerNet
Author-email: BusyBeaver <busybeaver.bb@gmail.com>
License: MIT License
        
        Copyright (c) 2026 Андрей Литвинов
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.25.0
Dynamic: license-file

# SimpleWorkerNet

Высокопроизводительный Python клиент для REST API системы WorkerNet с интеллектуальной системой трансформации и типизации сложных JSON структур

---

## 📋 Содержание

- [🌟 Особенности](#-особенности)
- [📦 Установка](#-установка)
- [🚀 Быстрый старт](#-быстрый-старт)
- [🔧 Конфигурация](#-конфигурация)
- [📚 Основные компоненты](#-основные-компоненты)
  - [WorkerNetClient](#workernetclient)
  - [BaseModel](#basemodel)
  - [SmartData Framework](#smartdata-framework)
  - [Метаданные и CollapsedField](#метаданные-и-CollapsedField)
- [📊 Логирование](#-логирование)
  - [Настройка логов](#настройка-логов)
  - [Сессионные логи](#сессионные-логи)
  - [Управление логами](#управление-логами)
- [💾 Кэширование](#-кэширование)
  - [Настройка кэша](#настройка-кэша)
  - [Управление кэшем](#управление-кэшем)
- [🎨 Примеры использования](#-примеры-использования)
  - [Базовые операции с API](#базовые-операции-с-api)
  - [Фильтрация данных](#фильтрация-данных)
  - [Продвинутый поиск](#продвинутый-поиск)
  - [Создание пользовательских моделей](#создание-пользовательских-моделей)
  - [Агрегация и статистика](#агрегация-и-статистика)
  - [Сериализация](#сериализация)
  - [Примитивные типы](#примитивные-типы)
  - [Пакетная обработка](#пакетная-обработка)
- [🧹 Очистка и деинсталляция](#-очистка-и-деинсталляция)
  - [Очистка данных](#очистка-данных)
  - [Консольная команда](#консольная-команда)
  - [Полное удаление пакета](#полное-удаление-пакета)
- [✒️ Автор](#️-автор)

---

## 🌟 Особенности <a name="особенности"></a>

### 🚀 SmartData Framework

SmartData — это специализированный SDK-компонент для обработки API-ответов сервера WorkerNet. Он превращает сырые, динамически типизированные JSON-данные сервера в строго типизированные объекты Python с поддержкой глубокого поиска и автоматической трансформации коллекций.

- **Автоматическое приведение типов** согласно аннотациям Python
- **Сохранение метаданных** о пути извлечения данных (MetaData класс)
- **Глубокий поиск** по любым уровням вложенности
- **Fluent-интерфейс** для фильтрации, сортировки и агрегации
- **Поддержка экспорта/импорта** (JSON, Pickle, Gzip)

### 🔧 BaseModel Engine

BaseModel - мощная система рекурсивного кастинга типов:

- **Автоматическое преобразование** данных в типизированные объекты
- **Поддержка Union, Optional, List**, вложенных моделей
- **Постобработка и схлопывание** избыточных структур
- **Сериализация/десериализация** с сохранением типов
- **Декоратор @smart_model** для удобного создания моделей

### 🎯 Умный клиент API

- **Автоматическое управление сессиями** (поддержка `with` контекста)
- **Интеллектуальный выбор метода** (GET/POST) при превышении лимита URL
- **Автоматические повторы** при таймаутах
- **Кэширование полей** для оптимизации производительности
- **Полное логирование** всех операций

### 📊 Продвинутое логирование

- **Сессионные логи** - каждый запуск создает отдельный файл с временной меткой
- **Автоматическая ротация** - старые логи удаляются
- **Детальная информация** - ID сессии, время создания, размер файла
- **Кросс-платформенность** - корректная работа на Windows, macOS и Linux
- **Управление сессиями** - создание новых сессий, просмотр истории

### 🗄️ Кэширование

- **Двухуровневое кэширование** (поля моделей и числовые ключи)
- **Автоматическая очистка** при достижении лимита
- **Сохранение на диск** и загрузка при инициализации
- **Возможность полного отключения** кэширования
- **Детальная статистика** использования

---

## 📦 Установка

### Базовая установка

```bash
pip install simpleworkernet

```

## 🚀 Быстрый старт

### Минимальный пример
```python

from simpleworkernet import WorkerNetClient

# Создаем клиент
client = WorkerNetClient(
    host="my.workernet.ru",
    apikey="your-secret-api-key"
)

# Получаем данные
cables = client.Fiber.catalog_cables_get()
print(f"Найдено кабелей в каталоге: {len(cables)}")
```

### Использование с контекстным менеджером
```python

from simpleworkernet import WorkerNetClient

with WorkerNetClient("my.workernet.ru", "your-api-key") as client:
    customers = client.Module.get_user_list()
    addresses = client.Address.get_city()
    
    print(f"Абонентов: {len(customers)}")
    print(f"Городов: {len(addresses)}")
```

### Умная фильтрация с SmartData
```python

from simpleworkernet import WorkerNetClient, Where, Operator

client = WorkerNetClient("my.workernet.ru", "your-api-key")

# Получаем данные
customers = client.Module.get_user_list()

# Создаем условия поиска
conditions = [
    Where('state_id', 2),                    # активные абоненты
    Where('balance', 1000, Operator.GT),     # с балансом > 1000
    Where('full_name', 'Иван', Operator.LIKE) # имя содержит 'Иван'
]

# Фильтруем
filtered = customers.filter(*conditions, join='AND')
print(f"Найдено: {filtered.count()}")

# Или через where для простых условий
active_customers = customers.where('state_id', 2)
```

## 🔧 Конфигурация

### Базовая настройка
```python

from simpleworkernet import ConfigManager

# Просмотр текущей конфигурации
ConfigManager.show_config()

# Изменение настроек через свойства
ConfigManager.log_level = "DEBUG"
ConfigManager.log_to_file = True
ConfigManager.console_output = True
ConfigManager.cache_enabled = True
ConfigManager.cache_max_size = 100000

# Сохранение в файл
ConfigManager.save()
```

### Изменение через update()
```python

from simpleworkernet import ConfigManager

ConfigManager.update(
    log_level="DEBUG",
    log_to_file=True,
    console_output=True,
    cache_enabled=True,
    cache_max_size=100000
)

ConfigManager.save()
```

### Полная конфигурация
```python

from simpleworkernet import ConfigManager, WorkerNetConfig

# Создание своей конфигурации
custom_config = WorkerNetConfig(
    log_level="INFO",
    log_file="/custom/path/workernet.log",
    cache_enabled=True,
    cache_max_size=50000,
    default_timeout=60,
    max_retries=5,
    smartdata_max_depth=200,
    smartdata_debug=True
)

# Применение
ConfigManager.update(**custom_config.to_dict())
ConfigManager.save()
```

### Интерактивная настройка
```python

from simpleworkernet import ConfigManager

# Запуск интерактивного режима
ConfigManager.interactive_configure()
```

### Сброс на значения по умолчанию
```python

from simpleworkernet import ConfigManager

ConfigManager.reset()
ConfigManager.save()
```

## 📚 Основные компоненты

### WorkerNetClient

WorkerNetClient - основной класс для взаимодействия с API WorkerNet.
Параметры инициализации:
Параметр	Тип	Описание	По умолчанию
host	str	Хост API (обязательный)	-
apikey	str	Ключ API (обязательный)	-
protocol	str	Протокол ('http' или 'https')	'https'
port	int	Порт	443
apiscr	str	Имя скрипта API	'api.php'
session	requests.Session	Существующая сессия	None
timeout	int	Таймаут запроса (сек)	из конфига
max_retries	int	Количество повторов	из конфига
Доступные категории:

    Address - работа с адресами

    Customer - работа с абонентами

    Device - оборудование

    Employee - сотрудники

    Fiber - кабельные линии

    Map - карты покрытия

    Module - внешние запросы

    Additional_data - дополнительные данные

    Advertising - рекламные кампании

    Attach - прикрепляемые файлы

    Billing - биллинги

    Cable_route - кабельные трассы

    Call - звонки

    Commutation - коммутация

    Cross - кроссы/ODF

    Cwdm - CWDM

    Gps - GPS трекеры

    Inventory - склад/ТМЦ

    Key - ключи

    Node - объекты инфраструктуры

### BaseModel и smart_model

Базовый класс для всех моделей с автоматическим кастингом типов и поддержкой метаданных.
```python
from simpleworkernet import smart_model, BaseModel, CollapsedField, vStr, GeoPoint, vPhoneNumber
from simpleworkernet.smartdata.metadata import SegmentType
from typing import List, Optional

@smart_model
class Contact(BaseModel):
    """Контактная информация"""
    email: Optional[str]
    phone: Optional[vPhoneNumber]
    telegram: Optional[str]

@smart_model
class Address(BaseModel):
    """Модель адреса"""
    id: int
    city: vStr
    street: vStr
    house: str
    apartment: Optional[int]
    coordinates: GeoPoint
    contacts: Optional[Contact]

@smart_model
class Traffic(BaseModel):
    """Трафик абонента"""
    up: int
    down: int
    # Поле month отсутствует в модели, но присутствует в данных API
    # CollapsedField позволяет получить к нему доступ из метаданных
    period = CollapsedField(type_filter=SegmentType.FLD)

# Автоматическое создание из словаря
addr = Address(
    id=1,
    city="Москва",
    street="Ленина",
    house="10",
    apartment=42,
    coordinates=[55.75, 37.62],
    contacts={"phone": "+7-999-123-45-67"}
)

print(addr.city)  # "Москва"
print(addr.coordinates)  # "55.75,37.62"
print(addr.contacts.phone.normalized)  # "79991234567"
```

### CollapsedField и метаданные

Каждый объект хранит метаданные о своем положении в исходной структуре. CollapsedField позволяет удобно получать доступ к схлопнутым данным.
```python

from simpleworkernet import SmartData, CollapsedField
from simpleworkernet.smartdata.metadata import SegmentType

# Получение данных от API
customers = client.Customer.get_data(customer_id='1,2')

for customer in customers:
    # Доступ к метаданным
    if customer.meta:
        print(f"Путь к объекту: {customer.meta.get_path_string()}")
        print(f"Все схлопнутые ключи: {customer.get_collapsed_keys()}")
        print(f"Только FLD ключи: {customer.get_collapsed_keys(type_filter=SegmentType.FLD)}")
    
    # Доступ к схлопнутым полям через CollapsedField
    if customer.tariff:
        print(f"container_name: {customer.tariff.container_name}")  # 'current'
```

### SmartData Framework

Контейнер для интеллектуальной обработки JSON-структур с fluent-интерфейсом.
```python

from simpleworkernet import SmartData, Where, Operator

# Из ответа API (автоматически)
customers = client.Module.get_user_list()  # уже SmartData

# Цепочка операций
result = (customers
    .where('balance', 0, Operator.GT)
    .where('state_id', 2)
    .sort(key=lambda x: x.balance, reverse=True)
    .limit(10)
    .map(lambda x: x.full_name))

# Группировка и агрегация
by_state = customers.group_by(lambda x: x.state_id)
for state, group in by_state.items():
    avg_balance = group.avg(lambda x: x.balance)
    print(f"Статус {state}: {group.count()} абонентов, средний баланс {avg_balance}")
```

## 📊 Логирование

### Настройка логов
```python

from simpleworkernet import log, ConfigManager

# Базовая настройка через конфиг
ConfigManager.update(
    log_level="DEBUG",
    log_to_file=True,
    console_output=True
)

# Прямая настройка логгера
log.configure(
    level="DEBUG",
    log_to_file=True,
    log_file="/custom/path/workernet.log",
    console_output=True,
    max_log_files=20  # хранить 20 последних сессий
)
```

### Сессионные логи

Логгер автоматически создает отдельные файлы для каждого запуска:
```python

from simpleworkernet import log

# Информация о текущей сессии
current_log = log.get_session_log_path()
session_id = log.get_session_id()
print(f"Сессия: {session_id}, лог: {current_log}")

# Список всех сессий
for log_file in log.list_session_logs()[:5]:
    info = log.get_session_info(log_file)
    print(f"{info['session_id']} - {info['size_kb']:.1f} KB")
```

### Управление логами
```python

from simpleworkernet import log
from datetime import datetime

# Список всех сессий (от новых к старым)
all_logs = log.list_session_logs(sort_by='newest')
print(f"Всего сессий: {len(all_logs)}")

# Детальная информация о каждой сессии
for log_file in all_logs[:5]:  # последние 5
    info = log.get_session_info(log_file)
    if 'created' in info:
        created = info['created'].strftime("%Y-%m-%d %H:%M:%S")
        size = info['size_kb']
        print(f"{info['session_id']} - {created} - {size:.1f} KB")

# Начать новую сессию вручную
new_session = log.new_session("my_custom_session")
print(f"Новая сессия: {new_session}")
```

### Пример структуры файлов логов
```text

~/.local/share/simpleworkernet/logs/
├── workernet_20250220_091233.log   # утренняя сессия (50 KB)
├── workernet_20250220_143022.log   # дневная сессия (120 KB)
└── workernet_20250220_163502.log   # текущая сессия (45 KB)
```

Уровни логирования

    DEBUG - детальная отладочная информация

    INFO - основные события (инициализация, запросы)

    WARNING - предупреждения

    ERROR - ошибки

    CRITICAL - критические ошибки

## 💾 Кэширование

### Настройка кэша
```python

from simpleworkernet import SmartData, ConfigManager

# Настройка через конфиг
ConfigManager.update(
    cache_enabled=True,
    cache_max_size=100000,
    cache_auto_save=True,
    cache_dir="/custom/cache/path"
)

# Прямое управление
SmartData.set_cache_max_size(50000)
```

### Управление кэшем
```python

from simpleworkernet import SmartData

# Сохранение кэша
SmartData.save_cache()
SmartData.save_cache(force=True)  # принудительно

# Загрузка кэша
SmartData.load_cache()

# Очистка
SmartData.clear_cache()

# Статистика
stats = SmartData.get_cache_stats()
print(f"Всего обращений: {stats['total']}")
print(f"Попаданий: {stats['hits']} ({stats['hit_rate']:.1f}%)")
print(f"Размер кэша: {stats['field_cache_size']} полей")
```

### Предзагрузка кэша из моделей
```python

from simpleworkernet import SmartData
from simpleworkernet.models.categories.customer import Customer

# Предварительная загрузка полей моделей
SmartData.preload_from_models(
    Customer.Get_data,
    Customer.Get_data.Address,
    Customer.Get_data.Tariff,
    recursive=True
)
```

## 🎨 Примеры использования

### Базовые операции с API
```python

from simpleworkernet import WorkerNetClient, log

# Настройка логирования
log.configure(level="DEBUG")

with WorkerNetClient("my.workernet.ru", "your-api-key") as client:
    
    # Получение списка абонентов
    customers = client.Module.get_user_list()
    log.info(f"Получено абонентов: {len(customers)}")
    
    # Получение конкретного абонента по ID
    customer = client.Customer.get_data(customer_id=123)
    
    # Получение адресов
    addresses = client.Address.get(city_id=1)
    
    # Получение каталога кабелей
    cables = client.Fiber.catalog_cables_get()
    
    # Работа с модулями
    users = client.Module.get_house_list()
```

### Фильтрация данных
```python

from simpleworkernet import SmartData, Where, Operator

# Создаем SmartData из ответа API
customers = client.Customer.get_data()

# Простая фильтрация
active = customers.where('state_id', 2)
positive_balance = customers.where('balance', 0, Operator.GT)
moscow = customers.where('city', 'Москва', Operator.LIKE)

# Составные условия
filtered = customers.filter(
    Where('state_id', 2),
    Where('balance', 1000, Operator.GT),
    Where('city', 'Москва', Operator.LIKE),
    join='AND'
)

# Диапазон
middle_age = customers.where('age', [25, 35], Operator.BETWEEN)

# Проверка вхождения
cities = customers.where('city', ['Москва', 'СПб'], Operator.IN)
```

### Продвинутый поиск
```python

# Глубокий поиск по всей структуре (включая вложенные объекты)
complex_data = [
    {
        "id": 1,
        "name": "Иван",
        "contacts": {
            "email": "ivan@example.com",
            "phone": "+7-999-123-45-67"
        },
        "orders": [
            {"id": 101, "amount": 1500},
            {"id": 102, "amount": 2300}
        ]
    },
    {
        "id": 2,
        "name": "Петр",
        "contacts": {
            "email": "petr@example.com",
            "phone": "+7-999-765-43-21"
        },
        "orders": [
            {"id": 103, "amount": 800}
        ]
    }
]

sd = SmartData(complex_data)

# Поиск по email (найдет в любом месте структуры)
results = sd.find_all('email', 'ivan@example.com')
print(f"Найдено объектов: {len(results)}")

# Проверка существования
if sd.exists('phone', '+7-999-123-45-67'):
    print("Телефон найден!")

# Поиск по частичному совпадению
results = sd.find_all('name', 'Иван', is_partial=True)

# Сложный поиск с несколькими критериями
found = sd.find_all(
    key=['name', 'amount'],
    value=['Иван', 1500],
    is_partial=False
)
```

### Создание пользовательских моделей
```python

from simpleworkernet import smart_model, BaseModel, vStr, vMoney
from typing import List, Optional

@smart_model
class Service(BaseModel):
    id: int
    name: vStr
    price: vMoney
    active: bool

@smart_model
class User(BaseModel):
    id: int
    login: str
    full_name: vStr
    balance: vMoney
    services: List[Service]

# Использование
user = User(**api_response)
print(f"Пользователь: {user.full_name}")
print(f"Баланс: {user.balance}")
for service in user.services:
    print(f"  - {service.name}: {service.price}")
```

### Агрегация и статистика
```python

from simpleworkernet import SmartData

data = [
    {"name": "Иван", "age": 30, "salary": 50000, "department": "IT"},
    {"name": "Петр", "age": 25, "salary": 45000, "department": "IT"},
    {"name": "Сидор", "age": 35, "salary": 60000, "department": "Sales"},
    {"name": "Анна", "age": 28, "salary": 55000, "department": "Sales"},
    {"name": "Мария", "age": 32, "salary": 52000, "department": "HR"},
]

sd = SmartData(data)

# Статистика
total = sd.count()  # 5
avg_age = sd.avg(lambda x: x['age'])  # 30.0
max_salary = sd.max(lambda x: x['salary'])  # 60000
min_salary = sd.min(lambda x: x['salary'])  # 45000
total_salary = sd.sum(lambda x: x['salary'])  # 262000

# Группировка по отделам
by_department = sd.group_by(lambda x: x['department'])
for dept, employees in by_department.items():
    print(f"{dept}: {employees.count()} сотрудников")
    print(f"  Средняя зарплата: {employees.avg(lambda x: x['salary']):.0f}")

# Уникальные значения
unique_depts = sd.unique(lambda x: x['department'])
print(f"Отделы: {list(unique_depts)}")

# Трансформация
names = sd.map(lambda x: x['name'].upper())
print(f"Имена: {names}")

# Сортировка
by_age = sd.sort(key=lambda x: x['age'])
by_salary_desc = sd.sort(key=lambda x: x['salary'], reverse=True)

# Лимиты и смещения
top_3 = sd.sort(key=lambda x: x['salary'], reverse=True).limit(3)
next_2 = sd.sort(key=lambda x: x['salary']).skip(3).limit(2)
```

### Сериализация
```python

from simpleworkernet import SmartData

data = [{"id": 1, "name": "Test"}, {"id": 2, "name": "Test2"}]
sd = SmartData(data)

# Сохранение в JSON
sd.to_file("data.json")
sd.to_file("data.json", clear_meta=True)  # без метаданных

# Сохранение в pickle
sd.to_file("data.pkl", format="pkl")

# Сохранение в сжатый gzip
sd.to_file("data.gz", format="gz")

# Загрузка из файлов
loaded_json = SmartData.from_file("data.json")
loaded_pkl = SmartData.from_file("data.pkl")
loaded_gz = SmartData.from_file("data.gz")

# Преобразование в словарь
original_dict = sd.to_dict()
print(original_dict)

# Получение плоского списка
flat_list = sd.to_list()

# Сохранение с метаданными
sd.to_file("data_with_meta.json", include_meta=True)

# Сохранение без метаданных
sd.to_file("data_clean.json", include_meta=False)

# Загрузка с восстановлением метаданных
loaded = SmartData.from_file("data_with_meta.json", load_meta=True)

# Загрузка без метаданных
loaded_clean = SmartData.from_file("data_clean.json", load_meta=False)
```

### Примитивные типы
```python

from simpleworkernet import vStr, vFlag, GeoPoint, vPhoneNumber, vMoney, vPercent, vINN, vKPP, vSNILS, vOGRN

# Декодирование строк
text = vStr("Hello%20World&amp;Co")  # "Hello World&Co"

# Битовые флаги
flag = vFlag.v1
if flag & vFlag.v1:
    print("Флаг установлен")
print(vFlag.from_bool(True))  # vFlag.v1

# Геокоординаты
point = GeoPoint(55.75, 37.62)
point2 = GeoPoint("55.76,37.63")
point3 = GeoPoint(lat=55.77,lon=37.64)
print(point)  # "55.75,37.62"
print(point.distance_to(point2))  # расстояние в км

# Телефонные номера
phone = vPhoneNumber("+7 (123) 456-78-90")
print(phone.normalized)  # "71234567890"
print(phone.formatted)   # "+7 (123) 456-78-90"
print(phone.international)  # "+71234567890"

# Денежные суммы
money = vMoney(100.50, "RUB")
money2 = money + 50.25
print(money2)  # "150.75 RUB"

# Проценты
p = vPercent(15.5)
print(p)  # "15.5%"
print(p.of(1000))  # 155.0
print(p.add_to(1000))  # 1155.0

# ИНН с валидацией
inn = vINN("1234567890")
print(inn.is_valid)  # True
print(inn.is_legal)  # True (10 цифр)

# КПП
kpp = vKPP("123456789")
print(kpp.is_valid)  # True

# СНИЛС
snils = vSNILS("123-456-789 01")
print(snils.normalized)  # "12345678901"
print(snils.formatted)   # "123-456-789 01"

# ОГРН
ogrn = vOGRN("1234567890123")
print(ogrn.is_valid)  # True
print(ogrn.is_legal)  # True
```

### Пакетная обработка
```python

from simpleworkernet import SmartData

sd1 = SmartData([1, 2, 3])
sd2 = SmartData([4, 5, 6])

# Конкатенация
combined = sd1 + sd2
print(combined.count())  # 6

# Массовое обновление
data = [
    {"id": 1, "status": "new"},
    {"id": 2, "status": "new"}
]
sd = SmartData(data)

# Обновить все элементы
sd.update_all(status="processed", priority=1)

# Через __setattr__
sd.status = "archived"
sd.priority = 2

for item in sd:
    print(item)  # {"id": 1, "status": "archived", "priority": 2}, ...
```

## 🧹 Очистка и деинсталляция

### Очистка данных
```python

from simpleworkernet import cleanup

# С подтверждением
cleanup()

# Без подтверждения (из кода)
cleanup(force=True)

# Очистка только определенных компонентов
from simpleworkernet.scripts.uninstall import cleanup_simpleworkernet

success, messages = cleanup_simpleworkernet(dry_run=False)
```

### Консольная команда
```bash

# Запуск очистки с подтверждением
cleanup-simpleworkernet

# Принудительная очистка без подтверждения
cleanup-simpleworkernet --force

# Просмотр того, что будет удалено (без удаления)
cleanup-simpleworkernet --dry-run

# Очистка только логов
cleanup-simpleworkernet --logs-only

# Очистка только кэша
cleanup-simpleworkernet --cache-only

# Очистка только конфигурации
cleanup-simpleworkernet --config-only

# Показать версию
cleanup-simpleworkernet --version
```

### Полное удаление
```bash

# 1. Сначала очищаем данные
cleanup-simpleworkernet --force

# 2. Затем удаляем пакет
pip uninstall simpleworkernet
```

## ✒️ Автор

 - [Андрей Литвинов](https://t.me/busy4beaver)
