Compare commits

...
32 Commits
Author SHA1 Message Date
Joe Rickerby 0627b38402 Bump version 2018-06-18 23:09:19 +01:00
Joe Rickerby 189dc13714 Merge pull request #71 from mayeut/macos-ssl
macOS: patch _ssl module on Python 3.4 & 3.5
2018-06-18 23:02:01 +01:00
Joe Rickerby 793026f3ed Merge pull request #60 from YannickJadoul/python-pip-replacement
Removing replacement of {python} and {pip} in CIBW_BEFORE_BUILD
2018-06-18 22:59:52 +01:00
Joe Rickerby 08b4895b9c Changelog update 2018-06-18 22:57:22 +01:00
Joe Rickerby 7c635b4550 Bump version 2018-06-18 22:52:02 +01:00
Joe Rickerby 33433f0b21 Merge pull request #73 from lelit/py37
Add support for Python 3.7
2018-06-18 22:50:54 +01:00
Joe Rickerby e3981db2a6 Skip the custom docker image specifier for Python 3.7
We'll reenable this when 3.7 is released and dockcross updates :)
2018-06-18 22:35:05 +01:00
Joe Rickerby 1ec652dff8 Fix pip variable use 2018-06-17 21:06:00 +01:00
Joe Rickerby d2394e9a57 Merge commit '57a2259a00bf7ea3309faa231406df8e487ae792' into python-pip-replacement
* commit '57a2259a00bf7ea3309faa231406df8e487ae792':
  Use travis-ci provided python3 on Linux
  linux: transfer ownership of the wheel to the current user
  Update changelog
  Bump version
  macOS/Windows: Update setuptools
  Drop python 3.3 support on Linux
  macOS: update to python 2.7.15
  Renaming util.get_build_verbosity_flag into util.get_build_verbosity_extra_flags
  Bump version
  windows: upgrade pip with 'python -m pip'
  Fixing empty verbosity flag argument to `subprocess.check_call`
  Adding an to make the `pip wheel` invocation more or less verbose
2018-06-17 21:00:16 +01:00
Joe Rickerby 0b21df216e update support matrix in readme 2018-06-17 20:52:46 +01:00
Lele Gaifax e5b9d1f586 Fix mistake in directory name 2018-06-16 15:23:26 +02:00
Lele Gaifax 9b31b5e6c9 Add support for Python 3.7
This enables building binary wheels for Python 3.7, now at its rc1 release.

It is included in the latest manylinux1 Docker image, see https://github.com/pypa/manylinux/pull/196.

Accordingly to https://www.appveyor.com/docs/build-environment/#python it is not yet available on Appveyor.
2018-06-16 13:42:11 +02:00
mayeut 1a910257bb macOS: patch _ssl module on Python 3.4 & 3.5 2018-05-06 17:13:21 +02:00
mayeut 4f542ca3d4 Add test for TLS 1.2 support & valid certificates 2018-05-06 17:13:21 +02:00
Yannick Jadoul 57a2259a00 Merge pull request #66 from mayeut/drop-linux-python3.3
Give ownership of the wheel files to the current user instead of root on Linux
2018-05-06 16:00:42 +02:00
mayeut d186b0bbb7 Use travis-ci provided python3 on Linux 2018-05-06 15:44:27 +02:00
mayeut 57cdb8711c linux: transfer ownership of the wheel to the current user 2018-05-06 15:44:27 +02:00
Joe Rickerby 7448ca3cf1 Update changelog 2018-05-04 10:21:34 -07:00
Joe Rickerby 0156a9a870 Fix "'NoneType' is not iterable" error
The build_options dict contains None objects ! :)
2018-04-08 23:38:54 +01:00
Joe Rickerby 460a4d9656 Code tidy/reorganise 2018-04-08 23:26:04 +01:00
Joe Rickerby b47a5c018f Remove unused warnings import 2018-04-08 19:11:38 +01:00
Joe Rickerby 94e33cd7e3 Switch to a more user-friendly warning style 2018-04-08 18:42:47 +01:00
Joe Rickerby c9c54602ed Correct comment 2018-04-08 18:42:21 +01:00
Joe Rickerby b74333a940 Simplify prepare_command function and add deprecation warning 2018-04-08 18:25:18 +01:00
Joe Rickerby 4655311a7a Merge origin/master into python-pip-replacement
* commit '71503b7143d22765a8f2b324dd75046644ea5726':
  Replacing leftover `test_command.format(...)` by `prepare_command(test_command, ...)` in linux.py
  Replacing {python} and {pip} in CIBW_TEST_COMMAND (and {project} in CIBW_BEFORE_BUILD) for consistency

