예제 #1
0
파일: rs_to_pg.py 프로젝트: jvehent/splice
def main():
    print "So it begins..."
    target_db_uri = Environment.instance().config.SQLALCHEMY_DATABASE_URI
    target_connection = psycopg2.connect(target_db_uri)
    target_cursor = target_connection.cursor()

    db_uri = Environment.instance().config.SQLALCHEMY_BINDS['stats']
    connection = psycopg2.connect(db_uri)
    cursor = connection.cursor()

    try:
        for table_name, columns in TABLES:
            print "Copying ", table_name

            # first, we need to lock the source table (ideally)
            # the problem with this is that we would need to modify permissions for production to allow
            # the lock for the user configured in SQLALCHEMY_DATABASE_URI
            # cursor.execute("LOCK TABLE %s" % table_name)

            # we need to assert the table is empty
            print "Counting ", table_name
            target_cursor.execute("select count(*) from %s" % table_name)
            count, = target_cursor.fetchone()
            assert count == 0, "Table %s "

            col_string = ','.join(columns)
            str_string = ','.join(["%s"] * len(columns))
            target_query = StringIO()
            target_query.write('insert into %s(%s) values ' %
                               (table_name, col_string))
            print "Reading ", table_name
            cursor.execute('select %s from %s' % (col_string, table_name))
            for rec in cursor:
                target_query.write(
                    "(%s)," % target_cursor.mogrify(str_string, tuple(rec)))
            print "Writing ", table_name
            target_cursor.execute(target_query.getvalue()[:-1])

            # now we need to reset the sequence associated with the id for this table
            target_cursor.execute("select max(id) + 1 from %s" % table_name)
            nextone, = target_cursor.fetchone()
            print "Updating sequence for ", table_name
            target_cursor.execute("SELECT setval('%s_id_seq', %s, false)" %
                                  (table_name, nextone))
            print "Done ", table_name

    except Exception as e:
        print "Error ", e
        target_connection.rollback()
        connection.rollback()
    else:
        print "Good, well done, excellent."
        target_connection.commit()
        connection.commit()
    finally:
        connection.close()
        target_connection.close()
예제 #2
0
def main():
    print "So it begins..."
    target_db_uri = Environment.instance().config.SQLALCHEMY_DATABASE_URI
    target_connection = psycopg2.connect(target_db_uri)
    target_cursor = target_connection.cursor()

    db_uri = Environment.instance().config.SQLALCHEMY_BINDS['stats']
    connection = psycopg2.connect(db_uri)
    cursor = connection.cursor()

    try:
        for table_name, columns in TABLES:
            print "Copying ", table_name

            # first, we need to lock the source table (ideally)
            # the problem with this is that we would need to modify permissions for production to allow
            # the lock for the user configured in SQLALCHEMY_DATABASE_URI
            # cursor.execute("LOCK TABLE %s" % table_name)

            # we need to assert the table is empty
            print "Counting ", table_name
            target_cursor.execute("select count(*) from %s" % table_name)
            count, = target_cursor.fetchone()
            assert count == 0, "Table %s "

            col_string = ','.join(columns)
            str_string = ','.join(["%s"] * len(columns))
            target_query = StringIO()
            target_query.write('insert into %s(%s) values ' % (table_name, col_string))
            print "Reading ", table_name
            cursor.execute('select %s from %s' % (col_string, table_name))
            for rec in cursor:
                target_query.write("(%s)," % target_cursor.mogrify(str_string, tuple(rec)))
            print "Writing ", table_name
            target_cursor.execute(target_query.getvalue()[:-1])

            # now we need to reset the sequence associated with the id for this table
            target_cursor.execute("select max(id) + 1 from %s" % table_name)
            nextone, = target_cursor.fetchone()
            print "Updating sequence for ", table_name
            target_cursor.execute("SELECT setval('%s_id_seq', %s, false)" % (table_name, nextone))
            print "Done ", table_name

    except Exception as e:
        print "Error ", e
        target_connection.rollback()
        connection.rollback()
    else:
        print "Good, well done, excellent."
        target_connection.commit()
        connection.commit()
    finally:
        connection.close()
        target_connection.close()
예제 #3
0
파일: campaign.py 프로젝트: mozilla/splice
def get_campaigns(account_id=None,
                  past=True,
                  in_flight=True,
                  scheduled=True,
                  utctoday=None):
    from splice.environment import Environment

    env = Environment.instance()

    query = env.db.session.query(Campaign)

    if account_id is not None:
        query = query.filter(Campaign.account_id == account_id)

    if utctoday is None:
        utctoday = datetime.utcnow().date()

    rows = query.order_by(Campaign.id.desc()).all()

    campaigns = []
    for row in rows:
        ret = row_to_dict(row)
        countries = []
        for country in row.countries:
            countries.append(country.country_code)
        ret['countries'] = countries

        # filter based on start and end dates unless an account ID is specified
        if ((past and row.end_date.date() <= utctoday) or
            (in_flight
             and row.end_date.date() >= utctoday >= row.start_date.date())
                or (scheduled and row.start_date.date() >= utctoday)):
            campaigns.append(ret)

    return campaigns
예제 #4
0
파일: queries.py 프로젝트: jvehent/splice
def get_all_distributions(limit=100):
    """
    Obtain distributions, partitioned by channels with up to ``limit`` results
    for each channel
    """
    from splice.environment import Environment

    env = Environment.instance()

    dist_cte = (env.db.session.query(
        Distribution.channel_id, Distribution.url, Distribution.created_at,
        func.row_number().over(
            partition_by=Distribution.channel_id,
            order_by=Distribution.created_at.desc()).label('row_num'))).cte()

    stmt = (env.db.session.query(
        dist_cte.c.channel_id, dist_cte.c.url,
        dist_cte.c.created_at).filter(dist_cte.c.row_num <= limit).order_by(
            dist_cte.c.created_at.desc()))

    rows = stmt.all()

    channels = {}

    for row in rows:
        c_dists = channels.setdefault(row.channel_id, [])
        c_dists.append({'url': row.url, 'created_at': row.created_at})

    return channels
