Skip to content

Commit a1b17bf

Browse files
authored
Merge pull request #31 from pycompression/windows
Add windows support.
2 parents 76726d8 + 3660703 commit a1b17bf

File tree

9 files changed

+163
-108
lines changed

9 files changed

+163
-108
lines changed

.github/workflows/ci.yml

Lines changed: 58 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ on:
99
tags:
1010
- "*"
1111

12+
defaults:
13+
run:
14+
# This is needed for miniconda, see:
15+
# https://github.com/marketplace/actions/setup-miniconda#important.
16+
shell: bash -l {0}
1217

1318
jobs:
1419
lint:
@@ -25,26 +30,14 @@ jobs:
2530
run: pip install tox
2631
- name: Lint
2732
run: tox -e lint
28-
docs:
29-
needs: lint
30-
runs-on: ubuntu-20.04
31-
steps:
32-
- uses: actions/[email protected]
33-
with:
34-
submodules: recursive
35-
- name: Set up Python 3.6
36-
uses: actions/[email protected]
37-
with:
38-
python-version: 3.6
39-
- name: Install isal
40-
run: sudo apt-get install libisal-dev
41-
- name: Install tox and upgrade setuptools and pip
42-
run: pip install --upgrade tox setuptools pip
43-
- name: Build docs
44-
run: tox -e docs
45-
env:
46-
PYTHON_ISAL_LINK_DYNAMIC: True
47-
mypy:
33+
34+
package-checks:
35+
strategy:
36+
matrix:
37+
tox_env:
38+
- docs
39+
- mypy
40+
- twine_check
4841
needs: lint
4942
runs-on: ubuntu-20.04
5043
steps:
@@ -59,38 +52,10 @@ jobs:
5952
run: sudo apt-get install libisal-dev
6053
- name: Install tox and upgrade setuptools and pip
6154
run: pip install --upgrade tox setuptools pip
62-
- name: Mypy checks
63-
run: tox -e mypy
55+
- name: Run tox -e ${{ matrix.tox_env }}
56+
run: tox -e ${{ matrix.tox_env }}
6457
env:
6558
PYTHON_ISAL_LINK_DYNAMIC: True
66-
twine_check:
67-
needs: lint
68-
runs-on: ${{ matrix.os }}
69-
strategy:
70-
matrix:
71-
python-version:
72-
- 3.6
73-
os: ["ubuntu-latest" ]
74-
steps:
75-
- uses: actions/[email protected]
76-
with:
77-
submodules: recursive
78-
- name: Set up Python ${{ matrix.python-version }}
79-
uses: actions/[email protected]
80-
with:
81-
python-version: ${{ matrix.python-version }}
82-
- name: Install build dependencies (Linux) # Yasm in pypa/manylinux images.
83-
run: sudo apt install yasm
84-
if: runner.os == 'Linux'
85-
- name: Install build dependencies (Macos)
86-
run: brew install yasm automake autoconf
87-
if: runner.os == 'macOS'
88-
- name: Install twine, cython wheel and upgrade setuptools
89-
run: pip install --upgrade twine cython wheel setuptools
90-
- name: create dists
91-
run: python setup.py sdist bdist_wheel
92-
- name: check dists
93-
run: twine check dist/*
9459

9560
test-static:
9661
needs: lint
@@ -105,48 +70,55 @@ jobs:
10570
os: ["ubuntu-latest"]
10671
include:
10772
- os: "macos-latest"
108-
python-version: 3.8
73+
python-version: 3.6
74+
- os: "windows-latest"
75+
python-version: 3.6
10976
steps:
11077
- uses: actions/[email protected]
11178
with:
11279
submodules: recursive
113-
- name: Set up Python ${{ matrix.python-version }}
114-
uses: actions/setup-python@v2.2.1
80+
- name: Install miniconda.
81+
uses: conda-incubator/setup-miniconda@v2.0.1 # https://github.com/conda-incubator/setup-miniconda.
11582
with:
116-
python-version: ${{ matrix.python-version }}
117-
- name: Install tox and upgrade setuptools
118-
run: pip install --upgrade tox setuptools
119-
- name: Install build dependencies (Linux) # Yasm in pypa/manylinux images.
120-
run: sudo apt install yasm
121-
if: runner.os == 'Linux'
122-
- name: Install build dependencies (Macos)
123-
run: brew install yasm automake autoconf
83+
channels: conda-forge,defaults
84+
- name: Install requirements (MacOS)
85+
run: conda install python=${{ matrix.python-version }} tox make automake autoconf libtool nasm
12486
if: runner.os == 'macOS'
87+
- name: Install requirements (Linux)
88+
run: conda install python=${{ matrix.python-version }} tox make automake autoconf libtool yasm # Yasm in pypa/manylinux images.
89+
if: runner.os == 'Linux'
90+
- name: install requirements (Windows)
91+
run: conda install python=${{ matrix.python-version }} tox nasm
92+
if: runner.os == 'Windows'
93+
- name: Set MSVC developer prompt
94+
uses: ilammy/[email protected]
95+
if: runner.os == 'Windows'
12596
- name: Run tests
12697
run: tox -e py3
12798
- name: Upload coverage report
12899
uses: codecov/codecov-action@v1
129100

101+
# Test if the python-isal conda package can be build. Which is linked
102+
# dynamically to the conda isa-l package.
130103
test-dynamic:
131104
runs-on: ${{ matrix.os }}
132105
needs: lint
133106
strategy:
134107
matrix:
135-
python-version:
136-
- 3.6
137-
os: ["ubuntu-20.04"]
108+
os: ["ubuntu-latest", "macos-latest", "windows-latest"]
138109
steps:
139110
- uses: actions/[email protected]
140111
with:
141112
submodules: recursive
142-
- name: Set up Python ${{ matrix.python-version }}
143-
uses: actions/setup-python@v2.2.1
113+
- name: Install miniconda.
114+
uses: conda-incubator/setup-miniconda@v2.0.1 # https://github.com/conda-incubator/setup-miniconda.
144115
with:
145-
python-version: ${{ matrix.python-version }}
146-
- name: Install isal
147-
run: sudo apt-get install libisal-dev
148-
- name: Install tox and upgrade setuptools and pip
149-
run: pip install --upgrade tox setuptools pip
116+
channels: conda-forge,defaults
117+
- name: Install requirements (universal)
118+
run: conda install isa-l python tox
119+
- name: Set MSVC developer prompt
120+
uses: ilammy/[email protected]
121+
if: runner.os == 'Windows'
150122
- name: Run tests (dynamic link)
151123
run: tox -e py3
152124
env:
@@ -155,21 +127,29 @@ jobs:
155127
deploy:
156128
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
157129
runs-on: ${{ matrix.os }}
158-
needs: [lint, docs, test-static, test-dynamic, twine_check]
130+
needs: [lint, package-checks, test-static, test-dynamic]
159131
strategy:
160132
matrix:
161-
os: [ "macos-latest", "ubuntu-latest" ]
133+
os: ["macos-latest", "ubuntu-latest", "windows-latest"]
162134
steps:
163135
- uses: actions/[email protected]
164136
with:
165137
submodules: recursive
166-
- uses: actions/setup-python@v2
167-
name: Install Python
168-
- name: Install cibuildwheel twine
169-
run: python -m pip install cibuildwheel twine
138+
- name: Install miniconda.
139+
uses: conda-incubator/[email protected] # https://github.com/conda-incubator/setup-miniconda.
140+
with:
141+
channels: conda-forge,defaults
170142
- name: Install build dependencies (Macos)
171-
run: brew install yasm automake autoconf
143+
run: conda install nasm automake autoconf python
172144
if: runner.os == 'macOS'
145+
- name: Install build dependencies (Windows)
146+
run: conda install nasm python
147+
if: runner.os == 'Windows'
148+
- name: Set MSVC developer prompt
149+
uses: ilammy/[email protected]
150+
if: runner.os == 'Windows'
151+
- name: Install cibuildwheel twine
152+
run: python -m pip install cibuildwheel twine
173153
- name: Build wheels
174154
run: cibuildwheel --output-dir dist
175155
env:

CHANGELOG.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ Changelog
77
.. This document is user facing. Please word the changes in such a way
88
.. that users understand how the changes affect the new version.
99
10+
version 0.6.0-dev
11+
-----------------
12+
+ Installation on Windows is now supported. Wheels are provided for Windows as
13+
well.
14+
1015
version 0.5.0
1116
-----------------
1217
+ Fix a bug where negative integers were not allowed for the ``adler32`` and

README.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ Installation
7171
Installation with pip
7272
.....................
7373

74-
+ Linux and MacOS: ``pip install isal``. Wheels are provided, so installation should
75-
be almost instantaneous.
76-
+ Windows: Installation is not supported yet.
74+
+ ``pip install isal``
7775

78-
The installation will include a staticallly linked version of isa-l. On Linux
79-
and MacOS, wheels are provided. If a wheel is not provided for your system the
76+
Installation is supported on Linux, MacOS and Windows. On x86-64 (amd64)
77+
platforms wheels are provided, so installation should be almost instantaneous.
78+
The installation will include a staticallly linked version of isa-l.
79+
If a wheel is not provided for your system the
8080
installation will build ISA-L first in a temporary directory. Please check the
8181
`ISA-L homepage <https://github.com/intel/isa-l>`_ for the build requirements.
8282

setup.py

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,21 @@
3030

3131
ISA_L_SOURCE = os.path.join("src", "isal", "isa-l")
3232

33+
SYSTEM_IS_UNIX = (sys.platform.startswith("linux") or
34+
sys.platform.startswith("darwin"))
35+
SYSTEM_IS_WINDOWS = sys.platform.startswith("win")
36+
3337

3438
class IsalExtension(Extension):
3539
"""Custom extension to allow for targeted modification."""
3640
pass
3741

3842

43+
MODULES = [IsalExtension("isal.isal_zlib", ["src/isal/isal_zlib.pyx"])]
44+
if SYSTEM_IS_UNIX:
45+
MODULES.append(IsalExtension("isal._isal", ["src/isal/_isal.pyx"]))
46+
47+
3948
class BuildIsalExt(build_ext):
4049
def build_extension(self, ext):
4150
if not isinstance(ext, IsalExtension):
@@ -50,19 +59,37 @@ def build_extension(self, ext):
5059
# installing in a conda environment.
5160
possible_prefixes = [sys.exec_prefix, sys.base_exec_prefix]
5261
for prefix in possible_prefixes:
53-
if os.path.exists(os.path.join(prefix, "include", "isa-l")):
54-
ext.include_dirs = [
55-
os.path.join(prefix, "include")]
56-
break # Only one include directory is needed.
57-
ext.libraries = ["isal"]
62+
if Path(prefix, "include", "isa-l").exists():
63+
ext.include_dirs = [os.path.join(prefix, "include")]
64+
break # Only one include directory is needed.
65+
# On windows include is in Library apparently
66+
elif Path(prefix, "Library", "include", "isa-l").exists():
67+
ext.include_dirs = [os.path.join(prefix, "Library",
68+
"include")]
69+
ext.library_dirs = [os.path.join(prefix, "Library", "lib")]
70+
break
71+
if SYSTEM_IS_UNIX:
72+
ext.libraries = ["isal"] # libisal.so*
73+
elif SYSTEM_IS_WINDOWS:
74+
ext.libraries = ["isa-l"] # isa-l.dll
75+
else:
76+
raise NotImplementedError(
77+
f"Unsupported platform: {sys.platform}")
5878
else:
5979
isa_l_prefix_dir = build_isa_l()
80+
if SYSTEM_IS_UNIX:
81+
ext.extra_objects = [
82+
os.path.join(isa_l_prefix_dir, "lib", "libisal.a")]
83+
elif SYSTEM_IS_WINDOWS:
84+
ext.extra_objects = [
85+
os.path.join(isa_l_prefix_dir, "isa-l_static.lib")]
86+
else:
87+
raise NotImplementedError(
88+
f"Unsupported platform: {sys.platform}")
6089
ext.include_dirs = [os.path.join(isa_l_prefix_dir,
6190
"include")]
6291
# -fPIC needed for proper static linking
6392
ext.extra_compile_args = ["-fPIC"]
64-
ext.extra_objects = [
65-
os.path.join(isa_l_prefix_dir, "lib", "libisal.a")]
6693

6794
if os.getenv("CYTHON_COVERAGE") is not None:
6895
# Import cython here so python setup.py can be used without
@@ -102,12 +129,23 @@ def build_isa_l():
102129
else: # sched_getaffinity not available on all platforms
103130
cpu_count = os.cpu_count() or 1 # os.cpu_count() can return None
104131
run_args = dict(cwd=build_dir, env=build_env)
105-
subprocess.run(os.path.join(build_dir, "autogen.sh"), **run_args)
106-
subprocess.run([os.path.join(build_dir, "configure"),
107-
"--prefix", temp_prefix], **run_args)
108-
subprocess.run(["make", "-j", str(cpu_count)],
109-
**run_args)
110-
subprocess.run(["make", "install"], **run_args)
132+
if SYSTEM_IS_UNIX:
133+
subprocess.run(os.path.join(build_dir, "autogen.sh"), **run_args)
134+
subprocess.run([os.path.join(build_dir, "configure"),
135+
"--prefix", temp_prefix], **run_args)
136+
subprocess.run(["make", "-j", str(cpu_count)],
137+
**run_args)
138+
subprocess.run(["make", "install"], **run_args)
139+
elif SYSTEM_IS_WINDOWS:
140+
subprocess.run(["nmake", "/f", "Makefile.nmake"], **run_args)
141+
Path(temp_prefix, "include").mkdir()
142+
print(temp_prefix, file=sys.stderr)
143+
shutil.copytree(os.path.join(build_dir, "include"),
144+
Path(temp_prefix, "include", "isa-l"))
145+
shutil.copy(os.path.join(build_dir, "isa-l_static.lib"),
146+
os.path.join(temp_prefix, "isa-l_static.lib"))
147+
else:
148+
raise NotImplementedError(f"Unsupported platform: {sys.platform}")
111149
shutil.rmtree(build_dir)
112150
return temp_prefix
113151

@@ -149,8 +187,5 @@ def build_isa_l():
149187
"Operating System :: MacOS"
150188
],
151189
python_requires=">=3.6",
152-
ext_modules=[
153-
IsalExtension("isal.isal_zlib", ["src/isal/isal_zlib.pyx"]),
154-
IsalExtension("isal._isal", ["src/isal/_isal.pyx"]),
155-
]
190+
ext_modules=MODULES
156191
)

src/isal/__init__.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,19 @@
1717
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1818
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1919
# SOFTWARE.
20+
from typing import Optional
2021

21-
from ._isal import ISAL_MAJOR_VERSION, ISAL_MINOR_VERSION, \
22-
ISAL_PATCH_VERSION, ISAL_VERSION
22+
try:
23+
from . import _isal
24+
ISAL_MAJOR_VERSION: Optional[int] = _isal.ISAL_MAJOR_VERSION
25+
ISAL_MINOR_VERSION: Optional[int] = _isal.ISAL_MINOR_VERSION
26+
ISAL_PATCH_VERSION: Optional[int] = _isal.ISAL_PATCH_VERSION
27+
ISAL_VERSION: Optional[str] = _isal.ISAL_VERSION
28+
except ImportError: # isa-l.h not available on windows
29+
ISAL_MAJOR_VERSION = None
30+
ISAL_MINOR_VERSION = None
31+
ISAL_PATCH_VERSION = None
32+
ISAL_VERSION = None
2333

2434
__all__ = [
2535
"ISAL_MAJOR_VERSION",

tests/test_gzip_compliance.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ def seek(self, *args):
5858

5959

6060
class BaseTest(unittest.TestCase):
61-
fileno, filename = tempfile.mkstemp()
61+
62+
def __init__(self, methodName):
63+
fileno, self.filename = tempfile.mkstemp()
64+
os.close(fileno)
65+
super().__init__(methodName)
6266

6367
def setUp(self):
6468
if os.path.exists(self.filename):
@@ -391,7 +395,8 @@ def test_metadata(self):
391395
self.assertEqual(isizeBytes, struct.pack('<i', len(data1)))
392396

393397
def test_metadata_ascii_name(self):
394-
self.filename = tempfile.mkstemp()[1]
398+
fd, self.filename = tempfile.mkstemp()
399+
os.close(fd)
395400
self.test_metadata()
396401

397402
def test_compresslevel_metadata(self):

0 commit comments

Comments
 (0)