Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.

Commit a82b293

Browse files
committed
Big step in the reorg.
1 parent 011fbe5 commit a82b293

File tree

13 files changed

+174
-40
lines changed

13 files changed

+174
-40
lines changed

Diff for: hendrix/contrib/resources/static.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import os
2-
from hendrix.resources import DjangoStaticResource
2+
3+
from hendrix.resources.resources import DjangoStaticResource
34
from django.conf import settings
45
from django.contrib.staticfiles import finders
56

Diff for: hendrix/deploy/base.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
import chalk
21
import importlib
32
import os
43
import time
5-
64
import pickle
7-
85
from os import environ
96
from socket import AF_INET
107

8+
import chalk
9+
from twisted.internet import reactor
10+
1111
from hendrix import defaults
12+
1213
from hendrix.options import options as hx_options
1314
from hendrix.resources import get_additional_resources
14-
from hendrix.services import get_additional_services, HendrixService
15+
from hendrix.resources.services import get_additional_services, HendrixService, TCPServer
1516
from hendrix.utils import get_pid
16-
from twisted.application.internet import TCPServer, SSLServer
17-
from twisted.internet import reactor
1817

1918

2019
class HendrixDeploy(object):
@@ -59,7 +58,8 @@ def __init__(self, action='start', options={}, reactor=reactor):
5958
django = importlib.import_module('django')
6059
if django.VERSION[:2] >= (1, 7):
6160
installed_apps = getattr(settings, "INSTALLED_APPS")
62-
django.apps.apps.populate(installed_apps)
61+
from django.apps import apps
62+
apps.populate(installed_apps)
6363
wsgi_dot_path = getattr(settings, 'WSGI_APPLICATION', None)
6464
self.application = HendrixDeploy.importWSGI(wsgi_dot_path)
6565

@@ -123,6 +123,7 @@ def addHendrix(self):
123123
)
124124

125125
def catalogServers(self, hendrix):
126+
from hendrix.contrib.ssl import SSLServer
126127
"collects a list of service names serving on TCP or SSL"
127128
for service in hendrix.services:
128129
if isinstance(service, (TCPServer, SSLServer)):

Diff for: hendrix/experience/__init__.py

Whitespace-only changes.

Diff for: hendrix/contrib/async/crosstown_traffic.py renamed to hendrix/experience/crosstown_traffic.py

+35-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from twisted.internet.threads import deferToThread, deferToThreadPool
22
from twisted.internet import reactor
3+
from twisted.python.threadpool import ThreadPool
34

45
import threading
56

@@ -8,12 +9,22 @@
89
logger = logging.getLogger(__name__)
910
logger.setLevel(logging.INFO)
1011

12+
13+
class ThreadHasNoResponse(RuntimeError):
14+
pass
15+
16+
1117
def get_response_for_thread(thread=None):
1218

1319
if not thread:
1420
thread = threading.current_thread()
1521

16-
response = thread.response_object
22+
try:
23+
response = thread.response_object
24+
except AttributeError:
25+
raise ThreadHasNoResponse('thread %s has no associated response object.' % thread)
26+
27+
1728
return response
1829

1930

@@ -25,30 +36,42 @@ def get_tasks_to_follow_current_response(thread=None):
2536
class ThroughToYou(object):
2637

2738
def __init__(self,
39+
reactor=reactor,
2840
same_thread=False,
2941
no_go_status_codes=['5xx', '4xx'],
30-
reactor=reactor,
42+
fail_without_response=False
3143
):
44+
self.reactor = reactor
3245
self.same_thread = same_thread
3346
self.no_go_status_codes = no_go_status_codes
34-
self.reactor = reactor
47+
self.fail_without_response = fail_without_response
48+
3549
self.no_go = False
3650
self.status_code = None
3751

38-
def __call__(self, crosstown_task):
52+
def __call__(self, crosstown_task=None):
3953
self.crosstown_task = crosstown_task
40-
self.response = get_response_for_thread()
4154

42-
if not self.no_go:
43-
logger.info("Adding '%s' to crosstown_traffic for %s" % (crosstown_task.__name__, self.response))
44-
self.response.crosstown_tasks.append(self)
55+
try:
56+
self.response = get_response_for_thread()
57+
logger.info("Adding '%s' to crosstown_traffic for %s" % (str(crosstown_task), self.response))
58+
if not self.no_go:
59+
self.response.crosstown_tasks.append(self)
60+
except ThreadHasNoResponse:
61+
if self.fail_without_response:
62+
raise
63+
else:
64+
logger.info("thread %s has no response; running crosstown task now. To supress this behavior, set fail_without_response == True." % threading.current_thread())
65+
self.run()
66+
return self.run
4567

