def event_doctree_read(app, doctree):
    """Called by Sphinx during phase 1 (reading).

    * Add new Imgur IDs to the cache.

    :param sphinx.application.Sphinx app: Sphinx application object.
    :param docutils.nodes.document doctree: Tree of docutils nodes.
    """
    albums, images = set(), set()
    for node in (n for c in (ImgurTextNode, ImgurImageNode) for n in doctree.traverse(c)):
        if node.album:
            albums.add(node.imgur_id)
        else:
            images.add(node.imgur_id)
    initialize(app.builder.env.imgur_album_cache, app.builder.env.imgur_image_cache, albums, images)
def test_initialize():
    """Test function."""
    album_cache, image_cache = initialize(dict(), dict(), ['album1'], ['image1'])
    assert sorted(album_cache) == ['album1']
    assert sorted(image_cache) == ['image1']
    assert album_cache['album1'].title == ''
    assert image_cache['image1'].title == ''

    album_cache['album1'].title = 'Set1'
    image_cache['image1'].title = 'Set2'
    album_cache, image_cache = initialize(album_cache, image_cache, ['album1', 'album2'], ['image1', 'image2'])
    assert album_cache['album1'].title == 'Set1'
    assert image_cache['image1'].title == 'Set2'
    assert album_cache['album2'].title == ''
    assert image_cache['image2'].title == ''
def test_update_cache_one_image_in_album(app, freezer):
    """Test one image in an album outdated (but not other images in said album).

    :param app: conftest fixture.
    :param freezer: conftest fixture.
    """
    album_cache, image_cache = initialize(dict(), dict(), ['V76cJ', 'VMlM6'], ['hiX02', 'Pwx1G5j'])
    update_cache(album_cache, image_cache, app, 'client_id', 30, list(), list())

    # Advance time by one second and outdate one image from V76cJ album.
    freezer.tick()
    image_cache['mGQBV'].mod_time = 0
    update_cache(album_cache, image_cache, app, 'client_id', 30, list(), list())

    # V76cJ should be updated since one of its images were.
    assert album_cache['V76cJ'].mod_time == int(time.time())  # Recently updated.
    assert album_cache['VMlM6'].mod_time != int(time.time())  # Not updated.
    assert image_cache['hiX02'].mod_time != int(time.time())
    assert image_cache['Pwx1G5j'].mod_time != int(time.time())

    # All images in V76cJ should be updated.
    assert image_cache['mGQBV'].mod_time == int(time.time())
    assert image_cache['pc8hc'].mod_time == int(time.time())
    assert image_cache['ojGG7'].mod_time == int(time.time())
    assert image_cache['2QcXR3R'].mod_time != int(time.time())
    assert image_cache['Hqw7KHM'].mod_time != int(time.time())
def test_initialize_not_dict(cache_in):
    """Test function with a non-dictionary cache value.

    :param cache_in: Input cache value.
    """
    album_cache, image_cache = initialize(cache_in, cache_in, ['album1'], ['image1'])
    assert sorted(album_cache) == ['album1']
    assert sorted(image_cache) == ['image1']
    assert album_cache['album1'].title == ''
    assert image_cache['image1'].title == ''
def test_prune_cache_prune_nothing(app):
    """Test with nothing to prune.

    :param app: conftest fixture.
    """
    album_cache, image_cache = initialize(dict(), dict(), ['album1'], ['image1', 'image2', 'image3'])
    album_cache['album1'].image_ids = ['image3']
    doctree_album_ids = ['album1']
    doctree_image_ids = ['image1', 'image2']
    prune_cache(album_cache, image_cache, app, doctree_album_ids, doctree_image_ids)
    assert sorted(album_cache) == ['album1']
    assert sorted(image_cache) == ['image1', 'image2', 'image3']
def test_update_cache_error_keep_previous(app):
    """Make sure error handling preserves previous data in cache.

    :param app: conftest fixture.
    """
    httpretty.register_uri(httpretty.GET, API_URL.format(type='album', id='album'), body='{"data": {}}', status=500)
    album_cache, image_cache = initialize(dict(), dict(), ['album'], [])
    album_cache['album'].description = 'Old'
    album_cache['album'].title = 'Old'

    update_cache(album_cache, image_cache, app, 'client_id', 30, list(), list())

    assert album_cache['album'].description == 'Old'
    assert album_cache['album'].title == 'Old'
    assert album_cache['album'].mod_time == 0

    merged = '\n'.join('\t'.join(m) for m in app.messages)
    assert 'query unsuccessful from https://api.imgur.com/3/album/album: no "error" key in JSON' in merged
