You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by jx...@apache.org on 2017/10/16 03:18:08 UTC
[incubator-mxnet] branch master updated: generate op frontend code
for IDE auto-complete (#8244)
This is an automated email from the ASF dual-hosted git repository.
jxie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git
The following commit(s) were added to refs/heads/master by this push:
new 99099fa generate op frontend code for IDE auto-complete (#8244)
99099fa is described below
commit 99099faa2422d1307d5a9a6c58a5d28ab0ea163f
Author: Sheng Zha <sz...@users.noreply.github.com>
AuthorDate: Sun Oct 15 20:18:06 2017 -0700
generate op frontend code for IDE auto-complete (#8244)
* decouple codegen and register
* address comments on refactor
* auto generate code
* trigger test
---
.gitignore | 5 +
python/mxnet/base.py | 134 +++++++++++++++----
python/mxnet/ndarray/__init__.py | 7 +-
python/mxnet/ndarray/_internal.py | 30 ++++-
python/mxnet/ndarray/contrib.py | 7 +
python/mxnet/ndarray/linalg.py | 7 +
python/mxnet/ndarray/ndarray.py | 2 +-
python/mxnet/ndarray/op.py | 161 +----------------------
python/mxnet/ndarray/{op.py => register.py} | 88 ++++++-------
python/mxnet/ndarray/sparse.py | 32 ++---
python/mxnet/symbol/__init__.py | 7 +-
python/mxnet/symbol/_internal.py | 33 ++++-
python/mxnet/symbol/contrib.py | 7 +
python/mxnet/symbol/linalg.py | 7 +
python/mxnet/symbol/op.py | 193 +---------------------------
python/mxnet/symbol/{op.py => register.py} | 103 +++++++--------
python/mxnet/symbol/sparse.py | 7 +
python/mxnet/symbol/symbol.py | 3 +-
python/setup.py | 20 ++-
19 files changed, 356 insertions(+), 497 deletions(-)
diff --git a/.gitignore b/.gitignore
index 7ca76c9..2028aa7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -148,3 +148,8 @@ target
bin/im2rec
model/
+
+# generated function signature for IDE auto-complete
+python/mxnet/symbol/gen_*
+python/mxnet/ndarray/gen_*
+python/.eggs
diff --git a/python/mxnet/base.py b/python/mxnet/base.py
index fe80bd6..138bb4d 100644
--- a/python/mxnet/base.py
+++ b/python/mxnet/base.py
@@ -20,6 +20,7 @@
"""ctypes library of mxnet and helper functions."""
from __future__ import absolute_import
+import os
import sys
import ctypes
import atexit
@@ -392,7 +393,7 @@ def _init_op_module(root_namespace, module_name, make_op_func):
Top level module name, `mxnet` in the current cases.
module_name : str
Second level module name, `ndarray` and `symbol` in the current cases.
- make_op_func : str
+ make_op_func : function
Function for creating op functions for `ndarray` and `symbol` modules.
"""
plist = ctypes.POINTER(ctypes.c_char_p)()
@@ -418,29 +419,114 @@ def _init_op_module(root_namespace, module_name, make_op_func):
for name in op_names:
hdl = OpHandle()
check_call(_LIB.NNGetOpHandle(c_str(name), ctypes.byref(hdl)))
- function = make_op_func(hdl, name)
- op_name_prefix = _get_op_name_prefix(function.__name__)
+ op_name_prefix = _get_op_name_prefix(name)
if len(op_name_prefix) > 0:
- # register op under mxnet.module_name.op_name_prefix[1:-1]
- # e.g. mxnet.ndarray.sparse.dot, mxnet.symbol.linalg.gemm
- function.__name__ = function.__name__[len(op_name_prefix):]
- function.__module__ = "%s.%s.%s" % (root_namespace, module_name, op_name_prefix[1:-1])
+ func_name = name[len(op_name_prefix):]
cur_module = submodule_dict[op_name_prefix]
- setattr(cur_module, function.__name__, function)
- cur_module.__all__.append(function.__name__)
- # if op_name_prefix is '_contrib_', also need to register
- # the op under mxnet.contrib.module_name for backward compatibility
- if op_name_prefix == '_contrib_':
- hdl = OpHandle()
- check_call(_LIB.NNGetOpHandle(c_str(name), ctypes.byref(hdl)))
- function = make_op_func(hdl, name)
- function.__name__ = function.__name__[len(op_name_prefix):]
- function.__module__ = contrib_module_name_old
- setattr(contrib_module_old, function.__name__, function)
- contrib_module_old.__all__.append(function.__name__)
- elif function.__name__.startswith('_'):
- setattr(module_internal, function.__name__, function)
- module_internal.__all__.append(function.__name__)
+ module_name = "%s.%s.%s" % (root_namespace, module_name, op_name_prefix[1:-1])
+ elif name.startswith('_'):
+ func_name = name
+ cur_module = module_internal
else:
- setattr(module_op, function.__name__, function)
- module_op.__all__.append(function.__name__)
+ func_name = name
+ cur_module = module_op
+
+ function = make_op_func(hdl, name, func_name)
+ function.__module__ = module_name
+ setattr(cur_module, function.__name__, function)
+ cur_module.__all__.append(function.__name__)
+
+ if op_name_prefix == '_contrib_':
+ hdl = OpHandle()
+ check_call(_LIB.NNGetOpHandle(c_str(name), ctypes.byref(hdl)))
+ func_name = name[len(op_name_prefix):]
+
+ function = make_op_func(hdl, name, func_name)
+ function.__module__ = contrib_module_name_old
+ setattr(contrib_module_old, function.__name__, function)
+ contrib_module_old.__all__.append(function.__name__)
+
+
+def _generate_op_module_signature(root_namespace, module_name, op_code_gen_func):
+ """
+ Generate op functions created by `op_code_gen_func` and write to the source file
+ of `root_namespace.module_name.[submodule_name]`,
+ where `submodule_name` is one of `_OP_SUBMODULE_NAME_LIST`.
+
+ Parameters
+ ----------
+ root_namespace : str
+ Top level module name, `mxnet` in the current cases.
+ module_name : str
+ Second level module name, `ndarray` and `symbol` in the current cases.
+ op_code_gen_func : function
+ Function for creating op functions for `ndarray` and `symbol` modules.
+ """
+ def get_module_file(module_name):
+ """Return the generated module file based on module name."""
+ path = os.path.dirname(__file__)
+ module_path = module_name.split('.')
+ module_path[-1] = 'gen_'+module_path[-1]
+ file_name = os.path.join(path, '..', *module_path) + '.py'
+ module_file = open(file_name, 'w')
+ dependencies = {'symbol': ['from ._internal import SymbolBase',
+ 'from ..base import _Null'],
+ 'ndarray': ['from ._internal import NDArrayBase',
+ 'from ..base import _Null']}
+ module_file.write('# File content is auto-generated. Do not modify.'+os.linesep)
+ module_file.write('# pylint: skip-file'+os.linesep)
+ module_file.write(os.linesep.join(dependencies[module_name.split('.')[1]]))
+ return module_file
+ def write_all_str(module_file, module_all_list):
+ """Write the proper __all__ based on available operators."""
+ module_file.write(os.linesep)
+ module_file.write(os.linesep)
+ all_str = '__all__ = [' + ', '.join(["'%s'"%s for s in module_all_list]) + ']'
+ module_file.write(all_str)
+
+ plist = ctypes.POINTER(ctypes.c_char_p)()
+ size = ctypes.c_uint()
+
+ check_call(_LIB.MXListAllOpNames(ctypes.byref(size),
+ ctypes.byref(plist)))
+ op_names = []
+ for i in range(size.value):
+ op_names.append(py_str(plist[i]))
+
+ module_op_file = get_module_file("%s.%s.op" % (root_namespace, module_name))
+ module_op_all = []
+ module_internal_file = get_module_file("%s.%s._internal"%(root_namespace, module_name))
+ module_internal_all = []
+ submodule_dict = {}
+ for op_name_prefix in _OP_NAME_PREFIX_LIST:
+ submodule_dict[op_name_prefix] =\
+ (get_module_file("%s.%s.%s" % (root_namespace, module_name,
+ op_name_prefix[1:-1])), [])
+ for name in op_names:
+ hdl = OpHandle()
+ check_call(_LIB.NNGetOpHandle(c_str(name), ctypes.byref(hdl)))
+ op_name_prefix = _get_op_name_prefix(name)
+ if len(op_name_prefix) > 0:
+ func_name = name[len(op_name_prefix):]
+ cur_module_file, cur_module_all = submodule_dict[op_name_prefix]
+ elif name.startswith('_'):
+ func_name = name
+ cur_module_file = module_internal_file
+ cur_module_all = module_internal_all
+ else:
+ func_name = name
+ cur_module_file = module_op_file
+ cur_module_all = module_op_all
+
+ code, _ = op_code_gen_func(hdl, name, func_name, True)
+ cur_module_file.write(os.linesep)
+ cur_module_file.write(code)
+ cur_module_all.append(func_name)
+
+ for (submodule_f, submodule_all) in submodule_dict.values():
+ write_all_str(submodule_f, submodule_all)
+ submodule_f.close()
+ write_all_str(module_op_file, module_op_all)
+ module_op_file.close()
+ write_all_str(module_internal_file, module_internal_all)
+ module_internal_file.close()
diff --git a/python/mxnet/ndarray/__init__.py b/python/mxnet/ndarray/__init__.py
index 1e1d8ed..586dc9e 100644
--- a/python/mxnet/ndarray/__init__.py
+++ b/python/mxnet/ndarray/__init__.py
@@ -17,8 +17,13 @@
"""NDArray API of MXNet."""
-from . import _internal, contrib, linalg, sparse, random, utils
+from . import _internal, contrib, linalg, op, random, sparse, utils
# pylint: disable=wildcard-import, redefined-builtin
+try:
+ from .gen_op import * # pylint: disable=unused-wildcard-import
+except ImportError:
+ pass
+from . import register
from .op import *
from .ndarray import *
# pylint: enable=wildcard-import
diff --git a/python/mxnet/ndarray/_internal.py b/python/mxnet/ndarray/_internal.py
index 96eff31..5f3ce97 100644
--- a/python/mxnet/ndarray/_internal.py
+++ b/python/mxnet/ndarray/_internal.py
@@ -15,5 +15,33 @@
# specific language governing permissions and limitations
# under the License.
+# pylint: disable=wildcard-import, unused-import
"""NDArray namespace used to register internal functions."""
-__all__ = []
+import os as _os
+import sys as _sys
+
+import numpy as np
+
+try:
+ if int(_os.environ.get("MXNET_ENABLE_CYTHON", True)) == 0:
+ from .._ctypes.ndarray import NDArrayBase, CachedOp
+ from .._ctypes.ndarray import _set_ndarray_class, _imperative_invoke
+ elif _sys.version_info >= (3, 0):
+ from .._cy3.ndarray import NDArrayBase, CachedOp
+ from .._cy3.ndarray import _set_ndarray_class, _imperative_invoke
+ else:
+ from .._cy2.ndarray import NDArrayBase, CachedOp
+ from .._cy2.ndarray import _set_ndarray_class, _imperative_invoke
+except ImportError:
+ if int(_os.environ.get("MXNET_ENFORCE_CYTHON", False)) != 0:
+ raise ImportError("Cython Module cannot be loaded but MXNET_ENFORCE_CYTHON=1")
+ from .._ctypes.ndarray import NDArrayBase, CachedOp
+ from .._ctypes.ndarray import _set_ndarray_class, _imperative_invoke
+
+from ..base import _Null
+try:
+ from .gen__internal import * # pylint: disable=unused-wildcard-import
+except ImportError:
+ pass
+
+__all__ = ['NDArrayBase', 'CachedOp', '_imperative_invoke', '_set_ndarray_class']
diff --git a/python/mxnet/ndarray/contrib.py b/python/mxnet/ndarray/contrib.py
index f21d144..0a3fe48 100644
--- a/python/mxnet/ndarray/contrib.py
+++ b/python/mxnet/ndarray/contrib.py
@@ -15,5 +15,12 @@
# specific language governing permissions and limitations
# under the License.
+# coding: utf-8
+# pylint: disable=wildcard-import, unused-wildcard-import
"""Contrib NDArray API of MXNet."""
+try:
+ from .gen_contrib import *
+except ImportError:
+ pass
+
__all__ = []
diff --git a/python/mxnet/ndarray/linalg.py b/python/mxnet/ndarray/linalg.py
index 0c8e7fd..baceab2 100644
--- a/python/mxnet/ndarray/linalg.py
+++ b/python/mxnet/ndarray/linalg.py
@@ -15,5 +15,12 @@
# specific language governing permissions and limitations
# under the License.
+# coding: utf-8
+# pylint: disable=wildcard-import, unused-wildcard-import
"""Linear Algebra NDArray API of MXNet."""
+try:
+ from .gen_linalg import *
+except ImportError:
+ pass
+
__all__ = []
diff --git a/python/mxnet/ndarray/ndarray.py b/python/mxnet/ndarray/ndarray.py
index 82e704a..2f9972b 100644
--- a/python/mxnet/ndarray/ndarray.py
+++ b/python/mxnet/ndarray/ndarray.py
@@ -39,7 +39,7 @@ from ..base import ctypes2buffer
from ..context import Context
from . import _internal
from . import op
-from .op import NDArrayBase
+from ._internal import NDArrayBase
__all__ = ["NDArray", "concatenate", "_DTYPE_NP_TO_MX", "_DTYPE_MX_TO_NP", "_GRAD_REQ_MAP",
"ones", "add", "arange", "divide", "equal", "full", "greater", "greater_equal",
diff --git a/python/mxnet/ndarray/op.py b/python/mxnet/ndarray/op.py
index 27ce09b..a328677 100644
--- a/python/mxnet/ndarray/op.py
+++ b/python/mxnet/ndarray/op.py
@@ -15,160 +15,13 @@
# specific language governing permissions and limitations
# under the License.
-"""Register backend ops in mxnet.ndarray namespace"""
-__all__ = ['CachedOp']
-
-import sys as _sys
-import os as _os
-import ctypes
-import numpy as np # pylint: disable=unused-import
-
-from ..ndarray_doc import _build_doc
-
-# Use different version of SymbolBase
-# When possible, use cython to speedup part of computation.
-# pylint: disable=unused-import
+# coding: utf-8
+# pylint: disable=wildcard-import, unused-wildcard-import, redefined-builtin
+"""Backend ops in mxnet.ndarray namespace"""
+from ._internal import CachedOp
try:
- if int(_os.environ.get("MXNET_ENABLE_CYTHON", True)) == 0:
- from .._ctypes.ndarray import NDArrayBase
- from .._ctypes.ndarray import CachedOp, _imperative_invoke
- elif _sys.version_info >= (3, 0):
- from .._cy3.ndarray import NDArrayBase, _imperative_invoke
- from .._cy3.ndarray import CachedOp, _imperative_invoke
- else:
- from .._cy2.ndarray import NDArrayBase, _imperative_invoke
- from .._cy2.ndarray import CachedOp, _imperative_invoke
+ from .gen_op import * # pylint: disable=unused-wildcard-import
except ImportError:
- if int(_os.environ.get("MXNET_ENFORCE_CYTHON", False)) != 0:
- raise ImportError("Cython Module cannot be loaded but MXNET_ENFORCE_CYTHON=1")
- from .._ctypes.ndarray import NDArrayBase, _imperative_invoke
- from .._ctypes.ndarray import CachedOp, _imperative_invoke
-
-from ..base import mx_uint, check_call, _LIB, py_str, _init_op_module, _Null
-# pylint: enable=unused-import
-
-
-# pylint: disable=too-many-locals, invalid-name
-def _make_ndarray_function(handle, name):
- """Create a NDArray function from the FunctionHandle."""
- real_name = ctypes.c_char_p()
- desc = ctypes.c_char_p()
- num_args = mx_uint()
- arg_names = ctypes.POINTER(ctypes.c_char_p)()
- arg_types = ctypes.POINTER(ctypes.c_char_p)()
- arg_descs = ctypes.POINTER(ctypes.c_char_p)()
- key_var_num_args = ctypes.c_char_p()
- ret_type = ctypes.c_char_p()
+ pass
- check_call(_LIB.MXSymbolGetAtomicSymbolInfo(
- handle, ctypes.byref(real_name), ctypes.byref(desc),
- ctypes.byref(num_args),
- ctypes.byref(arg_names),
- ctypes.byref(arg_types),
- ctypes.byref(arg_descs),
- ctypes.byref(key_var_num_args),
- ctypes.byref(ret_type)))
- narg = int(num_args.value)
- arg_names = [py_str(arg_names[i]) for i in range(narg)]
- arg_types = [py_str(arg_types[i]) for i in range(narg)]
- func_name = name
- key_var_num_args = py_str(key_var_num_args.value)
- ret_type = py_str(ret_type.value) if ret_type.value is not None else ''
- doc_str = _build_doc(func_name,
- py_str(desc.value),
- arg_names,
- arg_types,
- [py_str(arg_descs[i]) for i in range(narg)],
- key_var_num_args,
- ret_type)
-
- dtype_name = None
- arr_name = None
- ndsignature = []
- signature = []
- ndarg_names = []
- kwarg_names = []
- for i in range(narg):
- name, atype = arg_names[i], arg_types[i]
- if name == 'dtype':
- dtype_name = name
- signature.append('%s=_Null'%name)
- elif atype.startswith('NDArray') or atype.startswith('Symbol'):
- assert not arr_name, \
- "Op can only have one argument with variable " \
- "size and it must be the last argument."
- if atype.endswith('[]'):
- ndsignature.append('*%s'%name)
- arr_name = name
- else:
- ndsignature.append('%s=None'%name)
- ndarg_names.append(name)
- else:
- signature.append('%s=_Null'%name)
- kwarg_names.append(name)
- signature.append('out=None')
- signature.append('name=None')
- signature.append('**kwargs')
- signature = ndsignature + signature
-
- code = []
- if arr_name:
- code.append("""
-def %s(*%s, **kwargs):"""%(func_name, arr_name))
- code.append("""
- ndargs = []
- for i in {}:
- assert isinstance(i, NDArrayBase), \\
- "Positional arguments must have NDArray type, " \\
- "but got %s"%str(i)
- ndargs.append(i)""".format(arr_name))
- if dtype_name is not None:
- code.append("""
- if '%s' in kwargs:
- kwargs['%s'] = np.dtype(kwargs['%s']).name"""%(
- dtype_name, dtype_name, dtype_name))
- code.append("""
- _ = kwargs.pop('name', None)
- out = kwargs.pop('out', None)
- keys = list(kwargs.keys())
- vals = list(kwargs.values())""")
- else:
- code.append("""
-def %s(%s):
- ndargs = []
- keys = list(kwargs.keys())
- vals = list(kwargs.values())"""%(func_name, ', '.join(signature)))
- # NDArray args
- for name in ndarg_names: # pylint: disable=redefined-argument-from-local
- code.append("""
- if {name} is not None:
- assert isinstance({name}, NDArrayBase), \\
- "Argument {name} must have NDArray type, but got %s"%str({name})
- ndargs.append({name})""".format(name=name))
- # kwargs
- for name in kwarg_names: # pylint: disable=redefined-argument-from-local
- code.append("""
- if %s is not _Null:
- keys.append('%s')
- vals.append(%s)"""%(name, name, name))
- # dtype
- if dtype_name is not None:
- code.append("""
- if %s is not _Null:
- keys.append('%s')
- vals.append(np.dtype(%s).name)"""%(dtype_name, dtype_name, dtype_name))
-
- code.append("""
- return _imperative_invoke(%d, ndargs, keys, vals, out)"""%(
- handle.value))
-
- local = {}
- exec(''.join(code), None, local) # pylint: disable=exec-used
- ndarray_function = local[func_name]
- ndarray_function.__name__ = func_name
- ndarray_function.__doc__ = doc_str
- ndarray_function.__module__ = 'mxnet.ndarray'
- return ndarray_function
-
-
-_init_op_module('mxnet', 'ndarray', _make_ndarray_function)
+__all__ = ['CachedOp']
diff --git a/python/mxnet/ndarray/op.py b/python/mxnet/ndarray/register.py
similarity index 75%
copy from python/mxnet/ndarray/op.py
copy to python/mxnet/ndarray/register.py
index 27ce09b..48d5c01 100644
--- a/python/mxnet/ndarray/op.py
+++ b/python/mxnet/ndarray/register.py
@@ -16,41 +16,18 @@
# under the License.
"""Register backend ops in mxnet.ndarray namespace"""
-__all__ = ['CachedOp']
-
-import sys as _sys
import os as _os
import ctypes
import numpy as np # pylint: disable=unused-import
+from ._internal import NDArrayBase, _imperative_invoke # pylint: disable=unused-import
from ..ndarray_doc import _build_doc
-# Use different version of SymbolBase
-# When possible, use cython to speedup part of computation.
-# pylint: disable=unused-import
-try:
- if int(_os.environ.get("MXNET_ENABLE_CYTHON", True)) == 0:
- from .._ctypes.ndarray import NDArrayBase
- from .._ctypes.ndarray import CachedOp, _imperative_invoke
- elif _sys.version_info >= (3, 0):
- from .._cy3.ndarray import NDArrayBase, _imperative_invoke
- from .._cy3.ndarray import CachedOp, _imperative_invoke
- else:
- from .._cy2.ndarray import NDArrayBase, _imperative_invoke
- from .._cy2.ndarray import CachedOp, _imperative_invoke
-except ImportError:
- if int(_os.environ.get("MXNET_ENFORCE_CYTHON", False)) != 0:
- raise ImportError("Cython Module cannot be loaded but MXNET_ENFORCE_CYTHON=1")
- from .._ctypes.ndarray import NDArrayBase, _imperative_invoke
- from .._ctypes.ndarray import CachedOp, _imperative_invoke
-
-from ..base import mx_uint, check_call, _LIB, py_str, _init_op_module, _Null
-# pylint: enable=unused-import
+from ..base import mx_uint, check_call, _LIB, py_str, _init_op_module, _Null # pylint: disable=unused-import
-# pylint: disable=too-many-locals, invalid-name
-def _make_ndarray_function(handle, name):
- """Create a NDArray function from the FunctionHandle."""
+def _generate_ndarray_function_code(handle, name, func_name, signature_only=False):
+ """Generate function for ndarray op by handle and function name."""
real_name = ctypes.c_char_p()
desc = ctypes.c_char_p()
num_args = mx_uint()
@@ -71,10 +48,9 @@ def _make_ndarray_function(handle, name):
narg = int(num_args.value)
arg_names = [py_str(arg_names[i]) for i in range(narg)]
arg_types = [py_str(arg_types[i]) for i in range(narg)]
- func_name = name
key_var_num_args = py_str(key_var_num_args.value)
ret_type = py_str(ret_type.value) if ret_type.value is not None else ''
- doc_str = _build_doc(func_name,
+ doc_str = _build_doc(name,
py_str(desc.value),
arg_names,
arg_types,
@@ -115,60 +91,78 @@ def _make_ndarray_function(handle, name):
if arr_name:
code.append("""
def %s(*%s, **kwargs):"""%(func_name, arr_name))
- code.append("""
+ if not signature_only:
+ code.append("""
ndargs = []
for i in {}:
assert isinstance(i, NDArrayBase), \\
"Positional arguments must have NDArray type, " \\
"but got %s"%str(i)
ndargs.append(i)""".format(arr_name))
- if dtype_name is not None:
- code.append("""
+ if dtype_name is not None:
+ code.append("""
if '%s' in kwargs:
kwargs['%s'] = np.dtype(kwargs['%s']).name"""%(
dtype_name, dtype_name, dtype_name))
- code.append("""
+ code.append("""
_ = kwargs.pop('name', None)
out = kwargs.pop('out', None)
keys = list(kwargs.keys())
vals = list(kwargs.values())""")
else:
code.append("""
-def %s(%s):
+def %s(%s):"""%(func_name, ', '.join(signature)))
+ if not signature_only:
+ code.append("""
ndargs = []
keys = list(kwargs.keys())
- vals = list(kwargs.values())"""%(func_name, ', '.join(signature)))
- # NDArray args
- for name in ndarg_names: # pylint: disable=redefined-argument-from-local
- code.append("""
+ vals = list(kwargs.values())""")
+ # NDArray args
+ for name in ndarg_names: # pylint: disable=redefined-argument-from-local
+ code.append("""
if {name} is not None:
assert isinstance({name}, NDArrayBase), \\
"Argument {name} must have NDArray type, but got %s"%str({name})
ndargs.append({name})""".format(name=name))
- # kwargs
- for name in kwarg_names: # pylint: disable=redefined-argument-from-local
- code.append("""
+ # kwargs
+ for name in kwarg_names: # pylint: disable=redefined-argument-from-local
+ code.append("""
if %s is not _Null:
keys.append('%s')
vals.append(%s)"""%(name, name, name))
- # dtype
- if dtype_name is not None:
- code.append("""
+ # dtype
+ if dtype_name is not None:
+ code.append("""
if %s is not _Null:
keys.append('%s')
vals.append(np.dtype(%s).name)"""%(dtype_name, dtype_name, dtype_name))
- code.append("""
+ if not signature_only:
+ code.append("""
return _imperative_invoke(%d, ndargs, keys, vals, out)"""%(
handle.value))
+ else:
+ code.append("""
+ return (0,)""")
+
+ doc_str_lines = _os.linesep+''.join([' '+s if s.strip() else s
+ for s in 'r"""{doc_str}"""'.format(doc_str=doc_str)
+ .splitlines(True)])
+ code.insert(1, doc_str_lines)
+ return ''.join(code), doc_str
+
+
+# pylint: disable=too-many-locals, invalid-name
+def _make_ndarray_function(handle, name, func_name):
+ """Create a NDArray function from the FunctionHandle."""
+ code, doc_str = _generate_ndarray_function_code(handle, name, func_name)
local = {}
- exec(''.join(code), None, local) # pylint: disable=exec-used
+ exec(code, None, local) # pylint: disable=exec-used
ndarray_function = local[func_name]
ndarray_function.__name__ = func_name
ndarray_function.__doc__ = doc_str
ndarray_function.__module__ = 'mxnet.ndarray'
return ndarray_function
-
_init_op_module('mxnet', 'ndarray', _make_ndarray_function)
diff --git a/python/mxnet/ndarray/sparse.py b/python/mxnet/ndarray/sparse.py
index 5dc1092..72ce04c 100644
--- a/python/mxnet/ndarray/sparse.py
+++ b/python/mxnet/ndarray/sparse.py
@@ -16,6 +16,7 @@
# under the License.
# coding: utf-8
+# pylint: disable=wildcard-import, unused-wildcard-import, too-many-lines
"""Sparse NDArray API of MXNet."""
from __future__ import absolute_import
@@ -30,13 +31,9 @@ except ImportError:
import ctypes
import warnings
-import os as _os
-import sys as _sys
-
__all__ = ["_ndarray_cls", "csr_matrix", "row_sparse_array",
"BaseSparseNDArray", "CSRNDArray", "RowSparseNDArray"]
-# import operator
import numpy as np
from ..base import NotSupportedForSparseNDArray
from ..base import _LIB, numeric_types
@@ -44,29 +41,18 @@ from ..base import c_array, mx_real_t, integer_types
from ..base import mx_uint, NDArrayHandle, check_call
from ..context import Context
from . import _internal
-from .ndarray import _DTYPE_NP_TO_MX, _DTYPE_MX_TO_NP
-from .ndarray import _STORAGE_TYPE_STR_TO_ID
+from . import op
+try:
+ from .gen_sparse import * # pylint: disable=redefined-builtin
+except ImportError:
+ pass
+from ._internal import _set_ndarray_class
+from .ndarray import NDArray, _storage_type, _DTYPE_NP_TO_MX, _DTYPE_MX_TO_NP
+from .ndarray import _STORAGE_TYPE_STR_TO_ID, _STORAGE_TYPE_ROW_SPARSE, _STORAGE_TYPE_CSR
from .ndarray import _STORAGE_TYPE_UNDEFINED, _STORAGE_TYPE_DEFAULT
-from .ndarray import _STORAGE_TYPE_ROW_SPARSE, _STORAGE_TYPE_CSR
-from .ndarray import NDArray, _storage_type
from .ndarray import zeros as _zeros_ndarray
from .ndarray import array as _array
-from . import op
-# When possible, use cython to speedup part of computation.
-# pylint: disable=unused-import, too-many-lines
-try:
- if int(_os.environ.get("MXNET_ENABLE_CYTHON", True)) == 0:
- from .._ctypes.ndarray import _set_ndarray_class
- elif _sys.version_info >= (3, 0):
- from .._cy3.ndarray import _set_ndarray_class
- else:
- from .._cy2.ndarray import _set_ndarray_class
-except ImportError:
- if int(_os.environ.get("MXNET_ENFORCE_CYTHON", False)) != 0:
- raise ImportError("Cython Module cannot be loaded but MXNET_ENFORCE_CYTHON=1")
- from .._ctypes.ndarray import _set_ndarray_class
-# pylint: enable=unused-import
try:
import scipy.sparse as spsp
diff --git a/python/mxnet/symbol/__init__.py b/python/mxnet/symbol/__init__.py
index da395b7..a07025e 100644
--- a/python/mxnet/symbol/__init__.py
+++ b/python/mxnet/symbol/__init__.py
@@ -17,8 +17,13 @@
"""Symbol API of MXNet."""
-from . import _internal, contrib, linalg, sparse, random
+from . import _internal, contrib, linalg, op, random, sparse
# pylint: disable=wildcard-import, redefined-builtin
+try:
+ from .gen_op import * # pylint: disable=unused-wildcard-import
+except ImportError:
+ pass
+from . import register
from .op import *
from .symbol import *
# pylint: enable=wildcard-import
diff --git a/python/mxnet/symbol/_internal.py b/python/mxnet/symbol/_internal.py
index 25b3b60..53fc684 100644
--- a/python/mxnet/symbol/_internal.py
+++ b/python/mxnet/symbol/_internal.py
@@ -15,5 +15,36 @@
# specific language governing permissions and limitations
# under the License.
+# pylint: disable=wildcard-import, unused-import
"""Symbol namespace used to register internal functions."""
-__all__ = []
+# Use different version of SymbolBase
+# When possible, use cython to speedup part of computation.
+import sys as _sys
+import os as _os
+
+import numpy as np
+
+try:
+ if int(_os.environ.get("MXNET_ENABLE_CYTHON", True)) == 0:
+ from .._ctypes.symbol import SymbolBase, _set_symbol_class
+ from .._ctypes.symbol import _symbol_creator
+ elif _sys.version_info >= (3, 0):
+ from .._cy3.symbol import SymbolBase, _set_symbol_class
+ from .._cy3.symbol import _symbol_creator
+ else:
+ from .._cy2.symbol import SymbolBase, _set_symbol_class
+ from .._cy2.symbol import _symbol_creator
+except ImportError:
+ if int(_os.environ.get("MXNET_ENFORCE_CYTHON", False)) != 0:
+ raise ImportError("Cython Module cannot be loaded but MXNET_ENFORCE_CYTHON=1")
+ from .._ctypes.symbol import SymbolBase, _set_symbol_class
+ from .._ctypes.symbol import _symbol_creator
+from ..attribute import AttrScope
+from ..base import _Null
+from ..name import NameManager
+try:
+ from .gen__internal import * # pylint: disable=unused-wildcard-import
+except ImportError:
+ pass
+
+__all__ = ['SymbolBase', '_set_symbol_class', '_symbol_creator']
diff --git a/python/mxnet/symbol/contrib.py b/python/mxnet/symbol/contrib.py
index ff5aa37..13feb78 100644
--- a/python/mxnet/symbol/contrib.py
+++ b/python/mxnet/symbol/contrib.py
@@ -15,5 +15,12 @@
# specific language governing permissions and limitations
# under the License.
+# coding: utf-8
+# pylint: disable=wildcard-import, unused-wildcard-import
"""Contrib Symbol API of MXNet."""
+try:
+ from .gen_contrib import *
+except ImportError:
+ pass
+
__all__ = []
diff --git a/python/mxnet/symbol/linalg.py b/python/mxnet/symbol/linalg.py
index 58514ba..2bf543e 100644
--- a/python/mxnet/symbol/linalg.py
+++ b/python/mxnet/symbol/linalg.py
@@ -15,5 +15,12 @@
# specific language governing permissions and limitations
# under the License.
+# coding: utf-8
+# pylint: disable=wildcard-import, unused-wildcard-import
"""Linear Algebra Symbol API of MXNet."""
+try:
+ from .gen_linalg import *
+except ImportError:
+ pass
+
__all__ = []
diff --git a/python/mxnet/symbol/op.py b/python/mxnet/symbol/op.py
index 9353a73..2d63dfc 100644
--- a/python/mxnet/symbol/op.py
+++ b/python/mxnet/symbol/op.py
@@ -15,193 +15,12 @@
# specific language governing permissions and limitations
# under the License.
-"""Register backend ops in mxnet.symbol namespace."""
-__all__ = []
-
-import sys as _sys
-import os as _os
-import ctypes
-import numpy as _numpy # pylint: disable=unused-import
-
-from ..base import mx_uint, check_call, _LIB, py_str
-from ..symbol_doc import _build_doc
-
-# Use different version of SymbolBase
-# When possible, use cython to speedup part of computation.
-# pylint: disable=unused-import
+# coding: utf-8
+# pylint: disable=wildcard-import, unused-wildcard-import, redefined-builtin
+"""Backend ops in mxnet.symbol namespace."""
try:
- if int(_os.environ.get("MXNET_ENABLE_CYTHON", True)) == 0:
- from .._ctypes.symbol import SymbolBase, _set_symbol_class
- from .._ctypes.symbol import _symbol_creator
- elif _sys.version_info >= (3, 0):
- from .._cy3.symbol import SymbolBase, _set_symbol_class
- from .._cy3.symbol import _symbol_creator
- else:
- from .._cy2.symbol import SymbolBase, _set_symbol_class
- from .._cy2.symbol import _symbol_creator
+ from .gen_op import *
except ImportError:
- if int(_os.environ.get("MXNET_ENFORCE_CYTHON", False)) != 0:
- raise ImportError("Cython Module cannot be loaded but MXNET_ENFORCE_CYTHON=1")
- from .._ctypes.symbol import SymbolBase, _set_symbol_class
- from .._ctypes.symbol import _symbol_creator
-
-from ..base import _Null, _init_op_module
-from ..name import NameManager
-from ..attribute import AttrScope
-# pylint: enable=unused-import
-
-
-def _make_atomic_symbol_function(handle, name):
- """Create an atomic symbol function by handle and function name."""
- real_name = ctypes.c_char_p()
- desc = ctypes.c_char_p()
- num_args = mx_uint()
- arg_names = ctypes.POINTER(ctypes.c_char_p)()
- arg_types = ctypes.POINTER(ctypes.c_char_p)()
- arg_descs = ctypes.POINTER(ctypes.c_char_p)()
- key_var_num_args = ctypes.c_char_p()
- ret_type = ctypes.c_char_p()
-
- check_call(_LIB.MXSymbolGetAtomicSymbolInfo(
- handle, ctypes.byref(real_name), ctypes.byref(desc),
- ctypes.byref(num_args),
- ctypes.byref(arg_names),
- ctypes.byref(arg_types),
- ctypes.byref(arg_descs),
- ctypes.byref(key_var_num_args),
- ctypes.byref(ret_type)))
- narg = int(num_args.value)
- arg_names = [py_str(arg_names[i]) for i in range(narg)]
- arg_types = [py_str(arg_types[i]) for i in range(narg)]
- func_name = name
- key_var_num_args = py_str(key_var_num_args.value)
- ret_type = py_str(ret_type.value) if ret_type.value is not None else ''
- doc_str = _build_doc(func_name,
- py_str(desc.value),
- arg_names,
- arg_types,
- [py_str(arg_descs[i]) for i in range(narg)],
- key_var_num_args,
- ret_type)
+ pass
- dtype_name = None
- arr_name = None
- ndsignature = []
- signature = []
- ndarg_names = []
- kwarg_names = []
- for i in range(narg):
- name, atype = arg_names[i], arg_types[i]
- if name == 'dtype':
- dtype_name = name
- signature.append('%s=_Null'%name)
- elif atype.startswith('NDArray') or atype.startswith('Symbol'):
- assert not arr_name, \
- "Op can only have one argument with variable " \
- "size and it must be the last argument."
- if atype.endswith('[]'):
- ndsignature.append('*%s'%name)
- arr_name = name
- else:
- ndsignature.append('%s=None'%name)
- ndarg_names.append(name)
- else:
- signature.append('%s=_Null'%name)
- kwarg_names.append(name)
- #signature.append('is_train=False')
- signature.append('name=None')
- signature.append('attr=None')
- signature.append('out=None')
- signature.append('**kwargs')
- signature = ndsignature + signature
-
- code = []
- if arr_name:
- code.append("""
-def %s(*%s, **kwargs):"""%(func_name, arr_name))
- code.append("""
- sym_args = []
- for i in {}:
- assert isinstance(i, SymbolBase), \\
- "Positional arguments must be Symbol instances, " \\
- "but got %s"%str(i)
- sym_args.append(i)""".format(arr_name))
- if dtype_name is not None:
- code.append("""
- if '%s' in kwargs:
- kwargs['%s'] = _numpy.dtype(kwargs['%s']).name"""%(
- dtype_name, dtype_name, dtype_name))
- code.append("""
- attr = kwargs.pop('attr', None)
- kwargs.update(AttrScope.current.get(attr))
- name = kwargs.pop('name', None)
- name = NameManager.current.get(name, '%s')
- _ = kwargs.pop('out', None)
- keys = []
- vals = []
- sym_kwargs = dict()
- for k, v in kwargs.items():
- if isinstance(v, SymbolBase):
- sym_kwargs[k] = v
- else:
- keys.append(k)
- vals.append(v)"""%(func_name.lower()))
- if key_var_num_args:
- code.append("""
- if '%s' not in kwargs:
- keys.append('%s')
- vals.append(len(sym_args) + len(sym_kwargs))"""%(
- key_var_num_args, key_var_num_args))
-
- code.append("""
- return _symbol_creator(%d, sym_args, sym_kwargs, keys, vals, name)"""%(
- handle.value))
- else:
- code.append("""
-def %s(%s):
- kwargs.update(AttrScope.current.get(attr))
- sym_kwargs = dict()
- keys = []
- vals = []"""%(func_name, ', '.join(signature)))
- code.append("""
- for k, v in kwargs.items():
- if isinstance(v, SymbolBase):
- sym_kwargs[k] = v
- else:
- keys.append(k)
- vals.append(v)""")
- # NDArray args
- for name in ndarg_names: # pylint: disable=redefined-argument-from-local
- code.append("""
- if {name} is not None:
- assert isinstance({name}, SymbolBase), \\
- "Argument {name} must be Symbol instances, but got %s"%str({name})
- sym_kwargs['{name}'] = {name}""".format(name=name))
- # kwargs
- for name in kwarg_names: # pylint: disable=redefined-argument-from-local
- code.append("""
- if %s is not _Null:
- keys.append('%s')
- vals.append(%s)"""%(name, name, name))
- # dtype
- if dtype_name is not None:
- code.append("""
- if %s is not _Null:
- keys.append('%s')
- vals.append(_numpy.dtype(%s).name)"""%(dtype_name, dtype_name, dtype_name))
-
- code.append("""
- name = NameManager.current.get(name, '%s')
- return _symbol_creator(%d, None, sym_kwargs, keys, vals, name)"""%(
- func_name.lower(), handle.value))
-
- local = {}
- exec(''.join(code), None, local) # pylint: disable=exec-used
- symbol_function = local[func_name]
- symbol_function.__name__ = func_name
- symbol_function.__doc__ = doc_str
- symbol_function.__module__ = 'mxnet.symbol'
- return symbol_function
-
-
-_init_op_module('mxnet', 'symbol', _make_atomic_symbol_function)
+__all__ = []
diff --git a/python/mxnet/symbol/op.py b/python/mxnet/symbol/register.py
similarity index 75%
copy from python/mxnet/symbol/op.py
copy to python/mxnet/symbol/register.py
index 9353a73..cf279d1 100644
--- a/python/mxnet/symbol/op.py
+++ b/python/mxnet/symbol/register.py
@@ -15,44 +15,24 @@
# specific language governing permissions and limitations
# under the License.
+# pylint: disable=unused-import
"""Register backend ops in mxnet.symbol namespace."""
-__all__ = []
-
-import sys as _sys
import os as _os
import ctypes
-import numpy as _numpy # pylint: disable=unused-import
+import numpy as np
+from . import _internal
+from ._internal import SymbolBase, _symbol_creator
+from ..attribute import AttrScope
from ..base import mx_uint, check_call, _LIB, py_str
from ..symbol_doc import _build_doc
-
-# Use different version of SymbolBase
-# When possible, use cython to speedup part of computation.
-# pylint: disable=unused-import
-try:
- if int(_os.environ.get("MXNET_ENABLE_CYTHON", True)) == 0:
- from .._ctypes.symbol import SymbolBase, _set_symbol_class
- from .._ctypes.symbol import _symbol_creator
- elif _sys.version_info >= (3, 0):
- from .._cy3.symbol import SymbolBase, _set_symbol_class
- from .._cy3.symbol import _symbol_creator
- else:
- from .._cy2.symbol import SymbolBase, _set_symbol_class
- from .._cy2.symbol import _symbol_creator
-except ImportError:
- if int(_os.environ.get("MXNET_ENFORCE_CYTHON", False)) != 0:
- raise ImportError("Cython Module cannot be loaded but MXNET_ENFORCE_CYTHON=1")
- from .._ctypes.symbol import SymbolBase, _set_symbol_class
- from .._ctypes.symbol import _symbol_creator
-
from ..base import _Null, _init_op_module
from ..name import NameManager
-from ..attribute import AttrScope
# pylint: enable=unused-import
-def _make_atomic_symbol_function(handle, name):
- """Create an atomic symbol function by handle and function name."""
+def _generate_symbol_function_code(handle, name, func_name, signature_only=False):
+ """Generate function for symbol op by handle and function name."""
real_name = ctypes.c_char_p()
desc = ctypes.c_char_p()
num_args = mx_uint()
@@ -73,10 +53,9 @@ def _make_atomic_symbol_function(handle, name):
narg = int(num_args.value)
arg_names = [py_str(arg_names[i]) for i in range(narg)]
arg_types = [py_str(arg_types[i]) for i in range(narg)]
- func_name = name
key_var_num_args = py_str(key_var_num_args.value)
ret_type = py_str(ret_type.value) if ret_type.value is not None else ''
- doc_str = _build_doc(func_name,
+ doc_str = _build_doc(name,
py_str(desc.value),
arg_names,
arg_types,
@@ -119,19 +98,20 @@ def _make_atomic_symbol_function(handle, name):
if arr_name:
code.append("""
def %s(*%s, **kwargs):"""%(func_name, arr_name))
- code.append("""
+ if not signature_only:
+ code.append("""
sym_args = []
for i in {}:
assert isinstance(i, SymbolBase), \\
"Positional arguments must be Symbol instances, " \\
"but got %s"%str(i)
sym_args.append(i)""".format(arr_name))
- if dtype_name is not None:
- code.append("""
+ if dtype_name is not None:
+ code.append("""
if '%s' in kwargs:
- kwargs['%s'] = _numpy.dtype(kwargs['%s']).name"""%(
+ kwargs['%s'] = np.dtype(kwargs['%s']).name"""%(
dtype_name, dtype_name, dtype_name))
- code.append("""
+ code.append("""
attr = kwargs.pop('attr', None)
kwargs.update(AttrScope.current.get(attr))
name = kwargs.pop('name', None)
@@ -146,62 +126,77 @@ def %s(*%s, **kwargs):"""%(func_name, arr_name))
else:
keys.append(k)
vals.append(v)"""%(func_name.lower()))
- if key_var_num_args:
- code.append("""
+ if key_var_num_args:
+ code.append("""
if '%s' not in kwargs:
keys.append('%s')
vals.append(len(sym_args) + len(sym_kwargs))"""%(
key_var_num_args, key_var_num_args))
- code.append("""
+ code.append("""
return _symbol_creator(%d, sym_args, sym_kwargs, keys, vals, name)"""%(
handle.value))
else:
code.append("""
-def %s(%s):
+def %s(%s):"""%(func_name, ', '.join(signature)))
+ if not signature_only:
+ code.append("""
kwargs.update(AttrScope.current.get(attr))
sym_kwargs = dict()
keys = []
- vals = []"""%(func_name, ', '.join(signature)))
- code.append("""
+ vals = []
for k, v in kwargs.items():
if isinstance(v, SymbolBase):
sym_kwargs[k] = v
else:
keys.append(k)
vals.append(v)""")
- # NDArray args
- for name in ndarg_names: # pylint: disable=redefined-argument-from-local
- code.append("""
+ # NDArray args
+ for name in ndarg_names: # pylint: disable=redefined-argument-from-local
+ code.append("""
if {name} is not None:
assert isinstance({name}, SymbolBase), \\
"Argument {name} must be Symbol instances, but got %s"%str({name})
sym_kwargs['{name}'] = {name}""".format(name=name))
- # kwargs
- for name in kwarg_names: # pylint: disable=redefined-argument-from-local
- code.append("""
+ # kwargs
+ for name in kwarg_names: # pylint: disable=redefined-argument-from-local
+ code.append("""
if %s is not _Null:
keys.append('%s')
vals.append(%s)"""%(name, name, name))
- # dtype
- if dtype_name is not None:
- code.append("""
+ # dtype
+ if dtype_name is not None:
+ code.append("""
if %s is not _Null:
keys.append('%s')
- vals.append(_numpy.dtype(%s).name)"""%(dtype_name, dtype_name, dtype_name))
+ vals.append(np.dtype(%s).name)"""%(dtype_name, dtype_name, dtype_name))
- code.append("""
+ code.append("""
name = NameManager.current.get(name, '%s')
return _symbol_creator(%d, None, sym_kwargs, keys, vals, name)"""%(
func_name.lower(), handle.value))
+ if signature_only:
+ code.append("""
+ return (0,)""")
+
+ doc_str_lines = _os.linesep+''.join([' '+s if s.strip() else s
+ for s in 'r"""{doc_str}"""'.format(doc_str=doc_str)
+ .splitlines(True)])
+ code.insert(1, doc_str_lines)
+ return ''.join(code), doc_str
+
+
+def _make_symbol_function(handle, name, func_name):
+ """Create a symbol function by handle and function name."""
+ code, doc_str = _generate_symbol_function_code(handle, name, func_name)
+
local = {}
- exec(''.join(code), None, local) # pylint: disable=exec-used
+ exec(code, None, local) # pylint: disable=exec-used
symbol_function = local[func_name]
symbol_function.__name__ = func_name
symbol_function.__doc__ = doc_str
symbol_function.__module__ = 'mxnet.symbol'
return symbol_function
-
-_init_op_module('mxnet', 'symbol', _make_atomic_symbol_function)
+_init_op_module('mxnet', 'symbol', _make_symbol_function)
diff --git a/python/mxnet/symbol/sparse.py b/python/mxnet/symbol/sparse.py
index 3bfcf4a..66f4dbe 100644
--- a/python/mxnet/symbol/sparse.py
+++ b/python/mxnet/symbol/sparse.py
@@ -15,5 +15,12 @@
# specific language governing permissions and limitations
# under the License.
+# coding: utf-8
+# pylint: disable=wildcard-import, unused-wildcard-import
"""Sparse Symbol API of MXNet."""
+try:
+ from .gen_sparse import * # pylint: disable=redefined-builtin
+except ImportError:
+ pass
+
__all__ = []
diff --git a/python/mxnet/symbol/symbol.py b/python/mxnet/symbol/symbol.py
index 394f8b6..3c76826 100644
--- a/python/mxnet/symbol/symbol.py
+++ b/python/mxnet/symbol/symbol.py
@@ -31,6 +31,7 @@ from numbers import Number
import numpy as _numpy
+from ..attribute import AttrScope
from ..base import _LIB, numeric_types
from ..base import c_array, c_str, mx_uint, py_str, string_types
from ..base import NDArrayHandle, ExecutorHandle, SymbolHandle
@@ -42,7 +43,7 @@ from ..ndarray import _ndarray_cls
from ..executor import Executor
from . import _internal
from . import op
-from .op import SymbolBase, _set_symbol_class, AttrScope, _Null # pylint: disable=unused-import
+from ._internal import SymbolBase, _set_symbol_class
__all__ = ["Symbol", "var", "Variable", "Group", "load", "load_json",
"pow", "maximum", "minimum", "hypot", "zeros", "ones", "full", "arange"]
diff --git a/python/setup.py b/python/setup.py
index 14c8121..1e93ac0 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -22,15 +22,31 @@ import os
import sys
# need to use distutils.core for correct placement of cython dll
kwargs = {}
+required_packages = ['numpy', 'requests', 'graphviz']
if "--inplace" in sys.argv:
from distutils.core import setup
from distutils.extension import Extension
+ from distutils.command.install import install
else:
from setuptools import setup
from setuptools.extension import Extension
- kwargs = {'install_requires': ['numpy', 'requests', 'graphviz'], 'zip_safe': False}
+ kwargs = {'install_requires': required_packages,
+ 'setup_requires': required_packages,
+ 'tests_require': required_packages,
+ 'zip_safe': False}
+ from setuptools.command.install import install
from setuptools import find_packages
+class PostInstallCommand(install):
+ """Post-installation for installation mode."""
+ def run(self):
+ install.run(self)
+ from mxnet.base import _generate_op_module_signature
+ from mxnet.ndarray.register import _generate_ndarray_function_code
+ from mxnet.symbol.register import _generate_symbol_function_code
+ _generate_op_module_signature('mxnet', 'symbol', _generate_symbol_function_code)
+ _generate_op_module_signature('mxnet', 'ndarray', _generate_ndarray_function_code)
+
with_cython = False
if '--with-cython' in sys.argv:
with_cython = True
@@ -87,7 +103,6 @@ def config_cython():
print("WARNING: Cython is not installed, will compile without cython module")
return []
-
setup(name='mxnet',
version=__version__,
description=open(os.path.join(CURRENT_DIR, 'README.md')).read(),
@@ -95,4 +110,5 @@ setup(name='mxnet',
data_files=[('mxnet', [LIB_PATH[0]])],
url='https://github.com/dmlc/mxnet',
ext_modules=config_cython(),
+ cmdclass={'install': PostInstallCommand},
**kwargs)
--
To stop receiving notification emails like this one, please contact
['"commits@mxnet.apache.org" <co...@mxnet.apache.org>'].