46-
def run(self, threadpool):
47-
# See if status code is a go
48-
self.check_status_code_against_no_go_list()
68+
def run(self, threadpool=None):
4969
if self.no_go:
5070
return
5171

72+
if not threadpool:
73+
threadpool = reactor.threadpool or ThreadPool()
74+
5275
if self.same_thread:
5376
self.crosstown_task()
5477
else:
@@ -93,4 +116,5 @@ def __call__(self, *args, **kwargs):
93116
decorator = ThroughToYou(*args, **kwargs)
94117
return decorator
95118

119+
96120
follow_response = FollowResponse()

Diff for: hendrix/resources.py renamed to hendrix/resources/__init__.py

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
import sys
22
import importlib
3-
import inspect
4-
from hendrix.utils import responseInColor
5-
from hendrix.contrib.async import crosstown_traffic
3+
import logging
4+
import threading
65

76
from twisted.web import resource, static
87
from twisted.web.server import NOT_DONE_YET
98
from twisted.web.wsgi import WSGIResource, _WSGIResponse
10-
11-
import logging
129
import chalk
13-
from twisted.internet.threads import deferToThread
14-
import threading
15-
import uuid
10+
11+
from hendrix.utils import responseInColor
12+
1613

1714
logger = logging.getLogger(__name__)
1815

@@ -33,12 +30,17 @@ def run(self, *args, **kwargs):
3330
self.request.setHeader('server', 'hendrix/Twisted')
3431
ran = super(HendrixWSGIResponse, self).run(*args, **kwargs)
3532
self.follow_response_tasks()
33+
del self.thread.response_object
3634
return ran
3735

3836
def follow_response_tasks(self):
3937

4038
for task in self.crosstown_tasks:
41-
logger.info("Processing crosstown task: '%s'" % task)
39+
logger.info("Processing crosstown task: '%s'" % task.crosstown_task)
40+
41+
# Set no-go if status code is bad.
42+
task.check_status_code_against_no_go_list()
43+
4244
task.run(self.threadpool)
4345

4446
class LoudWSGIResponse(HendrixWSGIResponse):

Diff for: hendrix/services.py renamed to hendrix/resources/services.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import importlib
2-
from .resources import HendrixResource
2+
import logging
3+
34
from twisted.application import internet, service
45
from twisted.internet import reactor
56
from twisted.python.threadpool import ThreadPool
67
from twisted.web import server
78

8-
import logging
9+
from hendrix.resources import HendrixResource
10+
911

1012
logger = logging.getLogger(__name__)
1113

Diff for: hendrix/test/resources.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
#! python
2+
13
from multiprocessing import Queue
24
import threading
35
import logging
46

5-
from hendrix.contrib.async import crosstown_traffic
7+
from hendrix.experience import crosstown_traffic
68

7-
logger = logging.getLogger(__name__)
89

10+
logger = logging.getLogger(__name__)
911

10-
from hendrix.contrib.async.crosstown_traffic import get_response_for_thread,\
11-
get_tasks_to_follow_current_response
12+
from hendrix.experience.crosstown_traffic import get_response_for_thread, get_tasks_to_follow_current_response
1213

1314

1415
class TestNameSpace(object):

Diff for: hendrix/test/test_crosstown_traffic.py

+33-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
from twisted.python.threadpool import ThreadPool
1111
from twisted.web.test.requesthelper import DummyRequest
1212

13-
from hendrix.contrib.async import crosstown_traffic
13+
from hendrix.experience import crosstown_traffic
14+
from hendrix.experience.crosstown_traffic import ThreadHasNoResponse
1415
from hendrix.resources import HendrixWSGIResource
1516
from hendrix.test.resources import TestNameSpace, application as wsgi_application,\
1617
nameSpace
@@ -145,6 +146,12 @@ class PostResponseTest(TestCase):
145146
def setUp(self):
146147
nameSpace = TestNameSpace()
147148

149+
def tearDown(self):
150+
try:
151+
del threading.current_thread().response_object
152+
except AttributeError:
153+
pass
154+
148155
def test_postiive_decorator_coherence(self):
149156
self.pass_flag = False
150157

@@ -172,8 +179,8 @@ class FakeResponse(object):
172179
crosstown_tasks = []
173180
status = "418 I'm a teapot. Seriously."
174181

175-
through_to_you = crosstown_traffic.follow_response(same_thread=True)
176182
threading.current_thread().response_object = FakeResponse()
183+
through_to_you = crosstown_traffic.follow_response(same_thread=True)
177184

