From 726793702b0511cced247fe3a5e1d781fa1b6338 Mon Sep 17 00:00:00 2001 From: caktux Date: Tue, 17 Feb 2015 18:54:33 -0500 Subject: [PATCH] fix config not getting overridden by cmd line options, deploy as class --- pyepm/api.py | 39 ++++-- pyepm/deploy.py | 309 ++++++++++++++++++++++---------------------- pyepm/pyepm.py | 7 +- test/test_api.py | 9 +- test/test_deploy.py | 6 +- 5 files changed, 201 insertions(+), 169 deletions(-) diff --git a/pyepm/api.py b/pyepm/api.py index 62457d5..0c32e00 100644 --- a/pyepm/api.py +++ b/pyepm/api.py @@ -3,7 +3,7 @@ # @Author: jorisbontje # @Date: 2014-08-03 13:53:04 # @Last Modified by: caktux -# @Last Modified time: 2015-02-12 04:39:38 +# @Last Modified time: 2015-02-17 18:49:12 import json import logging @@ -15,9 +15,6 @@ from pyethereum import abi from serpent import get_prefix, decode_datalist -import config as c -config = c.read_config() - logger = logging.getLogger(__name__) class ApiException(Exception): @@ -31,11 +28,15 @@ def __str__(self): class Api(object): - def __init__(self): + def __init__(self, config): self.host = config.get('api', 'host') self.port = config.getint('api', 'port') self.jsonrpc_url = "http://%s:%s" % (self.host, self.port) + logger.debug("Deploying to %s" % self.jsonrpc_url) + self.address = config.get("api", "address") + self.gas = config.get("deploy", "gas") + self.gas_price = config.get("deploy", "gas_price") def _rpc_post(self, method, params): payload = { @@ -82,10 +83,18 @@ def check(self, addresses): def coinbase(self): return self._rpc_post('eth_coinbase', None) - def create(self, code, from_=config.get("api", "address"), gas=config.get("deploy", "gas"), gas_price=config.get("deploy", "gas_price"), endowment=0): + def create(self, code, from_=None, gas=None, gas_price=None, endowment=0): if not code.startswith('0x'): code = '0x' + code # params = [{'code': code}] + + if gas is None: + gas = self.gas + if gas_price is None: + gas_price = self.gas_price + if from_ is None: + from_ = self.address + params = [{ 'code': code, 'from': from_, @@ -152,13 +161,20 @@ def abi_data(self, fun_name, sig, data): logger.debug("ABI data: %s" % data_abi) return data_abi - def transact(self, dest, fun_name=None, sig='', data=None, gas=config.get("deploy", "gas"), gas_price=config.get("deploy", "gas_price"), value=0, from_=config.get("api", "address")): + def transact(self, dest, fun_name=None, sig='', data=None, gas=None, gas_price=None, value=0, from_=None): if not dest.startswith('0x'): dest = '0x' + dest if fun_name is not None: data = self.abi_data(fun_name, sig, data) + if gas is None: + gas = self.gas + if gas_price is None: + gas_price = self.gas_price + if from_ is None: + from_ = self.address + params = [{ 'to': dest, 'data': data, @@ -167,13 +183,20 @@ def transact(self, dest, fun_name=None, sig='', data=None, gas=config.get("deplo 'value': str(value)}] return self._rpc_post('eth_transact', params) - def call(self, dest, fun_name, sig='', data=None, gas=config.get("deploy", "gas"), gas_price=config.get("deploy", "gas_price"), value=0, from_=config.get("api", "address")): + def call(self, dest, fun_name, sig='', data=None, gas=None, gas_price=None, value=0, from_=None): if not dest.startswith('0x'): dest = '0x' + dest if fun_name is not None: data = self.abi_data(fun_name, sig, data) + if gas is None: + gas = self.gas + if gas_price is None: + gas_price = self.gas_price + if from_ is None: + from_ = self.address + params = [{ 'to': dest, 'data': data, diff --git a/pyepm/deploy.py b/pyepm/deploy.py index 72446d2..6559213 100644 --- a/pyepm/deploy.py +++ b/pyepm/deploy.py @@ -3,7 +3,7 @@ # @Author: caktux # @Date: 2014-12-21 12:44:20 # @Last Modified by: caktux -# @Last Modified time: 2015-02-12 04:41:40 +# @Last Modified time: 2015-02-17 18:41:40 import logging @@ -11,160 +11,165 @@ import api import json import yaml -import config as c -config = c.read_config() logger = logging.getLogger(__name__) from serpent import compile -default_from = config.get('api', 'address') -default_gas = int(config.get('deploy', 'gas')) -default_gas_price = int(config.get('deploy', 'gas_price')) - -def deploy(filename, wait=False): - # Load YAML definitions - definitions = load_yaml(filename) - - logger.info("Parsing %s..." % filename) - path = os.path.dirname(filename) - - for definition in definitions: - for key in definition: - logger.info("%s: " % key) - - if key == 'set': - for variable in definition[key]: - replacement = definition[key][variable] - definitions = replace(variable, definitions, replacement) - logger.debug(definitions) - - if key == 'deploy': - for name in definition[key]: - # Reset default values at each definition - from_ = default_from - gas = default_gas - gas_price = default_gas_price - value = 0 - wait = False - for option in definition[key][name]: - if option == 'contract': - contract = definition[key][name][option] - if option == 'gas': - gas = definition[key][name][option] - if option == 'gas_price': - gas_price = definition[key][name][option] - if option == 'endowment': - value = definition[key][name][option] - if option == 'wait': - wait = definition[key][name][option] - logger.info(" Deploying %s..." % os.path.join(path, contract)) - contract_address = create("%s" % os.path.join(path, contract), gas, gas_price, value, wait) - definitions = replace(name, definitions, contract_address, True) - logger.debug(definitions) - - if key in ['transact', 'call']: - for name in definition[key]: - # Reset default values at each definition - from_ = default_from - to = None - fun_name = None - sig = None - data = '' - gas = default_gas - gas_price = default_gas_price - value = 0 - wait = False - for option in definition[key][name]: - if option == 'from': - from_ = definition[key][name][option] - if option == 'to': - to = definition[key][name][option] - if option == 'fun_name': - fun_name = definition[key][name][option] - if option == 'sig': - sig = definition[key][name][option] - if option == 'data': - dat = definition[key][name][option] - if isinstance(dat, list): - for i, d in enumerate(dat): - if isinstance(d, (basestring)) and not d.startswith("0x") and not d.startswith("$"): - padded = "0x" + d.encode('hex') - definition[key][name][option][i] = u"%s" % padded - logger.info(" Converting '%s' string to %s" % (d, padded)) - data = definition[key][name][option] - if option == 'gas': - gas = definition[key][name][option] - if option == 'gas_price': - gas_price = definition[key][name][option] - if option == 'value': - value = definition[key][name][option] - if option == 'wait': - wait = definition[key][name][option] - logger.info(" %s to %s (%s)..." % ("Transaction" if key == 'transact' else "Call", name, to)) - if data: - logger.info(" with data: %s" % data) - if key == 'transact': - transact(to, from_, fun_name, sig, data, gas, gas_price, value, wait) - elif key == 'call': - call(to, from_, fun_name, sig, data, gas, gas_price, value, wait) - -def create(contract, gas, gas_price, value, wait): - instance = api.Api() - contract = compile(open(contract).read()).encode('hex') - contract_address = instance.create(contract, gas=gas, gas_price=gas_price, endowment=value) - logger.info(" Contract is available at %s" % contract_address) - if wait: - instance.wait_for_next_block(verbose=(True if config.get('misc', 'verbosity') > 1 else False)) - - return contract_address - -def transact(to, from_, fun_name, sig, data, gas, gas_price, value, wait): - instance = api.Api() - result = instance.transact(to, fun_name=fun_name, sig=sig, data=data, gas=gas, gas_price=gas_price, value=value) - logger.info(" Result: %s" % (result if result else "OK")) - if wait: - instance.wait_for_next_block(verbose=(True if config.get('misc', 'verbosity') > 1 else False)) - -def call(to, from_, fun_name, sig, data, gas, gas_price, value, wait): - instance = api.Api() - result = instance.call(to, fun_name=fun_name, sig=sig, data=data, gas=gas, gas_price=gas_price, value=value) - logger.info(" Result: %s" % result) - if wait: - instance.wait_for_next_block(verbose=(True if config.get('misc', 'verbosity') > 1 else False)) - - return result - -def replace(variable, definitions, replacement, isContract=False): - # Replace variables - count = 0 - for repdef in definitions: - for repkey in repdef: - for repname in repdef[repkey]: - if repkey != 'set': - for repoption in repdef[repkey][repname]: - to_replace = repdef[repkey][repname][repoption] - if to_replace == "$%s" % variable: - logger.debug("- Replacing $%s with %s" % (variable, replacement)) - repdef[repkey][repname][repoption] = replacement - count = count + 1 - if repoption == 'data': - for i, repdata in enumerate(to_replace): - if repdata == "$%s" % variable: - logger.debug("- Replacing $%s with %s" % (variable, replacement)) - repdef[repkey][repname][repoption][i] = replacement - count = count + 1 - if count: - logger.info(" %sReplacing $%s with %s (%s)" % ((" " if isContract else ""), variable, replacement, count)) - - return definitions - -def load_yaml(filename): - logger.info("Loading %s..." % filename) - f = open(filename) - data = yaml.load(f) - f.close() - logger.debug(json.dumps(data, indent=4)) - - return data +class Deploy(object): + def __init__(self, filename, config): + self.filename = filename + self.config = config + + def deploy(self, wait=False): + default_from = self.config.get('api', 'address') + default_gas = int(self.config.get('deploy', 'gas')) + default_gas_price = int(self.config.get('deploy', 'gas_price')) + + # Load YAML definitions + definitions = self.load_yaml() + + logger.info("Parsing %s..." % self.filename) + path = os.path.dirname(self.filename) + + for definition in definitions: + for key in definition: + logger.info("%s: " % key) + + if key == 'set': + for variable in definition[key]: + replacement = definition[key][variable] + definitions = self.replace(variable, definitions, replacement) + logger.debug(definitions) + + if key == 'deploy': + for name in definition[key]: + # Reset default values at each definition + from_ = default_from + gas = default_gas + gas_price = default_gas_price + value = 0 + wait = False + for option in definition[key][name]: + if option == 'contract': + contract = definition[key][name][option] + if option == 'from': + from_ = definition[key][name][option] + if option == 'gas': + gas = definition[key][name][option] + if option == 'gas_price': + gas_price = definition[key][name][option] + if option == 'endowment': + value = definition[key][name][option] + if option == 'wait': + wait = definition[key][name][option] + logger.info(" Deploying %s..." % os.path.join(path, contract)) + contract_address = self.create("%s" % os.path.join(path, contract), from_, gas, gas_price, value, wait) + definitions = self.replace(name, definitions, contract_address, True) + logger.debug(definitions) + + if key in ['transact', 'call']: + for name in definition[key]: + # Reset default values at each definition + from_ = default_from + to = None + fun_name = None + sig = None + data = '' + gas = default_gas + gas_price = default_gas_price + value = 0 + wait = False + for option in definition[key][name]: + if option == 'from': + from_ = definition[key][name][option] + if option == 'to': + to = definition[key][name][option] + if option == 'fun_name': + fun_name = definition[key][name][option] + if option == 'sig': + sig = definition[key][name][option] + if option == 'data': + dat = definition[key][name][option] + if isinstance(dat, list): + for i, d in enumerate(dat): + if isinstance(d, (basestring)) and not d.startswith("0x") and not d.startswith("$"): + padded = "0x" + d.encode('hex') + definition[key][name][option][i] = u"%s" % padded + logger.info(" Converting '%s' string to %s" % (d, padded)) + data = definition[key][name][option] + if option == 'gas': + gas = definition[key][name][option] + if option == 'gas_price': + gas_price = definition[key][name][option] + if option == 'value': + value = definition[key][name][option] + if option == 'wait': + wait = definition[key][name][option] + logger.info(" %s to %s (%s)..." % ("Transaction" if key == 'transact' else "Call", name, to)) + if data: + logger.info(" with data: %s" % data) + if key == 'transact': + self.transact(to, from_, fun_name, sig, data, gas, gas_price, value, wait) + elif key == 'call': + self.call(to, from_, fun_name, sig, data, gas, gas_price, value, wait) + + def create(self, contract, from_, gas, gas_price, value, wait): + instance = api.Api(self.config) + contract = compile(open(contract).read()).encode('hex') + contract_address = instance.create(contract, from_=from_, gas=gas, gas_price=gas_price, endowment=value) + logger.info(" Contract is available at %s" % contract_address) + if wait: + instance.wait_for_next_block(verbose=(True if self.config.get('misc', 'verbosity') > 1 else False)) + + return contract_address + + def transact(self, to, from_, fun_name, sig, data, gas, gas_price, value, wait): + instance = api.Api(self.config) + result = instance.transact(to, fun_name=fun_name, sig=sig, data=data, gas=gas, gas_price=gas_price, value=value) + logger.info(" Result: %s" % (result if result else "OK")) + if wait: + instance.wait_for_next_block(verbose=(True if self.config.get('misc', 'verbosity') > 1 else False)) + + def call(self, to, from_, fun_name, sig, data, gas, gas_price, value, wait): + instance = api.Api(self.config) + result = instance.call(to, fun_name=fun_name, sig=sig, data=data, gas=gas, gas_price=gas_price, value=value) + logger.info(" Result: %s" % result) + if wait: + instance.wait_for_next_block(verbose=(True if self.config.get('misc', 'verbosity') > 1 else False)) + + return result + + def replace(self, variable, definitions, replacement, isContract=False): + # Replace variables + count = 0 + for repdef in definitions: + for repkey in repdef: + for repname in repdef[repkey]: + if repkey != 'set': + for repoption in repdef[repkey][repname]: + to_replace = repdef[repkey][repname][repoption] + if to_replace == "$%s" % variable: + logger.debug("- Replacing $%s with %s" % (variable, replacement)) + repdef[repkey][repname][repoption] = replacement + count = count + 1 + if repoption == 'data': + for i, repdata in enumerate(to_replace): + if repdata == "$%s" % variable: + logger.debug("- Replacing $%s with %s" % (variable, replacement)) + repdef[repkey][repname][repoption][i] = replacement + count = count + 1 + if count: + logger.info(" %sReplacing $%s with %s (%s)" % ((" " if isContract else ""), variable, replacement, count)) + + return definitions + + def load_yaml(self): + logger.info("Loading %s..." % self.filename) + f = open(self.filename) + data = yaml.load(f) + f.close() + logger.debug(json.dumps(data, indent=4)) + + return data diff --git a/pyepm/pyepm.py b/pyepm/pyepm.py index 7faace0..21f8811 100644 --- a/pyepm/pyepm.py +++ b/pyepm/pyepm.py @@ -3,7 +3,7 @@ # @Author: caktux # @Date: 2014-12-21 12:44:20 # @Last Modified by: caktux -# @Last Modified time: 2015-01-06 22:08:20 +# @Last Modified time: 2015-02-17 18:04:31 import os import json @@ -11,7 +11,7 @@ import config as c import logging import logging.config -from deploy import * +import deploy logger = logging.getLogger(__name__) from utils import config_dir, configure_logging @@ -105,7 +105,8 @@ def main(): logger.warn("File does not exist: %s" % filename) else: logger.info("Deploying %s..." % filename) - deploy(filename) + deployment = deploy.Deploy(filename, config) + deployment.deploy() if __name__ == '__main__': diff --git a/test/test_api.py b/test/test_api.py index 109da45..f6318d4 100644 --- a/test/test_api.py +++ b/test/test_api.py @@ -3,7 +3,8 @@ import requests from pyepm import config -config.read_config = config.get_default_config +config = config.get_default_config() + from pyepm import api # NOQA base_json_response = {u'jsonrpc': u'2.0', u'id': u'c7c427a5-b6e9-4dbf-b218-a6f9d4f09246'} @@ -22,7 +23,7 @@ def mock_json_response(status_code=200, error=None, result=None): return m def test_api_exception_error_response(mocker): - instance = api.Api() + instance = api.Api(config) mocker.patch('requests.post', return_value=mock_json_response(error={'code': 31337, 'message': 'Too Elite'})) with pytest.raises(api.ApiException) as excinfo: instance.coinbase() @@ -30,7 +31,7 @@ def test_api_exception_error_response(mocker): assert excinfo.value.message == 'Too Elite' def test_api_exception_status_code(mocker): - instance = api.Api() + instance = api.Api(config) mocker.patch('requests.post', return_value=mock_json_response(status_code=404)) with pytest.raises(api.ApiException) as excinfo: instance.coinbase() @@ -38,7 +39,7 @@ def test_api_exception_status_code(mocker): assert excinfo.value.message == 'Error Reason' def mock_rpc(mocker, rpc_fun, rpc_args, json_result, rpc_method, rpc_params): - instance = api.Api() + instance = api.Api(config) mocker.patch('requests.post', return_value=mock_json_response(result=json_result)) mock_rpc_post = mocker.patch.object(instance, '_rpc_post', side_effect=instance._rpc_post) diff --git a/test/test_deploy.py b/test/test_deploy.py index 98f979c..38d67f9 100644 --- a/test/test_deploy.py +++ b/test/test_deploy.py @@ -1,7 +1,9 @@ -from pyepm import deploy +from pyepm import deploy, config +config = config.get_default_config() def test_load_yaml(): - result = deploy.load_yaml('test/fixtures/example.yaml.fixture') + deployment = deploy.Deploy('test/fixtures/example.yaml.fixture', config) + result = deployment.load_yaml() assert result == [ {'set': {'NameReg': '0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2'}}, {'deploy': {'NameCoin': {'contract': 'namecoin.se', 'wait': True},