Skip to content
Open
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
22 changes: 11 additions & 11 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,31 +12,31 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
python-version: ["3.10", "3.9", "3.8", "3.7", "3.6"]
python-version: ["3.14", "3.13", "3.12", "3.11", "3.10"]
name: "Tests: Python ${{ matrix.python-version }}"
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
- name: Install uv and set the Python version
uses: astral-sh/setup-uv@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install Requirements
run: python -m pip install -U tox
run: uv sync --dev
- name: Tests
run: python -m tox -e 'py-redis{3,4}'
run: uv run tox -e py-redis3,py-redis4,py-redis5,py-redis6,py-redis7
lint:
name: Linting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Python
uses: actions/setup-python@v2
- name: Install uv and set the Python version
uses: astral-sh/setup-uv@v6
- name: Install Requirements
run: python -m pip install -U tox
run: uv sync --dev
- name: Formatting (black)
run: python -m tox -e formatting
run: uv run tox -e formatting
- name: Typing (mypy)
run: python -m tox -e mypy
run: uv run tox -e mypy
- name: Linting (flake8)
run: python -m tox -e lint
run: uv run tox -e lint
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ venv.bak/
# mypy
.mypy_cache/

# ruff
.ruff_cache/

# other stuff
.vscode/
.DS_Store
Expand Down Expand Up @@ -131,5 +134,4 @@ node_modules/
.python-version

# Ignore lock files because this project is a library
Pipfile.lock
poetry.lock
uv.lock
29 changes: 12 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@ Simple, robust Redis configuration for Python

## Installation

```
pip install redisconfig
```
`pip install redisconfig` or `uv add redisconfig`

## Basic Usage

Expand Down Expand Up @@ -65,29 +63,26 @@ RedisConfig(host='10.0.0.1', port=6379, db=0, ssl=False, password=None)
The following things are needed to use this repository:

