Add 'flickrscripts/' from commit '89393c390fe69e66bd2d9aa275ba652e320a3215'

git-subtree-dir: flickrscripts
git-subtree-mainline: 1037e390b5
git-subtree-split: 89393c390f
This commit is contained in:
Dan Buch 2013-01-09 23:49:19 -05:00
commit fd87ec8fe9
7 changed files with 209 additions and 0 deletions

1
flickrscripts/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.egg-info

5
flickrscripts/README.rst Normal file
View File

@ -0,0 +1,5 @@
==============
Flickr Scripts
==============
Miscellaneous crap for doing stuff with my Flickr photos.

View File

@ -0,0 +1,30 @@
from __future__ import print_function
import sys
from os.path import basename
__meta__ = dict(
name='flickrscripts',
version='0.1.0',
entry_points={
'console_scripts': [
'flickrscripts = flickrscripts:route',
],
},
test_suite='nose.collector',
)
USAGE = 'Usage: {prog} <subcommand> [args]'
def route(sysargs=sys.argv[:]):
try:
subcommand = sysargs.pop(1)
import_name = 'flickrscripts.{}'.format(subcommand)
module = __import__(import_name, fromlist=[import_name])
return module.main(sysargs)
except IndexError:
print(USAGE.format(prog=basename(sysargs[0])), file=sys.stderr)
print('You must provide a subcommand', file=sys.stderr)
return 1

View File

@ -0,0 +1,49 @@
import json
from hashlib import sha1
from os.path import expanduser
import flickrapi
def setup_flickr(api_key, api_secret):
flickr = flickrapi.FlickrAPI(api_key, api_secret)
token, frob = flickr.get_token_part_one(perms='write')
if not token:
raw_input("Press ENTER after you authorized this program")
flickr.get_token_part_two((token, frob))
return flickr
def get_photo_signature(flickr, photo_id):
info = flickr.photos_getInfo(photo_id=photo_id).find('photo')
exif = flickr.photos_getExif(photo_id=photo_id).find('photo')
if not info or not exif:
raise InvalidPhotoIdError(photo_id)
return [
info.get('originalformat'), info.find('owner').get('location'),
info.find('dates').get('taken')
] + sorted(
(e.get('label'), e.get('tag'), e.get('tagspace'), e.get('tagspaceid'),
e.find('raw').text) for e in exif.findall('exif')
)
def get_photo_sha1sum(flickr, photo_id):
return sha1(str(get_photo_signature(flickr, photo_id)))
def get_flickr_from_rc_file(rc_file=expanduser('~/.flickrscripts.json')):
rc_conf = json.load(open(rc_file))
return setup_flickr(rc_conf['APIKEY'], rc_conf['APISECRET'])
def load_rc_file(rc_file=expanduser('~/.flickrscripts.json')):
return json.load(open(rc_file))
class InvalidPhotoIdError(ValueError):
pass

View File

@ -0,0 +1,95 @@
import argparse
import json
import logging
import sys
from datetime import datetime, timedelta
from os.path import expanduser
from flickrscripts.common import setup_flickr
class TimeWarper(object):
flickr = None
_base_query_args = dict(user_id='me', page=1)
def __init__(self, api_key, api_secret):
self.flickr = setup_flickr(api_key, api_secret)
self.log = logging.getLogger(self.__class__.__name__)
self.log.level = logging.INFO
def run(self, set_to_date, **query_args):
self.log.info(
'Setting upload dates for photos matching query %r', query_args
)
query = self._base_query_args.copy()
query.update(query_args)
for i, page in self._get_pages(query):
self.log.info('Processing page %s, attributes=%r',
i, page.attrib)
self._set_upload_date_for_photos(i, page, set_to_date)
return 0
def _set_upload_date_for_photos(self, pagenum, page, set_to_date):
for i, photo in enumerate(page.findall('photos/photo')):
setdate_response = self.flickr.photos_setDates(
photo_id=photo.attrib['id'],
date_posted=set_to_date
)
self.log.info('page %s photo %s: response attribs=%s',
pagenum, i, setdate_response.attrib)
def _get_pages(self, query):
self.log.info('Getting pages for query %r', query)
i = 1
while True:
page = self.flickr.photos_search(**query)
if len(page.findall('photos/photo')):
yield i, page
i += 1
else:
raise StopIteration
def main(sysargs=sys.argv[:]):
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog='flickrscripts timewarp')
parser.add_argument('set_to_date')
parser.add_argument('-q', '--search-query-param', default=[],
action='append', help='Add a key=value param to the search query list')
parser.add_argument(
'-c', '--rcfile', default=expanduser('~/.flickrscripts.json'),
help='JSON file containing `APIKEY` and `APISECRET` keys',
type=argparse.FileType('r')
)
args = parser.parse_args(sysargs[1:])
rc_conf = json.load(args.rcfile)
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
log = logging.getLogger('main')
log.level = logging.INFO
log.info('Preparing query args')
query_args = {}
for key_val in args.search_query_param:
key, value = key_val.split('=', 1)
query_args[key] = value
if len(query_args.keys()) == 0:
query_args = dict(
min_upload_date=(datetime.now() + timedelta(days=-1)),
max_upload_date=(datetime.now() + timedelta(days=1))
)
log.warn('No query arguments provided! ' +
'Defaulting to %r', query_args)
warper = TimeWarper(rc_conf['APIKEY'], rc_conf['APISECRET'])
return warper.run(args.set_to_date, **query_args)
if __name__ == '__main__':
sys.exit(main())

10
flickrscripts/setup.py Normal file
View File

@ -0,0 +1,10 @@
import sys
from setuptools import setup
from flickrscripts import __meta__
if __name__ == '__main__':
setup(**__meta__)
sys.exit(0)

View File

@ -0,0 +1,19 @@
import unittest
from flickrscripts.timewarp import TimeWarper
from flickrscripts.common import load_rc_file
class TimeWarperTestCase(unittest.TestCase):
def setUp(self):
rc_conf = load_rc_file()
self.warper = TimeWarper(rc_conf['APIKEY'], rc_conf['APISECRET'])
def test_is_not_horribly_busted(self):
self.assertTrue(True, 'please forgive the horrible test')
if __name__ == '__main__':
unittest.main()