From fcf01fca44c4b1096ff3e628265c8802d4c4560f Mon Sep 17 00:00:00 2001 From: Filipp Lepalaan Date: Fri, 24 Feb 2017 15:42:31 +0200 Subject: Added session_id caching --- README.md | 34 +++++++++++++++++++++++++++++++-- bimclient/__init__.py | 5 +++++ bimclient/bimclient.py | 52 ++++++++++++++++++++++++++++++++++++++------------ tests.py | 10 ++++------ 4 files changed, 81 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index c5b9bcb..c42a867 100644 --- a/README.md +++ b/README.md @@ -11,12 +11,42 @@ This is an ArchiCAD BIMServer/Cloud client library for Python. ### Usage -Example 1 - get the version number of your BIM server: - ```python import bimclient s = bimclient.connect('http://bim.example.com:19000') +# version of BIM server s.version + +# get all projects on the server +projects = s.projects() + ``` Check `tests.py` for more examples. + + +### License + + Copyright (c) 2017, Filipp Lepalaan All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. diff --git a/bimclient/__init__.py b/bimclient/__init__.py index e69de29..f429e02 100644 --- a/bimclient/__init__.py +++ b/bimclient/__init__.py @@ -0,0 +1,5 @@ +__title__ = 'bimclient' +__version__ = '0.1' +__author__ = 'Filipp Lepalaan' +__license__ = 'BSD' +__copyright__ = 'Copyright 2017 Filipp Lepalaan' diff --git a/bimclient/bimclient.py b/bimclient/bimclient.py index 0f0873c..9991822 100644 --- a/bimclient/bimclient.py +++ b/bimclient/bimclient.py @@ -1,6 +1,9 @@ +import os import json -import logging import base64 +import shelve +import urllib +import logging import tempfile import subprocess @@ -25,14 +28,17 @@ class Session(object): """ Sends a request to the BIM server. """ - url = self.url + method params = {} + url = self.url + method + + if type(data) is str: + data = json.loads(data) if self.session_id: params['session-id'] = self.session_id if data: - self._request = requests.post(url, json=data) + self._request = requests.post(url, params=params, json=data) else: self._request = requests.get(url, params=params) @@ -47,7 +53,14 @@ class Session(object): self.response = self._request.json() except ValueError: raise Exception(self._text) - + + if type(self.response) == dict: + if self.response.get('error-code'): + raise Exception(self.response.get('error-message')) + + if self.response.get('status', 0) == 400: + raise Exception(self.response.get('message')) + if method.endswith('get-server-info'): self.server = self.response self.id = self.response.get('serverId') @@ -73,30 +86,45 @@ class Session(object): stdout=subprocess.PIPE) o, e = p.communicate(password + '00000000') password = base64.b64encode(o) - return password def login(self, username, password): """ Authenticates with the BIM server. + Returns self for further queries. """ - self.request('management/latest/get-server-public-key') - password = self.encrypt_password(password) - d = {'username': username, 'password': password} - logging.debug('Auth request: %s' % d) - self.request('management/latest/create-session', data=d) + db = os.path.join(tempfile.gettempdir(), 'bimclient_db') + cache = shelve.open(db) + session = cache.get('session') + + if session: + logging.debug('Using cached session: %s' % session) + self.response = session + else: + self.request('management/latest/get-server-public-key') + password = self.encrypt_password(password) + d = {'username': username, 'password': password} + self.request('management/latest/create-session', data=d) + cache['session'] = self.response + cache.close() + logging.debug(self.response) + self.user_id = self.response.get('user-id') self.session_id = self.response.get('session-id') self.session_timeout = self.response.get('expire-timeout') - if not self.user_id: + if self.user_id: + logging.debug('Logged in as %s' % self.user_id) + else: raise Exception('Authentication failed') return self def projects(self): - self.request('management/latest/get-projects-by-criterion') + data = json.loads('{"$and":[{"$or":[{"$eq":{"id":"projectRoot"}},{"$eq":{"$parentId":"projectRoot"}}]}]}') + self.request('management/latest/get-resources-by-criterion', data=data) + logging.debug(self.response) return self.response diff --git a/tests.py b/tests.py index 136b7fd..80e0a31 100644 --- a/tests.py +++ b/tests.py @@ -8,17 +8,15 @@ from bimclient import bimclient class TestServerMethods(unittest.TestCase): def setUp(self): self.server = bimclient.connect(os.getenv('BIMCLIENT_URL')) - - def test_connect(self): - self.assertEquals(len(self.server.version), 6) - - def test_login(self): self.server.login(os.getenv('BIMCLIENT_USER'), os.getenv('BIMCLIENT_PW')) + def test_connect(self): + self.assertEquals(len(self.server.version), 6) + def test_projects(self): projects = self.server.projects() - self.assertGreater(len(projects), 0) + self.assertGreater(len(projects[0]['name']), 3) if __name__ == '__main__': -- cgit v1.2.3