Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
EldarAliiev committed Aug 3, 2017
0 parents commit 648d1cf
Show file tree
Hide file tree
Showing 21 changed files with 1,050 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

[run]
branch = True

[report]
precision = 2

[html]
directory = reports/coverage
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
__pycache__/
*.py[cod]
/.git/
/.tox/
/.cache/
.coverage
/reports/
/.idea/
/env/
/edbo_connector/config.py
6 changes: 6 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[MASTER]
ignore=tests

[REPORTS]
output-format = text
reports = yes
6 changes: 6 additions & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
edbo-connector-py is written and maintained by Eldar Aliiev.

Contributors
````````````

- Eldar Aliiev <[email protected]> `@ZimGreen <https://github.com/ZimGreen>`_
2 changes: 2 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
include README.rst AUTHORS.rst LICENSE
recursive-include tests *.py
32 changes: 32 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
EDBO-connector
==============

Python library for work with EDBO

https://github.com/ZimGreen/edbo-connector-py

Install:
--------

```bash
$ git clone https://github.com/ZimGreen/edbo-connector-py.git
$ cd edbo-connector-py
$ python setup.py install
```

or with pip:

```bash
$ pip install edbo_connector
```

Before use rename `"config.example.py"` to `"config.py"` inside the package
and add your own configs.

Usage example:
--------------

```python
```

For disable debug output change **ECHO_ON** variable to *False*.
21 changes: 21 additions & 0 deletions edbo_connector/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
edbo_connector
Author: Eldar Aliiev
Email: [email protected]
"""

from edbo_connector.client import EDBOWebApiClient

__name__ = 'edbo_connector'
__author__ = 'Eldar Aliiev'
__copyright__ = 'Copyright 2017, National Pirogov Memorial Medical University, Vinnytsya'
__credits__ = ['Eldar Aliiev']
__license__ = 'MIT'
__version__ = '1.0.0'
__maintainer__ = 'Eldar Aliiev'
__email__ = '[email protected]'
__status__ = 'Production'
__all__ = ['EDBOWebApiClient']
83 changes: 83 additions & 0 deletions edbo_connector/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
EDBOWebApiClient
Author: Eldar Aliiev
Email: [email protected]
"""

import re
import edbo_connector.config as config
from edbo_connector.connector import EDBOWebApiConnector
from edbo_connector.helper import EDBOWebApiHelper
from edbo_connector.methods import EDBOWebApiMethods


class EDBOWebApiClient(EDBOWebApiMethods):
"""EDBOWebApiClient - class which implements some RESTful API methods
and interface for methods execution by their names.
"""

def __init__(self, username=config.EDBO_USER, password=config.EDBO_PASSWORD):
"""Initialize connector and prepare client to work
:param username: Username (Default=from config file)
:param password: Method data (Default=from config file)
:type username: str
:type password: str
"""
self._connector = EDBOWebApiConnector(username, password) # Initialize connector
self._university_info = self._connector.execute('university/list')[0] # Get university info

def __getattr__(self, method):
"""Call RESTful API method
:param method: Method of RESTful API
:type method: str
:return: Method for execution
:rtype: function
"""

if re.match(r'([0-9a-z_]+)', method) is not None: # Check if method name is valid
url = method.replace('_', '/') # Transform method name into url

def wrapper(data=None, headers=None, json_format=True):
return self._connector.execute(
url,
data,
headers,
json_format
) # Send request to server

return wrapper
else: # Fail if method is incorrect
EDBOWebApiHelper.echo(u'Некоректний метод!', color='red')
return

def get_status(self):
"""Return status of last request
:return: Status of last method execution
:rtype: int
"""
return self._connector.status

def get_execution_time(self):
"""Return execution time of last request
:return: Time of last method execution
:rtype: float"""
return self._connector.execution_time

def get_user_info(self):
"""Get information about current user
:return: Information about current user
:rtype: dict
"""
return self._connector.execute('auth/userInfo')

def get_university_info(self, field):
"""Get university info
:param field: Name of field
:type field: str
:return: University info field
:rtype: str, int
"""
return self._university_info.get(field, None)
13 changes: 13 additions & 0 deletions edbo_connector/config.example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

EDBO_SERVER = '' # Path to "ІІТ Захист з'єднань-2.Клієнт"
EDBO_USER = '' # User of RESTful API
EDBO_PASSWORD = '' # Password
EDBO_APPLICATION_KEY = '' # RESTful API key

ECHO_ON = True # Print log messages
EXECUTION_TIMEOUT = 0 # Timeout between queries to server
CONNECTION_RETRIES = 15 # Maximal count of retries
USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
MAX_REQUESTS_COUNT = 15000 # Maximal count of requests in one query
180 changes: 180 additions & 0 deletions edbo_connector/connector.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

"""
EDBOWebApiConnector
Author: Eldar Aliiev
Email: [email protected]
"""

import time
import requests
from requests.adapters import HTTPAdapter
import edbo_connector.config as config
from edbo_connector.helper import EDBOWebApiHelper


