refactored configuration

Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>
This commit is contained in:
Jürgen Eckel 2022-03-24 00:21:54 +01:00
parent 77c1b49433
commit cb5a19f4ad
23 changed files with 767 additions and 758 deletions

View File

@ -3,127 +3,6 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0
import copy
import logging
import os
from planetmint.log import DEFAULT_LOGGING_CONFIG as log_config
from planetmint.version import __version__ # noqa
# from functools import reduce
# PORT_NUMBER = reduce(lambda x, y: x * y, map(ord, 'Planetmint')) % 2**16
# basically, the port number is 9984
# The following variable is used by `planetmint configure` to
# prompt the user for database values. We cannot rely on
# _base_database_localmongodb.keys() because dicts are unordered.
# I tried to configure
_database_keys_map = { # TODO Check if it is working after removing 'name' field
'tarantool_db': ('host', 'port'),
'localmongodb': ('host', 'port', 'name')
}
_base_database_localmongodb = {
'host': 'localhost',
'port': 27017,
'name': 'bigchain',
'replicaset': None,
'login': None,
'password': None,
}
_database_localmongodb = {
'backend': 'localmongodb',
'connection_timeout': 5000,
'max_tries': 3,
'ssl': False,
'ca_cert': None,
'certfile': None,
'keyfile': None,
'keyfile_passphrase': None,
'crlfile': None,
}
_database_localmongodb.update(_base_database_localmongodb)
_base_database_tarantool_local_db = { # TODO Rewrite this configs for tarantool usage
'host': 'localhost',
'port': 3301,
'username': None,
'password': None,
"connect_now": True,
"encoding": "utf-8"
}
init_config = {
"init_file": "init_db.txt",
"relative_path": os.path.dirname(os.path.abspath(__file__)) + "/backend/tarantool/"
}
drop_config = {
"drop_file": "drop_db.txt", # planetmint/backend/tarantool/init_db.txt
"relative_path": os.path.dirname(os.path.abspath(__file__)) + "/backend/tarantool/"
}
_database_tarantool = {
'backend': 'tarantool_db',
'connection_timeout': 5000,
'max_tries': 3,
"reconnect_delay": 0.5,
"ctl_config": {
"login": "guest",
"host": "guest@127.0.0.1:3301",
"service": "tarantoolctl connect",
"init_config": init_config,
"drop_config": drop_config
}
}
_database_tarantool.update(_base_database_tarantool_local_db)
_database_map = {
'tarantool_db': _database_tarantool,
'localmongodb': _database_localmongodb
}
config = {
'server': {
# Note: this section supports all the Gunicorn settings:
# - http://docs.gunicorn.org/en/stable/settings.html
'bind': 'localhost:9984',
'loglevel': logging.getLevelName(
log_config['handlers']['console']['level']).lower(),
'workers': None, # if None, the value will be cpu_count * 2 + 1
},
'wsserver': {
'scheme': 'ws',
'host': 'localhost',
'port': 9985,
'advertised_scheme': 'ws',
'advertised_host': 'localhost',
'advertised_port': 9985,
},
'tendermint': {
'host': 'localhost',
'port': 26657,
'version': 'v0.31.5', # look for __tm_supported_versions__
},
# TODO Maybe remove hardcode configs for tarantool (review)
'database': _database_map,
'log': {
'file': log_config['handlers']['file']['filename'],
'error_file': log_config['handlers']['errors']['filename'],
'level_console': logging.getLevelName(
log_config['handlers']['console']['level']).lower(),
'level_logfile': logging.getLevelName(
log_config['handlers']['file']['level']).lower(),
'datefmt_console': log_config['formatters']['console']['datefmt'],
'datefmt_logfile': log_config['formatters']['file']['datefmt'],
'fmt_console': log_config['formatters']['console']['format'],
'fmt_logfile': log_config['formatters']['file']['format'],
'granular_levels': {},
},
}
# We need to maintain a backup copy of the original config dict in case
# the user wants to reconfigure the node. Check ``planetmint.config_utils``
# for more info.
_config = copy.deepcopy(config) # TODO Check what to do with those imports
from planetmint.common.transaction import Transaction # noqa
from planetmint import models # noqa
from planetmint.upsert_validator import ValidatorElection # noqa

View File

