Skip to content

Commit 426846c

Browse files
authored
feat: Read config from XDG_CONFIG_HOME or custom path (#77)
* read config from XDG_CONFIG_HOME or custom path * v1.5.0 * test custom config path parsing * test default/custom XDG_CONFIG_HOME values
1 parent 4e5ee4e commit 426846c

File tree

5 files changed

+116
-61
lines changed

5 files changed

+116
-61
lines changed

README.md

Lines changed: 39 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,25 @@ A [Waybar](https://github.com/Alexays/Waybar) module for displaying cryptocurren
99

1010
## Requirements
1111

12-
- `python` >=3.8
12+
- `python` >=3.9
1313
- `python-requests`
1414

1515
## Installation
1616

17-
### Clone to the Waybar modules directory
17+
### AUR
18+
19+
```shell
20+
yay -S waybar-crypto
21+
```
22+
23+
**Note:** *For the time being, the `cryptofont` font still needs installing manually*
24+
25+
### (Or) Clone to the Waybar modules directory
1826

1927
```shell
2028
cd ~/.config/waybar/modules
2129
git clone https://github.com/chadsr/waybar-crypto.git crypto && cd crypto/
2230
git submodule update --init --recursive --remote --progress
23-
24-
# **only** If you for some reason don't want to install python-requests with a package manager, or setup a venv
25-
pip install --user --requirement <(poetry export --without=dev --format requirements.txt)
2631
```
2732

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

39-
### Update Waybar configuration
44+
### Create Configuration File
45+
46+
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.
47+
48+
An example can be found in [`config.ini.example`](./config.ini.example) with further options described below in the [Configuration](#configuration) section.
49+
50+
51+
### Update Waybar Configuration
4052

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

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

5769
```css
5870
#custom-crypto {
59-
font-family: cryptofont, monospace;
71+
font-family: cryptofont;
6072
}
6173
```
6274

6375
## Configuration
6476

65-
Copy the example configuration file `config.ini.example` to `config.ini`.
66-
67-
The information displayed can then be customised by editing the `config.ini` configuration file.
68-
(e.g. `~/.config/waybar/modules/crypto/config.ini` if you followed the instructions above)
69-
70-
```ini
71-
[general]
72-
currency = eur
73-
currency_symbol = €
74-
spacer_symbol = |
75-
display = price,percent_change_24h,percent_change_7d
76-
api_key = your_coinmarketcap_api_key
77-
78-
[btc]
79-
icon = 
80-
in_tooltip = false
81-
price_precision = 2
82-
change_precision = 2
83-
volume_precision = 2
84-
85-
[eth]
86-
icon = 
87-
in_tooltip = true
88-
price_precision = 2
89-
change_precision = 2
90-
volume_precision = 2
91-
```
92-
93-
- **currency:** Any valid currency code should be accepted
77+
- **currency:** A valid currency code
9478
- **currency_symbol:** A corresponding symbol of the currency you wish to display
95-
- **spacer_symbol:** A string/character to use as a spacer between tickers. Comment out to disable.
96-
- **api_key:** CoinmarketCap API key obtained from their [API Dashboard](https://coinmarketcap.com/api).
79+
- **spacer_symbol:** A string/character to use as a spacer between tickers. Comment out to disable
9780
- **display:** A list of metrics you wish to display for each crypto currency. No spaces.
9881
Valid options are:
99-
- **price:** Displays the current price.
100-
- **percent_change_1h:** Price change over the past hour.
101-
- **percent_change_24h:** Price change over the past 24 hours.
102-
- **percent_change_7d:** Price change over the past week.
103-
- **percent_change_30d:** Price change over the past thirty days.
104-
- **percent_change_60d:** Price change over the past sixty days.
105-
- **percent_change_90d:** Price change over the past ninety days.
106-
- **volume_24h:** Market volume in your chosen currency, over the past 24 hours.
107-
- **volume_change_24h:** Market volume change in your chosen currency, over the past 24 hours.
108-
109-
*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.*
82+
- **price:** current price
83+
- **percent_change_1h:** Price change over the past hour
84+
- **percent_change_24h:** Price change over the past 24 hours
85+
- **percent_change_7d:** Price change over the past week
86+
- **percent_change_30d:** Price change over the past thirty days
87+
- **percent_change_60d:** Price change over the past sixty days
88+
- **percent_change_90d:** Price change over the past ninety days
89+
- **volume_24h:** Market volume in your chosen currency, over the past 24 hours
90+
- **volume_change_24h:** Market volume change in your chosen currency, over the past 24 hours
91+
- **api_key:** CoinmarketCap API key obtained from their [API Dashboard](https://coinmarketcap.com/api)
92+
93+
*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.*
11094

11195
### Adding Cryptocurrencies
11296

11397
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/).
11498

11599
Valid options:
116100

117-
- **icon:** A character symbol to display next to this cryptocurrency's metrics.
118-
- **in_tooltip:** Whether to display the data in the tooltip instead of the bar (defaults to false).
119-
- **price_precision** The decimal precision at which to display the price value of the cryptocurrency.
120-
- **change_precision** The decimal precision at which to display the change value(s) of the cryptocurrency.
121-
- **volume_precision** The decimal precision at which to display the volume value of the cryptocurrency.
101+
- **icon:** A character symbol to display next to this cryptocurrency's metrics
102+
- **in_tooltip:** Whether to display the data in the tooltip instead of the bar (defaults to false)
103+
- **price_precision** The decimal precision at which to display the price value of the cryptocurrency
104+
- **change_precision** The decimal precision at which to display the change value(s) of the cryptocurrency
105+
- **volume_precision** The decimal precision at which to display the volume value of the cryptocurrency

config.ini.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ currency_symbol = €
44
display = price,percent_change_24h
55
spacer_symbol = |
66
api_key = your_coinmarketcap_api_key
7+
; COINMARKETCAP_API_KEY env variable can alternatively be used and will take precedence
78

89
[btc]
910
icon = 

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "waybar-crypto"
3-
version = "v1.4.0"
3+
version = "v1.5.0"
44
description = "A Waybar module for displaying cryptocurrency market information from CoinMarketCap."
55
authors = ["Ross <git@ross.ch>"]
66
license = "MIT"

tests/test_waybar_crypto.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
import os
2+
import argparse
23
import pytest
4+
from unittest import mock
35

4-
from waybar_crypto import CLASS_NAME, ResponseQuotesLatest, WaybarCrypto
6+
from waybar_crypto import (
7+
CLASS_NAME,
8+
DEFAULT_XDG_CONFIG_HOME_PATH,
9+
XDG_CONFIG_HOME_ENV,
10+
ResponseQuotesLatest,
11+
WaybarCrypto,
12+
parse_args,
13+
)
514

615

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

1121

1222
@pytest.fixture()
@@ -87,6 +97,34 @@ def quotes_latest():
8797
}
8898

8999

100+
def test_parse_args_default_path():
101+
with mock.patch("sys.argv", ["waybar_crypto.py"]):
102+
os.environ[XDG_CONFIG_HOME_ENV] = ""
103+
args = parse_args()
104+
assert "config_path" in args
105+
assert os.path.expanduser(DEFAULT_XDG_CONFIG_HOME_PATH) in os.path.expanduser(
106+
args["config_path"]
107+
)
108+
109+
110+
def test_parse_args_custom_xdg_data_home():
111+
with mock.patch("sys.argv", ["waybar_crypto.py"]):
112+
os.environ[XDG_CONFIG_HOME_ENV] = TEST_CONFIG_PATH
113+
args = parse_args()
114+
assert "config_path" in args
115+
assert TEST_CONFIG_PATH in args["config_path"]
116+
117+
118+
@mock.patch(
119+
"argparse.ArgumentParser.parse_args",
120+
return_value=argparse.Namespace(config_path=TEST_CONFIG_PATH),
121+
)
122+
def test_parse_args_custom_path(mock: mock.MagicMock):
123+
args = parse_args()
124+
assert "config_path" in args
125+
assert args["config_path"] == TEST_CONFIG_PATH
126+
127+
90128
class TestWaybarCrypto:
91129
"""Tests for the WaybarCrypto."""
92130

waybar_crypto.py

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,14 @@
66
import requests
77
import json
88
import configparser
9+
import argparse
910

1011
API_URL = "https://pro-api.coinmarketcap.com/v1/cryptocurrency/quotes/latest"
1112
API_KEY_ENV = "COINMARKETCAP_API_KEY"
13+
14+
XDG_CONFIG_HOME_ENV = "XDG_CONFIG_HOME"
15+
DEFAULT_XDG_CONFIG_HOME_PATH = "~/.config"
16+
CONFIG_DIR = "waybar-crypto"
1217
CONFIG_FILE = "config.ini"
1318

1419
DEFAULT_PRECISION = 2
@@ -43,6 +48,10 @@
4348
TIMEOUT_SECONDS = 10
4449

4550

51+
class Args(TypedDict):
52+
config_path: str
53+
54+
4655
class ConfigGeneral(TypedDict):
4756
currency: str
4857
currency_symbol: str
@@ -313,12 +322,35 @@ def waybar_output(self, quotes_latest: ResponseQuotesLatest) -> WaybarOutput:
313322
return output_obj
314323

315324

325+
def parse_args() -> Args:
326+
parser = argparse.ArgumentParser()
327+
328+
# Utilise XDG_CONFIG_HOME if it exists
329+
xdg_config_home_path = os.getenv(XDG_CONFIG_HOME_ENV)
330+
if not xdg_config_home_path:
331+
xdg_config_home_path = DEFAULT_XDG_CONFIG_HOME_PATH
332+
333+
default_config_path = os.path.join(xdg_config_home_path, CONFIG_DIR, CONFIG_FILE)
334+
parser.add_argument(
335+
"-c",
336+
"--config-path",
337+
type=str,
338+
default=default_config_path,
339+
help=f"Path to the configuration file (default: '{default_config_path}')",
340+
)
341+
args = parser.parse_args()
342+
343+
return {"config_path": args.config_path}
344+
345+
316346
def main():
317-
# Get the absolute path of this script
318-
abs_dir = os.path.dirname(os.path.abspath(__file__))
319-
config_path = f"{abs_dir}/{CONFIG_FILE}"
347+
args = parse_args()
348+
349+
config_path = args["config_path"]
350+
if not os.path.isfile(config_path):
351+
raise WaybarCryptoException(f"configuration file not found at '{config_path}'")
320352

321-
waybar_crypto = WaybarCrypto(config_path)
353+
waybar_crypto = WaybarCrypto(args["config_path"])
322354
quotes_latest = waybar_crypto.coinmarketcap_latest()
323355
output = waybar_crypto.waybar_output(quotes_latest)
324356

0 commit comments

Comments
 (0)