Skip to content

Commit

Permalink
Revert "Merge pull request #395 from HoverHell/deferred-config-dir"
Browse files Browse the repository at this point in the history
This reverts commit 2c7d9e6, reversing
changes made to 60804c6.
  • Loading branch information
Cryp Toon committed Jun 5, 2024
1 parent 2c7d9e6 commit a262f98
Show file tree
Hide file tree
Showing 17 changed files with 109 additions and 165 deletions.
162 changes: 52 additions & 110 deletions bitcoinlib/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,14 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

import functools
import os
import locale
import logging
import platform
import configparser
import enum
from logging.handlers import RotatingFileHandler
from .opcodes import *
from pathlib import Path
from datetime import datetime, timezone
from .opcodes import *

logger = logging.getLogger('bitcoinlib')

# General defaults
TYPE_TEXT = str
Expand All @@ -39,7 +34,6 @@


# File locations
CONFIG_FILE_NAME = os.environ.get('BCL_CONFIG_FILE')
BCL_CONFIG_FILE = ''
BCL_INSTALL_DIR = Path(__file__).parents[1]
BCL_DATA_DIR = ''
Expand All @@ -54,7 +48,6 @@
DATABASE_ENCRYPTION_ENABLED = False
DB_FIELD_ENCRYPTION_KEY = None
DB_FIELD_ENCRYPTION_PASSWORD = None
CONFIG = configparser.ConfigParser()

# Services
TIMEOUT_REQUESTS = 5
Expand Down Expand Up @@ -255,108 +248,43 @@
SERVICE_CACHING_ENABLED = True


def config_get(section, var, fallback, is_boolean=False):
try:
env_key = 'BCL_%s_%s' % (section.upper(), var.upper())
if env_key in os.environ:
env_val = os.environ[env_key]
if is_boolean:
return env_val.lower() not in ('', 'off', 'false')
return env_val

if is_boolean:
return CONFIG.getboolean(section, var, fallback=fallback)

return CONFIG.get(section, var, fallback=fallback)

except Exception:
return fallback


@functools.lru_cache(maxsize=None)
def read_config():
global BCL_INSTALL_DIR, BCL_DATABASE_DIR, BCL_DATA_DIR, BCL_CONFIG_FILE
config = configparser.ConfigParser()

def config_get(section, var, fallback, is_boolean=False):
try:
if is_boolean:
val = config.getboolean(section, var, fallback=fallback)
else:
val = config.get(section, var, fallback=fallback)
return val
except Exception:
return fallback

global BCL_INSTALL_DIR, BCL_DATABASE_DIR, DEFAULT_DATABASE, BCL_DATA_DIR, BCL_CONFIG_FILE
global ALLOW_DATABASE_THREADS, DEFAULT_DATABASE_CACHE
global BCL_LOG_FILE, LOGLEVEL, ENABLE_BITCOINLIB_LOGGING
global TIMEOUT_REQUESTS, DEFAULT_LANGUAGE, DEFAULT_NETWORK, DEFAULT_WITNESS_TYPE
global SERVICE_CACHING_ENABLED, DATABASE_ENCRYPTION_ENABLED, DB_FIELD_ENCRYPTION_KEY, DB_FIELD_ENCRYPTION_PASSWORD
global SERVICE_MAX_ERRORS, BLOCK_COUNT_CACHE_TIME, MAX_TRANSACTIONS

CONFIG_DIR = Path('~/.config/bitcoinlib').expanduser()
if not CONFIG_DIR.exists():
CONFIG_DIR = Path('~/.bitcoinlib').expanduser()

# Read settings from Configuration file provided in OS environment or home config directory
if CONFIG_FILE_NAME:
BCL_CONFIG_FILE = Path(CONFIG_FILE_NAME)
# Read settings from Configuration file provided in OS environment~/.bitcoinlib/ directory
config_file_name = os.environ.get('BCL_CONFIG_FILE')
if not config_file_name:
BCL_CONFIG_FILE = Path('~/.bitcoinlib/config.ini').expanduser()
else:
BCL_CONFIG_FILE = Path(CONFIG_DIR, 'config.ini')

if not BCL_CONFIG_FILE.is_absolute():
BCL_CONFIG_FILE = Path(CONFIG_DIR, BCL_CONFIG_FILE)
if not BCL_CONFIG_FILE.exists():
BCL_CONFIG_FILE = Path(BCL_INSTALL_DIR, 'data', CONFIG_FILE_NAME or "config.ini")
if not BCL_CONFIG_FILE.exists():
raise IOError('Bitcoinlib configuration file not found: %s' % str(BCL_CONFIG_FILE))
config_data = CONFIG.read(str(BCL_CONFIG_FILE))

