Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 48 additions & 19 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,42 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import urllib, urllib2
import urllib
import urllib2
import base64
import json
import datetime
import collections

API_ROOT = 'https://api.parse.com/1/classes'

API_ROOT = 'https://api.parse.com/1'
API_CLASSES_ROOT = API_ROOT + '/classes'

APPLICATION_ID = ''
MASTER_KEY = ''
# user objects cannot be modified under master key, even with active session
# so for this case we need to use REST API key
REST_API_KEY = ''
SESSION_TOKEN = ''


def login(username, password):
request = urllib2.Request(API_ROOT + '/login?username=' + username + "&" + "password=" + password)

request.add_header('X-Parse-Application-Id', APPLICATION_ID)
if REST_API_KEY:
request.add_header('X-Parse-REST-API-Key', REST_API_KEY)
elif MASTER_KEY:
request.add_header('X-Parse-Master-Key', MASTER_KEY)

response = urllib2.urlopen(request)
response_body = response.read()
response_dict = json.loads(response_body)

global SESSION_TOKEN
SESSION_TOKEN = response_dict[u"sessionToken"]

return response_dict


class ParseBinaryDataWrapper(str):
Expand All @@ -29,15 +55,18 @@ class ParseBinaryDataWrapper(str):

class ParseBase(object):
def _executeCall(self, uri, http_verb, data=None):
url = API_ROOT + uri
url = API_CLASSES_ROOT + uri

request = urllib2.Request(url, data)

request.add_header('Content-type', 'application/json')

# 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)
request.add_header('X-Parse-Application-Id', APPLICATION_ID)
if REST_API_KEY:
request.add_header('X-Parse-REST-API-Key', REST_API_KEY)
elif MASTER_KEY:
request.add_header('X-Parse-Master-Key', MASTER_KEY)
if SESSION_TOKEN:
request.add_header('X-Parse-Session-Token', SESSION_TOKEN)

request.get_method = lambda: http_verb

Expand Down Expand Up @@ -108,14 +137,14 @@ def _convertToParseType(self, prop):

if type(value) == ParseObject:
value = {'__type': 'Pointer',
'className': value._class_name,
'objectId': value._object_id}
'className': value._class_name,
'objectId': value._object_id}
elif type(value) == datetime.datetime:
value = {'__type': 'Date',
'iso': value.isoformat()[:-3] + 'Z'} # take off the last 3 digits and add a Z
'iso': value.isoformat()[:-3] + 'Z'} # take off the last 3 digits and add a Z
elif type(value) == ParseBinaryDataWrapper:
value = {'__type': 'Bytes',
'base64': base64.b64encode(value)}
'base64': base64.b64encode(value)}

return (key, value)

Expand All @@ -138,13 +167,13 @@ def _getJSONProperties(self):

properties_list = self.__dict__.items()

# filter properties that start with an underscore
properties_list = filter(lambda prop: prop[0][0] != '_', properties_list)
# filter properties that start with an underscore and equal to 'sessionToken'
properties_list = filter(lambda prop: prop[0][0] != '_' and prop[0] != 'sessionToken', properties_list)

#properties_list = [(key, value) for key, value in self.__dict__.items() if key[0] != '_']

properties_list = map(self._convertToParseType, properties_list)

properties_dict = dict(properties_list)
json_properties = json.dumps(properties_dict)

Expand All @@ -159,7 +188,7 @@ def _create(self):
data = self._getJSONProperties()

response_dict = self._executeCall(uri, 'POST', data)

self._created_at = self._updated_at = response_dict['createdAt']
self._object_id = response_dict['objectId']

Expand Down Expand Up @@ -192,15 +221,15 @@ def eq(self, name, value):
def lt(self, name, value):
self._where[name]['$lt'] = value
return self

def lte(self, name, value):
self._where[name]['$lte'] = value
return self

def gt(self, name, value):
self._where[name]['$gt'] = value
return self

def gte(self, name, value):
self._where[name]['$gte'] = value
return self
Expand Down Expand Up @@ -229,7 +258,7 @@ def get(self, object_id):
def fetch(self):
# hide the single_result param of the _fetch method from the library user
# since it's only useful internally
return self._fetch()
return self._fetch()

def _fetch(self, single_result=False):
# URL: /1/classes/<className>/<objectId>
Expand Down