178185
through_to_you.no_go = True # If no_go is True...
179186
through_to_you(append_me_to_pass) # and we call it...
@@ -185,6 +192,30 @@ class FakeResponse(object):
185192
append_me_to_pass
186193
) # We will have added the function.
187194

195+
def test_with_no_request(self):
196+
197+
self.has_run = False
198+
199+
def append_me_to_pass():
200+
self.has_run = True
201+
202+
through_to_you = crosstown_traffic.follow_response(same_thread=True)
203+
through_to_you(append_me_to_pass)
204+
205+
self.assertTrue(self.has_run)
206+
207+
def test_fail_without_response(self):
208+
'''
209+
Same test as above, but with fail_without_response, we get an error.
210+
'''
211+
self.has_run = False
212+
213+
def append_me_to_pass():
214+
self.has_run = True
215+
216+
through_to_you = crosstown_traffic.follow_response(same_thread=True, fail_without_response=True)
217+
218+
self.assertRaises(ThreadHasNoResponse, through_to_you, append_me_to_pass)
188219

189220
def test_contemporaneous_requests(self):
190221

Diff for: hendrix/test/test_resources.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import mock
21
import unittest
32

4-
from hendrix.resources import HendrixResource, NamedResource, WSGIResource
53
from twisted.web.resource import getChildForRequest, NoResource
64
from twisted.web.test.requesthelper import DummyRequest
75

6+
import mock
7+
from hendrix.resources import HendrixResource, NamedResource, WSGIResource
8+
89

910
class TestHendrixResource(unittest.TestCase):
1011

Diff for: hendrix/test/test_testing_utils.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from hendrix.experience import crosstown_traffic
2+
from hendrix.utils.test_utils import AsyncTestMixin
3+
from twisted.trial.unittest import TestCase
4+
5+
6+
7+
class TestMixinAssertions(TestCase):
8+
9+
def test_assert_num_tasks(self):
10+
11+
a_mixin = AsyncTestMixin()
12+
a_mixin.assertNumCrosstownTasks(0)
13+
14+
def some_task():
15+
pass
16+
17+
through_to_you = crosstown_traffic.follow_response()
18+
through_to_you(some_task)
19+
20+
a_mixin.assertNumCrosstownTasks(1)
21+
22+
def test_next_task(self):
23+
24+
a_mixin = AsyncTestMixin()
25+
a_mixin.assertNumCrosstownTasks(0)
26+
27+
def some_task():
28+
pass
29+
30+
through_to_you = crosstown_traffic.follow_response()
31+
through_to_you(some_task)
32+
33+
self.assertIs(some_task, a_mixin.next_task())
34+
35+
def test_no_more_tasks(self):
36+
37+
a_mixin = AsyncTestMixin()
38+
a_mixin.assertNumCrosstownTasks(0)
39+
40+
def some_task():
41+
pass
42+
43+
through_to_you = crosstown_traffic.follow_response()
44+
through_to_you(some_task)
45+
46+
same_task = a_mixin.next_task()
47+
48+
# That will be the only (and thus last) task.
49+
self.assertRaises(StopIteration, a_mixin.next_task)

Diff for: hendrix/ux.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,16 @@
1313
import traceback
1414
from .options import HendrixOptionParser, cleanOptions
1515
from hendrix.contrib import SettingsError
16-
from hendrix.deploy import base, ssl, cache, hybrid
16+
from hendrix.deploy import base, cache
17+
18+
import logging
19+
logger = logging.getLogger(__name__)
20+
21+
try:
22+
from hendrix.deploy import ssl, hybrid
23+
except ImportError:
24+
logger.warning("hendrix SSL is not available.")
25+
1726
from watchdog.observers import Observer
1827
from watchdog.events import FileSystemEventHandler
1928

Diff for: runtests.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#! python
2+
3+
import os, sys
4+
5+
# begin chdir armor
6+
sys.path[:] = map(os.path.abspath, sys.path)
7+
# end chdir armor
8+
9+
sys.path.insert(0, os.path.abspath(os.getcwd()))
10+
sys.argv.append("hendrix/test")
11+
12+
from twisted.scripts.trial import run
13+
run()

Diff for: setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,5 @@ def mkdir_p(path):
6969
(share_path, ['hendrix/utils/templates/init.d.j2', ]),
7070
],
7171
install_requires=readlines('requirements'),
72-
extras_require={'ssl': ['pyopenssl', ]}
72+
extras_require={'ssl': ['pyopenssl', ]}
7373
)

0 commit comments

Comments
 (0)