예제 #5
0
파일: queries.py 프로젝트: Mardak/splice
def tile_exists(target_url, bg_color, title, type, image_uri, enhanced_image_uri, locale, conn=None, *args, **kwargs):
    """
    Return the id of a tile having the data provided
    """
    from splice.environment import Environment
    env = Environment.instance()

    if conn is not None:
        sm = sessionmaker(bind=conn)
        session = sm()
    else:
        session = env.db.session

    # we add order_by in the query although it shouldn't be necessary
    # this is because of a previous bug where duplicate tiles could be created
    results = (
        session
        .query(Tile.id)
        .filter(Tile.target_url == target_url)
        .filter(Tile.bg_color == bg_color)
        .filter(Tile.title == title)
        .filter(Tile.image_uri == image_uri)
        .filter(Tile.enhanced_image_uri == enhanced_image_uri)
        .filter(Tile.locale == locale)
        .order_by(asc(Tile.id))
        .first()
    )

    if results:
        return results[0]

    return results
예제 #6
0
파일: queries.py 프로젝트: jvehent/splice
def insert_distribution(url, channel_id, deployed, scheduled_dt, *args,
                        **kwargs):
    from splice.environment import Environment

    # ensure that on insert, a distribution is either deployed or scheduled, not both
    if scheduled_dt is not None:
        deployed = False

    env = Environment.instance()
    conn = env.db.engine.connect()
    trans = conn.begin()
    try:
        conn.execute(text(
            "INSERT INTO distributions ("
            " url, channel_id, deployed, scheduled_start_date, created_at"
            ") "
            "VALUES ("
            " :url, :channel_id, :deployed, :scheduled_start_date, :created_at"
            ")"),
                     url=url,
                     channel_id=channel_id,
                     deployed=deployed,
                     scheduled_start_date=scheduled_dt,
                     created_at=datetime.utcnow())
        trans.commit()
    except:
        trans.rollback()
        raise
예제 #7
0
파일: campaign.py 프로젝트: mozilla/splice
def get_campaigns(account_id=None, past=True, in_flight=True, scheduled=True, utctoday=None):
    from splice.environment import Environment

    env = Environment.instance()

    query = env.db.session.query(Campaign)

    if account_id is not None:
        query = query.filter(Campaign.account_id == account_id)

    if utctoday is None:
        utctoday = datetime.utcnow().date()

    rows = query.order_by(Campaign.id.desc()).all()

    campaigns = []
    for row in rows:
        ret = row_to_dict(row)
        countries = []
        for country in row.countries:
            countries.append(country.country_code)
        ret['countries'] = countries

        # filter based on start and end dates unless an account ID is specified
        if ((past and row.end_date.date() <= utctoday) or
                (in_flight and row.end_date.date() >= utctoday >= row.start_date.date()) or
                (scheduled and row.start_date.date() >= utctoday)):
            campaigns.append(ret)

    return campaigns
예제 #8
0
def insert_distribution(url, channel_id, deployed, scheduled_dt, *args, **kwargs):
    from splice.environment import Environment

    # ensure that on insert, a distribution is either deployed or scheduled, not both
    if scheduled_dt is not None:
        deployed = False

    env = Environment.instance()
    conn = env.db.engine.connect()
    trans = conn.begin()
    try:
        conn.execute(
            text(
                "INSERT INTO distributions ("
                " url, channel_id, deployed, scheduled_start_date, created_at"
                ") "
                "VALUES ("
                " :url, :channel_id, :deployed, :scheduled_start_date, :created_at"
                ")"
            ),
            url=url,
            channel_id=channel_id,
            deployed=deployed,
            scheduled_start_date=scheduled_dt,
            created_at=datetime.utcnow()
        )
        trans.commit()
    except:
        trans.rollback()
        raise
예제 #9
0
파일: queries.py 프로젝트: jvehent/splice
def get_scheduled_distributions(minutes, dt_query=None):
    """
    Returns distributions scheduled from a point in time, and a leniency period
    within which a tasks could've been scheduled closed to that point.
    As a regular task, it is intended to run at least once hourly.
    :minutes: amount of time in the past from the query time which is still viable
    :dt_query: optionally set the date time to find schedules for
    """
    from splice.environment import Environment

    env = Environment.instance()

    if not minutes or not (0 < minutes < 60):
        raise ValueError(
            "minutes needs to be a number between 1..59 inclusive")

    if dt_query is None:
        dt_query = datetime.utcnow()

    # getting around PEP8 E712 warning. This is necessary for SQLAlchemy
    false_value = False

    min_query_dt = dt_query - timedelta(minutes=minutes)

    stmt = (env.db.session.query(Distribution).filter(
        Distribution.deployed == false_value).filter(
            Distribution.scheduled_start_date.between(min_query_dt, dt_query)))

    dists = stmt.all()

    return dists
예제 #10
0
def get_scheduled_distributions(minutes, dt_query=None):
    """
    Returns distributions scheduled from a point in time, and a leniency period
    within which a tasks could've been scheduled closed to that point.
    As a regular task, it is intended to run at least once hourly.
    :minutes: amount of time in the past from the query time which is still viable
    :dt_query: optionally set the date time to find schedules for
    """
    from splice.environment import Environment

    env = Environment.instance()

    if not minutes or not (0 < minutes < 60):
        raise ValueError("minutes needs to be a number between 1..59 inclusive")

    if dt_query is None:
        dt_query = datetime.utcnow()

    # getting around PEP8 E712 warning. This is necessary for SQLAlchemy
    false_value = False

    min_query_dt = dt_query - timedelta(minutes=minutes)

    stmt = (
        env.db.session
        .query(Distribution)
        .filter(Distribution.deployed == false_value)
        .filter(Distribution.scheduled_start_date.between(min_query_dt, dt_query))
    )

    dists = stmt.all()

    return dists
