From 5f034ec0a5da23cfd29f5f2c2e4500e94d981544 Mon Sep 17 00:00:00 2001 From: Darius Morawiec Date: Mon, 12 Nov 2018 00:35:43 +0100 Subject: [PATCH] release/0.7.0: Improve and replace 'porter' by native sdist --- Makefile | 15 ++---- readme.md | 13 ++--- recipes/function.sh | 13 ----- setup.py | 12 +++-- sklearn_porter/cli/__init__.py | 0 sklearn_porter/{ => cli}/__main__.py | 80 ++++++++++++++++++---------- sklearn_porter/language/PHP.py | 2 +- 7 files changed, 70 insertions(+), 65 deletions(-) delete mode 100644 recipes/function.sh create mode 100644 sklearn_porter/cli/__init__.py rename sklearn_porter/{ => cli}/__main__.py (69%) diff --git a/Makefile b/Makefile index 0a737f68..92d9ae5f 100644 --- a/Makefile +++ b/Makefile @@ -27,11 +27,6 @@ install.requirements.development: install.requirements.examples # Examples # -link: install.function -install.function: - $(info Start [install.function (to .bash_profile)] ...) - $(BASH) recipes/install.function.sh - open.examples: install.requirements.examples examples.pid examples.pid: @@ -47,7 +42,11 @@ stop.examples: examples.pid # Development # -all: lint test clean +all: lint test jupytext clean + +lint: install.requirements.development + $(info Start [lint] ...) + find ./sklearn_porter -name '*.py' -exec pylint {} \; test: install.requirements.development $(info Start [test] ...) @@ -61,10 +60,6 @@ test.sample: install.requirements.development TEST_N_EXISTING_FEATURE_SETS=3 \ $(BASH) recipes/run.tests.sh -lint: install.requirements.development - $(info Start [lint] ...) - find ./sklearn_porter -name '*.py' -exec pylint {} \; - jupytext: install.requirements.development $(info Start [jupytext] ...) $(BASH) recipes/run.jupytext.sh diff --git a/readme.md b/readme.md index a052190a..fc65c862 100644 --- a/readme.md +++ b/readme.md @@ -226,17 +226,14 @@ $ make stop.examples ## Command-line interface -In general you can use the porter on the command line. Either you use `python -m sklearn_porter [-h]` or you install an executable to use `porter [-h]` directly: - -```bash -$ make link -``` +In general you can use the porter on the command line: ``` -$ porter [-h] --input [--output ] \ - [--class_name ] [--method_name ] \ - [--c] [--java] [--js] [--go] [--php] [--ruby] \ +$ porter --input [--output ] + [--class_name ] [--method_name ] [--export] [--checksum] [--data] [--pipe] + [--c] [--java] [--js] [--go] [--php] [--ruby] + [--help] [--version] ``` The following example shows how you can save a trained estimator to the [pickle format](http://scikit-learn.org/stable/modules/model_persistence.html#persistence-example): diff --git a/recipes/function.sh b/recipes/function.sh deleted file mode 100644 index a7bc8a18..00000000 --- a/recipes/function.sh +++ /dev/null @@ -1,13 +0,0 @@ - -# porter by https://github.com/nok/sklearn-porter/ -function porter() { - if [[ "$(pip list --format=columns | grep sklearn-porter)" ]] - then - local CMDS="from distutils.sysconfig import get_python_lib;\ - print(get_python_lib())" - local LIBS=$(python -c "$CMDS") - python $LIBS/sklearn_porter "$@" - else - echo "Error: The module 'sklearn-porter' could not be found. Is 'sklearn-porter' installed and the right environment active?" - fi -} diff --git a/setup.py b/setup.py index 94620014..302fd288 100644 --- a/setup.py +++ b/setup.py @@ -3,11 +3,9 @@ import os from setuptools import setup from setuptools import find_packages -from typing import List def read_version(): - # type: () -> str """Read the module version from __version__.txt""" src_dir = os.path.abspath(os.path.dirname(__file__)) ver_file = os.path.join(src_dir, 'sklearn_porter', '__version__.txt') @@ -19,7 +17,6 @@ def read_version(): def parse_requirements(): - # type: () -> List[str] """Parse the modules from requirements.txt""" src_dir = os.path.abspath(os.path.dirname(__file__)) req_file = os.path.join(src_dir, 'requirements.txt') @@ -27,16 +24,21 @@ def parse_requirements(): reqs = [req.strip() for req in reqs if 'git+' not in req] return reqs - setup( name='sklearn-porter', packages=find_packages(exclude=["tests.*", "tests"]), include_package_data=True, version=read_version(), - description='Transpile trained scikit-learn models to C, Java, JavaScript and others.', + description='Transpile trained scikit-learn models ' + 'to C, Java, JavaScript and others.', author='Darius Morawiec', author_email='ping@nok.onl', url='https://github.com/nok/sklearn-porter/tree/stable', + entry_points={ + 'console_scripts': [ + 'porter = sklearn_porter.cli.__main__:main' + ], + }, classifiers=[ 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.7', diff --git a/sklearn_porter/cli/__init__.py b/sklearn_porter/cli/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/sklearn_porter/__main__.py b/sklearn_porter/cli/__main__.py similarity index 69% rename from sklearn_porter/__main__.py rename to sklearn_porter/cli/__main__.py index c726acdd..e2e4095d 100644 --- a/sklearn_porter/__main__.py +++ b/sklearn_porter/cli/__main__.py @@ -1,5 +1,7 @@ # -*- coding: utf-8 -*- +from __future__ import print_function + import sys import os import os.path @@ -7,15 +9,33 @@ from sklearn.externals import joblib -sys.path.append(os.path.join(os.path.dirname(__file__), '..')) from sklearn_porter.Porter import Porter +from sklearn_porter.language import * + + +header = ''' + # +### ### ### ### ### ### +# # # # # # ## # +### ### # ## ### # v{} +# + +Transpile trained scikit-learn estimators +to C, Java, JavaScript and others. + +Usage: + porter --input INPUT [--output OUTPUT] + [--class_name CLASS_NAME] [--method_name METHOD_NAME] + [--export] [--checksum] [--data] [--pipe] + [--c] [--java] [--js] [--go] [--php] [--ruby] + [--help] [--version]'''.format(Porter.__version__) def parse_args(args): - parser = argparse.ArgumentParser( - description=('Transpile trained scikit-learn estimators ' - 'to C, Java, JavaScript and others.'), - epilog='More details on: https://github.com/nok/sklearn-porter') + epilog = 'More details on https://github.com/nok/sklearn-porter' + description = '' + parser = argparse.ArgumentParser(description=description, + epilog=epilog, usage=header) # Remove the default arguments group: parser._action_groups.pop() @@ -27,7 +47,7 @@ def parse_args(args): help=('Path to an exported estimator in pickle ' '(.pkl) format.')) - # Optional arguments: +# Optional arguments: optional = parser.add_argument_group('Optional arguments') optional.add_argument('--output', '-o', required=False, @@ -46,13 +66,13 @@ def parse_args(args): default=False, action='store_true', help='Whether to export the model data or not.') - optional.add_argument('--checksum', + optional.add_argument('--checksum', '-s', required=False, default=False, action='store_true', help='Whether to append the checksum to the ' 'filename or not.') - optional.add_argument('--data', + optional.add_argument('--data', '-d', required=False, default=False, action='store_true', @@ -62,22 +82,28 @@ def parse_args(args): default=False, action='store_true', help='Print the transpiled estimator to the console.') - languages = { - 'c': 'C', - 'java': 'Java', - 'js': 'JavaScript', - 'go': 'Go', - 'php': 'PHP', - 'ruby': 'Ruby' - } - optional.add_argument('--language', '-l', - choices=languages.keys(), - default='java', - required=False, - help=argparse.SUPPRESS) - for key, lang in list(languages.items()): - help = 'Set \'{}\' as the target programming language.'.format(lang) - optional.add_argument('--{}'.format(key), action='store_true', help=help) + + # Languages: + langs = parser.add_argument_group('Programming languages') + languages = {key: clazz.LABEL for key, clazz in list(LANGUAGES.items())} + langs.add_argument('--language', '-l', + choices=languages.keys(), + default='java', + required=False, + help=argparse.SUPPRESS) + for key, label in list(languages.items()): + help = 'Set \'{}\' as the target programming language.'.format(label) + langs.add_argument('--{}'.format(key), action='store_true', help=help) + + # Extra arguments: + extras = parser.add_argument_group('Extra arguments') + extras.add_argument('--version', '-v', action='version', + version='sklearn-porter v{}'.format(Porter.__version__)) + + # Show help by default: + if len(sys.argv) == 1: + parser.print_help(sys.stderr) + sys.exit(1) # Return dictionary: args = vars(parser.parse_args(args)) @@ -119,10 +145,8 @@ def main(): with_export = bool(args.get('export')) with_checksum = bool(args.get('checksum')) porter = Porter(estimator, language=language) - output = porter.export(class_name=class_name, - method_name=method_name, - export_dir=dest_dir, - export_data=with_export, + output = porter.export(class_name=class_name, method_name=method_name, + export_dir=dest_dir, export_data=with_export, export_append_checksum=with_checksum, details=True) except Exception as exception: diff --git a/sklearn_porter/language/PHP.py b/sklearn_porter/language/PHP.py index d613c2e9..055a87c1 100644 --- a/sklearn_porter/language/PHP.py +++ b/sklearn_porter/language/PHP.py @@ -4,7 +4,7 @@ class PHP(object): KEY = 'php' - LABEL = 'KEY' + LABEL = 'PHP' DEPENDENCIES = ['php'] TEMP_DIR = 'php'