Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

V1.0.0b10 #154

Merged
merged 79 commits into from
Jul 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
086ed54
convert function wei to class Wei
iamdefinitelyahuman Jul 3, 2019
f4d3b11
bugfix
iamdefinitelyahuman Jul 3, 2019
ec4e197
use Wei in EventDict, add check.equal logic to KwargTuple.__eq__
iamdefinitelyahuman Jul 3, 2019
140d461
first pytest fixtures
iamdefinitelyahuman Jul 3, 2019
dd7d2cf
coverage, hacky but working
iamdefinitelyahuman Jul 3, 2019
5ab1a68
no_call_coverage (pytest equivalent of always_transact=False)
iamdefinitelyahuman Jul 3, 2019
addda6a
show gas profile after tests
iamdefinitelyahuman Jul 3, 2019
720a3c7
save coverage report
iamdefinitelyahuman Jul 3, 2019
0c5cd2e
calculate hashes and avoid re-running tests - working but messy
iamdefinitelyahuman Jul 5, 2019
cf66123
connect to other networks
iamdefinitelyahuman Jul 5, 2019
fd5ee43
cleanup
iamdefinitelyahuman Jul 5, 2019
7fa753a
merge coverage evaluation with pytest isolation - working, messy
iamdefinitelyahuman Jul 6, 2019
ba57b6b
remove functools
iamdefinitelyahuman Jul 6, 2019
a838b0c
coverage - merge, generate, display report all working
iamdefinitelyahuman Jul 6, 2019
1c7dbcf
bugfix - update/coverage
iamdefinitelyahuman Jul 6, 2019
7e59009
do not save new coverage report when nothing has changed
iamdefinitelyahuman Jul 6, 2019
7d2c5f7
much deletion, wow
iamdefinitelyahuman Jul 6, 2019
e926fae
cleanup, move test.run_script to project.scripts.run
iamdefinitelyahuman Jul 6, 2019
60adf20
bugfixes, isolation/updating without coverage
iamdefinitelyahuman Jul 6, 2019
2b247b4
use relative paths
iamdefinitelyahuman Jul 6, 2019
547c784
refactoring, reorganizing
iamdefinitelyahuman Jul 6, 2019
fbff788
disable storage capture outside of console
iamdefinitelyahuman Jul 6, 2019
11a7f7f
f > fp
iamdefinitelyahuman Jul 6, 2019
dcccb1f
raise from None to reduce traceback in pytest output
iamdefinitelyahuman Jul 7, 2019
3f4642a
remove logging from config, add flag to show traceback during tests -…
iamdefinitelyahuman Jul 7, 2019
140ae57
replace format with f-strings
iamdefinitelyahuman Jul 7, 2019
f259aaa
change fixture scope to session
iamdefinitelyahuman Jul 7, 2019
aa0dc8c
bugfix - do not evaluate coverage on temporary contracts
iamdefinitelyahuman Jul 7, 2019
40f1c3f
bugfix - catch changes in parent conftest files
iamdefinitelyahuman Jul 8, 2019
293fd48
ensure module_isolation always runs first
iamdefinitelyahuman Jul 8, 2019
3713f95
properly raise exceptions that aren't VirtualMachineError
iamdefinitelyahuman Jul 8, 2019
c98665f
raise from None
iamdefinitelyahuman Jul 8, 2019
c004807
set accounts on load
iamdefinitelyahuman Jul 8, 2019
ad1eaca
test_isolation always runs before other function scoped fixtures
iamdefinitelyahuman Jul 8, 2019
9ad5a7e
raise from a new function to reduce pytest traceback length
iamdefinitelyahuman Jul 8, 2019
66769a6
use colors when skipping tests with --update flag
iamdefinitelyahuman Jul 9, 2019
0c976f5
do not load rpc when skipping all tests
iamdefinitelyahuman Jul 9, 2019
494c6e1
bugfixes - indexed events, no source
iamdefinitelyahuman Jul 9, 2019
5222dd6
populate accounts on init
iamdefinitelyahuman Jul 9, 2019
e305238
HexString and EthAddress comparison helper classes
iamdefinitelyahuman Jul 10, 2019
b28f1bb
make Wei hashable
iamdefinitelyahuman Jul 11, 2019
107e07e
add @skipcoverage, better handling of skipped tests and when ganache …
iamdefinitelyahuman Jul 13, 2019
1de349c
simplify handling of snapshot on calls-as-tx
iamdefinitelyahuman Jul 13, 2019
ca1b943
save in sessionfinish (remove atexit), properly handle keyboard inter…
iamdefinitelyahuman Jul 13, 2019
ce0d15d
bugfix - not
iamdefinitelyahuman Jul 13, 2019
2c97036
changes to coverage evaluation behaviour, code formatting
iamdefinitelyahuman Jul 13, 2019
5c24fd1
fix report formatting on skipped tests via --update flag
iamdefinitelyahuman Jul 13, 2019
89e4596
remove or update failing tests
iamdefinitelyahuman Jul 14, 2019
986555f
replace FalseyDict with defaultdict
iamdefinitelyahuman Jul 14, 2019
8f036b5
do not load brownie plugin when running tests
iamdefinitelyahuman Jul 14, 2019
618e0e5
remove brownie.types package, move classes to related modules
iamdefinitelyahuman Jul 14, 2019
d6b80e3
update tests
iamdefinitelyahuman Jul 14, 2019
b69b622
ReturnValue unit tests, bugfixes
iamdefinitelyahuman Jul 14, 2019
f5bcfcc
start of plugin tests, so meta
iamdefinitelyahuman Jul 14, 2019
6d84e40
unit testing continues
iamdefinitelyahuman Jul 15, 2019
50a98d7
add support for xfail
iamdefinitelyahuman Jul 15, 2019
82d15ca
bugfix - isolation with update flag
iamdefinitelyahuman Jul 15, 2019
3b3e8f4
improve test.plugin isolation between sessions, unit tests
iamdefinitelyahuman Jul 15, 2019
65d558c
more tests
iamdefinitelyahuman Jul 16, 2019
7fcc0a1
pytest plugin unit tests
iamdefinitelyahuman Jul 16, 2019
fb24425
change organization of methods
iamdefinitelyahuman Jul 17, 2019
1e24e1c
use Wei for TransactionReceipt.value
iamdefinitelyahuman Jul 17, 2019
8283092
docs update - api-network finished, api-types removed
iamdefinitelyahuman Jul 17, 2019
62df171
update docs - api-project
iamdefinitelyahuman Jul 18, 2019
4c6010e
convert skipcoverage to fixture
iamdefinitelyahuman Jul 18, 2019
c78145c
make some methods private
iamdefinitelyahuman Jul 18, 2019
6e1ca87
update api-test docs, minor changes
iamdefinitelyahuman Jul 18, 2019
be7f917
update readme and requirements
iamdefinitelyahuman Jul 18, 2019
d18efa2
rename test_isolation to fn_isolation
iamdefinitelyahuman Jul 19, 2019
c4bed08
apply _to_wei to other value when adding and subtracting Wei
iamdefinitelyahuman Jul 19, 2019
19e47e0
update docs... so much docs...
iamdefinitelyahuman Jul 19, 2019
df29768
improved formatting for call_trace and traceback
iamdefinitelyahuman Jul 19, 2019
4a4ca50
better exception verbosity
iamdefinitelyahuman Jul 20, 2019
1cecfd5
more docs updates
iamdefinitelyahuman Jul 20, 2019
4b7f1ff
docs finished, yay
iamdefinitelyahuman Jul 20, 2019
c529e0c
bugfix
iamdefinitelyahuman Jul 20, 2019
f405bba
bump version, changelog, repo location
iamdefinitelyahuman Jul 20, 2019
bc006b1
Merge pull request #153 from iamdefinitelyahuman/pytest
iamdefinitelyahuman Jul 20, 2019
4025bb5
update links
iamdefinitelyahuman Jul 20, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
1.0.0b10
--------

