pyramid_di
==========
Easier service location and dependency injection for Pyramid.
Usage
-----
Define services:
```python
# app/services/__init__.py
from .my import MyService
from .another import AnotherService
```
```python
# app/services/my.py
from pyramid_di import service, RequestScopedBaseService, autowired
@service()
class MyService(RequestScopedBaseService):
def my_method(self):
return 'foobar'
```
```python
# app/services/another.py
from pyramid_di import service, RequestScopedBaseService, autowired
from .my import MyService
@service()
class AnotherService(RequestScopedBaseService):
dependency = autowired(MyService)
def another_method(self):
return self.dependency.my_method()
```
Setup when creating the Pyramid app:
```python
# Pyramid setup code:
from pyramid.config import Configurator
with Configurator() as config:
config.include('pyramid_di')
config.scan_services('app.services')
```
Use in views:
```python
from pyramid_di import autowired
from pyramid.view import view_config
from my.services import AnotherService
class MyViews:
service = autowired(AnotherService)
def __init__(self, request):
# self.request is required for autowired to work
self.request = request
@view_config(route_name='some_view', renderer='json')
def some_view(self):
return self.service.another_method() # 'foobar'
# alternatively, without class-based views:
@view_config(route_name='some_view')
def some_view(request):
service = request.find_service(AnotherService)
service.another_method() # 'foobar'
```
Mocking services for testing
----------------------------
```python3
class MockService:
def another_method(self):
return 'mocked'
def test_views():
request = DummyRequest()
my_views = MyViews(request)
my_views.service = MockService()
assert my_views.some_view() == 'mocked'
```
Development
-----------
Dev setup:
```
$ python3 -m venv venv
$ pip install -e '.[dev]'
```
Tests are run with pytest:
```
$ pytest
```
Changes
=======
0.4.2
=====
* 2023-05-28 Change from TravisCI to Github Actions, update testing matrix to cover Python 3.10 and Pyramid 2.0+.
0.4.1
=====
* 2021-03-19 The request-scoped services were not quite correct as they could have been instantiated twice
- once in the traversal-time and the other time after context was set. Now the context is forced to None
for the request-scoped services.
0.4.0
=====
* 2020-11-25 Python 3.6+ only; better test coverage, fixes for scoped services, deprecations and so forth.
0.3.dev0
========
* 2020-11 Unreleased development version
0.2.dev0
========
* 2020-11-04 Require Python 3 for cleaner code
0.1
===
* 2018-03-26 Initial release
Raw data
{
"_id": null,
"home_page": "http://github.com/tetframework/pyramid_di",
"name": "pyramid-di",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "web wsgi bfg pylons pyramid",
"author": "Antti Haapala",
"author_email": "antti.haapala@anttipatterns.com",
"download_url": "https://files.pythonhosted.org/packages/08/38/4be3f8fcfd661a72bcd3b2e32f35f25cbc3d99dac8296757c6c458e90fd9/pyramid_di-0.4.2.tar.gz",
"platform": null,
"description": "pyramid_di\n==========\n\nEasier service location and dependency injection for Pyramid.\n\nUsage\n-----\n\nDefine services:\n\n```python\n# app/services/__init__.py\n\nfrom .my import MyService\nfrom .another import AnotherService\n```\n\n```python\n# app/services/my.py\nfrom pyramid_di import service, RequestScopedBaseService, autowired\n\n@service()\nclass MyService(RequestScopedBaseService):\n def my_method(self):\n return 'foobar'\n```\n\n```python\n# app/services/another.py\nfrom pyramid_di import service, RequestScopedBaseService, autowired\nfrom .my import MyService\n\n@service()\nclass AnotherService(RequestScopedBaseService):\n dependency = autowired(MyService)\n\n def another_method(self):\n return self.dependency.my_method()\n```\n\nSetup when creating the Pyramid app:\n\n```python\n# Pyramid setup code:\nfrom pyramid.config import Configurator\n\nwith Configurator() as config:\n config.include('pyramid_di')\n config.scan_services('app.services')\n```\n\n\nUse in views:\n\n```python\nfrom pyramid_di import autowired\nfrom pyramid.view import view_config\nfrom my.services import AnotherService\n\nclass MyViews:\n service = autowired(AnotherService)\n\n def __init__(self, request):\n # self.request is required for autowired to work\n self.request = request\n\n @view_config(route_name='some_view', renderer='json')\n def some_view(self):\n return self.service.another_method() # 'foobar'\n\n# alternatively, without class-based views:\n\n@view_config(route_name='some_view')\ndef some_view(request):\n service = request.find_service(AnotherService)\n service.another_method() # 'foobar'\n```\n\nMocking services for testing\n----------------------------\n\n```python3\nclass MockService:\n def another_method(self):\n return 'mocked'\n\ndef test_views():\n request = DummyRequest()\n my_views = MyViews(request)\n my_views.service = MockService()\n assert my_views.some_view() == 'mocked'\n```\n\nDevelopment\n-----------\n\nDev setup:\n```\n$ python3 -m venv venv\n$ pip install -e '.[dev]'\n```\n\nTests are run with pytest:\n```\n$ pytest\n```\n\n\nChanges\n=======\n\n0.4.2\n=====\n\n* 2023-05-28 Change from TravisCI to Github Actions, update testing matrix to cover Python 3.10 and Pyramid 2.0+.\n\n\n0.4.1\n=====\n\n* 2021-03-19 The request-scoped services were not quite correct as they could have been instantiated twice\n - once in the traversal-time and the other time after context was set. Now the context is forced to None\n for the request-scoped services.\n\n0.4.0\n=====\n\n* 2020-11-25 Python 3.6+ only; better test coverage, fixes for scoped services, deprecations and so forth.\n\n0.3.dev0\n========\n\n* 2020-11 Unreleased development version\n\n\n0.2.dev0\n========\n\n* 2020-11-04 Require Python 3 for cleaner code\n\n0.1\n===\n\n* 2018-03-26 Initial release\n",
"bugtrack_url": null,
"license": "",
"summary": "Dependency injection stuff for Pyramid",
"version": "0.4.2",
"project_urls": {
"Homepage": "http://github.com/tetframework/pyramid_di"
},
"split_keywords": [
"web",
"wsgi",
"bfg",
"pylons",
"pyramid"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "4e669335d0afb5bb926957a66bfc2fa41848b3528f1654de544f0b7822d300d8",
"md5": "76903e4ec96fc8a023a33fca89ad1519",
"sha256": "16e88b53b36a53953a69b0ba847ab12e4f1591a7459771fd9f763eff04e99db6"
},
"downloads": -1,
"filename": "pyramid_di-0.4.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "76903e4ec96fc8a023a33fca89ad1519",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 4656,
"upload_time": "2023-06-01T20:29:41",
"upload_time_iso_8601": "2023-06-01T20:29:41.611478Z",
"url": "https://files.pythonhosted.org/packages/4e/66/9335d0afb5bb926957a66bfc2fa41848b3528f1654de544f0b7822d300d8/pyramid_di-0.4.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "08384be3f8fcfd661a72bcd3b2e32f35f25cbc3d99dac8296757c6c458e90fd9",
"md5": "c00e5b469f227183ac2dcc31835140c1",
"sha256": "3b58dd76e2c6fa06b9574afdce2cf05a24611f52988455502e7a230d0aeff14b"
},
"downloads": -1,
"filename": "pyramid_di-0.4.2.tar.gz",
"has_sig": false,
"md5_digest": "c00e5b469f227183ac2dcc31835140c1",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 5916,
"upload_time": "2023-06-01T20:29:42",
"upload_time_iso_8601": "2023-06-01T20:29:42.928214Z",
"url": "https://files.pythonhosted.org/packages/08/38/4be3f8fcfd661a72bcd3b2e32f35f25cbc3d99dac8296757c6c458e90fd9/pyramid_di-0.4.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-06-01 20:29:42",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "tetframework",
"github_project": "pyramid_di",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "pyramid-di"
}