strideutils 0.7.7__tar.gz → 0.7.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {strideutils-0.7.7 → strideutils-0.7.9}/.bumpversion.cfg +1 -1
- {strideutils-0.7.7 → strideutils-0.7.9}/.github/workflows/publish.yml +4 -2
- {strideutils-0.7.7 → strideutils-0.7.9}/.github/workflows/test.yml +3 -1
- strideutils-0.7.9/MANIFEST.in +1 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/Makefile +0 -3
- {strideutils-0.7.7 → strideutils-0.7.9}/PKG-INFO +1 -1
- {strideutils-0.7.7 → strideutils-0.7.9}/pyproject.toml +1 -1
- strideutils-0.7.9/strideutils/exec_tx.py +62 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/redis_connector.py +7 -14
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/stride_config.py +0 -12
- strideutils-0.7.9/strideutils/strideutils/__init__.pyi +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils.egg-info/PKG-INFO +1 -1
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils.egg-info/SOURCES.txt +2 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/tests/test_sheets_connector.py +1 -1
- strideutils-0.7.9/tests/test_twilio_connector.py +92 -0
- strideutils-0.7.7/strideutils/exec_tx.py +0 -62
- strideutils-0.7.7/tests/test_twilio_connector.py +0 -80
- {strideutils-0.7.7 → strideutils-0.7.9}/.github/workflows/lint.yml +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/.github/workflows/version.yaml +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/.gitignore +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/LICENSE +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/README.md +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/setup.cfg +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/Makefile +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/__init__.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/coingecko.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/config_examples/env.local.example +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/config_examples/strideutils_config.yaml.example +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/cryptography.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/invariant_helpers.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/run_safely.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/sheets_connector.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/slack_connector.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/stride_alerts.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/stride_requests.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/twilio_connector.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils/types.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils.egg-info/dependency_links.txt +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils.egg-info/requires.txt +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/strideutils.egg-info/top_level.txt +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/tests/test_config.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/tests/test_encryption.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/tests/test_redis_connector.py +0 -0
- {strideutils-0.7.7 → strideutils-0.7.9}/tests/test_slack_connector.py +0 -0
|
@@ -23,7 +23,7 @@ jobs:
|
|
|
23
23
|
- name: setup
|
|
24
24
|
run: |
|
|
25
25
|
python -m pip install -U pip
|
|
26
|
-
pip install --upgrade build setuptools twine wheel bump2version toml-cli
|
|
26
|
+
pip install --upgrade build setuptools twine wheel bump2version toml-cli mypy
|
|
27
27
|
git config user.name "GitHub Actions"
|
|
28
28
|
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
29
29
|
|
|
@@ -55,5 +55,7 @@ jobs:
|
|
|
55
55
|
TWINE_USERNAME: "__token__"
|
|
56
56
|
TWINE_PASSWORD: "${{ secrets.PYPI_TOKEN }}"
|
|
57
57
|
run: |
|
|
58
|
+
stubgen -m strideutils -o ./strideutils
|
|
59
|
+
echo "include strideutils/*.pyi" >> MANIFEST.in
|
|
58
60
|
python -m build
|
|
59
|
-
twine upload dist/*
|
|
61
|
+
twine upload dist/*
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include strideutils/*.pyi
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import re
|
|
3
|
+
import subprocess
|
|
4
|
+
import time
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from strideutils import stride_requests
|
|
9
|
+
from strideutils.stride_config import config
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class TxResponse:
|
|
14
|
+
stdout: dict
|
|
15
|
+
stderr: str
|
|
16
|
+
tx_hash: str = ""
|
|
17
|
+
success: bool = False
|
|
18
|
+
code: Optional[int] = None
|
|
19
|
+
tx_response: Optional[dict] = None
|
|
20
|
+
raw_log: Optional[str] = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def execute_tx(command: str, api_endpoint: str = config.stride.api_endpoint) -> TxResponse:
|
|
24
|
+
"""
|
|
25
|
+
Execute a tx and query the tx hash
|
|
26
|
+
"""
|
|
27
|
+
# Tack on the auto-confirm if it's not already in the command and capture the output as JSON
|
|
28
|
+
if "-y" not in command:
|
|
29
|
+
command += " -y"
|
|
30
|
+
command += " --output json"
|
|
31
|
+
|
|
32
|
+
# Run the command in the shell and store the response
|
|
33
|
+
output = subprocess.run(command, shell=True, capture_output=True, text=True)
|
|
34
|
+
|
|
35
|
+
# If there was stderr, return the response as failed
|
|
36
|
+
if not output.stdout or output.stderr:
|
|
37
|
+
return TxResponse(stdout={}, stderr=output.stderr, raw_log=output.stderr)
|
|
38
|
+
|
|
39
|
+
# Cast the stdout and build the response
|
|
40
|
+
response = TxResponse(stdout=json.loads(output.stdout), stderr=output.stderr)
|
|
41
|
+
|
|
42
|
+
# Get the tx hash or return an error if one was not generated
|
|
43
|
+
response.tx_hash = response.stdout.get("txhash", "")
|
|
44
|
+
if response.tx_hash == "":
|
|
45
|
+
response.raw_log = "Tx hash not found after running tx"
|
|
46
|
+
return response
|
|
47
|
+
|
|
48
|
+
# Poll the tx hash for the codeID and raw log
|
|
49
|
+
for _ in range(30):
|
|
50
|
+
response_data = stride_requests.get_tx(response.tx_hash, api_endpoint=api_endpoint)
|
|
51
|
+
if not response_data.get("tx_response"):
|
|
52
|
+
time.sleep(2)
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
response.code = int(response_data["tx_response"]["code"])
|
|
56
|
+
response.raw_log = response_data["tx_response"]["raw_log"]
|
|
57
|
+
response.success = response.code == 0
|
|
58
|
+
return response
|
|
59
|
+
|
|
60
|
+
# If the tx was never found on chain, return an error
|
|
61
|
+
response.raw_log = "Transaction not found on chain after one minute"
|
|
62
|
+
return response
|
|
@@ -14,6 +14,8 @@ import redis
|
|
|
14
14
|
from strideutils.stride_config import Environment as e
|
|
15
15
|
from strideutils.stride_config import get_env_or_raise
|
|
16
16
|
|
|
17
|
+
# TODO: add SSL option flag, defaulting to false
|
|
18
|
+
|
|
17
19
|
# TODO: Remove and use from environment variables
|
|
18
20
|
DATABASE_HOSTS = {
|
|
19
21
|
"public": "usw1-certain-beagle-33773.upstash.io",
|
|
@@ -61,22 +63,12 @@ ALL_DATABASE_NAMES = list(DATABASE_ENVIRONMENT_CONFIGS.keys())
|
|
|
61
63
|
|
|
62
64
|
|
|
63
65
|
class RedisClient:
|
|
64
|
-
"""
|
|
66
|
+
"""Redis client to connect to mulitple databases at once"""
|
|
65
67
|
|
|
66
|
-
|
|
68
|
+
# Mapping of database name to redis client
|
|
67
69
|
_dbs: Dict[str, redis.Redis] = {}
|
|
68
70
|
|
|
69
|
-
def
|
|
70
|
-
if cls._instance is None:
|
|
71
|
-
cls._instance = super(RedisClient, cls).__new__(cls)
|
|
72
|
-
cls._instance.__init__(db_names)
|
|
73
|
-
return cls._instance
|
|
74
|
-
|
|
75
|
-
def __init__(self, db_names: Optional[List[str] | str] = None):
|
|
76
|
-
if len(self._dbs) == 0:
|
|
77
|
-
self._init_dbs(db_names)
|
|
78
|
-
|
|
79
|
-
def _init_dbs(self, db_name_or_names: Optional[List[str] | str] = None):
|
|
71
|
+
def __init__(self, db_name_or_names: Optional[List[str] | str] = None):
|
|
80
72
|
"""
|
|
81
73
|
Initializes Redis database connections.
|
|
82
74
|
|
|
@@ -117,6 +109,7 @@ class RedisClient:
|
|
|
117
109
|
host = DATABASE_HOSTS.get(database_name)
|
|
118
110
|
port = DATABASE_PORTS.get(database_name)
|
|
119
111
|
password = get_env_or_raise(password_env)
|
|
112
|
+
ssl = database_name != "public"
|
|
120
113
|
|
|
121
114
|
if not host or not port:
|
|
122
115
|
raise ValueError(f"Host or port not known for database {database_name}")
|
|
@@ -125,7 +118,7 @@ class RedisClient:
|
|
|
125
118
|
"host": host,
|
|
126
119
|
"port": port,
|
|
127
120
|
"password": password,
|
|
128
|
-
"ssl":
|
|
121
|
+
"ssl": ssl,
|
|
129
122
|
"decode_responses": True,
|
|
130
123
|
}
|
|
131
124
|
|
|
@@ -218,9 +218,6 @@ class Config(ConfigObj):
|
|
|
218
218
|
ENV: str
|
|
219
219
|
timezone: str = "US/Eastern"
|
|
220
220
|
|
|
221
|
-
# Gsheets - loads from str env var in PROD
|
|
222
|
-
PUBLICSHEETS_AUTH: Union[str, ConfigDict] = field(default_factory=ConfigDict)
|
|
223
|
-
|
|
224
221
|
# Coingecko
|
|
225
222
|
COINGECKO_API_TOKEN: str = ""
|
|
226
223
|
|
|
@@ -231,15 +228,6 @@ class Config(ConfigObj):
|
|
|
231
228
|
alerts_playbook: str = ""
|
|
232
229
|
slack_channels: ConfigDict = field(default_factory=ConfigDict)
|
|
233
230
|
|
|
234
|
-
# Upstash
|
|
235
|
-
UPSTASH_PUBLIC_PASSWORD: str = ""
|
|
236
|
-
UPSTASH_STRIDE_FRONTEND_PASSWORD: str = ""
|
|
237
|
-
UPSTASH_STRIDE_BACKEND_PASSWORD: str = ""
|
|
238
|
-
UPSTASH_STRIDE_DYDX_PUBLIC_PASSWORD: str = ""
|
|
239
|
-
UPSTASH_STRIDE_DYDX_AIRDROP_PASSWORD: str = ""
|
|
240
|
-
UPSTASH_STRIDE_SAGA_AIRDROP_PASSWORD: str = ""
|
|
241
|
-
UPSTASH_STRIDE_MILESTONES_PASSWORD: str = ""
|
|
242
|
-
|
|
243
231
|
# Stride internal secrets
|
|
244
232
|
SLACK_BEARER_TOKEN: str = ""
|
|
245
233
|
SLACK_SUCCESS_CHANNEL_ID: str = ""
|
|
File without changes
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
.bumpversion.cfg
|
|
2
2
|
.gitignore
|
|
3
3
|
LICENSE
|
|
4
|
+
MANIFEST.in
|
|
4
5
|
Makefile
|
|
5
6
|
README.md
|
|
6
7
|
pyproject.toml
|
|
@@ -30,6 +31,7 @@ strideutils.egg-info/requires.txt
|
|
|
30
31
|
strideutils.egg-info/top_level.txt
|
|
31
32
|
strideutils/config_examples/env.local.example
|
|
32
33
|
strideutils/config_examples/strideutils_config.yaml.example
|
|
34
|
+
strideutils/strideutils/__init__.pyi
|
|
33
35
|
tests/test_config.py
|
|
34
36
|
tests/test_encryption.py
|
|
35
37
|
tests/test_redis_connector.py
|
|
@@ -58,7 +58,7 @@ def test_sheets_write_sheet_new_worksheet(sheets_client):
|
|
|
58
58
|
df = pd.DataFrame({'A': [1, 3], 'B': [2, 4]})
|
|
59
59
|
sheets_client.write_sheet(df, 'sheet_id', 'new_sheet')
|
|
60
60
|
|
|
61
|
-
mock_spreadsheet.add_worksheet.assert_called_once_with(title='new_sheet', rows=
|
|
61
|
+
mock_spreadsheet.add_worksheet.assert_called_once_with(title='new_sheet', rows=1, cols=1)
|
|
62
62
|
|
|
63
63
|
def test_sheets_reorder_sheet(sheets_client):
|
|
64
64
|
mock_spreadsheet = MagicMock()
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from unittest.mock import patch, MagicMock
|
|
3
|
+
from twilio.rest import Client as TwilioRestClient
|
|
4
|
+
from strideutils.twilio_connector import TwilioClient
|
|
5
|
+
from strideutils.stride_config import Environment as e
|
|
6
|
+
|
|
7
|
+
@pytest.fixture(autouse=True)
|
|
8
|
+
def reset_twilio_client():
|
|
9
|
+
TwilioClient._instance = None
|
|
10
|
+
yield
|
|
11
|
+
TwilioClient._instance = None
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def mock_twilio_rest_client():
|
|
15
|
+
with patch('strideutils.twilio_connector.Client') as mock:
|
|
16
|
+
mock_instance = MagicMock()
|
|
17
|
+
mock.return_value = mock_instance
|
|
18
|
+
yield mock_instance
|
|
19
|
+
|
|
20
|
+
@pytest.fixture(autouse=True)
|
|
21
|
+
def mock_env_vars():
|
|
22
|
+
with patch('strideutils.twilio_connector.get_env_or_raise') as mock_get_env:
|
|
23
|
+
def side_effect(arg):
|
|
24
|
+
if arg == e.TWILIO_ACCOUNT_ID:
|
|
25
|
+
return 'fake_account_id'
|
|
26
|
+
elif arg == e.TWILIO_API_TOKEN:
|
|
27
|
+
return 'fake_api_token'
|
|
28
|
+
elif arg == e.TWILIO_ALERTS_NUMBER:
|
|
29
|
+
return 'fake_alert_numbers'
|
|
30
|
+
return 'dummy_value'
|
|
31
|
+
mock_get_env.side_effect = side_effect
|
|
32
|
+
yield mock_get_env
|
|
33
|
+
|
|
34
|
+
@pytest.fixture
|
|
35
|
+
def twilio_client(mock_twilio_rest_client, mock_env_vars):
|
|
36
|
+
client = TwilioClient()
|
|
37
|
+
return client
|
|
38
|
+
|
|
39
|
+
def test_twilio_client_singleton():
|
|
40
|
+
client1 = TwilioClient()
|
|
41
|
+
client2 = TwilioClient()
|
|
42
|
+
assert client1 is client2
|
|
43
|
+
|
|
44
|
+
def test_twilio_client_initialization(twilio_client, mock_env_vars):
|
|
45
|
+
assert twilio_client.account_id == 'fake_account_id'
|
|
46
|
+
assert twilio_client.api_token == 'fake_api_token'
|
|
47
|
+
assert twilio_client.alert_numbers == 'fake_alert_numbers'
|
|
48
|
+
assert isinstance(twilio_client.client, MagicMock)
|
|
49
|
+
|
|
50
|
+
def test_call_single_recipient(twilio_client, mock_twilio_rest_client):
|
|
51
|
+
with patch('strideutils.twilio_connector.config') as mock_config:
|
|
52
|
+
mock_config.PHONE_NUMBERS = {'recipient': '+12223334444'}
|
|
53
|
+
mock_config.TWILIO_ALERTS_NUMBER = '+15556667777'
|
|
54
|
+
|
|
55
|
+
twilio_client.call("Test message", "recipient")
|
|
56
|
+
|
|
57
|
+
expected_twiml = "<Response><Say>Test message</Say></Response>"
|
|
58
|
+
mock_twilio_rest_client.calls.create.assert_called_once_with(
|
|
59
|
+
to='+12223334444',
|
|
60
|
+
from_='+15556667777',
|
|
61
|
+
twiml=expected_twiml
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def test_call_multiple_recipients(twilio_client, mock_twilio_rest_client):
|
|
65
|
+
with patch('strideutils.twilio_connector.config') as mock_config:
|
|
66
|
+
mock_config.PHONE_NUMBERS = {
|
|
67
|
+
'recipient1': '+12223334444',
|
|
68
|
+
'recipient2': '+13334445555'
|
|
69
|
+
}
|
|
70
|
+
mock_config.TWILIO_ALERTS_NUMBER = '+15556667777'
|
|
71
|
+
|
|
72
|
+
twilio_client.call("Test message", ["recipient1", "recipient2"])
|
|
73
|
+
|
|
74
|
+
expected_twiml = "<Response><Say>Test message</Say></Response>"
|
|
75
|
+
assert mock_twilio_rest_client.calls.create.call_count == 2
|
|
76
|
+
mock_twilio_rest_client.calls.create.assert_any_call(
|
|
77
|
+
to='+12223334444',
|
|
78
|
+
from_='+15556667777',
|
|
79
|
+
twiml=expected_twiml
|
|
80
|
+
)
|
|
81
|
+
mock_twilio_rest_client.calls.create.assert_any_call(
|
|
82
|
+
to='+13334445555',
|
|
83
|
+
from_='+15556667777',
|
|
84
|
+
twiml=expected_twiml
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
def test_call_invalid_recipient(twilio_client, mock_twilio_rest_client):
|
|
88
|
+
with patch('strideutils.twilio_connector.config') as mock_config:
|
|
89
|
+
mock_config.PHONE_NUMBERS = {}
|
|
90
|
+
|
|
91
|
+
with pytest.raises(KeyError):
|
|
92
|
+
twilio_client.call("Test message", "invalid_recipient")
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import re
|
|
2
|
-
import subprocess
|
|
3
|
-
import time
|
|
4
|
-
from dataclasses import dataclass
|
|
5
|
-
from typing import Optional
|
|
6
|
-
|
|
7
|
-
from strideutils import stride_requests
|
|
8
|
-
from strideutils.stride_config import config
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@dataclass
|
|
12
|
-
class TxResponse:
|
|
13
|
-
stdout: str
|
|
14
|
-
stderr: str
|
|
15
|
-
tx_response: Optional[dict] = None
|
|
16
|
-
tx_hash: Optional[str] = None
|
|
17
|
-
success: bool = False
|
|
18
|
-
raw_log: Optional[str] = None
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def execute_tx(command: str, api_endpoint: str = config.stride.api_endpoint, verbose=False) -> TxResponse:
|
|
22
|
-
"""
|
|
23
|
-
Execute a tx and query the tx hash
|
|
24
|
-
"""
|
|
25
|
-
output = subprocess.run(command, shell=True, capture_output=True)
|
|
26
|
-
standard_out = re.sub(r'\x1b\[[0-9;]*[mGKH]', '', output.stdout.decode('utf-8'))
|
|
27
|
-
error_out = re.sub(r'\x1b\[[0-9;]*[mGKH]', '', output.stderr.decode('utf-8'))
|
|
28
|
-
if verbose:
|
|
29
|
-
print("Standard Out: ", standard_out)
|
|
30
|
-
print("Error Out: ", error_out)
|
|
31
|
-
tx_hash = ""
|
|
32
|
-
for output_line in standard_out.split('\n'):
|
|
33
|
-
if 'txhash' in output_line:
|
|
34
|
-
tx_hash = output_line.split(': ')[-1]
|
|
35
|
-
|
|
36
|
-
tx_response = None
|
|
37
|
-
response_success = False
|
|
38
|
-
raw_log = "Transaction not found on chain after one minute" # default message
|
|
39
|
-
if not error_out:
|
|
40
|
-
event_filters = [(f"tx.hash='{tx_hash}'")]
|
|
41
|
-
for _ in range(30):
|
|
42
|
-
time.sleep(2)
|
|
43
|
-
tx_response = stride_requests.get_txs(event_filters, api_endpoint)
|
|
44
|
-
if tx_response.get('tx_responses'):
|
|
45
|
-
try:
|
|
46
|
-
response_code = tx_response['tx_responses'][0]['code']
|
|
47
|
-
raw_log = tx_response['tx_responses'][0]['raw_log']
|
|
48
|
-
response_success = response_code == 0
|
|
49
|
-
except KeyError:
|
|
50
|
-
response_success = False
|
|
51
|
-
break
|
|
52
|
-
|
|
53
|
-
success = response_success and not error_out
|
|
54
|
-
response = TxResponse(
|
|
55
|
-
stdout=standard_out,
|
|
56
|
-
stderr=error_out,
|
|
57
|
-
tx_response=tx_response,
|
|
58
|
-
success=success,
|
|
59
|
-
tx_hash=tx_hash,
|
|
60
|
-
raw_log=raw_log,
|
|
61
|
-
)
|
|
62
|
-
return response
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import pytest
|
|
2
|
-
from unittest.mock import patch, MagicMock
|
|
3
|
-
from twilio.rest import Client as TwilioRestClient
|
|
4
|
-
|
|
5
|
-
from strideutils.twilio_connector import TwilioClient
|
|
6
|
-
|
|
7
|
-
@pytest.fixture
|
|
8
|
-
def mock_twilio_client():
|
|
9
|
-
with patch('strideutils.twilio_connector.Client') as mock_client:
|
|
10
|
-
yield mock_client.return_value
|
|
11
|
-
|
|
12
|
-
@pytest.fixture
|
|
13
|
-
def twilio_client(mock_twilio_client):
|
|
14
|
-
with patch('strideutils.twilio_connector.get_env_or_raise') as mock_get_env:
|
|
15
|
-
mock_get_env.side_effect = ['fake_account_id', 'fake_api_token', 'fake_alert_numbers']
|
|
16
|
-
client = TwilioClient()
|
|
17
|
-
client.client = mock_twilio_client # Replaced the real Twilio client with a mock, to not send to the real.
|
|
18
|
-
yield client
|
|
19
|
-
|
|
20
|
-
def test_twilio_client_singleton():
|
|
21
|
-
with patch('strideutils.twilio_connector.Client'):
|
|
22
|
-
with patch('strideutils.twilio_connector.get_env_or_raise'):
|
|
23
|
-
client1 = TwilioClient()
|
|
24
|
-
client2 = TwilioClient()
|
|
25
|
-
assert client1 is client2
|
|
26
|
-
|
|
27
|
-
def test_call_single_recipient(twilio_client, mock_twilio_client):
|
|
28
|
-
with patch('strideutils.twilio_connector.config') as mock_config:
|
|
29
|
-
mock_config.PHONE_NUMBERS = {'recipient': '+12223334444'}
|
|
30
|
-
mock_config.TWILIO_ALERTS_NUMBER = '+15556667777'
|
|
31
|
-
|
|
32
|
-
twilio_client.call("Test message", "recipient")
|
|
33
|
-
|
|
34
|
-
expected_twiml = "<Response><Say>Test message</Say></Response>"
|
|
35
|
-
mock_twilio_client.calls.create.assert_called_once_with(
|
|
36
|
-
to='+12223334444',
|
|
37
|
-
from_='+15556667777',
|
|
38
|
-
twiml=expected_twiml
|
|
39
|
-
)
|
|
40
|
-
|
|
41
|
-
def test_call_multiple_recipients(twilio_client, mock_twilio_client):
|
|
42
|
-
with patch('strideutils.twilio_connector.config') as mock_config:
|
|
43
|
-
mock_config.PHONE_NUMBERS = {
|
|
44
|
-
'recipient1': '+12223334444',
|
|
45
|
-
'recipient2': '+13334445555'
|
|
46
|
-
}
|
|
47
|
-
mock_config.TWILIO_ALERTS_NUMBER = '+15556667777'
|
|
48
|
-
|
|
49
|
-
twilio_client.call("Test message", ["recipient1", "recipient2"])
|
|
50
|
-
|
|
51
|
-
expected_twiml = "<Response><Say>Test message</Say></Response>"
|
|
52
|
-
assert mock_twilio_client.calls.create.call_count == 2
|
|
53
|
-
mock_twilio_client.calls.create.assert_any_call(
|
|
54
|
-
to='+12223334444',
|
|
55
|
-
from_='+15556667777',
|
|
56
|
-
twiml=expected_twiml
|
|
57
|
-
)
|
|
58
|
-
mock_twilio_client.calls.create.assert_any_call(
|
|
59
|
-
to='+13334445555',
|
|
60
|
-
from_='+15556667777',
|
|
61
|
-
twiml=expected_twiml
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
def test_call_invalid_recipient(twilio_client, mock_twilio_client):
|
|
65
|
-
with patch('strideutils.twilio_connector.config') as mock_config:
|
|
66
|
-
mock_config.PHONE_NUMBERS = {}
|
|
67
|
-
|
|
68
|
-
with pytest.raises(KeyError):
|
|
69
|
-
twilio_client.call("Test message", "invalid_recipient")
|
|
70
|
-
|
|
71
|
-
@patch('strideutils.twilio_connector.get_env_or_raise')
|
|
72
|
-
def test_twilio_client_initialization(mock_get_env):
|
|
73
|
-
mock_get_env.side_effect = ['fake_account_id', 'fake_api_token', 'fake_alert_numbers'] # just dummy values, so this should fail.
|
|
74
|
-
|
|
75
|
-
client = TwilioClient()
|
|
76
|
-
|
|
77
|
-
assert client.account_id == 'fake_account_id'
|
|
78
|
-
assert client.api_token == 'fake_api_token'
|
|
79
|
-
assert client.alert_numbers == 'fake_alert_numbers'
|
|
80
|
-
assert isinstance(client.client, TwilioRestClient)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{strideutils-0.7.7 → strideutils-0.7.9}/strideutils/config_examples/strideutils_config.yaml.example
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|