@ -5,8 +5,7 @@
import logging
from importlib import import_module
from planetmint.backend.utils import get_planetmint_config_value
from planetmint.config import Config
BACKENDS = { # This is path to MongoDBClass
'tarantool_db': 'planetmint.backend.tarantool.connection.TarantoolDB',
@ -15,23 +14,22 @@ BACKENDS = { # This is path to MongoDBClass
logger = logging.getLogger(__name__)
# backend = get_planetmint_config_value("backend")
# if not backend:
# backend = 'tarantool_db'
#
# modulepath, _, class_name = BACKENDS[backend].rpartition('.')
# current_backend = getattr(import_module(modulepath), class_name)
def Connection(host: str = None, port: int = None, login: str = None, password: str = None, backend: str = None,
**kwargs):
# TODO To add parser for **kwargs, when mongodb is used
backend = backend or get_planetmint_config_value("backend") if not kwargs.get("backend") else kwargs["backend"]
host = host or get_planetmint_config_value("host") if kwargs.get("host") is None else kwargs["host"]
port = port or get_planetmint_config_value("port") if not kwargs.get("port") is None else kwargs["port"]
login = login or get_planetmint_config_value("login") if not kwargs.get("login") is None else kwargs["login"]
password = password or get_planetmint_config_value("password")
backend = backend
if not backend and kwargs and kwargs["backend"]:
backend = kwargs["backend"]
if backend and backend != Config().get()["database"]["backend"]:
Config().init_config(backend)
else:
backend = Config().get()["database"]["backend"]
host = host or Config().get()["database"]["host"] if not kwargs.get("host") else kwargs["host"]
port = port or Config().get()['database']['port'] if not kwargs.get("port") else kwargs["port"]
login = login or Config().get()["database"]["login"] if not kwargs.get("login") else kwargs["login"]
password = password or Config().get()["database"]["password"]
if backend == "tarantool_db":
modulepath, _, class_name = BACKENDS[backend].rpartition('.')
@ -40,17 +38,17 @@ def Connection(host: str = None, port: int = None, login: str = None, password:
elif backend == "localmongodb":
modulepath, _, class_name = BACKENDS[backend].rpartition('.')
Class = getattr(import_module(modulepath), class_name)
dbname = _kwargs_parser(key="name", kwargs=kwargs) or get_planetmint_config_value('name')
replicaset = _kwargs_parser(key="replicaset", kwargs=kwargs) or get_planetmint_config_value('replicaset')
ssl = _kwargs_parser(key="ssl", kwargs=kwargs) or get_planetmint_config_value('ssl', False)
login = login or get_planetmint_config_value('login') if _kwargs_parser(key="login", kwargs=kwargs) is None else _kwargs_parser(key="login", kwargs=kwargs)
password = password or get_planetmint_config_value('password') if _kwargs_parser(key="password", kwargs=kwargs) is None else _kwargs_parser(key="password", kwargs=kwargs)
ca_cert = _kwargs_parser(key="ca_cert", kwargs=kwargs) or get_planetmint_config_value('ca_cert')
certfile = _kwargs_parser(key="certfile", kwargs=kwargs) or get_planetmint_config_value('certfile')
keyfile = _kwargs_parser(key="keyfile", kwargs=kwargs) or get_planetmint_config_value('keyfile')
keyfile_passphrase = _kwargs_parser(key="keyfile_passphrase", kwargs=kwargs) or get_planetmint_config_value('keyfile_passphrase', None)
crlfile = _kwargs_parser(key="crlfile", kwargs=kwargs) or get_planetmint_config_value('crlfile')
print( Config().get())
dbname = _kwargs_parser(key="name", kwargs=kwargs) or Config().get()['database']['name']
replicaset = _kwargs_parser(key="replicaset", kwargs=kwargs) or Config().get()['database']['replicaset']
ssl = _kwargs_parser(key="ssl", kwargs=kwargs) or Config().get()['database']['ssl']
login = login or Config().get()['database']['login'] if _kwargs_parser(key="login", kwargs=kwargs) is None else _kwargs_parser(key="login", kwargs=kwargs)
password = password or Config().get()['database']['password'] if _kwargs_parser(key="password", kwargs=kwargs) is None else _kwargs_parser(key="password", kwargs=kwargs)
ca_cert = _kwargs_parser(key="ca_cert", kwargs=kwargs) or Config().get()['database']['ca_cert']
certfile = _kwargs_parser(key="certfile", kwargs=kwargs) or Config().get()['database']['certfile']
keyfile = _kwargs_parser(key="keyfile", kwargs=kwargs) or Config().get()['database']['keyfile']
keyfile_passphrase = _kwargs_parser(key="keyfile_passphrase", kwargs=kwargs) or Config().get()['database']['keyfile_passphrase']
crlfile = _kwargs_parser(key="crlfile", kwargs=kwargs) or Config().get()['database']['crlfile']
max_tries = _kwargs_parser(key="max_tries", kwargs=kwargs)
connection_timeout = _kwargs_parser(key="connection_timeout", kwargs=kwargs)
@ -65,3 +63,4 @@ def _kwargs_parser(key, kwargs):
if kwargs.get(key):
return kwargs[key]
return None

View File

@ -4,15 +4,13 @@
# Code is Apache-2.0 and docs are CC-BY-4.0
import logging
import planetmint
from ssl import CERT_REQUIRED
import pymongo
from planetmint.config import Config
from planetmint.backend.exceptions import (DuplicateKeyError,
OperationError,
ConnectionError)
from planetmint.backend.utils import get_planetmint_config_value
from planetmint.common.exceptions import ConfigurationError
from planetmint.utils import Lazy
@ -42,7 +40,7 @@ class Connection:
configuration's ``database`` settings
"""
dbconf = planetmint.config['database']
dbconf = Config().get()['database']
self.host = host or dbconf['host']
self.port = port or dbconf['port']
@ -112,15 +110,19 @@ class LocalMongoDBConnection(Connection):
"""
super().__init__(**kwargs)
self.replicaset = replicaset or get_planetmint_config_value('replicaset')
self.ssl = ssl if ssl is not None else get_planetmint_config_value('ssl', False)
self.login = login or get_planetmint_config_value('login')
self.password = password or get_planetmint_config_value('password')
self.ca_cert = ca_cert or get_planetmint_config_value('ca_cert')
self.certfile = certfile or get_planetmint_config_value('certfile')
self.keyfile = keyfile or get_planetmint_config_value('keyfile')
self.keyfile_passphrase = keyfile_passphrase or get_planetmint_config_value('keyfile_passphrase')
self.crlfile = crlfile or get_planetmint_config_value('crlfile')
self.replicaset = replicaset or Config().get()['database']['replicaset']
self.ssl = ssl if ssl is not None else Config().get()['database']['ssl']
self.login = login or Config().get()['database']['login']
self.password = password or Config().get()['database']['password']
self.ca_cert = ca_cert or Config().get()['database']['ca_cert']
self.certfile = certfile or Config().get()['database']['certfile']
self.keyfile = keyfile or Config().get()['database']['keyfile']
self.keyfile_passphrase = keyfile_passphrase or Config().get()['database']['keyfile_passphrase']
self.crlfile = crlfile or Config().get()['database']['crlfile']
if not self.ssl :
self.ssl = False
if not self.keyfile_passphrase:
self.keyfile_passphrase = None
@property
def db(self):

View File

@ -79,7 +79,7 @@ def init_database(connection=None, dbname=None): # FIXME HERE IS INIT DATABASE
"""
connection = connection or Connection()
dbname = dbname or planetmint.config['database']['name']
dbname = dbname or Config().get()['database']['name']
create_database(connection, dbname)
create_tables(connection, dbname)
@ -97,7 +97,7 @@ def validate_language_key(obj, key):
Raises:
ValidationError: will raise exception in case language is not valid.
"""
backend = planetmint.config['database']['backend']
backend = Config().get()['database']['backend']
if backend == 'localmongodb':
data = obj.get(key, {})

View File

@ -8,9 +8,9 @@ from importlib import import_module
from itertools import repeat
import tarantool
from planetmint.config import Config
from planetmint.backend.exceptions import ConnectionError
from planetmint.backend.utils import get_planetmint_config_value, get_planetmint_config_value_or_key_error
# BACKENDS = { # This is path to MongoDBClass
# 'tarantool_db': 'planetmint.backend.connection_tarantool.TarantoolDB',
@ -41,16 +41,16 @@ class TarantoolDB:
def drop_database(self):
from planetmint.backend.tarantool.utils import run
config = get_planetmint_config_value_or_key_error("ctl_config")
drop_config = config["drop_config"]
db_config = Config().get()["database"]
drop_config = db_config["drop_config"]
f_path = "%s%s" % (drop_config["relative_path"], drop_config["drop_file"])
commands = self.__read_commands(file_path=f_path)
run(commands=commands, config=config)
run(commands=commands, config=db_config)
def init_database(self):
from planetmint.backend.tarantool.utils import run
config = get_planetmint_config_value_or_key_error("ctl_config")
init_config = config["init_config"]
db_config = Config().get()["database"]
init_config = db_config["init_config"]
f_path = "%s%s" % (init_config["relative_path"], init_config["init_file"])
commands = self.__read_commands(file_path=f_path)
run(commands=commands, config=config)
run(commands=commands, config=db_config)

View File

@ -3,8 +3,6 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0
import planetmint
class ModuleDispatchRegistrationError(Exception):
"""Raised when there is a problem registering dispatched functions for a
@ -29,12 +27,3 @@ def module_dispatch_registrar(module):
return wrapper
return dispatch_wrapper
def get_planetmint_config_value(key, default_value=None):
print(planetmint.config["database"]) # backend ,po rt
return planetmint.config['database'].get(key, default_value)
def get_planetmint_config_value_or_key_error(key):
return planetmint.config['database'][key]

View File

@ -34,7 +34,7 @@ from planetmint.log import setup_logging
from planetmint.tendermint_utils import public_key_from_base64
from planetmint.commands.election_types import elections
from planetmint.version import __tm_supported_versions__
from planetmint.config import Config
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@ -51,9 +51,9 @@ def run_show_config(args):
# TODO Proposal: remove the "hidden" configuration. Only show config. If
# the system needs to be configured, then display information on how to
# configure the system.
config = copy.deepcopy(planetmint.config)
del config['CONFIGURED']
print(json.dumps(config, indent=4, sort_keys=True))
_config = Config().get()
del _config['CONFIGURED']
print(json.dumps(_config, indent=4, sort_keys=True))
@configure_planetmint
@ -72,14 +72,13 @@ def run_configure(args):
if want != 'y':
return
conf = copy.deepcopy(planetmint.config)
Config().init_config( args.backend )
conf = Config().get()
# select the correct config defaults based on the backend
print('Generating default configuration for backend {}'
.format(args.backend), file=sys.stderr)
database_keys = planetmint._database_keys_map[args.backend]
conf['database'] = planetmint._database_map[args.backend]
database_keys = Config().get_db_key_map( args.backend )
if not args.yes:
for key in ('bind', ):
val = conf['server'][key]
@ -101,6 +100,8 @@ def run_configure(args):
planetmint.config_utils.write_config(conf, config_path)
else:
print(json.dumps(conf, indent=4, sort_keys=True))
Config().set(conf)
print('Configuration written to {}'.format(config_path), file=sys.stderr)
print('Ready to go!', file=sys.stderr)

View File

@ -7,7 +7,7 @@ import time
import re
import rapidjson
import planetmint
from planetmint.config import Config
from planetmint.common.exceptions import ValidationError
@ -72,7 +72,7 @@ def validate_txn_obj(obj_name, obj, key, validation_fun):
Raises:
ValidationError: `validation_fun` will raise exception on failure
"""
backend = planetmint.config['database']['backend']
backend = Config().get()['database']['backend']
if backend == 'localmongodb':
data = obj.get(key, {})

140
planetmint/config.py Normal file
View File

@ -0,0 +1,140 @@
import copy
import logging
import os
from planetmint.log import DEFAULT_LOGGING_CONFIG as log_config
from planetmint.version import __version__ # noqa
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]
class Config(metaclass=Singleton):
def __init__(self):
# from functools import reduce
# PORT_NUMBER = reduce(lambda x, y: x * y, map(ord, 'Planetmint')) % 2**16
# basically, the port number is 9984
# The following variable is used by `planetmint configure` to
# prompt the user for database values. We cannot rely on
# _base_database_localmongodb.keys() because dicts are unordered.
# I tried to configure
db = 'tarantool_db'
self.__private_database_keys_map = { # TODO Check if it is working after removing 'name' field
'tarantool_db': ('host', 'port'),
'localmongodb': ('host', 'port', 'name')
}
self.__private_database_localmongodb = {
'backend': 'localmongodb',
'host': 'localhost',
'port': 27017,
'name': 'bigchain',
'replicaset': None,
'login': None,
'password': None,
'connection_timeout': 5000,
'max_tries': 3,
'ssl': False,
'ca_cert': None,
'certfile': None,
'keyfile': None,
'keyfile_passphrase': None,
'crlfile': None
}
self.__private_init_config = {
"init_file": "init_db.txt",
"relative_path": os.path.dirname(os.path.abspath(__file__)) + "/backend/tarantool/"
}
self.__private_drop_config = {
"drop_file": "drop_db.txt", # planetmint/backend/tarantool/init_db.txt
"relative_path": os.path.dirname(os.path.abspath(__file__)) + "/backend/tarantool/"
}
self.__private_database_tarantool = {
'backend': 'tarantool_db',
'connection_timeout': 5000,
'max_tries': 3,
'name': 'bigchain',
"reconnect_delay": 0.5,
'host': 'localhost',
'port': 3301,
"connect_now": True,
"encoding": "utf-8",
"login": "guest",
'password': None,
"service": "tarantoolctl connect",
"init_config": self.__private_init_config,
"drop_config": self.__private_drop_config,
'host': 'localhost',
'port': 3301,
"connect_now": True,
"encoding": "utf-8"
}
self.__private_database_map = {
'tarantool_db': self.__private_database_tarantool,
'localmongodb': self.__private_database_localmongodb
}
self.__private_config = {
'server': {
# Note: this section supports all the Gunicorn settings:
# - http://docs.gunicorn.org/en/stable/settings.html
'bind': 'localhost:9984',
'loglevel': logging.getLevelName(
log_config['handlers']['console']['level']).lower(),
'workers': None, # if None, the value will be cpu_count * 2 + 1
},
'wsserver': {
'scheme': 'ws',
'host': 'localhost',
'port': 9985,
'advertised_scheme': 'ws',
'advertised_host': 'localhost',
'advertised_port': 9985,
},
'tendermint': {
'host': 'localhost',
'port': 26657,
'version': 'v0.31.5', # look for __tm_supported_versions__
},
# TODO Maybe remove hardcode configs for tarantool (review)
'database': self.__private_database_map,
'log': {
'file': log_config['handlers']['file']['filename'],
'error_file': log_config['handlers']['errors']['filename'],
'level_console': logging.getLevelName(
log_config['handlers']['console']['level']).lower(),
'level_logfile': logging.getLevelName(
log_config['handlers']['file']['level']).lower(),
'datefmt_console': log_config['formatters']['console']['datefmt'],
'datefmt_logfile': log_config['formatters']['file']['datefmt'],
'fmt_console': log_config['formatters']['console']['format'],
'fmt_logfile': log_config['formatters']['file']['format'],
'granular_levels': {},
},
}
self._private_real_config = copy.deepcopy(self.__private_config)
# select the correct config defaults based on the backend
self._private_real_config['database'] = self.__private_database_map[db]
def init_config(self, db ):
self._private_real_config = copy.deepcopy(self.__private_config)
# select the correct config defaults based on the backend
self._private_real_config['database'] = self.__private_database_map[db]
return self._private_real_config
def get(self):
return self._private_real_config
def set(self, config):
self._private_real_config = config
def get_db_key_map(sefl, db):
return sefl.__private_database_keys_map[db]
def get_db_map(sefl, db):
return sefl.__private_database_map[db]

View File

@ -22,13 +22,10 @@ import json
import logging
import collections.abc
from functools import lru_cache
from pkg_resources import iter_entry_points, ResolutionError
from planetmint.common import exceptions
import planetmint
from planetmint.config import Config
from planetmint.validation import BaseValidationRules
# TODO: move this to a proper configuration file for logging
@ -192,10 +189,11 @@ def set_config(config):
Any previous changes made to ``planetmint.config`` will be lost.
"""
# Deep copy the default config into planetmint.config
planetmint.config = copy.deepcopy(planetmint._config)
_config = Config().get() #copy.deepcopy(planetmint._config)
# Update the default config with whatever is in the passed config
update(planetmint.config, update_types(config, planetmint.config))
planetmint.config['CONFIGURED'] = True
update(_config, update_types(config, _config))
_config['CONFIGURED'] = True
Config().set( _config )
def update_config(config):
@ -207,9 +205,11 @@ def update_config(config):
to the default config
"""
_config = Config().get()
# Update the default config with whatever is in the passed config
update(planetmint.config, update_types(config, planetmint.config))
planetmint.config['CONFIGURED'] = True
update(_config, update_types(config, _config))
_config['CONFIGURED'] = True
Config().set( _config )
def write_config(config, filename=None):
@ -228,7 +228,7 @@ def write_config(config, filename=None):
def is_configured():
return bool(planetmint.config.get('CONFIGURED'))
return bool(Config().get().get('CONFIGURED'))
def autoconfigure(filename=None, config=None, force=False):
@ -240,7 +240,7 @@ def autoconfigure(filename=None, config=None, force=False):
return
# start with the current configuration
newconfig = planetmint.config
newconfig = Config().get()
# update configuration from file
try:

View File

@ -22,6 +22,7 @@ except ImportError:
import requests
import planetmint
from planetmint.config import Config
from planetmint import backend, config_utils, fastquery
from planetmint.models import Transaction
from planetmint.common.exceptions import (SchemaValidationError,
@ -65,17 +66,17 @@ class Planetmint(object):
self.mode_list = (BROADCAST_TX_ASYNC,
BROADCAST_TX_SYNC,
self.mode_commit)
self.tendermint_host = planetmint.config['tendermint']['host']
self.tendermint_port = planetmint.config['tendermint']['port']
self.tendermint_host = Config().get()['tendermint']['host']
self.tendermint_port = Config().get()['tendermint']['port']
self.endpoint = 'http://{}:{}/'.format(self.tendermint_host, self.tendermint_port)
validationPlugin = planetmint.config.get('validation_plugin')
validationPlugin = Config().get().get('validation_plugin')
if validationPlugin:
self.validation = config_utils.load_validation_plugin(validationPlugin)
else:
self.validation = BaseValidationRules
# planetmint.backend.tarantool.connection_tarantool.connect(**planetmint.config['database'])
# planetmint.backend.tarantool.connection_tarantool.connect(**Config().get()['database'])
self.connection = connection if connection else planetmint.backend.Connection().get_connection()
def post_transaction(self, transaction, mode):

View File

@ -84,7 +84,7 @@ def setup_logging():
"""
logging_configs = DEFAULT_LOGGING_CONFIG
new_logging_configs = planetmint.config['log']
new_logging_configs = Config().get()['log']
if 'file' in new_logging_configs:
filename = new_logging_configs['file']

View File

@ -8,7 +8,7 @@ import setproctitle
from abci import TmVersion, ABCI
import planetmint
from planetmint.config import Config
from planetmint.lib import Planetmint
from planetmint.core import App
from planetmint.parallel_validation import ParallelValidationApp
@ -42,13 +42,13 @@ def start(args):
exchange = Exchange()
# start the web api
app_server = server.create_server(
settings=planetmint.config['server'],
log_config=planetmint.config['log'],
settings=Config().get()['server'],
log_config=Config().get()['log'],
planetmint_factory=Planetmint)
p_webapi = Process(name='planetmint_webapi', target=app_server.run, daemon=True)
p_webapi.start()
logger.info(BANNER.format(planetmint.config['server']['bind']))
logger.info(BANNER.format(Config().get()['server']['bind']))
# start websocket server
p_websocket_server = Process(name='planetmint_ws',
@ -68,7 +68,7 @@ def start(args):
setproctitle.setproctitle('planetmint')
# Start the ABCIServer
abci = ABCI(TmVersion(planetmint.config['tendermint']['version']))
abci = ABCI(TmVersion(Config().get()['tendermint']['version']))
if args.experimental_parallel_validation:
app = ABCIServer(
app=ParallelValidationApp(

View File

@ -2,7 +2,8 @@ import base64
import binascii
import codecs
import planetmint
from planetmint.config import Config
from abci import types_v0_22_8, types_v0_31_5, TmVersion
from planetmint.common.exceptions import InvalidPublicKey, BigchainDBError
@ -11,7 +12,7 @@ def encode_validator(v):
ed25519_public_key = v['public_key']['value']
# NOTE: tendermint expects public to be encoded in go-amino format
try:
version = TmVersion(planetmint.config["tendermint"]["version"])
version = TmVersion(Config().get()["tendermint"]["version"])
except ValueError:
raise BigchainDBError('Invalid tendermint version, '
'check Planetmint configuration file')

View File

@ -1,17 +1,17 @@
# Copyright © 2020 Interplanetary Database Association e.V.,
# Planetmint and IPDB software contributors.
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0
# # Copyright © 2020 Interplanetary Database Association e.V.,
# # Planetmint and IPDB software contributors.
# # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# # Code is Apache-2.0 and docs are CC-BY-4.0
from pymongo import MongoClient
from pytest import fixture
# from pymongo import MongoClient
# from pytest import fixture
@fixture
def mongo_client(db_context):
return MongoClient(host=db_context.host, port=db_context.port)
# @fixture
# def mongo_client(db_context):
# return MongoClient(host=db_context.host, port=db_context.port)
@fixture
def utxo_collection(db_context, mongo_client):
return mongo_client[db_context.name].utxos
# @fixture
# def utxo_collection(db_context, mongo_client):
# return mongo_client[db_context.name].utxos

View File

@ -1,486 +1,486 @@
# Copyright © 2020 Interplanetary Database Association e.V.,
# Planetmint and IPDB software contributors.
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0
# # Copyright © 2020 Interplanetary Database Association e.V.,
# # Planetmint and IPDB software contributors.
# # SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# # Code is Apache-2.0 and docs are CC-BY-4.0
from copy import deepcopy
# from copy import deepcopy
import pytest
import pymongo
# import pytest
# import pymongo
from planetmint.backend import Connection, query
# from planetmint.backend import Connection, query
pytestmark = pytest.mark.bdb
# pytestmark = pytest.mark.bdb
def test_get_txids_filtered(signed_create_tx, signed_transfer_tx):
from planetmint.backend import Connection, query
from planetmint.models import Transaction
conn = Connection() # TODO First rewrite to get here tarantool connection
print(conn)
# create and insert two blocks, one for the create and one for the
# transfer transactionTarantoolDBTarantoolDB
conn.db.transactions.insert_one(signed_create_tx.to_dict())
conn.db.transactions.insert_one(signed_transfer_tx.to_dict())
asset_id = Transaction.get_asset_id([signed_create_tx, signed_transfer_tx])
# Test get by just asset id
txids = set(query.get_txids_filtered(conn, asset_id))
assert txids == {signed_create_tx.id, signed_transfer_tx.id}
# Test get by asset and CREATE
txids = set(query.get_txids_filtered(conn, asset_id, Transaction.CREATE))
assert txids == {signed_create_tx.id}
# Test get by asset and TRANSFER
txids = set(query.get_txids_filtered(conn, asset_id, Transaction.TRANSFER))
assert txids == {signed_transfer_tx.id}
def test_write_assets():
from planetmint.backend import Connection, query
conn = Connection()
assets = [
{'id': 1, 'data': '1'},
{'id': 2, 'data': '2'},
{'id': 3, 'data': '3'},
# Duplicated id. Should not be written to the database
{'id': 1, 'data': '1'},
]
# write the assets
for asset in assets:
query.store_asset(conn, deepcopy(asset))
# check that 3 assets were written to the database
cursor = conn.db.assets.find({}, projection={'_id': False})\
.sort('id', pymongo.ASCENDING)
assert cursor.collection.count_documents({}) == 3
assert list(cursor) == assets[:-1]
def test_get_assets():
from planetmint.backend import Connection, query
conn = Connection()
assets = [
{'id': 1, 'data': '1'},
{'id': 2, 'data': '2'},
{'id': 3, 'data': '3'},
]
conn.db.assets.insert_many(deepcopy(assets), ordered=False)
for asset in assets:
assert query.get_asset(conn, asset['id'])
@pytest.mark.parametrize('table', ['assets', 'metadata'])
def test_text_search(table):
from planetmint.backend import Connection, query
conn = Connection()
# Example data and tests cases taken from the mongodb documentation
# https://docs.mongodb.com/manual/reference/operator/query/text/
objects = [
{'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50},
{'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
{'id': 3, 'subject': 'Baking a cake', 'author': 'abc', 'views': 90},
{'id': 4, 'subject': 'baking', 'author': 'xyz', 'views': 100},
{'id': 5, 'subject': 'Café Con Leche', 'author': 'abc', 'views': 200},
{'id': 6, 'subject': 'Сырники', 'author': 'jkl', 'views': 80},
{'id': 7, 'subject': 'coffee and cream', 'author': 'efg', 'views': 10},
{'id': 8, 'subject': 'Cafe con Leche', 'author': 'xyz', 'views': 10}
]
# insert the assets
conn.db[table].insert_many(deepcopy(objects), ordered=False)
# test search single word
assert list(query.text_search(conn, 'coffee', table=table)) == [
{'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50},
{'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
{'id': 7, 'subject': 'coffee and cream', 'author': 'efg', 'views': 10},
]
# match any of the search terms
assert list(query.text_search(conn, 'bake coffee cake', table=table)) == [
{'author': 'abc', 'id': 3, 'subject': 'Baking a cake', 'views': 90},
{'author': 'xyz', 'id': 1, 'subject': 'coffee', 'views': 50},
{'author': 'xyz', 'id': 4, 'subject': 'baking', 'views': 100},
{'author': 'efg', 'id': 2, 'subject': 'Coffee Shopping', 'views': 5},
{'author': 'efg', 'id': 7, 'subject': 'coffee and cream', 'views': 10}
]
# search for a phrase
assert list(query.text_search(conn, '\"coffee shop\"', table=table)) == [
{'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
]
# exclude documents that contain a term
assert list(query.text_search(conn, 'coffee -shop', table=table)) == [
{'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50},
{'id': 7, 'subject': 'coffee and cream', 'author': 'efg', 'views': 10},
]
# search different language
assert list(query.text_search(conn, 'leche', language='es', table=table)) == [
{'id': 5, 'subject': 'Café Con Leche', 'author': 'abc', 'views': 200},
{'id': 8, 'subject': 'Cafe con Leche', 'author': 'xyz', 'views': 10}
]
# case and diacritic insensitive search
assert list(query.text_search(conn, 'сы́рники CAFÉS', table=table)) == [
{'id': 6, 'subject': 'Сырники', 'author': 'jkl', 'views': 80},
{'id': 5, 'subject': 'Café Con Leche', 'author': 'abc', 'views': 200},
{'id': 8, 'subject': 'Cafe con Leche', 'author': 'xyz', 'views': 10}
]
# case sensitive search
assert list(query.text_search(conn, 'Coffee', case_sensitive=True, table=table)) == [
{'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
]
# diacritic sensitive search
assert list(query.text_search(conn, 'CAFÉ', diacritic_sensitive=True, table=table)) == [
{'id': 5, 'subject': 'Café Con Leche', 'author': 'abc', 'views': 200},
]
# return text score
assert list(query.text_search(conn, 'coffee', text_score=True, table=table)) == [
{'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50, 'score': 1.0},
{'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5, 'score': 0.75},
{'id': 7, 'subject': 'coffee and cream', 'author': 'efg', 'views': 10, 'score': 0.75},
]
# limit search result
assert list(query.text_search(conn, 'coffee', limit=2, table=table)) == [
{'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50},
{'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
]
def test_write_metadata():
from planetmint.backend import Connection, query
conn = Connection()
metadata = [
{'id': 1, 'data': '1'},
{'id': 2, 'data': '2'},
{'id': 3, 'data': '3'}
]
# write the assets
query.store_metadatas(conn, deepcopy(metadata))
# check that 3 assets were written to the database
cursor = conn.db.metadata.find({}, projection={'_id': False})\
.sort('id', pymongo.ASCENDING)
assert cursor.collection.count_documents({}) == 3
assert list(cursor) == metadata
def test_get_metadata():
from planetmint.backend import Connection, query
conn = Connection()
metadata = [
{'id': 1, 'metadata': None},
{'id': 2, 'metadata': {'key': 'value'}},
{'id': 3, 'metadata': '3'},
]
conn.db.metadata.insert_many(deepcopy(metadata), ordered=False)
for meta in metadata:
assert query.get_metadata(conn, [meta['id']])
def test_get_owned_ids(signed_create_tx, user_pk):
from planetmint.backend import Connection, query
conn = Connection()
# insert a transaction
conn.db.transactions.insert_one(deepcopy(signed_create_tx.to_dict()))
txns = list(query.get_owned_ids(conn, user_pk))
assert txns[0] == signed_create_tx.to_dict()
def test_get_spending_transactions(user_pk, user_sk):
from planetmint.backend import Connection, query
from planetmint.models import Transaction
conn = Connection()
out = [([user_pk], 1)]
tx1 = Transaction.create([user_pk], out * 3)
tx1.sign([user_sk])
inputs = tx1.to_inputs()
tx2 = Transaction.transfer([inputs[0]], out, tx1.id).sign([user_sk])
tx3 = Transaction.transfer([inputs[1]], out, tx1.id).sign([user_sk])
tx4 = Transaction.transfer([inputs[2]], out, tx1.id).sign([user_sk])
txns = [deepcopy(tx.to_dict()) for tx in [tx1, tx2, tx3, tx4]]
conn.db.transactions.insert_many(txns)
links = [inputs[0].fulfills.to_dict(), inputs[2].fulfills.to_dict()]
txns = list(query.get_spending_transactions(conn, links))
# tx3 not a member because input 1 not asked for
assert txns == [tx2.to_dict(), tx4.to_dict()]
def test_get_spending_transactions_multiple_inputs():
from planetmint.backend import Connection, query
from planetmint.models import Transaction
from planetmint.common.crypto import generate_key_pair
conn = Connection()
(alice_sk, alice_pk) = generate_key_pair()
(bob_sk, bob_pk) = generate_key_pair()
(carol_sk, carol_pk) = generate_key_pair()
out = [([alice_pk], 9)]
tx1 = Transaction.create([alice_pk], out).sign([alice_sk])
inputs1 = tx1.to_inputs()
tx2 = Transaction.transfer([inputs1[0]],
[([alice_pk], 6), ([bob_pk], 3)],
tx1.id).sign([alice_sk])
inputs2 = tx2.to_inputs()
tx3 = Transaction.transfer([inputs2[0]],
[([bob_pk], 3), ([carol_pk], 3)],
tx1.id).sign([alice_sk])
inputs3 = tx3.to_inputs()
tx4 = Transaction.transfer([inputs2[1], inputs3[0]],
[([carol_pk], 6)],
tx1.id).sign([bob_sk])
txns = [deepcopy(tx.to_dict()) for tx in [tx1, tx2, tx3, tx4]]
conn.db.transactions.insert_many(txns)
links = [
({'transaction_id': tx2.id, 'output_index': 0}, 1, [tx3.id]),
({'transaction_id': tx2.id, 'output_index': 1}, 1, [tx4.id]),
({'transaction_id': tx3.id, 'output_index': 0}, 1, [tx4.id]),
({'transaction_id': tx3.id, 'output_index': 1}, 0, None),
]
for li, num, match in links:
txns = list(query.get_spending_transactions(conn, [li]))
assert len(txns) == num
if len(txns):
assert [tx['id'] for tx in txns] == match
def test_store_block():
from planetmint.backend import Connection, query
from planetmint.lib import Block
conn = Connection()
block = Block(app_hash='random_utxo',
height=3,
transactions=[])
query.store_block(conn, block._asdict())
cursor = conn.db.blocks.find({}, projection={'_id': False})
assert cursor.collection.count_documents({}) == 1
def test_get_block():
from planetmint.backend import Connection, query
from planetmint.lib import Block
conn = Connection()
block = Block(app_hash='random_utxo',
height=3,
transactions=[])
conn.db.blocks.insert_one(block._asdict())
block = dict(query.get_block(conn, 3))
assert block['height'] == 3
def test_delete_zero_unspent_outputs(db_context, utxoset):
from planetmint.backend import query
unspent_outputs, utxo_collection = utxoset
delete_res = query.delete_unspent_outputs(db_context.conn)
assert delete_res is None
assert utxo_collection.count_documents({}) == 3
assert utxo_collection.count_documents(
{'$or': [
{'transaction_id': 'a', 'output_index': 0},
{'transaction_id': 'b', 'output_index': 0},
{'transaction_id': 'a', 'output_index': 1},
]}
) == 3
def test_delete_one_unspent_outputs(db_context, utxoset):
from planetmint.backend import query
unspent_outputs, utxo_collection = utxoset
delete_res = query.delete_unspent_outputs(db_context.conn,
unspent_outputs[0])
assert delete_res.raw_result['n'] == 1
assert utxo_collection.count_documents(
{'$or': [
{'transaction_id': 'a', 'output_index': 1},
{'transaction_id': 'b', 'output_index': 0},
]}
) == 2
assert utxo_collection.count_documents(
{'transaction_id': 'a', 'output_index': 0}) == 0
def test_delete_many_unspent_outputs(db_context, utxoset):
from planetmint.backend import query
unspent_outputs, utxo_collection = utxoset
delete_res = query.delete_unspent_outputs(db_context.conn,
*unspent_outputs[::2])
assert delete_res.raw_result['n'] == 2
assert utxo_collection.count_documents(
{'$or': [
{'transaction_id': 'a', 'output_index': 0},
{'transaction_id': 'b', 'output_index': 0},
]}
) == 0
assert utxo_collection.count_documents(
{'transaction_id': 'a', 'output_index': 1}) == 1
def test_store_zero_unspent_output(db_context, utxo_collection):
from planetmint.backend import query
res = query.store_unspent_outputs(db_context.conn)
assert res is None
assert utxo_collection.count_documents({}) == 0
def test_store_one_unspent_output(db_context,
unspent_output_1, utxo_collection):
from planetmint.backend import query
res = query.store_unspent_outputs(db_context.conn, unspent_output_1)
assert res.acknowledged
assert len(res.inserted_ids) == 1
assert utxo_collection.count_documents(
{'transaction_id': unspent_output_1['transaction_id'],
'output_index': unspent_output_1['output_index']}
) == 1
def test_store_many_unspent_outputs(db_context,
unspent_outputs, utxo_collection):
from planetmint.backend import query
res = query.store_unspent_outputs(db_context.conn, *unspent_outputs)
assert res.acknowledged
assert len(res.inserted_ids) == 3
assert utxo_collection.count_documents(
{'transaction_id': unspent_outputs[0]['transaction_id']}
) == 3
def test_get_unspent_outputs(db_context, utxoset):
from planetmint.backend import query
cursor = query.get_unspent_outputs(db_context.conn)
assert cursor.collection.count_documents({}) == 3
retrieved_utxoset = list(cursor)
unspent_outputs, utxo_collection = utxoset
assert retrieved_utxoset == list(
utxo_collection.find(projection={'_id': False}))
assert retrieved_utxoset == unspent_outputs
def test_store_pre_commit_state(db_context):
from planetmint.backend import query
state = dict(height=3, transactions=[])
query.store_pre_commit_state(db_context.conn, state)
cursor = db_context.conn.db.pre_commit.find({'commit_id': 'test'},
projection={'_id': False})
assert cursor.collection.count_documents({}) == 1
def test_get_pre_commit_state(db_context):
from planetmint.backend import query
state = dict(height=3, transactions=[])
db_context.conn.db.pre_commit.insert_one(state)
resp = query.get_pre_commit_state(db_context.conn)
assert resp == state
def test_validator_update():
from planetmint.backend import Connection, query
conn = Connection()
def gen_validator_update(height):
return {'data': 'somedata', 'height': height, 'election_id': f'election_id_at_height_{height}'}
for i in range(1, 100, 10):
value = gen_validator_update(i)
query.store_validator_set(conn, value)
v1 = query.get_validator_set(conn, 8)
assert v1['height'] == 1
v41 = query.get_validator_set(conn, 50)
assert v41['height'] == 41
v91 = query.get_validator_set(conn)
assert v91['height'] == 91
@pytest.mark.parametrize('description,stores,expected', [
(
'Query empty database.',
[],
None,
),
(
'Store one chain with the default value for `is_synced`.',
[
{'height': 0, 'chain_id': 'some-id'},
],
{'height': 0, 'chain_id': 'some-id', 'is_synced': True},
),
(
'Store one chain with a custom value for `is_synced`.',
[
{'height': 0, 'chain_id': 'some-id', 'is_synced': False},
],
{'height': 0, 'chain_id': 'some-id', 'is_synced': False},
),
(
'Store one chain, then update it.',
[
{'height': 0, 'chain_id': 'some-id', 'is_synced': True},
{'height': 0, 'chain_id': 'new-id', 'is_synced': False},
],
{'height': 0, 'chain_id': 'new-id', 'is_synced': False},
),
(
'Store a chain, update it, store another chain.',
[
{'height': 0, 'chain_id': 'some-id', 'is_synced': True},
{'height': 0, 'chain_id': 'some-id', 'is_synced': False},
{'height': 10, 'chain_id': 'another-id', 'is_synced': True},
],
{'height': 10, 'chain_id': 'another-id', 'is_synced': True},
),
])
def test_store_abci_chain(description, stores, expected):
conn = Connection()
for store in stores:
query.store_abci_chain(conn, **store)
actual = query.get_latest_abci_chain(conn)
assert expected == actual, description
#test_get_txids_filtered(None, None)
# def test_get_txids_filtered(signed_create_tx, signed_transfer_tx):
# from planetmint.backend import Connection, query
# from planetmint.models import Transaction
# conn = Connection() # TODO First rewrite to get here tarantool connection
# print(conn)
# # create and insert two blocks, one for the create and one for the
# # transfer transactionTarantoolDBTarantoolDB
# conn.db.transactions.insert_one(signed_create_tx.to_dict())
# conn.db.transactions.insert_one(signed_transfer_tx.to_dict())
# asset_id = Transaction.get_asset_id([signed_create_tx, signed_transfer_tx])
# # Test get by just asset id
# txids = set(query.get_txids_filtered(conn, asset_id))
# assert txids == {signed_create_tx.id, signed_transfer_tx.id}
# # Test get by asset and CREATE
# txids = set(query.get_txids_filtered(conn, asset_id, Transaction.CREATE))
# assert txids == {signed_create_tx.id}
# # Test get by asset and TRANSFER
# txids = set(query.get_txids_filtered(conn, asset_id, Transaction.TRANSFER))
# assert txids == {signed_transfer_tx.id}
# def test_write_assets():
# from planetmint.backend import Connection, query
# conn = Connection()
# assets = [
# {'id': 1, 'data': '1'},
# {'id': 2, 'data': '2'},
# {'id': 3, 'data': '3'},
# # Duplicated id. Should not be written to the database
# {'id': 1, 'data': '1'},
# ]
# # write the assets
# for asset in assets:
# query.store_asset(conn, deepcopy(asset))
# # check that 3 assets were written to the database
# cursor = conn.db.assets.find({}, projection={'_id': False})\
# .sort('id', pymongo.ASCENDING)
# assert cursor.collection.count_documents({}) == 3
# assert list(cursor) == assets[:-1]
# def test_get_assets():
# from planetmint.backend import Connection, query
# conn = Connection()
# assets = [
# {'id': 1, 'data': '1'},
# {'id': 2, 'data': '2'},
# {'id': 3, 'data': '3'},
# ]
# conn.db.assets.insert_many(deepcopy(assets), ordered=False)
# for asset in assets:
# assert query.get_asset(conn, asset['id'])
# @pytest.mark.parametrize('table', ['assets', 'metadata'])
# def test_text_search(table):
# from planetmint.backend import Connection, query
# conn = Connection()
# # Example data and tests cases taken from the mongodb documentation
# # https://docs.mongodb.com/manual/reference/operator/query/text/
# objects = [
# {'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50},
# {'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
# {'id': 3, 'subject': 'Baking a cake', 'author': 'abc', 'views': 90},
# {'id': 4, 'subject': 'baking', 'author': 'xyz', 'views': 100},
# {'id': 5, 'subject': 'Café Con Leche', 'author': 'abc', 'views': 200},
# {'id': 6, 'subject': 'Сырники', 'author': 'jkl', 'views': 80},
# {'id': 7, 'subject': 'coffee and cream', 'author': 'efg', 'views': 10},
# {'id': 8, 'subject': 'Cafe con Leche', 'author': 'xyz', 'views': 10}
# ]
# # insert the assets
# conn.db[table].insert_many(deepcopy(objects), ordered=False)
# # test search single word
# assert list(query.text_search(conn, 'coffee', table=table)) == [
# {'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50},
# {'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
# {'id': 7, 'subject': 'coffee and cream', 'author': 'efg', 'views': 10},
# ]
# # match any of the search terms
# assert list(query.text_search(conn, 'bake coffee cake', table=table)) == [
# {'author': 'abc', 'id': 3, 'subject': 'Baking a cake', 'views': 90},
# {'author': 'xyz', 'id': 1, 'subject': 'coffee', 'views': 50},
# {'author': 'xyz', 'id': 4, 'subject': 'baking', 'views': 100},
# {'author': 'efg', 'id': 2, 'subject': 'Coffee Shopping', 'views': 5},
# {'author': 'efg', 'id': 7, 'subject': 'coffee and cream', 'views': 10}
# ]
# # search for a phrase
# assert list(query.text_search(conn, '\"coffee shop\"', table=table)) == [
# {'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
# ]
# # exclude documents that contain a term
# assert list(query.text_search(conn, 'coffee -shop', table=table)) == [
# {'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50},
# {'id': 7, 'subject': 'coffee and cream', 'author': 'efg', 'views': 10},
# ]
# # search different language
# assert list(query.text_search(conn, 'leche', language='es', table=table)) == [
# {'id': 5, 'subject': 'Café Con Leche', 'author': 'abc', 'views': 200},
# {'id': 8, 'subject': 'Cafe con Leche', 'author': 'xyz', 'views': 10}
# ]
# # case and diacritic insensitive search
# assert list(query.text_search(conn, 'сы́рники CAFÉS', table=table)) == [
# {'id': 6, 'subject': 'Сырники', 'author': 'jkl', 'views': 80},
# {'id': 5, 'subject': 'Café Con Leche', 'author': 'abc', 'views': 200},
# {'id': 8, 'subject': 'Cafe con Leche', 'author': 'xyz', 'views': 10}
# ]
# # case sensitive search
# assert list(query.text_search(conn, 'Coffee', case_sensitive=True, table=table)) == [
# {'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
# ]
# # diacritic sensitive search
# assert list(query.text_search(conn, 'CAFÉ', diacritic_sensitive=True, table=table)) == [
# {'id': 5, 'subject': 'Café Con Leche', 'author': 'abc', 'views': 200},
# ]
# # return text score
# assert list(query.text_search(conn, 'coffee', text_score=True, table=table)) == [
# {'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50, 'score': 1.0},
# {'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5, 'score': 0.75},
# {'id': 7, 'subject': 'coffee and cream', 'author': 'efg', 'views': 10, 'score': 0.75},
# ]
# # limit search result
# assert list(query.text_search(conn, 'coffee', limit=2, table=table)) == [
# {'id': 1, 'subject': 'coffee', 'author': 'xyz', 'views': 50},
# {'id': 2, 'subject': 'Coffee Shopping', 'author': 'efg', 'views': 5},
# ]
# def test_write_metadata():
# from planetmint.backend import Connection, query
# conn = Connection()
# metadata = [
# {'id': 1, 'data': '1'},
# {'id': 2, 'data': '2'},
# {'id': 3, 'data': '3'}
# ]
# # write the assets
# query.store_metadatas(conn, deepcopy(metadata))
# # check that 3 assets were written to the database
# cursor = conn.db.metadata.find({}, projection={'_id': False})\
# .sort('id', pymongo.ASCENDING)
# assert cursor.collection.count_documents({}) == 3
# assert list(cursor) == metadata
# def test_get_metadata():
# from planetmint.backend import Connection, query
# conn = Connection()
# metadata = [
# {'id': 1, 'metadata': None},
# {'id': 2, 'metadata': {'key': 'value'}},
# {'id': 3, 'metadata': '3'},
# ]
# conn.db.metadata.insert_many(deepcopy(metadata), ordered=False)
# for meta in metadata:
# assert query.get_metadata(conn, [meta['id']])
# def test_get_owned_ids(signed_create_tx, user_pk):
# from planetmint.backend import Connection, query
# conn = Connection()
# # insert a transaction
# conn.db.transactions.insert_one(deepcopy(signed_create_tx.to_dict()))
# txns = list(query.get_owned_ids(conn, user_pk))
# assert txns[0] == signed_create_tx.to_dict()
# def test_get_spending_transactions(user_pk, user_sk):
# from planetmint.backend import Connection, query
# from planetmint.models import Transaction
# conn = Connection()
# out = [([user_pk], 1)]
# tx1 = Transaction.create([user_pk], out * 3)
# tx1.sign([user_sk])
# inputs = tx1.to_inputs()
# tx2 = Transaction.transfer([inputs[0]], out, tx1.id).sign([user_sk])
# tx3 = Transaction.transfer([inputs[1]], out, tx1.id).sign([user_sk])
# tx4 = Transaction.transfer([inputs[2]], out, tx1.id).sign([user_sk])
# txns = [deepcopy(tx.to_dict()) for tx in [tx1, tx2, tx3, tx4]]
# conn.db.transactions.insert_many(txns)
# links = [inputs[0].fulfills.to_dict(), inputs[2].fulfills.to_dict()]
# txns = list(query.get_spending_transactions(conn, links))
# # tx3 not a member because input 1 not asked for
# assert txns == [tx2.to_dict(), tx4.to_dict()]
# def test_get_spending_transactions_multiple_inputs():
# from planetmint.backend import Connection, query
# from planetmint.models import Transaction
# from planetmint.common.crypto import generate_key_pair
# conn = Connection()
# (alice_sk, alice_pk) = generate_key_pair()
# (bob_sk, bob_pk) = generate_key_pair()
# (carol_sk, carol_pk) = generate_key_pair()
# out = [([alice_pk], 9)]
# tx1 = Transaction.create([alice_pk], out).sign([alice_sk])
# inputs1 = tx1.to_inputs()
# tx2 = Transaction.transfer([inputs1[0]],
# [([alice_pk], 6), ([bob_pk], 3)],
# tx1.id).sign([alice_sk])
# inputs2 = tx2.to_inputs()
# tx3 = Transaction.transfer([inputs2[0]],
# [([bob_pk], 3), ([carol_pk], 3)],
# tx1.id).sign([alice_sk])
# inputs3 = tx3.to_inputs()
# tx4 = Transaction.transfer([inputs2[1], inputs3[0]],
# [([carol_pk], 6)],
# tx1.id).sign([bob_sk])
# txns = [deepcopy(tx.to_dict()) for tx in [tx1, tx2, tx3, tx4]]
# conn.db.transactions.insert_many(txns)
# links = [
# ({'transaction_id': tx2.id, 'output_index': 0}, 1, [tx3.id]),
# ({'transaction_id': tx2.id, 'output_index': 1}, 1, [tx4.id]),
# ({'transaction_id': tx3.id, 'output_index': 0}, 1, [tx4.id]),
# ({'transaction_id': tx3.id, 'output_index': 1}, 0, None),
# ]
# for li, num, match in links:
# txns = list(query.get_spending_transactions(conn, [li]))
# assert len(txns) == num
# if len(txns):
# assert [tx['id'] for tx in txns] == match
# def test_store_block():
# from planetmint.backend import Connection, query
# from planetmint.lib import Block
# conn = Connection()
# block = Block(app_hash='random_utxo',
# height=3,
# transactions=[])
# query.store_block(conn, block._asdict())
# cursor = conn.db.blocks.find({}, projection={'_id': False})
# assert cursor.collection.count_documents({}) == 1
# def test_get_block():
# from planetmint.backend import Connection, query
# from planetmint.lib import Block
# conn = Connection()
# block = Block(app_hash='random_utxo',
# height=3,
# transactions=[])
# conn.db.blocks.insert_one(block._asdict())
# block = dict(query.get_block(conn, 3))
# assert block['height'] == 3
# def test_delete_zero_unspent_outputs(db_context, utxoset):
# from planetmint.backend import query
# unspent_outputs, utxo_collection = utxoset
# delete_res = query.delete_unspent_outputs(db_context.conn)
# assert delete_res is None
# assert utxo_collection.count_documents({}) == 3
# assert utxo_collection.count_documents(
# {'$or': [
# {'transaction_id': 'a', 'output_index': 0},
# {'transaction_id': 'b', 'output_index': 0},
# {'transaction_id': 'a', 'output_index': 1},
# ]}
# ) == 3
# def test_delete_one_unspent_outputs(db_context, utxoset):
# from planetmint.backend import query
# unspent_outputs, utxo_collection = utxoset
# delete_res = query.delete_unspent_outputs(db_context.conn,
# unspent_outputs[0])
# assert delete_res.raw_result['n'] == 1
# assert utxo_collection.count_documents(
# {'$or': [
# {'transaction_id': 'a', 'output_index': 1},
# {'transaction_id': 'b', 'output_index': 0},
# ]}
# ) == 2
# assert utxo_collection.count_documents(
# {'transaction_id': 'a', 'output_index': 0}) == 0
# def test_delete_many_unspent_outputs(db_context, utxoset):
# from planetmint.backend import query
# unspent_outputs, utxo_collection = utxoset
# delete_res = query.delete_unspent_outputs(db_context.conn,
# *unspent_outputs[::2])
# assert delete_res.raw_result['n'] == 2
# assert utxo_collection.count_documents(
# {'$or': [
# {'transaction_id': 'a', 'output_index': 0},
# {'transaction_id': 'b', 'output_index': 0},
# ]}
# ) == 0
# assert utxo_collection.count_documents(
# {'transaction_id': 'a', 'output_index': 1}) == 1
# def test_store_zero_unspent_output(db_context, utxo_collection):
# from planetmint.backend import query
# res = query.store_unspent_outputs(db_context.conn)
# assert res is None
# assert utxo_collection.count_documents({}) == 0
# def test_store_one_unspent_output(db_context,
# unspent_output_1, utxo_collection):
# from planetmint.backend import query
# res = query.store_unspent_outputs(db_context.conn, unspent_output_1)
# assert res.acknowledged
# assert len(res.inserted_ids) == 1
# assert utxo_collection.count_documents(
# {'transaction_id': unspent_output_1['transaction_id'],
# 'output_index': unspent_output_1['output_index']}
# ) == 1
# def test_store_many_unspent_outputs(db_context,
# unspent_outputs, utxo_collection):
# from planetmint.backend import query
# res = query.store_unspent_outputs(db_context.conn, *unspent_outputs)
# assert res.acknowledged
# assert len(res.inserted_ids) == 3
# assert utxo_collection.count_documents(
# {'transaction_id': unspent_outputs[0]['transaction_id']}
# ) == 3
# def test_get_unspent_outputs(db_context, utxoset):
# from planetmint.backend import query
# cursor = query.get_unspent_outputs(db_context.conn)
# assert cursor.collection.count_documents({}) == 3
# retrieved_utxoset = list(cursor)
# unspent_outputs, utxo_collection = utxoset
# assert retrieved_utxoset == list(
# utxo_collection.find(projection={'_id': False}))
# assert retrieved_utxoset == unspent_outputs
# def test_store_pre_commit_state(db_context):
# from planetmint.backend import query
# state = dict(height=3, transactions=[])
# query.store_pre_commit_state(db_context.conn, state)
# cursor = db_context.conn.db.pre_commit.find({'commit_id': 'test'},
# projection={'_id': False})
# assert cursor.collection.count_documents({}) == 1
# def test_get_pre_commit_state(db_context):
# from planetmint.backend import query
# state = dict(height=3, transactions=[])
# db_context.conn.db.pre_commit.insert_one(state)
# resp = query.get_pre_commit_state(db_context.conn)
# assert resp == state
# def test_validator_update():
# from planetmint.backend import Connection, query
# conn = Connection()
# def gen_validator_update(height):
# return {'data': 'somedata', 'height': height, 'election_id': f'election_id_at_height_{height}'}
# for i in range(1, 100, 10):
# value = gen_validator_update(i)
# query.store_validator_set(conn, value)
# v1 = query.get_validator_set(conn, 8)
# assert v1['height'] == 1
# v41 = query.get_validator_set(conn, 50)
# assert v41['height'] == 41
# v91 = query.get_validator_set(conn)
# assert v91['height'] == 91
# @pytest.mark.parametrize('description,stores,expected', [
# (
# 'Query empty database.',
# [],
# None,
# ),
# (
# 'Store one chain with the default value for `is_synced`.',
# [
# {'height': 0, 'chain_id': 'some-id'},
# ],
# {'height': 0, 'chain_id': 'some-id', 'is_synced': True},
# ),
# (
# 'Store one chain with a custom value for `is_synced`.',
# [
# {'height': 0, 'chain_id': 'some-id', 'is_synced': False},
# ],
# {'height': 0, 'chain_id': 'some-id', 'is_synced': False},
# ),
# (
# 'Store one chain, then update it.',
# [
# {'height': 0, 'chain_id': 'some-id', 'is_synced': True},
# {'height': 0, 'chain_id': 'new-id', 'is_synced': False},
# ],
# {'height': 0, 'chain_id': 'new-id', 'is_synced': False},
# ),
# (
# 'Store a chain, update it, store another chain.',
# [
# {'height': 0, 'chain_id': 'some-id', 'is_synced': True},
# {'height': 0, 'chain_id': 'some-id', 'is_synced': False},
# {'height': 10, 'chain_id': 'another-id', 'is_synced': True},
# ],
# {'height': 10, 'chain_id': 'another-id', 'is_synced': True},
# ),
# ])
# def test_store_abci_chain(description, stores, expected):
# conn = Connection()
# for store in stores:
# query.store_abci_chain(conn, **store)
# actual = query.get_latest_abci_chain(conn)
# assert expected == actual, description
# #test_get_txids_filtered(None, None)

View File

@ -3,6 +3,7 @@
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0
from planetmint.config import Config
def test_init_database_is_graceful_if_db_exists():
import planetmint
@ -10,7 +11,7 @@ def test_init_database_is_graceful_if_db_exists():
from planetmint.backend.schema import init_database
conn = backend.connect()
dbname = planetmint.config['database']['name']
dbname = Config().get()['database']['name']
# The db is set up by the fixtures
assert dbname in conn.conn.list_database_names()
@ -24,7 +25,7 @@ def test_create_tables():
from planetmint.backend import schema
conn = backend.connect()
dbname = planetmint.config['database']['name']
dbname = Config().get()['database']['name']
# The db is set up by the fixtures so we need to remove it
conn.conn.drop_database(dbname)

View File

@ -11,6 +11,7 @@ from argparse import Namespace
import pytest
from planetmint.config import Config
from planetmint import ValidatorElection
from planetmint.commands.planetmint import run_election_show
from planetmint.elections.election import Election
@ -79,9 +80,10 @@ def test_bigchain_show_config(capsys):
# the default comparison fails i.e. when config is imported at the beginning the
# dict returned is different that what is expected after run_show_config
# and run_show_config updates the planetmint.config
from planetmint import config
del config['CONFIGURED']
assert output_config == config
from planetmint.config import Config
_config = Config().get()
del _config['CONFIGURED']
assert output_config == _config
def test__run_init(mocker):
@ -198,7 +200,7 @@ def test_run_configure_with_backend(backend, monkeypatch, mock_write_config):
mock_write_config)
args = Namespace(config=None, backend=backend, yes=True)
expected_config = planetmint.config
expected_config = Config().get()
run_configure(args)
# update the expected config with the correct backend and keypair

View File

@ -14,8 +14,8 @@ from unittest.mock import patch
@pytest.fixture
def reset_planetmint_config(monkeypatch):
import planetmint
monkeypatch.setattr('planetmint.config', planetmint._config)
from planetmint.config import Config
monkeypatch.setattr('planetmint.config', Config().init_config('tarantool_db'))
def test_input_on_stderr():

View File

@ -31,6 +31,7 @@ from planetmint.common.crypto import (key_pair_from_ed25519_key,
from planetmint.common.exceptions import DatabaseDoesNotExist
from planetmint.lib import Block
from tests.utils import gen_vote
from planetmint.config import Config
TEST_DB_NAME = 'planetmint_test'
@ -80,15 +81,13 @@ def _bdb_marker(request):
@pytest.fixture(autouse=True)
def _restore_config(_configure_planetmint):
from planetmint import config, config_utils
config_before_test = copy.deepcopy(config)
yield
config_utils.set_config(config_before_test)
config_before_test = Config().init_config('tarantool_db')
@pytest.fixture(scope='session')
def _configure_planetmint(request):
import planetmint
from planetmint import config_utils
test_db_name = TEST_DB_NAME
# Put a suffix like _gw0, _gw1 etc on xdist processes
@ -100,7 +99,7 @@ def _configure_planetmint(request):
backend = "tarantool_db"
config = {
'database': planetmint._database_map[backend],
'database': Config().get_db_map(backend),
'tendermint': {
'host': 'localhost',
'port': 26657,
@ -126,11 +125,12 @@ def _setup_database(_configure_planetmint): # TODO Here is located setup databa
@pytest.fixture
def _bdb(_setup_database, _configure_planetmint):
def _bdb(_setup_database ):
from planetmint.backend import Connection
from planetmint.common.memoize import to_dict, from_dict
from planetmint.models import Transaction
conn = Connection()
#conn = Connection( backend='tarantool_db', port=3301, host='localhost', login='guest')
#conn = Connection()
yield
to_dict.cache_clear()
@ -342,8 +342,7 @@ def _drop_db(conn, dbname):
@pytest.fixture
def db_config():
from planetmint import config
return config['database']
return Config().get()['database']
@pytest.fixture
@ -444,8 +443,7 @@ def abci_server():
@pytest.fixture
def wsserver_config():
from planetmint import config
return config['wsserver']
return Config().get()['wsserver']
@pytest.fixture

View File

@ -9,27 +9,23 @@ from unittest.mock import mock_open, patch
import pytest
import planetmint
ORIGINAL_CONFIG = copy.deepcopy(planetmint._config)
from planetmint.config import Config
@pytest.fixture(scope='function', autouse=True)
def clean_config(monkeypatch, request):
original_config = copy.deepcopy(ORIGINAL_CONFIG)
def clean_config(monkeypatch, request):
original_config = Config().init_config('tarantool_db')
backend = request.config.getoption('--database-backend')
original_config['database'] = planetmint._database_map[backend]
original_config['database'] = Config().get_db_map(backend)
monkeypatch.setattr('planetmint.config', original_config)
def test_bigchain_instance_is_initialized_when_conf_provided():
import planetmint
from planetmint import config_utils
assert 'CONFIGURED' not in planetmint.config
assert 'CONFIGURED' not in Config().get()
config_utils.set_config({'database': {'backend': 'a'}})
assert planetmint.config['CONFIGURED'] is True
assert Config().get()['CONFIGURED'] is True
def test_load_validation_plugin_loads_default_rules_without_name():
@ -247,16 +243,15 @@ def test_autoconfigure_env_precedence(monkeypatch):
monkeypatch.setattr('os.environ', {'PLANETMINT_DATABASE_NAME': 'test-dbname',
'PLANETMINT_DATABASE_PORT': 4242,
'PLANETMINT_SERVER_BIND': 'localhost:9985'})
import planetmint
from planetmint import config_utils
from planetmint.config import Config
config_utils.autoconfigure()
assert planetmint.config['CONFIGURED']
assert planetmint.config['database']['host'] == 'test-host'
assert planetmint.config['database']['name'] == 'test-dbname'
assert planetmint.config['database']['port'] == 4242
assert planetmint.config['server']['bind'] == 'localhost:9985'
assert Config().get()['CONFIGURED']
assert Config().get()['database']['host'] == 'test-host'
assert Config().get()['database']['name'] == 'test-dbname'
assert Config().get()['database']['port'] == 4242
assert Config().get()['server']['bind'] == 'localhost:9985'
def test_autoconfigure_explicit_file(monkeypatch):
@ -284,9 +279,9 @@ def test_update_config(monkeypatch):
# update configuration, retaining previous changes
config_utils.update_config({'database': {'port': 28016, 'name': 'planetmint_other'}})
assert planetmint.config['database']['host'] == 'test-host'
assert planetmint.config['database']['name'] == 'planetmint_other'
assert planetmint.config['database']['port'] == 28016
assert Config().get()['database']['host'] == 'test-host'
assert Config().get()['database']['name'] == 'planetmint_other'
assert Config().get()['database']['port'] == 28016
def test_file_config():
@ -327,7 +322,7 @@ def test_database_envs(env_name, env_value, config_key, monkeypatch):
monkeypatch.setattr('os.environ', {env_name: env_value})
planetmint.config_utils.autoconfigure()
expected_config = copy.deepcopy(planetmint.config)
expected_config = Config().get()
expected_config['database'][config_key] = env_value
assert planetmint.config == expected_config

View File

@ -15,12 +15,13 @@ def config(request, monkeypatch):
config = {
'database': {
'backend': backend,
'host': 'host',
'port': 28015,
'host': 'localhost',
'port': 3301,
'name': 'bigchain',
'replicaset': 'bigchain-rs',
'connection_timeout': 5000,
'max_tries': 3
'max_tries': 3,
'name':'bigchain'
},
'tendermint': {
'host': 'localhost',
@ -37,12 +38,12 @@ def config(request, monkeypatch):
def test_bigchain_class_default_initialization(config):
from planetmint import Planetmint
from planetmint.validation import BaseValidationRules
from planetmint.backend.connection import Connection
from planetmint.backend.tarantool.connection import TarantoolDB
planet = Planetmint()
assert isinstance(planet.connection, Connection)
#assert isinstance(planet.connection, TarantoolDB)
assert planet.connection.host == config['database']['host']
assert planet.connection.port == config['database']['port']
assert planet.connection.dbname == config['database']['name']
#assert planet.connection.dbname == config['database']['name']
assert planet.validation == BaseValidationRules
@ -61,7 +62,7 @@ def test_bigchain_class_initialization_with_parameters():
assert planet.connection == connection
assert planet.connection.host == init_db_kwargs['host']
assert planet.connection.port == init_db_kwargs['port']
assert planet.connection.dbname == init_db_kwargs['name']
#assert planet.connection.name == init_db_kwargs['name']
assert planet.validation == BaseValidationRules

View File

@ -5,11 +5,11 @@
def test_settings():
import planetmint
from planetmint.config import Config
from planetmint.web import server
s = server.create_server(planetmint.config['server'])
s = server.create_server(Config().get()['server'])
# for whatever reason the value is wrapped in a list
# needs further investigation
assert s.cfg.bind[0] == planetmint.config['server']['bind']
assert s.cfg.bind[0] == Config().get()['server']['bind']