def test_accumulate_hits_monthly(self): """ Test that the accumulate hits function works as expected for monthly hits. """ ts1 = datetime.datetime(year=2014, month=2, day=1) ts2 = datetime.datetime(year=2014, month=2, day=2) ts3 = datetime.datetime(year=2014, month=3, day=2) original_hits = [ Hits(ts=ts1, hits=5, app_id=2), Hits(ts=ts2, hits=6, app_id=2), Hits(ts=ts3, hits=8, app_id=2) ] # If using a monthly granularity, hits 1 and 2 should be accumulated, hits 2 not. accumulated = accumulate_hits(original_hits, "monthly") assert len(accumulated) == 2 s = sorted(accumulated) h1 = accumulated[s[0]] h2 = accumulated[s[1]] assert h1.hits == 11 # 5+6 assert h2.hits == 8
def test_ajax_call(self): """ Check the AJAX call itself. """ ts1 = datetime.datetime(year=2014, month=2, day=1) ts2 = datetime.datetime(year=2014, month=2, day=2) ts3 = datetime.datetime(year=2014, month=3, day=2) original_hits = [ Hits(ts=ts1, hits=5, app_id=2), Hits(ts=ts2, hits=6, app_id=2), Hits(ts=ts3, hits=8, app_id=2) ] s = sqla.db() for h in original_hits: s.add(h) s.commit() ret = self.flask_app.get("/ajax/hits/2?granularity=monthly") assert ret.status_code == 200 resp = json.loads(ret.data) h1 = resp[0] h2 = resp[1] print resp assert h1["hits"] == 11 assert h2["hits"] == 8
def fill(): start_date = datetime.datetime(year=2014, month=1, day=1) end_date = datetime.datetime(year=2015, month=1, day=1) for single_date in daterange(start_date, end_date): hits = random.randint(0, 15) s = sqla.db() u = Hits(hits=hits, user_id=2, ts=single_date) s.add(u) s.commit() return "Ok"
def accumulate_hits(hits, granularity): """ Accumulates the specified hits according to the specified granularity. @param hits: List of hits, with any time. @param granularity: yearly, monthly, weekly, daily or hourly Returns a simple dictionary of (accumulated) Hits, linked to the rounded timestamps. """ # Dictionary to store the hits organized by their granularity. hits_by_granularity = defaultdict(list) # Define the adaptors for each granularity if granularity == "yearly": adapt = lambda t: datetime.datetime(year=t.year, month=1, day=1) elif granularity == "monthly": adapt = lambda t: datetime.datetime(year=t.year, month=t.month, day=1) elif granularity == "weekly": # NOT YET SUPPORTED. TODO. adapt = None pass elif granularity == "daily": adapt = lambda t: datetime.datetime( year=t.year, month=t.month, day=t.day) elif granularity == "hourly": adapt = lambda t: datetime.datetime( year=t.year, month=t.month, day=t.day, hour=t.hour) else: raise Exception("Unknown granularity specified") for h in hits: # Round the detailed ts to the granularity, so that no matter what # the sub-granularity unit, they compare equally. ts = adapt(h.ts) # Add the rounded hit to the dictionary, using the rounded ts as the key. hits_by_granularity[ts].append({"hits": h.hits, "uid": h.app_id}) # Add up all the hits within the same granular date, to form a new simple dictionary. accumulated_hits = {} for ts, hits_list in hits_by_granularity.iteritems(): hits_number = 0 for h in hits_list: hits_number += h["hits"] appid = hits_list[0]["uid"] # Just get the app_id of one of them. hits = Hits(hits=hits_number, ts=ts, app_id=appid) accumulated_hits[ts] = hits return accumulated_hits
def addhits(): if request.method == "POST": # Read the input. isodate = request.values.get("datetime") if isodate is None: flash("Please, provide a date and time", "error") return render_template("add_hits.html") try: session["last_datetime"] = isodate isodate = dateutil.parser.parse(isodate) except: flash("Could not parse the date you provided", "error") return render_template("add_hits.html") hits = request.values.get("hits") if hits is None: flash("Please, provide the number of hits", "error") return render_template("add_hits.html") try: hits = int(hits) except: flash("The number of hits must be a valid integer") return render_template("add_hits.html") appid = request.values.get("appid") if appid is None: flash("Please, provide an application ID", "error") return render_template("add_hits.html") try: session["last_appid"] = appid appid = int(appid) except: flash("The Application ID must be a valid integer") return render_template("add_hits.html") # Add the specified hits themselves. hits = Hits(ts=isodate, hits=hits, app_id=appid) # WARNING: Doing db() only results in issues from the tests when we # modify the DB. TODO: A better method for testing. s = sqla.db() s.add(hits) s.commit() flash("The specified hits have been added", "success") return redirect(url_for("addhits")) return render_template("add_hits.html")
def new_hits(uid): s = sqla.db() u = Hits(hits=1, user_id=uid) s.add(u) s.commit() return "Done"