def test_update_cache_whitelist(app):
    """Test updating only whitelisted items.

    :param app: conftest fixture.
    """
    album_cache, image_cache = initialize(dict(), dict(), ['V76cJ', 'VMlM6'], ['hiX02', 'Pwx1G5j'])
    update_cache(album_cache, image_cache, app, 'client_id', 30, ['V76cJ'], ['hiX02'])
    updated = [m[1].split('/')[-1] for m in app.messages if m[0] == 'info' and m[1].startswith('querying https://api')]

    assert album_cache['V76cJ'].mod_time > 0
    assert album_cache['VMlM6'].mod_time == 0
    assert image_cache['hiX02'].mod_time > 0
    assert image_cache['Pwx1G5j'].mod_time == 0

    assert image_cache['mGQBV'].mod_time > 0
    assert image_cache['pc8hc'].mod_time > 0
    assert image_cache['ojGG7'].mod_time > 0

    assert updated == ['V76cJ', 'hiX02']
def test_update_cache_whitelist_parent_changed(app):
    """Make sure child image is still updated when parent album no longer has the image.

    :param app: conftest fixture.
    """
    album_cache, image_cache = initialize(dict(), dict(), ['V76cJ'], ['hiX02', 'Pwx1G5j', '2QcXR3R'])
    album_cache['V76cJ'].image_ids = ['2QcXR3R']
    update_cache(album_cache, image_cache, app, 'client_id', 30, [], ['2QcXR3R'])
    updated = [m[1].split('/')[-1] for m in app.messages if m[0] == 'info' and m[1].startswith('querying https://api')]

    assert album_cache['V76cJ'].mod_time > 0
    assert image_cache['hiX02'].mod_time == 0
    assert image_cache['Pwx1G5j'].mod_time == 0
    assert image_cache['2QcXR3R'].mod_time > 0

    assert image_cache['mGQBV'].mod_time > 0
    assert image_cache['pc8hc'].mod_time > 0
    assert image_cache['ojGG7'].mod_time > 0

    assert updated == ['V76cJ', '2QcXR3R']
def test_update_cache_half(app):
    """Test with half the albums and half the standalone images being outdated.

    :param app: conftest fixture.
    """
    album_cache, image_cache = initialize(dict(), dict(), ['V76cJ', 'VMlM6'], ['hiX02', 'Pwx1G5j'])
    album_cache['V76cJ'].mod_time = int(time.time())
    album_cache['V76cJ'].title = 'No Change'
    album_cache['VMlM6'].image_ids = ['image1', 'image2', 'image2']
    image_cache['hiX02'].mod_time = int(time.time())
    image_cache['hiX02'].title = 'No Change'

    update_cache(album_cache, image_cache, app, 'client_id', 30, list(), list())

    assert album_cache['V76cJ'].title == 'No Change'
    assert album_cache['V76cJ'].image_ids == list()
    assert album_cache['VMlM6'].title == 'Screenshots'
    assert album_cache['VMlM6'].image_ids == ['2QcXR3R', 'Hqw7KHM']
    assert image_cache['hiX02'].title == 'No Change'
    assert image_cache['Pwx1G5j'].title is None
示例#10
0
def event_before_read_docs(app, env, _):
    """Called by Sphinx before phase 1 (reading).

    * Verify config.
    * Initialize the cache dict before reading any docs with an empty dictionary if not exists.
    * Prune old/invalid data from cache.

    :param sphinx.application.Sphinx app: Sphinx application object.
    :param sphinx.environment.BuildEnvironment env: Sphinx build environment.
    :param _: Not used.
    """
    client_id = app.config['imgur_client_id']
    if not client_id:
        raise ExtensionError('imgur_client_id config value must be set for Imgur API calls.')
    if not RE_CLIENT_ID.match(client_id):
        raise ExtensionError('imgur_client_id config value must be 5-30 lower case hexadecimal characters only.')

    imgur_album_cache = getattr(env, 'imgur_album_cache', None)
    imgur_image_cache = getattr(env, 'imgur_image_cache', None)
    env.imgur_album_cache, env.imgur_image_cache = initialize(imgur_album_cache, imgur_image_cache, (), ())
    prune_cache(env.imgur_album_cache, env.imgur_image_cache, app)
