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
23 changes: 14 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,35 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
pip install sphinx
uv sync --extra dev
uv pip install sphinx


- name: Run linting (flake8)
run: |
make lint
uv run make lint

- name: Run core tests
run: |
# Run core tests only (excluding extra modules)
python -m unittest discover -s tests -p "test_*.py" -v | grep -v "extra\." || true
uv run python -m unittest discover -s tests -p "test_*.py" -v | grep -v "extra\." || true

- name: Run tests without mypy
run: |
# Run make test but ignore mypy failures
flake8 ioc/ tests/
python -m unittest discover -s tests -p "test_*.py" 2>&1 | grep -v "extra\." || echo "Some tests may require optional dependencies"
sphinx-build -nW -b html -d docs/_build/doctrees docs docs/_build/html || true
uv run flake8 ioc/ tests/
uv run python -m unittest discover -s tests -p "test_*.py" 2>&1 | grep -v "extra\." || echo "Some tests may require optional dependencies"
uv run sphinx-build -nW -b html -d docs/_build/doctrees docs docs/_build/html || true

- name: Run tests with type checking (optional)
run: |
make test-strict || echo "Type checking found issues (this is optional)"
uv run make test-strict || echo "Type checking found issues (this is optional)"
continue-on-error: true
13 changes: 9 additions & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,21 @@ jobs:
with:
python-version: '3.11'

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
uv pip install build twine

- name: Build package
run: |
python -m build
uv run python -m build

