Skip to content

Commit

Permalink
[CLIENT-2322] Add support for Windows (#437)
Browse files Browse the repository at this point in the history
  • Loading branch information
juliannguyen4 committed Feb 7, 2024
1 parent 851aee1 commit 8aa7e68
Show file tree
Hide file tree
Showing 25 changed files with 585 additions and 769 deletions.
84 changes: 84 additions & 0 deletions .github/workflows/build-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,89 @@ jobs:
docker container stop aerospike
docker container prune -f
windows-build:
needs: update-version
if: ${{ !cancelled() && (needs.update-version.result == 'skipped' || needs.update-version.result == 'success') }}
strategy:
fail-fast: false
matrix:
python: [
["cp38", "3.8"],
["cp39", "3.9"],
["cp310", "3.10"],
["cp311", "3.11"],
]
runs-on: windows-2022
# runs-on: [self-hosted, Windows]
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v1.1

- name: Install C client deps
run: nuget restore
working-directory: aerospike-client-c/vs

- name: Build wheel
uses: pypa/cibuildwheel@v2.11.2
env:
CIBW_BUILD: ${{ matrix.python[0] }}-win_amd64
CIBW_BUILD_FRONTEND: build
CIBW_ARCHS: auto64
CIBW_BEFORE_BUILD_WINDOWS: "pip install delvewheel"
CIBW_REPAIR_WHEEL_COMMAND: "delvewheel repair --add-path ./aerospike-client-c/vs/x64/Release -w {dest_dir} {wheel}"

- uses: actions/upload-artifact@v3
with:
path: ./wheelhouse/*.whl
name: ${{ matrix.python[0] }}-win_amd64

test-windows:
needs: windows-build
strategy:
fail-fast: false
matrix:
python: [
["cp38", "3.8"],
["cp39", "3.9"],
["cp310", "3.10"],
["cp311", "3.11"],
]
runs-on: [self-hosted, Windows, X64]
# Workaround for a bug where skipped ancestor job will also skip this job
if: ${{ !cancelled() && needs.windows-build.result == 'success' }}
steps:
- uses: actions/checkout@v4
- run: docker run -d -p 3000:3000 --name aerospike aerospike/aerospike-server
- name: Download wheel
uses: actions/download-artifact@v3
with:
name: ${{ matrix.python[0] }}-win_amd64
- name: Install wheel
run: python${{ matrix.python[1] }} -m pip install aerospike --force-reinstall --no-index --find-links=./
- name: Connect to Docker container on remote machine with Docker daemon
# DOCKER_HOST contains the IP address of the remote machine
run: |
python${{ matrix.python[1] }} -m pip install crudini==0.9.4
$env:DOCKER_HOST_IP = $env:DOCKER_HOST | foreach {$_.replace("tcp://","")} | foreach {$_.replace(":2375", "")}
python${{ matrix.python[1] }} -m crudini --set config.conf community-edition hosts ${env:DOCKER_HOST_IP}:3000
working-directory: test

- run: python${{ matrix.python[1] }} -m pip install pytest -c requirements.txt
working-directory: test

- run: python${{ matrix.python[1] }} -m pytest new_tests/
working-directory: test

- name: Cleanup
if: ${{ always() }}
run: |
docker stop aerospike
docker container rm aerospike
upload-artifacts-to-jfrog:
if: ${{ inputs.should-bump-version }}
needs: [
Expand All @@ -561,6 +644,7 @@ jobs:
manylinux_arm64,
macOS-x86,
macOS-m1,
test-windows
]
runs-on: ubuntu-latest
steps:
Expand Down
1 change: 1 addition & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The Python client for Aerospike works with Python 3.8 - 3.11 and supports the fo
* Amazon Linux 2023
* Debian 11 and 12
* Ubuntu 20.04 and 22.04
* Windows (x64)

The client is also verified to run on these operating systems, but we do not officially support them (i.e we don't distribute wheels or prioritize fixing bugs for these OSes):

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
15.0.0-rc.1
15.0.0-rc.2
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ classifiers = [
"License :: OSI Approved :: Apache Software License",
"Operating System :: POSIX :: Linux",
"Operating System :: MacOS :: MacOS X",
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
Expand Down
55 changes: 43 additions & 12 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from multiprocessing import cpu_count
import time
import io
import xml.etree.ElementTree as ET

################################################################################
# ENVIRONMENT VARIABLES
Expand All @@ -42,6 +43,8 @@
PLATFORM = platform.platform(1)
LINUX = 'Linux' in PLATFORM
DARWIN = 'Darwin' in PLATFORM or 'macOS' in PLATFORM
WINDOWS = 'Windows' in PLATFORM

CWD = os.path.abspath(os.path.dirname(__file__))
STATIC_SSL = os.getenv('STATIC_SSL')
SSL_LIB_PATH = os.getenv('SSL_LIB_PATH')
Expand All @@ -59,12 +62,16 @@
['aerospike-client-c/modules/common/src/include']
extra_compile_args = [
'-std=gnu99', '-g', '-Wall', '-fPIC', '-DDEBUG', '-O1',
'-fno-common', '-fno-strict-aliasing', '-Wno-strict-prototypes',
'-fno-common', '-fno-strict-aliasing',
'-D_FILE_OFFSET_BITS=64', '-D_REENTRANT',
'-DMARCH_' + machine,
'-Wno-implicit-function-declaration'
]

if not WINDOWS:
# Windows does not have this flag
extra_compile_args.append("-Wno-strict-prototypes")
extra_compile_args.append('-Wno-implicit-function-declaration')

if machine == 'x86_64':
extra_compile_args.append('-march=nocona')
extra_objects = []
Expand Down Expand Up @@ -123,6 +130,13 @@
# PLATFORM SPECIFIC BUILD SETTINGS
################################################################################

if WINDOWS:
AEROSPIKE_C_TARGET = AEROSPIKE_C_HOME
tree = ET.parse(f"{AEROSPIKE_C_TARGET}/vs/aerospike/packages.config")
packages = tree.getroot()
package = packages[0]
c_client_dependencies_version = package.attrib["version"]

if DARWIN:
# ---------------------------------------------------------------------------
# Mac Specific Compiler and Linker Settings
Expand All @@ -142,17 +156,28 @@
]
libraries = libraries + ['rt']
AEROSPIKE_C_TARGET = AEROSPIKE_C_HOME + '/target/Linux-' + machine
elif WINDOWS:
libraries.clear()
extra_compile_args.append("-DAS_SHARED_IMPORT")
include_dirs.append(f"{AEROSPIKE_C_TARGET}/vs/packages/aerospike-client-c-dependencies.{c_client_dependencies_version}/build/native/include")
else:
print("error: OS not supported:", PLATFORM, file=sys.stderr)
sys.exit(8)

include_dirs = include_dirs + [
'/usr/local/opt/openssl/include',
AEROSPIKE_C_TARGET + '/include'
]
extra_objects = extra_objects + [
AEROSPIKE_C_TARGET + '/lib/libaerospike.a'

]
if not WINDOWS:
include_dirs.append(AEROSPIKE_C_TARGET + '/include')
extra_objects = extra_objects + [
AEROSPIKE_C_TARGET + '/lib/libaerospike.a'
]
else:
include_dirs.append(AEROSPIKE_C_TARGET + '/src/include')
library_dirs.append(f"{AEROSPIKE_C_TARGET}/vs/packages/aerospike-client-c-dependencies.{c_client_dependencies_version}/build/native/lib/x64/Release")
# Needed for linking the Python client with the C client
extra_objects.append(AEROSPIKE_C_TARGET + "/vs/x64/Release/aerospike.lib")

os.putenv('CPATH', ':'.join(include_dirs))
os.environ['CPATH'] = ':'.join(include_dirs)
Expand All @@ -172,6 +197,7 @@
BASEPATH = os.path.dirname(os.path.abspath(__file__))
CCLIENT_PATH = os.path.join(BASEPATH, 'aerospike-client-c')


class CClientBuild(build):

def run(self):
Expand All @@ -191,10 +217,17 @@ def clean():
os.putenv('DYLD_LIBRARY_PATH', ':'.join(library_dirs))
os.environ['DYLD_LIBRARY_PATH'] = ':'.join(library_dirs)
# build core client
cmd = [
'make',
'V=' + str(self.verbose),
]
if WINDOWS:
cmd = [
'msbuild',
'vs/aerospike.sln',
'/property:Configuration=Release'
]
else:
cmd = [
'make',
'V=' + str(self.verbose),
]

def compile():
print(cmd, library_dirs, libraries)
Expand Down Expand Up @@ -259,7 +292,6 @@ def clean():
'src/main/client/remove.c',
'src/main/client/scan.c',
'src/main/client/select.c',
'src/main/client/tls_info_host.c',
'src/main/client/truncate.c',
'src/main/client/admin.c',
'src/main/client/udf.c',
Expand Down Expand Up @@ -336,7 +368,6 @@ def clean():
packages=['aerospike_helpers', 'aerospike_helpers.operations', 'aerospike_helpers.batch',
'aerospike_helpers.expressions',
'aerospike-stubs'],

cmdclass={
'build': CClientBuild,
'clean': CClientClean
Expand Down
6 changes: 3 additions & 3 deletions src/include/conversions.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ as_status as_udf_file_to_pyobject(as_error *err, as_udf_file *entry,
as_status as_udf_files_to_pyobject(as_error *err, as_udf_files *files,
PyObject **py_files);

as_status strArray_to_py_list(as_error *err, int num_elements, int element_size,
char str_array_ptr[][element_size],
PyObject *py_list);
as_status str_array_of_roles_to_py_list(as_error *err, int num_elements,
char str_array_ptr[][AS_ROLE_SIZE],
PyObject *py_list);

as_status char_double_ptr_to_py_list(as_error *err, int num_elements,
int element_size, char **str_array_ptr,
Expand Down
23 changes: 0 additions & 23 deletions src/include/tls_info_host.h

This file was deleted.

2 changes: 1 addition & 1 deletion src/main/aerospike.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ static int Aerospike_Clear(PyObject *aerospike)
PyMODINIT_FUNC PyInit_aerospike(void)
{

const char version[] = "15.0.0-rc.1";
const char version[] = "15.0.0-rc.2";
// Makes things "thread-safe"
Py_Initialize();
int i = 0;
Expand Down
1 change: 0 additions & 1 deletion src/main/cdt_types/type.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <Python.h>
#include <structmember.h>
#include <stdbool.h>
#include <unistd.h>
#include "types.h"
#include "cdt_types.h"

Expand Down
10 changes: 5 additions & 5 deletions src/main/client/batch_apply.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,23 +337,23 @@ PyObject *AerospikeClient_Batch_Apply(AerospikeClient *self, PyObject *args,
if (!PyList_Check(py_keys)) {
as_error_update(&err, AEROSPIKE_ERR_PARAM,
"keys should be a list of aerospike key tuples");
goto ERROR;
goto error;
}

if (!PyUnicode_Check(py_mod)) {
as_error_update(&err, AEROSPIKE_ERR_PARAM, "module must be a string");
goto ERROR;
goto error;
}

if (!PyUnicode_Check(py_func)) {
as_error_update(&err, AEROSPIKE_ERR_PARAM, "function must be a string");
goto ERROR;
goto error;
}

if (!PyList_Check(py_args)) {
as_error_update(&err, AEROSPIKE_ERR_PARAM,
"args must be a list of arguments for the UDF");
goto ERROR;
goto error;
}

py_results = AerospikeClient_Batch_Apply_Invoke(
Expand All @@ -362,7 +362,7 @@ PyObject *AerospikeClient_Batch_Apply(AerospikeClient *self, PyObject *args,

return py_results;

ERROR:
error:

if (err.code != AEROSPIKE_OK) {
raise_exception(&err);
Expand Down
8 changes: 4 additions & 4 deletions src/main/client/batch_operate.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,19 +363,19 @@ PyObject *AerospikeClient_Batch_Operate(AerospikeClient *self, PyObject *args,
if (!PyList_Check(py_ops) || !PyList_Size(py_ops)) {
as_error_update(&err, AEROSPIKE_ERR_PARAM,
"ops should be a list of op dictionaries");
goto ERROR;
goto error;
}

// required arg so don't need to check for NULL
if (!PyList_Check(py_keys)) {
as_error_update(&err, AEROSPIKE_ERR_PARAM,
"keys should be a list of aerospike key tuples");
goto ERROR;
goto error;
}

if (py_ttl && py_ttl != Py_None && !PyLong_Check(py_ttl)) {
as_error_update(&err, AEROSPIKE_ERR_PARAM, "ttl should be an integer");
goto ERROR;
goto error;
}

py_results = AerospikeClient_Batch_Operate_Invoke(
Expand All @@ -384,7 +384,7 @@ PyObject *AerospikeClient_Batch_Operate(AerospikeClient *self, PyObject *args,

return py_results;

ERROR:
error:

if (err.code != AEROSPIKE_OK) {
raise_exception(&err);
Expand Down
4 changes: 2 additions & 2 deletions src/main/client/batch_remove.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,15 +312,15 @@ PyObject *AerospikeClient_Batch_Remove(AerospikeClient *self, PyObject *args,
if (!PyList_Check(py_keys)) {
as_error_update(&err, AEROSPIKE_ERR_PARAM,
"keys should be a list of aerospike key tuples");
goto ERROR;
goto error;
}

py_results = AerospikeClient_Batch_Remove_Invoke(
self, &err, py_keys, py_policy_batch, py_policy_batch_remove);

return py_results;

ERROR:
error:

if (err.code != AEROSPIKE_OK) {
raise_exception(&err);
Expand Down

0 comments on commit 8aa7e68

Please sign in to comment.