Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge branch Davi0kProgramsThings:fix/refactoring into branch bitfinexcom:master. #235

Merged
merged 14 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
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
13 changes: 13 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[flake8]
max-line-length = 80
extend-select = B950
extend-ignore = E203,E501,E701

exclude =
__pycache__
build
dist
venv

per-file-ignores =
*/__init__.py:F401
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ A possible solution could be...
## Steps to reproduce (for bugs)
<!-- You can delete this section if you are not submitting a bug report -->

1. &nbsp;
2. &nbsp;
3. &nbsp;
1.
2.
3.

### Python version
<!-- Indicate your python version here -->
Expand Down
15 changes: 8 additions & 7 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ PR fixes the following issue:

# Checklist:

- [ ] My code follows the style guidelines of this project;
- [ ] I have performed a self-review of my code;
- [ ] I have commented my code, particularly in hard-to-understand areas;
- [ ] I have made corresponding changes to the documentation;
- [ ] My changes generate no new warnings;
- [ ] Mypy returns no errors or warnings when run on the root package;
- [ ] Pylint returns a score of 10.00/10.00 when run on the root package;
- [ ] I've done a self-review of my code;
- [ ] I've made corresponding changes to the documentation;
- [ ] I've made sure my changes generate no warnings;
- [ ] mypy returns no errors when run on the root package;
<!-- If you use pre-commit hooks you can always check off the following tasks -->
- [ ] I've run black to format my code;
- [ ] I've run isort to format my code's import statements;
- [ ] flake8 reports no errors when run on the entire code base;
9 changes: 3 additions & 6 deletions .github/workflows/bitfinex-api-py-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ on:
branches:
- master

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
Expand All @@ -23,7 +20,7 @@ jobs:
python-version: '3.8'
- name: Install bitfinex-api-py's dependencies
run: python -m pip install -r dev-requirements.txt
- name: Lint the project with pylint (and fail if score is lower than 10.00/10.00)
run: python -m pylint bfxapi
- name: Run mypy to check the correctness of type hinting (and fail if any error or warning is found)
- name: Run pre-commit hooks (see .pre-commit-config.yaml)
uses: pre-commit/[email protected]
- name: Run mypy to ensure correct type hinting
run: python -m mypy bfxapi
18 changes: 11 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
.venv
.DS_Store
.vscode
*.pyc
*.log
.python-version
__pycache__

bitfinex_api_py.egg-info
bitfinex_api_py.dist-info
build/
dist/
pip-wheel-metadata/
.eggs

__pycache__
.idea

dist
venv
!.gitkeep
MANIFEST
venv/
2 changes: 2 additions & 0 deletions .isort.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[settings]
profile = black
17 changes: 17 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
repos:
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 24.2.0
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 7.0.0
hooks:
- id: flake8

additional_dependencies: [
flake8-bugbear
]
25 changes: 0 additions & 25 deletions .pylintrc

This file was deleted.