- name: Check package
run: |
twine check dist/*
uv run twine check dist/*

15 changes: 10 additions & 5 deletions .github/workflows/test-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,27 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"

- name: Install core dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
uv sync

- name: Run core tests
run: |
python -m unittest discover -s tests/ioc_test -p "test_*.py" -v
uv run python -m unittest discover -s tests/ioc_test -p "test_*.py" -v

- name: Install dev dependencies
run: |
pip install -e ".[dev]"
uv sync --extra dev

- name: Run linting
run: |
flake8 ioc/ tests/
uv run flake8 ioc/ tests/

- name: Summary
if: always()
Expand Down
73 changes: 52 additions & 21 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,23 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
uv sync --extra dev

- name: Run flake8
run: |
flake8 ioc/ tests/
uv run flake8 ioc/ tests/

- name: Run mypy (optional)
run: |
mypy ioc/ || true
uv run mypy ioc/ || true
continue-on-error: true

test-core:
Expand All @@ -49,15 +54,20 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"

- name: Install core dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
uv sync

- name: Run core tests (excluding extras)
run: |
# Run only core tests, excluding extra package tests
python -m unittest discover -s tests -p "test_*.py" -v 2>&1 | grep -v "extra\." | tee test_output.txt
uv run python -m unittest discover -s tests -p "test_*.py" -v 2>&1 | grep -v "extra\." | tee test_output.txt

# Check results
if grep -q "FAILED" test_output.txt; then
Expand Down Expand Up @@ -86,10 +96,15 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"

- name: Install dependencies with ${{ matrix.extras }}
run: |
python -m pip install --upgrade pip
pip install -e ".[${{ matrix.extras }}]"
uv sync --extra ${{ matrix.extras }}

- name: Check if extras tests exist and dependencies are available
id: check_tests
Expand Down Expand Up @@ -132,7 +147,7 @@ jobs:
- name: Run tests for ${{ matrix.extras }}
if: steps.check_tests.outputs.should_run == 'true'
run: |
python -m unittest discover -s $(echo "${{ matrix.test_module }}" | tr '.' '/') -p "test_*.py" -v
uv run python -m unittest discover -s $(echo "${{ matrix.test_module }}" | tr '.' '/') -p "test_*.py" -v
continue-on-error: true

test-all-extras:
Expand All @@ -149,10 +164,15 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"

- name: Install all dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[flask,jinja2,redis,dev]"
uv sync --extra flask --extra jinja2 --extra redis --extra dev

- name: Create smart test runner
run: |
Expand Down Expand Up @@ -222,7 +242,7 @@ jobs:

- name: Run all tests with smart error handling
run: |
python smart_test_runner.py
uv run python smart_test_runner.py

docs:
runs-on: ubuntu-latest
Expand All @@ -235,15 +255,20 @@ jobs:
with:
python-version: '3.11'

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
pip install sphinx
uv sync
uv pip install sphinx

- name: Build documentation
run: |
sphinx-build -nW -b html -d docs/_build/doctrees docs docs/_build/html
uv run sphinx-build -nW -b html -d docs/_build/doctrees docs docs/_build/html

- name: Upload documentation artifacts
uses: actions/upload-artifact@v4
Expand All @@ -263,15 +288,21 @@ jobs:
with:
python-version: '3.11'

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true
cache-dependency-glob: "pyproject.toml"

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
uv sync
uv pip install build twine

- name: Build package
run: |
python -m build
uv run python -m build

- name: Check package
run: |
twine check dist/*
uv run twine check dist/*
48 changes: 25 additions & 23 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,40 +1,42 @@
all: build

build: clean
pip install build twine
build-install:
uv pip install build twine flake8 sphinx

build: build-install clean
rm -rf dist/
python -m build
twine check dist/*
uv run python -m build
uv run twine check dist/*

upload-prod: build
upload-prod: build-install build
export TWINE_USERNAME=__token__
bash -c 'read -s -p "Enter your Production PyPI token: " TWINE_PASSWORD; echo; export TWINE_PASSWORD; python -m twine upload dist/*'
bash -c 'read -s -p "Enter your Production PyPI token: " TWINE_PASSWORD; echo; export TWINE_PASSWORD; uv run twine upload dist/*'

upload-test: build
upload-test: build-install build
export TWINE_USERNAME=__token__
bash -c 'read -s -p "Enter your Test PyPI token: " TWINE_PASSWORD; echo; export TWINE_PASSWORD; python -m twine upload --repository testpypi dist/*'
bash -c 'read -s -p "Enter your Test PyPI token: " TWINE_PASSWORD; echo; export TWINE_PASSWORD; uv run twine upload --repository testpypi dist/*'

clean:
rm -rf build/ dist/ *.egg-info/ __pycache__/ .pytest_cache/ .mypy_cache/
find . -type f -name "*.pyc" -delete
find . -type d -name "__pycache__" -delete

test:
flake8 ioc/ tests/
python -m unittest discover -s tests -p "test_*.py"
sphinx-build -nW -b html -d docs/_build/doctrees docs docs/_build/html
test: build-install
uv run flake8 ioc/ tests/
uv run python -m unittest discover -s tests -p "test_*.py"
LC_ALL=C.UTF-8 LANG=C.UTF-8 uv run sphinx-build -nW -b html -d docs/_build/doctrees docs docs/_build/html

test-strict:
flake8 ioc/ tests/
mypy ioc/
python -m unittest discover -s tests -p "test_*.py"
sphinx-build -nW -b html -d docs/_build/doctrees docs docs/_build/html
test-strict: build-install
uv run flake8 ioc/ tests/
uv run mypy ioc/
uv run python -m unittest discover -s tests -p "test_*.py"
LC_ALL=C.UTF-8 LANG=C.UTF-8 uv run sphinx-build -nW -b html -d docs/_build/doctrees docs docs/_build/html

lint:
flake8 ioc/ tests/
lint: build-install
uv run flake8 ioc/ tests/

typecheck:
mypy ioc/
typecheck: build-install
uv run mypy ioc/

unittest:
python -m unittest discover -s tests -p "test_*.py" -v
unittest: build-install
uv run python -m unittest discover -s tests -p "test_*.py" -v
19 changes: 8 additions & 11 deletions ioc/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,16 @@
import yaml

from ioc.component import Definition, Reference, WeakReference, ContainerBuilder
import ioc.helper
import ioc.exceptions
from . import misc

from .misc import OrderedDictYAMLLoader
import ioc.misc

class Loader(object):
def fix_config(self, config: dict[str, Any]) -> 'ioc.helper.Dict':
def fix_config(self, config: dict[str, Any]) -> 'ioc.misc.Dict':
for key, value in config.items():
if isinstance(value, dict):
config[key] = self.fix_config(value)

return ioc.helper.Dict(config)
return ioc.misc.Dict(config)

class YamlLoader(Loader):
def support(self, file: str) -> bool:
Expand All @@ -42,7 +39,7 @@ def load(self, file: str, container_builder: ContainerBuilder) -> None:
content = f.read()

try:
data = yaml.load(content, OrderedDictYAMLLoader)
data = yaml.load(content, ioc.misc.OrderedDictYAMLLoader)
except yaml.scanner.ScannerError as e:
raise ioc.exceptions.LoadingError("file %s, \nerror: %s" % (file, e))

Expand Down Expand Up @@ -109,23 +106,23 @@ def load(self, file: str, container_builder: ContainerBuilder) -> None:
container_builder.add(id, definition)

def set_reference(self, value: Any) -> Any:
if misc.is_scalar(value) and value[0:1] == '@':
if ioc.misc.is_string(value) and value[0:1] == '@':
if '#' in value:
id, method = value.split("#")
return Reference(id[1:], method)

return Reference(value[1:])

if misc.is_scalar(value) and value[0:2] == '#@':
if ioc.misc.is_string(value) and value[0:2] == '#@':
return WeakReference(value[2:])

if misc.is_iterable(value):
if ioc.misc.is_iterable(value):
return self.set_references(value)

return value

def set_references(self, arguments: Union[list[Any], dict[str, Any]]) -> Union[list[Any], dict[str, Any]]:
for pos in misc.get_keys(arguments):
for pos in ioc.misc.get_keys(arguments):
arguments[pos] = self.set_reference(arguments[pos])

return arguments
2 changes: 1 addition & 1 deletion ioc/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def deepcopy(value: Any) -> Any:

return value

def is_scalar(value: Any) -> bool:
def is_string(value: Any) -> bool:
return isinstance(value, (str))

def is_iterable(value: Any) -> bool:
Expand Down
Loading