Metadata-Version: 2.4
Name: cloud-proxy-hub
Version: 0.1.0
Summary: Multi-provider proxy pool with geo/performance validation (Proxy-Seller, SmartProxy, pingnetwork).
License: Proprietary
Requires-Python: >=3.11
Requires-Dist: aiohttp>=3.9
Requires-Dist: countryinfo>=0.1.2
Requires-Dist: pycountry>=23.12
Requires-Dist: requests>=2.31
Description-Content-Type: text/markdown

# cloud-proxy-hub

Multi-provider proxy pool with geo and performance validation. Wraps
Proxy-Seller (datacenter + residential), SmartProxy (residential) and
pingnetwork.io (residential, secondary) behind a single class:

```python
from cloud_proxy_hub import ProxyHub, ProxyHubConfig

config = ProxyHubConfig(
    # provider credentials — or leave unset and export the same-named
    # env vars (PROXY_API_KEY, SMARTPROXY_LOGIN, SMARTPROXY_PASS, ...)
    proxy_api_key="...",
    proxy_seller_res_login="...",
    proxy_seller_res_pass="...",
    proxy_pingnetwork_res_login="...",
    proxy_pingnetwork_res_pass="...",
    smartproxy_login="...",
    smartproxy_pass="...",

    # extra static datacenter proxies per ISO-3166 alpha-2 country code
    # (used to be hardcoded in the library — now it's yours to supply)
    additional_datacenter_proxies={
        "ZA": ["http://user:pass@host:port", ...],
        "BR": ["http://user:pass@host:port", ...],
    },

    # which providers are active, and in what order (default shown here —
    # SmartProxy is OFF by default; add it back with any key/priority to
    # re-enable, e.g. provider_priority={"Proxy-Seller": 1, "SmartProxy": 2, "pingnetwork": 3}).
    # Drop "pingnetwork" too if you don't want the pingnetwork.io fallback.
    provider_priority={"Proxy-Seller": 1, "pingnetwork": 2},

    # tuning knobs, passed the same way at startup — shown with their defaults
    proxy_seller_weight=90,     # % of residential traffic via proxy-seller.com
    pingnetwork_weight=10,      # % via pingnetwork.io
    smartproxy_retries=5,
    smartproxy_backoff_factor=1.5,
    smartproxy_timeout=10,
)

proxy_hub = ProxyHub(validate_proxies=True, config=config)

proxy = proxy_hub.provide_valid_proxies(
    proxy_type="residential",
    country_code="DE",
    neighbor_geo_enable=False,
    reverse_proxy=is_last_attempt,  # force pingnetwork.io on the last retry
)
```

Everything you need to tune lives on `ProxyHubConfig` — construct it once,
pass it to `ProxyHub`, and call `provide_valid_proxies()`. No need to reach
into `cloud_proxy_hub.providers` / `cloud_proxy_hub.geo` /
`cloud_proxy_hub.performance` unless you're extending the library itself.

## Why a config object

The original script read paths and provider credentials from an internal
`src.settings` module, and had a dict of extra datacenter proxies (with real
login/password pairs) hardcoded in the class body. Both made the code
impossible to hand to anyone outside that one codebase, and unsafe to publish
anywhere public. `ProxyHubConfig` replaces both: every credential is either
passed explicitly or read from an environment variable of the same name, and
`additional_datacenter_proxies` is supplied by the caller instead of baked
into the source.

## Install

```bash
pip install cloud-proxy-hub
```

Published on public PyPI. No credentials are embedded anywhere in the
source — every secret is supplied by the consumer via `ProxyHubConfig` or
environment variables, as shown above.

### Publishing a new version

```bash
python -m pip install --upgrade build twine
python -m build          # produces dist/*.whl and dist/*.tar.gz
python -m twine upload dist/*
```

Requires a PyPI account with 2FA enabled and an API token (`__token__` as
username, the token as password).

## Migrating from the old `updated_proxy_hub.py`

- `from src.settings import settings` → build a `ProxyHubConfig(...)` once
  (from your own private settings) and pass it to `ProxyHub(config=...)`.
- The hardcoded `ADDITIONAL_DATACENTER_PROXIES` dict → pass it as
  `ProxyHubConfig(additional_datacenter_proxies={...})`.
- The hardcoded `proxy_priority` module dict (which providers run, and in
  what order) → `ProxyHubConfig(provider_priority={...})`. Default is
  `{"Proxy-Seller": 1, "pingnetwork": 2}` — SmartProxy is off by default
  (still fully implemented in the library, just excluded from the default
  dict); add an `"SmartProxy": <n>` key to turn it back on, or drop
  `"pingnetwork"` to disable that too. Same membership check for all three —
  drop any key to disable that provider at startup instead of commenting it
  out in library source. **Caveat:** `"pingnetwork"` only runs from inside
  Proxy-Seller's residential lookup, so dropping `"Proxy-Seller"` disables
  pingnetwork too even if `"pingnetwork"` is still in the dict — see
  `USAGE.md` for details.
- The hardcoded 90/10 provider split → `proxy_seller_weight` /
  `pingnetwork_weight` on `ProxyHubConfig` (defaults are still 90/10).
- SmartProxy's hardcoded `retries=5, backoff_factor=1.5, timeout=10` →
  `smartproxy_retries` / `smartproxy_backoff_factor` / `smartproxy_timeout`
  on `ProxyHubConfig` (same defaults).
- `ProxyHub(validate_proxies=...)` and `provide_valid_proxies(...)` keep
  their original signature and behavior.
