Skip to content

Commit

Permalink
Made changes for should_send_request to take in pyramid request object (
Browse files Browse the repository at this point in the history
#28)

* Made changes for should_send_request to take in pyramid request object

* passed in request object to every lifecycle method and rewrote tests

Co-authored-by: Shaheryar Ajmal <sajmal@yelp.com>
  • Loading branch information
shar-ajmal and shar-ajmal-yelp authored Mar 9, 2020
1 parent c9ef6a0 commit d17d25a
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 47 deletions.
12 changes: 6 additions & 6 deletions pyramid_hypernova/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def render(self, name, data, context=None):

identifier = str(uuid.uuid4())

data = self.plugin_controller.get_view_data(name, data)
data = self.plugin_controller.get_view_data(name, data, self.pyramid_request)
job = Job(name, data, context)
self.jobs[identifier] = job

Expand Down Expand Up @@ -120,7 +120,7 @@ def process_responses(self, query, jobs):
self.plugin_controller.on_error(error, jobs, self.pyramid_request)
else:
pyramid_response = self._parse_response(response_json)
self.plugin_controller.on_success(pyramid_response, jobs)
self.plugin_controller.on_success(pyramid_response, jobs, self.pyramid_request)

except (HypernovaQueryError, ValueError) as e:
# the service is unhealthy. fall back to client-side rendering
Expand All @@ -141,12 +141,12 @@ def submit(self):
:rtype: Dict[str, JobResult]
"""
self.jobs = self.plugin_controller.prepare_request(self.jobs)
self.jobs = self.plugin_controller.prepare_request(self.jobs, self.pyramid_request)

response = {}

if self.jobs and self.plugin_controller.should_send_request(self.jobs):
self.plugin_controller.will_send_request(self.jobs)
if self.jobs and self.plugin_controller.should_send_request(self.jobs, self.pyramid_request):
self.plugin_controller.will_send_request(self.jobs, self.pyramid_request)
job_groups = create_job_groups(self.jobs, self.max_batch_size)
queries = []

Expand All @@ -168,5 +168,5 @@ def submit(self):
# fall back to client-side rendering
response.update(create_fallback_response(self.jobs, True, self.json_encoder))

response = self.plugin_controller.after_response(response)
response = self.plugin_controller.after_response(response, self.pyramid_request)
return response
48 changes: 30 additions & 18 deletions pyramid_hypernova/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,35 @@ class PluginController(object):
def __init__(self, plugins):
self.plugins = plugins

def get_view_data(self, view_name, data):
def get_view_data(self, view_name, data, request):
"""Allows you to alter the data that a "view" will receive
:param view_name: the name of the component
:type view_name: string
:param data: the props that will be passed into the component
:type data: any
:type request: a Pyramid request object
:returns: the new data
:rtype: any
"""
for plugin in self.plugins:
data = plugin.get_view_data(view_name, data)
data = plugin.get_view_data(view_name, data, request)
return data

def prepare_request(self, jobs):
def prepare_request(self, jobs, request):
"""A reducer type function that is called when preparing the request
that will be sent to Hypernova. This function receives the current
running jobs Object and the original jobs Object.
:type jobs: Dict[str, Job]
:type request: a Pyramid request object
:returns: the modified Jobs to be submitted
:rtype: Dict[str, Job]
"""
current_jobs = jobs
original_jobs = jobs
for plugin in self.plugins:
current_jobs = plugin.prepare_request(current_jobs, original_jobs)
current_jobs = plugin.prepare_request(current_jobs, original_jobs, request)
return current_jobs

def transform_request_headers(self, headers, request):
Expand All @@ -56,49 +58,53 @@ def transform_request_headers(self, headers, request):
headers = plugin.transform_request_headers(headers, request)
return headers

def should_send_request(self, jobs):
def should_send_request(self, jobs, request):
"""An every type function. If one returns false then the request is
canceled.
:type jobs: Dict[str, Job]
:returns: False if the request should be cancelled
:type request: a Pyramid request object
:rtype: bool
"""
return all(plugin.should_send_request(jobs) for plugin in self.plugins)
return all(plugin.should_send_request(jobs, request) for plugin in self.plugins)

def will_send_request(self, jobs):
def will_send_request(self, jobs, request):
"""An event type function that is called prior to a request being sent.
:type jobs: Dict[str, Job]
:type request: a Pyramid request object
"""
for plugin in self.plugins:
plugin.will_send_request(jobs)
plugin.will_send_request(jobs, request)

def after_response(self, response):
def after_response(self, response, request):
"""A reducer type function which receives the current response and
the original response from the Hypernova service.
:param response: a response dict, as returned by
`parse_response`
:type response: dict
:type request: a Pyramid request object
:returns: the new response value
:rtype: any
"""
current_response = response
original_response = response
for plugin in self.plugins:
current_response = plugin.after_response(current_response, original_response)
current_response = plugin.after_response(current_response, original_response, request)
return current_response

def on_success(self, response, jobs):
def on_success(self, response, jobs, request):
"""An event type function that is called whenever a request was
successful.
:type response: dict
:type request: a Pyramid request object
:type jobs: Dict[str, Job]
"""
for plugin in self.plugins:
plugin.on_success(response, jobs)
plugin.on_success(response, jobs, request)

def on_error(self, err, jobs, request):
"""An event type function that is called whenever any error is
Expand All @@ -118,25 +124,27 @@ class BasePlugin(object):
See https://github.com/airbnb/hypernova/blob/master/docs/client-spec.md
"""

def get_view_data(self, view_name, data):
def get_view_data(self, view_name, data, request):
"""Allows you to alter the data that a "view" will receive
:param view_name: the name of the component
:type view_name: string
:param data: the props that will be passed into the component
:type data: any
:type request: a Pyramid request object
:returns: the new data
:rtype: any
"""
return data

def prepare_request(self, current_jobs, original_jobs):
def prepare_request(self, current_jobs, original_jobs, request):
"""A reducer type function that is called when preparing the request
that will be sent to Hypernova. This function receives the current
running jobs Object and the original jobs Object.
:type current_jobs: Dict[str, Job]
:type original_jobs: Dict[str, Job]
:type request: a Pyramid request object
:returns: the modified Jobs to be submitted
:rtype: Dict[str, Job]
"""
Expand All @@ -154,23 +162,25 @@ def transform_request_headers(self, headers, request):
"""
return headers

def should_send_request(self, jobs):
def should_send_request(self, jobs, request):
"""An every type function. If one returns false then the request is
canceled.
:type jobs: Dict[str, Job]
:type request: a Pyramid request object
:returns: False if the request should be cancelled
:rtype: bool
"""
return True

def will_send_request(self, jobs):
def will_send_request(self, jobs, request):
"""An event type function that is called prior to a request being sent.
:type jobs: Dict[str, Job]
:type request: a Pyramid request object
"""

def after_response(self, current_response, original_response):
def after_response(self, current_response, original_response, request):
"""A reducer type function which receives the current response and
the original response from the Hypernova service.
Expand All @@ -179,17 +189,19 @@ def after_response(self, current_response, original_response):
:param original_response: a response dict, as returned by
`parse_response`
:type original_response: dict
:type request: a Pyramid request object
:returns: the new response value
:rtype: any
"""
return current_response

def on_success(self, response, jobs):
def on_success(self, response, jobs, request):
"""An event type function that is called whenever a request was
successful.
:type response: dict
:type jobs: Dict[str, Job]
:type request: a Pyramid request object
"""

def on_error(self, err, jobs, request):
Expand Down
23 changes: 11 additions & 12 deletions tests/batch_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,29 +358,26 @@ def test_calls_get_view_data(self, spy_plugin_controller, test_data, batch_reque
spy_plugin_controller.get_view_data.assert_called_once_with(
'MyComponent.js',
data[0],
batch_request.pyramid_request,
)

job = batch_request.jobs[token.identifier]

assert job.data == spy_plugin_controller.get_view_data(
'MyComponent.js',
data[0],
batch_request.pyramid_request,
)

def test_calls_prepare_request(self, spy_plugin_controller, test_data, batch_request, mock_hypernova_query):
data = test_data[0]
batch_request.render('MySsrComponent.js', data[0])

original_jobs = dict(batch_request.jobs)

batch_request.submit()

spy_plugin_controller.prepare_request.assert_has_calls([
mock.call(original_jobs),
])

assert batch_request.jobs == spy_plugin_controller.prepare_request(
original_jobs
spy_plugin_controller.prepare_request.assert_called_once_with(
batch_request.jobs,
batch_request.pyramid_request
)

def test_calls_will_send_request(self, spy_plugin_controller, test_data, batch_request, mock_hypernova_query):
Expand All @@ -389,9 +386,10 @@ def test_calls_will_send_request(self, spy_plugin_controller, test_data, batch_r

batch_request.submit()

spy_plugin_controller.will_send_request.assert_has_calls([
mock.call(batch_request.jobs),
])
spy_plugin_controller.will_send_request.assert_called_once_with(
batch_request.jobs,
batch_request.pyramid_request,
)

def test_calls_after_response(self, spy_plugin_controller, test_data, batch_request, mock_hypernova_query):
data = test_data[0]
Expand Down Expand Up @@ -420,7 +418,7 @@ def test_calls_after_response(self, spy_plugin_controller, test_data, batch_requ
),
}

assert response == spy_plugin_controller.after_response(parsed_response)
assert response == spy_plugin_controller.after_response(parsed_response, batch_request.pyramid_request)

def test_calls_on_success(self, spy_plugin_controller, test_data, batch_request, mock_hypernova_query):
data = test_data[0]
Expand All @@ -442,6 +440,7 @@ def test_calls_on_success(self, spy_plugin_controller, test_data, batch_request,
spy_plugin_controller.on_success.assert_called_once_with(
response,
batch_request.jobs,
batch_request.pyramid_request,
)

def test_calls_on_error(self, spy_plugin_controller, test_data, batch_request, mock_hypernova_query):
Expand Down
Loading

0 comments on commit d17d25a

Please sign in to comment.