def send_request(url, data): """send a http request. """ req = urllib2.Request(url, data) try: return urllib2.urlopen(req).read() except urllib2.HTTPError as e: raise FlickrError(e.read().split('&')[0])
def _check_tickets(): try: tickets = yield Photo.checkUploadTickets(_futures.keys()) except Exception as e: print e raise e for t in tickets: f = _futures[t.id] del _futures[t.id] if not _futures: _periodic_checks.stop() if t.get("complete", 0) == 1: # completed successfully f.set_result() elif t.get("complete", 0) == 2: # ticket failed, problem converting photo? f.set_exception(FlickrError("Ticket %s failed" % t.id)) elif t.get("invalid", 0) == 1: # ticket not found f.set_exception(FlickrError("Ticket %s not found" % t.id))
def bindings_to(flickr_method): """ Returns the list of bindings to the given Flickr API method in the object API. ex: >>> bindings_to("flickr.people.getPhotos") ['Person.getPhotos'] this tells that the method from Flickr API 'flickr.people.getPhotos' is bound to the 'Person.getPhotos' method of the object API. """ try: return __bindings__[flickr_method] except KeyError: if flickr_method in __methods__: return [] else: raise FlickrError("Unknown Flickr API method: %s" % flickr_method)
def post(url, auth_handler, args, photo_file): args = format_dict(args) args["api_key"] = method_call.API_KEY params = auth_handler.complete_parameters(url, args).parameters fields = params.items() files = [("photo", os.path.basename(photo_file), open(photo_file).read())] r = multipart.posturl(url, fields, files) if r.status != 200: raise FlickrError("HTTP Error %i: %s" % (r.status, r.read())) r = ET.fromstring(r.read()) if r.get("stat") != 'ok': err = r[0] raise FlickrAPIError(int(err.get("code")), err.get("msg")) return r
def upload(**args): """ Authentication: This method requires authentication with 'write' permission. Arguments: photo_file The file to upload. title (optional) The title of the photo. description (optional) A description of the photo. May contain some limited HTML. tags (optional) A space-seperated list of tags to apply to the photo. is_public, is_friend, is_family (optional) Set to 0 for no, 1 for yes. Specifies who can view the photo. safety_level (optional) Set to 1 for Safe, 2 for Moderate, or 3 for Restricted. content_type (optional) Set to 1 for Photo, 2 for Screenshot, or 3 for Other. hidden (optional) Set to 1 to keep the photo in global search results, 2 to hide from public searches. async set to 1 for async mode, 0 for sync mode """ if "async" not in args: args["async"] = False photo_file = args.pop("photo_file") r = post(UPLOAD_URL, auth.AUTH_HANDLER, args, photo_file) t = r[0] if t.tag == 'photoid': return Photo(id=t.text, editurl='http://www.flickr.com/photos/upload/edit/?ids=' + t.text) elif t.tag == 'ticketid': return UploadTicket(id=t.text) else: raise FlickrError("Unexpected tag: %s" % t.tag)
def replace(**args): """ Authentication: This method requires authentication with 'write' permission. For details of how to obtain authentication tokens and how to sign calls, see the authentication api spec. Note that the 'photo' parameter should not be included in the signature. All other POST parameters should be included when generating the signature. Arguments: photo_file The file to upload. photo_id The ID of the photo to replace. async (optional) Photos may be replaced in async mode, for applications that don't want to wait around for an upload to complete, leaving a socket connection open the whole time. Processing photos asynchronously is recommended. Please consult the documentation for details. """ if "async" not in args: args["async"] = True if "photo" in args: args["photo_id"] = args.pop("photo").id photo_file = args.pop("photo_file") r = post(REPLACE_URL, AUTH_HANDLER, args, photo_file) t = r[0] if t.tag == 'photoid': return Photo(id=t.text) elif t.tag == 'ticketid': return UploadTicket(id=t.text, secret=t.secret) else: raise FlickrError("Unexpected tag: %s" % t.tag)
def post(url, auth_handler, photo_file, **kwargs): kwargs = format_dict(kwargs) kwargs["api_key"] = auth_handler.key params = auth_handler.complete_parameters(url, kwargs).parameters fields = params.items() files = [("photo", os.path.basename(photo_file), open(photo_file).read())] try: response = yield multipart.posturl(url, fields, files) except Exception as e: raise e if response.code != 200: raise FlickrError("HTTP Error %i: %s" % (response.code, response.body)) r = ElementTree.fromstring(response.body) if r.get("stat") != 'ok': err = r[0] raise FlickrAPIError(int(err.get("code")), err.get("msg")) raise Return(r)
def call_api(api_key=None, api_secret=None, auth_handler=None, needssigning=False, request_url=REST_URL, raw=False, **args): """ Performs the calls to the Flickr REST interface. Arguments : api_key : The API_KEY to use, if none is given, the key from flickr_keys is used. api_secret : The API_SECRET to use, if none is given, the key from flickr_keys is used. auth_handler : The authentication handler object to use to perform authentication request_url : The url to the rest interface to use by default the url in REST_URL is used. raw : if True the default xml response from the server is returned. if False (default) a dictionnary built from the JSON answer is returned. args : the arguments to pass to the method. """ if not api_key: api_key = API_KEY if not api_secret: api_secret = API_SECRET if not api_key or not api_secret: raise FlickrError("The Flickr API keys have not been set") clean_args(args) args["api_key"] = api_key if not raw: args["format"] = 'json' args["nojsoncallback"] = 1 if auth_handler is None: if needssigning: query_elements = [e.split("=") for e in query.split("&")] query_elements.sort() sig = API_SECRET + ["".join(["".join(e) for e in query_elements])] m = hashlib.md5() m.update(sig) api_sig = m.digest() args["api_sig"] = api_sig data = urllib.urlencode(args) else: data = auth_handler.complete_parameters(url=request_url, params=args).to_postdata() if CACHE is None: resp = send_request(request_url, data) else: resp = CACHE.get(data) or send_request(request_url, data) if data not in CACHE: CACHE.set(data, resp) if raw: return resp try: resp = json.loads(resp) except ValueError, e: print resp raise e
def upload(**kwargs): """ Authentication: This method requires authentication with 'write' permission. Arguments: photo_file The file to upload. title (optional) The title of the photo. description (optional) A description of the photo. May contain some limited HTML. tags (optional) A space-separated list of tags to apply to the photo. is_public, is_friend, is_family (optional) Set to 0 for no, 1 for yes. Specifies who can view the photo. safety_level (optional) Set to 1 for Safe, 2 for Moderate, or 3 for Restricted. content_type (optional) Set to 1 for Photo, 2 for Screenshot, or 3 for Other. hidden (optional) Set to 1 to keep the photo in global search results, 2 to hide from public searches. async set to 1 for async mode, 0 for sync mode """ if "async" not in kwargs: kwargs["async"] = False if auth.AUTH_HANDLER is None: raise FlickrError("Not authenticated") photo_file = kwargs.pop("photo_file") try: resp_body = yield post(UPLOAD_URL, auth.AUTH_HANDLER, photo_file, **kwargs) except Exception as e: log.error("Failed to upload %s" % photo_file) raise e t = resp_body[0] if t.tag == 'photoid': # sync mode, got a photo raise Return( Photo(id=t.text, editurl='https://www.flickr.com/photos/upload/edit/?ids=' + t.text)) elif t.tag == 'ticketid': # async mode, got a ticket if not _futures: _periodic_checks.start() _futures[t.text] = Future() try: yield _futures[t.text] except Exception as e: raise e raise Return( Photo(id=t.text, editurl='https://www.flickr.com/photos/upload/edit/?ids=' + t.text)) else: raise FlickrError("Unexpected tag: %s" % t.tag)
def replace(**kwargs): """ Authentication: This method requires authentication with 'write' permission. For details of how to obtain authentication tokens and how to sign calls, see the authentication api spec. Note that the 'photo' parameter should not be included in the signature. All other POST parameters should be included when generating the signature. Arguments: photo_file The file to upload. photo_id The ID of the photo to replace. async (optional) Photos may be replaced in async mode, for applications that don't want to wait around for an upload to complete, leaving a socket connection open the whole time. Processing photos asynchronously is recommended. Please consult the documentation for details. """ if "async" not in kwargs: kwargs["async"] = False if "photo" in kwargs: kwargs["photo_id"] = kwargs.pop("photo").id photo_file = kwargs.pop("photo_file") try: resp_body = yield post(REPLACE_URL, auth.AUTH_HANDLER, photo_file, **kwargs) except Exception as e: raise e t = resp_body[0] if t.tag == 'photoid': # sync mode, got a photo raise Return( Photo(id=t.text, editurl='https://www.flickr.com/photos/upload/edit/?ids=' + t.text)) elif t.tag == 'ticketid': # async mode, got a ticket if not _futures: _periodic_checks.start() _futures[t.text] = Future() try: yield _futures[t.text] except Exception as e: raise e raise Return( Photo(id=t.text, editurl='https://www.flickr.com/photos/upload/edit/?ids=' + t.text)) else: raise FlickrError("Unexpected tag: %s" % t.tag)
def call_api(api_key=None, api_secret=None, auth_handler=None, needssigning=False, request_url=REST_URL, raw=False, **args): """ Performs the calls to the Flickr REST interface. Parameters: api_key: The API_KEY to use. If none is given and a auth_handler is used the key stored in the auth_handler is used, otherwise, the values stored in the `flickr_keys` module are used. api_secret: The API_SECRET to use. If none is given and a auth_handler is used the key stored in the auth_handler is used, otherwise, the values stored in the `flickr_keys` module are used. auth_handler: The authentication handler object to use to perform authentication. request_url: The url to the rest interface to use by default the url in REST_URL is used. raw: if True the default xml response from the server is returned. If False (default) a dictionnary built from the JSON answer is returned. args: the arguments to pass to the method. """ if not api_key: if auth_handler is not None: api_key = auth_handler.key else: api_key = keys.API_KEY if not api_secret: if auth_handler is not None: api_secret = auth_handler.secret else: api_secret = keys.API_SECRET if not api_key or not api_secret: raise FlickrError("The Flickr API keys have not been set") clean_args(args) args["api_key"] = api_key if not raw: args["format"] = 'json' args["nojsoncallback"] = 1 if auth_handler is None: if needssigning: query_elements = args.items() query_elements.sort() sig = keys.API_SECRET + \ ["".join(["".join(e) for e in query_elements])] m = hashlib.md5() m.update(sig) api_sig = m.digest() args["api_sig"] = api_sig data = urllib3.request.urlencode(args) else: data = auth_handler.complete_parameters(url=request_url, params=args).to_postdata() if CACHE is None: resp = send_request(request_url, data) else: resp = CACHE.get(data) or send_request(request_url, data) if data not in CACHE: CACHE.set(data, resp) if raw: return resp try: resp = json.loads(resp) except ValueError as e: print(resp) raise e if resp["stat"] != "ok": raise FlickrAPIError(resp["code"], resp["message"]) resp = clean_content(resp) return resp