<commit_before># flickrpc -- a Flickr client library.
#
# Copyright (C) 2007 <NAME> <<EMAIL>>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 2, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA

import logging, md5, os, mimetools, urllib
from twisted.internet import defer
from twisted.python.failure import Failure
from twisted.web import client
try:
    from xml.etree import ElementTree
except ImportError:
    from elementtree import ElementTree

class FlickrError(Exception):
    def __init__(self, code, message):
        Exception.__init__(self)
        self.code = int(code)
        self.message = message
    
    def __str__(self):
        return "%d: %s" % (self.code, self.message)

(SIZE_SQUARE,
 SIZE_THUMB,
 SIZE_SMALL,
 SIZE_MEDIUM,
 SIZE_LARGE) = range (0, 5)

class Flickr:
    endpoint = "http://api.flickr.com/services/rest/?"
    
    def __init__(self, api_key, secret, perms="read"):
        self.__methods = {}
        self.api_key = api_key
        self.secret = secret
        self.perms = perms
        self.token = None
        self.logger = logging.getLogger('flickrest')
    
    def __repr__(self):
        return "<FlickREST>"
    
    def __getTokenFile(self):
        """Get the filename that contains the authentication token for the API key"""
        return os.path.expanduser(os.path.join("~", ".flickr", self.api_key, "auth.xml"))
    
    def __sign(self, kwargs):
        kwargs['api_key'] = self.api_key
        # If authenticating we don't yet have a token
        if self.token:
            kwargs['auth_token'] = self.token
        s = []
        for key in kwargs.keys():
            s.append("%s%s" % (key, kwargs[key]))
        s.sort()
        sig = md5.new(self.secret + ''.join(s)).hexdigest()
        kwargs['api_sig'] = sig

    def __call(self, method, kwargs):
        kwargs["method"] = method
        self.__sign(kwargs)
        self.logger.info("Calling %s" % method)
        return client.getPage(Flickr.endpoint, method="POST",
                              headers={"Content-Type": "application/x-www-form-urlencoded"},
                              postdata=urllib.urlencode(kwargs))
    
    def __getattr__(self, method):
        method = "flickr." + method.replace("_", ".")
        if not self.__methods.has_key(method):
            def proxy(method=method, **kwargs):
                def cb(data):
                    self.logger.info("%s returned" % method)
                    xml = ElementTree.XML(data)
                    if xml.tag == "rsp" and xml.get("stat") == "ok":
                        return xml
                    elif xml.tag == "rsp" and xml.get("stat") == "fail":
                        err = xml.find("err")
                        raise FlickrError(err.get("code"), err.get("msg"))
                    else:
                        # Fake an error in this case
                        raise FlickrError(0, "Invalid response")
                return self.__call(method, kwargs).addCallback(cb)
            self.__methods[method] = proxy
        return self.__methods[method]

    @staticmethod
    def __encodeForm(inputs):
        """
        Takes a dict of inputs and returns a multipart/form-data string
        containing the utf-8 encoded data. Keys must be strings, values
        can be either strings or file-like objects.
        """
        boundary = mimetools.choose_boundary()
        lines = []
        for key, val in inputs.items():
            lines.append("--" + boundary.encode("utf-8"))
            header = 'Content-Disposition: form-data; name="%s";' % key
            # Objects with name value are probably files
            if hasattr(val, 'name'):
                header += 'filename="%s";' % os.path.split(val.name)[1]
                lines.append(header)
                header = "Content-Type: application/octet-stream"
            lines.append(header)
            lines.append("")
            # If there is a read attribute, it is a file-like object, so read all the data
            if hasattr(val, 'read'):
                lines.append(val.read())
            # Otherwise just hope it is string-like and encode it to
            # UTF-8. TODO: this breaks when val is binary data.
            else:
                lines.append(val.encode('utf-8'))
        # Add final boundary.
        lines.append("--" + boundary.encode("utf-8"))
        return (boundary, '\r\n'.join(lines))
    
    # TODO: add is_public, is_family, is_friends arguments
    def upload(self, filename=None, imageData=None, title=None, desc=None, tags=None):
        # Sanity check the arguments
        if filename is None and imageData is None:
            raise ValueError("Need to pass either filename or imageData")
        if filename and imageData:
            raise ValueError("Cannot pass both filename and imageData")

        kwargs = {}
        if title:
            kwargs['title'] = title
        if desc:
            kwargs['description'] = desc
        if tags:
            kwargs['tags'] = tags
        self.__sign(kwargs)
        
        if imageData:
            kwargs['photo'] = imageData
        else:
            kwargs['photo'] = file(filename, "rb")

        (boundary, form) = self.__encodeForm(kwargs)
        headers= {
            "Content-Type": "multipart/form-data; boundary=%s" % boundary,
            "Content-Length": str(len(form))
            }

        def cb(data):
            self.logger.info("upload returned")
            xml = ElementTree.XML(data)
            if xml.tag == "rsp" and xml.get("stat") == "ok":
                return xml
            elif xml.tag == "rsp" and xml.get("stat") == "fail":
                err = xml.find("err")
                raise FlickrError(err.get("code"), err.get("msg"))
            else:
                # Fake an error in this case
                raise FlickrError(0, "Invalid response")
        return client.getPage("http://api.flickr.com/services/upload/", method="POST",
                              headers=headers, postdata=form).addCallback(cb)

    def authenticate_2(self, state):
        def gotToken(e):
            # Set the token<commit_msg>Pull out the response parser<commit_after># flickrpc -- a Flickr client library.
