From b5ac0a412e1958cdff581d14b818bf042293267f Mon Sep 17 00:00:00 2001 From: Cédric Ollivier Date: Fri, 18 Aug 2017 16:20:33 +0200 Subject: Add domino package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's required by Functest to ease integrating all OPNFV projects and their requirements. It also synchronizes requirements with stable/ocata and renames domino-cli to domino_cli to conform with common module names. It defines scripts and console_scripts to rely on $PATH. run_multimode.sh is adapted to correctly call client, cli and server. It should be noted that run.sh can raise conflicts if it's already provided by another OPNFV package and that run_on_remote_nodes.sh is not fully updated. Otherwise it obliges all OPNFV installers to be updated as well. run.sh is unchanged and it's called by releng from local directory. It may rise runtime issues if several files are not loaded via pkg_resources. Change-Id: Ibd9dd56f316609180aa432c6b7ee5a375d9af674 Signed-off-by: Cédric Ollivier --- DominoClient.py | 7 +++-- DominoServer.py | 10 ++++---- domino-cli.py | 62 --------------------------------------------- domino_cli.py | 62 +++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 15 +++++------ setup.cfg | 18 +++++++++++++ setup.py | 22 ++++++++++++++++ tests/run.sh | 24 +++++++++--------- tests/run_multinode.sh | 44 ++++++++++++++++---------------- tests/run_on_remotenodes.sh | 20 +++++++-------- tests/test_partitioner.py | 7 ++--- 11 files changed, 164 insertions(+), 127 deletions(-) delete mode 100755 domino-cli.py create mode 100755 domino_cli.py create mode 100644 setup.cfg create mode 100644 setup.py diff --git a/DominoClient.py b/DominoClient.py index 32d1433..b417186 100755 --- a/DominoClient.py +++ b/DominoClient.py @@ -438,13 +438,13 @@ class DominoClient: elif RPCmessage.messageType == QUERY: logging.debug('RPC Timeout for message type: QUERY') -def main(argv): +def main(): client = DominoClient() loglevel = LOGLEVEL interactive = INTERACTIVE #process input arguments try: - opts, args = getopt.getopt(argv,"hc:p:i:l:",["conf=","port=","ipaddr=","log=","iac=","cliport=","uuid=","regmod="]) + opts, args = getopt.getopt(sys.argv[1:],"hc:p:i:l:",["conf=","port=","ipaddr=","log=","iac=","cliport=","uuid=","regmod="]) except getopt.GetoptError: print 'DominoClient.py -c/--conf -p/--port -i/--ipaddr -l/--log --iac=true/false --cliport ' sys.exit(2) @@ -486,5 +486,4 @@ def main(argv): client.start_communicationService() if __name__ == "__main__": - main(sys.argv[1:]) - + sys.exit(main()) diff --git a/DominoServer.py b/DominoServer.py index 8716799..dc4a9b9 100755 --- a/DominoServer.py +++ b/DominoServer.py @@ -464,15 +464,15 @@ class DominoServer: logging.debug('RPC Timeout for message type: PUSH') # TBD: handle each RPC timeout separately -def main(argv): +def main(): server = DominoServer() loglevel = LOGLEVEL #process input arguments try: - opts, args = getopt.getopt(argv,"hc:l:",["conf=","log="]) + opts, args = getopt.getopt(sys.argv[1:],"hc:l:",["conf=","log="]) except getopt.GetoptError: - print 'DominoServer.py -c/--conf -l/--log ' - sys.exit(2) + print 'DominoServer.py -c/--conf -l/--log ' + sys.exit(2) for opt, arg in opts: if opt == '-h': print 'DominoServer.py -c/--conf -l/--log ' @@ -527,4 +527,4 @@ def main(argv): print 'done.' if __name__ == "__main__": - main(sys.argv[1:]) + sys.exit(main()) diff --git a/domino-cli.py b/domino-cli.py deleted file mode 100755 index d9245b3..0000000 --- a/domino-cli.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python - -#Copyright 2016 Open Platform for NFV Project, Inc. and its contributors -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# http://www.apache.org/licenses/LICENSE-2.0 -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sys, glob, getopt -import getopt - -sys.path.insert(0, glob.glob('./lib')[0]) - -from dominoCLI import DominoClientCLI -from dominoCLI.ttypes import * -from dominoCLI.constants import * - -from thrift import Thrift -from thrift.transport import TSocket -from thrift.transport import TTransport -from thrift.protocol import TBinaryProtocol - -#Load configuration parameters -from domino_conf import * - -def main(argv, cli_port): - #cli_port = DOMINO_CLI_PORT - - try: - # Make socket - # NOTE that domino-cli.py and DominoClient.py are assumed to be run in the same machine - transport = TSocket.TSocket('localhost', int(cli_port)) - # Buffering is critical. Raw sockets are very slow - transport = TTransport.TBufferedTransport(transport) - # Wrap in a protocol - protocol = TBinaryProtocol.TBinaryProtocol(transport) - - # Create a client to use the protocol encoder - client = DominoClientCLI.Client(protocol) - - # Connect! - transport.open() - - CLImsg = CLIMessage() - CLImsg.CLI_input = argv - CLIrespmsg = client.d_CLI(CLImsg) - if CLIrespmsg.CLI_response is not None: - print CLIrespmsg.CLI_response - except Thrift.TException, tx: - print '%s' % (tx.message) - -if __name__ == "__main__": - if len(sys.argv) >= 2: - main(sys.argv[2:], sys.argv[1]) - else: - print 'domino-cli.py ...' - sys.exit(2) diff --git a/domino_cli.py b/domino_cli.py new file mode 100755 index 0000000..5cb0b1c --- /dev/null +++ b/domino_cli.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +#Copyright 2016 Open Platform for NFV Project, Inc. and its contributors +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# http://www.apache.org/licenses/LICENSE-2.0 +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import sys, glob, getopt +import getopt + +sys.path.insert(0, glob.glob('./lib')[0]) + +from dominoCLI import DominoClientCLI +from dominoCLI.ttypes import * +from dominoCLI.constants import * + +from thrift import Thrift +from thrift.transport import TSocket +from thrift.transport import TTransport +from thrift.protocol import TBinaryProtocol + +#Load configuration parameters +from domino_conf import * + +def main(): + #cli_port = DOMINO_CLI_PORT + if len(sys.argv) >= 2: + cli_port = sys.argv[1] + else: + print 'domino-cli.py ...' + return 2 + try: + # Make socket + # NOTE that domino-cli.py and DominoClient.py are assumed to be run in the same machine + transport = TSocket.TSocket('localhost', int(cli_port)) + # Buffering is critical. Raw sockets are very slow + transport = TTransport.TBufferedTransport(transport) + # Wrap in a protocol + protocol = TBinaryProtocol.TBinaryProtocol(transport) + + # Create a client to use the protocol encoder + client = DominoClientCLI.Client(protocol) + + # Connect! + transport.open() + + CLImsg = CLIMessage() + CLImsg.CLI_input = sys.argv[2:] + CLIrespmsg = client.d_CLI(CLImsg) + if CLIrespmsg.CLI_response is not None: + print CLIrespmsg.CLI_response + except Thrift.TException, tx: + print '%s' % (tx.message) + +if __name__ == "__main__": + sys.exit(main()) diff --git a/requirements.txt b/requirements.txt index e0760f6..7989e45 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,8 @@ -# The order of packages is significant, because pip processes them in the order -# of appearance. Changing the order has an impact on the overall integration -# process, which may cause wedges in the gate later. -pbr>=1.6 # Apache-2.0 -Babel>=1.3 # BSD -cliff!=1.16.0,!=1.17.0,>=1.15.0 # Apache-2.0 -PyYAML>=3.1.0 # MIT +pbr>=1.8 # Apache-2.0 +Babel>=2.3.4 # BSD +cliff>=2.3.0 # Apache-2.0 +PyYAML>=3.10.0 # MIT python-dateutil>=2.4.2 # BSD six>=1.9.0 # MIT -tosca-parser>=0.4.0 # Apache-2.0 -heat-translator>=0.5.0 # Apache-2.0 +tosca-parser>=0.7.0 # Apache-2.0 +heat-translator>=0.4.0 # Apache-2.0 diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..7526e38 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,18 @@ +[metadata] +name = domino +version = 5 +home-page = https://wiki.opnfv.org/display/domino/Domino+Home + +[files] +packages = . +scripts = + tests/run_multinode.sh + tests/run_on_remotenodes.sh + tests/run.sh + +[entry_points] +console_scripts = + DominoClient = DominoClient:main + DominoServer = DominoServer:main + domino_cli = domino_cli:main + test_partitioner = tests.test_partitioner:main diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..a1e9b3b --- /dev/null +++ b/setup.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +# Copyright (c) 2017 Orange and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import setuptools + +# In python < 2.7.4, a lazy loading of package `pbr` will break +# setuptools if some other modules registered functions in `atexit`. +# solution from: http://bugs.python.org/issue15881#msg170215 +try: + import multiprocessing # noqa +except ImportError: + pass + +setuptools.setup( + setup_requires=['pbr>=1.8'], + pbr=True) diff --git a/tests/run.sh b/tests/run.sh index 7da8f36..3971009 100755 --- a/tests/run.sh +++ b/tests/run.sh @@ -111,42 +111,42 @@ start_client2 sleep 1 echo "Test Heartbeat" -python domino-cli.py $CLIENT1_CLIPORT heartbeat +python domino_cli.py $CLIENT1_CLIPORT heartbeat sleep 1 echo "Test Subscribe API" -python domino-cli.py $CLIENT1_CLIPORT subscribe -t hot \ +python domino_cli.py $CLIENT1_CLIPORT subscribe -t hot \ -l tosca.policies.Placement:properties:region:nova-1 sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top OVERWRITE +python domino_cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top OVERWRITE sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top DELETE +python domino_cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top DELETE sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe \ +python domino_cli.py $CLIENT1_CLIPORT subscribe \ -l tosca.policies.Placement:properties:region:nova-2 sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe \ +python domino_cli.py $CLIENT1_CLIPORT subscribe \ -l tosca.policies.Placement:properties:region:nova-3 \ --lop OVERWRITE sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe \ +python domino_cli.py $CLIENT1_CLIPORT subscribe \ -l tosca.policies.Placement:properties:region:nova-3 \ --lop DELETE sleep 1 echo "Test Publish API" -python domino-cli.py $CLIENT1_CLIPORT publish -t "$toscafile_test1" +python domino_cli.py $CLIENT1_CLIPORT publish -t "$toscafile_test1" sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe \ +python domino_cli.py $CLIENT1_CLIPORT subscribe \ -l tosca.policies.Placement.Geolocation:properties:region:us-west-1 sleep 1 -python domino-cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1" +python domino_cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1" sleep 1 -TUID=$(python domino-cli.py $CLIENT2_CLIPORT list-tuids | cut -c3-34) +TUID=$(python domino_cli.py $CLIENT2_CLIPORT list-tuids | cut -c3-34) echo $TUID sleep 1 -python domino-cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1" -k "$TUID" +python domino_cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1" -k "$TUID" #echo "Stopping Domino Client 1..." #stop_client1 diff --git a/tests/run_multinode.sh b/tests/run_multinode.sh index 7da8f36..5ccdf65 100755 --- a/tests/run_multinode.sh +++ b/tests/run_multinode.sh @@ -26,31 +26,31 @@ server_log=./tests/logdata/server.log start_server() { - pgrep -f "python DominoServer.py" && return 0 - python DominoServer.py --log "$LOGLEVEL" > "$server_log" 2>&1 & + pgrep -f "DominoServer" && return 0 + DominoServer --log "$LOGLEVEL" > "$server_log" 2>&1 & } stop_server() { - pgrep -f "python DominoServer.py" || return 0 - kill $(pgrep -f "python DominoServer.py") + pgrep -f "DominoServer" || return 0 + kill $(pgrep -f "DominoServer") #cat server.log } start_client1() { - #pgrep -f "python DominoClient.py -p $CLIENT1_PORT" && return 0 - python DominoClient.py -p $CLIENT1_PORT --cliport $CLIENT1_CLIPORT \ + #pgrep -f "DominoClient -p $CLIENT1_PORT" && return 0 + DominoClient -p $CLIENT1_PORT --cliport $CLIENT1_CLIPORT \ --log "$LOGLEVEL" > "$client1_log" 2>&1 & } start_client2() { - #pgrep -f "python DominoClient.py -p $CLIENT2_PORT" && return 0 - python DominoClient.py -p $CLIENT2_PORT --cliport $CLIENT2_CLIPORT \ + #pgrep -f "DominoClient -p $CLIENT2_PORT" && return 0 + DominoClient -p $CLIENT2_PORT --cliport $CLIENT2_CLIPORT \ --log "$LOGLEVEL" > "$client2_log" 2>&1 & } stop_clients() { - pgrep -f "python DominoClient.py" || return 0 - kill $(pgrep -f "python DominoClient.py") + pgrep -f "DominoClient" || return 0 + kill $(pgrep -f "DominoClient") #cat client1.log } @@ -111,42 +111,42 @@ start_client2 sleep 1 echo "Test Heartbeat" -python domino-cli.py $CLIENT1_CLIPORT heartbeat +domino_cli $CLIENT1_CLIPORT heartbeat sleep 1 echo "Test Subscribe API" -python domino-cli.py $CLIENT1_CLIPORT subscribe -t hot \ +domino_cli $CLIENT1_CLIPORT subscribe -t hot \ -l tosca.policies.Placement:properties:region:nova-1 sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top OVERWRITE +domino_cli $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top OVERWRITE sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top DELETE +domino_cli $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top DELETE sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe \ +domino_cli $CLIENT1_CLIPORT subscribe \ -l tosca.policies.Placement:properties:region:nova-2 sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe \ +domino_cli $CLIENT1_CLIPORT subscribe \ -l tosca.policies.Placement:properties:region:nova-3 \ --lop OVERWRITE sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe \ +domino_cli $CLIENT1_CLIPORT subscribe \ -l tosca.policies.Placement:properties:region:nova-3 \ --lop DELETE sleep 1 echo "Test Publish API" -python domino-cli.py $CLIENT1_CLIPORT publish -t "$toscafile_test1" +domino_cli $CLIENT1_CLIPORT publish -t "$toscafile_test1" sleep 1 -python domino-cli.py $CLIENT1_CLIPORT subscribe \ +domino_cli $CLIENT1_CLIPORT subscribe \ -l tosca.policies.Placement.Geolocation:properties:region:us-west-1 sleep 1 -python domino-cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1" +domino_cli $CLIENT2_CLIPORT publish -t "$toscafile_test1" sleep 1 -TUID=$(python domino-cli.py $CLIENT2_CLIPORT list-tuids | cut -c3-34) +TUID=$(domino_cli $CLIENT2_CLIPORT list-tuids | cut -c3-34) echo $TUID sleep 1 -python domino-cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1" -k "$TUID" +domino_cli $CLIENT2_CLIPORT publish -t "$toscafile_test1" -k "$TUID" #echo "Stopping Domino Client 1..." #stop_client1 diff --git a/tests/run_on_remotenodes.sh b/tests/run_on_remotenodes.sh index f60f469..a371427 100755 --- a/tests/run_on_remotenodes.sh +++ b/tests/run_on_remotenodes.sh @@ -132,30 +132,30 @@ if [ "$IS_IPandKEY_CONFIGURED" = "true" ]; then echo "Test Heartbeat" - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino-cli.py $CLIENT1_CLIPORT heartbeat'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino_cli.py $CLIENT1_CLIPORT heartbeat'" sleep 1 echo "Test Subscribe API" - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino-cli.py $CLIENT1_CLIPORT subscribe -t hot -l tosca.policies.Placement:properties:region:nova-1'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino_cli.py $CLIENT1_CLIPORT subscribe -t hot -l tosca.policies.Placement:properties:region:nova-1'" sleep 1 - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino-cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top OVERWRITE'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino_cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top OVERWRITE'" sleep 1 - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino-cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top DELETE'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino_cli.py $CLIENT1_CLIPORT subscribe -t dummy1,dummy2 --top DELETE'" sleep 1 - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino-cli.py $CLIENT1_CLIPORT subscribe -l tosca.policies.Placement:properties:region:nova-2'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino_cli.py $CLIENT1_CLIPORT subscribe -l tosca.policies.Placement:properties:region:nova-2'" sleep 1 - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino-cli.py $CLIENT1_CLIPORT subscribe -l tosca.policies.Placement:properties:region:nova-3 --lop OVERWRITE'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino_cli.py $CLIENT1_CLIPORT subscribe -l tosca.policies.Placement:properties:region:nova-3 --lop OVERWRITE'" sleep 1 - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino-cli.py $CLIENT1_CLIPORT subscribe -l tosca.policies.Placement:properties:region:nova-3 --lop DELETE'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino_cli.py $CLIENT1_CLIPORT subscribe -l tosca.policies.Placement:properties:region:nova-3 --lop DELETE'" sleep 1 echo "Test Publish API" - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_3" "sh -c 'cd domino; python domino-cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1"'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_3" "sh -c 'cd domino; python domino_cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1"'" sleep 1 - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino-cli.py $CLIENT1_CLIPORT subscribe -l tosca.policies.Placement.Geolocation:properties:region:us-west-1'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_2" "sh -c 'cd domino; python domino_cli.py $CLIENT1_CLIPORT subscribe -l tosca.policies.Placement.Geolocation:properties:region:us-west-1'" sleep 1 - ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_3" "sh -c 'cd domino; python domino-cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1"'" + ssh $ssh_opts -i "$SSH_KEY_PATH" "$USERNAME"@"$CONTROLLER_NODE_3" "sh -c 'cd domino; python domino_cli.py $CLIENT2_CLIPORT publish -t "$toscafile_test1"'" echo "done" diff --git a/tests/test_partitioner.py b/tests/test_partitioner.py index 5634c01..439f84c 100755 --- a/tests/test_partitioner.py +++ b/tests/test_partitioner.py @@ -20,7 +20,8 @@ sys.path.insert(0, glob.glob('./lib')[0]) from mapper import * from partitioner import * -def main(argv): +def main(): + argv = sys.argv[1:] try: #tosca = ToscaTemplate(argv[0]) tpl = yaml.load(file(argv[0],'r')) @@ -52,6 +53,6 @@ def main(argv): except: print('Unexpected error: %s', sys.exc_info()[0]) raise -if __name__ == "__main__": - main(sys.argv[1:]) +if __name__ == "__main__": + sys.exit(main()) -- cgit 1.2.3-korg