Metadata-Version: 2.4
Name: small-py
Version: 1.1.1
Summary: Utility library for various uses
Author-email: Nathan Smalley <nathansmalley2@gmail.com>
License: MIT
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas
Requires-Dist: pyautogui
Dynamic: license-file

# smallpy Utility Functions
A collection of reusable Python utility functions and classes for:
- console output control
- JSON "memory" file management
- Excel exporting
- basic image recognition and screen navigation
- progression tracking with time estimation

This module is intended to be imported and reused across automation and data-processing scripts.

---

## Features
- Enable ANSI color / cursor control on Windows terminals
- Clear previously printed terminal lines
- Write Pandas DataFrames to Excel
- Persist structured data to JSON "memory"
  - check for existing entries in "memory"
- Wait for UI images to appear or disappear (via PyAutoGUI)
- Click UI elements based on image matching
- Track progess of iteration with dynamic formatting options
- Get most recentely created file in a directory

## Installation
```bash
pip install small-py
```

**Dependencies:**
```bash
pip install pandas pyautogui
```

---

## Usage
Import the functions or classes you need:
```python
from smallpy.utils import (
  enable_virtual_terminal,
  clear_terminal,
  write_to_excel,
  Counter,
  get_most_recent_file,
)
from smallpy.memory import (
  add_to_memory,
  is_in_memory
)
from smallpy.screen.navigation import (
  BaseScreen,
  ImageLocator
)
```
Or more concisely:
```python
from smallpy import callable_name
```

## Console Utilities
### Enable ANSI / Virtual Terminal Support (Windows)
Need to call if using `clear_terminal()` in command prompt window
```python
enable_virtual_terminal()
```

### Clear Previously Printed Lines
```python
clear_terminal(lines=2)
```

## Excel Output
### Write Dataframe to Excel
```python
import pandas as pd

df = pd.DataFrame({"a": [1, 2], "b": [3, 4]})
write_to_excel(df, "output.xlsx")
```

## Persistent Memory (JSON)
Stored in ./memory/memory.json by default
### Memory Strucutre
```python
{"key":"entry"}
```
```json
{
  "key1":{
    "id":"entry1",
    "optional_field_1":"value",
    ...
    "optional_field_n":"value"
  },
  ...
}
```
- "Key" identifies a shared entry structure for a particular purpose
  - All entries under the same key must share the same structure
  - A "memory" file can have multiple "keys"
- Entries **must** contain an "id" field
- New entries replace existing entries with the same id
### Add or Update an Entry
```python
entry = {"id": 1, "status": "done"}
add_to_memory(
  memory_key = "tasks",
  new_entry = entry
)
```

### Check if an Entry Exists
```python
exists = is_in_memory(
  memory_key="tasks",
  new_entry={"id": 1, "status": "done"},
  comparison_field="status"
)
```

## Screen Automation (PyAutoGUI)
### ImageLocator

`ImageLocator` provides a simple interface to wait for images to appear or disappear on screen.  
It is useful for automating UI interactions based on visual cues.

#### Features

- Wait for a single image or a list of images to appear on screen
- Wait for images to disappear
- Configurable confidence threshold for image recognition
- Keeps a history of located coordinates
- Access the last known location via the `last_location` property
- Optional status printing with indentation

#### Usage

```python
from pathlib import Path
from smallpy.screen.navigation import ImageLocator

# Initialize with a single image
locator = ImageLocator(Path("submit_button.png"))

# Initialize with multiple images
locator = ImageLocator([Path("submit_button.png"), Path("icon.png")])

# Wait for image to appear
location = locator.locate(timeout=5, confidence=0.95)

# Access the most recent location
last = locator.last_location

# Wait for images to disappear
locator.wait_for_disappear(timeout=10)
```

### BaseScreen

`BaseScreen` is an abstract base class designed for screen automation.  
It standardizes image management and interaction, allowing subclasses to inherit image paths and utility methods without hardcoding images.

#### Features

- Dynamically load or accept a dictionary of image paths (`Path`) for a given domain or project.
- Group images by base name, stripping numeric suffixes (e.g., `button1.png`, `button2.png` → `"button"` key).
- Click images with optional offsets, multiple clicks, and intervals.
- Click arbitrary screen coordinates.
- Click a series of images in order.
- Wait for specific images to appear on screen using `ImageLocator`.
- Subclasses inherit all image paths and helper methods without needing to redefine `.images`.

#### Usage

##### Using a Config Dictionary
```python
from pathlib import Path
from config import IMAGE_DICT
from smallpy.screen.navigation import BaseScreen

class LoginScreen(BaseScreen):
    def __init__(self):
        super().__init__(IMAGE_DICT)

login_screen = LoginScreen()
paths = login_screen._get_path("username_field")
```

## Progress Tracking
### Counter Class

Tracks progress and estimates remaining time.
```python
counter = Counter(
    count=10
)

for _ in range(10):
    # do work
    counter.display()
```
- Output of `counter.display()` will default to `n/N` where `n` is the iteration number and `N` is the total count
- A custom format can be passed upon initialization
```python
counter = Counter(
    count=10,
    format = "Iteration %n/%N"
)

for _ in range(10):
    # do work
    counter.display()
```
- Or by changing the `formatter` attribute to utilize dynamic formatting with f-strings
```python
counter = Counter(
    count=10
)

for item in ['foo','bar','baz','qux']:
    # do work
    counter.formatter = f"Iteration %n/%N - {item}"
    counter.display()
```

#### Format tokens:
- `%n` — iteration number
- `%N` — total count
- `%T` — estimated completion time (e.g. "02:04 PM")
- `%t` — raw seconds remaining as float
- `%f` — time remaining split by unit (e.g. "2h 4m 8s")

## File Utilities
### Get Most Recent File in a Directory
```python
latest = get_most_recent_file("downloads")
```
Returns the path to the most recently created file, or "No files found".

## Notes & Limitations
- Screen automation relies on image matching and screen resolution
- JSON memory assumes consistent dictionary structure per key
- Designed for scripting and automation, not as a full framework

## License
MIT License (or update as appropriate)
