Commit 4323b999 by Raphael Lullis

Finally getting rid of all the senseless code on __init__, and creating the code…

Finally getting rid of all the senseless code on __init__, and creating the code (for exceptions) and connection (for access keys management and the ParseBase class) modules.
parent 1098b32a
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, 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 General Public License for more details.
#
# 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
import urllib2
import base64
import json
import datetime
API_ROOT = 'https://api.parse.com/1'
class ParseError(Exception):
'''Base exceptions from requests made to Parse'''
pass
class ResourceRequestBadRequest(ParseError):
'''Request returns a 400'''
pass
class ResourceRequestLoginRequired(ParseError):
'''Request returns a 401'''
pass
class ResourceRequestForbidden(ParseError):
'''Request returns a 403'''
pass
class ResourceRequestNotFound(ParseError):
'''Request returns a 404'''
pass
def master_key_required(func):
'''decorator describing methods that require the master key'''
def ret(obj, *args, **kw):
conn = ParseBase.CONNECTION
if not (conn and conn.get('master_key')):
message = '%s requires the master key' % func.__name__
raise ParseError(message)
func(obj, *args, **kw)
return ret
class ParseBase(object):
ENDPOINT_ROOT = API_ROOT
@classmethod
def register(cls, app_id, rest_key, **kw):
ParseBase.CONNECTION = {
'app_id': app_id,
'rest_key': rest_key
}
ParseBase.CONNECTION.update(**kw)
@classmethod
def execute(cls, uri, http_verb, extra_headers=None, **kw):
if not ParseBase.CONNECTION:
raise ParseError('Missing connection credentials')
app_id = ParseBase.CONNECTION.get('app_id')
rest_key = ParseBase.CONNECTION.get('rest_key')
master_key = ParseBase.CONNECTION.get('master_key')
headers = extra_headers or {}
url = uri if uri.startswith(API_ROOT) else cls.ENDPOINT_ROOT + uri
data = kw and json.dumps(kw) or "{}"
if http_verb == 'GET' and data:
url += '?%s' % urllib.urlencode(kw)
data = None
request = urllib2.Request(url, data, headers)
request.add_header('Content-type', 'application/json')
request.add_header('X-Parse-Application-Id', app_id)
request.add_header('X-Parse-REST-API-Key', rest_key)
if master_key: request.add_header('X-Parse-Master-Key', master_key)
request.get_method = lambda: http_verb
try:
response = urllib2.urlopen(request)
except urllib2.HTTPError, e:
exc = {
400: ResourceRequestBadRequest,
401: ResourceRequestLoginRequired,
403: ResourceRequestForbidden,
404: ResourceRequestNotFound
}.get(e.code, ParseError)
raise exc(e.read())
return json.loads(response.read())
@classmethod
def GET(cls, uri, **kw):
return cls.execute(uri, 'GET', **kw)
@classmethod
def POST(cls, uri, **kw):
return cls.execute(uri, 'POST', **kw)
@classmethod
def PUT(cls, uri, **kw):
return cls.execute(uri, 'PUT', **kw)
@classmethod
def DELETE(cls, uri, **kw):
return cls.execute(uri, 'DELETE', **kw)
__all__ = [
'ParseBase', 'ResourceRequestBadRequest', 'ResourceLoginRequired',
'ResourceRequestForbidden', 'ResourceRequestNotFound'
]
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, 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 General Public License for more details.
#
# 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 urllib2
import urllib
import json
import core
API_ROOT = 'https://api.parse.com/1'
ACCESS_KEYS = {}
def register(app_id, rest_key, **kw):
global ACCESS_KEYS
ACCESS_KEYS = {
'app_id': app_id,
'rest_key': rest_key
}
ACCESS_KEYS.update(**kw)
def master_key_required(func):
'''decorator describing methods that require the master key'''
def ret(obj, *args, **kw):
conn = ACCESS_KEYS
if not (conn and conn.get('master_key')):
message = '%s requires the master key' % func.__name__
raise core.ParseError(message)
func(obj, *args, **kw)
return ret
class ParseBase(object):
ENDPOINT_ROOT = API_ROOT
@classmethod
def execute(cls, uri, http_verb, extra_headers=None, **kw):
if not ('app_id' in ACCESS_KEYS and 'rest_key' in ACCESS_KEYS):
raise core.ParseError('Missing connection credentials')
app_id = ACCESS_KEYS.get('app_id')
rest_key = ACCESS_KEYS.get('rest_key')
master_key = ACCESS_KEYS.get('master_key')
headers = extra_headers or {}
url = uri if uri.startswith(API_ROOT) else cls.ENDPOINT_ROOT + uri
data = kw and json.dumps(kw) or "{}"
if http_verb == 'GET' and data:
url += '?%s' % urllib.urlencode(kw)
data = None
request = urllib2.Request(url, data, headers)
request.add_header('Content-type', 'application/json')
request.add_header('X-Parse-Application-Id', app_id)
request.add_header('X-Parse-REST-API-Key', rest_key)
if master_key: request.add_header('X-Parse-Master-Key', master_key)
request.get_method = lambda: http_verb
try:
response = urllib2.urlopen(request)
except urllib2.HTTPError, e:
exc = {
400: core.ResourceRequestBadRequest,
401: core.ResourceRequestLoginRequired,
403: core.ResourceRequestForbidden,
404: core.ResourceRequestNotFound
}.get(e.code, core.ParseError)
raise exc(e.read())
return json.loads(response.read())
@classmethod
def GET(cls, uri, **kw):
return cls.execute(uri, 'GET', **kw)
@classmethod
def POST(cls, uri, **kw):
return cls.execute(uri, 'POST', **kw)
@classmethod
def PUT(cls, uri, **kw):
return cls.execute(uri, 'PUT', **kw)
@classmethod
def DELETE(cls, uri, **kw):
return cls.execute(uri, 'DELETE', **kw)
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
class ParseError(Exception):
'''Base exceptions from requests made to Parse'''
pass
class ResourceRequestBadRequest(ParseError):
'''Request returns a 400'''
pass
class ResourceRequestLoginRequired(ParseError):
'''Request returns a 401'''
pass
class ResourceRequestForbidden(ParseError):
'''Request returns a 403'''
pass
class ResourceRequestNotFound(ParseError):
'''Request returns a 404'''
pass
......@@ -13,11 +13,11 @@
import base64
import datetime
import urllib2
from __init__ import ParseBase, API_ROOT
from connection import API_ROOT, ParseBase
from query import QueryManager
class ParseType(object):
@staticmethod
......@@ -176,6 +176,7 @@ class File(ParseType):
_absolute_url = property(lambda self: self._api_url)
class ParseResource(ParseBase, Pointer):
PROTECTED_ATTRIBUTES = ['objectId', 'createdAt', 'updatedAt']
......@@ -302,4 +303,3 @@ class Object(ParseResource):
}
self.__class__.PUT(self._absolute_url, **payload)
self.__dict__[key] += amount
......@@ -9,10 +9,11 @@ import os
import sys
import subprocess
import unittest
import urllib2
import datetime
import __init__ as parse_rest
from core import ResourceRequestNotFound
from connection import register
from datatypes import GeoPoint, Object
from function import Function
from user import User
......@@ -24,7 +25,7 @@ except ImportError:
sys.exit('You must create a settings_local.py file with APPLICATION_ID, ' \
'REST_API_KEY, MASTER_KEY variables set')
parse_rest.ParseBase.register(
register(
getattr(settings_local, 'APPLICATION_ID'),
getattr(settings_local, 'REST_API_KEY'),
master_key=getattr(settings_local, 'MASTER_KEY')
......@@ -169,7 +170,6 @@ class TestTypes(unittest.TestCase):
'Can not serialize geopoint data')
def testCanConvertDate(self):
native_score = self.score._to_native()
native_date = self.score._to_native().get('date_of_birth')
self.assert_(type(native_date) is dict,
'Could not serialize date into dict')
......@@ -271,7 +271,6 @@ class TestQuery(unittest.TestCase):
def testCanCompareDateInequality(self):
today = datetime.datetime.today()
tomorrow = today + datetime.timedelta(days=1)
yesterday = today - datetime.timedelta(days=1)
self.assert_(GameScore.Query.lte(createdAt=tomorrow).count() == 5,
'Could not make inequality comparison with dates')
......@@ -352,7 +351,7 @@ class TestUser(unittest.TestCase):
try:
u = User.login(self.USERNAME, self.PASSWORD)
except parse_rest.ResourceRequestNotFound as e:
except ResourceRequestNotFound:
# if the user doesn't exist, that's fine
return
u.delete()
......
......@@ -11,11 +11,9 @@
# 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 base64
import datetime
import copy
from __init__ import API_ROOT
from core import ResourceRequestLoginRequired
from connection import API_ROOT
from datatypes import ParseResource, ParseType
from query import QueryManager
......@@ -85,7 +83,7 @@ class User(ParseResource):
try:
User.POST(url, email=email)
return True
except Exception, why:
except:
return False
def _to_native(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment