Skip to content

Commit 49953a1

Browse files
committed
use distutils exceptions; add rust version check
1 parent 746cbcb commit 49953a1

File tree

4 files changed

+69
-24
lines changed

4 files changed

+69
-24
lines changed

CHANGES.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
CHANGES
22
=======
33

4+
0.3 (2017-xx-xx)
5+
----------------
6+
7+
- Use distutils exceptions for errors.
8+
9+
- Add rust version check for extension.
10+
11+
412
0.2 (2017-03-08)
513
----------------
614

example/setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
setup(name='hello-rust',
66
version='1.0',
7-
rust_extensions=[RustExtension('hello_rust._helloworld', 'extensions/Cargo.toml')],
7+
rust_extensions=[
8+
RustExtension('hello_rust._helloworld', 'extensions/Cargo.toml')],
89
packages=['hello_rust'],
910
# rust extensions are not zip safe, just like C-extensions.
10-
zip_safe=False
11-
)
11+
zip_safe=False)

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from setuptools import setup, find_packages
1+
from setuptools import setup
22

33
version = '0.2'
44

@@ -15,6 +15,7 @@
1515
(open('README.rst').read(), open('CHANGES.rst').read())),
1616
license='MIT',
1717
packages=['setuptools_rust'],
18+
install_requires=['semver==2.7.6'],
1819
zip_safe=True,
1920
classifiers=[
2021
"Topic :: Software Development :: Version Control",

setuptools_rust/__init__.py

Lines changed: 56 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,28 @@
77
from distutils.cmd import Command
88
from distutils.dist import Distribution
99
from distutils.command.build import build as Build
10-
from distutils.command.build_ext import build_ext
11-
from distutils.command.install_lib import install_lib
12-
from setuptools import dist, setup, Extension
13-
from setuptools.command import develop, bdist_egg
10+
from distutils.errors import (
11+
DistutilsExecError, DistutilsFileError, DistutilsPlatformError)
12+
from setuptools.command import develop
13+
14+
import semver
1415

1516
__all__ = ('RustExtension', 'build_rust')
1617

1718

1819
# allow to use 'rust_extensions' parameter for setup() call
1920
Distribution.rust_extensions = ()
2021

22+
2123
def has_ext_modules(self):
2224
return (self.ext_modules and len(self.ext_modules) > 0 or
2325
self.rust_extensions and len(self.rust_extensions) > 0)
2426

27+
2528
Distribution.has_ext_modules = has_ext_modules
26-
#dist.Distribution.has_ext_modules = has_ext_modules
2729

28-
# add support for build_rust sub0command
30+
31+
# add support for build_rust sub-command
2932
def has_rust_extensions(self):
3033
exts = [ext for ext in self.distribution.rust_extensions
3134
if isinstance(ext, RustExtension)]
@@ -38,13 +41,15 @@ def has_rust_extensions(self):
3841
# monkey patch "develop" command
3942
orig_run_command = develop.develop.run_command
4043

44+
4145
def monkey_run_command(self, cmd):
4246
orig_run_command(self, cmd)
4347

4448
if cmd == 'build_ext':
4549
self.reinitialize_command('build_rust', inplace=1)
4650
orig_run_command(self, 'build_rust')
4751

52+
4853
develop.develop.run_command = monkey_run_command
4954

5055

@@ -60,18 +65,33 @@ class RustExtension:
6065
path to the cargo.toml manifest
6166
args : [stirng]
6267
a list of extra argumenents to be passed to cargo.
68+
version : string
69+
rust compiler version
6370
quiet : bool
6471
If True, doesn't echo cargo's output.
6572
debug : bool
6673
Controls whether --debug or --release is passed to cargo.
6774
"""
6875

69-
def __init__(self, name, path, args=None, quiet=False, debug=False):
70-
self.name=name
71-
self.path=path
72-
self.args=args
73-
self.quiet=quiet
74-
self.debug=debug
76+
def __init__(self, name, path,
77+
args=None, version=None, quiet=False, debug=False):
78+
self.name = name
79+
self.path = path
80+
self.args = args
81+
self.version = version
82+
self.quiet = quiet
83+
self.debug = debug
84+
85+
@staticmethod
86+
def get_version():
87+
env = os.environ.copy()
88+
try:
89+
output = subprocess.check_output(["rustc", "-V"], env=env)
90+
return output.split(' ')[1]
91+
except subprocess.CalledProcessError:
92+
return None
93+
except OSError:
94+
return None
7595

7696

7797
class build_rust(Command):
@@ -99,12 +119,13 @@ def finalize_options(self):
99119

100120
def features(self):
101121
version = sys.version_info
102-
if (2,7) < version < (2,8):
122+
if (2, 7) < version < (2, 8):
103123
return "python27-sys"
104-
elif (3,3) < version:
124+
elif (3, 3) < version:
105125
return "python3-sys"
106126
else:
107-
raise ValueError("Unsupported python version: %s" % sys.version)
127+
raise DistutilsPlatformError(
128+
"Unsupported python version: %s" % sys.version)
108129

109130
def build_extension(self, ext):
110131
# Make sure that if pythonXX-sys is used, it builds against the current
@@ -120,6 +141,10 @@ def build_extension(self, ext):
120141
"PATH": bindir + os.pathsep + os.environ.get("PATH", "")
121142
})
122143

144+
if not os.path.exists(ext.path):
145+
raise DistutilsFileError(
146+
"Can not file rust extension project file: %s" % ext.path)
147+
123148
# Execute cargo.
124149
try:
125150
args = (["cargo", "build", "--manifest-path", ext.path,
@@ -130,11 +155,12 @@ def build_extension(self, ext):
130155
print(" ".join(args), file=sys.stderr)
131156
output = subprocess.check_output(args, env=env)
132157
except subprocess.CalledProcessError as e:
133-
msg = "cargo failed with code: %d\n%s" % (e.returncode, e.output)
134-
raise Exception(msg)
158+
raise DistutilsExecError(
159+
"cargo failed with code: %d\n%s" % (e.returncode, e.output))
135160
except OSError:
136-
raise Exception("Unable to execute 'cargo' - this package "
137-
"requires rust to be installed and cargo to be on the PATH")
161+
raise DistutilsExecError(
162+
"Unable to execute 'cargo' - this package "
163+
"requires rust to be installed and cargo to be on the PATH")
138164

139165
if not ext.quiet:
140166
print(output, file=sys.stderr)
@@ -158,7 +184,7 @@ def build_extension(self, ext):
158184
try:
159185
dylib_path = glob.glob(os.path.join(target_dir, wildcard_so))[0]
160186
except IndexError:
161-
raise Exception(
187+
raise DistutilsExecError(
162188
"rust build failed; unable to find any .dylib in %s" %
163189
target_dir)
164190

@@ -179,5 +205,15 @@ def build_extension(self, ext):
179205
shutil.copyfile(dylib_path, ext_path)
180206

181207
def run(self):
208+
version = RustExtension.get_version()
209+
if self.extensions and version is None:
210+
raise DistutilsPlatformError('Can not find Rust compiler')
211+
182212
for ext in self.extensions:
213+
if ext.version is not None:
214+
if not semver.match(version, ext.version):
215+
raise DistutilsPlatformError(
216+
"Rust %s does not match extension requirenment %s" % (
217+
version, ext.version))
218+
183219
self.build_extension(ext)

0 commit comments

Comments
 (0)