Metadata-Version: 2.4
Name: countrystatecity-countries
Version: 1.0.2
Summary: Type-safe Python package for countries, states, and cities data with 250+ countries, 5000+ states, and 151K+ cities. Features Pydantic models, lazy loading, and comprehensive geographic metadata.
Author-email: dr5hn <support@countrystatecity.in>
Maintainer-email: dr5hn <support@countrystatecity.in>
License: Open Database License (ODbL) v1.0
        
        This package uses data from the countries-states-cities-database project,
        which is licensed under the Open Database License (ODbL) v1.0.
        
        For the full text of the ODbL license, please visit:
        https://opendatacommons.org/licenses/odbl/1-0/
        
        Summary:
        You are free to:
        - Share: Copy and redistribute the database
        - Create: Produce works from the database
        - Adapt: Modify, transform and build upon the database
        
        Under the following conditions:
        - Attribute: You must attribute any public use of the database
        - Share-Alike: If you publicly use any adapted version, you must also offer 
          that adapted database under the ODbL
        - Keep open: If you redistribute the database, you must keep it open
        
Project-URL: Homepage, https://github.com/dr5hn/countrystatecity-pypi
Project-URL: Documentation, https://github.com/dr5hn/countrystatecity-pypi/tree/master/python/packages/countries
Project-URL: Repository, https://github.com/dr5hn/countrystatecity-pypi
Project-URL: Source, https://github.com/dr5hn/countrystatecity-pypi/tree/master/python/packages/countries
Project-URL: Issues, https://github.com/dr5hn/countrystatecity-pypi/issues
Project-URL: Changelog, https://github.com/dr5hn/countrystatecity-pypi/blob/master/python/packages/countries/CHANGELOG.md
Keywords: countries,states,cities,geography,geolocation,timezone,translations,iso,lazy-loading,type-hints,pydantic
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic<3.0.0,>=2.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
Requires-Dist: mypy>=1.0.0; extra == "dev"
Requires-Dist: black>=23.0.0; extra == "dev"
Requires-Dist: isort>=5.0.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Dynamic: license-file

# countrystatecity-countries

Official Python package for accessing comprehensive countries, states, and cities database with type hints and lazy loading.