예제 #11
0
파일: tile.py 프로젝트: mozilla/splice
def get_tile(id):
    from splice.environment import Environment

    env = Environment.instance()

    row = (env.db.session.query(Tile).get(id))
    return row_to_dict(row) if row else None
예제 #12
0
def get_upcoming_distributions(limit=100, leniency_minutes=15, include_past=False):
    """
    Obtain distributions, partitioned by channels with up to ``limit`` results
    for each channel
    :leniency_minutes: have a leniency in minutes up to the present when looking for distributions
    :include_past: always return all past distributions
    """
    from splice.environment import Environment

    env = Environment.instance()

    # getting around PEP8 E712 warning. This is necessary for SQLAlchemy
    false_value = False

    dist_cte = (
        env.db.session
        .query(
            Distribution.id,
            Distribution.channel_id,
            Distribution.url,
            Distribution.created_at,
            Distribution.scheduled_start_date,
            func.row_number().over(
                partition_by=Distribution.channel_id,
                order_by=Distribution.scheduled_start_date.asc())
            .label('row_num')
        )
        .filter(Distribution.deployed == false_value))

    if not include_past:
        min_dt = datetime.utcnow() - timedelta(minutes=leniency_minutes)
        dist_cte = (
            dist_cte
            .filter(Distribution.scheduled_start_date >= min_dt))

    dist_cte = dist_cte.cte()

    stmt = (
        env.db.session
        .query(
            dist_cte.c.id,
            dist_cte.c.channel_id,
            dist_cte.c.url,
            dist_cte.c.created_at,
            dist_cte.c.scheduled_start_date)
        .filter(dist_cte.c.row_num <= limit)
        .order_by(dist_cte.c.scheduled_start_date.asc())
    )

    rows = stmt.all()

    channels = {}

    for row in rows:
        c_dists = channels.setdefault(row.channel_id, [])
        c_dists.append({'id': row.id, 'url': row.url, 'created_at': row.created_at, 'scheduled_at': row.scheduled_start_date})

    return channels
예제 #13
0
def get_upcoming_distributions(limit=100, leniency_minutes=15, include_past=False):
    """
    Obtain distributions, partitioned by channels with up to ``limit`` results
    for each channel
    :leniency_minutes: have a leniency in minutes up to the present when looking for distributions
    :include_past: always return all past distributions
    """
    from splice.environment import Environment

    env = Environment.instance()

    # getting around PEP8 E712 warning. This is necessary for SQLAlchemy
    false_value = False

    dist_cte = (
        env.db.session
        .query(
            Distribution.id,
            Distribution.channel_id,
            Distribution.url,
            Distribution.created_at,
            Distribution.scheduled_start_date,
            func.row_number().over(
                partition_by=Distribution.channel_id,
                order_by=Distribution.scheduled_start_date.asc())
            .label('row_num')
        )
        .filter(Distribution.deployed == false_value))

    if not include_past:
        min_dt = datetime.utcnow() - timedelta(minutes=leniency_minutes)
        dist_cte = (
            dist_cte
            .filter(Distribution.scheduled_start_date >= min_dt))

    dist_cte = dist_cte.cte()

    stmt = (
        env.db.session
        .query(
            dist_cte.c.id,
            dist_cte.c.channel_id,
            dist_cte.c.url,
            dist_cte.c.created_at,
            dist_cte.c.scheduled_start_date)
        .filter(dist_cte.c.row_num <= limit)
        .order_by(dist_cte.c.scheduled_start_date.asc())
    )

    rows = stmt.all()

    channels = {}

    for row in rows:
        c_dists = channels.setdefault(row.channel_id, [])
        c_dists.append({'id': row.id, 'url': row.url, 'created_at': row.created_at, 'scheduled_at': row.scheduled_start_date})

    return channels
예제 #14
0
파일: test_init.py 프로젝트: mozilla/splice
    def test_get_all_categories(self):
        """ Test for getting all categories"""
        url = url_for('api.init.init', target="categories")
        response = self.client.get(url)
        assert_equal(response.status_code, 200)
        categories = json.loads(response.data)['results']

        categories_fixture = Environment.instance()._load_categories()
        assert_equal(categories, categories_fixture)
예제 #15
0
파일: account.py 프로젝트: mozilla/splice
def get_accounts():
    from splice.environment import Environment

    env = Environment.instance()

    rows = (env.db.session.query(Account).order_by(Account.id.desc()).all())
    output = [row_to_dict(d) for d in rows]

    return output
예제 #16
0
def _update_image(bucket, image_url, tile_id, column='image_uri'):
    env = Environment.instance()
    if image_url and not image_url.startswith('http'):
        imgs = list(bucket.list(prefix="images/%s" % image_url))
        if len(imgs):
            uri = os.path.join('https://%s.s3.amazonaws.com' % env.config.S3['bucket'], imgs[0])
            print "updating %s for tile=%s" % (column, tile_id)
            return "update tiles set %s = '%s' where id = %s" % (column, uri, tile_id)
    return None
예제 #17
0
    def test_get_all_categories(self):
        """ Test for getting all categories"""
        url = url_for('api.init.init', target="categories")
        response = self.client.get(url)
        assert_equal(response.status_code, 200)
        categories = json.loads(response.data)['results']

        categories_fixture = Environment.instance()._load_categories()
        assert_equal(categories, categories_fixture)
