Skip to content

Commit

Permalink
Merge pull request #493 from MasoniteFramework/develop
Browse files Browse the repository at this point in the history
Next Minor
  • Loading branch information
josephmancuso committed Dec 17, 2018
2 parents e4d16db + 6323ac8 commit 314b7b9
Show file tree
Hide file tree
Showing 26 changed files with 228 additions and 62 deletions.
5 changes: 5 additions & 0 deletions app/http/controllers/subdirectory/SubController.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

class SubController:

def show(self):
return 'test'
10 changes: 9 additions & 1 deletion config/queue.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,12 @@
|
"""

DRIVERS = {}
DRIVERS = {
'amqp': {
'username': 'guest',
'password': 'guest',
'host': 'localhost',
'port': '5672',
'channel': 'default',
}
}
7 changes: 5 additions & 2 deletions masonite/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def resolve(self, obj, *resolving_arguments):
provider_list = []
passing_arguments = list(resolving_arguments)

for _, value in inspect.signature(obj).parameters.items():
for _, value in self.get_parameters(obj):
if ':' in str(value):
provider_list.append(self._find_annotated_parameter(value))
elif self.resolve_parameters:
Expand All @@ -148,7 +148,7 @@ def resolve(self, obj, *resolving_arguments):
try:
return obj(*provider_list)
except TypeError as e:
raise ContainerError('Either Tried resolving the too many dependencies or {}'.format(str(e)))
raise ContainerError(str(e))

def collect(self, search):
"""Fetch a dictionary of objects using a search query.
Expand Down Expand Up @@ -223,6 +223,9 @@ def _find_annotated_parameter(self, parameter):
raise ContainerError(
'The dependency with the {0} annotation could not be resolved by the container'.format(parameter))

def get_parameters(self, obj):
return inspect.signature(obj).parameters.items()

def _find_parameter(self, parameter):
"""Find a parameter in the container.
Expand Down
8 changes: 7 additions & 1 deletion masonite/commands/QueueWorkCommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ def callback(ch, method, properties, body):
job = pickle.loads(body)
obj = job['obj']
args = job['args']
callback = job['callback']
if inspect.isclass(obj):
obj = container.resolve(obj)
obj.handle(*args)

try:
getattr(obj, callback)(*args)
except AttributeError:
obj(*args)

ch.basic_ack(delivery_tag=method.delivery_tag)


Expand Down
13 changes: 13 additions & 0 deletions masonite/drivers/BaseMailDriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def __init__(self, app: App, view: View):
self.message_subject = 'Subject'
self.message_body = None
self.view = view
self._queue = False

def to(self, user_email):
"""Set the user email address who you want to send mail to.
Expand All @@ -37,6 +38,18 @@ def to(self, user_email):
self.to_address = user_email
return self

def queue(self):
"""Set the user email address who you want to send mail to.
Arguments:
user_email {string} -- The user email address.
Returns:
self
"""
self._queue = True
return self

def template(self, template_name, dictionary={}):
"""Create an email from a normal Jinja template.
Expand Down
18 changes: 18 additions & 0 deletions masonite/drivers/MailMailgunDriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,29 @@ def send(self, message=None):
Returns:
requests.post -- Returns the response as a requests object.
"""

if self._queue:
from wsgi import container
from masonite import Queue
return container.make(Queue).push(self._send_mail, args=(message,))

return self._send_mail(message)

def _send_mail(self, message):
"""Wrapper around sending mail so it can also be used with queues.
Arguments:
message {string|None} -- The message to be sent passed in from the send method.
Returns:
requests.post
"""
if not message:
message = self.message_body

domain = self.config.DRIVERS['mailgun']['domain']
secret = self.config.DRIVERS['mailgun']['secret']

return requests.post(
"https://api.mailgun.net/v3/{0}/messages".format(domain),
auth=("api", secret),
Expand Down
19 changes: 16 additions & 3 deletions masonite/drivers/MailSmtpDriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,20 @@ def send(self, message_contents=None):

self.smtp.login(config['username'], config['password'])

# self.smtp.send_message(message)
self.smtp.sendmail(self.config.FROM['name'],
self.to_address, message.as_string())
if self._queue:
from wsgi import container
from masonite import Queue
container.make(Queue).push(
self._send_mail,
args=(self.config.FROM['name'], self.to_address, message.as_string())
)
return

self._send_mail(self.config.FROM['name'],
self.to_address, message.as_string())

def _send_mail(self, *args):
"""Wrapper around sending mail so it can also be used for queues.
"""
self.smtp.sendmail(*args)
self.smtp.quit()
4 changes: 2 additions & 2 deletions masonite/drivers/QueueAmqpDriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _publish(self, body):
delivery_mode=2, # make message persistent
))

def push(self, *objects, args=()):
def push(self, *objects, args=(), callback='handle'):
"""Push objects onto the amqp stack.
Arguments:
Expand All @@ -70,7 +70,7 @@ def push(self, *objects, args=()):
for obj in objects:
# Publish to the channel for each object
try:
self._publish({'obj': obj, 'args': args})
self._publish({'obj': obj, 'args': args, 'callback': callback})
except self.pika.exceptions.ConnectionClosed:
self._connect()
self._publish({'obj': obj, 'args': args})
12 changes: 9 additions & 3 deletions masonite/drivers/QueueAsyncDriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def __init__(self, app: App):
"""
self.container = app

