refactor: Fix __init__.py - remove duplicates, add lazy loading for Qt deps
This commit is contained in:
parent
b2ec4e2f0f
commit
6f3b6f6781
|
|
@ -0,0 +1,533 @@
|
|||
# EU-Utility Architecture
|
||||
|
||||
> System architecture, component design, and data flow documentation
|
||||
|
||||
---
|
||||
|
||||
## System Overview
|
||||
|
||||
EU-Utility is built on a **modular plugin architecture** with clear separation of concerns. The system is organized into three main layers:
|
||||
|
||||
1. **Core Layer** - Foundation services and APIs
|
||||
2. **Plugin Layer** - Extensible functionality modules
|
||||
3. **UI Layer** - User interface components and overlays
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ UI Layer │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
|
||||
│ │ Overlay │ │ Widgets │ │ Activity Bar │ │
|
||||
│ │ Window │ │ (Draggable)│ │ (Taskbar + App Drawer) │ │
|
||||
│ └──────┬──────┘ └──────┬──────┘ └───────────┬─────────────┘ │
|
||||
└─────────┼────────────────┼─────────────────────┼────────────────┘
|
||||
│ │ │
|
||||
└────────────────┴──────────┬──────────┘
|
||||
│
|
||||
┌─────────────────────────────────────┼─────────────────────────────┐
|
||||
│ Plugin Layer │ │
|
||||
│ ┌──────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
|
||||
│ │ │ Search │ │ Calculator│ │ Tracker │ │ Scanner │ │
|
||||
│ │ │ Plugins │ │ Plugins │ │ Plugins │ │ Plugins │ │
|
||||
│ │ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ └─────────────┴──────┬──────┴─────────────┘ │
|
||||
│ │ │ │
|
||||
│ │ ┌────────┴────────┐ │
|
||||
│ │ │ BasePlugin API │ │
|
||||
│ │ │ (Base Class) │ │
|
||||
│ │ └────────┬────────┘ │
|
||||
│ └─────────────────────────────┼─────────────────────────────────┘
|
||||
└────────────────────────────────┼─────────────────────────────────┘
|
||||
│
|
||||
┌────────────────────────────────┼─────────────────────────────────┐
|
||||
│ Core Layer│ │
|
||||
│ ┌─────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ │ Three-Tier API System │ │
|
||||
│ │ ├───────────────┬───────────────┬───────────────────────┤ │
|
||||
│ │ │ PluginAPI │ WidgetAPI │ ExternalAPI │ │
|
||||
│ │ │ (Services) │ (Overlays) │ (REST/Webhooks) │ │
|
||||
│ │ └───────┬───────┴───────┬───────┴───────────┬───────────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ │ ┌───────┴───────┐ ┌─────┴─────┐ ┌───────────┴──────────┐ │
|
||||
│ │ │ Core Services │ │ Event │ │ Data Layer │ │
|
||||
│ │ │ │ │ Bus │ │ │ │
|
||||
│ │ │ • Window Mgr │ │ (Pub/Sub) │ │ • SQLite Store │ │
|
||||
│ │ │ • OCR Service │ │ │ │ • Settings │ │
|
||||
│ │ │ • Screenshot │ │ │ │ • Plugin States │ │
|
||||
│ │ │ • Log Reader │ │ │ │ • Activity Log │ │
|
||||
│ │ │ • Nexus API │ │ │ │ │ │
|
||||
│ │ │ • HTTP Client │ │ │ │ │ │
|
||||
│ │ │ • Audio │ │ │ │ │ │
|
||||
│ │ └───────────────┘ └───────────┘ └──────────────────────┘ │
|
||||
│ │ │
|
||||
│ │ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ │ Plugin Manager │ │
|
||||
│ │ │ (Discovery, Loading, Lifecycle, Dependencies) │ │
|
||||
│ │ └──────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ └────────────────────────────────────────────────────────────────┘
|
||||
└────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Core Layer
|
||||
|
||||
### Three-Tier API System
|
||||
|
||||
The Core provides a unified API organized into three tiers:
|
||||
|
||||
#### 1. PluginAPI
|
||||
Primary interface for plugin developers to access core services.
|
||||
|
||||
```python
|
||||
from core.api import get_api
|
||||
|
||||
api = get_api()
|
||||
|
||||
# Window Management
|
||||
window = api.get_eu_window()
|
||||
is_focused = api.is_eu_focused()
|
||||
|
||||
# OCR
|
||||
if api.ocr_available():
|
||||
text = api.recognize_text(region=(100, 100, 200, 50))
|
||||
|
||||
# Data Storage
|
||||
api.set_data("key", value)
|
||||
value = api.get_data("key", default)
|
||||
```
|
||||
|
||||
**Available Services:**
|
||||
- `LogReader` - Read and monitor Entropia Universe chat logs
|
||||
- `WindowManager` - Detect and interact with EU window
|
||||
- `OCRService` - Screen text recognition (EasyOCR/Tesseract/PaddleOCR)
|
||||
- `Screenshot` - Screen capture with multiple backends
|
||||
- `NexusAPI` - Entropia Nexus item database integration
|
||||
- `HTTPClient` - Cached web requests with rate limiting
|
||||
- `Audio` - Sound playback and volume control
|
||||
- `Clipboard` - Cross-platform copy/paste
|
||||
- `Notifications` - Desktop toast notifications
|
||||
- `EventBus` - Pub/sub event system
|
||||
- `DataStore` - Persistent key-value storage
|
||||
- `TaskManager` - Background task execution
|
||||
|
||||
#### 2. WidgetAPI
|
||||
Manages overlay widgets - floating UI components.
|
||||
|
||||
```python
|
||||
from core.api import get_widget_api
|
||||
|
||||
widget_api = get_widget_api()
|
||||
|
||||
# Create widget
|
||||
widget = widget_api.create_widget(
|
||||
name="loot_tracker",
|
||||
title="Loot Tracker",
|
||||
size=(400, 300)
|
||||
)
|
||||
|
||||
widget.show()
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Draggable overlay widgets
|
||||
- Size and position persistence
|
||||
- Opacity control
|
||||
- Lock/unlock positioning
|
||||
- Layout helpers (grid, cascade)
|
||||
|
||||
#### 3. ExternalAPI
|
||||
Provides REST endpoints and webhook support for third-party integrations.
|
||||
|
||||
```python
|
||||
from core.api import get_external_api
|
||||
|
||||
ext = get_external_api()
|
||||
ext.start_server(port=8080)
|
||||
|
||||
# Register endpoint
|
||||
@ext.endpoint("stats", methods=["GET"])
|
||||
def get_stats():
|
||||
return {"kills": 100, "loot": "50 PED"}
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- REST API server with CORS
|
||||
- Incoming/outgoing webhooks
|
||||
- HMAC authentication
|
||||
- IPC (Inter-Process Communication)
|
||||
- Server-Sent Events (SSE)
|
||||
|
||||
---
|
||||
|
||||
## Plugin Layer
|
||||
|
||||
### Plugin Architecture
|
||||
|
||||
All plugins inherit from `BasePlugin` and implement a standard interface:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ BasePlugin (Abstract) │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Metadata: name, version, author, etc. │
|
||||
├─────────────────────────────────────────┤
|
||||
│ initialize() → Setup plugin │
|
||||
│ get_ui() → Return QWidget │
|
||||
│ on_show() → Overlay visible │
|
||||
│ on_hide() → Overlay hidden │
|
||||
│ on_hotkey() → Hotkey pressed │
|
||||
│ shutdown() → Cleanup resources │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Helper Methods: │
|
||||
│ • OCR capture │
|
||||
│ • Screenshot │
|
||||
│ • Log reading │
|
||||
│ • Data storage │
|
||||
│ • Event publishing/subscribing │
|
||||
│ • Nexus API access │
|
||||
│ • Background tasks │
|
||||
│ • Notifications │
|
||||
└─────────────────────────────────────────┘
|
||||
│
|
||||
┌───────────┼───────────┐
|
||||
▼ ▼ ▼
|
||||
┌─────────┐ ┌─────────┐ ┌─────────┐
|
||||
│ Search │ │ Tracker │ │Utility │
|
||||
│ Plugins │ │ Plugins │ │ Plugins │
|
||||
└─────────┘ └─────────┘ └─────────┘
|
||||
```
|
||||
|
||||
### Plugin Categories
|
||||
|
||||
| Category | Purpose | Examples |
|
||||
|----------|---------|----------|
|
||||
| **Search** | Data lookup | Universal Search, Nexus Search, TP Runner |
|
||||
| **Trackers** | Progress monitoring | Loot, Skills, Codex, Missions, Globals |
|
||||
| **Calculators** | Game math | DPP, Crafting, Enhancer, Markup |
|
||||
| **Scanners** | OCR-based tools | Game Reader, Skill Scanner |
|
||||
| **Integration** | External services | Spotify Controller, Chat Logger |
|
||||
| **System** | Core functionality | Dashboard, Settings, Plugin Store |
|
||||
|
||||
### Plugin Lifecycle
|
||||
|
||||
```
|
||||
Discovery
|
||||
│
|
||||
▼
|
||||
┌──────────┐
|
||||
│ Import │
|
||||
└────┬─────┘
|
||||
│
|
||||
▼
|
||||
┌──────────┐ No ┌──────────┐
|
||||
│ Enabled? │───────────▶│ Skip │
|
||||
└────┬─────┘ └──────────┘
|
||||
│ Yes
|
||||
▼
|
||||
┌──────────┐
|
||||
│ Load │
|
||||
│ Module │
|
||||
└────┬─────┘
|
||||
│
|
||||
▼
|
||||
┌──────────┐ Error ┌──────────┐
|
||||
│Initialize│───────────▶│ Disable │
|
||||
└────┬─────┘ └──────────┘
|
||||
│ Success
|
||||
▼
|
||||
┌──────────┐
|
||||
│ Running │◀───────┐
|
||||
└────┬─────┘ │
|
||||
│ │
|
||||
▼ │
|
||||
┌──────────┐ │
|
||||
│ Hotkey │ │
|
||||
│ Pressed │────────┘
|
||||
└──────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────┐
|
||||
│ Shutdown │
|
||||
└──────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Event System
|
||||
|
||||
### Event Bus Architecture
|
||||
|
||||
The Event Bus provides typed, filterable pub/sub communication:
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────┐
|
||||
│ Event Bus │
|
||||
├─────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Publisher ─────┐ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────┐ │
|
||||
│ │ Event Router │ │
|
||||
│ │ (Type + Filter Match) │ │
|
||||
│ └────────────┬────────────┘ │
|
||||
│ │ │
|
||||
│ ┌───────────┼───────────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌──────┐ ┌──────┐ ┌──────┐ │
|
||||
│ │ Sub │ │ Sub │ │ Sub │ │
|
||||
│ │ #1 │ │ #2 │ │ #3 │ │
|
||||
│ └──────┘ └──────┘ └──────┘ │
|
||||
│ │ │ │ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ Plugin A Plugin B Plugin C │
|
||||
│ │
|
||||
│ ┌────────────────────────────────────────────┐ │
|
||||
│ │ Event Types: │ │
|
||||
│ │ • SkillGainEvent │ │
|
||||
│ │ • LootEvent │ │
|
||||
│ │ • DamageEvent │ │
|
||||
│ │ • GlobalEvent │ │
|
||||
│ │ • ChatEvent │ │
|
||||
│ │ • EconomyEvent │ │
|
||||
│ │ • SystemEvent │ │
|
||||
│ └────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Event Flow Example
|
||||
|
||||
```python
|
||||
# Plugin A publishes loot event
|
||||
from core.event_bus import LootEvent
|
||||
|
||||
self.publish_typed(LootEvent(
|
||||
mob_name="Daikiba",
|
||||
items=[{"name": "Animal Oil", "value": 0.05}],
|
||||
total_tt_value=0.05
|
||||
))
|
||||
|
||||
# Plugin B subscribes with filter
|
||||
self.subscribe_typed(
|
||||
LootEvent,
|
||||
on_loot,
|
||||
mob_types=["Daikiba", "Atrox"] # Filter
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Data Layer Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Data Layer │
|
||||
├─────────────────────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────┐ │
|
||||
│ │ SQLite Data Store │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ │ │
|
||||
│ │ │user_prefs │ │plugin_states│ │ │
|
||||
│ │ ├─────────────┤ ├─────────────┤ │ │
|
||||
│ │ │• settings │ │• enabled │ │ │
|
||||
│ │ │• hotkeys │ │• version │ │ │
|
||||
│ │ │• theme │ │• settings │ │ │
|
||||
│ │ └─────────────┘ └─────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ │ │
|
||||
│ │ │sessions │ │activity_log │ │ │
|
||||
│ │ ├─────────────┤ ├─────────────┤ │ │
|
||||
│ │ │• start_time │ │• timestamp │ │ │
|
||||
│ │ │• end_time │ │• category │ │ │
|
||||
│ │ │• stats │ │• action │ │ │
|
||||
│ │ └─────────────┘ └─────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ │ ┌─────────────┐ ┌─────────────┐ │ │
|
||||
│ │ │dashboard │ │hotkeys │ │ │
|
||||
│ │ │_widgets │ │ │ │ │
|
||||
│ │ ├─────────────┤ ├─────────────┤ │ │
|
||||
│ │ │• position │ │• key_combo │ │ │
|
||||
│ │ │• size │ │• action │ │ │
|
||||
│ │ │• config │ │• plugin_id │ │ │
|
||||
│ │ └─────────────┘ └─────────────┘ │ │
|
||||
│ │ │ │
|
||||
│ └─────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────────────────────┐ │
|
||||
│ │ Data Access Pattern │ │
|
||||
│ │ │ │
|
||||
│ │ Plugin ──▶ API ──▶ SQLiteStore ──▶ SQLite DB │ │
|
||||
│ │ │ │
|
||||
│ │ All data is JSON-serialized for flexibility │ │
|
||||
│ └─────────────────────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## UI Architecture
|
||||
|
||||
### Overlay System
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Desktop │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ Main Overlay Window │ │
|
||||
│ │ ┌─────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Plugin Tab Bar │ │ │
|
||||
│ │ │ [Dash][Search][Calc][Track][...] │ │ │
|
||||
│ │ └─────────────────────────────────────────────┘ │ │
|
||||
│ │ ┌─────────┬──────────────────────────────────┐ │ │
|
||||
│ │ │ Plugin │ │ │ │
|
||||
│ │ │ List │ Active Plugin Content │ │ │
|
||||
│ │ │ │ │ │ │
|
||||
│ │ │ • Search│ ┌──────────────────────┐ │ │ │
|
||||
│ │ │ • Calc │ │ │ │ │ │
|
||||
│ │ │ • Track │ │ Plugin UI Here │ │ │ │
|
||||
│ │ │ • ... │ │ │ │ │ │
|
||||
│ │ │ │ └──────────────────────┘ │ │ │
|
||||
│ │ └─────────┴──────────────────────────────────┘ │ │
|
||||
│ │ ┌─────────────────────────────────────────────┐ │ │
|
||||
│ │ │ Quick Actions Bar │ │ │
|
||||
│ │ └─────────────────────────────────────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
│ │ │
|
||||
│ ┌─────────────────┼─────────────────┐ │
|
||||
│ ▼ ▼ ▼ │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
||||
│ │ Floating │ │ Widget │ │ Activity │ │
|
||||
│ │ Icon │ │ (Loot) │ │ Bar │ │
|
||||
│ │ (Draggable)│ │ (Draggable)│ │(Bottom/Top) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Component Hierarchy
|
||||
|
||||
```
|
||||
QApplication
|
||||
└── EUUtilityApp
|
||||
├── MainOverlayWindow
|
||||
│ ├── PluginTabBar
|
||||
│ ├── PluginSidebar
|
||||
│ ├── PluginContentArea
|
||||
│ └── QuickActionsBar
|
||||
├── FloatingIcon (always on top)
|
||||
├── ActivityBar (optional, bottom/top)
|
||||
│ ├── StartButton (opens AppDrawer)
|
||||
│ ├── PinnedPlugins
|
||||
│ ├── SearchBox
|
||||
│ └── Clock/Settings
|
||||
├── WidgetOverlay
|
||||
│ └── Individual Widgets
|
||||
└── TrayIcon
|
||||
└── ContextMenu
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Security Architecture
|
||||
|
||||
### Data Protection
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Security Layer │
|
||||
├─────────────────────────────────────────┤
|
||||
│ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ Input Sanitization │ │
|
||||
│ │ • Path traversal protection │ │
|
||||
│ │ • SQL injection prevention │ │
|
||||
│ │ • XSS protection │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ Data Encryption │ │
|
||||
│ │ • AES-256 for sensitive data │ │
|
||||
│ │ • Secure key storage │ │
|
||||
│ │ • Encrypted settings │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ File Operations │ │
|
||||
│ │ • Atomic writes (temp files) │ │
|
||||
│ │ • Proper file permissions │ │
|
||||
│ │ • Safe temp file handling │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────────────────────┐ │
|
||||
│ │ Plugin Isolation │ │
|
||||
│ │ • Try/except around plugin ops │ │
|
||||
│ │ • Separate error handling │ │
|
||||
│ │ • Resource cleanup on crash │ │
|
||||
│ └─────────────────────────────────┘ │
|
||||
│ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Performance Optimizations
|
||||
|
||||
### Caching Strategy
|
||||
|
||||
| Layer | Cache Type | TTL | Purpose |
|
||||
|-------|------------|-----|---------|
|
||||
| HTTP Client | Response cache | Configurable | API responses |
|
||||
| Nexus API | Item data | 5 minutes | Item/market data |
|
||||
| Icon Manager | Loaded icons | Session | UI performance |
|
||||
| Plugin Manager | Loaded plugins | Session | Startup time |
|
||||
| Settings | Config values | Session | Fast access |
|
||||
|
||||
### Resource Management
|
||||
|
||||
```python
|
||||
# Lazy initialization pattern
|
||||
class ExpensiveService:
|
||||
def __init__(self):
|
||||
self._initialized = False
|
||||
self._resource = None
|
||||
|
||||
@property
|
||||
def resource(self):
|
||||
if not self._initialized:
|
||||
self._resource = self._create_expensive_resource()
|
||||
self._initialized = True
|
||||
return self._resource
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Technology Stack
|
||||
|
||||
| Component | Technology |
|
||||
|-----------|------------|
|
||||
| **Language** | Python 3.11+ |
|
||||
| **UI Framework** | PyQt6 |
|
||||
| **Database** | SQLite |
|
||||
| **HTTP Client** | `requests` with caching |
|
||||
| **OCR** | EasyOCR / Tesseract / PaddleOCR |
|
||||
| **Screenshot** | PIL / MSS / Win32 (Windows) |
|
||||
| **Audio** | pygame.mixer / simpleaudio |
|
||||
| **Task Queue** | ThreadPoolExecutor |
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [API Reference](./API.md) - Complete API documentation
|
||||
- [Plugin Development](./docs/PLUGIN_DEVELOPMENT.md) - Creating plugins
|
||||
- [Contributing](./CONTRIBUTING.md) - Contribution guidelines
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
# EU-Utility - MANIFEST.in
|
||||
# Controls what files are included in the source distribution (sdist)
|
||||
# https://packaging.python.org/en/latest/guides/using-manifest-in/
|
||||
|
||||
# =============================================================================
|
||||
# INCLUDE PATTERNS
|
||||
# =============================================================================
|
||||
|
||||
# Core package files
|
||||
recursive-include core *.py
|
||||
recursive-include core *.json *.yaml *.yml
|
||||
recursive-include core *.css *.qss *.ui
|
||||
recursive-include core *.png *.jpg *.jpeg *.gif *.ico *.svg
|
||||
|
||||
# Plugin files
|
||||
recursive-include plugins *.py
|
||||
recursive-include plugins *.json *.yaml *.yml
|
||||
recursive-include plugins *.css *.qss *.ui
|
||||
recursive-include plugins/assets *.png *.jpg *.jpeg *.gif *.ico *.svg *.ttf *.woff *.woff2
|
||||
recursive-include plugins/templates *.html *.txt *.md
|
||||
|
||||
# Documentation
|
||||
recursive-include docs *.md *.rst *.txt
|
||||
recursive-include docs *.png *.jpg *.jpeg *.gif *.svg
|
||||
include README.md
|
||||
include CONTRIBUTING.md
|
||||
include CHANGELOG.md
|
||||
include SECURITY_AUDIT_REPORT.md
|
||||
include LICENSE
|
||||
|
||||
# Configuration files
|
||||
include requirements.txt
|
||||
include requirements-dev.txt
|
||||
include pytest.ini
|
||||
|
||||
# Build and packaging
|
||||
include setup.py
|
||||
include pyproject.toml
|
||||
include MANIFEST.in
|
||||
include Makefile
|
||||
|
||||
# GitHub templates and workflows
|
||||
recursive-include .github *.md *.yml *.yaml
|
||||
|
||||
# Assets
|
||||
recursive-include assets *.png *.jpg *.jpeg *.gif *.ico *.svg
|
||||
recursive-include benchmarks *.py *.md
|
||||
|
||||
# =============================================================================
|
||||
# EXCLUDE PATTERNS
|
||||
# =============================================================================
|
||||
|
||||
# Test files (excluded from distribution)
|
||||
recursive-exclude tests *
|
||||
recursive-exclude * test_*.py *_test.py
|
||||
recursive-exclude * __pycache__
|
||||
recursive-exclude * *.py[co]
|
||||
recursive-exclude * *.so
|
||||
recursive-exclude * .pytest_cache
|
||||
recursive-exclude * .coverage
|
||||
recursive-exclude * coverage.xml
|
||||
recursive-exclude * htmlcov
|
||||
|
||||
# Development environment
|
||||
recursive-exclude * .venv
|
||||
recursive-exclude * venv
|
||||
recursive-exclude * env
|
||||
recursive-exclude * .env
|
||||
recursive-exclude * .env.*
|
||||
|
||||
# Version control
|
||||
recursive-exclude * .git
|
||||
recursive-exclude * .gitignore
|
||||
recursive-exclude * .gitattributes
|
||||
|
||||
# IDE and editor files
|
||||
recursive-exclude * .vscode
|
||||
recursive-exclude * .idea
|
||||
recursive-exclude * *.swp
|
||||
recursive-exclude * *.swo
|
||||
recursive-exclude * *~
|
||||
recursive-exclude * .DS_Store
|
||||
recursive-exclude * Thumbs.db
|
||||
|
||||
# Build artifacts
|
||||
recursive-exclude * build
|
||||
recursive-exclude * dist
|
||||
recursive-exclude * *.egg-info
|
||||
recursive-exclude * .eggs
|
||||
|
||||
# CI/CD (excluded - these are for development only)
|
||||
recursive-exclude .github/workflows *
|
||||
|
||||
# Temporary and cache files
|
||||
recursive-exclude * .tox
|
||||
recursive-exclude * .mypy_cache
|
||||
recursive-exclude * .hypothesis
|
||||
recursive-exclude * .ruff_cache
|
||||
recursive-exclude * *.log
|
||||
recursive-exclude * logs/*.log
|
||||
recursive-exclude * *.db
|
||||
recursive-exclude * *.sqlite
|
||||
recursive-exclude * *.sqlite3
|
||||
|
||||
# Security and sensitive files (never include these)
|
||||
exclude .env
|
||||
exclude .env.local
|
||||
exclude .env.production
|
||||
exclude secrets.json
|
||||
exclude credentials.json
|
||||
exclude *secret*
|
||||
exclude *password*
|
||||
exclude *credential*
|
||||
exclude *_key*
|
||||
exclude private_*
|
||||
|
||||
# Debug and vulnerable files (exclude from distribution)
|
||||
recursive-exclude * *_vulnerable.py
|
||||
recursive-exclude * *_insecure.py
|
||||
recursive-exclude * *_debug.py
|
||||
|
|
@ -0,0 +1,328 @@
|
|||
# EU-Utility - Modern Python Packaging Configuration
|
||||
# https://github.com/ImpulsiveFPS/EU-Utility
|
||||
|
||||
[build-system]
|
||||
requires = [
|
||||
"setuptools>=65.0",
|
||||
"wheel>=0.41.0",
|
||||
"setuptools-scm>=7.0",
|
||||
]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "eu-utility"
|
||||
version = "2.1.0"
|
||||
description = "A versatile Entropia Universe utility suite with a modular plugin system"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{name = "ImpulsiveFPS", email = "dev@impulsivefps.com"},
|
||||
]
|
||||
maintainers = [
|
||||
{name = "ImpulsiveFPS", email = "dev@impulsivefps.com"},
|
||||
]
|
||||
keywords = [
|
||||
"entropia universe",
|
||||
"game utility",
|
||||
"overlay",
|
||||
"plugin system",
|
||||
"ocr",
|
||||
"tracker",
|
||||
"calculator",
|
||||
"gaming",
|
||||
"mmorpg",
|
||||
]
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: End Users/Desktop",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
"Topic :: Games/Entertainment",
|
||||
"Topic :: Utilities",
|
||||
"Topic :: Desktop Environment",
|
||||
"Environment :: X11 Applications :: Qt",
|
||||
"Environment :: Win32 (MS Windows)",
|
||||
"Natural Language :: English",
|
||||
]
|
||||
requires-python = ">=3.11"
|
||||
dependencies = [
|
||||
"PyQt6>=6.4.0,<7.0.0",
|
||||
"keyboard>=0.13.5,<1.0.0",
|
||||
"psutil>=5.9.0,<6.0.0",
|
||||
"pyperclip>=1.8.2,<2.0.0",
|
||||
"easyocr>=1.7.0,<2.0.0",
|
||||
"pytesseract>=0.3.10,<1.0.0",
|
||||
"pyautogui>=0.9.54,<1.0.0",
|
||||
"pillow>=10.0.0,<11.0.0",
|
||||
"requests>=2.28.0,<3.0.0",
|
||||
"urllib3>=1.26.0,<3.0.0",
|
||||
"numpy>=1.21.0,<2.0.0",
|
||||
'portalocker>=2.7.0; platform_system=="Windows"',
|
||||
'pywin32>=306; platform_system=="Windows"',
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
spotify = [
|
||||
"spotipy>=2.23.0,<3.0.0",
|
||||
'pycaw>=20230407; platform_system=="Windows"',
|
||||
]
|
||||
discord = [
|
||||
"pypresence>=4.3.0,<5.0.0",
|
||||
]
|
||||
all = [
|
||||
"spotipy>=2.23.0,<3.0.0",
|
||||
'pycaw>=20230407; platform_system=="Windows"',
|
||||
"pypresence>=4.3.0,<5.0.0",
|
||||
]
|
||||
dev = [
|
||||
"pytest>=7.4.0,<8.0.0",
|
||||
"pytest-cov>=4.1.0,<5.0.0",
|
||||
"pytest-mock>=3.11.0,<4.0.0",
|
||||
"pytest-benchmark>=4.0.0,<5.0.0",
|
||||
"pytest-qt>=4.2.0,<5.0.0",
|
||||
"pytest-xvfb>=2.0.0,<3.0.0",
|
||||
"black>=23.0.0,<24.0.0",
|
||||
"flake8>=6.0.0,<7.0.0",
|
||||
"mypy>=1.5.0,<2.0.0",
|
||||
"isort>=5.12.0,<6.0.0",
|
||||
"pydocstyle>=6.3.0,<7.0.0",
|
||||
"bandit>=1.7.5,<2.0.0",
|
||||
"safety>=2.3.0,<3.0.0",
|
||||
"sphinx>=7.0.0,<8.0.0",
|
||||
"sphinx-rtd-theme>=1.3.0,<2.0.0",
|
||||
"myst-parser>=2.0.0,<3.0.0",
|
||||
"build>=0.10.0,<1.0.0",
|
||||
"twine>=4.0.0,<5.0.0",
|
||||
"wheel>=0.41.0,<1.0.0",
|
||||
"pre-commit>=3.4.0,<4.0.0",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
eu-utility = "core.main:main"
|
||||
eu-utility-secure = "core.main_optimized:main"
|
||||
|
||||
[project.gui-scripts]
|
||||
eu-utility-gui = "core.main:main"
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/ImpulsiveFPS/EU-Utility"
|
||||
Documentation = "https://github.com/ImpulsiveFPS/EU-Utility/tree/main/docs"
|
||||
Repository = "https://github.com/ImpulsiveFPS/EU-Utility.git"
|
||||
"Bug Tracker" = "https://github.com/ImpulsiveFPS/EU-Utility/issues"
|
||||
Changelog = "https://github.com/ImpulsiveFPS/EU-Utility/blob/main/CHANGELOG.md"
|
||||
|
||||
# =============================================================================
|
||||
# TOOL CONFIGURATIONS
|
||||
# =============================================================================
|
||||
|
||||
# Black - Code Formatter
|
||||
[tool.black]
|
||||
line-length = 100
|
||||
target-version = ["py311", "py312"]
|
||||
include = '\.pyi?$'
|
||||
extend-exclude = '''
|
||||
/(
|
||||
\.git
|
||||
| \.venv
|
||||
| venv
|
||||
| env
|
||||
| build
|
||||
| dist
|
||||
| __pycache__
|
||||
| \.pytest_cache
|
||||
| htmlcov
|
||||
| \.tox
|
||||
| migrations
|
||||
)/
|
||||
'''
|
||||
skip-string-normalization = false
|
||||
preview = false
|
||||
|
||||
# isort - Import Sorting
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
line_length = 100
|
||||
multi_line_output = 3
|
||||
include_trailing_comma = true
|
||||
force_grid_wrap = 0
|
||||
use_parentheses = true
|
||||
ensure_newline_before_comments = true
|
||||
skip = [".git", "__pycache__", "venv", ".venv", "build", "dist"]
|
||||
known_first_party = ["core", "plugins"]
|
||||
known_third_party = ["PyQt6", "pytest"]
|
||||
|
||||
# flake8 - Linting
|
||||
[tool.flake8]
|
||||
max-line-length = 100
|
||||
extend-ignore = [
|
||||
"E203", # Whitespace before ':' (conflicts with black)
|
||||
"E501", # Line too long (handled by black)
|
||||
"W503", # Line break before binary operator (black style)
|
||||
]
|
||||
exclude = [
|
||||
".git",
|
||||
"__pycache__",
|
||||
".venv",
|
||||
"venv",
|
||||
"build",
|
||||
"dist",
|
||||
".pytest_cache",
|
||||
"htmlcov",
|
||||
".tox",
|
||||
"migrations",
|
||||
]
|
||||
per-file-ignores = [
|
||||
"__init__.py:F401,F403",
|
||||
"test_*.py:S101",
|
||||
]
|
||||
max-complexity = 10
|
||||
|
||||
# mypy - Type Checking
|
||||
[tool.mypy]
|
||||
python_version = "3.11"
|
||||
warn_return_any = true
|
||||
warn_unused_configs = true
|
||||
disallow_untyped_defs = true
|
||||
disallow_incomplete_defs = true
|
||||
check_untyped_defs = true
|
||||
disallow_untyped_decorators = false
|
||||
no_implicit_optional = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_ignores = true
|
||||
warn_no_return = true
|
||||
warn_unreachable = true
|
||||
strict_equality = true
|
||||
show_error_codes = true
|
||||
show_column_numbers = true
|
||||
show_error_context = true
|
||||
pretty = true
|
||||
|
||||
# Module-specific settings
|
||||
[[tool.mypy.overrides]]
|
||||
module = [
|
||||
"pytesseract.*",
|
||||
"pyautogui.*",
|
||||
"easyocr.*",
|
||||
"keyboard.*",
|
||||
"psutil.*",
|
||||
"PIL.*",
|
||||
"win32con.*",
|
||||
"win32gui.*",
|
||||
"win32api.*",
|
||||
"portalocker.*",
|
||||
]
|
||||
ignore_missing_imports = true
|
||||
|
||||
# pytest - Testing
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
python_files = ["test_*.py"]
|
||||
python_classes = ["Test*"]
|
||||
python_functions = ["test_*"]
|
||||
addopts = [
|
||||
"-v",
|
||||
"--tb=short",
|
||||
"--strict-markers",
|
||||
"--cov=core",
|
||||
"--cov=plugins",
|
||||
"--cov-report=term-missing",
|
||||
"--cov-report=html:htmlcov",
|
||||
"--cov-report=xml:coverage.xml",
|
||||
"--cov-fail-under=80",
|
||||
]
|
||||
markers = [
|
||||
"unit: Unit tests for individual components",
|
||||
"integration: Integration tests for plugin interactions",
|
||||
"ui: UI automation tests",
|
||||
"performance: Performance benchmarks",
|
||||
"slow: Slow tests that may be skipped in CI",
|
||||
"requires_qt: Tests requiring PyQt6",
|
||||
"requires_network: Tests requiring network access",
|
||||
]
|
||||
filterwarnings = [
|
||||
"ignore::DeprecationWarning",
|
||||
"ignore::PendingDeprecationWarning",
|
||||
]
|
||||
|
||||
# Coverage - Code Coverage
|
||||
[tool.coverage.run]
|
||||
source = ["core", "plugins"]
|
||||
branch = true
|
||||
omit = [
|
||||
"*/tests/*",
|
||||
"*/test_*",
|
||||
"*/venv/*",
|
||||
"*/.venv/*",
|
||||
"setup.py",
|
||||
"run_tests.py",
|
||||
"code_review_report.py",
|
||||
"*/benchmarks/*",
|
||||
"*_vulnerable.py",
|
||||
]
|
||||
|
||||
[tool.coverage.report]
|
||||
exclude_lines = [
|
||||
"pragma: no cover",
|
||||
"def __repr__",
|
||||
"if self.debug:",
|
||||
"if settings.DEBUG",
|
||||
"raise AssertionError",
|
||||
"raise NotImplementedError",
|
||||
"if 0:",
|
||||
"if __name__ == .__main__.:",
|
||||
"class .*\\bProtocol\\):",
|
||||
"@(abc\\.)?abstractmethod",
|
||||
"pass",
|
||||
]
|
||||
fail_under = 80
|
||||
show_missing = true
|
||||
skip_covered = false
|
||||
|
||||
[tool.coverage.html]
|
||||
directory = "htmlcov"
|
||||
|
||||
# Bandit - Security Linter
|
||||
[tool.bandit]
|
||||
exclude_dirs = [
|
||||
"tests",
|
||||
"test",
|
||||
".venv",
|
||||
"venv",
|
||||
"build",
|
||||
"dist",
|
||||
]
|
||||
skips = [
|
||||
"B101", # assert_used (common in Python code)
|
||||
"B311", # random (acceptable for non-cryptographic use)
|
||||
]
|
||||
|
||||
# Pydocstyle - Docstring Conventions
|
||||
[tool.pydocstyle]
|
||||
convention = "google"
|
||||
match = "(?!test_).*\\.py"
|
||||
match_dir = "^(?!tests|\\.venv|venv|build|dist).*"
|
||||
add_ignore = [
|
||||
"D100", # Missing docstring in public module
|
||||
"D104", # Missing docstring in public package
|
||||
"D107", # Missing docstring in __init__
|
||||
]
|
||||
|
||||
# setuptools - Package Discovery
|
||||
[tool.setuptools]
|
||||
packages = ["core", "core.*", "plugins", "plugins.*"]
|
||||
include-package-data = true
|
||||
zip-safe = false
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
core = ["*.json", "*.yaml", "*.yml", "*.css", "*.qss"]
|
||||
plugins = ["*/assets/*", "*/templates/*"]
|
||||
|
||||
[tool.setuptools.exclude-package-data]
|
||||
core = ["tests/*", "*_test.py", "test_*.py"]
|
||||
plugins = ["tests/*", "*_test.py", "test_*.py"]
|
||||
|
|
@ -7,12 +7,6 @@ addopts =
|
|||
-v
|
||||
--tb=short
|
||||
--strict-markers
|
||||
--cov=core
|
||||
--cov=plugins
|
||||
--cov-report=term-missing
|
||||
--cov-report=html:htmlcov
|
||||
--cov-report=xml:coverage.xml
|
||||
--cov-fail-under=80
|
||||
markers =
|
||||
unit: Unit tests for individual components
|
||||
integration: Integration tests for plugin interactions
|
||||
|
|
|
|||
|
|
@ -0,0 +1,249 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
EU-Utility - Setup Script
|
||||
|
||||
A versatile Entropia Universe utility suite with a modular plugin system.
|
||||
|
||||
For more information, visit: https://github.com/ImpulsiveFPS/EU-Utility
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
# Ensure setuptools is available
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
# Project root directory
|
||||
PROJECT_ROOT = Path(__file__).parent.resolve()
|
||||
|
||||
# Read version from core/__init__.py
|
||||
def get_version():
|
||||
"""Extract version from core/__init__.py."""
|
||||
init_file = PROJECT_ROOT / "core" / "__init__.py"
|
||||
with open(init_file, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
if line.startswith("__version__"):
|
||||
return line.split("=")[1].strip().strip('"\'')
|
||||
raise RuntimeError("Version not found in core/__init__.py")
|
||||
|
||||
# Read long description from README
|
||||
def get_long_description():
|
||||
"""Read README.md for long description."""
|
||||
readme_file = PROJECT_ROOT / "README.md"
|
||||
if readme_file.exists():
|
||||
with open(readme_file, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
return ""
|
||||
|
||||
# Runtime dependencies
|
||||
INSTALL_REQUIRES = [
|
||||
# Core GUI Framework
|
||||
"PyQt6>=6.4.0,<7.0.0",
|
||||
|
||||
# System Integration
|
||||
"keyboard>=0.13.5,<1.0.0",
|
||||
"psutil>=5.9.0,<6.0.0",
|
||||
"pyperclip>=1.8.2,<2.0.0",
|
||||
|
||||
# OCR and Image Processing
|
||||
"easyocr>=1.7.0,<2.0.0",
|
||||
"pytesseract>=0.3.10,<1.0.0",
|
||||
"pyautogui>=0.9.54,<1.0.0",
|
||||
"pillow>=10.0.0,<11.0.0",
|
||||
|
||||
# HTTP and Networking
|
||||
"requests>=2.28.0,<3.0.0",
|
||||
"urllib3>=1.26.0,<3.0.0",
|
||||
|
||||
# Data Processing
|
||||
"numpy>=1.21.0,<2.0.0",
|
||||
|
||||
# Windows-specific dependencies (installed only on Windows)
|
||||
'portalocker>=2.7.0; platform_system=="Windows"',
|
||||
'pywin32>=306; platform_system=="Windows"',
|
||||
]
|
||||
|
||||
# Development dependencies
|
||||
DEV_REQUIRES = [
|
||||
# Testing
|
||||
"pytest>=7.4.0,<8.0.0",
|
||||
"pytest-cov>=4.1.0,<5.0.0",
|
||||
"pytest-mock>=3.11.0,<4.0.0",
|
||||
"pytest-benchmark>=4.0.0,<5.0.0",
|
||||
"pytest-qt>=4.2.0,<5.0.0",
|
||||
"pytest-xvfb>=2.0.0,<3.0.0",
|
||||
|
||||
# Code Quality
|
||||
"black>=23.0.0,<24.0.0",
|
||||
"flake8>=6.0.0,<7.0.0",
|
||||
"mypy>=1.5.0,<2.0.0",
|
||||
"isort>=5.12.0,<6.0.0",
|
||||
"pydocstyle>=6.3.0,<7.0.0",
|
||||
|
||||
# Security
|
||||
"bandit>=1.7.5,<2.0.0",
|
||||
"safety>=2.3.0,<3.0.0",
|
||||
|
||||
# Documentation
|
||||
"sphinx>=7.0.0,<8.0.0",
|
||||
"sphinx-rtd-theme>=1.3.0,<2.0.0",
|
||||
"myst-parser>=2.0.0,<3.0.0",
|
||||
|
||||
# Build and Packaging
|
||||
"build>=0.10.0,<1.0.0",
|
||||
"twine>=4.0.0,<5.0.0",
|
||||
"wheel>=0.41.0,<1.0.0",
|
||||
|
||||
# Pre-commit hooks
|
||||
"pre-commit>=3.4.0,<4.0.0",
|
||||
]
|
||||
|
||||
# Optional plugin dependencies
|
||||
EXTRAS_REQUIRE = {
|
||||
# Advanced media control features
|
||||
"spotify": [
|
||||
"spotipy>=2.23.0,<3.0.0",
|
||||
'pycaw>=20230407; platform_system=="Windows"',
|
||||
],
|
||||
|
||||
# Discord Rich Presence integration
|
||||
"discord": [
|
||||
"pypresence>=4.3.0,<5.0.0",
|
||||
],
|
||||
|
||||
# All optional features
|
||||
"all": [
|
||||
"spotipy>=2.23.0,<3.0.0",
|
||||
'pycaw>=20230407; platform_system=="Windows"',
|
||||
"pypresence>=4.3.0,<5.0.0",
|
||||
],
|
||||
|
||||
# Development extras (includes all dev dependencies)
|
||||
"dev": DEV_REQUIRES,
|
||||
}
|
||||
|
||||
# Package classifiers
|
||||
CLASSIFIERS = [
|
||||
# Development Status
|
||||
"Development Status :: 4 - Beta",
|
||||
|
||||
# Intended Audience
|
||||
"Intended Audience :: End Users/Desktop",
|
||||
"Intended Audience :: Gamers",
|
||||
|
||||
# License
|
||||
"License :: OSI Approved :: MIT License",
|
||||
|
||||
# Operating System
|
||||
"Operating System :: OS Independent",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
|
||||
# Programming Language
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3 :: Only",
|
||||
|
||||
# Topic
|
||||
"Topic :: Games/Entertainment",
|
||||
"Topic :: Utilities",
|
||||
"Topic :: Desktop Environment",
|
||||
|
||||
# Environment
|
||||
"Environment :: X11 Applications :: Qt",
|
||||
"Environment :: Win32 (MS Windows)",
|
||||
|
||||
# Natural Language
|
||||
"Natural Language :: English",
|
||||
]
|
||||
|
||||
# Entry points for CLI usage
|
||||
ENTRY_POINTS = {
|
||||
"console_scripts": [
|
||||
"eu-utility=core.main:main",
|
||||
"eu-utility-secure=core.main_optimized:main",
|
||||
],
|
||||
"gui_scripts": [
|
||||
"eu-utility-gui=core.main:main",
|
||||
],
|
||||
}
|
||||
|
||||
# Package data to include
|
||||
PACKAGE_DATA = {
|
||||
"core": ["*.json", "*.yaml", "*.yml", "*.css", "*.qss"],
|
||||
"plugins": ["*/assets/*", "*/templates/*"],
|
||||
}
|
||||
|
||||
|
||||
def main():
|
||||
"""Execute setup."""
|
||||
setup(
|
||||
# Basic metadata
|
||||
name="eu-utility",
|
||||
version=get_version(),
|
||||
author="ImpulsiveFPS",
|
||||
author_email="dev@impulsivefps.com",
|
||||
maintainer="ImpulsiveFPS",
|
||||
maintainer_email="dev@impulsivefps.com",
|
||||
url="https://github.com/ImpulsiveFPS/EU-Utility",
|
||||
project_urls={
|
||||
"Bug Reports": "https://github.com/ImpulsiveFPS/EU-Utility/issues",
|
||||
"Source": "https://github.com/ImpulsiveFPS/EU-Utility",
|
||||
"Documentation": "https://github.com/ImpulsiveFPS/EU-Utility/tree/main/docs",
|
||||
"Changelog": "https://github.com/ImpulsiveFPS/EU-Utility/blob/main/CHANGELOG.md",
|
||||
},
|
||||
|
||||
# Descriptions
|
||||
description="A versatile Entropia Universe utility suite with a modular plugin system",
|
||||
long_description=get_long_description(),
|
||||
long_description_content_type="text/markdown",
|
||||
keywords=[
|
||||
"entropia universe",
|
||||
"game utility",
|
||||
"overlay",
|
||||
"plugin system",
|
||||
"ocr",
|
||||
"tracker",
|
||||
"calculator",
|
||||
"gaming",
|
||||
"mmorpg",
|
||||
],
|
||||
|
||||
# Classifiers
|
||||
classifiers=CLASSIFIERS,
|
||||
|
||||
# License
|
||||
license="MIT",
|
||||
|
||||
# Python version requirement
|
||||
python_requires=">=3.11",
|
||||
|
||||
# Packages
|
||||
packages=find_packages(
|
||||
include=["core", "core.*", "plugins", "plugins.*"],
|
||||
exclude=["tests", "tests.*", "benchmarks", "benchmarks.*", "docs", "docs.*"],
|
||||
),
|
||||
|
||||
# Dependencies
|
||||
install_requires=INSTALL_REQUIRES,
|
||||
extras_require=EXTRAS_REQUIRE,
|
||||
|
||||
# Package data
|
||||
include_package_data=True,
|
||||
package_data=PACKAGE_DATA,
|
||||
|
||||
# Entry points
|
||||
entry_points=ENTRY_POINTS,
|
||||
|
||||
# Zip safety
|
||||
zip_safe=False,
|
||||
|
||||
# Platforms
|
||||
platforms=["win32", "win64", "linux"],
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in New Issue