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

feat: Read config from XDG_CONFIG_HOME or custom path #77

Merged
merged 4 commits into from
May 26, 2024
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
94 changes: 39 additions & 55 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,25 @@ A [Waybar](https://github.com/Alexays/Waybar) module for displaying cryptocurren

## Requirements

- `python` >=3.8
- `python` >=3.9
- `python-requests`

## Installation

### Clone to the Waybar modules directory
### AUR

```shell
yay -S waybar-crypto
```

**Note:** *For the time being, the `cryptofont` font still needs installing manually*

### (Or) Clone to the Waybar modules directory

```shell
cd ~/.config/waybar/modules
git clone https://github.com/chadsr/waybar-crypto.git crypto && cd crypto/
git submodule update --init --recursive --remote --progress

# **only** If you for some reason don't want to install python-requests with a package manager, or setup a venv
pip install --user --requirement <(poetry export --without=dev --format requirements.txt)
```

### Install the needed fonts
Expand All @@ -36,7 +41,14 @@ ln -s ./.submodules/cryptofont/fonts/cryptofont.ttf ~/.local/share/fonts/TTF
fc-cache -f
```

### Update Waybar configuration
### Create Configuration File

Create a configuration file at `$XDG_CONFIG_HOME/waybar-crypto/config.ini` (This location can be customised with the `--config-path` flag). The module **will not** run without first creating this configuration file.

An example can be found in [`config.ini.example`](./config.ini.example) with further options described below in the [Configuration](#configuration) section.


### Update Waybar Configuration

*Found at `~/.config/waybar/config` by default*

Expand All @@ -45,7 +57,7 @@ fc-cache -f
"format": "{}",
"interval": 600,
"return-type": "json",
"exec": "~/.config/waybar/modules/crypto/waybar_crypto.py",
"exec": "waybar-crypto", // change this if you installed manually
"exec-if": "ping pro-api.coinmarketcap.com -c1"
}
```
Expand All @@ -56,66 +68,38 @@ fc-cache -f

```css
#custom-crypto {
font-family: cryptofont, monospace;
font-family: cryptofont;
}
```

## Configuration

Copy the example configuration file `config.ini.example` to `config.ini`.

The information displayed can then be customised by editing the `config.ini` configuration file.
(e.g. `~/.config/waybar/modules/crypto/config.ini` if you followed the instructions above)

```ini
[general]
currency = eur
currency_symbol = €
spacer_symbol = |
display = price,percent_change_24h,percent_change_7d
api_key = your_coinmarketcap_api_key

[btc]
icon = 
in_tooltip = false
price_precision = 2
change_precision = 2
volume_precision = 2

[eth]
icon = 
in_tooltip = true
price_precision = 2
change_precision = 2
volume_precision = 2
```

- **currency:** Any valid currency code should be accepted
- **currency:** A valid currency code
- **currency_symbol:** A corresponding symbol of the currency you wish to display
- **spacer_symbol:** A string/character to use as a spacer between tickers. Comment out to disable.
- **api_key:** CoinmarketCap API key obtained from their [API Dashboard](https://coinmarketcap.com/api).
- **spacer_symbol:** A string/character to use as a spacer between tickers. Comment out to disable
- **display:** A list of metrics you wish to display for each crypto currency. No spaces.
Valid options are:
- **price:** Displays the current price.
- **percent_change_1h:** Price change over the past hour.
- **percent_change_24h:** Price change over the past 24 hours.
- **percent_change_7d:** Price change over the past week.
- **percent_change_30d:** Price change over the past thirty days.
- **percent_change_60d:** Price change over the past sixty days.
- **percent_change_90d:** Price change over the past ninety days.
- **volume_24h:** Market volume in your chosen currency, over the past 24 hours.
- **volume_change_24h:** Market volume change in your chosen currency, over the past 24 hours.

*Alternatively, the CoinMarketCap API key can be set through the environment variable `COINMARKETCAP_API_KEY`, if you do not wish to save it to the `config.ini` configuration file.*
- **price:** current price
- **percent_change_1h:** Price change over the past hour
- **percent_change_24h:** Price change over the past 24 hours
- **percent_change_7d:** Price change over the past week
- **percent_change_30d:** Price change over the past thirty days
- **percent_change_60d:** Price change over the past sixty days
- **percent_change_90d:** Price change over the past ninety days
- **volume_24h:** Market volume in your chosen currency, over the past 24 hours
- **volume_change_24h:** Market volume change in your chosen currency, over the past 24 hours
- **api_key:** CoinmarketCap API key obtained from their [API Dashboard](https://coinmarketcap.com/api)

*Alternatively, the CoinMarketCap API key can be set through the environment variable `COINMARKETCAP_API_KEY`, if you do not wish to save it to the `config.ini` configuration file.*

### Adding Cryptocurrencies

For each cryptocurrency you wish to display, add a section as shown in the example above, where the section name is the **short** cryptocurrency name as found on [CoinMarketCap](https://coinmarketcap.com/).

Valid options:

- **icon:** A character symbol to display next to this cryptocurrency's metrics.
- **in_tooltip:** Whether to display the data in the tooltip instead of the bar (defaults to false).
- **price_precision** The decimal precision at which to display the price value of the cryptocurrency.
- **change_precision** The decimal precision at which to display the change value(s) of the cryptocurrency.
- **volume_precision** The decimal precision at which to display the volume value of the cryptocurrency.
- **icon:** A character symbol to display next to this cryptocurrency's metrics
- **in_tooltip:** Whether to display the data in the tooltip instead of the bar (defaults to false)
- **price_precision** The decimal precision at which to display the price value of the cryptocurrency
- **change_precision** The decimal precision at which to display the change value(s) of the cryptocurrency
- **volume_precision** The decimal precision at which to display the volume value of the cryptocurrency
1 change: 1 addition & 0 deletions config.ini.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ currency_symbol = €
display = price,percent_change_24h
spacer_symbol = |
api_key = your_coinmarketcap_api_key
; COINMARKETCAP_API_KEY env variable can alternatively be used and will take precedence

[btc]
icon = 
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "waybar-crypto"
version = "v1.4.0"
version = "v1.5.0"
description = "A Waybar module for displaying cryptocurrency market information from CoinMarketCap."
authors = ["Ross <[email protected]>"]
license = "MIT"
Expand Down
40 changes: 39 additions & 1 deletion tests/test_waybar_crypto.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import os
import argparse
import pytest
from unittest import mock

from waybar_crypto import CLASS_NAME, ResponseQuotesLatest, WaybarCrypto
from waybar_crypto import (
CLASS_NAME,
DEFAULT_XDG_CONFIG_HOME_PATH,
XDG_CONFIG_HOME_ENV,
ResponseQuotesLatest,
WaybarCrypto,
parse_args,
)


# Get the absolute path of this script
ABS_DIR = os.path.dirname(os.path.abspath(__file__))
CONFIG_PATH = f"{ABS_DIR}/../config.ini.example"
TEST_CONFIG_PATH = "/test_path"


@pytest.fixture()
Expand Down Expand Up @@ -87,6 +97,34 @@ def quotes_latest():
}


def test_parse_args_default_path():
with mock.patch("sys.argv", ["waybar_crypto.py"]):
os.environ[XDG_CONFIG_HOME_ENV] = ""
args = parse_args()
assert "config_path" in args
assert os.path.expanduser(DEFAULT_XDG_CONFIG_HOME_PATH) in os.path.expanduser(
args["config_path"]
)


def test_parse_args_custom_xdg_data_home():
with mock.patch("sys.argv", ["waybar_crypto.py"]):
os.environ[XDG_CONFIG_HOME_ENV] = TEST_CONFIG_PATH
args = parse_args()
assert "config_path" in args
assert TEST_CONFIG_PATH in args["config_path"]


@mock.patch(
"argparse.ArgumentParser.parse_args",
return_value=argparse.Namespace(config_path=TEST_CONFIG_PATH),
)
def test_parse_args_custom_path(mock: mock.MagicMock):
args = parse_args()
assert "config_path" in args
assert args["config_path"] == TEST_CONFIG_PATH


class TestWaybarCrypto:
"""Tests for the WaybarCrypto."""

Expand Down
40 changes: 36 additions & 4 deletions waybar_crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@
import requests
import json
import configparser
import argparse

API_URL = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest"
API_KEY_ENV = "COINMARKETCAP_API_KEY"

XDG_CONFIG_HOME_ENV = "XDG_CONFIG_HOME"
DEFAULT_XDG_CONFIG_HOME_PATH = "~/.config"
CONFIG_DIR = "waybar-crypto"
CONFIG_FILE = "config.ini"

DEFAULT_PRECISION = 2
Expand Down Expand Up @@ -43,6 +48,10 @@
TIMEOUT_SECONDS = 10


class Args(TypedDict):
config_path: str


class ConfigGeneral(TypedDict):
currency: str
currency_symbol: str
Expand Down Expand Up @@ -313,12 +322,35 @@
return output_obj


def parse_args() -> Args:
parser = argparse.ArgumentParser()

# Utilise XDG_CONFIG_HOME if it exists
xdg_config_home_path = os.getenv(XDG_CONFIG_HOME_ENV)
if not xdg_config_home_path:
xdg_config_home_path = DEFAULT_XDG_CONFIG_HOME_PATH

default_config_path = os.path.join(xdg_config_home_path, CONFIG_DIR, CONFIG_FILE)
parser.add_argument(
"-c",
"--config-path",
type=str,
default=default_config_path,
help=f"Path to the configuration file (default: '{default_config_path}')",
)
args = parser.parse_args()

return {"config_path": args.config_path}


def main():
# Get the absolute path of this script
abs_dir = os.path.dirname(os.path.abspath(__file__))
config_path = f"{abs_dir}/{CONFIG_FILE}"
args = parse_args()

Check warning on line 347 in waybar_crypto.py

View check run for this annotation

Codecov / codecov/patch

waybar_crypto.py#L347

Added line #L347 was not covered by tests

config_path = args["config_path"]
if not os.path.isfile(config_path):
raise WaybarCryptoException(f"configuration file not found at '{config_path}'")

Check warning on line 351 in waybar_crypto.py

View check run for this annotation

Codecov / codecov/patch

waybar_crypto.py#L349-L351

Added lines #L349 - L351 were not covered by tests

waybar_crypto = WaybarCrypto(config_path)
waybar_crypto = WaybarCrypto(args["config_path"])

Check warning on line 353 in waybar_crypto.py

View check run for this annotation

Codecov / codecov/patch

waybar_crypto.py#L353

Added line #L353 was not covered by tests
quotes_latest = waybar_crypto.coinmarketcap_latest()
output = waybar_crypto.waybar_output(quotes_latest)

Expand Down