diff --git a/azure-pipelines.yml b/azure-pipelines.yml index aa91291..7d98a8e 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,19 +1,57 @@ -# Starter pipeline -# Start with a minimal pipeline that you can customize to build and deploy your code. -# Add steps that build, run tests, deploy, and more: -# https://aka.ms/yaml - trigger: -- master - -pool: - vmImage: 'ubuntu-latest' - -steps: -- script: echo Hello, world! - displayName: 'Run a one-line script' + # start a new build for every push + batch: False + branches: + include: + - master -- script: | - echo Add other tasks to build, test, and deploy your project. - echo See https://aka.ms/yaml - displayName: 'Run a multi-line script' +jobs: +- job: Windows + variables: + PIP_CACHE_FOLDER: $(Pipeline.Workspace)/.cache/pip + pool: + vmIMage: 'VS2017-Win2016' + strategy: + maxParallel: 4 + matrix: + Python37-64bit: + PYTHON_VERSION: '3.7' + PYTHON_ARCH: 'x64' + steps: + - task: UsePythonVersion@0 + inputs: + versionSpec: $(PYTHON_VERSION) + architecture: $(PYTHON_ARCH) + addToPath: true + - task: Cache@2 + inputs: + key: 'pip' + path: $(PIP_CACHE_FOLDER) + displayName: Cache pip packages + - powershell: | + pip install numpy scipy matplotlib nose pillow pytest pytest-cov pytest-faulthandler coverage imageio imageio-ffmpeg codecov pyqt5==5.9 --cache-dir $(PIP_CACHE_FOLDER) + pip install traits traitsui pyface vtk mayavi nibabel --cache-dir $(PIP_CACHE_FOLDER) + displayName: 'Install pip dependencies' + - powershell: | + powershell make/get_fsaverage.ps1 + $env:SUBJECTS_DIR = '$(System.DefaultWorkingDirectory)' + '\subjects' + Write-Host ("##vso[task.setvariable variable=SUBJECTS_DIR]" + $env:SUBJECTS_DIR) + displayName: 'Get fsaverage' + - powershell: | + git clone --depth 1 git://github.com/pyvista/gl-ci-helpers.git + powershell gl-ci-helpers/appveyor/install_opengl.ps1 + displayName: 'Get OpenGL' + - script: python setup.py develop + displayName: 'Install' + - script: pytest surfer --cov=surfer -v + displayName: 'Run tests' + - script: codecov --root %BUILD_REPOSITORY_LOCALPATH% -t %CODECOV_TOKEN% + displayName: 'Codecov' + env: + CODECOV_TOKEN: $(CODECOV_TOKEN) + condition: always() + - task: PublishTestResults@2 + inputs: + testResultsFiles: 'junit-*.xml' + testRunTitle: 'Publish test results for Python $(python.version)' + condition: always() diff --git a/surfer/tests/test_viz.py b/surfer/tests/test_viz.py index 206d1f2..ac96fe2 100644 --- a/surfer/tests/test_viz.py +++ b/surfer/tests/test_viz.py @@ -1,3 +1,4 @@ +import gc import os import os.path as op from os.path import join as pjoin @@ -210,6 +211,17 @@ def test_data(): brain.close() +@requires_fsaverage() +def test_close(): + """Test that close and del actually work.""" + _set_backend() + brain = Brain('fsaverage', 'both', 'inflated') + brain.close() + brain.__del__() + del brain + gc.collect() + + @requires_fsaverage() def test_data_limits(): """Test handling of data limits.""" diff --git a/surfer/viz.py b/surfer/viz.py index df6763b..b6579c9 100644 --- a/surfer/viz.py +++ b/surfer/viz.py @@ -2296,7 +2296,10 @@ def hide_colorbar(self, row=-1, col=-1): def close(self): """Close all figures and cleanup data structure.""" - for ri, ff in enumerate(self._figures): + self._close() + + def _close(self, force_render=True): + for ri, ff in enumerate(getattr(self, '_figures', [])): for ci, f in enumerate(ff): if f is not None: try: @@ -2305,7 +2308,8 @@ def close(self): pass self._figures[ri][ci] = None - _force_render([]) + if force_render: + _force_render([]) # should we tear down other variables? if getattr(self, '_v', None) is not None: @@ -2316,7 +2320,8 @@ def close(self): self._v = None def __del__(self): - self.close() + # Forcing the GUI updates during GC seems to be problematic + self._close(force_render=False) ########################################################################### # SAVING OUTPUT