#
# Copyright (C) 2007 <NAME> <<EMAIL>>
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation; either version 2, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# St, Fifth Floor, Boston, MA 02110-1301 USA

import logging, md5, os, mimetools, urllib
from twisted.internet import defer
from twisted.python.failure import Failure
from twisted.web import client
try:
    from xml.etree import ElementTree
except ImportError:
    from elementtree import ElementTree

class FlickrError(Exception):
    def __init__(self, code, message):
        Exception.__init__(self)
        self.code = int(code)
        self.message = message
    
    def __str__(self):
        return "%d: %s" % (self.code, self.message)

(SIZE_SQUARE,
 SIZE_THUMB,
 SIZE_SMALL,
 SIZE_MEDIUM,
 SIZE_LARGE) = range (0, 5)

class Flickr:
    endpoint = "http://api.flickr.com/services/rest/?"
    
    def __init__(self, api_key, secret, perms="read"):
        self.__methods = {}
        self.api_key = api_key
        self.secret = secret
        self.perms = perms
        self.token = None
        self.logger = logging.getLogger('flickrest')
    
    def __repr__(self):
        return "<FlickREST>"
    
    def __getTokenFile(self):
        """Get the filename that contains the authentication token for the API key"""
        return os.path.expanduser(os.path.join("~", ".flickr", self.api_key, "auth.xml"))
    
    def __sign(self, kwargs):
        kwargs['api_key'] = self.api_key
        # If authenticating we don't yet have a token
        if self.token:
            kwargs['auth_token'] = self.token
        s = []
        for key in kwargs.keys():
            s.append("%s%s" % (key, kwargs[key]))
        s.sort()
        sig = md5.new(self.secret + ''.join(s)).hexdigest()
        kwargs['api_sig'] = sig

    def __call(self, method, kwargs):
        kwargs["method"] = method
        self.__sign(kwargs)
        self.logger.info("Calling %s" % method)
        return client.getPage(Flickr.endpoint, method="POST",
                              headers={"Content-Type": "application/x-www-form-urlencoded"},
                              postdata=urllib.urlencode(kwargs))
    
    def __cb(self, data, method):
        self.logger.info("%s returned" % method)
        xml = ElementTree.XML(data)
        if xml.tag == "rsp" and xml.get("stat") == "ok":
            return xml
        elif xml.tag == "rsp" and xml.get("stat") == "fail":
            err = xml.find("err")
            raise FlickrError(err.get("code"), err.get("msg"))
        else:
            # Fake an error in this case
            raise FlickrError(0, "Invalid response")
    
    def __getattr__(self, method):
        method = "flickr." + method.replace("_", ".")
        if not self.__methods.has_key(method):
            def proxy(method=method, **kwargs):
                return self.__call(method, kwargs).addCallback(self.__cb, method)
            self.__methods[method] = proxy
        return self.__methods[method]

    @staticmethod
    def __encodeForm(inputs):
        """
        Takes a dict of inputs and returns a multipart/form-data string
        containing the utf-8 encoded data. Keys must be strings, values
        can be either strings or file-like objects.
        """
        boundary = mimetools.choose_boundary()
        lines = []
        for key, val in inputs.items():
            lines.append("--" + boundary.encode("utf-8"))
            header = 'Content-Disposition: form-data; name="%s";' % key
            # Objects with name value are probably files
            if hasattr(val, 'name'):
                header += 'filename="%s";' % os.path.split(val.name)[1]
                lines.append(header)
                header = "Content-Type: application/octet-stream"
            lines.append(header)
            lines.append("")
            # If there is a read attribute, it is a file-like object, so read all the data
            if hasattr(val, 'read'):
                lines.append(val.read())
            # Otherwise just hope it is string-like and encode it to
            # UTF-8. TODO: this breaks when val is binary data.
            else:
                lines.append(val.encode('utf-8'))
        # Add final boundary.
        lines.append("--" + boundary.encode("utf-8"))
        return (boundary, '\r\n'.join(lines))
    
    # TODO: add is_public, is_family, is_friends arguments
    def upload(self, filename=None, imageData=None, title=None, desc=None, tags=None):
        # Sanity check the arguments
        if filename is None and imageData is None:
            raise ValueError("Need to pass either filename or imageData")
        if filename and imageData:
            raise ValueError("Cannot pass both filename and imageData")

        kwargs = {}
        if title:
            kwargs['title'] = title
        if desc:
            kwargs['description'] = desc
        if tags:
            kwargs['tags'] = tags
        self.__sign(kwargs)
        
        if imageData:
            kwargs['photo'] = imageData
        else:
            kwargs['photo'] = file(filename, "rb")

        (boundary, form) = self.__encodeForm(kwargs)
        headers= {
            "Content-Type": "multipart/form-data; boundary=%s" % boundary,
            "Content-Length": str(len(form))
            }

        self.logger.info("Calling upload")
        return client.getPage("http://api.flickr.com/services/upload/", method="POST",
                              headers=headers, postdata=form).addCallback(self.__cb, "upload")

    def authenticate_2(self, state):
        def gotToken(e):
            # Set the token
{'fraction_non_alphanumeric': 0.11359950575334003, 'fraction_numerical': 0.00440188431539115, 'mean_word_length': 2.121234032296939, 'pattern_counts': {'":': 12, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 25}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '287995', 'n_tokens_mistral': 3651, 'n_tokens_neox': 3541, 'n_words': 1097}