예제 #18
0
파일: test_init.py 프로젝트: mozilla/splice
    def test_get_all_locale(self):
        """ Test for getting all locales"""
        url = url_for('api.init.init', target="locales")
        response = self.client.get(url)
        assert_equal(response.status_code, 200)
        locales = json.loads(response.data)['results']

        locales_fixture = Environment.instance()._load_locales()[:-1]
        locales_fixture.sort()
        assert_equal(locales, locales_fixture)
예제 #19
0
파일: test_init.py 프로젝트: mozilla/splice
    def test_get_all_countries(self):
        """ Test for getting all countries"""
        url = url_for('api.init.init', target="countries")
        response = self.client.get(url)
        assert_equal(response.status_code, 200)
        countries = json.loads(response.data)['results']

        countries_fixture = Environment.instance()._load_countries()[:-1]
        items = [{"country_code": code, "country_name": name} for code, name in countries_fixture]
        assert_equal(countries, items)
예제 #20
0
파일: account.py 프로젝트: mozilla/splice
def get_account(id):
    from splice.environment import Environment

    env = Environment.instance()

    row = (
        env.db.session
        .query(Account).get(id)
    )
    return row_to_dict(row) if row else None
예제 #21
0
    def test_get_all_locale(self):
        """ Test for getting all locales"""
        url = url_for('api.init.init', target="locales")
        response = self.client.get(url)
        assert_equal(response.status_code, 200)
        locales = json.loads(response.data)['results']

        locales_fixture = Environment.instance()._load_locales()[:-1]
        locales_fixture.sort()
        assert_equal(locales, locales_fixture)
예제 #22
0
파일: tile.py 프로젝트: mozilla/splice
def get_tiles(filters=None, limit_fields=None):
    from splice.environment import Environment

    fields = [getattr(Tile, field)
              for field in limit_fields] if limit_fields else [Tile]
    format_row = tuple_to_dict if limit_fields else row_to_dict

    rows = Environment.instance().db.session.query(*fields)
    rows = add_filters(rows, filters)
    rows = rows.all()

    return [format_row(r) for r in rows] if rows else None
예제 #23
0
    def test_get_all_countries(self):
        """ Test for getting all countries"""
        url = url_for('api.init.init', target="countries")
        response = self.client.get(url)
        assert_equal(response.status_code, 200)
        countries = json.loads(response.data)['results']

        countries_fixture = Environment.instance()._load_countries()[:-1]
        items = [{
            "country_code": code,
            "country_name": name
        } for code, name in countries_fixture]
        assert_equal(countries, items)
예제 #24
0
def session_scope():
    from splice.environment import Environment

    env = Environment.instance()
    session = env.db.session
    try:
        yield session
        session.commit()
    except:
        session.rollback()
        raise
    finally:
        session.close()
예제 #25
0
파일: s3_common.py 프로젝트: mozilla/splice
def setup_s3(bucket="bucket"):
    from splice.environment import Environment
    from boto.s3.cors import CORSConfiguration

    env = Environment.instance()
    bucket = env.s3.get_bucket(env.config.S3[bucket])
    cors = CORSConfiguration()
    cors.add_rule("GET", "*", allowed_header="*")
    bucket.set_cors(cors)
    headers = {
        'Cache-Control': 'public, max-age=31536000',
        'Content-Disposition': 'inline',
    }
    return bucket, headers
예제 #26
0
def get_content(name):
    from splice.environment import Environment

    env = Environment.instance()

    row = env.db.session.query(Content).filter(Content.name == name).first()
    c = row_to_dict(row) if row else None
    if c is not None:
        versions = []
        for version in row.versions:
            versions.append(row_to_dict(version))
        c['versions'] = versions

    return c
예제 #27
0
파일: content.py 프로젝트: mozilla/splice
def get_content(name):
    from splice.environment import Environment

    env = Environment.instance()

    row = env.db.session.query(Content).filter(Content.name == name).first()
    c = row_to_dict(row) if row else None
    if c is not None:
        versions = []
        for version in row.versions:
            versions.append(row_to_dict(version))
        c['versions'] = versions

    return c
예제 #28
0
파일: queries.py 프로젝트: jvehent/splice
def get_channels(limit=100):
    from splice.environment import Environment

    env = Environment.instance()

    rows = (env.db.session.query(Channel.id, Channel.name,
                                 Channel.created_at).order_by(
                                     Channel.id.asc()).limit(limit).all())

    # ensure items are a list of dicts
    # KeyedTuples may serialize differently on other systems
    output = [d._asdict() for d in rows]

    return output
예제 #29
0
파일: account.py 프로젝트: mozilla/splice
def get_accounts():
    from splice.environment import Environment

    env = Environment.instance()

    rows = (
        env.db.session
        .query(Account)
        .order_by(Account.id.desc())
        .all()
    )
    output = [row_to_dict(d) for d in rows]

    return output
예제 #30
0
파일: campaign.py 프로젝트: mozilla/splice
def get_campaign(campaign_id):
    from splice.environment import Environment

    env = Environment.instance()

    row = (env.db.session.query(Campaign).get(campaign_id))
    if row:
        ret = row_to_dict(row)
        countries = []
        for country in row.countries:
            countries.append(country.country_code)
        ret['countries'] = countries
        return ret
    else:
        return None
