Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
event-tracking
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
event-tracking
Commits
66d523ae
Commit
66d523ae
authored
Apr 24, 2015
by
Gabe Mulley
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
addressed review comments
parent
b605265b
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
58 additions
and
15 deletions
+58
-15
eventtracking/backends/routing.py
+5
-4
eventtracking/processors/tests/test_whitelist.py
+40
-7
eventtracking/processors/whitelist.py
+13
-4
No files found.
eventtracking/backends/routing.py
View file @
66d523ae
...
@@ -24,13 +24,14 @@ class RoutingBackend(object):
...
@@ -24,13 +24,14 @@ class RoutingBackend(object):
logged and swallowed, subsequent processors will execute and the event will be emitted.
logged and swallowed, subsequent processors will execute and the event will be emitted.
2) Backends - Backends are intended to not mutate the event and each receive the same event data. They are not
2) Backends - Backends are intended to not mutate the event and each receive the same event data. They are not
chained like processors. Once an event has been processed by the processor chain, it is passed to each backend in
chained like processors. Once an event has been processed by the processor chain, it is passed to each backend in
order, sorted by the name of the backen
d. Backends typically persist the event in some way, either by sending it
the order that they were registere
d. Backends typically persist the event in some way, either by sending it
to an external system or saving it to disk. They are called synchronously and in sequence, so a long running
to an external system or saving it to disk. They are called synchronously and in sequence, so a long running
backend will block other backends until it is done persisting the event. Note that you can register another
backend will block other backends until it is done persisting the event. Note that you can register another
`RoutingBackend` as a backend of a `RoutingBackend`, allowing for arbitrary processing trees.
`RoutingBackend` as a backend of a `RoutingBackend`, allowing for arbitrary processing trees.
`backends` is a collection that supports iteration over it's items using `iteritems()`. The keys are expected to be
`backends` is a collection that supports iteration over its items using `iteritems()`. The keys are expected to be
sortable and the values are expected to expose a `send(event)` method that will be called for each event.
sortable and the values are expected to expose a `send(event)` method that will be called for each event. Each
backend in this collection is registered in order sorted alphanumeric ascending by key.
`processors` is an iterable of callables.
`processors` is an iterable of callables.
Raises a `ValueError` if any of the provided backends do not have a callable "send" attribute or any of the
Raises a `ValueError` if any of the provided backends do not have a callable "send" attribute or any of the
...
@@ -51,7 +52,7 @@ class RoutingBackend(object):
...
@@ -51,7 +52,7 @@ class RoutingBackend(object):
def
register_backend
(
self
,
name
,
backend
):
def
register_backend
(
self
,
name
,
backend
):
"""
"""
Register a new backend that will be called for each processed event
Register a new backend that will be called for each processed event
.
Note that backends are called in the order that they are registered.
Note that backends are called in the order that they are registered.
"""
"""
...
...
eventtracking/processors/tests/test_whitelist.py
View file @
66d523ae
...
@@ -7,34 +7,67 @@ from unittest import TestCase
...
@@ -7,34 +7,67 @@ from unittest import TestCase
from
mock
import
sentinel
from
mock
import
sentinel
from
eventtracking.processors.exceptions
import
EventEmissionExit
from
eventtracking.processors.exceptions
import
EventEmissionExit
from
eventtracking.processors.whitelist
import
WhitelistProcessor
from
eventtracking.processors.whitelist
import
Name
WhitelistProcessor
class
TestWhitelistProcessor
(
TestCase
):
class
Test
Name
WhitelistProcessor
(
TestCase
):
"""Test the whitelist processor"""
"""Test the whitelist processor"""
def
test_filtering_out
(
self
):
def
test_filtering_out
(
self
):
whitelist
=
WhitelistProcessor
(
whitelist
=
[
sentinel
.
allowed_event
])
whitelist
=
Name
WhitelistProcessor
(
whitelist
=
[
sentinel
.
allowed_event
])
with
self
.
assertRaises
(
EventEmissionExit
):
with
self
.
assertRaises
(
EventEmissionExit
):
whitelist
({
'name'
:
sentinel
.
not_allowed_event
})
whitelist
({
'name'
:
sentinel
.
not_allowed_event
})
def
test_allowed_event
(
self
):
def
test_allowed_event
(
self
):
whitelist
=
WhitelistProcessor
(
whitelist
=
[
sentinel
.
allowed_event
])
whitelist
=
Name
WhitelistProcessor
(
whitelist
=
[
sentinel
.
allowed_event
])
self
.
assert_event_passed_through
(
whitelist
,
{
'name'
:
sentinel
.
allowed_event
})
self
.
assert_event_passed_through
(
whitelist
,
{
'name'
:
sentinel
.
allowed_event
})
def
assert_event_passed_through
(
self
,
whitelist
,
event
):
def
assert_event_passed_through
(
self
,
whitelist
,
event
):
"""Assert that the whitelist allowed the event processing to proce
de
"""
"""Assert that the whitelist allowed the event processing to proce
ed
"""
self
.
assertEquals
(
whitelist
(
event
),
event
)
self
.
assertEquals
(
whitelist
(
event
),
event
)
def
test_empty_whitelist
(
self
):
def
test_empty_whitelist
(
self
):
whitelist
=
WhitelistProcessor
(
whitelist
=
[])
whitelist
=
Name
WhitelistProcessor
(
whitelist
=
[])
with
self
.
assertRaises
(
EventEmissionExit
):
with
self
.
assertRaises
(
EventEmissionExit
):
whitelist
({
'name'
:
sentinel
.
not_allowed_event
})
whitelist
({
'name'
:
sentinel
.
not_allowed_event
})
def
test_multi_entry_whitelist
(
self
):
def
test_multi_entry_whitelist
(
self
):
whitelist
=
WhitelistProcessor
(
whitelist
=
[
sentinel
.
allowed_event
,
sentinel
.
another_event
])
whitelist
=
Name
WhitelistProcessor
(
whitelist
=
[
sentinel
.
allowed_event
,
sentinel
.
another_event
])
with
self
.
assertRaises
(
EventEmissionExit
):
with
self
.
assertRaises
(
EventEmissionExit
):
whitelist
({
'name'
:
sentinel
.
not_allowed_event
})
whitelist
({
'name'
:
sentinel
.
not_allowed_event
})
self
.
assert_event_passed_through
(
whitelist
,
{
'name'
:
sentinel
.
allowed_event
})
self
.
assert_event_passed_through
(
whitelist
,
{
'name'
:
sentinel
.
allowed_event
})
self
.
assert_event_passed_through
(
whitelist
,
{
'name'
:
sentinel
.
another_event
})
self
.
assert_event_passed_through
(
whitelist
,
{
'name'
:
sentinel
.
another_event
})
def
test_no_whitelist_param
(
self
):
with
self
.
assert_initialization_fails
():
NameWhitelistProcessor
()
def
assert_initialization_fails
(
self
):
"""Assert that the constructor raises the expected initialization exception"""
return
self
.
assertRaisesRegexp
(
TypeError
,
r'The NameWhitelistProcessor must be passed'
)
def
test_whitelist_param_not_iterable
(
self
):
with
self
.
assert_initialization_fails
():
NameWhitelistProcessor
(
10
)
def
test_whitelist_param_just_a_string
(
self
):
with
self
.
assert_initialization_fails
():
NameWhitelistProcessor
(
'foobar'
)
def
test_whitelist_param_is_none
(
self
):
with
self
.
assert_initialization_fails
():
NameWhitelistProcessor
(
None
)
def
test_initialize_with_set
(
self
):
self
.
assert_properly_configured
(
frozenset
([
sentinel
.
allowed_event
]))
def
assert_properly_configured
(
self
,
allowed_names
):
"""Assert that whitelist was configured properly by correctly passing and/or filtering events"""
whitelist
=
NameWhitelistProcessor
(
whitelist
=
allowed_names
)
self
.
assert_event_passed_through
(
whitelist
,
{
'name'
:
sentinel
.
allowed_event
})
with
self
.
assertRaises
(
EventEmissionExit
):
whitelist
({
'name'
:
sentinel
.
not_allowed_event
})
def
test_initialize_with_dict
(
self
):
self
.
assert_properly_configured
({
sentinel
.
allowed_event
:
sentinel
.
discarded
})
eventtracking/processors/whitelist.py
View file @
66d523ae
...
@@ -3,16 +3,25 @@
...
@@ -3,16 +3,25 @@
from
eventtracking.processors.exceptions
import
EventEmissionExit
from
eventtracking.processors.exceptions
import
EventEmissionExit
class
WhitelistProcessor
(
object
):
class
Name
WhitelistProcessor
(
object
):
"""
"""
Filter out events whose names aren't on a pre-configured whitelist.
Filter out events whose names aren't on a pre-configured whitelist.
`whitelist` is an iterable containing event names that should be allowed to pass.
`whitelist` is an iterable co
llection co
ntaining event names that should be allowed to pass.
"""
"""
def
__init__
(
self
,
**
kwargs
):
def
__init__
(
self
,
whitelist
=
None
,
**
_kwargs
):
self
.
whitelist
=
frozenset
(
kwargs
.
get
(
'whitelist'
,
[]))
try
:
if
isinstance
(
whitelist
,
basestring
):
raise
TypeError
self
.
whitelist
=
frozenset
(
whitelist
)
except
TypeError
:
raise
TypeError
(
'The NameWhitelistProcessor must be passed a collection of allowed names '
'using the "whitelist" parameter'
)
def
__call__
(
self
,
event
):
def
__call__
(
self
,
event
):
if
event
[
'name'
]
not
in
self
.
whitelist
:
if
event
[
'name'
]
not
in
self
.
whitelist
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment