Skip to content

Commit b40fca1

Browse files
chylli-derivsasikala-binarysasikalachinnasamysasikala-binary
authored
* init * type hinting * doc * remove debug code * remove debug code * change init * update makefile * docstring of cache * apply Sasikala doc change * Update README.md * add docstring * rename varialbe * fix warnings in pycharm * fix something according to pycharm * fix something according to pycharm * fix something according to pycharm * fix something according to pycharm * install pdoc * improvement * fix __init__.py * setup instruction * doc * docs * calls file from script * include readme and examples in doc * update doc * add more example * improve doc * remove html docs from main branch * improve * improve * improve * update filie * fix error * add doc and improve * Update docs/templates/config.mako * add python to md * new line * newline * type annotation, doc, fixes * PR fix * pr comments fix * improvement * package setup for pypi * pr comment addressed and improve doc * small change * pypi setup improvements * pypi setup improvements * coverage * coverage * coverage * small changes and example with stream * doc improvement * improvement * improvement * company name and gitignore update * dependency Co-authored-by: sasikala-binary <76985137+sasikala-binary@users.noreply.github.com> Co-authored-by: sasikala-binary <sasikala.chinnasamy@gmail.com> Co-authored-by: sasikala-binary <sasikala-binary@deriv.com> Co-authored-by: sasikala-binary <sasikala@deriv.com>
1 parent fb6c5ec commit b40fca1

34 files changed

+10941
-1
lines changed

