Metadata-Version: 2.4
Name: jsurl
Version: 0.1.3
Summary: Javascript-like URL parser for Python
Project-URL: Homepage, https://github.com/frodo821/jsurl
Project-URL: Repository, https://github.com/frodo821/jsurl
Author-email: frodo821 <sakaic2003@gmail.com>
License: MIT License
        
        Copyright (c) 2025 frodo821
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# jsurl

A Python implementation of the JavaScript URL and URLSearchParams APIs, bringing familiar web development patterns to Python.

## Features

- **JavaScript-compatible API**: Use the same URL manipulation patterns you know from JavaScript
- **Full URL parsing**: Support for all URL components including protocol, hostname, port, pathname, search, and hash
- **URLSearchParams**: Complete implementation of the URLSearchParams interface for query string manipulation
- **Type hints**: Full type annotation support for better IDE integration
- **Immutable-friendly**: Clean API design that supports both mutable and immutable usage patterns
- **Pure Python**: No external dependencies, pure Python implementation for maximum compatibility

## Installation

```bash
pip install jsurl
```

## Quick Start

### Basic URL Parsing

```python
from jsurl import URL

# Parse a URL
url = URL("https://example.com:8080/path?query=value#section")

print(url.protocol)  # "https:"
print(url.hostname)  # "example.com"
print(url.port)      # "8080"
print(url.pathname)  # "/path"
print(url.search)    # "?query=value"
print(url.hash)      # "#section"
```

### URL Manipulation

```python
from jsurl import URL

url = URL("https://example.com/api")

# Modify components
url.pathname = "/v2/users"
url.search = "?limit=10&page=1"

print(url.href)  # "https://example.com/v2/users?limit=10&page=1"

# Path joining with / operator
api_url = URL("https://api.example.com/v1")
users_url = api_url / "users"
user_url = users_url / "123"

print(user_url.href)  # "https://api.example.com/v1/users/123"
```

### Working with Query Parameters

```python
from jsurl import URL, URLSearchParams

# Using URLSearchParams directly
params = URLSearchParams.from_string("name=John&age=30&city=Tokyo")

print(params.get("name"))     # "John"
print(params.get_all("tag"))  # []

params.append("tag", "python")
params.append("tag", "web")
print(params.get_all("tag"))  # ["python", "web"]

# Using search_params on URL
url = URL("https://example.com/search")
url.search_params.set("q", "python url parsing")
url.search_params.set("limit", "50")

print(url.href)  # "https://example.com/search?q=python%20url%20parsing&limit=50"
```

### Authentication URLs

```python
from jsurl import URL

url = URL("https://user:password@api.example.com/secure")

print(url.username)  # "user"
print(url.password)  # "password"
print(url.host)      # "api.example.com"
print(url.origin)    # "https://api.example.com"
```

### IPv6 Support

```python
from jsurl import URL

# IPv6 addresses are properly handled
url = URL("https://[2001:db8::1]:8080/path")

print(url.hostname)  # "[2001:db8::1]"
print(url.port)      # "8080"
print(url.host)      # "[2001:db8::1]:8080"
```

## API Reference

### URL Class

#### Properties

- `protocol`: URL scheme (e.g., "https:")
- `username`: Username for authentication
- `password`: Password for authentication  
- `hostname`: Domain name or IP address
- `port`: Port number as string
- `pathname`: Path portion of URL
- `search`: Query string including "?"
- `hash`: Fragment identifier including "#"
- `search_params`: URLSearchParams instance for query manipulation
- `host`: hostname:port combination
- `origin`: protocol + "//" + host
- `href`: Complete URL string

#### Methods

- `URL(url)`: Constructor accepting string or URL instance
- `url / path`: Join path components using `/` operator

### URLSearchParams Class

#### Methods

- `URLSearchParams.from_string(query)`: Create from query string
- `get(key)`: Get first value for key
- `get_all(key)`: Get all values for key as list
- `set(key, value)`: Set single value (replaces existing)
- `append(key, value)`: Add value (preserves existing)
- `delete(key)`: Remove all values for key
- `key in params`: Check if key exists
- `params[key]`: Get all values (same as get_all)
- `params[key] = value`: Set value (same as set)

## Use Cases

### Web Scraping

```python
from jsurl import URL

base_url = URL("https://api.example.com/v1")

# Build API endpoints
users_endpoint = base_url / "users"
users_endpoint.search_params.set("page", "1")
users_endpoint.search_params.set("limit", "100")

response = requests.get(str(users_endpoint))
```

### Configuration Management

```python
from jsurl import URL

# Parse database URLs
db_url = URL("postgresql://user:pass@localhost:5432/mydb")

DATABASE_CONFIG = {
    'host': db_url.hostname,
    'port': int(db_url.port) if db_url.port else 5432,
    'username': db_url.username,
    'password': db_url.password,
    'database': db_url.pathname.lstrip('/')
}
```

### URL Validation and Normalization

```python
from jsurl import URL

def normalize_api_url(url_string):
    """Normalize API URL format"""
    url = URL(url_string)
    
    # Ensure HTTPS
    if url.protocol == "http:":
        url.protocol = "https"
    
    # Remove default ports
    if url.port == "443" and url.protocol == "https:":
        url.port = None
    elif url.port == "80" and url.protocol == "http:":
        url.port = None
    
    # Ensure trailing slash for API endpoints
    if not url.pathname.endswith('/'):
        url.pathname += '/'
    
    return str(url)
```

## Why jsurl?

If you're coming from JavaScript/TypeScript development, you'll feel right at home with `jsurl`. Instead of learning Python-specific URL libraries, you can use the same patterns you already know:

```python
# Instead of urllib.parse
from urllib.parse import urlparse, parse_qs
parsed = urlparse(url_string)
query_params = parse_qs(parsed.query)

# Use familiar JavaScript patterns
from jsurl import URL
url = URL(url_string)
url.search_params.get('param_name')
```

## Requirements

- Python 3.10 or higher
- No external dependencies

## License

MIT License - see LICENSE file for details.

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.