43 changes: 35 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,9 @@ Contributors must uphold the [Contributor Covenant code of conduct](https://gith
1. [Installation and setup](#installation-and-setup)
* [Cloning the repository](#cloning-the-repository)
* [Installing the dependencies](#installing-the-dependencies)
* [Set up the pre-commit hooks (optional)](#set-up-the-pre-commit-hooks-optional)
2. [Before opening a PR](#before-opening-a-pr)
* [Tip](#tip)
3. [License](#license)

## Installation and setup
Expand All @@ -333,23 +335,48 @@ git clone --branch v3-beta --single-branch https://github.com/bitfinexcom/bitfin
python3 -m pip install -r dev-requirements.txt
```

Make sure to install `dev-requirements.txt` instead of `requirements.txt`. \
`dev-requirements.txt` will install all dependencies in `requirements.txt` plus any development dependencies. \
This will also install the versions in use of [`pylint`](https://github.com/pylint-dev/pylint) and [`mypy`](https://github.com/python/mypy), which you should both use before opening your PRs.
Make sure to install `dev-requirements.txt` (and not `requirements.txt`!). \
`dev-requirements.txt` will install all dependencies in `requirements.txt` plus any development dependency. \
dev-requirements includes [mypy](https://github.com/python/mypy), [black](https://github.com/psf/black), [isort](https://github.com/PyCQA/isort), [flake8](https://github.com/PyCQA/flake8), and [pre-commit](https://github.com/pre-commit/pre-commit) (more on these tools in later chapters).

All done, your Python 3.8+ environment should now be able to run `bitfinex-api-py`'s source code.

### Set up the pre-commit hooks (optional)

**Do not skip this paragraph if you intend to contribute to the project.**

This repository includes a pre-commit configuration file that defines the following hooks:
1. [isort](https://github.com/PyCQA/isort)
2. [black](https://github.com/psf/black)
3. [flake8](https://github.com/PyCQA/flake8)

To set up pre-commit use:
```console
python3 -m pre-commit install
```

These will ensure that isort, black and flake8 are run on each git commit.

[Visit this page to learn more about git hooks and pre-commit.](https://pre-commit.com/#introduction)

#### Manually triggering the pre-commit hooks

You can also manually trigger the execution of all hooks with:
```console
python3 -m pre-commit run --all-files
```

## Before opening a PR

**We won't accept your PR or we will request changes if the following requirements aren't met.**
**We won't accept your PR or we'll request changes if the following requirements aren't met.**

Wheter you're submitting a bug fix, a new feature or a documentation change, you should first discuss it in an issue.

All PRs must follow this [PULL_REQUEST_TEMPLATE](https://github.com/bitfinexcom/bitfinex-api-py/blob/v3-beta/.github/PULL_REQUEST_TEMPLATE.md) and include an exhaustive description.
You must be able to check off all tasks listed in [PULL_REQUEST_TEMPLATE](https://raw.githubusercontent.com/bitfinexcom/bitfinex-api-py/master/.github/PULL_REQUEST_TEMPLATE.md) before opening a pull request.

### Tip

Before opening a pull request, you should also make sure that:
- [ ] [`pylint`](https://github.com/pylint-dev/pylint) returns a score of 10.00/10.00 when run against your code.
- [ ] [`mypy`](https://github.com/python/mypy) doesn't throw any error code when run on the project (excluding notes).
Setting up the project's pre-commit hooks will help automate this process ([more](#set-up-the-pre-commit-hooks-optional)).

## License

Expand Down
7 changes: 1 addition & 6 deletions bfxapi/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
from ._client import \
Client, \
REST_HOST, \
WSS_HOST, \
PUB_REST_HOST, \
PUB_WSS_HOST
from ._client import PUB_REST_HOST, PUB_WSS_HOST, REST_HOST, WSS_HOST, Client
50 changes: 27 additions & 23 deletions bfxapi/_client.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,48 @@
from typing import \
TYPE_CHECKING, List, Optional
from typing import TYPE_CHECKING, List, Optional

from bfxapi._utils.logging import ColorLogger

from bfxapi.exceptions import IncompleteCredentialError
from bfxapi.rest import BfxRestInterface
from bfxapi.websocket import BfxWebSocketClient
from bfxapi.exceptions import IncompleteCredentialError

if TYPE_CHECKING:
from bfxapi.websocket._client.bfx_websocket_client import \
_Credentials
from bfxapi.websocket._client.bfx_websocket_client import _Credentials

REST_HOST = "https://api.bitfinex.com/v2"
WSS_HOST = "wss://api.bitfinex.com/ws/2"

PUB_REST_HOST = "https://api-pub.bitfinex.com/v2"
PUB_WSS_HOST = "wss://api-pub.bitfinex.com/ws/2"


class Client:
def __init__(
self,
api_key: Optional[str] = None,
api_secret: Optional[str] = None,
*,
rest_host: str = REST_HOST,
wss_host: str = WSS_HOST,
filters: Optional[List[str]] = None,
timeout: Optional[int] = 60 * 15,
log_filename: Optional[str] = None
self,
api_key: Optional[str] = None,
api_secret: Optional[str] = None,
*,
rest_host: str = REST_HOST,
wss_host: str = WSS_HOST,
filters: Optional[List[str]] = None,
timeout: Optional[int] = 60 * 15,
log_filename: Optional[str] = None,
) -> None:
credentials: Optional["_Credentials"] = None

if api_key and api_secret:
credentials = \
{ "api_key": api_key, "api_secret": api_secret, "filters": filters }
credentials = {
"api_key": api_key,
"api_secret": api_secret,
"filters": filters,
}
elif api_key:
raise IncompleteCredentialError( \
"You must provide both an API-KEY and an API-SECRET (missing API-KEY).")
raise IncompleteCredentialError(
"You must provide both API-KEY and API-SECRET (missing API-KEY)."
)
elif api_secret:
raise IncompleteCredentialError( \
"You must provide both an API-KEY and an API-SECRET (missing API-SECRET).")
raise IncompleteCredentialError(
"You must provide both API-KEY and API-SECRET (missing API-SECRET)."
)

self.rest = BfxRestInterface(rest_host, api_key, api_secret)

Expand All @@ -48,5 +51,6 @@ def __init__(
if log_filename:
logger.register(filename=log_filename)

self.wss = BfxWebSocketClient(wss_host, \
credentials=credentials, timeout=timeout, logger=logger)
self.wss = BfxWebSocketClient(
wss_host, credentials=credentials, timeout=timeout, logger=logger
)
11 changes: 7 additions & 4 deletions bfxapi/_utils/json_decoder.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
from typing import Dict, Any
import json
import re
from typing import Any, Dict

import re, json

def _to_snake_case(string: str) -> str:
return re.sub(r"(?<!^)(?=[A-Z])", "_", string).lower()


def _object_hook(data: Dict[str, Any]) -> Any:
return { _to_snake_case(key): value for key, value in data.items() }
return {_to_snake_case(key): value for key, value in data.items()}


class JSONDecoder(json.JSONDecoder):
def __init__(self, *args: Any, **kwargs: Any) -> None:
super().__init__(object_hook=_object_hook, *args, **kwargs)
super().__init__(*args, **kwargs, object_hook=_object_hook)
24 changes: 11 additions & 13 deletions bfxapi/_utils/json_encoder.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
from typing import \
Union, List, Dict, \
Any

import json

from decimal import Decimal
from typing import Any, Dict, List, Union

_ExtJSON = Union[
Dict[str, "_ExtJSON"], List["_ExtJSON"], bool, int, float, str, Decimal, None
]

_ExtJSON = Union[Dict[str, "_ExtJSON"], List["_ExtJSON"], \
bool, int, float, str, Decimal, None]
_StrictJSON = Union[Dict[str, "_StrictJSON"], List["_StrictJSON"], int, str, None]

_StrictJSON = Union[Dict[str, "_StrictJSON"], List["_StrictJSON"], \
int, str, None]

def _clear(dictionary: Dict[str, Any]) -> Dict[str, Any]:
return { key: value for key, value in dictionary.items() \
if value is not None }
return {key: value for key, value in dictionary.items() if value is not None}


def _adapter(data: _ExtJSON) -> _StrictJSON:
if isinstance(data, bool):
Expand All @@ -25,12 +22,13 @@ def _adapter(data: _ExtJSON) -> _StrictJSON:
return format(data, "f")

if isinstance(data, list):
return [ _adapter(sub_data) for sub_data in data ]
return [_adapter(sub_data) for sub_data in data]
if isinstance(data, dict):
return _clear({ key: _adapter(value) for key, value in data.items() })
return _clear({key: _adapter(value) for key, value in data.items()})

return data


class JSONEncoder(json.JSONEncoder):
def encode(self, o: _ExtJSON) -> str:
return super().encode(_adapter(o))
Loading
Loading