diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e99e36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.pyc \ No newline at end of file diff --git a/__init__.py b/__init__.py index e01657c..74fe695 100644 --- a/__init__.py +++ b/__init__.py @@ -16,8 +16,9 @@ import json import datetime import collections +import re -API_ROOT = 'https://api.parse.com/1/classes' +API_ROOT = 'https://api.parse.com/1' APPLICATION_ID = '' MASTER_KEY = '' @@ -28,8 +29,13 @@ class ParseBinaryDataWrapper(str): class ParseBase(object): - def _executeCall(self, uri, http_verb, data=None): - url = API_ROOT + uri + def _executeCall(self, uri, http_verb, data=None, apiType=None): + url = API_ROOT + if apiType: + url = url + apiType + else : + url = url + '/classes' + url = url + uri request = urllib2.Request(url, data) @@ -40,7 +46,7 @@ def _executeCall(self, uri, http_verb, data=None): request.add_header("Authorization", auth_header) request.get_method = lambda: http_verb - + # TODO: add error handling for server response response = urllib2.urlopen(request) response_body = response.read() @@ -65,6 +71,12 @@ def __init__(self, class_name, attrs_dict=None): if attrs_dict: self._populateFromDict(attrs_dict) + def __str__(self): + return self._object_id + + def __unicode__(self): + return self._object_id + def objectId(self): return self._object_id @@ -116,7 +128,14 @@ def _convertToParseType(self, prop): elif type(value) == ParseBinaryDataWrapper: value = {'__type': 'Bytes', 'base64': base64.b64encode(value)} - + elif type(value) == ParseFile: + value = {'__type': 'File', + 'name': value.file_name, + 'url': value.url} + elif type(value) == ParseGeoPoint: + value = {'__type': 'GeoPoint', + 'latitude': value._latitude, + 'longitude': value._longitude} return (key, value) def _convertFromParseType(self, prop): @@ -124,11 +143,20 @@ def _convertFromParseType(self, prop): if type(value) == dict and value.has_key('__type'): if value['__type'] == 'Pointer': - value = ParseQuery(value['className']).get(value['objectId']) + try: + value = ParseQuery(value['className']).get(value['objectId']) + except urllib2.HTTPError: + pass elif value['__type'] == 'Date': value = self._ISO8601ToDatetime(value['iso']) elif value['__type'] == 'Bytes': value = ParseBinaryDataWrapper(base64.b64decode(value['base64'])) + elif value['__type'] == 'File': + value = ParseFile(value['name'], value['url']) + elif value['__type'] == 'GeoPoint': + value = ParseGeoPoint(value['latitude'], value['longitude']) + # elif value['__type'] == "PFUser" + # value = ParseUser() else: raise Exception('Invalid __type.') @@ -242,14 +270,121 @@ def _fetch(self, single_result=False): if self._where: # JSON encode WHERE values where = json.dumps(self._where) + where = where.translate(None, '\\') + where = re.sub('"{', '{', where) + where = re.sub('}"', '}', where) options.update({'where': where}) - + uri = '/%s?%s' % (self._class_name, urllib.urlencode(options)) response_dict = self._executeCall(uri, 'GET') - + if single_result: return ParseObject(self._class_name, response_dict) else: return [ParseObject(self._class_name, result) for result in response_dict['results']] + +class ParseFile(ParseObject): + def __init__(self, file_name, url): + self.file_name = file_name + self.url = url + + def __unicode__(self): + return self.url + + def __str__(self): + return self.url + +class ParseGeoPoint(ParseObject): + def __init__(self, latitude, longitude): + self._latitude = latitude + self._longitude = longitude + + def __unicode__(self): + return self._latitude + ", " + self._longitude + + def __str__(self): + return "%f, %f" % (self._latitude, self._longitude) + +class ParseUser(ParseObject): + def __init__(self, username=None, email=None, session_token=None): + self.username = username + self.email = email + self.session_token = session_token + + def __unicode__(self): + return username + + def facebookLogin(self, userID, access_token, expiration_date): + url = API_ROOT + '/users?' + + encoded_args = urllib.urlencode({"authData": {"facebook": {"id": userID, + "access_token": access_token, + "expiration_date": "2020-01-01'T'12:12:12.111'Z'"}}}) + + + url = url + encoded_args + print url + request = urllib2.Request(url) + + # we could use urllib2's authentication system, but it seems like overkill for this + auth_header = "Basic %s" % base64.b64encode('%s:%s' % (APPLICATION_ID, MASTER_KEY)) + request.add_header("Authorization", auth_header) + try: + print 'before response' + response = urllib2.urlopen(request) + print response + response_body = response.read() + response_dict = json.loads(response_body) + + + + self.username = response_dict['username'] + self.email = response_dict['email'] + self.session_token = response_dict['sessionToken'] + self._object_id = response_dict['objectId'] + except urllib2.HTTPError: + print 'http error' + self.session_token = None + pass + + return self + + def login(self, username, password): + + + + url = API_ROOT + '/login?' + + + + + encoded_args = urllib.urlencode({"username": username, "password": password}) + + url = url + encoded_args + + request = urllib2.Request(url) + + # we could use urllib2's authentication system, but it seems like overkill for this + auth_header = "Basic %s" % base64.b64encode('%s:%s' % (APPLICATION_ID, MASTER_KEY)) + request.add_header("Authorization", auth_header) + + try: + response = urllib2.urlopen(request) + response_body = response.read() + response_dict = json.loads(response_body) + + + + self.username = response_dict['username'] + self.email = response_dict['email'] + self.session_token = response_dict['sessionToken'] + self._object_id = response_dict['objectId'] + except urllib2.HTTPError: + self.session_token = None + pass + + return self + +