diff --git a/test/functional/abc-transaction-ordering.py b/test/functional/abc-transaction-ordering.py --- a/test/functional/abc-transaction-ordering.py +++ b/test/functional/abc-transaction-ordering.py @@ -145,7 +145,9 @@ self.tip = self.blocks[number] # adds transactions to the block and updates state - def update_block(block_number, new_transactions=[]): + def update_block(block_number, new_transactions=None): + if new_transactions is None: + new_transactions = [] block = self.blocks[block_number] self.add_transactions_to_block(block, new_transactions) old_sha256 = block.sha256 diff --git a/test/functional/test_framework/messages.py b/test/functional/test_framework/messages.py --- a/test/functional/test_framework/messages.py +++ b/test/functional/test_framework/messages.py @@ -690,7 +690,9 @@ return [key0, key1] # Version 2 compact blocks use wtxid in shortids (rather than txid) - def initialize_from_block(self, block, nonce=0, prefill_list=[0]): + def initialize_from_block(self, block, nonce=0, prefill_list=None): + if prefill_list is None: + prefill_list = [0] self.header = CBlockHeader(block) self.nonce = nonce self.prefilled_txn = [PrefilledTransaction(i, block.vtx[i]) diff --git a/test/functional/wallet_importmulti.py b/test/functional/wallet_importmulti.py --- a/test/functional/wallet_importmulti.py +++ b/test/functional/wallet_importmulti.py @@ -45,8 +45,10 @@ self.setup_nodes() def test_importmulti(self, req, success, error_code=None, - error_message=None, warnings=[]): + error_message=None, warnings=None): """Run importmulti and assert success""" + if warnings is None: + warnings = [] result = self.nodes[1].importmulti([req]) observed_warnings = [] if 'warnings' in result[0]: diff --git a/test/lint/lint-python-mutable-default-parameters.sh b/test/lint/lint-python-mutable-default-parameters.sh new file mode 100755 --- /dev/null +++ b/test/lint/lint-python-mutable-default-parameters.sh @@ -0,0 +1,52 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# +# Detect when a mutable list or dict is used as a default parameter value in a Python function. + +export LC_ALL=C +EXIT_CODE=0 +OUTPUT=$(git grep -E '^\s*def [a-zA-Z0-9_]+\(.*=\s*(\[|\{)' -- "*.py") +if [[ ${OUTPUT} != "" ]]; then + echo "A mutable list or dict seems to be used as default parameter value:" + echo + echo "${OUTPUT}" + echo + cat << EXAMPLE +This is how mutable list and dict default parameter values behave: + +>>> def f(i, j=[], k={}): +... j.append(i) +... k[i] = True +... return j, k +... +>>> f(1) +([1], {1: True}) +>>> f(1) +([1, 1], {1: True}) +>>> f(2) +([1, 1, 2], {1: True, 2: True}) + +The intended behaviour was likely: + +>>> def f(i, j=None, k=None): +... if j is None: +... j = [] +... if k is None: +... k = {} +... j.append(i) +... k[i] = True +... return j, k +... +>>> f(1) +([1], {1: True}) +>>> f(1) +([1], {1: True}) +>>> f(2) +([2], {2: True}) +EXAMPLE + EXIT_CODE=1 +fi +exit ${EXIT_CODE}