.circleci/config.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
version: 2
2+
jobs:
3+
build:
4+
docker:
5+
- image: circleci/python:3.9.6
6+
environment: # environment variables for primary container
7+
PIPENV_VENV_IN_PROJECT: true
8+
steps: # steps that comprise the `build` job
9+
- checkout # check out source code to working directory
10+
- run: sudo chown -R circleci:circleci /usr/local/bin
11+
- restore_cache:
12+
# Read about caching dependencies: https://circleci.com/docs/2.0/caching/
13+
key: deps9-{{ .Branch }}-{{ checksum "Pipfile.lock" }}
14+
- run:
15+
command: |
16+
make setup
17+
- save_cache: # cache Python dependencies using checksum of Pipfile as the cache-key
18+
key: deps9-{{ .Branch }}-{{ checksum "Pipfile.lock" }}
19+
paths:
20+
- "venv"
21+
- run:
22+
command: |
23+
make test
24+
- run:
25+
command: |
26+
make coverage

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
__pycache_/
2+
*.py[cod]
3+
.pytest_cache/
4+
.eggs/
5+
venv/
6+
*.egg-info/
7+
.idea
8+
dist
9+
.coverage

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021 Deriv Group Services Ltd
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.PHONY: all setup test doc gh-pages build
2+
all: setup test
3+
setup:
4+
pip3 install pipenv && pipenv install --dev
5+
test:
6+
pipenv run python setup.py pytest
7+
doc:
8+
pdoc deriv_api --force --html -o docs/html --template-dir docs/templates
9+
gh-pages:
10+
pdoc deriv_api --force --html -o /tmp/python-deriv-api-docs --template-dir docs/templates && git add . && git stash && git checkout gh-pages && cp -r /tmp/python-deriv-api-docs/deriv_api/* . && git add . && git commit -m 'Update docs' && git push && git checkout -
11+
build:
12+
pip3 install build && python3 -m build
13+
coverage:
14+
pipenv run coverage run --source deriv_api -m pytest && pipenv run coverage report -m

Pipfile

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[packages]
2+
websockets = "==9.1"
3+
rx = "==3.1.1"
4+
deriv-api = {editable = true, path = "."}
5+
6+
[dev-packages]
7+
pytest = "*"
8+
pytest-runner = "*"
9+
pytest-mock = "*"
10+
pytest-asyncio = "*"
11+
pdoc3 = "*"
12+
coverage = "===4.5.4"
13+
14+
[requires]
15+
python_version = "3.9.6"

Pipfile.lock

Lines changed: 316 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,117 @@
11
# python-deriv-api
2-
Python bindings for deriv.com websocket API
2+
A python implementation of deriv api library.
3+
4+
[![PyPI](https://img.shields.io/pypi/v/python_deriv_api.svg?style=flat-square)](https://pypi.org/project/python_deriv_api/)
5+
[![Python 3.9.6](https://img.shields.io/badge/python-3.9.6-blue.svg)](https://www.python.org/download/releases/3.9.6/)
6+
[![Test status](https://circleci.com/gh/binary-com/python-deriv-api.svg?style=shield&circle-token=8b7c7b39615ea83053044854105bf90975b18126)](https://app.circleci.com/pipelines/github/binary-com/python-deriv-api)
7+
8+
Go through [api.deriv.com](https://api.deriv.com/) to know simple easy steps on how to register and get access.
9+
Use this all-in-one python library to set up and make your app running or you can extend it.
10+
11+
### Requirement
12+
Python (3.9.6 or higher is recommended) and pip3
13+
14+
Note: There is bug in 'websockets' package with python 3.9.7, hope that will be fixed in 3.9.8 as mentioned in
15+
https://github.com/aaugustin/websockets/issues/1051. Please exclude python 3.9.7.
16+
17+
# Installation
18+
19+
`python3 -m pip install python_deriv_api`
20+
21+
# Usage
22+
This is basic deriv-api python library which helps to make websockets connection and
23+
deal the API calls (including subscription).
24+
25+
Import the module
26+
27+
```
28+
from deriv_api import DerivAPI
29+
```
30+
31+
Access
32+
33+
```
34+
api = DerivAPI(endpoint='ws://...', app_id=1234);
35+
response = await api.ping({'ping': 1})
36+
print(response)
37+
```
38+
39+
## Creating a websockets connection and API instantiation
40+
You can either create an instance of websockets and pass it as connection
41+
or
42+
pass the endpoint and app_id to the constructor to create the connection for you.
43+
44+
If you pass the connection it's up to you to reconnect in case the connection drops (cause API doesn't know how to create the same connection).
45+
46+
47+
- Pass the arguments needed to create a connection:
48+
```
49+
api = DerivAPI(endpoint='ws://...', app_id=1234);
50+
```
51+
52+
- create and use a previously opened connection:
53+
```
54+
connection = await websockets.connect('ws://...')
55+
api = DerivAPI(connection=connection)
56+
```
57+
58+
# Documentation
59+
60+
#### API reference
61+
The complete API reference is hosted [here](https://binary-com.github.io/python-deriv-api/)
62+
63+
Examples [here](https://github.com/binary-com/python-deriv-api/examples)
64+
65+
# Development
66+
```
67+
git clone https://github.com/binary-com/python-deriv-api
68+
cd python-deriv-api
69+
```
70+
Setup environment
71+
```
72+
make setup
73+
```
74+
75+
Setup environment and run test
76+
```
77+
make all
78+
```
79+
80+
#### Run test
81+
82+
```
83+
python setup.py pytest
84+
```
85+
86+
or
87+
88+
```
89+
pytest
90+
```
91+
92+
or
93+
94+
```
95+
make test
96+
```
97+
#### Generate documentations
98+
99+
Generate html version of the docs and publish it to gh-pages
100+
101+
```
102+
make gh-pages
103+
```
104+
105+
#### Build the package
106+
```
107+
make build
108+
```
109+
#### Run examples
110+
111+
set token and run example
112+
113+
```
114+
export DERIV_TOKEN=xxxTokenxxx
115+
PYTHONPATH=. python3 examples/simple_bot1.py
116+
```
117+

deriv_api/__init__.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
.. include:: ../README.md
3+
.. include:: ../docs/usage_examples.md
4+
"""
5+
6+
__pdoc__ = {
7+
'deriv_api.errors': False,
8+
'deriv_api.utils': False,
9+
'deriv_api.easy_future': False
10+
}
11+
12+
from .deriv_api import DerivAPI
13+
from .errors import AddedTaskError, APIError, ConstructionError, ResponseError
14+

deriv_api/cache.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
from __future__ import annotations
2+
from typing import TYPE_CHECKING, Union
3+
4+
if TYPE_CHECKING:
5+
from deriv_api import DerivAPI
6+
from deriv_api.deriv_api_calls import DerivAPICalls
7+
from deriv_api.errors import ConstructionError
8+
from deriv_api.utils import dict_to_cache_key
9+
from deriv_api.in_memory import InMemory
10+
11+
__pdoc__ = {
12+
'deriv_api.cache.Cache.get': False,
13+
'deriv_api.cache.Cache.get_by_msg_type': False,
14+
'deriv_api.cache.Cache.has': False,
15+
'deriv_api.cache.Cache.send': False,
16+
'deriv_api.cache.Cache.set': False
17+
}
18+
19+
20+
class Cache(DerivAPICalls):
21+
"""
22+
Cache - A class for implementing in-memory and persistent cache
23+
24+
The real implementation of the underlying cache is delegated to the storage
25+
object (See the params).
26+
27+
The storage object needs to implement the API.
28+
29+
Examples
30+
--------
31+
- Read the latest active symbols
32+
>>> symbols = await api.active_symbols()
33+
34+
- Read the data from cache if available
35+
>>> cached_symbols = await api.cache.active_symbols()
36+
37+
Parameters
38+
----------
39+
api : deriv_api.DerivAPI
40+
API instance to get data that is not cached
41+
storage : Object
42+
A storage instance to use for caching
43+
"""
44+
45+
def __init__(self, api: Union[DerivAPI, Cache], storage: Union[InMemory, Cache]) -> None:
46+
if not api:
47+
raise ConstructionError('Cache object needs an API to work')
48+
49+
super().__init__()
50+
self.api = api
51+
self.storage = storage
52+
53+
async def send(self, request: dict) -> dict:
54+
"""Check if there is a cache for the request. If so then return that value.
55+
Otherwise send the request by the api
56+
57+
Parameters
58+
----------
59+
request : dict
60+
API request
61+
62+
Returns
63+
-------
64+
API Response
65+
"""
66+
if await self.has(request):
67+
return await self.get(request)
68+
69+
response = await self.api.send(request)
70+
self.set(request, response)
71+
return response
72+
73+
async def has(self, request: dict) -> bool:
74+
"""Redirected to the method defined by the storage
75+
76+
Parameters
77+
----------
78+
request : dict
79+
API request
80+
81+
Returns
82+
-------
83+
Returns true if the request exists
84+
"""
85+
return self.storage.has(dict_to_cache_key(request))
86+
87+
async def get(self, request: dict) -> dict:
88+
"""Redirected to the method defined by the storage
89+
90+
Parameters
91+
----------
92+
request : dict
93+
API request
94+
95+
Returns
96+
-------
97+
API response stored in
98+
"""
99+
return self.storage.get(dict_to_cache_key(request))
100+
101+
async def get_by_msg_type(self, msg_type: str) -> dict:
102+
"""Redirected to the method defined by the storage
103+
104+
Parameters
105+
----------
106+
msg_type : str
107+
Request msg_type
108+
109+
Returns
110+
-------
111+
Returns response stored in
112+
"""
113+
return self.storage.get_by_msg_type(msg_type)
114+
115+
def set(self, request: dict, response: dict) -> None:
116+
"""Redirected to the method defined by the storage
117+
118+
Parameters
119+
----------
120+
request : dict
121+
API request
122+
response : dict
123+
API response
124+
"""
125+
return self.storage.set(dict_to_cache_key(request), response)

0 commit comments

Comments
 (0)