Metadata-Version: 2.4
Name: smart_session
Version: 2.8
Summary: Sync HTTP session wrapper with cache modes, response validation, introspection, and Mongo/network helpers
Author-email: dharmik.vadher@xbyte.io
Maintainer-email: dharmik.vadher@xbyte.io
License-Expression: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests
Requires-Dist: loguru
Dynamic: license-file

# smart_session

`smart_session` adds disk-backed page saves to sync HTTP clients with cache modes, response validation, runtime introspection, and bundled Mongo/network helper utilities.

## Install

```bash
pip install smart_session
```

Prebuilt wheels are intended for Windows x64 CPython 3.10+.

## Import note

The package root currently exports the Mongo helper module eagerly. In the current source layout that means a top-level import also expects:

- `pymongo`
- `python-dotenv`
- a `config.py` file beside your entry script with `FEED`, `MONGO_URI`, and `MONGO_DB`

If those pieces are missing, `import smart_session` will fail before you create a session wrapper.

## Global library patching

Call `smart_pagesave()` once near the top of your process to patch supported HTTP libraries globally:

```python
import smart_session

smart_session.smart_pagesave()

import requests

resp = requests.get(
    "https://example.com/data.json",
    mode="smart",
    filepath="cache/data.json",
    conditions=[lambda r: r.status_code == 200],
)
```

After setup, normal outbound calls from supported sync libraries accept the same extra kwargs:

- `mode`
- `filepath`
- `conditions`

Supported global patches:

- `requests`
- `cloudscraper`
- `curl_cffi.requests`
- `httpx.Client`
- `tls_client.Session`

`smart_pagesave()` patches library classes directly, so it also affects sessions created before setup when their methods are resolved from the class.

Runtime signature metadata is updated for patched methods, so tools based on `inspect.signature()` can show `mode`, `filepath`, and `conditions`. Static IDE autocomplete for raw third-party calls such as `requests.get()` still depends on that library's own type stubs, so full static hints are guaranteed only for `smart_session` exports and the typed `session_wrapper` surface.

## Session wrapper

Wrap either a session class or an already-created sync session object:

```python
import requests
from smart_session import session_wrapper

sess = session_wrapper(requests.Session)
resp = sess.get(
    "https://example.com/data.json",
    mode="smart",
    filepath="cache/data.json",
    conditions=[lambda r: r.status_code == 200],
)
```

The wrapper supports libraries that expose `.request()` or `.execute_request()`, including `requests`, `curl_cffi`, `cloudscraper`, `tls_client`, `httpx.Client`, and compatible custom clients.

## What changes and what stays the same

- Without `mode`, requests pass straight through to the wrapped session.
- If you pass `filepath` without `mode`, the wrapper defaults to `mode="fresh"`.
- All original session attributes and methods remain available through the wrapper.
- `sess.docs` prints instance-specific usage help.
- `sess.supported` prints the wrapped session's detected verbs, methods, and attributes.
- `debug_mode=True` prints compact request summaries for saves and cache loads.
- Async sessions are not supported.

## Cache modes

Modes are case-insensitive.

| Mode | Binary mode | Behavior |
|------|-------------|----------|
| `smart` | `smartb` | Return cache if present, otherwise fetch and save |
| `fresh` | `freshb` | Always fetch live data and overwrite the cache |
| `offline` | `offlineb` | Read from cache only and raise if the file is missing |

Supported cache file extensions:

`html`, `json`, `txt`, `xml`, `pdf`, `png`, `jpg`, `jpeg`, `gif`, `csv`, `bin`

## Conditions

`conditions` is a list of callables that run only on live responses before the cache is written.

```python
resp = sess.post(
    "https://example.com/api",
    json={"page": 1},
    mode="fresh",
    filepath="cache/api.json",
    conditions=[
        lambda r: r.status_code == 200,
        lambda r: len(r.content) > 100,
        lambda r: "error" not in r.text.lower(),
    ],
)
```

If any condition fails, a `ValueError` is raised and nothing is written to disk.

## Cached response behavior

- Live requests return the wrapped client's native response object.
- Cache hits and `offline` replays return a synthesized `requests.Response`.
- Replayed responses are rebuilt from disk content with `status_code = 200`.
- Text cache hits are decoded as UTF-8.
- JSON text cache hits also expose `resp.json()`.

## Public API

```python
from smart_session import (
    session_wrapper,
    smart_pagesave,
    info,
    insert_to_db,
    get_local_ip,
    mount_path,
)
```

- `session_wrapper` is the exported `SmartSession` wrapper class.
- `smart_pagesave()` globally patches supported sync HTTP libraries.
- `info()` prints package-level help.
- `insert_to_db()` inserts cleaned records into MongoDB.
- `get_local_ip()` returns a cached private LAN IP when available.
- `mount_path()` mounts a UNC share with `net use`.

## Mongo helper utilities

### `insert_to_db`

`insert_to_db(data, output_col, input_field, page_save, feed=FEED, **kwargs)` accepts a single dict or a list of dicts.

Behavior:

- `output_col` can be a `pymongo` collection or a string collection suffix.
- String collections are expanded to `f"{feed}_{output_col}"`.
- Flat fields are cleaned and stored as strings.
- Nested dicts and lists of dicts are inserted recursively into child collections.
- `page_save` must be a relative filename and must match `input_field`.
- `_id` is generated deterministically from the cleaned payload.
- `_datetime` and `_ip` are added automatically.
- Duplicate `_id` inserts are logged and treated as success.

Example:

```python
from smart_session import insert_to_db

insert_to_db(
    {"parcel": "123", "owner": "Jane Doe"},
    output_col="properties",
    input_field="123",
    page_save="123.html",
    source="county_site",
)
```

### `get_local_ip`

Returns the first private IPv4 address found on the host, or `127.0.0.1` as a fallback. The result is cached for the process lifetime.

### `mount_path`

Mounts a UNC share by running Windows `net use` against the share root:

```python
from smart_session import mount_path

mount_path(r"\\server\share\folder", user="admin", pwd="secret")
```

## Introspection helpers

```python
from smart_session import info

info()            # package overview
sess.docs         # detailed session wrapper help
sess.supported    # detected verbs, methods, and attributes
```

## Contact

Dharmik Vadher  
dharmik.vadher@xbyte.io
