Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Unreleased entry.
- Rust checks, regression tests, pedantic Clippy, and Python API tests on Python 3.10 and 3.15.

### Changed
- **Breaking:** Rename the Python distribution, import module, and Rust crate to `proxyprobe`; update dependencies and imports from `rsloop-rust-proxychecker` / `rsloop_rust_proxychecker`. Function signatures and result dictionaries remain unchanged.
- Split the extension implementation into API, configuration, checker, worker, and stream modules without changing the public Python API.
- Enable PyO3 extension-module mode through Maturin so Rust unit tests can embed Python normally.
- Update the Rust `rsloop` dependency to 0.1.56 and `wreq` to the stable 0.16.1 series.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
[package]
name = "rsloop-rust-proxychecker"
name = "proxyprobe"
version = "0.1.0"
edition = "2021"
rust-version = "1.98"
publish = false

[lib]
name = "rsloop_rust_proxychecker"
name = "proxyprobe"
crate-type = ["cdylib"]

[dependencies]
Expand Down
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Rust Proxy Checker Example
# proxyprobe

[![CI](https://github.com/RustedBytes/proxychecker/actions/workflows/ci.yml/badge.svg)](https://github.com/RustedBytes/proxychecker/actions/workflows/ci.yml)

This example is a standalone PyO3 extension built on top of `rsloop::rust_async`
`proxyprobe` is a standalone PyO3 extension built on top of `rsloop::rust_async`
that checks many proxies concurrently and yields Python-friendly result objects
as soon as each proxy finishes.

Expand All @@ -12,11 +12,20 @@ It uses:
- `wreq` for the HTTP client and proxy support
- a dedicated Tokio runtime inside the Rust worker because `wreq` runs on Tokio

## Migration

The distribution and import name are now `proxyprobe` (previously
`rsloop-rust-proxychecker` and `rsloop_rust_proxychecker`). Update your dependency
and imports; function arguments and result dictionaries are unchanged.

## Python API

```python
import proxyprobe


async def main():
stream = await rsloop_rust_proxychecker.check_proxies(
stream = await proxyprobe.check_proxies(
proxies,
user_agent="my-app/1.0",
check_url="https://httpbin.org/post",
Expand Down Expand Up @@ -67,6 +76,7 @@ dictionary in a dataclass while still processing results as they arrive:

```python
from dataclasses import dataclass
import proxyprobe


@dataclass(slots=True)
Expand Down Expand Up @@ -97,7 +107,7 @@ class ProxyCheckResult:
successful: list[ProxyCheckResult] = []
failed: list[ProxyCheckResult] = []

stream = await rsloop_rust_proxychecker.check_proxies(proxies, user_agent="my-app/1.0")
stream = await proxyprobe.check_proxies(proxies, user_agent="my-app/1.0")
async for result in stream:
proxy_result = ProxyCheckResult.from_result(result)
if proxy_result.ok:
Expand Down
6 changes: 3 additions & 3 deletions demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dataclasses import dataclass

import rsloop
import rsloop_rust_proxychecker
import proxyprobe


@dataclass(slots=True)
Expand Down Expand Up @@ -40,9 +40,9 @@ def read_proxies_from_file(file_path: str) -> list[str]:

async def main() -> None:
proxies = read_proxies_from_file("proxies.txt")
stream = await rsloop_rust_proxychecker.check_proxies(
stream = await proxyprobe.check_proxies(
proxies,
user_agent="rsloop-rust-proxychecker-demo/0.1",
user_agent="proxyprobe-demo/0.1",
timeout_ms=3_000,
return_response=True,
)
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["maturin>=1.7,<2"]
build-backend = "maturin"

[project]
name = "rsloop-rust-proxychecker"
name = "proxyprobe"
version = "0.1.0"
requires-python = ">=3.10"
dependencies = [
Expand All @@ -12,7 +12,7 @@ dependencies = [

[tool.maturin]
features = ["pyo3/extension-module"]
module-name = "rsloop_rust_proxychecker"
module-name = "proxyprobe"

[dependency-groups]
dev = [
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use pyo3::prelude::*;

/// Register the existing Python function and asynchronous stream class.
#[pymodule(gil_used = false)]
fn rsloop_rust_proxychecker(m: &Bound<'_, PyModule>) -> PyResult<()> {
fn proxyprobe(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_class::<stream::PyProxyCheckStream>()?;
m.add_function(wrap_pyfunction!(api::check_proxies, m)?)?;
Ok(())
Expand Down
2 changes: 1 addition & 1 deletion src/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use pyo3::types::PyDict;
use crate::checker::ProxyOutcome;

/// Asynchronous iterator backed by a Python queue populated from a Rust worker.
#[pyclass(module = "rsloop_rust_proxychecker")]
#[pyclass(module = "proxyprobe")]
pub(crate) struct PyProxyCheckStream {
pub(crate) queue: Py<PyAny>,
}
Expand Down
8 changes: 7 additions & 1 deletion tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import asyncio
from importlib.metadata import metadata
from contextlib import contextmanager
import threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
import unittest

import rsloop_rust_proxychecker as checker
import proxyprobe as checker


class ApiTests(unittest.TestCase):
def test_package_identity(self):
self.assertEqual(metadata("proxyprobe")["Name"], "proxyprobe")
self.assertEqual(checker.__name__, "proxyprobe")
self.assertEqual(checker.PyProxyCheckStream.__module__, "proxyprobe")

def test_empty_input_ends_stream(self):
async def run():
stream = await checker.check_proxies([], user_agent="test")
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.