- [Git](https://git-scm.com)
- [Python 3.6.2+](https://www.python.org/downloads/)
- [Poetry](https://python-poetry.org/)

Once you have the prerequisites installed and have cloned the repository you can ready your development environment with `poetry install -E dev`. You should see output similar to:

```
$ poetry install -E dev
Creating virtualenv redisconfig in /tmp/redisconfig/.venv
Installing dependencies from lock file
- [Python 3.10+](https://www.python.org/downloads/)
- [uv](https://docs.astral.sh/uv/)

...

Installing the current project: redisconfig (0.1.1)
```
Once you have the prerequisites installed and have cloned the repository you can ready your development environment with `uv sync --dev`.

## Testing

```
poetry run pytest
uv run pytest
```

## Changelog

### 0.2.0

- Switch from poetry to uv
- Switch from black and flake8 to ruff
- Fix a few warnings
- Update supported Python and redis versions

### 0.1.1

- Fix typing-extensions import on Python >=3.8
Expand Down
79 changes: 52 additions & 27 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,48 +1,69 @@
[tool.poetry]
[project]
name = "redisconfig"
version = "0.1.1"
description = "Simple, robust Redis configuration for Python"
authors = ["Jeremy Carbaugh <jeremy.carbaugh@xplortechnologies.com>", "Jason Williams <jason.williams@xplortechnologies.com>"]
version = "0.2.0"
description = "Simple, robust Redis configuration"
authors = [
{name = "Jeremy Carbaugh", email = "jeremy.carbaugh@xplortechnologies.com"},
{name = "Jason Williams", email = "jason.williams@xplortechnologies.com"},
]
license = "MIT"
keywords = ["redis"]
readme = "README.md"
license = "MIT"
homepage = "https://github.com/xplor/redisconfig"
repository = "https://github.com/xplor/redisconfig"
include = ["LICENSE"]

[tool.poetry.dependencies]
python = "^3.6.2"
redis = ">=3,<5"
pytest = { version = "^6.2.5", optional = true }
black = { version = "==22.3.0", optional = true }
mypy = {version = "^0.920", optional = true}
flake8 = {version = "^4.0.1", optional = true}
dataclasses = {version = "^0.8", python = "3.6"}

[tool.poetry.extras]
test = ["pytest", "black", "mypy", "flake8"]
dev = ["pytest", "black", "mypy", "flake8"]
requires-python = ">=3.10"
dependencies = [
"redis>=3.0.0",
]


[project.urls]
Homepage = "https://github.com/xplor/redisconfig"
Repository = "https://github.com/xplor/redisconfig"


[dependency-groups]
dev = [
"mypy>=1.18.2,<2",
"pytest>=8.4.2,<9",
"ruff>=0.14.2,<1",
"tox>=4.32.0,<5",
"tox-uv>=1.29.0,<2",
]


[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
build-backend = "uv_build"
requires = ["uv_build"]


[tool.uv]
package = true


[tool.uv.build-backend]
module-name = "redisconfig"
module-root = ""
namespace = true
source-include = ["LICENSE"]


[tool.pytest.ini_options]
addopts = "-v -ra"
testpaths = "tests"


[tool.mypy]
files = "redisconfig"
ignore_missing_imports = true


[tool.tox]
legacy_tox_ini = """
[env]
FORMAT_PATHS = redisconfig tests

[tox]
envlist =
py{310,39,38,37,36}-redis{3,4}
py{314,313,312,311,310}-redis{3,4,5,6,7}
mypy
formatting
lint
Expand All @@ -54,7 +75,10 @@ extras =
test
deps =
redis3: redis>=3,<4
redis4: redis>=4.0.0b1,<5
redis4: redis>=4,<5
redis5: redis>=5,<6
redis6: redis>=6,<7
redis7: redis>=7,<8
commands =
pytest

Expand All @@ -64,9 +88,10 @@ commands =

[testenv:formatting]
commands =
black --check {[env]FORMAT_PATHS}
ruff format --check

[testenv:lint]
commands =
flake8 --ignore=E501
ruff check
"""

35 changes: 15 additions & 20 deletions redisconfig/config.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import os
from dataclasses import dataclass, replace
from typing import Optional
from typing import Final, Optional, TypedDict
from urllib.parse import urlparse, urlunparse, parse_qs

from redis import Redis

try:
from typing import Final, TypedDict
except ImportError:
from typing_extensions import Final, TypedDict

DEFAULT_ENV_VAR: Final = "REDIS_URL"
DEFAULT_HOST: Final = "127.0.0.1"
DEFAULT_PORT: Final = 6379
Expand Down Expand Up @@ -92,8 +87,8 @@ def url(self, **kwargs) -> str:
-------
str
"""
config = replace(self, **kwargs) if kwargs else self
return to_url(config)
redis_config = replace(self, **kwargs) if kwargs else self
return to_url(redis_config)


def url_from_env(var: Optional[str] = None) -> str:
Expand Down Expand Up @@ -148,13 +143,13 @@ def from_url(url: str) -> RedisConfig:
"ssl": parts.scheme == "rediss",
"password": parts.password,
}
config = RedisConfig(**kwargs)
return config
redis_config = RedisConfig(**kwargs)
return redis_config
else:
raise ValueError("Argument 'url' must be a non-empty string")


def to_url(config: RedisConfig) -> str:
def to_url(redis_config: RedisConfig) -> str:
"""
Converts a Redis configuration into a URL.

Expand All @@ -164,20 +159,20 @@ def to_url(config: RedisConfig) -> str:

Parameters
----------
config : RedisConfig
redis_config : RedisConfig
RedisConfig instance

Returns
-------
str
"""
scheme = "rediss" if config.ssl else "redis"
netloc = f"{config.host}:{config.port}"
if config.password:
netloc = f"redis:{config.password}@{netloc}"
scheme = "rediss" if redis_config.ssl else "redis"
netloc = f"{redis_config.host}:{redis_config.port}"
if redis_config.password:
netloc = f"redis:{redis_config.password}@{netloc}"
# Parts tuple consists of the following:
# scheme, netloc, path, params, query, fragment
return urlunparse((scheme, netloc, str(config.db), None, None, None))
return urlunparse((scheme, netloc, str(redis_config.db), None, None, None))


def config(url: Optional[str] = None) -> RedisConfig:
Expand All @@ -198,10 +193,10 @@ def config(url: Optional[str] = None) -> RedisConfig:
"""
if not url:
url = url_from_env()
config = from_url(url)
if not config:
redis_config = from_url(url)
if not redis_config:
raise ValueError("Invalid Redis URL or missing environment variable")
return config
return redis_config


def connection(url: Optional[str] = None, **kwargs) -> Redis:
Expand Down
Empty file removed tox.ini
Empty file.