示例#11
0
def test_update_cache_none_needed(app, freezer):
    """Test no updates needed.

    :param app: conftest fixture.
    :param freezer: conftest fixture.
    """
    album_cache, image_cache = initialize(dict(), dict(), ['album1'], ['image1', 'image2', 'image3'])
    album_cache['album1'].image_ids = ['image3']

    album_cache['album1'].mod_time = int(time.time())
    image_cache['image1'].mod_time = int(time.time())
    image_cache['image2'].mod_time = int(time.time())
    image_cache['image3'].mod_time = int(time.time())
    before = {k: v.__dict__.copy() for k, v in album_cache.items()}
    before.update({k: v.__dict__.copy() for k, v in image_cache.items()})

    freezer.tick()
    update_cache(album_cache, image_cache, app, 'client_id', 30, list(), list())
    after = {k: v.__dict__.copy() for k, v in album_cache.items()}
    after.update({k: v.__dict__.copy() for k, v in image_cache.items()})

    assert not app.messages
    assert after == before
示例#12
0
def test_prune_cache_bad_types(app, doctree_none):
    """Test pruning v1.0.0/invalid items from cache.

    :param app: conftest fixture.
    :param bool doctree_none: Test with None value for last argument.
    """
    album_cache, image_cache = initialize(dict(), dict(), ['album1', 'willBeBad1'], ['image1', 'willBeBad2'])
    doctree_album_ids = None if doctree_none else list(album_cache)  # Same effect.
    doctree_image_ids = None if doctree_none else list(image_cache)  # Same effect.
    for key in ('album2', 0, False, None, ''):
        album_cache[key] = album_cache['album1']
        if not doctree_none:
            doctree_album_ids.append(key)
    for key in ('image2', 0, False, None, ''):
        image_cache[key] = image_cache['image1']
        if not doctree_none:
            doctree_image_ids.append(key)
    album_cache['willBeBad1'] = None
    image_cache['willBeBad2'] = str()

    prune_cache(album_cache, image_cache, app, doctree_album_ids, doctree_image_ids)
    assert sorted(album_cache) == ['album1']
    assert sorted(image_cache) == ['image1']
示例#13
0
def test_update_cache_everything(app):
    """Test with everything outdated.

    :param app: conftest fixture.
    """
    album_cache, image_cache = initialize(dict(), dict(), ['V76cJ'], ['hiX02'])
    before = {k: v.__dict__.copy() for k, v in album_cache.items()}
    before.update({k: v.__dict__.copy() for k, v in image_cache.items()})

    update_cache(album_cache, image_cache, app, 'client_id', 30, list(), list())
    after = {k: v.__dict__.copy() for k, v in album_cache.items()}
    after.update({k: v.__dict__.copy() for k, v in image_cache.items()})
    assert after != before

    assert sorted(album_cache) == ['V76cJ']
    assert sorted(image_cache) == ['hiX02', 'mGQBV', 'ojGG7', 'pc8hc']
    assert album_cache['V76cJ'].mod_time == int(time.time())
    assert image_cache['hiX02'].mod_time == int(time.time())
    assert image_cache['mGQBV'].mod_time == int(time.time())
    assert image_cache['ojGG7'].mod_time == int(time.time())
    assert image_cache['pc8hc'].mod_time == int(time.time())
    assert album_cache['V76cJ'].imgur_id == 'V76cJ'
    assert image_cache['hiX02'].imgur_id == 'hiX02'
    assert image_cache['mGQBV'].imgur_id == 'mGQBV'
    assert image_cache['ojGG7'].imgur_id == 'ojGG7'
    assert image_cache['pc8hc'].imgur_id == 'pc8hc'
    assert album_cache['V76cJ'].description.startswith('Installing a Qi wireless induction charger inside my door to c')
    assert image_cache['hiX02'].description is None
    assert image_cache['mGQBV'].description.startswith('Removed door panel from my car and tested whether my idea woul')
    assert image_cache['ojGG7'].description.startswith("Setting my phone in my door pocket charges it! The door panel'")
    assert image_cache['pc8hc'].description == 'Closeup of Nokia DT-900 charger wedged in my door panel.'
    assert album_cache['V76cJ'].title == '2010 JSW, 2012 Projects'
    assert image_cache['hiX02'].title is None
    assert image_cache['mGQBV'].title == 'Wireless Charging 1: Testing'
    assert image_cache['ojGG7'].title == 'Wireless Charging 3: Works'
    assert image_cache['pc8hc'].title == 'Wireless Charging 2: Testing Closeup'
    assert album_cache['V76cJ'].image_ids == ['mGQBV', 'pc8hc', 'ojGG7']
