import os import six import json from requests_oauthlib import OAuth1Session consumer_key = 'XJCbpn5nHHDNW48NBMx0eg' consumer_secret = 'gcxv78Aq6kBulp663LFgug' class Figshare(object): def __init__(self, consumer_key, consumer_secret, access_token, access_token_secret): """ Connects to the figshare API. """ self.client = OAuth1Session( consumer_key, consumer_secret, access_token, access_token_secret) self.endpoint = 'http://api.figshare.com/v1/my_data' def article(self, article_id): """ Returns a single article. """ response = self.client.get(self.endpoint + '/articles/%s' % article_id) return response.json()['items'][0] def delete_article(self, article_id): """ Deletes article `article_id`. """ response = self.client.delete( self.endpoint + '/articles/%s' % article_id) return json.loads(response.content) def articles(self, limit=None): """ Parameters ---------- limit : int or None If not None, then limit the number of articles returned. Returns ------- Dict of {count: integer count of articles, items: dictionary representing each article} """ # API only returns 10 results at a time, so keep asking for more pages # until we can't get any more... all_articles = [] count = 0 page = 1 while True: if limit is not None and (len(all_articles) < limit): break data = {'page': page} response = self.client.get( self.endpoint + '/articles', params={'page': page} ) # Keep the response around for debugging if needed; get a separate # results dict results = response.json() if results['count'] == 0: break all_articles.extend(results['items']) count += results['count'] page += 1 # Reconstruct the JSON dict in the same format returned by a single # response (with keys [count, items]) assert count == len(all_articles) return {'count': count, 'items': all_articles} def create_article(self, title, description, defined_type='dataset'): """ Create an article. `title`, `description` are required; other `defined_type` value can be "fileset". There are likely others (e.g., "figure", "code", "media", etc) but these are currently undocumented by the API, so use at your own risk. """ response = self.client.post( self.endpoint + '/articles', data=json.dumps({'title': title, 'description': description, 'defined_type': defined_type, }), headers={'content-type': 'application/json'}) return response.json() def make_private(self, article_id): """ Make an article private. If an article was just created, it is still in draft form. This method will turn it into a private article. """ response = self.client.post( '%s/articles/%s/action/make_private' % (self.endpoint, article_id)) return response.json() def update_article(self, article_id, title=None, description=None, defined_type=None): """ Update title, description, and defined_type. Any of these values can be None if you don't want to change them. """ data = {'title': title, 'description': description, 'defined_type': defined_type} data = dict((k, v) for k, v in data.items() if v is not None) response = self.client.put( '%s/articles/%s' % (self.endpoint, article_id), data=json.dumps(data), headers={'content-type': 'application/json'}) return response.json() def upload_file(self, article_id, filepath_or_buffer): """ Upload a file. `filepath_or_buffer` can be a string or an open file object. """ if isinstance(filepath_or_buffer, six.string_types): file = open(filepath_or_buffer, 'rb') own_handle = True else: file = filepath_or_buffer own_handle = False try: files = {'filedata': (os.path.basename(file.name), file)} response = self.client.put( '%s/articles/%s/files' % (self.endpoint, article_id), files=files) return response.json() finally: if own_handle: file.close() def delete_file(self, article_id, file_id): """ Delete a file. """ response = self.client.delete( '%s/articles/%s/files/%s' % (self.endpoint, article_id, file_id) ) return response.json() def add_link(self, article_id, link): """ Add a link. """ response = self.client.put( self.endpoint + '/articles/%s/links' % article_id, data=json.dumps({'link': link}), headers={'content-type': 'application/json'} ) return response.json() def delete_link(self, article_id, link_id): """ Delete a link. This requires a link ID, which you can get from inspecting the article JSON. For example:: first_link_id = article['links'][0]['id'] """ response = self.client.delete( self.endpoint + '/articles/%s/links/%s' % (article_id, link_id) ) return reponse.json() def versions(self, article_id): """ Show the versions of this article """ response = self.client.get( self.endpoint + '/articles/%s/versions' % article_id ) return response.json() def get_version(self, article_id, version_number): """ Get a particular version of this article. """ response = self.client.get( self.endpoint + '/articles/%s/versions/%s' % (article_id, version_number) ) return response.json() def categories(self): """ Show the possible categories supplied by figshare. """ response = self.client.get( self.endpoint.replace('/my_data', '') + '/categories' ) return response.json() def add_tag(self, article_id, tag): """ Add a tag to an article. """ response = self.client.put( self.endpoint + '/articles/%s/tags' % article_id, data=json.dumps({'tag_name': tag}), headers={'content-type': 'application/json'}) return response.json() def delete_tag(self, article_id, tag_id): """ Delete a tag from an article. This requires a tag ID, which you can get from inspecting the article JSON. For example:: first_tag_id = article['tags'][0]['id'] """ response = self.client.delete( self.endpoint + '/articles/%s/categories/%s' % (article_id, tag_id) ) return response.json() def add_category(self, article_id, category_id): """ Add a category to an article. See the categories() method to see the options and to select a `category_id`. """ response = self.client.put( self.endpoint + '/articles/%s/categories' % article_id, data=json.dumps({'category_id': category_id}), headers={'content-type': 'application/json'}) return response.json() def delete_category(self, article_id, category_id): """ Delete a category from an article. """ response = self.client.delete( self.endpoint + '/articles/%s/categories/%s' % (article_id, category_id) ) return response.json() def add_author(self, article_id, author_id): """ Add an author to an article. """ response = self.client.put( self.endpoint + '/articles/%s/categories' % article_id, data=json.dumps({'author_id': author_id}), headers={'content-type': 'application/json'}) return response.json() def delete_author(self, article_id, author_id): """ Delete an author from an article """ response = self.client.delete( self.endpoint + '/articles/%s/categories/%s' % (article_id, author_id) ) return response.json()