aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFilipp Lepalaan <filipp@mac.com>2017-02-22 22:44:36 +0200
committerFilipp Lepalaan <filipp@mac.com>2017-02-22 22:44:36 +0200
commitf998a6bca5ab48ee2d5ce5f52f6a93cff2485c9e (patch)
treeaf9b6dd23b5882a25aeb67c01cfc82d9f4d173d1
downloadbimclient-f998a6bca5ab48ee2d5ce5f52f6a93cff2485c9e.tar.gz
bimclient-f998a6bca5ab48ee2d5ce5f52f6a93cff2485c9e.tar.bz2
bimclient-f998a6bca5ab48ee2d5ce5f52f6a93cff2485c9e.zip
Initial commit
-rw-r--r--.gitignore1
-rw-r--r--README.md22
-rw-r--r--bimclient/__init__.py0
-rw-r--r--bimclient/bimclient.py105
-rw-r--r--requirements.pip1
-rw-r--r--tests.py26
6 files changed, 155 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c5b9bcb
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+### Introduction
+
+This is an ArchiCAD BIMServer/Cloud client library for Python.
+
+
+### System Requirements
+
+- pip install -r requirements.pip
+- ArchiCAD BIMServer or BIMCloud
+
+
+### Usage
+
+Example 1 - get the version number of your BIM server:
+
+```python
+import bimclient
+s = bimclient.connect('http://bim.example.com:19000')
+s.version
+```
+
+Check `tests.py` for more examples.
diff --git a/bimclient/__init__.py b/bimclient/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bimclient/__init__.py
diff --git a/bimclient/bimclient.py b/bimclient/bimclient.py
new file mode 100644
index 0000000..0f0873c
--- /dev/null
+++ b/bimclient/bimclient.py
@@ -0,0 +1,105 @@
+import json
+import logging
+import base64
+import tempfile
+import subprocess
+
+import requests
+
+
+class Session(object):
+ def __init__(self, url):
+ self.session_id = None
+ self.url = url.rstrip('/') + '/'
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args):
+ pass
+
+ def __dict__(self):
+ return self.response
+
+ def request(self, method, data=None):
+ """
+ Sends a request to the BIM server.
+ """
+ url = self.url + method
+ params = {}
+
+ if self.session_id:
+ params['session-id'] = self.session_id
+
+ if data:
+ self._request = requests.post(url, json=data)
+ else:
+ self._request = requests.get(url, params=params)
+
+ self._text = self._request.text
+
+ if method.endswith('get-server-public-key'):
+ logging.debug('Got public key: %s' % self._text)
+ self.key = self._text
+ return self
+
+ try:
+ self.response = self._request.json()
+ except ValueError:
+ raise Exception(self._text)
+
+ if method.endswith('get-server-info'):
+ self.server = self.response
+ self.id = self.response.get('serverId')
+ self.version = self.response.get('versionString')
+ self.name = self.response.get('friendlyName')
+ self.license = self.response.get('license')
+ self.platform = self.response.get('platform')
+
+ return self
+
+ def encrypt_password(self, password):
+ """
+ Encrypts the supplied password with the server's public key
+ and returns the encrypted password
+ """
+ with tempfile.NamedTemporaryFile() as f:
+ f.write(self.key)
+ logging.debug('Wrote public key to %s' % f.name)
+ f.seek(0)
+ p = subprocess.Popen(['openssl', 'rsautl', '-encrypt',
+ '-inkey', f.name, '-pubin'],
+ stdin=subprocess.PIPE,
+ 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.
+ """
+ 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)
+ 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:
+ raise Exception('Authentication failed')
+
+ return self
+
+ def projects(self):
+ self.request('management/latest/get-projects-by-criterion')
+ return self.response
+
+
+def connect(url):
+ with Session(url) as session:
+ return session.request('get-server-info')
diff --git a/requirements.pip b/requirements.pip
new file mode 100644
index 0000000..f229360
--- /dev/null
+++ b/requirements.pip
@@ -0,0 +1 @@
+requests
diff --git a/tests.py b/tests.py
new file mode 100644
index 0000000..136b7fd
--- /dev/null
+++ b/tests.py
@@ -0,0 +1,26 @@
+import os
+import logging
+import unittest
+
+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_projects(self):
+ projects = self.server.projects()
+ self.assertGreater(len(projects), 0)
+
+
+if __name__ == '__main__':
+ logging.basicConfig(level=logging.DEBUG)
+ unittest.main()