示例#14
0
def test_update_cache_error_handling(app, album):
    """Test error handling.

    :param app: conftest fixture.
    :param bool album: Error on album instead of image.
    """
    if album:
        httpretty.register_uri(httpretty.GET, API_URL.format(type='album', id='album'), body='{}', status=500)
        album_cache, image_cache = initialize(dict(), dict(), ['album'], ['611EovQ'])
    else:
        httpretty.register_uri(httpretty.GET, API_URL.format(type='image', id='image'), body='{}', status=500)
        album_cache, image_cache = initialize(dict(), dict(), ['V76cJ'], ['image'])
    before = {k: v.__dict__.copy() for k, v in album_cache.items()}
    before.update({k: v.__dict__.copy() for k, v in image_cache.items()})

    update_cache(album_cache, image_cache, app, 'client_id', 30, list(), list())
    after = {k: v.__dict__.copy() for k, v in album_cache.items()}
    after.update({k: v.__dict__.copy() for k, v in image_cache.items()})
    assert after != before

    if album:
        assert sorted(album_cache) == ['album']
        assert sorted(image_cache) == ['611EovQ']
        assert image_cache['611EovQ'].mod_time > 0
        assert image_cache['611EovQ'].description.startswith('Right before I moved desks for the 6th time in 1.5 years')
        assert image_cache['611EovQ'].title == 'Work, June 1st, 2016: Uber'
        assert album_cache['album'].mod_time == 0
        assert album_cache['album'].description == ''
        assert album_cache['album'].title == ''
        assert album_cache['album'].image_ids == list()
    else:
        assert sorted(album_cache) == ['V76cJ']
        assert sorted(image_cache) == ['image', 'mGQBV', 'ojGG7', 'pc8hc']
        assert album_cache['V76cJ'].mod_time > 0
        assert album_cache['V76cJ'].description.startswith('Installing a Qi wireless induction charger inside my door ')
        assert album_cache['V76cJ'].title == '2010 JSW, 2012 Projects'
        assert album_cache['V76cJ'].image_ids == ['mGQBV', 'pc8hc', 'ojGG7']
        assert image_cache['image'].mod_time == 0
        assert image_cache['image'].description == ''
        assert image_cache['image'].title == ''
        assert image_cache['mGQBV'].mod_time > 0
        assert image_cache['mGQBV'].description.startswith('Removed door panel from my car and tested whether my idea ')
        assert image_cache['mGQBV'].title == 'Wireless Charging 1: Testing'
        assert image_cache['ojGG7'].mod_time > 0
        assert image_cache['ojGG7'].description.startswith('Setting my phone in my door pocket charges it! The door pa')
        assert image_cache['ojGG7'].title == 'Wireless Charging 3: Works'
        assert image_cache['pc8hc'].mod_time > 0
        assert image_cache['pc8hc'].description == 'Closeup of Nokia DT-900 charger wedged in my door panel.'
        assert image_cache['pc8hc'].title == 'Wireless Charging 2: Testing Closeup'

    # Verify log.
    merged = '\n'.join('\t'.join(m) for m in app.messages)
    if album:
        assert 'query unsuccessful from https://api.imgur.com/3/album/album: no "data" key in JSON' in merged
        assert '"id": "611EovQ"' in merged
    else:
        assert '"id": "V76cJ"' in merged
        assert '"id": "mGQBV"' in merged
        assert '"id": "ojGG7"' in merged
        assert '"id": "pc8hc"' in merged
        assert 'query unsuccessful from https://api.imgur.com/3/image/image: no "data" key in JSON' in merged