[![Python Version](https://img.shields.io/pypi/pyversions/countrystatecity-countries)](https://pypi.org/project/countrystatecity-countries/)
[![License](https://img.shields.io/badge/License-ODbL--1.0-blue.svg)](LICENSE)
[![Type Checked](https://img.shields.io/badge/type--checked-mypy-blue)](https://mypy.readthedocs.io/)

## Features

- ✅ **Type-safe** with Pydantic models and mypy support
- ✅ **Lazy loading** for minimal memory footprint
- ✅ **250+ countries** with full metadata
- ✅ **5,000+ states/provinces**
- ✅ **151,000+ cities**
- ✅ **Translations** in 18+ languages
- ✅ **Timezone data** per location
- ✅ **Zero external dependencies** (except Pydantic)
- ✅ **Full test coverage** with pytest

## Installation

```bash
pip install countrystatecity-countries
```

## Quick Start

```python
from countrystatecity_countries import (
    get_countries,
    get_country_by_code,
    get_states_of_country,
    get_cities_of_state,
)

# Get all countries (lightweight)
countries = get_countries()
print(f"Total countries: {len(countries)}")

# Get specific country
usa = get_country_by_code("US")
print(f"Country: {usa.name}")
print(f"Capital: {usa.capital}")
print(f"Currency: {usa.currency_symbol} {usa.currency_name}")

# Get states (lazy loaded)
states = get_states_of_country("US")
print(f"Total states: {len(states)}")

# Get cities (lazy loaded)
cities = get_cities_of_state("US", "CA")
print(f"Cities in California: {len(cities)}")
```

## API Reference

### Countries API

#### `get_countries() -> List[Country]`

Get all countries with basic metadata.

```python
countries = get_countries()
for country in countries:
    print(f"{country.emoji} {country.name} ({country.iso2})")
```

#### `get_country_by_code(country_code: str) -> Optional[Country]`

Get country by ISO2 or ISO3 code.

```python
usa = get_country_by_code("US")  # or "USA"
print(usa.name)  # "United States"
```

#### `get_country_by_id(country_id: int) -> Optional[Country]`

Get country by ID.

```python
country = get_country_by_id(1)
```

#### `search_countries(query: str) -> List[Country]`

Search countries by name (case-insensitive).

```python
results = search_countries("united")
# Returns: [United States, United Kingdom, United Arab Emirates]
```

#### `get_countries_by_region(region: str) -> List[Country]`

Get countries in a region.

```python
asian_countries = get_countries_by_region("Asia")
```

#### `get_countries_by_subregion(subregion: str) -> List[Country]`

Get countries in a subregion.

```python
countries = get_countries_by_subregion("Southern Asia")
```

### States API

#### `get_states_of_country(country_code: str) -> List[State]`

Get all states in a country (lazy loaded).

```python
states = get_states_of_country("US")
```

#### `get_state_by_code(country_code: str, state_code: str) -> Optional[State]`

Get specific state.

```python
california = get_state_by_code("US", "CA")
print(california.name)  # "California"
```

#### `search_states(country_code: str, query: str) -> List[State]`

Search states within a country.

```python
results = search_states("US", "New")
# Returns: [New York, New Jersey, New Mexico, New Hampshire]
```

### Cities API

#### `get_cities_of_state(country_code: str, state_code: str) -> List[City]`

Get all cities in a state (lazy loaded).

```python
cities = get_cities_of_state("US", "CA")
```

#### `get_cities_of_country(country_code: str) -> List[City]`

Get all cities in a country (warning: may return a large list).

```python
cities = get_cities_of_country("US")
```

#### `search_cities(country_code: str, state_code: Optional[str], query: str) -> List[City]`

Search cities.

```python
# Search within a state
results = search_cities("US", "CA", "Los")

# Search entire country
results = search_cities("US", None, "Springfield")
```

## Data Models

### Country

```python
class Country(BaseModel):
    id: int
    name: str
    iso2: str
    iso3: str
    numeric_code: str
    phone_code: str
    capital: Optional[str]
    currency: Optional[str]
    currency_name: Optional[str]
    currency_symbol: Optional[str]
    tld: Optional[str]
    native: Optional[str]
    region: Optional[str]
    subregion: Optional[str]
    timezones: List[Dict[str, str]]
    translations: Dict[str, str]
    latitude: Optional[str]
    longitude: Optional[str]
    emoji: Optional[str]
    emojiU: Optional[str]
```

### State

```python
class State(BaseModel):
    id: int
    name: str
    country_id: int
    country_code: str
    state_code: str
    type: Optional[str]
    latitude: Optional[str]
    longitude: Optional[str]
```

### City

```python
class City(BaseModel):
    id: int
    name: str
    state_id: int
    state_code: str
    country_id: int
    country_code: str
    latitude: str
    longitude: str
    wikiDataId: Optional[str]
```

## Examples

### Flask Integration

```python
from flask import Flask, jsonify
from countrystatecity_countries import get_countries, get_states_of_country

app = Flask(__name__)

@app.route('/api/countries')
def api_countries():
    countries = get_countries()
    return jsonify([c.dict() for c in countries])

@app.route('/api/countries/<code>/states')
def api_states(code: str):
    states = get_states_of_country(code.upper())
    return jsonify([s.dict() for s in states])
```

### Django Integration

```python
from countrystatecity_countries import get_countries

def get_country_choices():
    """Generate choices for Django ChoiceField."""
    countries = get_countries()
    return [(c.iso2, c.name) for c in countries]

# In your model
from django.db import models

class UserProfile(models.Model):
    country = models.CharField(
        max_length=2,
        choices=get_country_choices()
    )
```

### Command Line Tool

```python
#!/usr/bin/env python3
import sys
from countrystatecity_countries import get_country_by_code, get_states_of_country

def main():
    if len(sys.argv) < 2:
        print("Usage: python script.py <country_code>")
        sys.exit(1)
    
    country_code = sys.argv[1]
    country = get_country_by_code(country_code)
    
    if not country:
        print(f"Country {country_code} not found")
        sys.exit(1)
    
    print(f"\n{country.emoji} {country.name}")
    print(f"Capital: {country.capital}")
    print(f"Region: {country.region}")
    print(f"Currency: {country.currency_symbol} {country.currency_name}")
    
    states = get_states_of_country(country_code)
    print(f"\nTotal states/provinces: {len(states)}")

if __name__ == "__main__":
    main()
```

## Performance

The package uses LRU caching and lazy loading for optimal performance:

- **Countries list**: <50ms load time
- **States data**: Loaded only when requested
- **Cities data**: Loaded only when requested
- **Memory footprint**: <10MB base, grows with usage

## Development

### Setup

```bash
# Clone the repository
git clone https://github.com/dr5hn/countrystatecity-pypi.git
cd countrystatecity-pypi/python/packages/countries

# Install dependencies
pip install -e ".[dev]"
```

### Running Tests

```bash
# Run all tests
pytest

# Run with coverage
pytest --cov=countrystatecity_countries --cov-report=html

# Run specific test file
pytest tests/test_countries.py
```

### Type Checking

```bash
mypy countrystatecity_countries/
```

### Code Formatting

```bash
# Format code
black countrystatecity_countries/ tests/
isort countrystatecity_countries/ tests/

# Lint code
ruff countrystatecity_countries/ tests/
```

## License

This package is licensed under the [Open Database License (ODbL-1.0)](LICENSE).

## Contributing

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

1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Run tests (`pytest`)
4. Commit your changes (`git commit -m 'Add amazing feature'`)
5. Push to the branch (`git push origin feature/amazing-feature`)
6. Open a Pull Request

## Support

- **Documentation**: [GitHub Repository](https://github.com/dr5hn/countrystatecity-pypi)
- **Issues**: [GitHub Issues](https://github.com/dr5hn/countrystatecity-pypi/issues)
- **Website**: [countrystatecity.in](https://countrystatecity.in)

## Related Packages

- `countrystatecity-timezones` (Coming soon)
- `countrystatecity-currencies` (Coming soon)
- `countrystatecity-languages` (Coming soon)
- `countrystatecity-phonecodes` (Coming soon)

## Acknowledgments

This package is part of the [countries-states-cities-database](https://github.com/dr5hn/countries-states-cities-database) project.

---

Made with ❤️ by [dr5hn](https://github.com/dr5hn)
