Skip to content

Commit 7954d1c

Browse files
committed
a bunch of stuff which may be wrong
0 parents  commit 7954d1c

10 files changed

Lines changed: 468 additions & 0 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
_trial_temp
2+
*.pyc
3+
build/
4+
dist/

.travis.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
sudo: false
2+
3+
language: python
4+
python:
5+
- "2.7"
6+
- "2.6"
7+
- "3.4"
8+
- "pypy"
9+
install:
10+
- pip install -r dev-requirements.txt
11+
- pip install six
12+
- pip install 'characteristic>=14.0.0'
13+
- pip install sphinx
14+
- pip install effect
15+
script:
16+
- make lint
17+
- py.test
18+
- make doc
19+
20+
notifications:
21+
irc:
22+
channels:
23+
- "chat.freenode.net#python-effect"
24+
skip_join: true
25+
use_notice: true
26+
template:
27+
- "%{repository} %{branch} %{commit} by %{author}: %{message} %{build_url}"

Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
lint:
2+
flake8 --ignore=E131,E731,W503 txeffect/ examples/
3+
4+
build-dist:
5+
rm -rf dist
6+
python setup.py sdist bdist_wheel
7+
8+
upload-dist:
9+
twine upload dist/*
10+
echo
11+
echo "Don't forget to add a git tag."
12+
echo "And don't forget to bump the version in setup.py and docs/source/conf.py."
13+
14+
doc:
15+
rm -rf docs/build
16+
rm -rf docs/source/api
17+
cd docs; sphinx-apidoc -e -o source/api ../txeffect ../setup.py ../examples ../txeffect/test_*.py
18+
cd docs; PYTHONPATH=..:$(PYTHONPATH) sphinx-build -W -b html -d build/doctrees source build/html

README.rst

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
txEffect
2+
========
3+
4+
.. image:: https://travis-ci.org/radix/txeffect.svg?branch=master
5+
:target: https://travis-ci.org/radix/txeffect
6+
7+
`Effect`_ is a library for helping you write purely functional code by
8+
isolating the effects (that is, IO or state manipulation) in your code.
9+
Documentation is available at https://effect.readthedocs.org/.
10+
11+
.. _`Effect`: https://github.com/radix/effect
12+
13+
txEffect is a small library for integrating Twisted and Effect, mostly
14+
around Deferred<->Effect interoperation. Documentation is available at
15+
https://txeffect.readthedocs.org/
16+
17+
Example
18+
=======
19+
20+
TBD
21+
22+
23+
Thanks
24+
======
25+
26+
Thanks to Rackspace for allowing me to work on this project, and having an
27+
*excellent* `open source employee contribution policy`_
28+
29+
.. _`open source employee contribution policy`: https://www.rackspace.com/blog/rackspaces-policy-on-contributing-to-open-source/
30+
31+
32+
IRC
33+
===
34+
35+
There is a ``#python-effect`` IRC channel on irc.freenode.net.
36+
37+
License
38+
=======
39+
40+
txEffect is licensed under the MIT license:
41+
42+
Copyright (C) 2014 Christopher Armstrong
43+
44+
Permission is hereby granted, free of charge, to any person obtaining a copy of
45+
this software and associated documentation files (the "Software"), to deal in
46+
the Software without restriction, including without limitation the rights to
47+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
48+
the Software, and to permit persons to whom the Software is furnished to do so,
49+
subject to the following conditions:
50+
51+
The above copyright notice and this permission notice shall be included in all
52+
copies or substantial portions of the Software.
53+
54+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
55+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
56+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
57+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
58+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
59+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

dev-requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
testtools
2+
flake8
3+
pytest

rtd-requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# requirements for Read The Docs
2+
alabaster
3+
twisted

setup.cfg

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[bdist_wheel]
2+
# This flag says that the code is written to work on both Python 2 and Python
3+
# 3. If at all possible, it is good practice to do this. If you cannot, you
4+
# will need to generate wheels for each Python version that you support.
5+
universal=1

setup.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env python
2+
import setuptools
3+
4+
setuptools.setup(
5+
name="txeffect",
6+
version="0.1a1",
7+
description="Effect/Twisted integration",
8+
long_description=open('README.rst').read(),
9+
url="http://github.com/radix/txeffect/",
10+
author="Christopher Armstrong",
11+
license="MIT",
12+
classifiers=[
13+
'Development Status :: 3 - Alpha',
14+
'License :: OSI Approved :: MIT License',
15+
'Programming Language :: Python :: 2',
16+
'Programming Language :: Python :: 3',
17+
],
18+
packages=['effect'],
19+
install_requires=['effect', 'twisted', 'six', 'characteristic>=14.0.0'],
20+
)

txeffect/__init__.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# -*- test-case-name: effect.test_twisted -*-
2+
3+
"""
4+
Twisted integration for the Effect library.
5+
6+
This is largely concerned with bridging the gap between Effects and Deferreds,
7+
and also implementing Twisted-specific performers for standard Intents.
8+
9+
The most important functions here are :func:`perform`,
10+
:func:`make_twisted_dispatcher`, and :func:`deferred_performer`.
11+
12+
Note that the core effect library does *not* depend on Twisted, but this module
13+
does.
14+
"""
15+
16+
from __future__ import absolute_import
17+
18+
from functools import partial
19+
import sys
20+
21+
from twisted.internet.defer import Deferred
22+
from twisted.python.failure import Failure
23+
from twisted.internet.task import deferLater
24+
25+
from ._intents import Delay, ParallelEffects
26+
from ._base import perform as base_perform
27+
from ._dispatcher import TypeDispatcher
28+
from ._utils import wraps
29+
from .async import perform_parallel_async
30+
31+
32+
def deferred_to_box(d, box):
33+
"""
34+
Make a Deferred pass its success or fail events on to the given box.
35+
"""
36+
d.addCallbacks(box.succeed, lambda f: box.fail((f.type, f.value, f.tb)))
37+
38+
39+
def make_twisted_dispatcher(reactor):
40+
"""
41+
Create a dispatcher that knows how to perform certain built-in Intents
42+
with Twisted-specific implementations.
43+
"""
44+
return TypeDispatcher({
45+
ParallelEffects: perform_parallel_async,
46+
Delay: deferred_performer(partial(perform_delay, reactor)),
47+
})
48+
49+
50+
def deferred_performer(f):
51+
"""
52+
A decorator for performers that return Deferreds.
53+
54+
The function being decorated is expected to take a dispatcher and an intent
55+
(and not a box), and may return a Deferred. The wrapper function
56+
that this decorator returns will accept a dispatcher, an intent, and a box
57+
(conforming to the performer interface). The wrapper deals with
58+
putting the Deferred's result into the box.
59+
60+
Example::
61+
62+
@deferred_performer
63+
def perform_foo(dispatcher, foo):
64+
return do_side_effecting_deferred_operation(foo)
65+
"""
66+
@wraps(f)
67+
def deferred_wrapper(*args):
68+
box = args[-1]
69+
pass_args = args[:-1]
70+
try:
71+
result = f(*pass_args)
72+
except:
73+
box.fail(sys.exc_info())
74+
else:
75+
if isinstance(result, Deferred):
76+
deferred_to_box(result, box)
77+
else:
78+
box.succeed(result)
79+
return deferred_wrapper
80+
81+
82+
def perform_delay(reactor, dispatcher, delay):
83+
"""
84+
Perform a :obj:`effect.Delay` with Twisted's
85+
:func:`twisted.internet.task.deferLater`.
86+
"""
87+
return deferLater(reactor, delay.delay, lambda: None)
88+
89+
90+
def perform(dispatcher, effect):
91+
"""
92+
Perform an effect, returning a Deferred that will fire with the effect's
93+
ultimate result.
94+
"""
95+
d = Deferred()
96+
eff = effect.on(
97+
success=d.callback,
98+
error=lambda e: d.errback(exc_info_to_failure(e)))
99+
base_perform(dispatcher, eff)
100+
return d
101+
102+
103+
def exc_info_to_failure(exc_info):
104+
"""Convert an exc_info tuple to a :class:`Failure`."""
105+
return Failure(exc_info[1], exc_info[0], exc_info[2])

0 commit comments

Comments
 (0)