default_data_dir = str(BCL_CONFIG_FILE.parent)
BCL_DATA_DIR = Path(config_get('locations', 'data_dir', fallback=default_data_dir)).expanduser()
BCL_DATABASE_DIR = Path(config_get('locations', 'database_dir', fallback='database'))
if not BCL_DATABASE_DIR.is_absolute():
BCL_DATABASE_DIR = Path(CONFIG_DIR, BCL_DATABASE_DIR)

# Log settings
ENABLE_BITCOINLIB_LOGGING = config_get("logs", "enable_bitcoinlib_logging", fallback=True, is_boolean=True)
BCL_LOG_FILE = Path(CONFIG_DIR, config_get('logs', 'log_file', fallback='bitcoinlib.log'))
LOGLEVEL = config_get('logs', 'loglevel', fallback=LOGLEVEL)

# Service settings
TIMEOUT_REQUESTS = int(config_get('common', 'timeout_requests', fallback=TIMEOUT_REQUESTS))
SERVICE_MAX_ERRORS = int(config_get('common', 'service_max_errors', fallback=SERVICE_MAX_ERRORS))
MAX_TRANSACTIONS = int(config_get('common', 'max_transactions', fallback=MAX_TRANSACTIONS))
BLOCK_COUNT_CACHE_TIME = int(config_get('common', 'block_count_cache_time', fallback=BLOCK_COUNT_CACHE_TIME))

# Other settings
DEFAULT_LANGUAGE = config_get('common', 'default_language', fallback=DEFAULT_LANGUAGE)
DEFAULT_NETWORK = config_get('common', 'default_network', fallback=DEFAULT_NETWORK)
DEFAULT_WITNESS_TYPE = config_get('common', 'default_witness_type', fallback=DEFAULT_WITNESS_TYPE)

return bool(config_data)


@functools.lru_cache(maxsize=None)
def initialize_logging():
if not ENABLE_BITCOINLIB_LOGGING:
return

logger.setLevel(LOGLEVEL)
if not logger.handlers:
BCL_LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
handler = RotatingFileHandler(str(BCL_LOG_FILE), maxBytes=100 * 1024 * 1024, backupCount=2)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s',
datefmt='%Y/%m/%d %H:%M:%S')
handler.setFormatter(formatter)
handler.setLevel(LOGLEVEL)
logger.addHandler(handler)

logger.info('WELCOME TO BITCOINLIB - CRYPTOCURRENCY LIBRARY')
logger.info('Version: %s', BITCOINLIB_VERSION)
logger.info('Logger name: %s', logger.name)
logger.info('Read config from: %s', BCL_CONFIG_FILE)
logger.info('Databases directory: %s', BCL_DATABASE_DIR)
logger.info('Default database: %s', DEFAULT_DATABASE)
logger.info('Logging to: %s', BCL_LOG_FILE)
logger.info('Directory for data files: %s', BCL_DATA_DIR)


@functools.lru_cache(maxsize=None)
def initialize_db():
global DEFAULT_DATABASE, ALLOW_DATABASE_THREADS, DEFAULT_DATABASE_CACHE
global UNITTESTS_FULL_DATABASE_TEST, SERVICE_CACHING_ENABLED, DATABASE_ENCRYPTION_ENABLED, DB_FIELD_ENCRYPTION_KEY

read_config()
BCL_CONFIG_FILE = Path(config_file_name)
if not BCL_CONFIG_FILE.is_absolute():
BCL_CONFIG_FILE = Path(Path.home(), '.bitcoinlib', BCL_CONFIG_FILE)
if not BCL_CONFIG_FILE.exists():
BCL_CONFIG_FILE = Path(BCL_INSTALL_DIR, 'data', config_file_name)
if not BCL_CONFIG_FILE.exists():
raise IOError('Bitcoinlib configuration file not found: %s' % str(BCL_CONFIG_FILE))
data = config.read(str(BCL_CONFIG_FILE))
BCL_DATA_DIR = Path(config_get('locations', 'data_dir', fallback='~/.bitcoinlib')).expanduser()

# Database settings
BCL_DATABASE_DIR = Path(BCL_DATA_DIR, config_get('locations', 'database_dir', 'database'))
BCL_DATABASE_DIR.mkdir(parents=True, exist_ok=True)
default_databasefile = DEFAULT_DATABASE = \
config_get('locations', 'default_databasefile', fallback='bitcoinlib.sqlite')
Expand All @@ -372,16 +300,30 @@ def initialize_db():
DB_FIELD_ENCRYPTION_KEY = os.environ.get('DB_FIELD_ENCRYPTION_KEY')
DB_FIELD_ENCRYPTION_PASSWORD = os.environ.get('DB_FIELD_ENCRYPTION_PASSWORD')