def push(self, *objects, args=()):
def push(self, *objects, args=(), callback='handle'):
"""Push objects onto the async stack.
Arguments:
Expand All @@ -29,6 +29,12 @@ def push(self, *objects, args=()):
if inspect.isclass(obj):
obj = self.container.resolve(obj)

thread = threading.Thread(
target=obj.handle, args=args, kwargs={})
try:
thread = threading.Thread(
target=getattr(obj, callback), args=args, kwargs={})
except AttributeError:
# Could be wanting to call only a method asyncronously
thread = threading.Thread(
target=obj, args=args, kwargs={})

thread.start()
2 changes: 1 addition & 1 deletion masonite/info.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Module for specifying the Masonite version in a central location."""

VERSION = '2.1.1'
VERSION = '2.1.2'
2 changes: 2 additions & 0 deletions masonite/queues/ShouldQueue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ShouldQueue:
pass
1 change: 1 addition & 0 deletions masonite/queues/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .Queueable import Queueable
from .ShouldQueue import ShouldQueue
16 changes: 11 additions & 5 deletions masonite/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ def user(self):
"""
return self.user_model

def redirect(self, route, params={}):
def redirect(self, route=None, params={}, name=None, controller=None, status=302):
"""Redirect the user based on the route specified.
Arguments:
Expand All @@ -597,11 +597,17 @@ def redirect(self, route, params={}):
Returns:
self
"""
self.redirect_url = self.compile_route_to_url(route, params)
self.status(302)
if name:
return self.redirect_to(name, params, status=status)
elif route:
self.redirect_url = self.compile_route_to_url(route, params)
elif controller:
self.redirect_url = self.url_from_controller(controller, params)

self.status(status)
return self

def redirect_to(self, route_name, params={}):
def redirect_to(self, route_name, params={}, status=302):
"""Redirect to a named route.
Arguments:
Expand All @@ -616,7 +622,7 @@ def redirect_to(self, route_name, params={}):
self
"""
self.redirect_url = self._get_named_route(route_name, params)
self.status(302)
self.status(status)

return self

Expand Down
2 changes: 2 additions & 0 deletions masonite/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ def view(self, view, status=200):

if isinstance(view, dict) or isinstance(view, list):
return self.json(view)
elif isinstance(view, int):
view = str(view)
elif isinstance(view, View):
view = view.rendered_template
elif isinstance(view, self.request.__class__):
Expand Down
4 changes: 3 additions & 1 deletion masonite/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,9 @@ def _find_controller(self, controller):
if mod[0].startswith('/'):
self.module_location = '.'.join(
mod[0].replace('/', '').split('.')[0:-1])

elif '.' in mod[0]:
# This is a deeper module controller
self.module_location = self.module_location + '.' + '.'.join(mod[0].split('.')[:-1])
else:
if controller is None:
return None
Expand Down
Empty file added tests/__init__.py
Empty file.
Empty file added tests/queues/__init__.py
Empty file.
27 changes: 0 additions & 27 deletions tests/queues/test_async_driver.py

This file was deleted.

55 changes: 55 additions & 0 deletions tests/queues/test_drivers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
from masonite.app import App
from masonite.drivers import QueueAsyncDriver, QueueAmqpDriver
from masonite.managers import QueueManager
from config import queue

from masonite.queues.Queueable import Queueable
import os
from masonite.environment import LoadEnvironment, env

LoadEnvironment()


class Job(Queueable):

def handle(self):
print('sending from job handled')
return 'test'

class Random(Queueable):

def send(self):
print('sending from random send method')
return 'test'

def handle(self):
print('sending from random handle method')
return 'test'


class TestAsyncDriver:

def setup_method(self):
self.app = App()

self.app.bind('QueueAsyncDriver', QueueAsyncDriver)
self.app.bind('QueueAmqpDriver', QueueAmqpDriver)
self.app.bind('QueueConfig', queue)
self.app.bind('Queueable', Queueable)
self.app.bind('Container', self.app)
self.app.bind('QueueManager', QueueManager(self.app))
self.drivers = ['async']
if env('RUN_AMQP'):
self.drivers.append('amqp')

def test_async_driver_pushes_to_queue(self):
for driver in self.drivers:
assert self.app.make('QueueManager').driver(driver).push(Job) is None

def test_async_driver_can_run_any_callback_method(self):
for driver in self.drivers:
assert self.app.make('QueueManager').driver(driver).push(Random, callback="send") is None

def test_async_driver_can_run_any_method(self):
for driver in self.drivers:
assert self.app.make('QueueManager').driver(driver).push(Random().send) is None
10 changes: 0 additions & 10 deletions tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,6 @@ def test_app_makes(self):
self.app.bind('Request', REQUEST)
assert self.app.make('Request').cookies == []

def test_throws_exception_if_too_many_bindings(self):
REQUEST.cookies = ['hey']
self.app.bind('Request', REQUEST)
self.app.bind('Route', Get().route('test/', None))
with pytest.raises(ContainerError, message="should raise error"):
self.app.resolve(self._functest)

def _functest(Request, get: Get, post: Post):
return Request.cookies

def test_can_set_container_hook(self):
self.app.on_bind('Request', self._func_on_bind)
self.app.bind('Request', REQUEST)
Expand Down
8 changes: 4 additions & 4 deletions tests/test_container.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ def find(self):
class MakeObject:
pass


class SubstituteThis:
pass


class TestContainer:

def setup_method(self):
Expand Down Expand Up @@ -162,11 +164,10 @@ def test_can_pass_variables(self):
assert obj[0] == 'test1'
assert obj[1] == req
assert obj[2] == 'test2'

def _test_resolves_variables(self, var1, request: Request, var2):
return [var1, request, var2]


def test_can_substitute(self):
app = App()
app.swap(SubstituteThis, self._substitute)
Expand All @@ -187,7 +188,6 @@ def test_can_substitute_with_make_object(self):

def _substitute(self, method, container):
return 'test'

def _test_substitute(self, test: SubstituteThis):
return test

Loading

0 comments on commit 314b7b9

Please sign in to comment.