class EDBOWebApiConnector(object):
"""EDBOWebApiConnector - class which implements connection
and method execution with EDBO RESTfull API.
Attributes:
url_prefix Path to RESTful API server.
"""

url_prefix = '%s/data/EDEBOWebApi' % config.EDBO_SERVER # Build url to RESTful server

def __init__(self, username=config.EDBO_USER, password=config.EDBO_PASSWORD):
"""Initialize connect and login into RESTful API server.
:param username: Username (Default=from config file)
:param password: Method data (Default=from config file)
:type username: str
:type password: str
"""
self._status = None # Initialize status
self._execution_time = 0 # Initialize execution_time
self._is_logged_in = False # Is user logged in
self._session = requests.Session() # Initialize client session
self._session.mount(
config.EDBO_SERVER,
HTTPAdapter(max_retries=config.CONNECTION_RETRIES)
) # Mount RESTful API server to our session
self.__login(username, password) # Login into server

def __del__(self):
"""End of session"""
if self._is_logged_in: # Check if user is logged in
self.__logout()

@property
def status(self):
"""Return status of last request
:return: Status of last method execution
:rtype: int
"""
return self._status

@property
def execution_time(self):
"""Return execution time of last request
:return: Time of last method execution
:rtype: float
"""
return self._execution_time

@property
def default_headers(self):
"""Default request headers
:return: Default request headers such as user-agent, referer and etc
:rtype: dict
"""
return {
'Origin': config.EDBO_SERVER,
'Referer': config.EDBO_SERVER,
'User-Agent': config.USER_AGENT,
}

def __login(self, username=config.EDBO_USER, password=config.EDBO_PASSWORD):
"""Login request to RESTful API"""

EDBOWebApiHelper.echo(u'Вхід в систему...')
try:
response = self._session.post(
self.url_prefix + '/oauth/token',
data={
'grant_type': 'password',
'username': username,
'password': password,
'app_key': config.EDBO_APPLICATION_KEY,
},
headers=self.default_headers
) # Send authorization request
except requests.exceptions.ConnectionError:
EDBOWebApiHelper.echo(
u'Не вдалося встановити зв\'язок з сервером!',
color='red',
force_exit=True
)

if response.status_code == 200: # Check if authorization is successful
self._session_start_time = time.time() # Catch session start time
self._status = response.status_code # Catch last response status code
self._is_logged_in = True # Logged in
self._access_token = response.json().get('access_token', None) # Get access token
EDBOWebApiHelper.echo(u'Вхід успішний, вітаю %s!' % config.EDBO_USER, color='green')
elif response.status_code == 400:
EDBOWebApiHelper.echo(
response.json().get('error', u'Трапилася невідома помилка!'),
color='red',
force_exit=True
) # Incorrect login data
else:
EDBOWebApiHelper.echo(
u'Не вдалося авторизуватися в системі!',
color='red',
force_exit=True
) # Fail if login is unsuccessful

def __logout(self):
"""Logout from server"""
EDBOWebApiHelper.echo(u'Вихід з системи...', color='red')
self.execute('auth/logout') # Logout from server
self._is_logged_in = False # Logged out

def execute(self, url, data=None, headers=None, json_format=True):
"""Send request to RESTful server.
:param url: Path to RESTful method
:param data: Method data (Default=empty)
:param headers: Default headers (Default=empty)
:param json_format: Return results dictionary or object (Default=True)
:type url: str
:type data: dict
:type headers: dict
:type json_format: bool
:returns: Result of method execution
:rtype: dict, object
"""
if int(time.time() - self._session_start_time) > 60 * 15: # Check if session is not expired (15min)
EDBOWebApiHelper.echo(u'Сесія добігає кінця, поновлення...')
self.__logout() # Logout from server
self.__login() # Login again if session is expired

time.sleep(config.EXECUTION_TIMEOUT) # Wait between methods execution

headers = headers if headers is not None else {} # Initialize headers if not exists
headers.update(self.default_headers) # Add default headers
headers.update({
'authorization': 'Bearer ' + self._access_token,
}) # Add OAuth header

while True: # Try to execute method
try:
EDBOWebApiHelper.echo(u'Виконання методу %s...' % url)
execution_start = time.time() # Catch start of execution
response = self._session.post(
'%s/api/%s' % (self.url_prefix, url),
data if data is not None else {'': ''},
headers=headers
) # Send request to RESTful server
execution_end = time.time() # Catch end of execution
except requests.exceptions.ConnectionError: # Check if method execution is successful
EDBOWebApiHelper.echo(
u'Виконання методу завершено невдало, повторна спроба...',
color='red'
)
continue # Retry if unsuccessful
break

self._execution_time = execution_end - execution_start # Save last execution time
self._status = response.status_code # Save last status code

EDBOWebApiHelper.echo(
u'Виконання методу завершено з кодом %d [%.3fs]' % (
self._status,
self._execution_time
),
color='green'
)

if self._status == 200: # Check if server return data
return response.json() if json_format else response # Return result of method execution
Loading

0 comments on commit 648d1cf

Please sign in to comment.