Skip to content
This repository has been archived by the owner on Nov 15, 2021. It is now read-only.

Initial Django inspired component loading #719

Merged
merged 8 commits into from
Nov 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ All notable changes to this project are documented in this file.
- Fix RPC's ``getaccountstate`` response schema to match ``neo-cli`` `#714 <https://github.com/CityOfZion/neo-python/issues/714>`
- Add fix to ensure tx is saved to wallet when sent using RPC
- Add bad peers to the ``getpeers`` RPC method `#715 <https://github.com/CityOfZion/neo-python/pull/715>`
- Introduce Django inspired component loading for REST and RPC server
- Allow a raw tx to be build without an active blockchain db in the environment


Expand Down
7 changes: 7 additions & 0 deletions neo/Settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,11 @@ class SettingsHolder:

VERSION_NAME = "/NEO-PYTHON:%s/" % __version__

RPC_SERVER = None
REST_SERVER = None
DEFAULT_RPC_SERVER = 'neo.api.JSONRPC.JsonRpcApi.JsonRpcApi'
DEFAULT_REST_SERVER = 'neo.api.REST.RestApi.RestApi'

# Logging settings
log_level = None
log_smart_contract_events = False
Expand Down Expand Up @@ -210,6 +215,8 @@ def get_config_and_warn(key, default, abort=False):
self.NOTIFICATION_DB_PATH = config.get('NotificationDataPath', 'Chains/notification_data')
self.SERVICE_ENABLED = config.get('ServiceEnabled', False)
self.COMPILER_NEP_8 = config.get('CompilerNep8', False)
self.REST_SERVER = config.get('RestServer', self.DEFAULT_REST_SERVER)
self.RPC_SERVER = config.get('RPCServer', self.DEFAULT_RPC_SERVER)

def setup_mainnet(self):
""" Load settings from the mainnet JSON config file """
Expand Down
29 changes: 29 additions & 0 deletions neo/Utils/plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import importlib


def load_class_from_path(path_and_class: str):
"""
Dynamically load a class from a module at the specified path

Args:
path_and_class: relative path where to find the module and its class name
i.e. 'neo.<package>.<package>.<module>.<class name>'

Raises:
ValueError: if the Module or Class is not found.

Returns:
class object
"""
try:
module_path = '.'.join(path_and_class.split('.')[:-1])
module = importlib.import_module(module_path)
except ImportError as err:
raise ValueError(f"Failed to import module {module_path} with error: {err}")

try:
class_name = path_and_class.split('.')[-1]
class_obj = getattr(module, class_name)
return class_obj
except AttributeError as err:
raise ValueError(f"Failed to get class {class_name} with error: {err}")
40 changes: 18 additions & 22 deletions neo/bin/api_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""
API server to run the JSON-RPC and REST API.

Uses neo.api.JSONRPC.JsonRpcApi or neo.api.JSONRPC.ExtendedJsonRpcApi and neo.api.REST.RestApi
Uses servers specified in protocol.xxx.json files

Print the help and all possible arguments:

