Skip to content

Commit 9cb0214

Browse files
committed
generate console script for Exec extension #22
1 parent e52306d commit 9cb0214

File tree

5 files changed

+66
-2
lines changed

5 files changed

+66
-2
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ CHANGES
44
0.7.2 (2017-09-01)
55
------------------
66

7+
- Generate console-script for Binding.Exec #22
8+
79
- Remove extra python3 file extension for executables.
810

911

README.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ You can define rust extension with `RustExtension` class:
8888
`Binding.RustCPython` uses rust-cpython
8989
`Binding.NoBinding` uses no binding.
9090

91+
:param bool script: Generate console script for executable
92+
if `Binding.Exec` is used.
93+
9194
:param bool optional: if it is true, a build failure in the extension will not abort the build process,
9295
but instead simply not install the failing extension.
9396

setuptools_rust/build.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ def build_extension(self, ext):
188188
ext_path, _ = os.path.splitext(ext_path)
189189
# remove python3 extension (i.e. cpython-36m)
190190
ext_path, _ = os.path.splitext(ext_path)
191+
192+
ext.install_script(ext_path)
191193
else:
192194
ext_path = build_ext.get_ext_fullpath(target_fname)
193195

setuptools_rust/extension.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from __future__ import print_function, absolute_import
22
import os
3+
import os.path
34
import sys
45
from distutils.errors import DistutilsSetupError
56
from .utils import Binding, Strip
@@ -41,22 +42,25 @@ class RustExtension:
4142
* Strip.No - do not strip symbols
4243
* Strip.Debug - strip debug symbols
4344
* Strip.All - strip all symbols
45+
script : bool
46+
Generate console script for executable if `Binding.Exec` is used.
4447
optional : bool
4548
if it is true, a build failure in the extension will not abort the
4649
build process, but instead simply not install the failing extension.
4750
"""
4851

4952
def __init__(self, name, path,
5053
args=None, features=None, rust_version=None,
51-
quiet=False, debug=None, binding=Binding.PyO3, strip=Strip.No,
52-
optional=False):
54+
quiet=False, debug=None, binding=Binding.PyO3,
55+
strip=Strip.No, script=False, optional=False):
5356
self.name = name
5457
self.args = args
5558
self.binding = binding
5659
self.rust_version = rust_version
5760
self.quiet = quiet
5861
self.debug = debug
5962
self.strip = strip
63+
self.script = script
6064
self.optional = optional
6165

6266
if features is None:
@@ -84,3 +88,36 @@ def get_rust_version(self):
8488
except:
8589
raise DistutilsSetupError(
8690
'Can not parse rust compiler version: %s', self.rust_version)
91+
92+
def entry_points(self):
93+
entry_points = []
94+
if self.script and self.binding == Binding.Exec:
95+
base_mod, name = self.name.rsplit('.')
96+
script = '%s=%s.%s:run' % (name, base_mod, '_gen_%s' % name)
97+
entry_points.append(script)
98+
99+
return entry_points
100+
101+
def install_script(self, ext_path):
102+
if self.script and self.binding == Binding.Exec:
103+
dirname, name = os.path.split(ext_path)
104+
file = os.path.join(dirname, '_gen_%s.py' % name)
105+
with open(file, 'w') as f:
106+
f.write(TMPL.format({'name': name}))
107+
108+
109+
TMPL = """from __future__ import absolute_import, print_function
110+
111+
import os
112+
import sys
113+
114+
115+
def run():
116+
path = os.path.split(__file__)[0]
117+
file = os.path.join(path, "%(name)")
118+
if os.path.isfile(file):
119+
os.execv(file, sys.argv)
120+
else:
121+
print("Can not execute %(name)")
122+
123+
"""

setuptools_rust/patch.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,26 @@ def finalize_options(self):
4444
if self.distribution.rust_extensions:
4545
mods.extend(self.distribution.rust_extensions)
4646

47+
scripts = []
48+
for ext in self.distribution.rust_extensions:
49+
scripts.extend(ext.entry_points())
50+
51+
if scripts:
52+
if not self.distribution.entry_points:
53+
self.distribution.entry_points = {
54+
'console_scripts': scripts,
55+
}
56+
else:
57+
ep_scripts = self.distribution.entry_points.get(
58+
'console_scripts')
59+
if ep_scripts:
60+
ep_scripts.extend(scripts)
61+
else:
62+
ep_scripts = scripts
63+
64+
self.distribution.entry_points[
65+
'console_scripts'] = ep_scripts
66+
4767
self.distribution.ext_modules = mods
4868

4969
self.orig_finalize_options()

0 commit comments

Comments
 (0)