- Use pytest for unit testing
- remove check module, add check.equals comparison logic to ReturnValue
- Modify coverage evaluation to work with pytest
- remove brownie.types package, move classes to related modules
- replace wei function with Wei class, expand functionality
- add EthAddress and HexString helper classes
- improved formatting for tx.traceback and tx.call_trace

1.0.0b9
-------

Expand Down
10 changes: 3 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Brownie

[![Pypi Status](https://img.shields.io/pypi/v/eth-brownie.svg)](https://pypi.org/project/eth-brownie/) [![Build Status](https://img.shields.io/travis/com/HyperLink-Technology/brownie.svg)](https://travis-ci.com/HyperLink-Technology/brownie) [![Docs Status](https://readthedocs.org/projects/eth-brownie/badge/?version=latest)](https://eth-brownie.readthedocs.io/en/latest/) [![Coverage Status](https://coveralls.io/repos/github/HyperLink-Technology/brownie/badge.svg?branch=master)](https://coveralls.io/github/HyperLink-Technology/brownie?branch=master)
[![Pypi Status](https://img.shields.io/pypi/v/eth-brownie.svg)](https://pypi.org/project/eth-brownie/) [![Build Status](https://img.shields.io/travis/com/iamdefinitelyahuman/brownie.svg)](https://travis-ci.com/iamdefinitelyahuman/brownie) [![Docs Status](https://readthedocs.org/projects/eth-brownie/badge/?version=latest)](https://eth-brownie.readthedocs.io/en/latest/) [![Coverage Status](https://coveralls.io/repos/github/iamdefinitelyahuman/brownie/badge.svg?branch=master)](https://coveralls.io/github/iamdefinitelyahuman/brownie?branch=master)

Brownie is a Python framework for deploying, testing and interacting with Ethereum smart contracts.

Expand Down Expand Up @@ -50,15 +50,11 @@ To run the tests, first install the developer dependencies:
$ pip install -r requirements-dev.txt
```

Then use ``tox`` to run the complete suite against the full set of build targets, or ``py.test`` to run specific tests against a specific version of Python.
Then use ``tox`` to run the complete suite against the full set of build targets, or ``pytest`` to run tests against a specific version of Python. If you are using ``pytest`` you must include the ``-p no:pytest-brownie`` flag to prevent it from loading the Brownie plugin.

## Contributing

Help is always appreciated! In particular, Brownie needs work in the following areas before we can comfortably take it out of beta:

* More tests

Feel free to open an issue if you find a problem, or a pull request if you've solved an issue.
Help is always appreciated! Feel free to open an issue if you find a problem, or a pull request if you've solved an issue.

## License

Expand Down
8 changes: 4 additions & 4 deletions brownie/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
)
from .project import (
compile_source,
run,
__brownie_import_all__
)
from brownie.gui import Gui
from brownie.test import check
from brownie._config import CONFIG as config
from brownie.types.convert import wei
from brownie.convert import Wei

__all__ = [
'accounts',
Expand All @@ -25,9 +25,9 @@
'web3',
'project',
'__brownie_import_all__',
'check',
'compile_source',
'wei',
'run',
'Wei',
'config',
'Gui'
]
72 changes: 48 additions & 24 deletions brownie/_config.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,58 @@
#!/usr/bin/python3

from collections import defaultdict
import json
from pathlib import Path
import shutil
import sys

from brownie.types.types import (
FalseyDict,
StrictDict,
_Singleton
)
from brownie._singleton import _Singleton


REPLACE = ['active_network', 'networks']
IGNORE = ['active_network', 'folders', 'logging']
IGNORE = ['active_network', 'folders']


class ConfigDict(dict):
'''Dict subclass that prevents adding new keys when locked'''

def __init__(self, values={}):
self._locked = False
super().__init__()
self.update(values)

def __setitem__(self, key, value):
if self._locked and key not in self:
raise KeyError(f"{key} is not a known config setting")
if type(value) is dict:
value = ConfigDict(value)
super().__setitem__(key, value)

def update(self, arg):
for k, v in arg.items():
self.__setitem__(k, v)

def _lock(self):
'''Locks the dict so that new keys cannot be added'''
for v in [i for i in self.values() if type(i) is ConfigDict]:
v._lock()
self._locked = True

def _unlock(self):
'''Unlocks the dict so that new keys can be added'''
for v in [i for i in self.values() if type(i) is ConfigDict]:
v._unlock()
self._locked = False


def _load_default_config():
'''Loads the default configuration settings from brownie/data/config.json'''
with Path(__file__).parent.joinpath("data/config.json").open() as f:
config = _Singleton("Config", (StrictDict,), {})(json.load(f))
with Path(__file__).parent.joinpath("data/config.json").open() as fp:
config = _Singleton("Config", (ConfigDict,), {})(json.load(fp))
config['folders'] = {
'brownie': str(Path(__file__).parent),
'project': None
}
config['active_network'] = {'name': None}
# set logging
try:
config['logging'] = config['logging'][sys.argv[1]]
config['logging'].setdefault('tx', 0)
config['logging'].setdefault('exc', 0)
for k, v in [(k, v) for k, v in config['logging'].items() if type(v) is list]:
config['logging'][k] = v[1 if '--verbose' in sys.argv else 0]
except Exception:
config['logging'] = {"tx": 1, "exc": 1}
return config


Expand All @@ -45,8 +65,8 @@ def load_project_config(project_path):
CONFIG['folders']['project'] = str(project_path)
config_path = project_path.joinpath("brownie-config.json")
try:
with config_path.open() as f:
_recursive_update(CONFIG, json.load(f), [])
with config_path.open() as fp:
_recursive_update(CONFIG, json.load(fp), [])
except FileNotFoundError:
shutil.copy(
str(Path(CONFIG['folders']['brownie']).joinpath("data/config.json")),
Expand Down Expand Up @@ -75,7 +95,7 @@ def modify_network_config(network=None):
if not CONFIG['active_network']['broadcast_reverting_tx']:
print("WARNING: Reverting transactions will NOT be broadcasted.")
except KeyError:
raise KeyError("Network '{}' is not defined in config.json".format(network))
raise KeyError(f"Network '{network}' is not defined in config.json")
finally:
CONFIG._lock()

Expand All @@ -91,13 +111,17 @@ def _recursive_update(original, new, base):
original[k] = new[k]
for k in [i for i in original if i not in new and not set(base+[i]).intersection(IGNORE)]:
print(
"WARNING: Value '{}' not found in the config file for this project."
" The default setting has been used.".format(".".join(base+[k]))
f"WARNING: '{'.'.join(base+[k])}' not found in the config file for this project."
" The default setting has been used."
)


def update_argv_from_docopt(args):
ARGV.update(dict((k.lstrip("-"), v) for k, v in args.items()))


# create argv object
ARGV = _Singleton("Argv", (FalseyDict,), {})()
ARGV = _Singleton("Argv", (defaultdict,), {})(lambda: None)

# load config
CONFIG = _load_default_config()
11 changes: 11 additions & 0 deletions brownie/_singleton.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/python3


class _Singleton(type):

_instances = {}

def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super(_Singleton, cls).__call__(*args, **kwargs)
return cls._instances[cls]
3 changes: 1 addition & 2 deletions brownie/cli/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from brownie.exceptions import ProjectNotFound
from brownie._config import ARGV

__version__ = "1.0.0b9" # did you change this in docs/conf.py as well?
__version__ = "1.0.0b10" # did you change this in docs/conf.py as well?

__doc__ = """Usage: brownie <command> [<args>...] [options <args>]

Expand All @@ -21,7 +21,6 @@
gui Load the GUI to view opcodes and test coverage
init Initialize a new brownie project
run Run a script in the /scripts folder
test Run test scripts in the /tests folder

Options:
--help -h Display this message
Expand Down
2 changes: 1 addition & 1 deletion brownie/cli/compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ def main():
if args['--all']:
shutil.rmtree(build_path, ignore_errors=True)
project.load(project_path)
print("Brownie project has been compiled at {}".format(build_path))
print(f"Brownie project has been compiled at {build_path}")
4 changes: 2 additions & 2 deletions brownie/cli/console.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from brownie import network, project
from brownie.cli.utils.console import Console
from brownie._config import ARGV, CONFIG
from brownie._config import ARGV, CONFIG, update_argv_from_docopt


__doc__ = f"""Usage: brownie console [options]
Expand All @@ -21,7 +21,7 @@

def main():
args = docopt(__doc__)
ARGV._update_from_args(args)
update_argv_from_docopt(args)

project.load()
network.connect(ARGV['network'])
Expand Down
16 changes: 7 additions & 9 deletions brownie/cli/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,30 @@

from docopt import docopt

from brownie import network, project, run
from brownie._config import ARGV, CONFIG, update_argv_from_docopt

from brownie import network, project
from brownie.test.main import run_script
from brownie._config import ARGV, CONFIG


__doc__ = """Usage: brownie run <filename> [<function>] [options]
__doc__ = f"""Usage: brownie run <filename> [<function>] [options]

Arguments:
<filename> The name of the script to run
[<function>] The function to call (default is main)

Options:
--network [name] Use a specific network (default {})
--network [name] Use a specific network (default {CONFIG['network_defaults']['name']})
--gas -g Display gas profile for function calls
--verbose -v Enable verbose reporting
--tb -t Show entire python traceback on exceptions
--help -h Display this message

Use run to execute scripts for contract deployment, to automate common
interactions, or for gas profiling.""".format(CONFIG['network_defaults']['name'])
interactions, or for gas profiling."""


def main():
args = docopt(__doc__)
ARGV._update_from_args(args)
update_argv_from_docopt(args)
project.load()
network.connect(ARGV['network'])
run_script(args['<filename>'], args['<function>'] or "main", gas_profile=ARGV['gas'])
run(args['<filename>'], args['<function>'] or "main", gas_profile=ARGV['gas'])
37 changes: 0 additions & 37 deletions brownie/cli/test.py

This file was deleted.

9 changes: 3 additions & 6 deletions brownie/cli/utils/console.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
#!/usr/bin/python3

import atexit
import builtins
import code
from pathlib import Path
import sys

import brownie
from brownie.test.main import run_script
from . import color
from brownie._config import CONFIG

Expand All @@ -22,10 +20,9 @@ class Console(code.InteractiveConsole):

def __init__(self):
locals_dict = dict((i, getattr(brownie, i)) for i in brownie.__all__)
locals_dict['run'] = run_script
locals_dict['dir'] = self._dir
del locals_dict['project']

builtins.dir = self._dir
self._stdout_write = sys.stdout.write
sys.stdout.write = self._console_write

Expand All @@ -37,7 +34,7 @@ def __init__(self):
pass
super().__init__(locals_dict)

# replaces builtin dir method, for simplified and colorful output
# console dir method, for simplified and colorful output
def _dir(self, obj=None):
if obj is None:
results = [(k, v) for k, v in self.locals.items() if not k.startswith('_')]
Expand All @@ -55,7 +52,7 @@ def _console_write(self, text):
text = color.pretty_dict(obj)
elif obj and type(obj) in (tuple, list, set):
text = color.pretty_list(obj)
except SyntaxError:
except (SyntaxError, NameError):
pass
return self._stdout_write(text)

Expand Down
Loading