From b32629cc501bea1392f1f182a08846fe13f79bfe Mon Sep 17 00:00:00 2001 From: Jarrett Johnson Date: Sat, 11 May 2024 10:32:33 -0400 Subject: [PATCH 1/4] Fix GIL for CmdGetCCP4Str --- layer4/Cmd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/layer4/Cmd.cpp b/layer4/Cmd.cpp index 02b4a1e2f..20b9ca263 100644 --- a/layer4/Cmd.cpp +++ b/layer4/Cmd.cpp @@ -693,12 +693,12 @@ static PyObject * CmdGetCCP4Str(PyObject * self, PyObject * args) } else { API_SETUP_PYMOL_GLOBALS; if (G) { - APIEnter(G); + APIEnterBlocked(G); auto v = ObjectMapGetCCP4Str(G, name, state, quiet, format); PyObject * result = v.empty() ? NULL : PyBytes_FromStringAndSize(&v.front(), v.size()); - APIExit(G); + APIExitBlocked(G); return APIAutoNone(result); } } From 41d01b6cccfe9a91e7f0ff78022b1124ace8e664 Mon Sep 17 00:00:00 2001 From: Jarrett Johnson Date: Sat, 11 May 2024 14:18:09 -0400 Subject: [PATCH 2/4] Fix champ mem alloc file buffer overflow --- contrib/champ/os_memory.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/contrib/champ/os_memory.c b/contrib/champ/os_memory.c index cc26984f9..5b38ccfa4 100644 --- a/contrib/champ/os_memory.c +++ b/contrib/champ/os_memory.c @@ -176,7 +176,15 @@ void *OSMemoryMalloc(unsigned int size,const char *file,int line,int type) rec=(DebugRec*)malloc(sizeof(DebugRec)+size); if(!rec) return(NULL); - strcpy(rec->file,file); + + int len = strlen(file); + int max_size = sizeof(rec->file) - 1; + if (len > max_size) { + strcpy(rec->file, file + len - max_size); + } else { + strcpy(rec->file, file); + } + rec->file[max_size - 1] = '\0'; rec->line=line; rec->size=size; rec->type=type; @@ -196,7 +204,15 @@ void *OSMemoryCalloc(unsigned int count,unsigned int size,const char *file,int l rec=(DebugRec*)calloc(1,sizeof(DebugRec)+size); if(!rec) return(NULL); - strcpy(rec->file,file); + + int len = strlen(file); + int max_size = sizeof(rec->file) - 1; + if (len > max_size) { + strcpy(rec->file, file + len - max_size); + } else { + strcpy(rec->file, file); + } + rec->file[max_size - 1] = '\0'; rec->line=line; rec->size=size; rec->type=type; From 51d33232b25e242f945ed30aaf9131a1fd978ac6 Mon Sep 17 00:00:00 2001 From: Jarrett Johnson Date: Sat, 11 May 2024 20:08:09 -0400 Subject: [PATCH 3/4] ok assignment breaks tests on Windows --- layer2/ObjectMolecule.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layer2/ObjectMolecule.cpp b/layer2/ObjectMolecule.cpp index 1479e5ba1..1f6f23bc4 100644 --- a/layer2/ObjectMolecule.cpp +++ b/layer2/ObjectMolecule.cpp @@ -2388,7 +2388,7 @@ static ObjectMolecule *ObjectMoleculeReadTOPStr(PyMOLGlobals * G, ObjectMolecule */ if(ok && isNew) - ok &= ObjectMoleculeConnect(I, cset, false); + ok = ObjectMoleculeConnect(I, cset, false); if(cset->Symmetry && (!I->Symmetry)) { I->Symmetry.reset(new CSymmetry(*cset->Symmetry)); CHECKOK(ok, I->Symmetry); From 33f1735cd16b524b76bccc311f48d82988e46a8c Mon Sep 17 00:00:00 2001 From: Jarrett Johnson Date: Sun, 12 May 2024 12:20:12 -0400 Subject: [PATCH 4/4] Add CI for Windows and Mac --- .github/workflows/build.yml | 90 +++++++++++++++++++++++++++++++++- setup.py | 24 +++++---- testing/tests/api/externing.py | 14 +++++- 3 files changed, 114 insertions(+), 14 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 88e602593..f9953c74f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,12 +3,12 @@ name: CI on: [push, pull_request] jobs: - build: + build-Linux: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4.0.0 - name: Install system dependencies run: > @@ -26,6 +26,7 @@ jobs: python-is-python3 python3-biopython python3-dev + python3-setuptools python3-numpy python3-pil python3-pytest @@ -49,3 +50,88 @@ jobs: - name: Test run: | ./install-prefix/bin/pymol -ckqy testing/testing.py --run all + + build-Windows: + + runs-on: windows-latest + + env: + CONDA_ROOT: ${{github.workspace}}\..\tmp\mambaforge + MAMBAFORGE_EXEC: ${{github.workspace}}\..\tmp\mambaforge.exe + + steps: + - uses: actions/checkout@v4.0.0 + - name: Download miniconda + shell: cmd + run: |- + if not exist %CONDA_ROOT% mkdir %CONDA_ROOT% + curl -L -o %MAMBAFORGE_EXEC% https://github.com/conda-forge/miniforge/releases/download/24.3.0-0/Mambaforge-24.3.0-0-Windows-x86_64.exe + start /wait %MAMBAFORGE_EXEC% /S /D=%CONDA_ROOT% + + - name: Set up Miniconda + shell: cmd + run: |- + CALL %CONDA_ROOT%\\Scripts\\activate.bat + conda install -y -c conda-forge -c schrodinger python cmake libpng freetype pyqt glew libxml2 numpy catch2=2.13.3 glm libnetcdf collada2gltf biopython pillow msgpack-python pytest + + - name: Conda info + shell: cmd + run: |- + CALL %CONDA_ROOT%\\Scripts\\activate.bat + conda info + + - name: Get additional sources + shell: cmd + run: | + git clone --depth 1 https://github.com/rcsb/mmtf-cpp.git + cp -R mmtf-cpp/include/mmtf* %CONDA_ROOT%/Library/include/ + git clone --depth 1 --single-branch --branch cpp_master https://github.com/msgpack/msgpack-c.git + cp -R msgpack-c/include/msgpack* %CONDA_ROOT%/Library/include/ + + - name: Build PyMOL + shell: cmd + run: | + CALL %CONDA_ROOT%\\Scripts\\activate.bat + python setup.py --testing install --prefix=%GITHUB_WORKSPACE%\\install-prefix + + - name: Test + shell: cmd + run: | + CALL %CONDA_ROOT%\\Scripts\\activate.bat + %GITHUB_WORKSPACE%\\install-prefix\\Scripts\\pymol.bat -ckqy testing\\testing.py --run all + + build-MacOS: + + runs-on: macos-latest + + env: + CONDA_ROOT: "/tmp/miniconda" + + steps: + - uses: actions/checkout@v4.0.0 + - name: Set up Miniconda and Build + run: |- + curl -L -o $CONDA_ROOT.sh https://github.com/conda-forge/miniforge/releases/download/24.3.0-0/Mambaforge-MacOSX-x86_64.sh + bash $CONDA_ROOT.sh -b -p $CONDA_ROOT + export PATH="$CONDA_ROOT/bin:$PATH" + conda config --set quiet yes + conda install -y -c conda-forge -c schrodinger python cmake libpng freetype pyqt glew libxml2 numpy catch2=2.13.3 glm libnetcdf collada2gltf biopython pillow msgpack-python pytest + conda info + + - name: Get additional sources + run: | + git clone --depth 1 https://github.com/rcsb/mmtf-cpp.git + cp -R mmtf-cpp/include/mmtf* ${CONDA_ROOT}/include/ + git clone --depth 1 --single-branch --branch cpp_master https://github.com/msgpack/msgpack-c.git + cp -R msgpack-c/include/msgpack* ${CONDA_ROOT}/include/ + + - name: Build PyMOL + run: |- + export MACOSX_DEPLOYMENT_TARGET=12.0 + export PATH="$CONDA_ROOT/bin:$PATH" + python setup.py install --prefix=${GITHUB_WORKSPACE}/install-prefix + + - name: Test + run: |- + export PATH="$CONDA_ROOT/bin:$PATH" + ${GITHUB_WORKSPACE}/install-prefix/bin/pymol -ckqy testing/testing.py --run all diff --git a/setup.py b/setup.py index 5657d49f6..08e9a2e35 100644 --- a/setup.py +++ b/setup.py @@ -114,17 +114,18 @@ def is_conda_env(): def guess_msgpackc(): for prefix in prefix_path: - f = os.path.join(prefix, 'include', 'msgpack', 'version_master.h') + for suffix in ['h', 'hpp']: + f = os.path.join(prefix, 'include', 'msgpack', f'version_master.{suffix}') - try: - m = re.search(r'MSGPACK_VERSION_MAJOR\s+(\d+)', open(f).read()) - except EnvironmentError: - continue + try: + m = re.search(r'MSGPACK_VERSION_MAJOR\s+(\d+)', open(f).read()) + except EnvironmentError: + continue - if m is not None: - major = int(m.group(1)) - if major > 1: - return 'c++11' + if m is not None: + major = int(m.group(1)) + if major > 1: + return 'c++11' return 'no' @@ -422,7 +423,10 @@ def make_launch_script(self): def_macros += [("_PYMOL_NO_MSGPACKC", None)] else: if options.use_msgpackc == 'c++11': - def_macros += [("MMTF_MSGPACK_USE_CPP11", None)] + def_macros += [ + ("MMTF_MSGPACK_USE_CPP11", None), + ("MSGPACK_NO_BOOST", None), + ] else: libs += ['msgpackc'] diff --git a/testing/tests/api/externing.py b/testing/tests/api/externing.py index ac52bce31..b3ccdcb9d 100644 --- a/testing/tests/api/externing.py +++ b/testing/tests/api/externing.py @@ -1,4 +1,5 @@ import os +import sys from pymol import cmd, testing, stored def touch(filename): @@ -9,8 +10,17 @@ class TestExterning(testing.PyMOLTestCase): def testCdLsPwd(self): with testing.mkdtemp() as path: cmd.cd(path) - self.assertEqual(os.getcwd(), - os.path.realpath(path)) + if sys.platform == 'win32': + import ctypes + def get_long_path_name(path): + buf = ctypes.create_unicode_buffer(260) + ctypes.windll.kernel32.GetLongPathNameW(path, buf, len(buf)) + return buf.value + self.assertEqual(get_long_path_name(os.getcwd()), + get_long_path_name(os.path.realpath(path))) + else: + self.assertEqual(os.getcwd(), + os.path.realpath(path)) touch('foo1.txt') touch('foo2.txt')