From 5b66c65c48f8c0bd598836505e28c1f19a7865d2 Mon Sep 17 00:00:00 2001 From: Thierry Jossermoz Date: Thu, 16 Jun 2016 18:02:30 +1200 Subject: [PATCH] Signals updates --- predicthq/endpoints/schemas.py | 14 ++ predicthq/endpoints/v1/events/schemas.py | 3 +- predicthq/endpoints/v1/signals/schemas.py | 33 ++-- setup.py | 2 +- tests/endpoints/v1/events_tests.py | 6 +- tests/endpoints/v1/signals_tests.py | 2 +- .../signals_test/test_analysis.json | 164 ++++++------------ .../signals_test/test_summary.json | 42 ++--- 8 files changed, 109 insertions(+), 157 deletions(-) diff --git a/predicthq/endpoints/schemas.py b/predicthq/endpoints/schemas.py index 48ab0e2..308b2a1 100644 --- a/predicthq/endpoints/schemas.py +++ b/predicthq/endpoints/schemas.py @@ -129,6 +129,20 @@ class Options: exact = ListType(StringType) +class Signal(Model): + + class Options: + serialize_when_none = False + + id = StringType(required=True) + analysis_from = DateTimeType() + analysis_to = DateTimeType() + analysis_tz = StringType(choices=pytz.all_timezones) + significance = FloatType(min_value=0, max_value=100) + metric = StringType(choices=('demand', 'lead', 'span')) + explain = DateType() + + class DateTimeRange(Model): class Options: diff --git a/predicthq/endpoints/v1/events/schemas.py b/predicthq/endpoints/v1/events/schemas.py index 1b715a6..3ef8eb9 100644 --- a/predicthq/endpoints/v1/events/schemas.py +++ b/predicthq/endpoints/v1/events/schemas.py @@ -4,7 +4,7 @@ from predicthq.endpoints.schemas import PaginatedMixin, SortableMixin, Model, ResultSet, \ ListType, StringType, GeoJSONPointType, StringListType, StringModelType, Area, \ ModelType, IntRange, IntType, DateTimeRange, DateTimeType, FloatType, ResultType, \ - DictType, DateType, Place + DictType, DateType, Place, Signal class SearchParams(PaginatedMixin, SortableMixin, Model): @@ -24,6 +24,7 @@ class Options: country = ListType(StringType) within = StringListType(StringModelType(Area), separator="+") place = ModelType(Place) + signal = ModelType(Signal) class Event(Model): diff --git a/predicthq/endpoints/v1/signals/schemas.py b/predicthq/endpoints/v1/signals/schemas.py index 6c3081e..a409349 100644 --- a/predicthq/endpoints/v1/signals/schemas.py +++ b/predicthq/endpoints/v1/signals/schemas.py @@ -154,34 +154,27 @@ class Dimensions(Model): # @todo: Support custom dimensions from signal -class DailyAnalysisDetailsComponent(Model): +class MeanAnalysisComponent(Model): - count = IntType() - min = IntType() - max = IntType() - avg = FloatType() - sum = IntType() - sum_of_squares = IntType() - variance = FloatType() + mean = FloatType() std_deviation = FloatType() - std_deviation_bounds = DictType(FloatType) - percentiles = DictType(FloatType) + expected = FloatType() + excess = FloatType() -class DailyAnalysisDetails(Model): +class CountAnalysisComponent(Model): - lead = ModelType(DailyAnalysisDetailsComponent) - span = ModelType(DailyAnalysisDetailsComponent) + count = IntType() + expected = FloatType() + excess = FloatType() class DailyAnalysis(Model): date = DateType() - trend = FloatType() - actual = FloatType() - expected = FloatType() - excess = FloatType() - details = ModelType(DailyAnalysisDetails) + demand = ModelType(CountAnalysisComponent) + lead = ModelType(MeanAnalysisComponent) + span = ModelType(MeanAnalysisComponent) class AnalysisResultSet(ResultSet): @@ -199,9 +192,7 @@ class Options: initiated = ModelType(DateTimeRange) completed = ModelType(DateTimeRange) within = StringListType(StringModelType(Area), separator="+") - significance = IntType(min_value=0, max_value=100) - lead = BooleanType(default=False) - span = BooleanType(default=False) + significance = FloatType(min_value=0, max_value=100) place = ModelType(Place) # @todo: Support custom dimensions from signal diff --git a/setup.py b/setup.py index 629cecd..c6a49ce 100644 --- a/setup.py +++ b/setup.py @@ -40,7 +40,7 @@ def read(*parts): ], tests_require=[ "nose==1.3.7", - "coverage==4.0.3", + "coverage>=4.0.0", "responses==0.5.1", "mock==1.3.0", ], diff --git a/tests/endpoints/v1/events_tests.py b/tests/endpoints/v1/events_tests.py index f8d691f..517fb2b 100644 --- a/tests/endpoints/v1/events_tests.py +++ b/tests/endpoints/v1/events_tests.py @@ -16,12 +16,14 @@ def test_search_params(self, client): client.events.search(id="id", q="query", rank_level=[4,5], rank__gt=85, country=["NZ", "AU"], within__radius="2km", within__longitude=-71.0432, within__latitude=42.346, label=["label1", "label2"], category="category", - start__gte="2016-03-01", start__lt=datetime(2016, 4, 1), start__tz="Pacific/Auckland",) + start__gte="2016-03-01", start__lt=datetime(2016, 4, 1), start__tz="Pacific/Auckland", + signal__id='zVNLr8tHvWQw', signal__explain=datetime(2016, 4, 1)) client.request.assert_called_once_with('get', '/v1/events/', params={ 'id': 'id', 'rank.gt': 85, 'rank_level': '4,5', 'category': 'category', 'country': 'NZ,AU', 'within': '2km@42.346,-71.0432', 'label': 'label1,label2', 'q': 'query', - 'start.lt': '2016-04-01T00:00:00.000000', 'start.gte': '2016-03-01T00:00:00.000000', 'start.tz': 'Pacific/Auckland'}) + 'start.lt': '2016-04-01T00:00:00.000000', 'start.gte': '2016-03-01T00:00:00.000000', 'start.tz': 'Pacific/Auckland', + 'signal.id': 'zVNLr8tHvWQw', 'signal.explain': '2016-04-01'}) @with_mock_client() def test_search_for_account(self, client): diff --git a/tests/endpoints/v1/signals_tests.py b/tests/endpoints/v1/signals_tests.py index 3bed7b7..fc281ca 100644 --- a/tests/endpoints/v1/signals_tests.py +++ b/tests/endpoints/v1/signals_tests.py @@ -158,6 +158,6 @@ def test_summary(self, client, responses): @with_mock_responses() def test_analysis(self, client, responses): signal = client.signals.get(id="zVNLr8tHvWQw") - analysis = signal.analysis(lead=True, span=True) + analysis = signal.analysis() self.assertEqual(analysis.count, 365) # @todo: add tests for custom signal dimensions diff --git a/tests/fixtures/requests_responses/signals_test/test_analysis.json b/tests/fixtures/requests_responses/signals_test/test_analysis.json index e8c6901..646523d 100644 --- a/tests/fixtures/requests_responses/signals_test/test_analysis.json +++ b/tests/fixtures/requests_responses/signals_test/test_analysis.json @@ -26,7 +26,7 @@ { "method": "GET", "match_querystring": true, - "url": "/v1/signals/zVNLr8tHvWQw/analysis/?span=1&lead=1", + "url": "/v1/signals/zVNLr8tHvWQw/analysis/", "status": 200, "content_type": "application/json", "body": { @@ -35,122 +35,64 @@ "previous": null, "results": [ { - "actual": 329, - "trend": 326.7875867369319, - "expected": 407.6649175062919, - "details": { - "span": { - "count": 329, - "min": 0, - "sum_of_squares": 11645, - "max": 29, - "sum": 1575, - "std_deviation": 3.532354314042595, - "percentiles": { - "5.0": 0, - "25.0": 3, - "1.0": 0, - "95.0": 11, - "75.0": 6, - "99.0": 16, - "50.0": 4 - }, - "std_deviation_bounds": { - "upper": 11.851942670638381, - "lower": -2.2774745855319978 - }, - "variance": 12.47752699993533, - "avg": 4.787234042553192 - }, - "lead": { - "count": 329, - "min": 0, - "sum_of_squares": 729639, - "max": 281, - "sum": 7951, - "std_deviation": 40.41899871791781, - "percentiles": { - "5.0": 0, - "25.0": 1.125, - "1.0": 0, - "95.0": 115.19999999999959, - "75.0": 27.999999999999996, - "99.0": 189.35999999999888, - "50.0": 9 - }, - "std_deviation_bounds": { - "upper": 105.00517068811526, - "lower": -56.67082418355598 - }, - "variance": 1633.6954573590413, - "avg": 24.167173252279635 - } + "date": "2014-01-01T00:00:00", + "demand": { + "count": 319, + "expected": 319, + "excess": 0 }, - "excess": -78.66491750629189, - "date": "2015-01-01T00:00:00" + "lead": { + "expected": 29.877742946708462, + "std_deviation": 44.753600299118915, + "excess": 0, + "mean": 29.877742946708462 + }, + "span": { + "expected": 5.554858934169279, + "std_deviation": 4.659836385200691, + "mean": 5.554858934169279, + "excess": 0 + } }, { - "actual": 342, - "trend": 325.63983679188283, - "expected": 475.5862667153484, - "details": { - "span": { - "count": 342, - "min": 0, - "sum_of_squares": 14740, - "max": 34, - "sum": 1762, - "std_deviation": 4.0688854916316, - "percentiles": { - "5.0": 1, - "25.0": 2, - "1.0": 0, - "95.0": 13, - "75.0": 7, - "99.0": 19, - "50.0": 4.166666666666667 - }, - "std_deviation_bounds": { - "upper": 13.28981776688893, - "lower": -2.9857241996374695 - }, - "variance": 16.555829144010126, - "avg": 5.152046783625731 - }, - "lead": { - "count": 342, - "min": 0, - "sum_of_squares": 1107796, - "max": 301, - "sum": 10220, - "std_deviation": 48.43731469724757, - "percentiles": { - "5.0": 0, - "25.0": 2, - "1.0": 0, - "95.0": 131, - "75.0": 37.5, - "99.0": 227.20999999999952, - "50.0": 9 - }, - "std_deviation_bounds": { - "upper": 126.75767033016766, - "lower": -66.99158845882263 - }, - "variance": 2346.1734550801957, - "avg": 29.883040935672515 - } + "date": "2014-01-02T00:00:00", + "demand": { + "count": 427, + "expected": 427, + "excess": 0 + }, + "lead": { + "expected": 33.95316159250586, + "std_deviation": 48.977819938991054, + "excess": 0, + "mean": 33.95316159250586 }, - "excess": -133.58626671534842, - "date": "2015-01-02T00:00:00" + "span": { + "expected": 4.948477751756441, + "std_deviation": 3.819359814466576, + "mean": 4.948477751756441, + "excess": 0 + } }, { - "actual": 0, - "trend": 4.974674771228433, - "expected": 3.9252131844241966, - "details": {}, - "excess": -3.9252131844241966, - "date": "2015-12-07T00:00:00" + "date": "2014-12-24T00:00:00", + "demand": { + "count": 621, + "expected": 509.0973596475694, + "excess": 111.90264035243055 + }, + "lead": { + "expected": 35.075696145743926, + "std_deviation": 49.04110699946923, + "excess": 1.9967676223720208, + "mean": 37.072463768115945 + }, + "span": { + "expected": 5.040257648953301, + "std_deviation": 3.590556938479606, + "mean": 5.040257648953301, + "excess": 0 + } } ] } diff --git a/tests/fixtures/requests_responses/signals_test/test_summary.json b/tests/fixtures/requests_responses/signals_test/test_summary.json index 5336da3..97f628d 100644 --- a/tests/fixtures/requests_responses/signals_test/test_summary.json +++ b/tests/fixtures/requests_responses/signals_test/test_summary.json @@ -57,26 +57,28 @@ -27.46846 ] }, - "country": { - "type": "category", - "options": [ - { - "count": 2445, - "name": "NZ" - }, - { - "count": 282, - "name": "AU" - } - ] - }, - "revenue": { - "count": 2729, - "min": 0, - "max": 754.1099853515625, - "std_deviation": 76.9167076432597, - "avg": 51.462359763100366, - "type": "number" + "custom": { + "country": { + "type": "category", + "options": [ + { + "count": 2445, + "name": "NZ" + }, + { + "count": 282, + "name": "AU" + } + ] + }, + "revenue": { + "count": 2729, + "min": 0, + "max": 754.1099853515625, + "std_deviation": 76.9167076432597, + "avg": 51.462359763100366, + "type": "number" + } } } }