Skip to content

Commit 6909f24

Browse files
authored
Added contributing instructions. (#7)
* Added contributing instructions.
1 parent d6326ba commit 6909f24

9 files changed

+253
-13
lines changed

Diff for: .gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -162,4 +162,6 @@ cython_debug/
162162
#.idea/
163163

164164
# project - specific
165-
config.yml
165+
tests/test_data/precompiled_registrations.json
166+
tests/test_data/registrations.db
167+
tests/test_data/aprstastic.yaml

Diff for: CONTRIBUTING.md

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# CONTRIBUTING
2+
3+
Code contributions are welcomed and appreciated. Just submit a PR!
4+
5+
The current build environment uses `pre-commit`, and `hatch`.
6+
7+
### Environment setup:
8+
9+
```console
10+
pip install hatch
11+
git clone [email protected]:afourney/aprstastic.git
12+
cd aprstastic
13+
pre-commit install
14+
15+
# Optionally run the pre-commit scripts at any time
16+
pre-commit run --all-files
17+
```
18+
19+
### Running and testing:
20+
21+
From the aprstastic directory:
22+
23+
```console
24+
hatch shell
25+
26+
# Running
27+
python -m aprstastic
28+
29+
30+
# Testing
31+
hatch test
32+
```

Diff for: README.md

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
> [!WARNING]
99
> Legal operation of this software requires an amateur radio license and a valid call sign.
1010
11+
> [!NOTE]
12+
> Code contributions are welcomed and appreciated. See [CONTRIBUTING.md](https://github.com/afourney/aprstastic/blob/main/CONTRIBUTING.md) for details.
13+
1114
## New!
1215

1316
:fire: 2-minute [YouTube demo](https://www.youtube.com/watch?v=qUvpZUwl-cY)

Diff for: src/aprstastic/__about__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-FileCopyrightText: 2024-present Adam Fourney <[email protected]>
22
#
33
# SPDX-License-Identifier: MIT
4-
__version__ = "0.0.1a12"
4+
__version__ = "0.0.1a14"

Diff for: src/aprstastic/_config.py

+6-10
Original file line numberDiff line numberDiff line change
@@ -61,29 +61,25 @@ def init_config():
6161

6262
# Try to get the data directory
6363
data_dir = config.get("data_dir")
64-
if data_dir is None:
64+
if data_dir is None or data_dir.strip() == "":
6565
data_dir = os.path.join(
6666
os.path.dirname(os.path.abspath(config_path)), DATA_SUBDIR
6767
)
68-
elif data_dir.strip() == "":
69-
data_dir = os.path.join(os.getcwd(), DATA_SUBDIR)
70-
else:
71-
data_dir = os.path.expanduser(data_dir)
68+
elif not os.path.isabs(data_dir):
69+
data_dir = os.path.join(os.path.dirname(os.path.abspath(config_path)), data_dir)
7270

7371
logger.debug(f"data directory: {data_dir}")
7472
os.makedirs(data_dir, exist_ok=True)
7573
config["data_dir"] = data_dir
7674

7775
# Try to get the logging directory
7876
logs_dir = config.get("logs_dir")
79-
if logs_dir is None:
77+
if logs_dir is None or logs_dir.strip() == "":
8078
logs_dir = os.path.join(
8179
os.path.dirname(os.path.abspath(config_path)), LOGS_SUBDIR
8280
)
83-
elif logs_dir.strip() == "":
84-
logs_dir = os.path.join(os.getcwd(), LOGS_SUBDIR)
85-
else:
86-
logs_dir = os.path.expanduser(logs_dir)
81+
elif not os.path.isabs(logs_dir):
82+
logs_dir = os.path.join(os.path.dirname(os.path.abspath(config_path)), logs_dir)
8783

8884
logger.debug(f"logs directory: {logs_dir}")
8985
os.makedirs(logs_dir, exist_ok=True)

Diff for: src/aprstastic/_config_const.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
2727
# Where should logs be stored?
2828
# If null, (or commented out), store logs in the `logs` dir, sibling to this file.
29-
#log_dir: null
29+
#logs_dir: null
3030
3131
3232
# Where should data be stored?

Diff for: tests/test_config.py

+152
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# SPDX-FileCopyrightText: 2024-present Adam Fourney <[email protected]>
2+
#
3+
# SPDX-License-Identifier: MIT
4+
import os
5+
import json
6+
import time
7+
import shutil
8+
9+
from aprstastic._config import (
10+
ConfigError,
11+
init_config,
12+
CONFIG_FILE_NAME,
13+
LOGS_SUBDIR,
14+
DATA_SUBDIR,
15+
DEFAULT_CALL_SIGN,
16+
)
17+
18+
19+
TEST_CONFIG_FILE_NAME_1 = "test_aprstastic_1.yaml"
20+
TEST_CONFIG_FILE_NAME_2 = "test_aprstastic_2.yaml"
21+
config_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_data")
22+
23+
# Monkey patch the default directory
24+
import aprstastic._config
25+
26+
aprstastic._config.DEFAULT_DATA_DIR = config_dir
27+
28+
logs_dir = os.path.join(config_dir, LOGS_SUBDIR)
29+
data_dir = os.path.join(config_dir, DATA_SUBDIR)
30+
31+
32+
def test_initialize_config():
33+
config_file = os.path.join(config_dir, CONFIG_FILE_NAME)
34+
35+
# Start fresh
36+
if os.path.isfile(config_file):
37+
os.unlink(config_file)
38+
39+
assert not os.path.isfile(config_file)
40+
41+
cwd = os.path.abspath(os.getcwd())
42+
error_msg = None
43+
try:
44+
os.chdir(config_dir)
45+
46+
# Initialize the config
47+
config = init_config()
48+
49+
except ConfigError as e:
50+
error_msg = str(e)
51+
finally:
52+
os.chdir(cwd)
53+
54+
# Make sure the sample config exists now
55+
assert os.path.isfile(config_file)
56+
# assert os.path.isdir(logs_dir)
57+
# assert os.path.isdir(data_dir)
58+
59+
# Make sure the correct error was thrown
60+
assert "A sample configuration was written" in error_msg
61+
62+
# Try loading it again, and check that the correct error was thrown the second time
63+
try:
64+
os.chdir(config_dir)
65+
config = init_config()
66+
except ConfigError as e:
67+
error_msg = str(e)
68+
finally:
69+
os.chdir(cwd)
70+
assert "appears to be the sample config" in error_msg
71+
72+
73+
def test_load_config():
74+
config_file = os.path.join(config_dir, CONFIG_FILE_NAME)
75+
test_config_file_1 = os.path.join(config_dir, TEST_CONFIG_FILE_NAME_1)
76+
test_config_file_2 = os.path.join(config_dir, TEST_CONFIG_FILE_NAME_2)
77+
78+
mylogs_dir = os.path.join(config_dir, "mylogs")
79+
mydata_dir = os.path.join(config_dir, "mydata")
80+
81+
# Install our test config #1
82+
shutil.copyfile(test_config_file_1, config_file)
83+
84+
# Load the config
85+
cwd = os.path.abspath(os.getcwd())
86+
error_msg = None
87+
try:
88+
os.chdir(config_dir)
89+
config = init_config()
90+
finally:
91+
os.chdir(cwd)
92+
93+
# Check that it looks right
94+
assert config == json.loads(
95+
"""
96+
{
97+
"gateway": {
98+
"call_sign": "N0CALL-1",
99+
"aprsis_passcode": 12345,
100+
"meshtastic_interface": {
101+
"type": "serial"
102+
},
103+
"beacon_registrations": true,
104+
"data_dir": "%s",
105+
"logs_dir": "%s"
106+
},
107+
"licensed_operators": {}
108+
}
109+
"""
110+
% (data_dir, logs_dir)
111+
)
112+
113+
# Install our test config #2
114+
shutil.copyfile(test_config_file_2, config_file)
115+
116+
# Load the config
117+
cwd = os.path.abspath(os.getcwd())
118+
error_msg = None
119+
try:
120+
os.chdir(config_dir)
121+
config = init_config()
122+
finally:
123+
os.chdir(cwd)
124+
125+
# Check that it looks right
126+
assert config == json.loads(
127+
"""
128+
{
129+
"gateway": {
130+
"call_sign": "N0CALL-2",
131+
"aprsis_passcode": 12345,
132+
"meshtastic_interface": {
133+
"type": "serial"
134+
},
135+
"beacon_registrations": false,
136+
"data_dir": "%s",
137+
"logs_dir": "%s"
138+
},
139+
"licensed_operators": {}
140+
}
141+
"""
142+
% (mydata_dir, mylogs_dir)
143+
)
144+
145+
146+
##########################
147+
if __name__ == "__main__":
148+
import logging
149+
150+
logging.basicConfig(level=logging.DEBUG)
151+
test_initialize_config()
152+
test_load_config()

Diff for: tests/test_data/test_aprstastic_1.yaml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#
2+
# APRSTASTIC CONFIGURATION FILE (version: 1)
3+
# Be sure to at least modify 'call_sign' and 'aprsis_passcode'.
4+
#
5+
6+
# Radio call sign of the gateway itself (analogy, iGate's call sign)
7+
call_sign: N0CALL-1
8+
9+
# APRS-IS passcode. Search Google for how to get this
10+
aprsis_passcode: 12345
11+
12+
# Only serial devices are supported right now.
13+
# If 'device' is null (or commented out), an attempt will be made to
14+
# detected it automatically.
15+
meshtastic_interface:
16+
type: serial
17+
# device: /dev/ttyACM0
18+
19+
# Beacon new registrations to APRS-IS to facilitate discovery
20+
beacon_registrations: true
21+
# Where should logs be stored?
22+
# If null, (or commented out), store logs in the `logs` dir, sibling to this file.
23+
#logs_dir: null
24+
25+
# Where should data be stored?
26+
# If null, (or commented out), store data in the `data` dir, sibling to this file.
27+
#data_dir: null

Diff for: tests/test_data/test_aprstastic_2.yaml

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#
2+
# APRSTASTIC CONFIGURATION FILE (version: 1)
3+
# Be sure to at least modify 'call_sign' and 'aprsis_passcode'.
4+
#
5+
6+
# Radio call sign of the gateway itself (analogy, iGate's call sign)
7+
call_sign: N0CALL-2
8+
9+
# APRS-IS passcode. Search Google for how to get this
10+
aprsis_passcode: 12345
11+
12+
# Only serial devices are supported right now.
13+
# If 'device' is null (or commented out), an attempt will be made to
14+
# detected it automatically.
15+
meshtastic_interface:
16+
type: serial
17+
# device: /dev/ttyACM0
18+
19+
# Beacon new registrations to APRS-IS to facilitate discovery
20+
beacon_registrations: false
21+
22+
# Where should logs be stored?
23+
# If null, (or commented out), store logs in the `logs` dir, sibling to this file.
24+
logs_dir: mylogs
25+
26+
# Where should data be stored?
27+
# If null, (or commented out), store data in the `data` dir, sibling to this file.
28+
data_dir: mydata

0 commit comments

Comments
 (0)