예제 #31
0
def tile_exists(target_url, bg_color, title, typ, image_uri, enhanced_image_uri, locale,
                frecent_sites, time_limits, frequency_caps, adgroup_name, explanation, check_inadjacency, channel_id, conn=None, *args, **kwargs):
    """
    Return the id of a tile having the data provided
    """
    from splice.environment import Environment
    env = Environment.instance()

    if conn is not None:
        sm = sessionmaker(bind=conn)
        session = sm()
    else:
        session = env.db.session

    # we add order_by in the query although it shouldn't be necessary
    # this is because of a previous bug where duplicate tiles could be created
    results = (
        session
        .query(Tile.id, Tile.adgroup_id)
        .filter(Tile.target_url == target_url)
        .filter(Tile.bg_color == bg_color)
        .filter(Tile.title == title)
        .filter(Tile.type == typ)
        .filter(Tile.image_uri == image_uri)
        .filter(Tile.enhanced_image_uri == enhanced_image_uri)
        .filter(Adgroup.locale == locale)
        .filter(Adgroup.start_date == time_limits.get('start'))
        .filter(Adgroup.end_date == time_limits.get('end'))
        .filter(Adgroup.start_date_dt == time_limits.get('start_dt'))
        .filter(Adgroup.end_date_dt == time_limits.get('end_dt'))
        .filter(Adgroup.frequency_cap_daily == frequency_caps['daily'])
        .filter(Adgroup.frequency_cap_total == frequency_caps['total'])
        .filter(Adgroup.name == adgroup_name)
        .filter(Adgroup.explanation == explanation)
        .filter(Adgroup.check_inadjacency == check_inadjacency)
        .filter(Adgroup.channel_id == channel_id)
        .join(Adgroup.tiles)
        .order_by(asc(Tile.id))
    )

    if results:
        for tile_id, adgroup_id in results:
            # now check frecent sites for this tile
            db_frecents = get_frecent_sites_for_tile(tile_id, conn)
            if db_frecents == sorted(set(frecent_sites)):
                return tile_id, adgroup_id

    return None, None
예제 #32
0
def get_adgroup(id):
    from splice.environment import Environment

    env = Environment.instance()

    row = (env.db.session.query(Adgroup).get(id))
    if row is None:
        return None

    new = row_to_dict(row)
    categories = []
    for category in row.categories:
        categories.append(category.category)
    new['categories'] = categories

    return new
예제 #33
0
    def test_single_creative_upload_endpoint(self):
        """Test the API endpoint for the single creative upload"""
        from splice.environment import Environment

        env = Environment.instance()
        url = url_for('api.tile.handler_creative_upload')
        with zipfile.ZipFile(self.zip_file, "r") as zf:
            f = zf.getinfo("samples/firefox_mdn_a.png")
            data = {'creative': (StringIO.StringIO(zf.read(f)), 'creative.png')}
            response = self.client.post(url, data=data)
            assert_equal(response.status_code, 200)
            creative_url = json.loads(response.data)['result']
            bucket = env.s3.get_bucket(env.config.S3["bucket"])
            s3_key = os.path.basename(creative_url)
            key = bucket.get_key(s3_key)
            self.assertIsNotNone(key)
예제 #34
0
def get_contents():
    from splice.environment import Environment

    env = Environment.instance()

    rows = (env.db.session.query(Content).order_by(Content.id.desc()).all())

    output = []
    for d in rows:
        versions = []
        for version in d.versions:
            versions.append(row_to_dict(version))
        c = row_to_dict(d)
        c['versions'] = versions
        output.append(c)

    return output
예제 #35
0
파일: queries.py 프로젝트: imclab/splice
def get_adgroups():
    from splice.environment import Environment

    env = Environment.instance()

    rows = (
        env.db.session
        .query(Adgroup.id, Adgroup.locale)
        .order_by(Adgroup.id)
        .all()
    )

    # ensure items are a list of dicts
    # KeyedTuples may serialize differently on other systems
    output = [d._asdict() for d in rows]

    return output
예제 #36
0
파일: queries.py 프로젝트: imclab/splice
def get_tiles():
    from splice.environment import Environment

    env = Environment.instance()

    rows = (
        env.db.session
        .query(Tile.id, Tile.adgroup_id, Tile.title, Tile.type, Tile.bg_color, Tile.target_url)
        .order_by(Tile.id.asc())
        .all()
    )

    # ensure items are a list of dicts
    # KeyedTuples may serialize differently on other systems
    output = [d._asdict() for d in rows]

    return output
예제 #37
0
파일: queries.py 프로젝트: jvehent/splice
def unschedule_distribution(dist_id):
    """
    Remove a distribution id if it is scheduled but not deployed yet
    """
    from splice.environment import Environment

    env = Environment.instance()

    # getting around PEP8 E711 warning. This is necessary for SQLAlchemy
    none_value = None

    stmt = (env.db.session.query(Distribution).filter(
        Distribution.id == dist_id).filter(
            Distribution.scheduled_start_date != none_value))

    dist = stmt.one()
    dist.scheduled_start_date = None
    env.db.session.commit()
예제 #38
0
def get_adgroups_by_campaign_id(campaign_id):
    from splice.environment import Environment

    env = Environment.instance()

    rows = (env.db.session.query(Adgroup).filter(
        Adgroup.campaign_id == campaign_id).order_by(Adgroup.id.desc()).all())

    output = []
    for d in rows:
        new = row_to_dict(d)
        categories = []
        for category in d.categories:
            categories.append(category.category)
        new['categories'] = categories
        output.append(new)

    return output
예제 #39
0
    def test_single_creative_upload_endpoint(self):
        """Test the API endpoint for the single creative upload"""
        from splice.environment import Environment

        env = Environment.instance()
        url = url_for('api.tile.handler_creative_upload')
        with zipfile.ZipFile(self.zip_file, "r") as zf:
            f = zf.getinfo("samples/firefox_mdn_a.png")
            data = {
                'creative': (StringIO.StringIO(zf.read(f)), 'creative.png')
            }
            response = self.client.post(url, data=data)
            assert_equal(response.status_code, 200)
            creative_url = json.loads(response.data)['result']
            bucket = env.s3.get_bucket(env.config.S3["bucket"])
            s3_key = os.path.basename(creative_url)
            key = bucket.get_key(s3_key)
            self.assertIsNotNone(key)