full_db_test = os.environ.get('UNITTESTS_FULL_DATABASE_TEST')
if full_db_test in [1, True, 'True', 'true', 'TRUE']:
UNITTESTS_FULL_DATABASE_TEST = True
# Log settings
ENABLE_BITCOINLIB_LOGGING = config_get("logs", "enable_bitcoinlib_logging", fallback=True, is_boolean=True)
BCL_LOG_FILE = Path(BCL_DATA_DIR, config_get('logs', 'log_file', fallback='bitcoinlib.log'))
BCL_LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
LOGLEVEL = config_get('logs', 'loglevel', fallback=LOGLEVEL)

# Service settings
TIMEOUT_REQUESTS = int(config_get('common', 'timeout_requests', fallback=TIMEOUT_REQUESTS))
SERVICE_MAX_ERRORS = int(config_get('common', 'service_max_errors', fallback=SERVICE_MAX_ERRORS))
MAX_TRANSACTIONS = int(config_get('common', 'max_transactions', fallback=MAX_TRANSACTIONS))
BLOCK_COUNT_CACHE_TIME = int(config_get('common', 'block_count_cache_time', fallback=BLOCK_COUNT_CACHE_TIME))

# Other settings
DEFAULT_LANGUAGE = config_get('common', 'default_language', fallback=DEFAULT_LANGUAGE)
DEFAULT_NETWORK = config_get('common', 'default_network', fallback=DEFAULT_NETWORK)
DEFAULT_WITNESS_TYPE = config_get('common', 'default_witness_type', fallback=DEFAULT_WITNESS_TYPE)

if not data:
return False
return True


# Copy data and settings to default settings directory if install.log is not found
@functools.lru_cache(maxsize=None)
def initialize_lib():
read_config()

global BCL_INSTALL_DIR, BCL_DATA_DIR, BITCOINLIB_VERSION
instlogfile = Path(BCL_DATA_DIR, 'install.log')
if instlogfile.exists():
Expand All @@ -408,10 +350,10 @@ def initialize_lib():
for file in Path(BCL_INSTALL_DIR, 'data').iterdir():
if file.suffix not in ['.ini', '.json']:
continue
target_path = Path(BCL_DATA_DIR, file.name)
if not target_path.exists():
copyfile(str(file), target_path)
copyfile(str(file), Path(BCL_DATA_DIR, file.name))


# Initialize library
read_config()
BITCOINLIB_VERSION = Path(BCL_INSTALL_DIR, 'config/VERSION').open().read().strip()
initialize_lib()
15 changes: 3 additions & 12 deletions bitcoinlib/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.orm import sessionmaker, relationship, session
from urllib.parse import urlparse
from bitcoinlib.config import config
from bitcoinlib.main import *
from bitcoinlib.encoding import aes_encrypt, aes_decrypt, double_sha256

Expand All @@ -50,12 +49,7 @@ class Db:
"""
def __init__(self, db_uri=None, password=None):
if db_uri is None:
# Default configuration, populate and use the home dir config.
config.initialize_lib()
config.initialize_db()
config.initialize_logging()
db_uri = config.DEFAULT_DATABASE
assert db_uri
db_uri = DEFAULT_DATABASE
self.o = urlparse(db_uri)
if not self.o.scheme or \
len(self.o.scheme) < 2: # Dirty hack to avoid issues with urlparse on Windows confusing drive with scheme
Expand All @@ -82,11 +76,8 @@ def __init__(self, db_uri=None, password=None):
self._import_config_data(Session)
self.session = Session()

# Partial URL to avoid printing credentials.
_logger.info(
"Using database: %s://%s:%s/%s",
self.o.scheme or '', self.o.hostname or '', self.o.port or '', self.o.path or ''
)
_logger.info("Using database: %s://%s:%s/%s" % (self.o.scheme or '', self.o.hostname or '',
self.o.port or '', self.o.path or ''))
self.db_uri = db_uri

# VERIFY AND UPDATE DATABASE
Expand Down
25 changes: 24 additions & 1 deletion bitcoinlib/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,32 @@
import sys
import functools
import logging
from logging.handlers import RotatingFileHandler
from bitcoinlib.config.config import *


# Initialize logging
logger = logging.getLogger('bitcoinlib')
logger.setLevel(LOGLEVEL)

if ENABLE_BITCOINLIB_LOGGING:
handler = RotatingFileHandler(str(BCL_LOG_FILE), maxBytes=100 * 1024 * 1024, backupCount=2)
formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s',
datefmt='%Y/%m/%d %H:%M:%S')
handler.setFormatter(formatter)
handler.setLevel(LOGLEVEL)
logger.addHandler(handler)

_logger = logging.getLogger(__name__)
logger.info('WELCOME TO BITCOINLIB - CRYPTOCURRENCY LIBRARY')
logger.info('Version: %s' % BITCOINLIB_VERSION)
logger.info('Logger name: %s' % logging.__name__)
logger.info('Read config from: %s' % BCL_CONFIG_FILE)
logger.info('Directory databases: %s' % BCL_DATABASE_DIR)
logger.info('Default database: %s' % DEFAULT_DATABASE)
logger.info('Logging to: %s' % BCL_LOG_FILE)
logger.info('Directory for data files: %s' % BCL_DATA_DIR)


def script_type_default(witness_type=None, multisig=False, locking_script=False):
"""
Expand Down Expand Up @@ -123,5 +146,5 @@ def deprecated(func):
def new_func(*args, **kwargs):
logging.warning("Call to deprecated function {}.".format(func.__name__))
return func(*args, **kwargs)

