Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Pre-commit hooks for luno-python
# See https://pre-commit.com for more information
repos:
# General file checks
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.6.0
hooks:
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]
- id: end-of-file-fixer
- id: check-yaml
- id: check-json
- id: check-added-large-files
args: ['--maxkb=500']
- id: check-merge-conflict
- id: check-case-conflict
- id: mixed-line-ending
args: ['--fix=lf']
- id: detect-private-key

# Python code formatting
- repo: https://github.com/psf/black
rev: 24.10.0
hooks:
- id: black
language_version: python3
args: ['--line-length=120']

# Import sorting
- repo: https://github.com/pycqa/isort
rev: 5.13.2
hooks:
- id: isort
args: ['--profile=black', '--line-length=120']

# Linting
- repo: https://github.com/pycqa/flake8
rev: 7.1.1
hooks:
- id: flake8
args: ['--max-line-length=120', '--extend-ignore=E203,W503']
additional_dependencies: [flake8-docstrings, flake8-bugbear]

# Security checks
- repo: https://github.com/PyCQA/bandit
rev: 1.7.10
hooks:
- id: bandit
args: ['-c', 'pyproject.toml']
additional_dependencies: ['bandit[toml]']

# Python upgrade syntax
- repo: https://github.com/asottile/pyupgrade
rev: v3.19.0
hooks:
- id: pyupgrade
args: [--py37-plus]

# Check for common Python bugs
- repo: https://github.com/pre-commit/pygrep-hooks
rev: v1.10.0
hooks:
- id: python-check-blanket-noqa
- id: python-check-blanket-type-ignore
- id: python-use-type-annotations

# Tests
- repo: local
hooks:
- id: pytest
name: pytest
entry: env/bin/pytest
args: ['-v', '--override-ini=addopts=']
language: system
pass_filenames: false
always_run: true
49 changes: 46 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,66 @@
# Contributing

## Clone

```bash
git clone https://github.com/luno/luno-python.git
```
## Create Virtual env

## Create Virtual env

```bash
cd luno-python
python -m venv env
source env/bin/activate
```

## Install Dependencies

```bash
python -m pip install --upgrade pip setuptools wheel
pip install -e '.[test]'
pip install -e '.[dev]'
```

This installs the package in editable mode with all development dependencies including testing tools and pre-commit hooks.

## Set Up Pre-commit Hooks

This project uses [pre-commit](https://pre-commit.com/) to maintain code quality and consistency. The hooks run automatically before commits and pushes.

### Install the git hook scripts

```bash
pre-commit install
```

This will run code formatting, linting, security checks, and tests on every commit.

### Run hooks manually

To run all hooks on all files manually:

```bash
pre-commit run --all-files
```

### What the hooks do

- **Code formatting**: Automatically formats code with `black` and sorts imports with `isort`
- **Linting**: Checks code quality with `flake8`
- **Security**: Scans for common security issues with `bandit`
- **File checks**: Fixes trailing whitespace, ensures files end with newlines, validates YAML/JSON
- **Tests**: Runs the full test suite (via `pytest`)

### Skip hooks (use sparingly)

If you need to skip hooks for a specific commit:

```bash
git commit --no-verify
```

## Run Tests

```bash
pytest
```
```
1 change: 0 additions & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,3 @@ except Exception as e:
### License

[MIT](https://github.com/luno/luno-python/blob/master/LICENSE.txt)

34 changes: 16 additions & 18 deletions examples/readonly.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,37 @@

from luno_python.client import Client


if __name__ == '__main__':
c = Client(api_key_id=os.getenv('LUNO_API_KEY_ID'),
api_key_secret=os.getenv('LUNO_API_KEY_SECRET'))
if __name__ == "__main__":
c = Client(api_key_id=os.getenv("LUNO_API_KEY_ID"), api_key_secret=os.getenv("LUNO_API_KEY_SECRET"))

res = c.get_tickers()
print(res)
time.sleep(0.5)

res = c.get_ticker(pair='XBTZAR')
res = c.get_ticker(pair="XBTZAR")
print(res)
time.sleep(0.5)

res = c.get_order_book(pair='XBTZAR')
res = c.get_order_book(pair="XBTZAR")
print(res)
time.sleep(0.5)

since = int(time.time()*1000)-24*60*59*1000
res = c.list_trades(pair='XBTZAR', since=since)
since = int(time.time() * 1000) - 24 * 60 * 59 * 1000
res = c.list_trades(pair="XBTZAR", since=since)
print(res)
time.sleep(0.5)

res = c.get_candles(pair='XBTZAR', since=since, duration=300)
res = c.get_candles(pair="XBTZAR", since=since, duration=300)
print(res)
time.sleep(0.5)

res = c.get_balances()
print(res)
time.sleep(0.5)

aid = ''
if res['balance']:
aid = res['balance'][0]['account_id']
aid = ""
if res["balance"]:
aid = res["balance"][0]["account_id"]

if aid:
res = c.list_transactions(id=aid, min_row=1, max_row=10)
Expand All @@ -51,25 +49,25 @@
print(res)
time.sleep(0.5)

res = c.list_user_trades(pair='XBTZAR')
res = c.list_user_trades(pair="XBTZAR")
print(res)
time.sleep(0.5)

res = c.get_fee_info(pair='XBTZAR')
res = c.get_fee_info(pair="XBTZAR")
print(res)
time.sleep(0.5)

res = c.get_funding_address(asset='XBT')
res = c.get_funding_address(asset="XBT")
print(res)
time.sleep(0.5)

res = c.list_withdrawals()
print(res)
time.sleep(0.5)

wid = ''
if res['withdrawals']:
wid = res['withdrawals'][0]['id']
wid = ""
if res["withdrawals"]:
wid = res["withdrawals"][0]["id"]

if wid:
res = c.get_withdrawal(id=wid)
Expand Down
2 changes: 1 addition & 1 deletion luno_python/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = '0.0.10'
VERSION = "0.0.10"
29 changes: 14 additions & 15 deletions luno_python/base_client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import json
import platform

import requests
import six

Expand All @@ -11,16 +12,15 @@
from . import VERSION
from .error import APIError

DEFAULT_BASE_URL = 'https://api.luno.com'
DEFAULT_BASE_URL = "https://api.luno.com"
DEFAULT_TIMEOUT = 10
PYTHON_VERSION = platform.python_version()
SYSTEM = platform.system()
ARCH = platform.machine()


class BaseClient:
def __init__(self, base_url='', timeout=0,
api_key_id='', api_key_secret=''):
def __init__(self, base_url="", timeout=0, api_key_id="", api_key_secret=""):
"""
:type base_url: str
:type timeout: float
Expand All @@ -47,9 +47,9 @@ def set_base_url(self, base_url):

:type base_url: str
"""
if base_url == '':
if base_url == "":
base_url = DEFAULT_BASE_URL
self.base_url = base_url.rstrip('/')
self.base_url = base_url.rstrip("/")

def set_timeout(self, timeout):
"""Sets the timeout, in seconds, for requests made by the client.
Expand All @@ -74,33 +74,32 @@ def do(self, method, path, req=None, auth=False):
params = json.loads(json.dumps(req))
except Exception:
params = None
headers = {'User-Agent': self.make_user_agent()}
headers = {"User-Agent": self.make_user_agent()}
args = dict(timeout=self.timeout, params=params, headers=headers)
if auth:
args['auth'] = (self.api_key_id, self.api_key_secret)
args["auth"] = (self.api_key_id, self.api_key_secret)
url = self.make_url(path, params)
res = self.session.request(method, url, **args)
try:
e = res.json()
if 'error' in e and 'error_code' in e:
raise APIError(e['error_code'], e['error'])
if "error" in e and "error_code" in e:
raise APIError(e["error_code"], e["error"])
return e
except JSONDecodeError:
raise Exception('luno: unknown API error (%s)' % res.status_code)
raise Exception("luno: unknown API error (%s)" % res.status_code)

def make_url(self, path, params):
"""
:type path: str
:rtype: str
"""
if params:
for k, v in six.iteritems(params):
path = path.replace('{' + k + '}', str(v))
return self.base_url + '/' + path.lstrip('/')
for k, v in params.items():
path = path.replace("{" + k + "}", str(v))
return self.base_url + "/" + path.lstrip("/")

def make_user_agent(self):
"""
:rtype: str
"""
return "LunoPythonSDK/%s python/%s %s %s" % \
(VERSION, PYTHON_VERSION, SYSTEM, ARCH)
return f"LunoPythonSDK/{VERSION} python/{PYTHON_VERSION} {SYSTEM} {ARCH}"
Loading