# Conflicts:
#	README.md
#	cibuildwheel/macos.py
2018-04-08 18:11:00 +01:00
Joe Rickerby 5099d60584 Use a separate folder for bin overrides 2018-04-08 18:05:59 +01:00
Yannick Jadoul 2ebde4c078 Reverting removal of prepare_command to maintain backwards compatibility of configurations with {python} and {pip} 2018-04-08 17:01:54 +02:00
Yannick Jadoul 4d61b08fa3 Updating README, removing documentation on {python} and {pip} 2018-04-08 15:26:09 +02:00
Yannick Jadoul 5e009e53c9 Symlinking only on first-time installation of Python versions on mac OS X 2018-04-08 15:15:47 +02:00
Yannick Jadoul 783a4deec6 Symlinking python3 and pip3 to python and pip for OS X runs 2018-04-08 15:05:21 +02:00
Yannick Jadoul 529e22bfe0 Removing {python} from test 03_before_build 2018-04-08 14:14:01 +02:00
Yannick Jadoul 418cb9c39d Removing replacement of {python} and {pip} in CIBW_BEFORE_BUILD 2018-04-08 13:40:30 +02:00
14 changed files with 177 additions and 68 deletions
+11 -25
View File
@@ -5,42 +5,28 @@ matrix:
# Linux Python 2
- sudo: required
language: python
services:
- docker
env:
- "PYTHON=python2"
python: 2.7
services: docker
env: PYTHON=python
# Linux Python 3
- sudo: required
language: python
services:
- docker
env:
- "PYTHON=python3"
before_install:
- sudo apt-get -qq update
- sudo apt-get install -y python3-pip
python: 3.4
services: docker
env: PYTHON=python
# macOS Python 2
- os: osx
env:
- "PYTHON=python2"
env: PYTHON=python2
# macOS Python 3
- os: osx
env:
- "PYTHON=python3"
env: PYTHON=python3
before_install:
- brew update
- brew outdated python || brew upgrade python
script:
- |
if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
$PYTHON -m pip install -r requirements-dev.txt
$PYTHON ./bin/run_tests.py
else
# linux test requires root to clean up the wheelhouse (docker runs as root)
sudo $PYTHON -m pip install -r requirements-dev.txt
sudo $PYTHON ./bin/run_tests.py
fi
install: $PYTHON -m pip install -r requirements-dev.txt
script: $PYTHON ./bin/run_tests.py
+24 -10
View File
@@ -19,6 +19,7 @@ What does it do?
| Python 3.4 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Python 3.5 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Python 3.6 | ✅ | ✅ | ✅ | ✅ | ✅ |
| Python 3.7 | ✅ | ✅ | ✅ | | |
- Builds manylinux, macOS and Windows (32 and 64bit) wheels using Travis CI and Appveyor
- Bundles shared library dependencies on Linux and macOS through [auditwheel](https://github.com/pypa/auditwheel) and [delocate](https://github.com/matthew-brett/delocate)
@@ -49,7 +50,7 @@ Usage
env: PIP=pip2
script:
- $PIP install cibuildwheel==0.8.0
- $PIP install cibuildwheel==0.9.1
- cibuildwheel --output-dir wheelhouse
```
@@ -59,7 +60,7 @@ Usage
```
build_script:
- pip install cibuildwheel==0.8.0
- pip install cibuildwheel==0.9.1
- cibuildwheel --output-dir wheelhouse
artifacts:
- path: "wheelhouse\\*.whl"
@@ -152,7 +153,7 @@ Space-separated list of builds to skip. Each build has an identifier like `cp27-
The format is `python_tag-platform_tag`. The tags are as defined in [PEP 0425](https://www.python.org/dev/peps/pep-0425/#details).
Python tags look like `cp27` `cp34` `cp35` `cp36`
Python tags look like `cp27` `cp34` `cp35` `cp36` `cp37`
Platform tags look like `macosx_10_6_intel` `manylinux1_x86_64` `manylinux1_i686` `win32` `win_amd64`
@@ -205,13 +206,13 @@ Optional.
A shell command to run before building the wheel. This option allows you to run a command in **each** Python environment before the `pip wheel` command. This is useful if you need to set up some dependency so it's available during the build.
If dependencies are required to build your wheel (for example if you include a header from a Python module), set this to `{pip} install .`, and the dependencies will be installed automatically by pip. However, this means your package will be built twice - if your package takes a long time to build, you might wish to manually list the dependencies here instead.
If dependencies are required to build your wheel (for example if you include a header from a Python module), set this to `pip install .`, and the dependencies will be installed automatically by pip. However, this means your package will be built twice - if your package takes a long time to build, you might wish to manually list the dependencies here instead.
The active Python binary can be accessed using `{python}`, and pip with `{pip}`. These are useful when you need to write `python3` or `pip3` on a Python 3.x build. `{project}` can be used as a placeholder for the absolute path to the project's root.
The active Python binary can be accessed using `python`, and pip with `pip`; `cibuildwheel` makes sure the right version of Python and pip will be executed. `{project}` can be used as a placeholder for the absolute path to the project's root.
Example: `{pip} install .`
Example: `{pip} install pybind11`
Example: `yum install -y libffi-dev && {pip} install .`
Example: `pip install .`
Example: `pip install pybind11`
Example: `yum install -y libffi-dev && pip install .`
Platform-specific variants also available:
`CIBW_BEFORE_BUILD_MACOS` | `CIBW_BEFORE_BUILD_WINDOWS` | `CIBW_BEFORE_BUILD_LINUX`
@@ -233,7 +234,7 @@ Example: `dockcross/manylinux-x86`
Optional.
Shell command to run tests after the build. The wheel will be installed automatically and available for import from the tests. Just like in the `CIBW_BEFORE_BUILD` option, `{python}`, `{pip}`, and `{project}` will respectively be replaced by the Python executable, the pip executable, and the absolute project directory.
Shell command to run tests after the build. The wheel will be installed automatically and available for import from the tests. `{project}` can be used as a placeholder for the absolute path to the project's root and will be replaced by `cibuildwheel`.
Example: `nosetests {project}/tests`
@@ -328,6 +329,15 @@ Since `cibuildwheel` runs the wheel through delocate or auditwheel, it will auto
Changelog
=========
### 0.9.0
- Add support for Python 3.7 (#73)
### 0.8.0
- Drop support for Python 3.3 on Linux (#67)
- Fix TLS by updating setuptools (#69)
### 0.7.1
- macOS: Fix Pip bugs resulting from PyPI TLS 1.2 enforcement
@@ -418,12 +428,16 @@ Maintainers
Credits
-------
`cibuildwheel` stands on the shoulders of giants. Massive props to-
`cibuildwheel` stands on the shoulders of giants.
- ⭐️ @matthew-brett for [matthew-brett/multibuild](http://github.com/matthew-brett/multibuild) and [matthew-brett/delocate](http://github.com/matthew-brett/delocate)
- @PyPA for the manylinux Docker images [pypa/manylinux](https://github.com/pypa/manylinux)
- @ogrisel for [wheelhouse-uploader](https://github.com/ogrisel/wheelhouse-uploader) and `run_with_env.cmd`
Massive props to-
- @zfrenchee for [help debugging many issues](https://github.com/joerick/cibuildwheel/issues/2)
- @lelit for some great bug reports and [contributions](https://github.com/joerick/cibuildwheel/pull/73)
See also
--------
+1 -1
View File
@@ -1 +1 @@
__version__ = '0.8.0'
__version__ = '0.9.1'
+20
View File
@@ -171,7 +171,27 @@ def print_preamble(platform, build_options):
for option, value in build_options.items():
print(' %s: %r' % (option, value))
warnings = detect_warnings(platform, build_options)
if warnings:
print('\nWarnings:')
for warning in warnings:
print(' ' + warning)
print('\nHere we go!\n')
def detect_warnings(platform, build_options):
warnings = []
# warn about deprecated {python} and {pip}
for option_name in ['test_command', 'before_build']:
option_value = build_options.get(option_name)
if option_value:
if '{python}' in option_value or '{pip}' in option_value:
warnings.append(option_name + ": '{python}' and '{pip}' are no longer needed, and will be removed in a future release. Simply use 'python' or 'pip' instead.")
return warnings
if __name__ == '__main__':
main()
+7 -2
View File
@@ -25,11 +25,13 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
PythonConfiguration(identifier='cp34-manylinux1_x86_64', path='/opt/python/cp34-cp34m'),
PythonConfiguration(identifier='cp35-manylinux1_x86_64', path='/opt/python/cp35-cp35m'),
PythonConfiguration(identifier='cp36-manylinux1_x86_64', path='/opt/python/cp36-cp36m'),
PythonConfiguration(identifier='cp37-manylinux1_x86_64', path='/opt/python/cp37-cp37m'),
PythonConfiguration(identifier='cp27-manylinux1_i686', path='/opt/python/cp27-cp27m'),
PythonConfiguration(identifier='cp27-manylinux1_i686', path='/opt/python/cp27-cp27mu'),
PythonConfiguration(identifier='cp34-manylinux1_i686', path='/opt/python/cp34-cp34m'),
PythonConfiguration(identifier='cp35-manylinux1_i686', path='/opt/python/cp35-cp35m'),
PythonConfiguration(identifier='cp36-manylinux1_i686', path='/opt/python/cp36-cp36m'),
PythonConfiguration(identifier='cp37-manylinux1_i686', path='/opt/python/cp37-cp37m'),
]
# skip builds as required
@@ -95,19 +97,22 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
# we're all done here; move it to output
mv "$delocated_wheel" /output
chown {uid}:{gid} "/output/$(basename "$delocated_wheel")"
done
'''.format(
package_name=package_name,
pybin_paths=' '.join(c.path+'/bin' for c in platform_configs),
test_requires=' '.join(test_requires),
test_command=shlex_quote(
prepare_command(test_command, python='python', pip='pip', project='/project') if test_command else ''
prepare_command(test_command, project='/project') if test_command else ''
),
before_build=shlex_quote(
prepare_command(before_build, python='python', pip='pip', project='/project') if before_build else ''
prepare_command(before_build, project='/project') if before_build else ''
),
build_verbosity_flag=' '.join(get_build_verbosity_extra_flags(build_verbosity)),
environment_exports='\n'.join(environment.as_shell_commands()),
uid=os.getuid(),
gid=os.getgid(),
)
docker_process = subprocess.Popen([
+32 -16
View File
@@ -17,6 +17,7 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
PythonConfiguration(version='3.4', identifier='cp34-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.4.4/python-3.4.4-macosx10.6.pkg'),
PythonConfiguration(version='3.5', identifier='cp35-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.5.4/python-3.5.4-macosx10.6.pkg'),
PythonConfiguration(version='3.6', identifier='cp36-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.6.5/python-3.6.5-macosx10.6.pkg'),
PythonConfiguration(version='3.7', identifier='cp37-macosx_10_6_intel', url='https://www.python.org/ftp/python/3.7.0/python-3.7.0rc1-macosx10.6.pkg'),
]
get_pip_url = 'https://bootstrap.pypa.io/get-pip.py'
get_pip_script = '/tmp/get-pip.py'
@@ -52,27 +53,42 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
call(['curl', '-L', '-o', '/tmp/Python.pkg', config.url])
# install
call(['sudo', 'installer', '-pkg', '/tmp/Python.pkg', '-target', '/'])
# patch open ssl
if config.version in ('3.4', '3.5'):
call(['curl', '-fsSLo', '/tmp/python-patch.tar.gz', 'https://github.com/mayeut/patch-macos-python-openssl/releases/download/v0.1.0/patch-macos-python-%s-openssl-v0.1.0.tar.gz' % config.version])
call(['sudo', 'tar', '-C', '/Library/Frameworks/Python.framework/Versions/%s/' % config.version, '-xmf', '/tmp/python-patch.tar.gz'])
installation_bin_path = '/Library/Frameworks/Python.framework/Versions/{}/bin'.format(config.version)
# Python bin folders on Mac don't symlink python3 to python, so we do that
# so `python` and `pip` always point to the active configuration.
if os.path.exists('/tmp/cibw_bin'):
shutil.rmtree('/tmp/cibw_bin')
os.makedirs('/tmp/cibw_bin')
if config.version[0] == '3':
os.symlink(os.path.join(installation_bin_path, 'python3'), '/tmp/cibw_bin/python')
os.symlink(os.path.join(installation_bin_path, 'python3-config'), '/tmp/cibw_bin/python-config')
os.symlink(os.path.join(installation_bin_path, 'pip3'), '/tmp/cibw_bin/pip')
env = os.environ.copy()
env['PATH'] = os.pathsep.join([
'/Library/Frameworks/Python.framework/Versions/%s/bin' % config.version,
'/tmp/cibw_bin',
installation_bin_path,
env['PATH'],
])
env = environment.as_dictionary(prev_environment=env)
python = 'python3' if config.version[0] == '3' else 'python2'
pip = 'pip3' if config.version[0] == '3' else 'pip2'
# check what version we're on
call(['which', python], env=env)
call([python, '--version'], env=env)
call(['which', 'python'], env=env)
call(['python', '--version'], env=env)
# install pip & wheel
call([python, get_pip_script, '--no-setuptools', '--no-wheel'], env=env)
call([pip, '--version'], env=env)
call([pip, 'install', '--upgrade', 'setuptools'], env=env)
call([pip, 'install', 'wheel'], env=env)
call([pip, 'install', 'delocate'], env=env)
call(['python', get_pip_script, '--no-setuptools', '--no-wheel'], env=env)
call(['pip', '--version'], env=env)
call(['pip', 'install', '--upgrade', 'setuptools'], env=env)
call(['pip', 'install', 'wheel'], env=env)
call(['pip', 'install', 'delocate'], env=env)
# setup dirs
if os.path.exists('/tmp/built_wheel'):
@@ -84,11 +100,11 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
# run the before_build command
if before_build:
before_build_prepared = prepare_command(before_build, python=python, pip=pip, project=abs_project_dir)
before_build_prepared = prepare_command(before_build, project=abs_project_dir)
call(before_build_prepared, env=env, shell=True)
# build the wheel
call([pip, 'wheel', abs_project_dir, '-w', '/tmp/built_wheel', '--no-deps'] + get_build_verbosity_extra_flags(build_verbosity), env=env)
call(['pip', 'wheel', abs_project_dir, '-w', '/tmp/built_wheel', '--no-deps'] + get_build_verbosity_extra_flags(build_verbosity), env=env)
built_wheel = glob('/tmp/built_wheel/*.whl')[0]
if built_wheel.endswith('none-any.whl'):
@@ -102,16 +118,16 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
delocated_wheel = glob('/tmp/delocated_wheel/*.whl')[0]
# install the wheel
call([pip, 'install', delocated_wheel], env=env)
call(['pip', 'install', delocated_wheel], env=env)
# test the wheel
if test_requires:
call([pip, 'install'] + test_requires, env=env)
call(['pip', 'install'] + test_requires, env=env)
if test_command:
# run the tests from $HOME, with an absolute path in the command
# (this ensures that Python runs the tests against the installed wheel
# and not the repo code)
test_command_prepared = prepare_command(test_command, python=python, pip=pip, project=abs_project_dir)
test_command_prepared = prepare_command(test_command, project=abs_project_dir)
call(shlex.split(test_command_prepared), cwd=os.environ['HOME'], env=env)
# we're all done here; move it to output
+6 -7
View File
@@ -1,16 +1,15 @@
from fnmatch import fnmatch
import warnings
def prepare_command(command, python, pip, project):
def prepare_command(command, project):
'''
Preprocesses a command by expanding variables like {python} or {pip}.
Preprocesses a command by expanding variables like {project}.
For example, used for the before_build option, where the user would
like to run a command like `python setup.py test`. If the command should run on
Python 3, the user could write `{python} setup.py test`. This command would expand
it out to python2 or python3 as appropriate.
For example, used in the test_command option, to specify the path to the
tests directory.
'''
return command.format(python=python, pip=pip, project=project)
return command.format(python='python', pip='pip', project=project)
def get_build_verbosity_extra_flags(level):
+2 -2
View File
@@ -79,7 +79,7 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
# run the before_build command
if before_build:
before_build_prepared = prepare_command(before_build, python='python', pip='pip', project=abs_project_dir)
before_build_prepared = prepare_command(before_build, project=abs_project_dir)
shell([before_build_prepared], env=env)
# build the wheel
@@ -96,7 +96,7 @@ def build(project_dir, package_name, output_dir, test_command, test_requires, be
# run the tests from c:\, with an absolute path in the command
# (this ensures that Python runs the tests against the installed wheel
# and not the repo code)
test_command_prepared = prepare_command(test_command, python='python', pip='pip', project=abs_project_dir)
test_command_prepared = prepare_command(test_command, project=abs_project_dir)
shell([test_command_prepared], cwd='c:\\', env=env)
# we're all done here; move it to output
+1 -1
View File
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.8.0
current_version = 0.9.1
commit = True
tag = True
message = Bump version
+1 -1
View File
@@ -8,7 +8,7 @@ except ImportError:
setup(
name='cibuildwheel',
version='0.8.0',
version='0.9.1',
install_requires=['bashlex'],
description="Build Python wheels on CI with minimal configuration.",
long_description='For readme please see http://github.com/joerick/cibuildwheel',
+2 -2
View File
@@ -1,4 +1,4 @@
{
"CIBW_BEFORE_BUILD": "{python} -c \"import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)\" && {python} -c \"import sys; open('/tmp/pythonexecutable.txt', 'w').write(sys.executable)\"",
"CIBW_BEFORE_BUILD_WINDOWS": "{python} -c \"import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)\" && {python} -c \"import sys; open('c:\\pythonexecutable.txt', 'w').write(sys.executable)\""
"CIBW_BEFORE_BUILD": "python -c \"import sys; open('/tmp/pythonversion.txt', 'w').write(sys.version)\" && python -c \"import sys; open('/tmp/pythonexecutable.txt', 'w').write(sys.executable)\"",
"CIBW_BEFORE_BUILD_WINDOWS": "python -c \"import sys; open('c:\\pythonversion.txt', 'w').write(sys.version)\" && python -c \"import sys; open('c:\\pythonexecutable.txt', 'w').write(sys.executable)\""
}
+2 -1
View File
@@ -1,4 +1,5 @@
{
"CIBW_MANYLINUX1_X86_64_IMAGE": "dockcross/manylinux-x64",
"CIBW_MANYLINUX1_I686_IMAGE": "dockcross/manylinux-x86"
"CIBW_MANYLINUX1_I686_IMAGE": "dockcross/manylinux-x86",
"CIBW_SKIP": "cp37-manylinux*"
}
+20
View File
@@ -0,0 +1,20 @@
import ssl
import sys
from setuptools import setup, Extension
if sys.version_info[0] == 2:
from urllib2 import urlopen
else:
from urllib.request import urlopen
if sys.version_info[0:2] == (3, 3):
data = urlopen('https://www.nist.gov')
else:
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
data = urlopen('https://www.nist.gov', context=context)
setup(
name="spam",
ext_modules=[Extension('spam', sources=['spam.c'])],
version="0.1.0",
)
+48
View File
@@ -0,0 +1,48 @@
#include <Python.h>
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = system(command);
return PyLong_FromLong(sts);
}
/* Module initialization */
#if PY_MAJOR_VERSION >= 3
#define MOD_INIT(name) PyMODINIT_FUNC PyInit_##name(void)
#define MOD_DEF(m, name, doc, methods, module_state_size) \
static struct PyModuleDef moduledef = { \
PyModuleDef_HEAD_INIT, name, doc, module_state_size, methods, }; \
m = PyModule_Create(&moduledef);
#define MOD_RETURN(m) return m;
#else
#define MOD_INIT(name) PyMODINIT_FUNC init##name(void)
#define MOD_DEF(m, name, doc, methods, module_state_size) \
m = Py_InitModule3(name, methods, doc);
#define MOD_RETURN(m) return;
#endif
static PyMethodDef module_methods[] = {
{"system", (PyCFunction)spam_system, METH_VARARGS,
"Execute a shell command."},
{NULL} /* Sentinel */
};
MOD_INIT(spam)
{
PyObject* m;
MOD_DEF(m,
"spam",
"Example module",
module_methods,
-1)
MOD_RETURN(m)
}