Metadata-Version: 2.4
Name: bytewyrm
Version: 0.6.0
Summary: Beginner-friendly online tools for small Python game projects.
Author: ByteWyrm
License-Expression: MIT
Project-URL: Homepage, https://bytewyrm.dev
Project-URL: Repository, https://github.com/William-Nitrosis/bytewyrm
Project-URL: Issues, https://github.com/William-Nitrosis/bytewyrm/issues
Project-URL: API, https://api.bytewyrm.dev
Keywords: education,games,api,students,bytewyrm
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Education
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# ByteWyrm

ByteWyrm gives small Python game projects simple online tools without making students build or manage a server themselves.

The package is designed for learners: create one `ByteWyrm` object, then use the tools inside it. Networking, web requests, JSON, authentication headers and server details stay out of the way.

> ByteWyrm is currently an alpha project. The API is intentionally small and may grow as more tools are added.

## Install

```bash
python -m pip install bytewyrm
```

ByteWyrm requires Python 3.10 or newer and has no third-party runtime dependencies.

## Data safety

> **ByteWyrm is designed for small amounts of non-sensitive game data only.**

Good examples include scores, player nicknames, progress values, lap times, flags and other simple game state.

Do **not** use ByteWyrm to store real names, email addresses, passwords, addresses, private messages, medical information, or other personal, sensitive, or confidential information.

The Python library also prints a short safety notice the first time a `ByteWyrm` object is created in each program run. It is a normal console message rather than a Python warning, so Python does not echo the source line containing your API key.

## Connect to a Project

Your teacher will normally give you a ByteWyrm key beginning with `bwk_`.

```python
from bytewyrm import ByteWyrm


wyrm = ByteWyrm("bwk_YOUR_KEY_HERE")
```

You normally create this object once near the start of your program.

## Store

The Store saves small pieces of structured data such as player nicknames, scores, levels, times and booleans. Your teacher chooses which fields the Store accepts and what rules they follow.

### Save a record

```python
wyrm.store.add(
    player="Drake",
    score=12500,
)
```

A normal dictionary works too:

```python
wyrm.store.add(
    {
        "player": "Drake",
        "score": 12500,
    }
)
```

The returned record behaves like a normal Python dictionary:

```python
record = wyrm.store.add(player="Drake", score=12500)

if record is not None:
    print(record["player"])
    print(record["score"])
```

If saving cannot be confirmed, `add()` prints an error and returns `None`.

### Read records

```python
records = wyrm.store.records()

for record in records:
    print(record["player"], record["score"])
```

With no extra options, the newest records are returned first.

Ask for fewer records with:

```python
records = wyrm.store.records(limit=10)
```

### Sort records

For example, get the ten highest scores:

```python
top_scores = wyrm.store.records(
    sort_by="score",
    reverse=True,
    limit=10,
)
```

Or get the fastest times first:

```python
fastest_times = wyrm.store.records(
    sort_by="time",
)
```

### Filter records

ByteWyrm intentionally keeps filtering simple. Use one of `equals`, `greater_than` or `less_than` at a time.

```python
finished = wyrm.store.records(
    where="completed",
    equals=True,
)
```

```python
high_scores = wyrm.store.records(
    where="score",
    greater_than=1000,
)
```

```python
fast_runs = wyrm.store.records(
    where="time",
    less_than=60,
)
```

Sorting and filtering can be combined:

```python
top_finished = wyrm.store.records(
    where="completed",
    equals=True,
    sort_by="score",
    reverse=True,
    limit=10,
)
```

### Read the newest record

```python
record = wyrm.store.latest()

if record is not None:
    print(record["score"])
```

If nothing has been saved yet or the request fails, `latest()` returns `None`.

### See what the Store accepts

Your teacher will normally tell you which values the Store accepts, but you can inspect its schema:

```python
print(wyrm.store.schema())
```

## Record information

