Release-notes and fix the build (#1135)

* kick

* release-notes

* updating black

* Slightly changes rule for black

* version now v1.3.1

* pin pre-commit and black-version used for linting

* black
This commit is contained in:
Kim Neunert 2021-04-26 14:09:42 +02:00 committed by GitHub
parent b2a89981b2
commit b816a3d480
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 106 additions and 79 deletions

View file

@ -8,6 +8,6 @@ jobs:
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: psf/black@stable # the default is equivalent to `black . --diff --check`.
- uses: psf/black@21.4b0 # the default is equivalent to `black . --diff --check`.
with:
args: ". --diff --check"

View file

@ -24,7 +24,7 @@ before_script:
- python -V # Print out python version for debugging
- apt update
- apt install -y libusb-1.0-0-dev libudev-dev # usb-support in hidapi
- pip3 install virtualenv
- pip3 install --upgrade virtualenv
- virtualenv --python=python3 .env
- source .env/bin/activate

View file

@ -1,6 +1,6 @@
repos:
- repo: https://github.com/ambv/black
rev: stable
rev: 21.4b0
hooks:
- id: black
language_version: python3.8

View file

@ -136,7 +136,7 @@ Check the cypress-section on how to run cypress-frontend-tests.
## Code-Style
Before your create a PR, make sure to [blackify](https://github.com/psf/black) all your changes. In order to automate that,
there is a git pre-commit hook which you can simply install like this:
there is a git [pre-commit hook](https://ljvmiranda921.github.io/notebook/2018/06/21/precommits-using-black-and-flake8/) which you can simply install like this:
```
pre-commit install
```

View file

@ -1,3 +1,30 @@
## v1.3.1 April 26, 2021
- Feature: Add unconfirmed tx fees data #1085 (benk10)
- Feature: Use RPCAuth instead of username + password #1093 (benk10)
- Feature: Return to/ cancel setup process #1091 (benk10)
- UIUX: Show user-friendly error messages when session expires #1087 (benk10)
- UIUX: Use Bitcoin icon set #1080 (benk10)
- Docs: Update faq.md #1123 (Kim Neunert)
- Docs: added build-instructions #1077 (Kim Neunert)
- Bugfix: BitBox02 timeout issue #1090 (benk10)
- Bugfix: Fix crash if estimatesmartfee fails #1086 (benk10)
- Bugfix: typo/exception #1102 (djpnewton)
- Bugfix: #1073 #1094 (benk10)
- Bugfix: #987 #1088 (benk10)
- Bugfix: arrow down svg #1125 (benk10)
- Bugfix: del user with wallets #1126 (Stepan Snigirev)
- Bugfix: month names #1069 (Kim Neunert)
- Bugfix: truncated PDF #1095 (benk10)
- Bugfix: UI issues #1084 (benk10)
- Bugfix: using correct image for gitlab #1127 (Kim Neunert)
- Bugfix: Improve tx-table and addresses-table render performance #1122 (Will Cosgrove)
- Chore: Bump y18n from 5.0.4 to 5.0.8 in /pyinstaller/electron #1114 (dependabot[bot])
- Chore: Refactoring new device setup #1111 (benk10)
- Chore: allow python version 3.9.X after upgrade to HWI 2.0.1 #1104 (djpnewton)
- Chore: upgrade wait-on and axios #1124 (Kim Neunert)
- Chore: refactor check_methods out of specter #1106 (Kim Neunert)
- Chore: Refactor setup wizard #1120 (benk10)
## v1.3.0 March 29, 2021
- Bugfix: bump embit version, add secp binary #1031 (Stepan Snigirev)
- Bugfix: consolidations issue #1034 (benk10)

View file

@ -25,7 +25,7 @@ logger = logging.getLogger(__name__)
class Btcd_conn:
""" An object to easily store connection data """
"""An object to easily store connection data"""
def __init__(
self, rpcuser="bitcoin", rpcpassword="secret", rpcport=18543, ipaddress=None
@ -47,7 +47,7 @@ class Btcd_conn:
self._ipaddress = ipaddress
def get_rpc(self):
""" returns a BitcoinRPC """
"""returns a BitcoinRPC"""
# def __init__(self, user, passwd, host="127.0.0.1", port=8332, protocol="http", path="", timeout=30, **kwargs):
rpc = BitcoinRPC(
self.rpcuser, self.rpcpassword, host=self.ipaddress, port=self.rpcport
@ -65,7 +65,7 @@ class Btcd_conn:
)
def as_data(self):
""" returns a data-representation of this connection """
"""returns a data-representation of this connection"""
me = {
"user": self.rpcuser,
"password": self.rpcpassword,
@ -76,7 +76,7 @@ class Btcd_conn:
return me
def render_json(self):
""" returns a json-representation of this connection """
"""returns a json-representation of this connection"""
return json.dumps(self.as_data())
def __repr__(self):
@ -84,7 +84,7 @@ class Btcd_conn:
class BitcoindController:
""" A kind of abstract class to simplify running a bitcoind with or without docker """
"""A kind of abstract class to simplify running a bitcoind with or without docker"""
def __init__(
self, rpcport=18443, network="regtest", rpcuser="bitcoin", rpcpassword="secret"
@ -138,13 +138,13 @@ class BitcoindController:
return self.rpcconn
def version(self):
""" Returns the version of bitcoind, e.g. "v0.19.1" """
"""Returns the version of bitcoind, e.g. "v0.19.1" """
version = self.get_rpc().getnetworkinfo()["subversion"]
version = version.replace("/", "").replace("Satoshi:", "v")
return version
def get_rpc(self):
""" wrapper for convenience """
"""wrapper for convenience"""
return self.rpcconn.get_rpc()
def _start_bitcoind(
@ -159,11 +159,11 @@ class BitcoindController:
raise Exception("This should not be used in the baseclass!")
def mine(self, address="mruae2834buqxk77oaVpephnA5ZAxNNJ1r", block_count=1):
""" Does mining to the attached address with as many as block_count blocks """
"""Does mining to the attached address with as many as block_count blocks"""
self.rpcconn.get_rpc().generatetoaddress(block_count, address)
def testcoin_faucet(self, address, amount=20, mine_tx=False):
""" an easy way to get some testcoins """
"""an easy way to get some testcoins"""
rpc = self.get_rpc()
try:
test3rdparty_rpc = rpc.wallet("test3rdparty")
@ -187,7 +187,7 @@ class BitcoindController:
@staticmethod
def check_bitcoind(rpcconn, raise_exception=False):
""" returns true if bitcoind is running on that address/port """
"""returns true if bitcoind is running on that address/port"""
if raise_exception:
rpcconn.get_rpc() # that call will also check the connection
return True
@ -214,7 +214,7 @@ class BitcoindController:
@staticmethod
def wait_for_bitcoind(rpcconn, timeout=15):
""" tries to reach the bitcoind via rpc. Timeout after n seconds """
"""tries to reach the bitcoind via rpc. Timeout after n seconds"""
i = 0
while True:
if BitcoindController.check_bitcoind(rpcconn):
@ -250,7 +250,7 @@ class BitcoindController:
network="regtest",
extra_args=[],
):
""" returns a bitcoind-command to run bitcoind """
"""returns a bitcoind-command to run bitcoind"""
btcd_cmd = '"{}" '.format(bitcoind_path)
if network != "mainnet":
btcd_cmd += " -{} ".format(network)
@ -274,7 +274,7 @@ class BitcoindController:
class BitcoindPlainController(BitcoindController):
""" A class controlling the bitcoind-process directly on the machine """
"""A class controlling the bitcoind-process directly on the machine"""
def __init__(
self,

View file

@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
class BitcoindDockerController(BitcoindController):
""" A class specifically controlling a docker-based bitcoind-container """
"""A class specifically controlling a docker-based bitcoind-container"""
def __init__(self, rpcport=18443, docker_tag="latest"):
self.btcd_container = None
@ -92,7 +92,7 @@ class BitcoindDockerController(BitcoindController):
raise Exception("Ambigious Container running")
def check_existing(self):
""" Checks whether self.btcd_container is up2date and not ambigious """
"""Checks whether self.btcd_container is up2date and not ambigious"""
if self.btcd_container != None:
self.btcd_container.reload()
if self.btcd_container.status == "running":
@ -106,7 +106,7 @@ class BitcoindDockerController(BitcoindController):
@staticmethod
def search_bitcoind_container(all=False):
""" returns a list of containers which are running bitcoind """
"""returns a list of containers which are running bitcoind"""
d_client = docker.from_env()
return [
c
@ -179,7 +179,7 @@ class BitcoindDockerController(BitcoindController):
return None
def wait_for_container(self):
""" waits for the docker-container to come up. Times out after 10 seconds """
"""waits for the docker-container to come up. Times out after 10 seconds"""
i = 0
while True:
ip_address = self.btcd_container.attrs["NetworkSettings"]["IPAddress"]

View file

@ -229,7 +229,7 @@ def bitcoind(
def miner_loop(my_bitcoind, data_folder, mining_every_x_seconds, echo):
" An endless loop mining bitcoin "
"An endless loop mining bitcoin"
echo(
"Now, mining a block every %f seconds, avoid it via --no-mining"

View file

@ -278,7 +278,7 @@ def server(
def configure_ssl(kwargs, app_config, ssl):
""" accepts kwargs and adjust them based on the config and ssl """
"""accepts kwargs and adjust them based on the config and ssl"""
# If we should create a cert but it's not specified where, let's specify the location
if not ssl and app_config["CERT"] is None:

View file

@ -143,19 +143,19 @@ class ConfigManager(GenericDataManager):
return get_default_datadir()
def set_bitcoind_pid(self, pid):
""" set the control pid of the bitcoind daemon """
"""set the control pid of the bitcoind daemon"""
if self.data.get("bitcoind", False) != pid:
self.data["bitcoind"] = pid
self._save()
def update_use_external_node(self, use_external_node):
""" set whatever specter should connect to internal or external node """
"""set whatever specter should connect to internal or external node"""
assert isinstance(use_external_node, bool)
self.data["rpc"]["external_node"] = use_external_node
self._save()
def update_auth(self, method, rate_limit, registration_link_timeout):
""" simply persisting the current auth-choice """
"""simply persisting the current auth-choice"""
auth = self.data["auth"]
if auth["method"] != method:
auth["method"] = method
@ -166,7 +166,7 @@ class ConfigManager(GenericDataManager):
self._save()
def update_explorer(self, explorer_id, explorer_data, user, chain):
""" update the block explorers urls """
"""update the block explorers urls"""
if isinstance(user, str):
raise Exception("Please pass a real user, not a string-user")
# we don't know what chain to change
@ -193,7 +193,7 @@ class ConfigManager(GenericDataManager):
user.set_explorer(explorer_id, explorer_data["url"])
def update_fee_estimator(self, fee_estimator, custom_url, user):
""" update the fee estimator option and its url if custom """
"""update the fee estimator option and its url if custom"""
if isinstance(user, str):
raise Exception("Please pass a real user, not a string-user")
fee_estimator_options = ["mempool", "bitcoin_core", "custom"]
@ -210,24 +210,24 @@ class ConfigManager(GenericDataManager):
user.set_fee_estimator(fee_estimator, custom_url)
def update_proxy_url(self, proxy_url, user):
""" update the Tor proxy url """
"""update the Tor proxy url"""
if self.data["proxy_url"] != proxy_url:
self.data["proxy_url"] = proxy_url
self._save()
def toggle_tor_status(self):
""" toggle the Tor status """
"""toggle the Tor status"""
self.data["tor_status"] = not self.data["tor_status"]
self._save()
def update_only_tor(self, only_tor, user):
""" switch whatever to use Tor for all calls """
"""switch whatever to use Tor for all calls"""
if self.data["only_tor"] != only_tor:
self.data["only_tor"] = only_tor
self._save()
def update_tor_control_port(self, tor_control_port, user):
""" set the control port of the tor daemon """
"""set the control port of the tor daemon"""
if self.data["tor_control_port"] != tor_control_port:
self.data["tor_control_port"] = tor_control_port
self._save()
@ -240,7 +240,7 @@ class ConfigManager(GenericDataManager):
logger.info(f"Generated torrc_password in {self.data_file}")
def update_hwi_bridge_url(self, url, user):
""" update the hwi bridge url to use """
"""update the hwi bridge url to use"""
if isinstance(user, str):
raise Exception("Please pass a real user, not a string-user")
if url and not url.endswith("/"):

View file

@ -14,14 +14,14 @@ class OtpManager(GenericDataManager):
name_of_json_file = "otps.json"
def add_new_user_otp(self, otp_dict):
""" adds an OTP for user registration """
"""adds an OTP for user registration"""
if "new_user_otps" not in self.data:
self.data["new_user_otps"] = []
self.data["new_user_otps"].append(otp_dict)
self._save()
def validate_new_user_otp(self, otp):
""" validates an OTP for user registration and removes it if expired"""
"""validates an OTP for user registration and removes it if expired"""
if "new_user_otps" not in self.data:
return False
now = time.time()
@ -39,7 +39,7 @@ class OtpManager(GenericDataManager):
return False
def remove_new_user_otp(self, otp):
""" removes an OTP for user registration"""
"""removes an OTP for user registration"""
if "new_user_otps" not in self.data:
return False
for i, otp_dict in enumerate(self.data["new_user_otps"]):

View file

@ -44,14 +44,14 @@ def read_json_file(path):
def _delete_folder(path):
""" Internal method which won't trigger the callback """
"""Internal method which won't trigger the callback"""
with fslock:
if os.path.exists(path):
shutil.rmtree(path)
def _write_json_file(content, path, lock=None):
""" Internal method which won't trigger the callback """
"""Internal method which won't trigger the callback"""
if lock is None:
lock = fslock
with lock:
@ -101,7 +101,7 @@ def delete_file(path):
def write_devices(devices_json):
""" interpret a json as a list of devices and write them in the devices subfolder inside the specter-folder """
"""interpret a json as a list of devices and write them in the devices subfolder inside the specter-folder"""
for device_json in devices_json:
_write_json_file(
device_json,

View file

@ -277,7 +277,7 @@ class BitcoinRPC:
self._create_session()
def test_connection(self):
""" returns a boolean depending on whether getblockchaininfo() succeeds """
"""returns a boolean depending on whether getblockchaininfo() succeeds"""
try:
self.getblockchaininfo()
return True

View file

@ -27,7 +27,7 @@ csrf = CSRFProtect()
def calc_module_name(config):
""" tiny helper to make passing configs more convenient """
"""tiny helper to make passing configs more convenient"""
if "." in config:
return config
else:
@ -75,7 +75,7 @@ def create_app(config=None):
def init_app(app, hwibridge=False, specter=None):
""" see blogpost 19nd Feb 2020 """
"""see blogpost 19nd Feb 2020"""
# Login via Flask-Login
app.logger.info("Initializing LoginManager")
app.secret_key = app.config["SECRET_KEY"]

View file

@ -25,7 +25,7 @@ auth_endpoint = Blueprint("auth_endpoint", __name__)
@auth_endpoint.route("/login", methods=["GET", "POST"])
@app.csrf.exempt
def login():
""" login """
"""login"""
if request.method == "POST":
rate_limit()
auth = app.specter.config["auth"]
@ -97,7 +97,7 @@ def login():
@auth_endpoint.route("/register", methods=["GET", "POST"])
def register():
""" register """
"""register"""
if request.method == "POST":
rate_limit()
username = request.form["username"]

View file

@ -45,7 +45,7 @@ rand = random.randint(0, 1e32) # to force style refresh
########## exception handlers ##############
@app.errorhandler(RpcError)
def server_rpc_error(rpce):
""" Specific SpecterErrors get passed on to the User as flash """
"""Specific SpecterErrors get passed on to the User as flash"""
if rpce.error_code == -18: # RPC_WALLET_NOT_FOUND
flash(
"Wallet not found. Specter reloaded all Wallets, please try again.", "error"
@ -61,7 +61,7 @@ def server_rpc_error(rpce):
@app.errorhandler(SpecterError)
def server_specter_error(se):
""" Specific EpecterErrors get passed on to the User as flash """
"""Specific EpecterErrors get passed on to the User as flash"""
flash(str(se), "error")
try:
app.specter.wallet_manager.update()
@ -72,7 +72,7 @@ def server_specter_error(se):
@app.errorhandler(Exception)
def server_error(e):
""" Unspecific Exceptions get a 500 Error-Page """
"""Unspecific Exceptions get a 500 Error-Page"""
# if rpc is not available
if app.specter.rpc is None or not app.specter.rpc.test_connection():
# make sure specter knows that rpc is not there
@ -85,7 +85,7 @@ def server_error(e):
@app.errorhandler(ExtProcTimeoutException)
def server_error_timeout(e):
""" Unspecific Exceptions get a 500 Error-Page """
"""Unspecific Exceptions get a 500 Error-Page"""
# if rpc is not available
if app.specter.rpc is None or not app.specter.rpc.test_connection():
# make sure specter knows that rpc is not there
@ -112,7 +112,7 @@ def server_error_csrf(e):
@app.errorhandler(MethodNotAllowed)
def server_error_405(e):
""" 405 method not allowed. Token might have expired."""
"""405 method not allowed. Token might have expired."""
app.logger.error("405 MethodNotAllowed Exception: %s" % e)
trace = traceback.format_exc()
app.logger.error(trace)
@ -135,7 +135,7 @@ def selfcheck():
########## template injections #############
@app.context_processor
def inject_debug():
""" Can be used in all jinja2 templates """
"""Can be used in all jinja2 templates"""
return dict(debug=app.config["DEBUG"])

View file

@ -43,7 +43,7 @@ def start():
@setup_endpoint.route("/tor/", methods=["GET"])
@login_required
def tor():
""" wizard: Setup Tor daemon (Skip / Setup Tor) """
"""wizard: Setup Tor daemon (Skip / Setup Tor)"""
app.specter.setup_status["stage"] = "tor"
return render_template(
"setup/tor.jinja",
@ -66,7 +66,7 @@ def node_type():
@setup_endpoint.route("/bitcoind/", methods=["GET"])
@login_required
def bitcoind():
""" wizard: Setup Bitcoin Core (Start the Setup!) """
"""wizard: Setup Bitcoin Core (Start the Setup!)"""
app.specter.setup_status["stage"] = "bitcoind"
return render_template("setup/bitcoind.jinja", specter=app.specter, rand=rand)
@ -74,7 +74,7 @@ def bitcoind():
@setup_endpoint.route("/bitcoind_datadir/", methods=["GET"])
@login_required
def bitcoind_datadir():
""" wizard: Configure your node (Quicksync? , Start Syncing) """
"""wizard: Configure your node (Quicksync? , Start Syncing)"""
app.specter.setup_status["stage"] = "bitcoind_datadir"
return render_template(
"setup/bitcoind_datadir.jinja", specter=app.specter, rand=rand
@ -84,7 +84,7 @@ def bitcoind_datadir():
@setup_endpoint.route("/end/", methods=["GET"])
@login_required
def end():
""" wizard: Setup competed Successfully (Done)"""
"""wizard: Setup competed Successfully (Done)"""
app.specter.setup_status["stage"] = "start"
return render_template("setup/end.jinja", specter=app.specter, rand=rand)
@ -92,7 +92,7 @@ def end():
@setup_endpoint.route("/tor_setup/", methods=["GET"])
@login_required
def tor_from_settings():
""" wizard: Setup Tor daemon (Setup Tor) """
"""wizard: Setup Tor daemon (Setup Tor)"""
return render_template(
"setup/tor.jinja",
nextURL="settings_endpoint.tor",

View file

@ -90,7 +90,7 @@ def get_rpc(
class Specter:
""" A central Object mostly holding app-settings """
"""A central Object mostly holding app-settings"""
# use this lock for all fs operations
lock = threading.Lock()
@ -445,7 +445,7 @@ class Specter:
# mark
def set_bitcoind_pid(self, pid):
""" set the control pid of the bitcoind daemon """
"""set the control pid of the bitcoind daemon"""
self.config_manager.set_bitcoind_pid(pid)
def update_setup_status(self, software_name, stage):
@ -483,44 +483,44 @@ class Specter:
# mark
def update_use_external_node(self, use_external_node):
""" set whatever specter should connect to internal or external node """
"""set whatever specter should connect to internal or external node"""
self.config_manager.update_use_external_node(use_external_node)
# mark
def update_auth(self, method, rate_limit, registration_link_timeout):
""" simply persisting the current auth-choice """
"""simply persisting the current auth-choice"""
self.config_manager.update_auth(method, rate_limit, registration_link_timeout)
# mark
def update_explorer(self, explorer_id, explorer_data, user):
""" update the block explorers urls """
"""update the block explorers urls"""
self.config_manager.update_explorer(
explorer_id, explorer_data, user, self.chain
)
# mark
def update_fee_estimator(self, fee_estimator, custom_url, user):
""" update the fee estimator option and its url if custom """
"""update the fee estimator option and its url if custom"""
self.config_manager.update_fee_estimator(fee_estimator, custom_url, user)
# mark
def update_proxy_url(self, proxy_url, user):
""" update the Tor proxy url """
"""update the Tor proxy url"""
self.config_manager.update_proxy_url(proxy_url, user)
# mark
def toggle_tor_status(self):
""" toggle the Tor status """
"""toggle the Tor status"""
self.config_manager.toggle_tor_status()
# mark
def update_only_tor(self, only_tor, user):
""" switch whatever to use Tor for all calls """
"""switch whatever to use Tor for all calls"""
self.config_manager.update_only_tor(only_tor, user)
# mark
def update_tor_control_port(self, tor_control_port, user):
""" set the control port of the tor daemon """
"""set the control port of the tor daemon"""
if self.config_manager.update_tor_control_port:
self.update_tor_controller()
@ -597,7 +597,7 @@ class Specter:
# mark
def update_hwi_bridge_url(self, url, user):
""" update the hwi bridge url to use """
"""update the hwi bridge url to use"""
self.config_manager.update_hwi_bridge_url(url, user)
# mark

View file

@ -5,7 +5,7 @@ logger = logging.getLogger(__name__)
class SpecterError(Exception):
""" A SpecterError contains meaningfull messages which can be passed directly to the user """
"""A SpecterError contains meaningfull messages which can be passed directly to the user"""
def __init__(self, message):
# Call the base class constructor with the parameters it needs
@ -38,7 +38,7 @@ class ExtProcTimeoutException(Exception):
def handle_exception(exception, user=None):
""" prints the exception and most important the stacktrace """
"""prints the exception and most important the stacktrace"""
logger.error("Unexpected error:")
logger.error(
"----START-TRACEBACK-----------------------------------------------------------------"

View file

@ -9,7 +9,7 @@ logger = logging.getLogger(__name__)
class TorDaemonController:
""" A class controlling the tor-daemon process directly on the machine """
"""A class controlling the tor-daemon process directly on the machine"""
def __init__(
self,

View file

@ -27,7 +27,7 @@ def encode_base58(s):
def encode_base58_checksum(s):
""" Adds the checksum and then encodes to base58 """
"""Adds the checksum and then encodes to base58"""
return encode_base58(s + double_sha256(s)[:4]).decode("ascii")

View file

@ -56,7 +56,7 @@ def run_shell(cmd):
def get_last_lines_from_file(file_localtion, x=50):
""" returns an array of the last x lines of a file """
"""returns an array of the last x lines of a file"""
with open(file_localtion, "r") as the_file:
lines = the_file.readlines()
last_lines = lines[-x:]

View file

@ -1016,7 +1016,7 @@ class Wallet:
return addrinfo and not addrinfo.is_external
def get_electrum_file(self):
""" Exports the wallet data as Electrum JSON format """
"""Exports the wallet data as Electrum JSON format"""
electrum_devices = [
"bitbox02",
"coldcard",

View file

@ -1,6 +1,6 @@
# requirements for testing
black==20.8b1
pre-commit==2.8.2
black==21.4b0
pre-commit==2.9.2
docker==4.3.1
pip-tools==5.3.1
pytest==6.1.2

View file

@ -282,7 +282,7 @@ def specter_regtest_configured(bitcoin_regtest, devices_filled_data_folder):
@pytest.fixture
def app(specter_regtest_configured):
""" the Flask-App, but uninitialized """
"""the Flask-App, but uninitialized"""
app = create_app()
app.app_context().push()
app.config["TESTING"] = True
@ -295,5 +295,5 @@ def app(specter_regtest_configured):
@pytest.fixture
def client(app):
""" a test_client from an initialized Flask-App """
"""a test_client from an initialized Flask-App"""
return app.test_client()

View file

@ -3,7 +3,7 @@ import pytest
def test_home(caplog, client):
""" The root of the app """
"""The root of the app"""
caplog.set_level(logging.INFO)
caplog.set_level(logging.DEBUG, logger="cryptoadvance.specter")
login(client, "secret")
@ -85,7 +85,7 @@ def test_settings_general_restore_wallet(bitcoin_regtest, caplog, client):
def login(client, password):
""" login helper-function """
"""login helper-function"""
result = client.post(
"auth/login", data=dict(password=password), follow_redirects=True
)
@ -97,5 +97,5 @@ def login(client, password):
def logout(client):
""" logout helper-method """
"""logout helper-method"""
return client.get("auth/logout", follow_redirects=True)