Skip to content

Commit

Permalink
Merge branch 'pytest' of https://github.com/adriangb/di into pytest
Browse files Browse the repository at this point in the history
  • Loading branch information
adriangb committed Dec 7, 2021
2 parents fc294b2 + 97e3a5d commit 5e5a2f7
Show file tree
Hide file tree
Showing 16 changed files with 248 additions and 196 deletions.
83 changes: 0 additions & 83 deletions .github/workflows/test-prs.yaml

This file was deleted.

47 changes: 42 additions & 5 deletions .github/workflows/release.yaml → .github/workflows/workflow.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
name: Test & Release
name: CI/CD

on:
pull_request:
push:
branches: [ main ]

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
lint:
name: Run Linters
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
Expand All @@ -14,13 +20,14 @@ jobs:
with:
python-version: '3.x'
- name: Install and configure Poetry
uses: snok/install-poetry@v1.2.0
uses: snok/install-poetry@v1.3.0
with:
version: 1.2.0a2
virtualenvs-in-project: true
- name: Lint
run: make lint
test:
name: Run Tests
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
Expand All @@ -37,7 +44,7 @@ jobs:
with:
python-version: ${{ matrix.python-version }}
- name: Install and configure Poetry
uses: snok/install-poetry@v1.2.0
uses: snok/install-poetry@v1.3.0
with:
version: 1.2.0a2
virtualenvs-in-project: true
Expand All @@ -53,7 +60,35 @@ jobs:
name: di
env_vars: OS,PYTHON
fail_ci_if_error: true
version-check:
name: Check Version Bump
if: github.ref != 'refs/heads/main'
runs-on: ubuntu-latest
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v2
with:
path: current
- uses: actions/checkout@v2
with:
ref: main
path: main
- name: Install and configure Poetry
uses: snok/install-poetry@v1.3.0
with:
version: 1.2.0a2
- name: Check version bump
run: |
cd $GITHUB_WORKSPACE/current
NEW_VERSION=$(poetry version -s)
cd $GITHUB_WORKSPACE/main
OLD_VERSION=$(poetry version -s)
python -c "from packaging import version;assert version.parse(\"${NEW_VERSION}\") > version.parse(\"${OLD_VERSION}\"), \"❌ Bad version bump detected: you must bump the version in pyproject.toml\""
python -c "print(\"✅ Version will be bumped from ${OLD_VERSION} to ${NEW_VERSION}\")"
docs:
if: github.ref == 'refs/heads/main'
concurrency: docs-branch
name: 🚀 Deploy Docs 📄
runs-on: ubuntu-latest
Expand All @@ -65,7 +100,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
- name: Install and configure Poetry
uses: snok/install-poetry@v1.2.0
uses: snok/install-poetry@v1.3.0
with:
version: 1.2.0a2
virtualenvs-in-project: true
Expand All @@ -75,6 +110,7 @@ jobs:
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
make docs-deploy
pypi:
if: github.ref == 'refs/heads/main'
name: 🚀 PyPi Release 📦
runs-on: ubuntu-latest
needs: ["test", "lint"]
Expand All @@ -83,7 +119,7 @@ jobs:
- name: Set up Python
uses: actions/setup-python@v2
- name: Install and configure Poetry
uses: snok/install-poetry@v1.2.0
uses: snok/install-poetry@v1.3.0
with:
version: 1.2.0a2
virtualenvs-in-project: true
Expand All @@ -99,3 +135,4 @@ jobs:
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ env.package_version }}
generateReleaseNotes: true
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# di: pythonic dependency injection

