Skip to content

Instantly share code, notes, and snippets.

@rubik
Created July 9, 2012 19:53
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rubik/3078516 to your computer and use it in GitHub Desktop.
Save rubik/3078516 to your computer and use it in GitHub Desktop.
Example command line program powered by Baker and other cool libraries (pathlib, slumber & colorama)
import sys
import baker
import slumber
import pathlib
import colorama
API_URL = 'https://api.github.com/'
def get_api(auth=None):
if auth is not None:
auth = tuple(map(str.strip, auth.split(',')))
return slumber.API(base_url=API_URL, auth=auth, append_slash=False)
def find_matching(dir, include, exclude):
if not include:
return []
included = set(dir.glob(include))
if exclude is not None:
included -= set(dir.glob(exclude))
return [path for path in included if path.is_file()]
def log(msg, indent=0):
if indent == 0:
prompt = colorama.Fore.RED + '=>'
msg = '{0}{1} {2}{3}'.format(colorama.Style.BRIGHT,
prompt,
colorama.Fore.GREEN,
msg)
sys.stdout.write('{0}{1}{2}\n'.format(' ' * indent * 4, msg,
colorama.Style.RESET_ALL))
@baker.command(shortopts={'dest': 'd'})
def get(id, dest='.', auth=None):
'''Download all files from a specified gist.
:param id: The number identifying the gist.
:param dest: The destination directory. Default to the current working
directory.
:param auth: Authentication tokens separated by a comma
(i.e. username,password)..
'''
dest = pathlib.Path(dest).resolve()
api = get_api(auth)
log('Downloading gist {0}'.format(id))
files = api.gists(id).get()['files']
for file, properties in files.items():
filename = properties['filename']
with dest[str(filename)].open('w') as fobj:
log('Getting {0}'.format(filename), 1)
fobj.write(properties['content'])
@baker.command(shortopts={'dir': 'd', 'include': 'i', 'exclude': 'e',
'public': 'p', 'description': 'D', 'auth': 'a'})
def new(dir='.', include=None, exclude=None, public=False, description=None,
auth=None, *additional_files):
'''Create a new gist and upload files to it.
:param dir: The directory where to search for files. Default to current
working directory.
:param include: A glob pattern indicating which files to select.
:param exclude: A glob pattern indicating which files to exclude.
:param public: If True, gist will be set to public. Otherwise it will
be private. Default to False.
:param description: A description of the gist.
:param auth: Authentication tokens separated by a comma
(i.e. username,password)..
'''
dir = pathlib.Path(dir).resolve()
payload = {'description': description, 'public': public, 'files': {}}
log('Looking for matching files')
files = find_matching(dir, include, exclude)
if not files + list(additional_files):
log('ERROR: No files to upload!')
sys.exit(1)
for path in files + map(pathlib.Path, additional_files):
log('Adding {0}'.format(path), 1)
with path.open() as fobj:
payload['files'][path.parts[-1]] = {'content': fobj.read()}
log('Metadata')
log('Description: {0}'.format(payload['description']), 1)
log('Public: {0}'.format(payload['public']), 1)
api = get_api(auth)
log('Uploading')
response = api.gists.post(payload)
log('Gist id is: {0}'.format(response['id']))
@baker.command
def delete(id, auth):
'''Delete a gist.
:param id: The number which identifies the gist.
:param auth: Authentication tokens separated by a comma
(i.e. username,password).
'''
api = get_api(auth)
log('Deleting gist')
api.gists(id).delete()
def _star(func):
def aux(id, auth):
'''{0} a gist.
:param id: The number identifying the gist.
:param auth: Authentication tokens separated by a comma
(i.e. username,password).
'''
api = get_api(auth).gists(id).star
func(api)
name = func.__name__
aux.__name__ = name
aux.__doc__ = aux.__doc__.format(name.capitalize())
return aux
@baker.command
@_star
def star(api):
log('Starring the gist')
api.put({})
@baker.command
@_star
def unstar(api):
log('Unstarring the gist')
api.delete()
if __name__ == '__main__':
baker.run()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment