Skip to content

Commit 78ae253

Browse files
authored
precommit: Add config, apply changes (#72)
* precommit: Add config, apply changes * tests: Extract common responses to vars * pyproject: Update settings to match hook line length
1 parent 71f9031 commit 78ae253

12 files changed

Lines changed: 620 additions & 354 deletions

File tree

.pre-commit-config.yaml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Pre-commit hooks for luno-python
2+
# See https://pre-commit.com for more information
3+
repos:
4+
# General file checks
5+
- repo: https://github.com/pre-commit/pre-commit-hooks
6+
rev: v4.6.0
7+
hooks:
8+
- id: trailing-whitespace
9+
args: [--markdown-linebreak-ext=md]
10+
- id: end-of-file-fixer
11+
- id: check-yaml
12+
- id: check-json
13+
- id: check-added-large-files
14+
args: ['--maxkb=500']
15+
- id: check-merge-conflict
16+
- id: check-case-conflict
17+
- id: mixed-line-ending
18+
args: ['--fix=lf']
19+
- id: detect-private-key
20+
21+
# Python code formatting
22+
- repo: https://github.com/psf/black
23+
rev: 24.10.0
24+
hooks:
25+
- id: black
26+
language_version: python3
27+
args: ['--line-length=120']
28+
29+
# Import sorting
30+
- repo: https://github.com/pycqa/isort
31+
rev: 5.13.2
32+
hooks:
33+
- id: isort
34+
args: ['--profile=black', '--line-length=120']
35+
36+
# Linting
37+
- repo: https://github.com/pycqa/flake8
38+
rev: 7.1.1
39+
hooks:
40+
- id: flake8
41+
args: ['--max-line-length=120', '--extend-ignore=E203,W503']
42+
additional_dependencies: [flake8-docstrings, flake8-bugbear]
43+
44+
# Security checks
45+
- repo: https://github.com/PyCQA/bandit
46+
rev: 1.7.10
47+
hooks:
48+
- id: bandit
49+
args: ['-c', 'pyproject.toml']
50+
additional_dependencies: ['bandit[toml]']
51+
52+
# Python upgrade syntax
53+
- repo: https://github.com/asottile/pyupgrade
54+
rev: v3.19.0
55+
hooks:
56+
- id: pyupgrade
57+
args: [--py37-plus]
58+
59+
# Check for common Python bugs
60+
- repo: https://github.com/pre-commit/pygrep-hooks
61+
rev: v1.10.0
62+
hooks:
63+
- id: python-check-blanket-noqa
64+
- id: python-check-blanket-type-ignore
65+
- id: python-use-type-annotations
66+
67+
# Tests
68+
- repo: local
69+
hooks:
70+
- id: pytest
71+
name: pytest
72+
entry: env/bin/pytest
73+
args: ['-v', '--override-ini=addopts=']
74+
language: system
75+
pass_filenames: false
76+
always_run: true

CONTRIBUTING.md

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,66 @@
11
# Contributing
22

33
## Clone
4+
45
```bash
56
git clone https://github.com/luno/luno-python.git
67
```
7-
## Create Virtual env
8+
9+
## Create Virtual env
10+
811
```bash
912
cd luno-python
1013
python -m venv env
1114
source env/bin/activate
1215
```
1316

1417
## Install Dependencies
18+
1519
```bash
1620
python -m pip install --upgrade pip setuptools wheel
17-
pip install -e '.[test]'
21+
pip install -e '.[dev]'
22+
```
23+
24+
This installs the package in editable mode with all development dependencies including testing tools and pre-commit hooks.
25+
26+
## Set Up Pre-commit Hooks
27+
28+
This project uses [pre-commit](https://pre-commit.com/) to maintain code quality and consistency. The hooks run automatically before commits and pushes.
29+
30+
### Install the git hook scripts
31+
32+
```bash
33+
pre-commit install
34+
```
35+
36+
This will run code formatting, linting, security checks, and tests on every commit.
37+
38+
### Run hooks manually
39+
40+
To run all hooks on all files manually:
41+
42+
```bash
43+
pre-commit run --all-files
44+
```
45+
46+
### What the hooks do
47+
48+
- **Code formatting**: Automatically formats code with `black` and sorts imports with `isort`
49+
- **Linting**: Checks code quality with `flake8`
50+
- **Security**: Scans for common security issues with `bandit`
51+
- **File checks**: Fixes trailing whitespace, ensures files end with newlines, validates YAML/JSON
52+
- **Tests**: Runs the full test suite (via `pytest`)
53+
54+
### Skip hooks (use sparingly)
55+
56+
If you need to skip hooks for a specific commit:
57+
58+
```bash
59+
git commit --no-verify
1860
```
1961

2062
## Run Tests
63+
2164
```bash
2265
pytest
23-
```
66+
```

LICENSE.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1919
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2020
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
SOFTWARE.
22-

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,3 @@ except Exception as e:
3131
### License
3232

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

examples/readonly.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,37 @@
33

44
from luno_python.client import Client
55

6-
7-
if __name__ == '__main__':
8-
c = Client(api_key_id=os.getenv('LUNO_API_KEY_ID'),
9-
api_key_secret=os.getenv('LUNO_API_KEY_SECRET'))
6+
if __name__ == "__main__":
7+
c = Client(api_key_id=os.getenv("LUNO_API_KEY_ID"), api_key_secret=os.getenv("LUNO_API_KEY_SECRET"))
108

119
res = c.get_tickers()
1210
print(res)
1311
time.sleep(0.5)
1412

15-
res = c.get_ticker(pair='XBTZAR')
13+
res = c.get_ticker(pair="XBTZAR")
1614
print(res)
1715
time.sleep(0.5)
1816

19-
res = c.get_order_book(pair='XBTZAR')
17+
res = c.get_order_book(pair="XBTZAR")
2018
print(res)
2119
time.sleep(0.5)
2220

23-
since = int(time.time()*1000)-24*60*59*1000
24-
res = c.list_trades(pair='XBTZAR', since=since)
21+
since = int(time.time() * 1000) - 24 * 60 * 59 * 1000
22+
res = c.list_trades(pair="XBTZAR", since=since)
2523
print(res)
2624
time.sleep(0.5)
2725

28-
res = c.get_candles(pair='XBTZAR', since=since, duration=300)
26+
res = c.get_candles(pair="XBTZAR", since=since, duration=300)
2927
print(res)
3028
time.sleep(0.5)
3129

3230
res = c.get_balances()
3331
print(res)
3432
time.sleep(0.5)
3533

36-
aid = ''
37-
if res['balance']:
38-
aid = res['balance'][0]['account_id']
34+
aid = ""
35+
if res["balance"]:
36+
aid = res["balance"][0]["account_id"]
3937

4038
if aid:
4139
res = c.list_transactions(id=aid, min_row=1, max_row=10)
@@ -51,25 +49,25 @@
5149
print(res)
5250
time.sleep(0.5)
5351

54-
res = c.list_user_trades(pair='XBTZAR')
52+
res = c.list_user_trades(pair="XBTZAR")
5553
print(res)
5654
time.sleep(0.5)
5755

58-
res = c.get_fee_info(pair='XBTZAR')
56+
res = c.get_fee_info(pair="XBTZAR")
5957
print(res)
6058
time.sleep(0.5)
6159

62-
res = c.get_funding_address(asset='XBT')
60+
res = c.get_funding_address(asset="XBT")
6361
print(res)
6462
time.sleep(0.5)
6563

6664
res = c.list_withdrawals()
6765
print(res)
6866
time.sleep(0.5)
6967

70-
wid = ''
71-
if res['withdrawals']:
72-
wid = res['withdrawals'][0]['id']
68+
wid = ""
69+
if res["withdrawals"]:
70+
wid = res["withdrawals"][0]["id"]
7371

7472
if wid:
7573
res = c.get_withdrawal(id=wid)

luno_python/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
VERSION = '0.0.10'
1+
VERSION = "0.0.10"

luno_python/base_client.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import json
22
import platform
3+
34
import requests
45
import six
56

@@ -11,16 +12,15 @@
1112
from . import VERSION
1213
from .error import APIError
1314

14-
DEFAULT_BASE_URL = 'https://api.luno.com'
15+
DEFAULT_BASE_URL = "https://api.luno.com"
1516
DEFAULT_TIMEOUT = 10
1617
PYTHON_VERSION = platform.python_version()
1718
SYSTEM = platform.system()
1819
ARCH = platform.machine()
1920

2021

2122
class BaseClient:
22-
def __init__(self, base_url='', timeout=0,
23-
api_key_id='', api_key_secret=''):
23+
def __init__(self, base_url="", timeout=0, api_key_id="", api_key_secret=""):
2424
"""
2525
:type base_url: str
2626
:type timeout: float
@@ -47,9 +47,9 @@ def set_base_url(self, base_url):
4747
4848
:type base_url: str
4949
"""
50-
if base_url == '':
50+
if base_url == "":
5151
base_url = DEFAULT_BASE_URL
52-
self.base_url = base_url.rstrip('/')
52+
self.base_url = base_url.rstrip("/")
5353

5454
def set_timeout(self, timeout):
5555
"""Sets the timeout, in seconds, for requests made by the client.
@@ -74,33 +74,32 @@ def do(self, method, path, req=None, auth=False):
7474
params = json.loads(json.dumps(req))
7575
except Exception:
7676
params = None
77-
headers = {'User-Agent': self.make_user_agent()}
77+
headers = {"User-Agent": self.make_user_agent()}
7878
args = dict(timeout=self.timeout, params=params, headers=headers)
7979
if auth:
80-
args['auth'] = (self.api_key_id, self.api_key_secret)
80+
args["auth"] = (self.api_key_id, self.api_key_secret)
8181
url = self.make_url(path, params)
8282
res = self.session.request(method, url, **args)
8383
try:
8484
e = res.json()
85-
if 'error' in e and 'error_code' in e:
86-
raise APIError(e['error_code'], e['error'])
85+
if "error" in e and "error_code" in e:
86+
raise APIError(e["error_code"], e["error"])
8787
return e
8888
except JSONDecodeError:
89-
raise Exception('luno: unknown API error (%s)' % res.status_code)
89+
raise Exception("luno: unknown API error (%s)" % res.status_code)
9090

9191
def make_url(self, path, params):
9292
"""
9393
:type path: str
9494
:rtype: str
9595
"""
9696
if params:
97-
for k, v in six.iteritems(params):
98-
path = path.replace('{' + k + '}', str(v))
99-
return self.base_url + '/' + path.lstrip('/')
97+
for k, v in params.items():
98+
path = path.replace("{" + k + "}", str(v))
99+
return self.base_url + "/" + path.lstrip("/")
100100

101101
def make_user_agent(self):
102102
"""
103103
:rtype: str
104104
"""
105-
return "LunoPythonSDK/%s python/%s %s %s" % \
106-
(VERSION, PYTHON_VERSION, SYSTEM, ARCH)
105+
return f"LunoPythonSDK/{VERSION} python/{PYTHON_VERSION} {SYSTEM} {ARCH}"

0 commit comments

Comments
 (0)