Expand Down Expand Up @@ -33,6 +33,7 @@
* https://twistedmatrix.com/documents/17.9.0/api/twisted.logger.STDLibLogObserver.html
"""
import os
import sys
import argparse
import threading
from time import sleep
Expand All @@ -52,16 +53,14 @@
# neo methods and modules
from neo.Core.Blockchain import Blockchain
from neo.Implementations.Blockchains.LevelDB.LevelDBBlockchain import LevelDBBlockchain
from neo.api.JSONRPC.JsonRpcApi import JsonRpcApi
from neo.api.JSONRPC.ExtendedJsonRpcApi import ExtendedJsonRpcApi
from neo.Implementations.Notifications.LevelDB.NotificationDB import NotificationDB
from neo.api.REST.RestApi import RestApi
from neo.Wallets.utils import to_aes_key
from neo.Implementations.Wallets.peewee.UserWallet import UserWallet

from neo.Network.NodeLeader import NodeLeader
from neo.Settings import settings

from neo.Utils.plugin import load_class_from_path
import neo.Settings

# Logfile default settings (only used if --logfile arg is used)
LOGFILE_MAX_BYTES = 5e7 # 50 MB
Expand Down Expand Up @@ -128,9 +127,6 @@ def main():
# host
parser.add_argument("--host", action="store", type=str, help="Hostname ( for example 127.0.0.1)", default="0.0.0.0")

# extended json-rpc api
parser.add_argument("--extended-rpc", action="store_true", default=False, help="Use extended json-rpc api")

# Now parse
args = parser.parse_args()
# print(args)
Expand Down Expand Up @@ -249,28 +245,28 @@ def loopingCallErrorHandler(error):
d.setDaemon(True) # daemonizing the thread will kill it when the main thread is quit
d.start()

if args.port_rpc and args.extended_rpc:
logger.info("Starting extended json-rpc api server on http://%s:%s" % (args.host, args.port_rpc))
api_server_rpc = ExtendedJsonRpcApi(args.port_rpc, wallet=wallet)
endpoint_rpc = "tcp:port={0}:interface={1}".format(args.port_rpc, args.host)
endpoints.serverFromString(reactor, endpoint_rpc).listen(Site(api_server_rpc.app.resource()))
# reactor.listenTCP(int(args.port_rpc), server.Site(api_server_rpc))
# api_server_rpc.app.run(args.host, args.port_rpc)

elif args.port_rpc:
if args.port_rpc:
logger.info("Starting json-rpc api server on http://%s:%s" % (args.host, args.port_rpc))
api_server_rpc = JsonRpcApi(args.port_rpc, wallet=wallet)
try:
rpc_class = load_class_from_path(settings.RPC_SERVER)
except ValueError as err:
logger.error(err)
sys.exit()
api_server_rpc = rpc_class(args.port_rpc, wallet=wallet)

endpoint_rpc = "tcp:port={0}:interface={1}".format(args.port_rpc, args.host)
endpoints.serverFromString(reactor, endpoint_rpc).listen(Site(api_server_rpc.app.resource()))
# reactor.listenTCP(int(args.port_rpc), server.Site(api_server_rpc))
# api_server_rpc.app.run(args.host, args.port_rpc)

if args.port_rest:
logger.info("Starting REST api server on http://%s:%s" % (args.host, args.port_rest))
api_server_rest = RestApi()
try:
rest_api = load_class_from_path(settings.REST_SERVER)
except ValueError as err:
logger.error(err)
sys.exit()
api_server_rest = rest_api()
endpoint_rest = "tcp:port={0}:interface={1}".format(args.port_rest, args.host)
endpoints.serverFromString(reactor, endpoint_rest).listen(Site(api_server_rest.app.resource()))
# api_server_rest.app.run(args.host, args.port_rest)

reactor.run()

Expand Down
4 changes: 3 additions & 1 deletion neo/data/protocol.mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
"BootstrapFiles": "https://s3.us-east-2.amazonaws.com/cityofzion/bootstrap_latest",
"DebugStorage": 1,
"AcceptIncomingPeers": false,
"CompilerNep8": false
"CompilerNep8": false,
"RestServer": "neo.api.REST.RestApi.RestApi",
"RPCServer": "neo.api.JSONRPC.JsonRpcApi.JsonRpcApi"
}
}
4 changes: 3 additions & 1 deletion neo/data/protocol.privnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
"BootstrapFiles": "https://s3.us-east-2.amazonaws.com/cityofzion/bootstrap_latest",
"DebugStorage": 1,
"AcceptIncomingPeers": false,
"CompilerNep8":false
"CompilerNep8": false,
"RestServer": "neo.api.REST.RestApi.RestApi",
"RPCServer": "neo.api.JSONRPC.JsonRpcApi.JsonRpcApi"
}
}
4 changes: 3 additions & 1 deletion neo/data/protocol.testnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
"BootstrapFiles": "https://s3.us-east-2.amazonaws.com/cityofzion/bootstrap_latest",
"DebugStorage": 1,
"AcceptIncomingPeers": false,
"CompilerNep8": false
"CompilerNep8": false,
"RestServer": "neo.api.REST.RestApi.RestApi",
"RPCServer": "neo.api.JSONRPC.JsonRpcApi.JsonRpcApi"
},
"ProtocolConfiguration": {
"AddressVersion": 23,
Expand Down
4 changes: 3 additions & 1 deletion neo/data/protocol.unittest-net.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
"AcceptIncomingPeers": false,
"CompilerNep8": true,
"BootstrapName": "fauxnet",
"BootstrapFiles": "this_does_not_exist_for_this_network"
"BootstrapFiles": "this_does_not_exist_for_this_network",
"RestServer": "neo.api.REST.RestApi.RestApi",
"RPCServer": "neo.api.JSONRPC.JsonRpcApi.JsonRpcApi"
}
}