예제 #40
0
파일: campaign.py 프로젝트: mozilla/splice
def get_campaign(campaign_id):
    from splice.environment import Environment

    env = Environment.instance()

    row = (
        env.db.session
        .query(Campaign).get(campaign_id)
    )
    if row:
        ret = row_to_dict(row)
        countries = []
        for country in row.countries:
            countries.append(country.country_code)
        ret['countries'] = countries
        return ret
    else:
        return None
예제 #41
0
def get_channels(limit=100):
    from splice.environment import Environment

    env = Environment.instance()

    rows = (
        env.db.session
        .query(Channel.id, Channel.name, Channel.created_at)
        .order_by(Channel.id.asc())
        .limit(limit)
        .all()
    )

    # ensure items are a list of dicts
    # KeyedTuples may serialize differently on other systems
    output = [d._asdict() for d in rows]

    return output
예제 #42
0
파일: queries.py 프로젝트: Mardak/splice
def get_distributions(limit=100, *args, **kwargs):
    from splice.environment import Environment

    env = Environment.instance()

    rows = (
        env.db.session
        .query(Distribution.url, Distribution.created_at)
        .order_by(Distribution.id.desc())
        .limit(limit)
        .all()
    )

    # ensure items are lists of lists rather than KeyedTuples
    # KeyedTuples may serialize differently on other systems
    output = [list(d) for d in rows]

    return output
예제 #43
0
def switch_to_cdn_url(image_uri):
    """Switch the S3 URI with the CDN URI

    We store the S3 URI in the database to allow campaign managers to view the
    uploaded images without suffering from the CDN latency. When preparing to
    generate tiles for the Firefox, it's necessary to replace the S3 URIs with
    the CDN ones, as Firefox only allows images hosted on a trusted URI, e.g.
    "tiles.cdn.mozilla.net".

    See https://github.com/oyiptong/splice/issues/203 for more details.
    """
    from splice.environment import Environment

    env = Environment.instance()
    try:
        basename = os.path.basename(image_uri)
    except:
        basename = image_uri  # if the image_uri is a hash string, use it directly
    return os.path.join(env.config.CLOUDFRONT_BASE_URL, "images/%s" % basename)
예제 #44
0
파일: adgroup.py 프로젝트: mozilla/splice
def get_adgroup(id):
    from splice.environment import Environment

    env = Environment.instance()

    row = (
        env.db.session
        .query(Adgroup).get(id)
    )
    if row is None:
        return None

    new = row_to_dict(row)
    categories = []
    for category in row.categories:
        categories.append(category.category)
    new['categories'] = categories

    return new
예제 #45
0
def switch_to_cdn_url(image_uri):
    """Switch the S3 URI with the CDN URI

    We store the S3 URI in the database to allow campaign managers to view the
    uploaded images without suffering from the CDN latency. When preparing to
    generate tiles for the Firefox, it's necessary to replace the S3 URIs with
    the CDN ones, as Firefox only allows images hosted on a trusted URI, e.g.
    "tiles.cdn.mozilla.net".

    See https://github.com/oyiptong/splice/issues/203 for more details.
    """
    from splice.environment import Environment

    env = Environment.instance()
    try:
        basename = os.path.basename(image_uri)
    except:
        basename = image_uri  # if the image_uri is a hash string, use it directly
    return os.path.join(env.config.CLOUDFRONT_BASE_URL, "images/%s" % basename)
예제 #46
0
def get_stats(group_by, filters=None, limit=60):
    """
    Get aggregated stats based on a list of group_by fields and filters
    """
    from splice.environment import Environment
    env = Environment.instance()

    isd = aliased(impression_stats_daily)
    base_table = isd
    local_filters = filters.copy()

    has_cross_db_filters = bool(
        CROSS_DB_COLUMNS.intersection(filters)) if filters else False
    cross_db_group_by = list(CROSS_DB_COLUMNS.intersection(group_by))

    # Build base table and list of tiles
    if cross_db_group_by:
        base_table = build_subquery_table(env=env,
                                          stats_table=isd,
                                          group_by=group_by,
                                          cross_db_group_by=cross_db_group_by,
                                          filters=filters)
        # No tiles were found, so no stats
        if base_table is None:
            return None

    elif has_cross_db_filters:
        tiles_result = get_tiles(limit_fields=['id'], filters=filters)
        # No tiles were found, so no stats
        if not tiles_result:
            return None
        local_filters['tile_id'] = [t['id'] for t in tiles_result]

    # Build query
    rows = build_base_query(env=env, group_by=group_by, base_table=base_table)
    rows = add_filters(query=rows,
                       base_table=base_table,
                       filters=local_filters)
    rows = rows.order_by(base_table.c[group_by[0]]).limit(limit)
    rows = rows.all()

    return [tuple_to_dict(r) for r in rows] if rows else None