[![codecov](https://codecov.io/gh/adriangb/di/branch/main/graph/badge.svg?token=A0FXC8B93Y)](https://codecov.io/gh/adriangb/di)
![Test & Release](https://github.com/adriangb/di/actions/workflows/release.yaml/badge.svg)
![Workflow](https://github.com/adriangb/di/actions/workflows/workflow.yaml/badge.svg)

⚠️ This project is a WIP. Until there is a 1.X.Y release, expect breaking changes. ⚠️

Expand Down
5 changes: 0 additions & 5 deletions di/_utils/task.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
from __future__ import annotations

import threading
from contextlib import AsyncExitStack, ExitStack, asynccontextmanager, contextmanager
from typing import (
Any,
Deque,
Dict,
Generator,
Iterable,
Expand Down Expand Up @@ -44,13 +42,10 @@ def __init__(
self.stacks = stacks
self.results = results
self.toplogical_sorter = toplogical_sorter
self.lock = threading.Lock()


DependencyType = TypeVar("DependencyType")

TaskQueue = Deque[Optional[ExecutorTask]]


def gather_new_tasks(
state: ExecutionState,
Expand Down
9 changes: 3 additions & 6 deletions di/api/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ class DependantBase(Generic[DependencyType], metaclass=abc.ABCMeta):
"""A dependant is an object that can provide the container with:
- A hash, to compare itself against other dependants
- A scope
- A callable that can be used to assemble itself
- The dependants that correspond to the keyword arguments of that callable
- A callable who's returned value is the dependency
"""

__slots__ = ("call", "scope", "share")
Expand All @@ -42,7 +41,7 @@ def __eq__(self, o: object) -> bool:
If this returns `True`, the two dependencies are considered the same and
`di` will pick one to subsitute for the other.
Note that using the same dependenyc in two different scopes is prohibited,
Note that using the same dependency in two different scopes is prohibited,
so if this returns `True` and `self.scope != o.scope` `di` will raise a SolvingError.
"""
pass # pragma: no cover
Expand All @@ -61,9 +60,7 @@ def register_parameter(
"""Called by the parent so that us / this / the child can register
the parameter it is attached to.
It is *required* that this method register a non None `call` method,
if one is not already present.
That is, after this is run, self.call should not be None.
If this is an autowired Dependant, this can be used to register self.call.
This can also be used for recording type annotations or parameter names.
Expand Down
38 changes: 22 additions & 16 deletions di/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@
from di.exceptions import SolvingError
from di.executors import DefaultExecutor

Dependency = Any

_Task = Union[AsyncTask, SyncTask]

_DependantTaskDag = Dict[_Task, Set[_Task]]
Expand All @@ -49,19 +47,25 @@
_nullcontext = nullcontext(None)


__all__ = ("BaseContainer", "Container", "ContainerState")
__all__ = ("BaseContainer", "Container")


class _ContainerCommon:
__slots__ = ("_executor", "_execution_scope", "_binds", "_dep_registry")
__slots__ = ("_executor", "_execution_scope", "_binds")

_executor: Union[SyncExecutor, AsyncExecutor]
_execution_scope: Scope
_binds: Dict[DependencyProvider, DependantBase[Any]]
_dep_registry: Dict[DependantBase[Any], int]

def __init__(self) -> None:
self._dep_registry = {}
def __init__(
self,
executor: Union[SyncExecutor, AsyncExecutor],
execution_scope: Scope,
binds: Optional[Dict[DependencyProvider, DependantBase[Any]]],
):
self._executor = executor
self._execution_scope = execution_scope
self._binds = binds or {}

@property
def binds(self) -> Mapping[DependencyProvider, DependantBase[Any]]:
Expand Down Expand Up @@ -225,7 +229,7 @@ def _build_tasks(
positional: List[_Task] = []
keyword: Dict[str, _Task] = {}
for param in dag[dep]:
if param.parameter is not None:
if param.parameter is not None and param.dependency.call is not None:
task = tasks[param.dependency]
# prefer positional arguments since those can be unpacked from a generator
# saving generation of an intermediate dict
Expand Down Expand Up @@ -339,11 +343,12 @@ def __init__(
_state: Optional[ContainerState] = None,
_binds: Optional[Dict[DependencyProvider, DependantBase[Any]]] = None,
) -> None:
super().__init__()
self._executor = executor or DefaultExecutor()
self._execution_scope = execution_scope
super().__init__(
executor=executor or DefaultExecutor(),
execution_scope=execution_scope,
binds=_binds,
)
self.__state = _state or ContainerState.initialize()
self._binds = _binds or {}

@property
def binds(self) -> Mapping[DependencyProvider, DependantBase[Any]]:
Expand Down Expand Up @@ -433,15 +438,16 @@ def __init__(
_context: Optional[contextvars.ContextVar[ContainerState]] = None,
_binds: Optional[Dict[DependencyProvider, DependantBase[Any]]] = None,
) -> None:
super().__init__()
super().__init__(
executor=executor or DefaultExecutor(),
execution_scope=execution_scope,
binds=_binds,
)
if _context is None:
self._context = contextvars.ContextVar(f"{self}._context")
self._context.set(ContainerState.initialize())
else:
self._context = _context
self._execution_scope = execution_scope
self._executor = executor or DefaultExecutor()
self._binds = _binds or {}

@property
def _state(self) -> ContainerState:
Expand Down

0 comments on commit 5e5a2f7

Please sign in to comment.