return new_func
8 changes: 4 additions & 4 deletions bitcoinlib/networks.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import json
from bitcoinlib.encoding import *
from bitcoinlib.config import config


_logger = logging.getLogger(__name__)
Expand All @@ -45,13 +44,14 @@ def _read_network_definitions():
:return dict: Network definitions
"""

fn = Path(config.BCL_DATA_DIR, 'networks.json')
fn = Path(BCL_DATA_DIR, 'networks.json')
f = fn.open('rb')

try:
network_definitions = json.loads(fn.read_bytes())
network_definitions = json.loads(f.read())
except json.decoder.JSONDecodeError as e:
raise NetworkError("Error reading provider definitions from %s: %s" % (fn, e))

f.close()
return network_definitions


Expand Down
3 changes: 1 addition & 2 deletions bitcoinlib/services/bitcoind.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#

import configparser
from bitcoinlib.config import config
from bitcoinlib.main import *
from bitcoinlib.services.authproxy import AuthServiceProxy
from bitcoinlib.services.baseclient import BaseClient, ClientError
Expand Down Expand Up @@ -87,7 +86,7 @@ def from_config(configfile=None, network='bitcoin', **kwargs):
if cfn.exists():
break
else:
cfn = Path(config.BCL_DATA_DIR, 'config', configfile)
cfn = Path(BCL_DATA_DIR, 'config', configfile)

if not cfn or not cfn.is_file():
raise ConfigError("Config file %s not found. Please install bitcoin client and specify a path to config "
Expand Down
3 changes: 1 addition & 2 deletions bitcoinlib/services/dogecoind.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@

import configparser
from datetime import datetime
from bitcoinlib.config import config
from bitcoinlib.main import *
from bitcoinlib.services.authproxy import AuthServiceProxy
from bitcoinlib.services.baseclient import BaseClient, ClientError
Expand Down Expand Up @@ -85,7 +84,7 @@ def from_config(configfile=None, network='dogecoin', **kargs):
if cfn.exists():
break
else:
cfn = Path(config.BCL_DATA_DIR, 'config', configfile)
cfn = Path(BCL_DATA_DIR, 'config', configfile)
if not cfn or not cfn.is_file():
raise ConfigError("Config file %s not found. Please install dogecoin client and specify a path to config "
"file if path is not default. Or place a config file in .bitcoinlib/dogecoin.conf to "
Expand Down
3 changes: 1 addition & 2 deletions bitcoinlib/services/litecoind.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
#

import configparser
from bitcoinlib.config import config
from bitcoinlib.main import *
from datetime import datetime, timezone
from bitcoinlib.networks import Network
Expand Down Expand Up @@ -85,7 +84,7 @@ def from_config(configfile=None, network='litecoin', **kargs):
if cfn.exists():
break
else:
cfn = Path(config.BCL_DATA_DIR, 'config', configfile)
cfn = Path(BCL_DATA_DIR, 'config', configfile)

if not cfn or not cfn.is_file():
raise ConfigError("Config file %s not found. Please install Litecoin client and specify a path to config "
Expand Down
3 changes: 1 addition & 2 deletions bitcoinlib/services/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
from datetime import timedelta
from sqlalchemy import func
from bitcoinlib import services
from bitcoinlib.config import config
from bitcoinlib.networks import Network
from bitcoinlib.encoding import to_bytes, int_to_varbyteint, varstr
from bitcoinlib.db_cache import *
Expand Down Expand Up @@ -89,7 +88,7 @@ def __init__(self, network=DEFAULT_NETWORK, min_providers=1, max_providers=1, pr
self.network = Network(network)
if min_providers > max_providers:
max_providers = min_providers
fn = Path(config.BCL_DATA_DIR, 'providers.json')
fn = Path(BCL_DATA_DIR, 'providers.json')
f = fn.open("r")

try:
Expand Down
Loading

0 comments on commit a262f98

Please sign in to comment.