예제 #47
0
파일: queries.py 프로젝트: imclab/splice
def tile_exists(target_url, bg_color, title, typ, image_uri, enhanced_image_uri, locale,
                frecent_sites, time_limits, channel_id, conn=None, *args, **kwargs):
    """
    Return the id of a tile having the data provided
    """
    from splice.environment import Environment
    env = Environment.instance()

    if conn is not None:
        sm = sessionmaker(bind=conn)
        session = sm()
    else:
        session = env.db.session

    # we add order_by in the query although it shouldn't be necessary
    # this is because of a previous bug where duplicate tiles could be created
    results = (
        session
        .query(Tile.id, Tile.adgroup_id)
        .filter(Tile.target_url == target_url)
        .filter(Tile.bg_color == bg_color)
        .filter(Tile.title == title)
        .filter(Tile.image_uri == image_uri)
        .filter(Tile.enhanced_image_uri == enhanced_image_uri)
        .filter(Adgroup.locale == locale)
        .filter(Adgroup.start_date == time_limits.get('start'))
        .filter(Adgroup.end_date == time_limits.get('end'))
        .filter(Adgroup.start_date_dt == time_limits.get('start_dt'))
        .filter(Adgroup.end_date_dt == time_limits.get('end_dt'))
        .filter(Adgroup.channel_id == channel_id)
        .join(Adgroup.tiles)
        .order_by(asc(Tile.id))
    )

    if results:
        for tile_id, adgroup_id in results:
            # now check frecent sites for this tile
            db_frecents = get_frecent_sites_for_tile(tile_id, conn)
            if db_frecents == sorted(set(frecent_sites)):
                return tile_id, adgroup_id

    return None, None
예제 #48
0
def get_all_distributions(limit=100):
    """
    Obtain distributions, partitioned by channels with up to ``limit`` results
    for each channel
    """
    from splice.environment import Environment

    env = Environment.instance()

    dist_cte = (
        env.db.session
        .query(
            Distribution.channel_id,
            Distribution.url,
            Distribution.created_at,
            func.row_number().over(
                partition_by=Distribution.channel_id,
                order_by=Distribution.created_at.desc())
            .label('row_num')
        )
    ).cte()

    stmt = (
        env.db.session
        .query(
            dist_cte.c.channel_id,
            dist_cte.c.url,
            dist_cte.c.created_at)
        .filter(dist_cte.c.row_num <= limit)
        .order_by(dist_cte.c.created_at.desc())
    )

    rows = stmt.all()

    channels = {}

    for row in rows:
        c_dists = channels.setdefault(row.channel_id, [])
        c_dists.append({'url': row.url, 'created_at': row.created_at})

    return channels
예제 #49
0
def unschedule_distribution(dist_id):
    """
    Remove a distribution id if it is scheduled but not deployed yet
    """
    from splice.environment import Environment

    env = Environment.instance()

    # getting around PEP8 E711 warning. This is necessary for SQLAlchemy
    none_value = None

    stmt = (
        env.db.session
        .query(Distribution)
        .filter(Distribution.id == dist_id)
        .filter(Distribution.scheduled_start_date != none_value)
    )

    dist = stmt.one()
    dist.scheduled_start_date = None
    env.db.session.commit()
예제 #50
0
파일: tile.py 프로젝트: mozilla/splice
def get_tile_ids_by_group(group_by, filters=None):
    from splice.environment import Environment
    env = Environment.instance()

    group_by_field = {
        'category': AdgroupCategory.category,
        'account_id': Account.id,
        'campaign_id': Campaign.id,
        'adgroup_id': Adgroup.id
    }.get(group_by)

    rows = (env.db.session.query(
        group_by_field.label(group_by),
        func.array_agg(Tile.id).label('tile_ids')).select_from(Tile).group_by(
            group_by_field))

    rows = add_joins_for_group_by(query=rows, group_by=group_by)
    rows = add_filters(rows, filters, group_by)
    rows = rows.all()

    return [tuple_to_dict(r) for r in rows] if rows else None
예제 #51
0
파일: content.py 프로젝트: mozilla/splice
def get_contents():
    from splice.environment import Environment

    env = Environment.instance()

    rows = (
        env.db.session
        .query(Content)
        .order_by(Content.id.desc())
        .all()
    )

    output = []
    for d in rows:
        versions = []
        for version in d.versions:
            versions.append(row_to_dict(version))
        c = row_to_dict(d)
        c['versions'] = versions
        output.append(c)

    return output
예제 #52
0
파일: queries.py 프로젝트: Mardak/splice
def insert_tile(target_url, bg_color, title, type, image_uri, enhanced_image_uri, locale, conn=None, *args, **kwargs):

    from splice.environment import Environment
    env = Environment.instance()

    trans = None
    if conn is None:
        conn = env.db.engine.connect()
        trans = conn.begin()

    try:
        conn.execute(

            text(
                "INSERT INTO tiles ("
                " target_url, bg_color, title, type, image_uri, enhanced_image_uri, locale, created_at"
                ") "
                "VALUES ("
                " :target_url, :bg_color, :title, :type, :image_uri, :enhanced_image_uri, :locale, :created_at"
                ")"
            ),
            target_url=target_url,
            bg_color=bg_color,
            title=title,
            type=type,
            image_uri=image_uri,
            enhanced_image_uri=enhanced_image_uri,
            locale=locale,
            created_at=datetime.utcnow()
        )

        result = conn.execute("SELECT MAX(id) FROM tiles;").scalar()
        if trans is not None:
            trans.commit()
        return result
    except:
        if trans is not None:
            trans.rollback()
        raise
예제 #53
0
파일: webapp.py 프로젝트: mozilla/splice
def setup_routes(app):
    env = Environment.instance()
    global register_flask_restful

    if "signing" in env.config.ALLOWED_APPS:
        import splice.web.api.content
        splice.web.api.content.register_routes(app)

    if "tiles" in env.config.ALLOWED_APPS:
        import splice.web.views
        splice.web.views.register_routes(app)

        import splice.web.api.heartbeat
        splice.web.api.heartbeat.register_routes(app)

        if not register_flask_restful:
            import splice.web.api.init
            splice.web.api.init.register_routes(app)

            import splice.web.api.account
            splice.web.api.account.register_routes(app)

            import splice.web.api.campaign
            splice.web.api.campaign.register_routes(app)

            import splice.web.api.adgroup
            splice.web.api.adgroup.register_routes(app)

            import splice.web.api.tile
            splice.web.api.tile.register_routes(app)

            import splice.web.api.reporting
            splice.web.api.reporting.register_routes(app)

            import splice.web.api.distribution
            splice.web.api.distribution.register_routes(app)

            register_flask_restful = True