Store records behave like dictionaries, but ByteWyrm also keeps the record number and creation time:

```python
record = wyrm.store.latest()

if record is not None:
    print(record.id)
    print(record.created_at)
```

Most student projects will not need these extra values.

## Project information

```python
print(wyrm.info())
```

This shows information about the ByteWyrm Project connected to your key.

## Helpful printing

```python
print(wyrm)
```

prints a short description instead of exposing the API key:

```text
ByteWyrm Project (use .store to work with Store data)
```

Likewise:

```python
print(wyrm.store)
```

prints:

```text
ByteWyrm Store (use .add(), .records(), .latest(), or .schema())
```

## Errors

Starting with version 0.6.0, ByteWyrm prints a short error message to the console and lets your program
continue. This includes an unreachable domain, lost internet connection, a
timeout, a rejected key, invalid data or options, and an unexpected server
response. You do not need `try` and `except` around ByteWyrm calls.

Each method returns a predictable value when it cannot complete:

| Method | Return value on failure |
| --- | --- |
| `wyrm.store.add(...)` | `None` (saving could not be confirmed) |
| `wyrm.store.records(...)` | `[]` |
| `wyrm.store.latest()` | `None` |
| `wyrm.store.schema()` | `[]` |
| `wyrm.info()` | `{}` |

For example, this program continues even when ByteWyrm is offline:

```python
from bytewyrm import ByteWyrm


wyrm = ByteWyrm("bwk_YOUR_KEY_HERE")

record = wyrm.store.add(player="Drake", score=12500)
if record is not None:
    print("Score saved!")

for record in wyrm.store.records(sort_by="score", reverse=True, limit=10):
    print(record["player"], record["score"])

print("The game can carry on.")
```

Creating a `ByteWyrm` object does not connect to the server. Each later operation
makes one request, so the next call can work again once the connection returns.
Requests use the configured timeout (5 seconds by default); a call may pause
while waiting for the network. This does not add offline storage or a queue.
Failed saves are not automatically retried: if the connection breaks after the
server saves a record, the client cannot know whether it was saved.

Invalid constructor settings print an error and leave a disabled object whose
methods return the same fallback values. Create a new object with corrected
settings to connect. Keys are masked in error output, and messages are printed
to standard error without tracebacks. If the console is unavailable, printing
is skipped so it cannot interrupt the program.

Check for `None` before accessing a returned record, as shown above. Records
still behave like ordinary Python dictionaries: errors in your own code, such
as looking up a missing field, are not caught by the library. Ctrl+C and explicit
program exits also continue to work normally.

For existing users: public methods now print errors instead of raising them.
The `ByteWyrmError` classes remain importable for compatibility, but existing
`except ByteWyrmError` handlers should be replaced by checking return values.

## Keep your key private

A ByteWyrm key gives a program permission to use part of a Project. Do not post a real key publicly or commit one to a public repository unless your teacher has told you it is safe to do so.

ByteWyrm deliberately masks the key in its normal `str()`/`repr()` output, safety notice, and error messages. The key still has to exist in your program's memory so requests can be authenticated, so code that deliberately inspects private attributes can still retrieve it.

---

## Teacher / advanced notes

The student-facing API is intentionally based around one object:

```python
wyrm = ByteWyrm(KEY)
```

Tools live beneath it:

```python
wyrm.store
```

The key identifies the Project, so normal student code does not need a Project ID, URL, HTTP headers or database details.

The client deliberately hides HTTP requests, bearer authentication, JSON encoding/decoding, pagination cursors and server status codes. It uses only the Python standard library at runtime.

The production API defaults to:

```text
https://api.bytewyrm.dev
```

A custom `base_url` and request `timeout` are available on `ByteWyrm(...)` for development/testing.

### Development

Install the package in editable mode:

```bash
python -m pip install -e .
```

Run the test suite:

```bash
python -m unittest discover -s tests -v
```