예제 #54
0
파일: webapp.py 프로젝트: mozilla/splice
def setup_routes(app):
    env = Environment.instance()
    global register_flask_restful

    if "signing" in env.config.ALLOWED_APPS:
        import splice.web.api.content
        splice.web.api.content.register_routes(app)

    if "tiles" in env.config.ALLOWED_APPS:
        import splice.web.views
        splice.web.views.register_routes(app)

        import splice.web.api.heartbeat
        splice.web.api.heartbeat.register_routes(app)

        if not register_flask_restful:
            import splice.web.api.init
            splice.web.api.init.register_routes(app)

            import splice.web.api.account
            splice.web.api.account.register_routes(app)

            import splice.web.api.campaign
            splice.web.api.campaign.register_routes(app)

            import splice.web.api.adgroup
            splice.web.api.adgroup.register_routes(app)

            import splice.web.api.tile
            splice.web.api.tile.register_routes(app)

            import splice.web.api.reporting
            splice.web.api.reporting.register_routes(app)

            import splice.web.api.distribution
            splice.web.api.distribution.register_routes(app)

            register_flask_restful = True
예제 #55
0
    def setUp(self):
        super(TestReporting, self).setUp()

        def values(fd, date_index=0):
            for line in fd:
                row = [el.decode('utf-8') for el in line.split(',')]
                # sqlalchemy doesn't like date strings....
                row[date_index] = datetime.strptime(row[date_index], "%Y-%m-%d")
                yield row

        # load db
        from splice.models import impression_stats_daily, newtab_stats_daily
        conn = Environment.instance().db.engine.connect()

        with open(self.get_fixture_path('impression_stats.csv')) as fd:
            for row in values(fd, 1):
                ins = impression_stats_daily.insert().values(row)
                conn.execute(ins)

        with open(self.get_fixture_path('newtabs.csv')) as fd:
            for row in values(fd):
                ins = newtab_stats_daily.insert().values(row)
                conn.execute(ins)
예제 #56
0
파일: adgroup.py 프로젝트: mozilla/splice
def get_adgroups_by_campaign_id(campaign_id):
    from splice.environment import Environment

    env = Environment.instance()

    rows = (
        env.db.session
        .query(Adgroup)
        .filter(Adgroup.campaign_id == campaign_id)
        .order_by(Adgroup.id.desc())
        .all()
    )

    output = []
    for d in rows:
        new = row_to_dict(d)
        categories = []
        for category in d.categories:
            categories.append(category.category)
        new['categories'] = categories
        output.append(new)

    return output
예제 #57
0
파일: queries.py 프로젝트: Mardak/splice
def insert_distribution(url, *args, **kwargs):
    from splice.environment import Environment

    env = Environment.instance()
    conn = env.db.engine.connect()
    trans = conn.begin()
    try:
        conn.execute(
            text(
                "INSERT INTO distributions ("
                " url, created_at"
                ") "
                "VALUES ("
                " :url, :created_at"
                ")"
            ),
            url=url,
            created_at=datetime.utcnow()
        )
        trans.commit()
    except:
        trans.rollback()
        raise
예제 #58
0
    def get(self, target):
        """Returns the init data including locales, countries, channels etc.

        Params: target string, [all|locales|countries|channels]
        """
        target = target.lower()
        if target == "all":
            locales = Environment.instance()._load_locales()[:-1]
            locales.sort()
            countries = Environment.instance()._load_countries()[:-1]
            country_items = [{"country_code": code, "country_name": name} for code, name in countries]
            channels = get_channels()
            categories = Environment.instance()._load_categories()
            data = {
                "countries": country_items,
                "channels": channels,
                "locales": locales,
                "categories": categories,
            }
            return {'result': marshal(data, all_fields)}
        elif target == "locales":
            # the last item is 'ERROR', client won't need this
            locales = Environment.instance()._load_locales()[:-1]
            locales.sort()
            return marshal({"results": locales}, locale_fields)
        elif target == "countries":
            # the last item is 'ERROR', client won't need this
            countries = Environment.instance()._load_countries()[:-1]
            country_items = [{"country_code": code, "country_name": name} for code, name in countries]
            return {'results': marshal(country_items, country_fields)}
        elif target == "channels":
            channels = get_channels()
            return {'results': marshal(channels, channel_fields)}
        elif target == "categories":
            categories = Environment.instance()._load_categories()
            return marshal({"results": categories}, category_fields)
        else:
            return {"message": "Unknown target, must be one of [all|locales|countries|channels]"}, 404
예제 #59
0
import calendar
from datetime import datetime, timedelta
from nose.tools import assert_equal
from flask import url_for, json
from mock import Mock, PropertyMock
from tests.base import BaseTestCase
from tests.test_scheduling import ScheduleTest
import splice.ingest
from splice.queries import (
    get_scheduled_distributions,
    get_all_distributions,
    get_channels)
from splice.environment import Environment

env = Environment.instance()


class TestAuthoring(BaseTestCase):
    def setUp(self):
        self.key_mock = Mock()
        self.key_mock.name = PropertyMock()
        self.bucket_mock = Mock()

        def bucket_get_key_mock(*args, **kwargs):
            return None
        self.bucket_mock.get_key = Mock(side_effect=bucket_get_key_mock)

        def get_key_mock(*args, **kwargs):
            return self.key_mock
        splice.ingest.Key = Mock(side_effect=get_key_mock)