diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2566d1b1523..0776c98b5ed 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,8 +3,7 @@ name: CI on: push: branches: - - master - - '*_maintenance' + - '*' pull_request: branches: - master @@ -33,6 +32,7 @@ jobs: linux-python2-debug, linux-python3, macos-python2, + windows-python3, ] include: @@ -79,6 +79,14 @@ jobs: testRunner: bash -c sconsCacheMegabytes: 400 + - name: windows-python3 + os: windows-2016 + buildType: RELEASE + variant: windows-python3 + publish: false + containerImage: + dependenciesURL: https://github.com/hypothetical-inc/gafferDependencies/releases/download/4.0.0/gafferDependencies-4.0.0-Python3-windows.zip + runs-on: ${{ matrix.os }} container: ${{ matrix.containerImage }} @@ -93,6 +101,21 @@ jobs: - uses: actions/checkout@v2 + - uses: ilammy/msvc-dev-cmd@v1.10.0 + with: + sdk: 10.0.17763.0 + + - name: Install toolchain (Windows) + run: python -m pip install scons + if: runner.os == 'Windows' + + - name: Install Inkscape (Windows) + run: | + Invoke-WebRequest -Uri "https://inkscape.org/gallery/item/18067/inkscape-0.92.5-x64.exe" -OutFile "inkscape.exe" + Start-Process .\inkscape.exe /S -NoNewWindow -Wait + shell: pwsh + if: runner.os == 'Windows' + - name: Install toolchain (MacOS) # Prefer `pip install` where possible because it is faster # than `brew install`. @@ -131,6 +154,7 @@ jobs: env: GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} GAFFER_BUILD_VARIANT: ${{ matrix.name }} + shell: bash - name: Disable macOS PR Docs run: | @@ -144,8 +168,9 @@ jobs: # below. run: | echo GAFFER_DEPENDENCIES_HASH=`python .github/workflows/main/installDependencies.py --archiveURL ${{ matrix.dependenciesURL }} --dependenciesDir ${{ env.GAFFER_BUILD_DIR }} --outputFormat "{archiveDigest}"` >> $GITHUB_ENV - ./.github/workflows/main/installDelight.sh + ./.github/workflows/main/installDelight.py echo DELIGHT=$GITHUB_WORKSPACE/3delight >> $GITHUB_ENV + shell: bash - name: Cache uses: actions/cache@v1 @@ -168,13 +193,14 @@ jobs: echo "::add-matcher::./.github/workflows/main/problemMatchers/unittest.json" ${{ matrix.testRunner }} "${{ env.GAFFER_BUILD_DIR }}/bin/gaffer test" echo "::remove-matcher owner=unittest::" + if: runner.os == 'macOS' || runner.os == 'Linux' - - name: Build and test Arnold extension + - name: Build and test Arnold extension (MacOS and Linux) run: | for arnoldVersion in 6.2.0.1 7.0.0.0 do # Install Arnold - ./.github/workflows/main/installArnold.sh $arnoldVersion + ./.github/workflows/main/installArnold.py --version $arnoldVersion export ARNOLD_ROOT=$GITHUB_WORKSPACE/arnoldRoot/$arnoldVersion # Build Arnold extension scons -j 2 build BUILD_TYPE=${{ matrix.buildType }} OPTIONS=.github/workflows/main/sconsOptions @@ -186,6 +212,22 @@ jobs: # so we can build the docs for GafferArnold. echo ARNOLD_ROOT=$ARNOLD_ROOT >> $GITHUB_ENV done + if: runner.os == 'macOS' || runner.os == 'Linux' + + - name: Build and test Arnold extension (Windows) + run: | + for %%G in (6.2.0.1 7.0.0.0) do ( + REM Install Arnold + python .github/workflows/main/installArnold.py --version %%G + set ARNOLD_ROOT=%GITHUB_WORKSPACE%\arnoldRoot\%%G + REM Build Arnold extension + scons -j 2 build BUILD_TYPE=${{ matrix.buildType }} OPTIONS=.github/workflows/main/sconsOptions + REM Publish ARNOLD_ROOT to the environment for subsequent steps, + REM so we can build the docs for GafferArnold. + echo ARNOLD_ROOT=%ARNOLD_ROOT% >> %GITHUB_ENV% + ) + shell: cmd + if: runner.os == 'Windows' - name: Build Docs and Package # We currently experience sporadic hangs in the docs builds (mac), this diff --git a/.github/workflows/main/installArnold.py b/.github/workflows/main/installArnold.py new file mode 100755 index 00000000000..7478b934573 --- /dev/null +++ b/.github/workflows/main/installArnold.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright (c) 2021, Hypothetical Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Image Engine Design nor the names of any +# other contributors to this software may be used to endorse or +# promote products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +########################################################################## + +import sys +import argparse +import os +import urllib +import zipfile + +if sys.version_info[0] < 3 : + from urllib import urlretrieve +else: + from urllib.request import urlretrieve + +platform = { "darwin" : "osx", "win32" : "windows" }.get( sys.platform, "linux" ) +format = { "win32" : "zip" }.get( sys.platform, "tar.gz" ) + +parser = argparse.ArgumentParser() + +parser.add_argument( + "--version", + help = "The Arnold version to install." +) + +args = parser.parse_args() + +archive = "Arnold-{version}-{platform}.{format}".format( + version = args.version, + platform = platform, + format = format +) + +url="https://forgithubci.solidangle.com/arnold/{}".format( archive ) + +installDir = os.path.join( "arnoldRoot", args.version ) +os.makedirs( installDir ) +os.chdir( installDir ) + +print( "Downloading Arnold \"{}\"".format( url ) ) +archiveFile, headers = urlretrieve( url ) + +if format == "tar.gz" : + os.system( "tar -xzf {}".format( archiveFile ) ) +elif format == "zip": + with zipfile.ZipFile( archiveFile ) as f : + f.extractall() diff --git a/.github/workflows/main/installDelight.py b/.github/workflows/main/installDelight.py new file mode 100755 index 00000000000..860f9620cc3 --- /dev/null +++ b/.github/workflows/main/installDelight.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright (c) 2021, Hypothetical Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# * Neither the name of Image Engine Design nor the names of any +# other contributors to this software may be used to endorse or +# promote products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +########################################################################## + +import sys +import os +import shutil +import subprocess + +if sys.version_info[0] < 3 : + from urllib import urlretrieve +else : + from urllib.request import urlretrieve + +delightVersion="1.1.12" +delightDirectory="free/beta/2018-11-01-oIDoJTpO" + +baseUrl = "https://3delight-downloads.s3-us-east-2.amazonaws.com" + +if sys.platform.startswith("linux") : # pre Python 3.3 the major version is added at the end + package="3DelightNSI-{}-Linux-x86_64".format( delightVersion ) + + url = "{baseUrl}/{delightDirectory}/{package}.tar.xz".format( + baseUrl = baseUrl, + delightDirectory = delightDirectory, + package = package + ) + + print( "Downloading 3Delight \"{}\"".format( url ) ) + archiveFileName, headers = urlretrieve( url ) + + exitStatus = os.system( "tar -xf {} -C .".format( archiveFileName ) ) + if exitStatus != 0 : + exit( exitStatus ) + + shutil.copytree( "./{}/3delight/Linux-x86_64".format( package ), "./3delight" ) + +elif sys.platform == "darwin" : + package="3DelightNSI-{}-Darwin-Universal".format( delightVersion ) + + url = "{baseUrl}/{delightDirectory}/{package}.dmg".format( + baseUrl = baseUrl, + delightDirectory = delightDirectory, + package = package + ) + + print( "Downloading 3Delight \"{}\"".format( url ) ) + archiveFileName, headers = urlretrieve( url ) + + subprocess.check_call( + [ + "sudo", + "hdiutil", + "mount", + archiveFileName, + ] + ) + subprocess.check_call( + [ + "sudo", + "installer", + "-pkg", + "/Volumes/3Delight NSI " + "{delightVersion}/3DelightNSI-{delightVersion}-Darwin-x86_64.pkg".format( + delightVersion = delightVersion + ), + "-target", + "/", + ] + ) + subprocess.check_call( + [ + "sudo", + "mv", + "/Applications/3Delight", + "./3delight", + ] + ) + + +elif sys.platform == "win32": + package = "3DelightNSI-{}-setup.exe".format( delightVersion ) + + url = "{baseUrl}/{delightDirectory}/{package}".format( + baseUrl = baseUrl, + delightDirectory = delightDirectory, + package = package + ) + + print( "Downloading 3Delight \"{}\"".format( url ) ) + archiveFileName, headers = urlretrieve( url ) + + subprocess.check_call( [ archiveFileName, "/VERYSILENT", "/DIR=3delight" ] ) + + + diff --git a/.github/workflows/main/installDelight.sh b/.github/workflows/main/installDelight.sh deleted file mode 100755 index c74600ed712..00000000000 --- a/.github/workflows/main/installDelight.sh +++ /dev/null @@ -1,19 +0,0 @@ -#! /bin/bash - -set -e - -version=1.1.12 -directory=free/beta/2018-11-01-oIDoJTpO - -if [[ `uname` = "Linux" ]] ; then - package=3DelightNSI-$version-Linux-x86_64 - curl https://3delight-downloads.s3-us-east-2.amazonaws.com/$directory/$package.tar.xz > $package.tar.xz - tar -xf $package.tar.xz - mv ./$package/3delight/Linux-x86_64 ./3delight -else - package=3DelightNSI-$version-Darwin-Universal - curl https://3delight-downloads.s3-us-east-2.amazonaws.com/$directory/$package.dmg > $package.dmg - sudo hdiutil mount $package.dmg - sudo installer -pkg /Volumes/3Delight\ NSI\ $version/3DelightNSI-$version-Darwin-x86_64.pkg -target / - sudo mv /Applications/3Delight ./3delight -fi diff --git a/.github/workflows/main/installDependencies.py b/.github/workflows/main/installDependencies.py index b76ac7b3fb9..096fcdf7825 100755 --- a/.github/workflows/main/installDependencies.py +++ b/.github/workflows/main/installDependencies.py @@ -38,6 +38,9 @@ import sys import argparse import hashlib +import subprocess +import glob +import shutil if sys.version_info[0] < 3 : from urllib import urlretrieve @@ -46,7 +49,7 @@ # Determine default archive URL. -platform = "osx" if sys.platform == "darwin" else "linux" +platform = { "darwin" : "osx", "win32" : "windows" }.get( sys.platform, "linux" ) defaultURL = "https://github.com/GafferHQ/dependencies/releases/download/4.0.0/gafferDependencies-4.0.0-Python2-" + platform + ".tar.gz" # Parse command line arguments. @@ -81,14 +84,28 @@ archiveFileName, headers = urlretrieve( args.archiveURL ) os.makedirs( args.dependenciesDir ) -os.system( "tar xf %s -C %s --strip-components=1" % ( archiveFileName, args.dependenciesDir ) ) +if platform != "windows": + os.system( "tar xf %s -C %s --strip-components=1" % ( archiveFileName, args.dependenciesDir ) ) +else: + subprocess.check_output( "7z x %s -o%s -aoa -y" % ( archiveFileName, args.dependenciesDir ) ) + # 7z (and zip extractors generally) don't have an equivalent of --strip-components=1 + # Copy the files up one directory level to compensate + for p in glob.glob( + os.path.join( + args.dependenciesDir.replace( "/", "\\" ), + os.path.splitext( args.archiveURL.split( "/" )[-1] )[0], + "*" + ) + ): + shutil.move( p, args.dependenciesDir ) + # Tell the world if args.outputFormat : md5 = hashlib.md5() - with open( archiveFileName ) as f : + with open( archiveFileName, mode="rb" ) as f : md5.update( f.read() ) print( diff --git a/.github/workflows/main/sconsOptions b/.github/workflows/main/sconsOptions index 5d4daad8690..eab69b1ba3c 100644 --- a/.github/workflows/main/sconsOptions +++ b/.github/workflows/main/sconsOptions @@ -35,6 +35,11 @@ ########################################################################## import os +import sys +import glob +import subprocess + +platform = {"darwin" : "osx", "win32" : "windows"}.get(sys.platform, "linux") ENV_VARS_TO_IMPORT = "PATH" @@ -46,6 +51,40 @@ DELIGHT_ROOT = os.environ["DELIGHT"] BUILD_DIR = os.environ["GAFFER_BUILD_DIR"] INSTALL_DIR = os.path.join( "install", os.environ["GAFFER_BUILD_NAME"] ) -PACKAGE_FILE = "%s.tar.gz" % os.environ["GAFFER_BUILD_NAME"] +PACKAGE_FILE = "{}.{}".format( + os.environ["GAFFER_BUILD_NAME"], + {"win32" : "zip"}.get( sys.platform, "tar.gz" ) +) SPHINX = os.environ["GAFFER_SPHINX"] + +if sys.platform == "win32" : + + # It would be nice to get this from the command line, but I don't know of any way + # to do that. It will need to be changed when upgrading Visual Studio versions. + toolSetVersion = "141" + + # Get the Boost version from the include directory. + # It is named "boost-_" + boostInclude = glob.glob( os.path.join( os.environ["GAFFER_BUILD_DIR"], "include", "boost-*" ) ) + if len( boostInclude ) > 0 : + boostVersion = os.path.split( boostInclude[0] )[-1].split( '-' )[1] + + # Get the Python version, as in SConstruct but without the '.' separating major from minor version + pythonVersion = subprocess.check_output( + [ "python", "-c", "import sys; print( '{}{}'.format( *sys.version_info[:2] ) )" ], + universal_newlines=True + ).strip() + + BOOST_LIB_SUFFIX = "-vc" + toolSetVersion + "-mt-x64-" + boostVersion + BOOST_PYTHON_LIB_SUFFIX = pythonVersion + "-vc" + toolSetVersion + "-mt-x64-" + boostVersion + LOCATE_DEPENDENCY_SYSTEMPATH = [ + os.path.join( os.environ["GAFFER_BUILD_DIR"], "include", "boost-" + boostVersion ) + ] + + LOCATE_DEPENDENCY_LIBPATH=os.path.join(os.environ["GAFFER_BUILD_DIR"], "lib") + LOCATE_DEPENDENCY_PYTHONPATH=os.path.join(os.environ["GAFFER_BUILD_DIR"], "python") + GLEW_LIB_SUFFIX = "32" + INKSCAPE = "C:\\Program Files\\Inkscape\\inkscape.com" + WARNINGS_AS_ERRORS = False + APPLESEED_ROOT = None diff --git a/.gitignore b/.gitignore index d807cd9eaa7..f43b8b7ab8d 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,13 @@ *.tmp *.desktop *.code-workspace +*.obj +*.pyd +*.pdb +*.dll +*.lib +*.ilk +*.exp .gafferBackups .idea .sconf_temp diff --git a/Changes.md b/Changes.md index 99d93696d9a..4402c3e5690 100644 --- a/Changes.md +++ b/Changes.md @@ -1,3 +1,10 @@ +0.61.1.2 (relative to 0.61.1.1) +======== + +- Browsing UNC paths in a file dialog is now supported. +- Fixed regression where scene paths chosen from a path widget or dialog would leave out the leading slash. +- Showing / hiding hidden files are now supported on Windows. + 0.61.1.1 (relative to 0.61.1.0) ======== diff --git a/SConstruct b/SConstruct index 9f0625601dd..1391d9d2bf6 100644 --- a/SConstruct +++ b/SConstruct @@ -2,6 +2,7 @@ # # Copyright (c) 2011-2014, John Haddon. All rights reserved. # Copyright (c) 2011-2014, Image Engine Design Inc. All rights reserved. +# Copyright 2019, Hypothetical Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -40,9 +41,12 @@ import re import sys import glob import platform +import shutil import subprocess import distutils.dir_util +EnsureSConsVersion( 3, 0, 2 ) # Substfile is a default builder as of 3.0.2 + ############################################################################################### # Version ############################################################################################### @@ -50,7 +54,7 @@ import distutils.dir_util gafferMilestoneVersion = 0 # for announcing major milestones - may contain all of the below gafferMajorVersion = 61 # backwards-incompatible changes gafferMinorVersion = 1 # new backwards-compatible features -gafferPatchVersion = 1 # bug fixes +gafferPatchVersion = 2 # bug fixes # All of the following must be considered when determining # whether or not a change is backwards-compatible @@ -77,13 +81,13 @@ options = Variables( optionsFile, ARGUMENTS ) options.Add( "CXX", "The C++ compiler.", - "clang++" if sys.platform == "darwin" else "g++", + {"darwin" : "clang++", "win32" : "cl"}.get(sys.platform, "g++") ) options.Add( "CXXFLAGS", "The extra flags to pass to the C++ compiler during compilation.", - [ "-pipe", "-Wall" ] + [ "-pipe", "-Wall" ] if Environment()["PLATFORM"] != "win32" else [], ) options.Add( @@ -118,7 +122,7 @@ options.Add( options.Add( "BUILD_DIR", "The destination directory in which the build will be made.", - "./build/gaffer-${GAFFER_MILESTONE_VERSION}.${GAFFER_MAJOR_VERSION}.${GAFFER_MINOR_VERSION}.${GAFFER_PATCH_VERSION}-${GAFFER_PLATFORM}", + os.path.join( "build", "gaffer-${GAFFER_MILESTONE_VERSION}.${GAFFER_MAJOR_VERSION}.${GAFFER_MINOR_VERSION}.${GAFFER_PATCH_VERSION}-${GAFFER_PLATFORM}" ), ) options.Add( @@ -132,13 +136,13 @@ options.Add( options.Add( "INSTALL_DIR", "The destination directory for the installation.", - "./install/gaffer-${GAFFER_MILESTONE_VERSION}.${GAFFER_MAJOR_VERSION}.${GAFFER_MINOR_VERSION}.${GAFFER_PATCH_VERSION}-${GAFFER_PLATFORM}", + os.path.join( "install", "gaffer-${GAFFER_MILESTONE_VERSION}.${GAFFER_MAJOR_VERSION}.${GAFFER_MINOR_VERSION}.${GAFFER_PATCH_VERSION}-${GAFFER_PLATFORM}" ), ) options.Add( "PACKAGE_FILE", "The file in which the final gaffer file will be created by the package target.", - "${INSTALL_DIR}.tar.gz", + "${INSTALL_DIR}.tar.gz" if sys.platform != "win32" else "${INSTALL_DIR}.zip", ) options.Add( @@ -167,7 +171,7 @@ options.Add( options.Add( "APPLESEED_ROOT", "The directory in which Appleseed is installed. Used to build Gafferseed", - "$BUILD_DIR/appleseed", + os.path.join( "$BUILD_DIR", "appleseed" ), ) options.Add( @@ -328,6 +332,10 @@ options.Add( "GAFFER_PATCH_VERSION", "Patch version", str( gafferPatchVersion ) # Basic environment object. All the other environments will be based on this. ############################################################################################### +########################################################################################### +# All platforms +########################################################################################### + env = Environment( options = options, @@ -360,10 +368,14 @@ env = Environment( ) + # include 3rd party headers with -isystem rather than -I. # this should turn off warnings from those headers, allowing us to # build with -Werror. there are so many warnings from boost # in particular that this would be otherwise impossible. + +systemIncludeArgument = "/external:I" if env[ "PLATFORM" ] == "win32" else "-isystem" + for path in [ "$BUILD_DIR/include", "$BUILD_DIR/include/OpenEXR", @@ -371,7 +383,7 @@ for path in [ ] + env["LOCATE_DEPENDENCY_SYSTEMPATH"] : env.Append( - CXXFLAGS = [ "-isystem", path ] + CXXFLAGS = [ systemIncludeArgument, path ] ) if "clang++" in os.path.basename( env["CXX"] ): @@ -381,75 +393,179 @@ if "clang++" in os.path.basename( env["CXX"] ): env["BUILD_DIR"] = os.path.abspath( env["BUILD_DIR"] ) -# DISPLAY and HOME are essential for running gaffer when generating -# the documentation. TERM is needed to get coloured output from the -# compiler. -for e in env["ENV_VARS_TO_IMPORT"].split() + [ "DISPLAY", "HOME", "TERM" ] : +for e in env["ENV_VARS_TO_IMPORT"].split() : if e in os.environ : env["ENV"][e] = os.environ[e] -if env["PLATFORM"] == "darwin" : +########################################################################################### +# POSIX configuration +########################################################################################### - env.Append( CXXFLAGS = [ "-D__USE_ISOC99" ] ) - env["GAFFER_PLATFORM"] = "osx" +if env["PLATFORM"] != "win32" : - osxVersion = [ int( v ) for v in platform.mac_ver()[0].split( "." ) ] - if osxVersion[0] == 10 and osxVersion[1] > 7 : - # Fix problems with Boost 1.55 and recent versions of Clang. - env.Append( CXXFLAGS = [ "-DBOOST_HAS_INT128", "-Wno-unused-local-typedef" ] ) + # DISPLAY and HOME are essential for running gaffer when generating + # the documentation. TERM is needed to get coloured output from the + # compiler. + for e in [ "DISPLAY", "HOME", "TERM" ] : + if e in os.environ : + env["ENV"][e] = os.environ[e] -elif env["PLATFORM"] == "posix" : + if env["PLATFORM"] == "darwin" : + + env.Append( CXXFLAGS = [ "-D__USE_ISOC99" ] ) + env["GAFFER_PLATFORM"] = "osx" + + osxVersion = [ int( v ) for v in platform.mac_ver()[0].split( "." ) ] + if osxVersion[0] == 10 and osxVersion[1] > 7 : + # Fix problems with Boost 1.55 and recent versions of Clang. + env.Append( CXXFLAGS = [ "-DBOOST_HAS_INT128", "-Wno-unused-local-typedef" ] ) + + else : - if "g++" in os.path.basename( env["CXX"] ) : + if "g++" in os.path.basename( env["CXX"] ) : - # Get GCC version. - gccVersion = subprocess.check_output( [ env["CXX"], "-dumpversion" ], env=env["ENV"] ).decode().strip() - if "." not in gccVersion : - # GCC 7 onwards requires `-dumpfullversion` to get minor/patch, but this - # flag does not exist on earlier GCCs, where minor/patch was provided by `-dumpversion`. - gccVersion = subprocess.check_output( [ env["CXX"], "-dumpfullversion" ], env=env["ENV"] ).decode().strip() - gccVersion = [ int( v ) for v in gccVersion.split( "." ) ] + # Get GCC version. + gccVersion = subprocess.check_output( [ env["CXX"], "-dumpversion" ], env=env["ENV"], universal_newlines=True ).strip() + if "." not in gccVersion : + # GCC 7 onwards requires `-dumpfullversion` to get minor/patch, but this + # flag does not exist on earlier GCCs, where minor/patch was provided by `-dumpversion`. + gccVersion = subprocess.check_output( [ env["CXX"], "-dumpfullversion" ], env=env["ENV"], universal_newlines=True ).strip() + gccVersion = [ int( v ) for v in gccVersion.split( "." ) ] - # GCC 4.1.2 in conjunction with boost::flat_map produces crashes when - # using the -fstrict-aliasing optimisation (which defaults to on with -O2), - # so we turn the optimisation off here, only for that specific GCC version. - if gccVersion == [ 4, 1, 2 ] : - env.Append( CXXFLAGS = [ "-fno-strict-aliasing" ] ) + # GCC 4.1.2 in conjunction with boost::flat_map produces crashes when + # using the -fstrict-aliasing optimisation (which defaults to on with -O2), + # so we turn the optimisation off here, only for that specific GCC version. + if gccVersion == [ 4, 1, 2 ] : + env.Append( CXXFLAGS = [ "-fno-strict-aliasing" ] ) - # GCC emits spurious "assuming signed overflow does not occur" - # warnings, typically triggered by the comparisons in Box3f::isEmpty(). - # Downgrade these back to warning status. - if gccVersion >= [ 4, 2 ] : - env.Append( CXXFLAGS = [ "-Wno-error=strict-overflow" ] ) + # GCC emits spurious "assuming signed overflow does not occur" + # warnings, typically triggered by the comparisons in Box3f::isEmpty(). + # Downgrade these back to warning status. + if gccVersion >= [ 4, 2 ] : + env.Append( CXXFLAGS = [ "-Wno-error=strict-overflow" ] ) - # Old GCC emits spurious "maybe uninitialized" warnings when using - # boost::optional - if gccVersion < [ 5, 1 ] : - env.Append( CXXFLAGS = [ "-Wno-error=maybe-uninitialized" ] ) + # Old GCC emits spurious "maybe uninitialized" warnings when using + # boost::optional + if gccVersion < [ 5, 1 ] : + env.Append( CXXFLAGS = [ "-Wno-error=maybe-uninitialized" ] ) - if gccVersion >= [ 5, 1 ] : - env.Append( CXXFLAGS = [ "-D_GLIBCXX_USE_CXX11_ABI=0" ] ) + if gccVersion >= [ 5, 1 ] : + env.Append( CXXFLAGS = [ "-D_GLIBCXX_USE_CXX11_ABI=0" ] ) - if gccVersion >= [ 9, 2 ] : - env.Append( CXXFLAGS = [ "-Wsuggest-override" ] ) + if gccVersion >= [ 9, 2 ] : + env.Append( CXXFLAGS = [ "-Wsuggest-override" ] ) - env["GAFFER_PLATFORM"] = "linux" + env["GAFFER_PLATFORM"] = "linux" -env.Append( CXXFLAGS = [ "-std=$CXXSTD", "-fvisibility=hidden" ] ) + env.Append( CXXFLAGS = [ "-std=$CXXSTD", "-fvisibility=hidden" ] ) -if env["BUILD_TYPE"] == "DEBUG" : - env.Append( CXXFLAGS = ["-g", "-O0", "-DTBB_USE_DEBUG=1"] ) -elif env["BUILD_TYPE"] == "RELEASE" : - env.Append( CXXFLAGS = ["-DNDEBUG", "-DBOOST_DISABLE_ASSERTS", "-O3"] ) -elif env["BUILD_TYPE"] == "RELWITHDEBINFO" : - env.Append( CXXFLAGS = ["-DNDEBUG", "-DBOOST_DISABLE_ASSERTS", "-O3", "-g", "-fno-omit-frame-pointer"] ) + if env["BUILD_TYPE"] == "DEBUG" : + env.Append( CXXFLAGS = ["-g", "-O0", "-DTBB_USE_DEBUG=1"] ) + elif env["BUILD_TYPE"] == "RELEASE" : + env.Append( CXXFLAGS = ["-DNDEBUG", "-DBOOST_DISABLE_ASSERTS", "-O3"] ) + elif env["BUILD_TYPE"] == "RELWITHDEBINFO" : + env.Append( CXXFLAGS = ["-DNDEBUG", "-DBOOST_DISABLE_ASSERTS", "-O3", "-g", "-fno-omit-frame-pointer"] ) -if env["WARNINGS_AS_ERRORS"] : + if env["WARNINGS_AS_ERRORS"] : + env.Append( + CXXFLAGS = [ "-Werror" ], + SHLINKFLAGS = [ "-Wl,-fatal_warnings" ], + ) + +########################################################################################### +# Windows configuration +########################################################################################### + +else: env.Append( - CXXFLAGS = [ "-Werror" ], - SHLINKFLAGS = [ "-Wl,-fatal_warnings" ], + CXXFLAGS = [ + "/nologo", # Suppress startup banner + "/DOPENEXR_DLL", # Link to dynamic OpenEXR library + "/DNOMINMAX", # Suppress compiler definition of `min` and `max` + "/D__PRETTY_FUNCTION__=__FUNCSIG__", + "/DBOOST_ALL_DYN_LINK", + "/DBOOST_FILESYSTEM_NO_DEPRECATED", + "/DBOOST_SIGNALS_NO_DEPRECATION_WARNING", + "/DBOOST_PYTHON_MAX_ARITY=20", + "/W4", # Warning level 4, one level less than all warnings + "/experimental:external", # Allow use of /external:I + "/external:W0", # Suppress warnings for headers included with /external:I + "/Zc:inline", # Remove unreferenced function or data if it is COMDAT or has internal linkage only + "/GR", # Enable RTTI + "/TP", # Treat all files as c++ (vs C) + "/FC", # Display full paths in diagnostics + "/EHsc", # Catch c++ exceptions only + "/MP", # Enable multiprocessing of builds + "/permissive-", # Disable permissive mode, which also enables standard compliant two phase name lookup + "/D_USE_MATH_DEFINES", # Required when permissive mode is off, for defining constants like M_PI used by OpenVDB + "/std:$CXXSTD", + ] ) + if env["WARNINGS_AS_ERRORS"] : + env.Append( + CXXFLAGS = [ + "/WX", # Treat warnings as errors + "/wd4100", # Suppress warning about unused parameters + "/wd4706", # Suppress warning about using assignment in conditionals + "/wd4267", # Suppress warning about conversion from int to size_t + "/wd4244", # Suppress warning about possible loss of data in type conversion + "/wd4305", # Suppress warning about conversion from double to float + "/D_CRT_SECURE_NO_WARNINGS", # Suppress warnings about getenv and similar + ], + ) + + if env["BUILD_TYPE"] == "DEBUG" : + env.Append( + CXXFLAGS = + [ + "/O0", + "/Zi", + "/MDd", + "/DBOOST_DISABLE_ASSERTS", + "/bigobj", + ], + CCPDBFLAGS= + [ + "/Zi", + "/Fd${TARGET}.pdb", + ], + ) + elif env["BUILD_TYPE"] == "RELEASE" : + env.Append( + CXXFLAGS = + [ + "/DNDEBUG", + "/MD", # create multithreaded DLL + "/DBOOST_DISABLE_ASSERTS", + "/O2", + # /Og optimization (included via /O2) generates lots of unreachable + # code warnings from boost::intrusive_ptr. Disabled in release build only. + "/wd4702" + ] + ) + elif env["BUILD_TYPE"] == "RELWITHDEBINFO" : + env.Append( + CXXFLAGS = + [ + "/DNDEBUG", + "/MD", + "/bigobj", + "/DBOOST_DISABLE_ASSERTS", + "/Zi", + ], + LINKFLAGS = + [ + "/DEBUG", + ], + CCPDBFLAGS= + [ + "/Zi", + "/Fd${TARGET}.pdb", + ], + ) + + if env["BUILD_CACHEDIR"] != "" : CacheDir( env["BUILD_CACHEDIR"] ) @@ -545,7 +661,7 @@ if env["ASAN"] : # An environment for running commands with access to the applications we've built ############################################################################################### -def split( stringOrList, separator = ":" ) : +def split( stringOrList, separator = os.path.pathsep ) : if isinstance( stringOrList, list ) : return stringOrList @@ -553,14 +669,18 @@ def split( stringOrList, separator = ":" ) : return stringOrList.split( separator ) commandEnv = env.Clone() -commandEnv["ENV"]["PATH"] = commandEnv.subst( "$BUILD_DIR/bin:" ) + commandEnv["ENV"]["PATH"] +commandEnv["ENV"]["PATH"] = commandEnv.subst( "$BUILD_DIR/bin" + os.path.pathsep ) + commandEnv["ENV"]["PATH"] +if env["PLATFORM"] == "win32" : + commandEnv["ENV"]["PATH"] = commandEnv.subst( "$BUILD_DIR/lib" + os.path.pathsep ) + commandEnv["ENV"]["PATH"] if commandEnv["PLATFORM"]=="darwin" : - commandEnv["ENV"]["DYLD_LIBRARY_PATH"] = commandEnv.subst( ":".join( [ "$BUILD_DIR/lib" ] + split( commandEnv["LOCATE_DEPENDENCY_LIBPATH"] ) ) ) -else : - commandEnv["ENV"]["LD_LIBRARY_PATH"] = commandEnv.subst( ":".join( [ "$BUILD_DIR/lib" ] + split( commandEnv["LOCATE_DEPENDENCY_LIBPATH"] ) ) ) + commandEnv["ENV"]["DYLD_LIBRARY_PATH"] = commandEnv.subst( os.path.pathsep.join( [ "$BUILD_DIR/lib" ] + split( commandEnv["LOCATE_DEPENDENCY_LIBPATH"] ) ) ) +elif commandEnv["PLATFORM"] == "win32" : + commandEnv["ENV"]["PATH"] = commandEnv.subst( os.path.pathsep.join( [ "$BUILD_DIR/lib" ] + split( commandEnv[ "LOCATE_DEPENDENCY_LIBPATH" ] ) + [ commandEnv["ENV"]["PATH"] ] ) ) +else: + commandEnv["ENV"]["LD_LIBRARY_PATH"] = commandEnv.subst( os.path.pathsep.join( [ "$BUILD_DIR/lib" ] + split( commandEnv["LOCATE_DEPENDENCY_LIBPATH"] ) ) ) -commandEnv["ENV"]["PYTHONPATH"] = commandEnv.subst( ":".join( split( commandEnv["LOCATE_DEPENDENCY_PYTHONPATH"] ) ) ) +commandEnv["ENV"]["PYTHONPATH"] = commandEnv.subst( os.path.pathsep.join( split( commandEnv["LOCATE_DEPENDENCY_PYTHONPATH"] ) ) ) # SIP on MacOS prevents DYLD_LIBRARY_PATH being passed down so we make sure # we also pass through to gaffer the other base vars it uses to populate paths @@ -572,7 +692,7 @@ def runCommand( command ) : command = commandEnv.subst( command ) sys.stderr.write( command + "\n" ) - subprocess.check_call( command, shell=True, env=commandEnv["ENV"] ) + return subprocess.check_output( command, shell=True, env=commandEnv["ENV"], universal_newlines=True ) ############################################################################################### # The basic environment for building libraries @@ -678,6 +798,10 @@ else : CPPPATH = [ "$BUILD_DIR/include/python$PYTHON_ABI_VERSION" ] ) + if basePythonEnv["PLATFORM"] == "win32" : + + basePythonEnv.Append( LIBPATH = "$BUILD_DIR/libs" ) + ############################################################################################### # Arnold configuration ############################################################################################### @@ -705,25 +829,9 @@ if env["ARNOLD_ROOT"] : # Definitions for the libraries we wish to build ############################################################################################### -vTuneRoot = env.subst("$VTUNE_ROOT") - -gafferLib = {} - -if os.path.exists( vTuneRoot ): - gafferLib = { - "envAppends" : { - "CXXFLAGS" : [ "-isystem", "$VTUNE_ROOT/include", "-DGAFFER_VTUNE"], - "LIBPATH" : [ "$VTUNE_ROOT/lib64" ], - "LIBS" : [ "ittnotify" ] - }, - "pythonEnvAppends" : { - "CXXFLAGS" : [ "-DGAFFER_VTUNE"] - } - } - libraries = { - "Gaffer" : gafferLib, + "Gaffer" : {}, "GafferTest" : { "envAppends" : { @@ -865,7 +973,7 @@ libraries = { "IECoreArnold" : { "envAppends" : { - "LIBPATH" : [ "$ARNOLD_ROOT/bin" ], + "LIBPATH" : [ "$ARNOLD_ROOT/bin", "$ARNOLD_ROOT/lib" ], ## \todo Remove GafferScene. We need it at present to get access to `IECoreScenePreview::Renderer`, # but IECoreArnold must never depend on Gaffer code; logically it is in the layer below Gaffer. "LIBS" : [ "GafferScene", "ai", "IECoreScene$CORTEX_LIB_SUFFIX", "IECoreVDB$CORTEX_LIB_SUFFIX", "openvdb$VDB_LIB_SUFFIX" ], @@ -873,7 +981,7 @@ libraries = { "CPPPATH" : [ "$ARNOLD_ROOT/include" ], }, "pythonEnvAppends" : { - "LIBPATH" : [ "$ARNOLD_ROOT/bin" ], + "LIBPATH" : [ "$ARNOLD_ROOT/bin", "$ARNOLD_ROOT/lib" ], "LIBS" : [ "IECoreScene$CORTEX_LIB_SUFFIX", "IECoreArnold" ], "CXXFLAGS" : [ "-DAI_ENABLE_DEPRECATION_WARNINGS" ], "CPPPATH" : [ "$ARNOLD_ROOT/include" ], @@ -883,20 +991,20 @@ libraries = { }, "IECoreArnoldTest" : { - "additionalFiles" : [ "python/IECoreArnoldTest/metadata", "python/IECoreArnoldTest/assFiles" ], + "additionalFiles" : glob.glob( "python/IECoreArnoldTest/metadata/*" ) + glob.glob( "python/IECoreArnoldTest/assFiles/*" ), "requiredOptions" : [ "ARNOLD_ROOT" ], "installRoot" : arnoldInstallRoot, }, "GafferArnold" : { "envAppends" : { - "LIBPATH" : [ "$ARNOLD_ROOT/bin" ], + "LIBPATH" : [ "$ARNOLD_ROOT/bin", "$ARNOLD_ROOT/lib" ], "LIBS" : [ "Gaffer", "GafferScene", "GafferDispatch", "ai", "GafferVDB", "openvdb$VDB_LIB_SUFFIX", "IECoreScene$CORTEX_LIB_SUFFIX", "IECoreVDB$CORTEX_LIB_SUFFIX", "IECoreArnold", "GafferOSL" ], "CXXFLAGS" : [ "-DAI_ENABLE_DEPRECATION_WARNINGS" ], "CPPPATH" : [ "$ARNOLD_ROOT/include" ], }, "pythonEnvAppends" : { - "LIBPATH" : [ "$ARNOLD_ROOT/bin" ], + "LIBPATH" : [ "$ARNOLD_ROOT/bin", "$ARNOLD_ROOT/lib" ], "LIBS" : [ "Gaffer", "GafferScene", "GafferBindings", "GafferVDB", "GafferDispatch", "GafferArnold", "GafferOSL", "IECoreScene$CORTEX_LIB_SUFFIX", "IECoreArnold" ], "CXXFLAGS" : [ "-DAI_ENABLE_DEPRECATION_WARNINGS" ], "CPPPATH" : [ "$ARNOLD_ROOT/include" ], @@ -914,7 +1022,7 @@ libraries = { "GafferArnoldUI" : { "envAppends" : { - "LIBPATH" : [ "$ARNOLD_ROOT/bin" ], + "LIBPATH" : [ "$ARNOLD_ROOT/bin", "$ARNOLD_ROOT/lib" ], "LIBS" : [ "IECoreScene$CORTEX_LIB_SUFFIX", "IECoreGL$CORTEX_LIB_SUFFIX", "OpenImageIO$OIIO_LIB_SUFFIX", "oslquery$OSL_LIB_SUFFIX", "Gaffer", "GafferScene", "GafferOSL", "GafferSceneUI", "ai" ], "CXXFLAGS" : [ "-DAI_ENABLE_DEPRECATION_WARNINGS" ], "CPPPATH" : [ "$ARNOLD_ROOT/include" ], @@ -934,7 +1042,7 @@ libraries = { "GafferArnoldPlugin" : { "envAppends" : { - "LIBPATH" : [ "$ARNOLD_ROOT/bin" ], + "LIBPATH" : [ "$ARNOLD_ROOT/bin", "$ARNOLD_ROOT/lib" ], "LIBS" : [ "IECoreArnold", "ai", "IECoreImage$CORTEX_LIB_SUFFIX" ], "CXXFLAGS" : [ "-DAI_ENABLE_DEPRECATION_WARNINGS" ], "CPPPATH" : [ "$ARNOLD_ROOT/include" ], @@ -996,12 +1104,12 @@ libraries = { "GafferAppleseed" : { "envAppends" : { - "CXXFLAGS" : [ "-isystem", "$APPLESEED_ROOT/include", "-DAPPLESEED_ENABLE_IMATH_INTEROP", "-DAPPLESEED_USE_SSE" ], + "CXXFLAGS" : [ systemIncludeArgument, "$APPLESEED_ROOT/include", "-DAPPLESEED_ENABLE_IMATH_INTEROP", "-DAPPLESEED_USE_SSE" ], "LIBPATH" : [ "$APPLESEED_ROOT/lib" ], "LIBS" : [ "Gaffer", "GafferDispatch", "GafferScene", "appleseed", "IECoreScene$CORTEX_LIB_SUFFIX", "IECoreAppleseed$CORTEX_LIB_SUFFIX", "OpenImageIO$OIIO_LIB_SUFFIX", "oslquery$OSL_LIB_SUFFIX" ], }, "pythonEnvAppends" : { - "CXXFLAGS" : [ "-isystem", "$APPLESEED_ROOT/include", "-DAPPLESEED_ENABLE_IMATH_INTEROP", "-DAPPLESEED_USE_SSE" ], + "CXXFLAGS" : [ systemIncludeArgument, "$APPLESEED_ROOT/include", "-DAPPLESEED_ENABLE_IMATH_INTEROP", "-DAPPLESEED_USE_SSE" ], "LIBPATH" : [ "$APPLESEED_ROOT/lib" ], "LIBS" : [ "Gaffer", "GafferDispatch", "GafferScene", "GafferBindings", "GafferAppleseed" ], }, @@ -1086,10 +1194,16 @@ libraries = { } +if env["PLATFORM"] == "win32" : + libraries["scripts"]["additionalFiles"].append( "bin/gaffer.bat" ) + + # Add on OpenGL libraries to definitions - these vary from platform to platform for library in ( "GafferUI", "GafferScene", "GafferSceneUI", "GafferImageUI" ) : if env["PLATFORM"] == "darwin" : libraries[library]["envAppends"].setdefault( "FRAMEWORKS", [] ).append( "OpenGL" ) + elif env["PLATFORM"] == "win32" : + libraries[library]["envAppends"]["LIBS"].append( "opengl32" ) else : libraries[library]["envAppends"]["LIBS"].append( "GL" ) libraries[library]["envAppends"]["LIBS"].append( "GLEW$GLEW_LIB_SUFFIX" ) @@ -1116,6 +1230,90 @@ for library in ( "GafferUI", ) : if int( env["QT_VERSION"] ) > 4 : addQtLibrary( library, "Widgets" ) +# Add required libraries for Windows + +if env["PLATFORM"] == "win32" : + + for library in ( "Gaffer", ) : + + libraries[library].setdefault( "envAppends", {} ) + libraries[library]["envAppends"].setdefault( "LIBS", [] ).extend( [ "Advapi32" ] ) + +# Optionally add vTune requirements + +if os.path.exists( env.subst("$VTUNE_ROOT") ): + + for library in ( "Gaffer", ) : + + libraries[library].setdefault( "envAppends", {} ) + libraries[library]["envAppends"].setdefault( "CXXFLAGS", [] ).extend( + [ systemIncludeArgument, "$VTUNE_ROOT/include", "-DGAFFER_VTUNE" ] + ) + libraries[library]["envAppends"].setdefault( "LIBPATH", [] ).extend( [ "$VTUNE_ROOT/lib64" ] ) + libraries[library]["envAppends"].setdefault( "LIBS", [] ).extend( [ "ittnotify" ] ) + + + libraries[library].setdefault( "pythonEnvAppends", {} ) + libraries[library]["pythonEnvAppends"].setdefault( "CXXFLAGS", [] ).extend( [ "-DGAFFER_VTUNE" ] ) + +######################################################################################################### +# Repair Symlinks on Windows +######################################################################################################### + +# Windows does not support symlinks except with special (non-default) privileges. +# When cloning the repository git will create symlink source files as a text +# file with the symlink target as its content. 'fileOrigin' is a dictionary of the form +# fileSource: fileTarget used by installers to check for overriding the file's origin. + +if env["PLATFORM"] == "win32" : + + def customInstaller( dest, source, env ) : + + if os.path.isdir( source ) or os.path.isdir( dest ) : + raise RuntimeError( "Cannot copy {} to {}. Source and destination cannot be directories.".format( source, dest ) ) + + fileInfo = runCommand( "git ls-files -s {}".format( source ) ).split() + + if len( fileInfo ) == 4 or len( fileInfo ) == 5: + + # ls-files output format: [ ] + # The magic code for symlinks in git is file mode 120000 + + fileMode = fileInfo[1] if len( fileInfo ) == 5 else fileInfo[0] + filePath = fileInfo[4] if len( fileInfo ) == 5 else fileInfo[3] + filePath = filePath.replace( "/", "\\" ) # filePath comes in from git with / + + if fileMode == "120000" and os.path.exists( filePath ): + + with open( filePath, "r" ) as f : + + sourceFile = f.readline().replace( "/", "\\" ) + + linkSource = os.path.abspath( + os.path.join( + os.getcwd(), + os.path.dirname(filePath ), + sourceFile + ) + ) + + # If running with priveleges that allow symlinks, the file content will + # already be correct (`linkSource` will likely be the first line of + # the license). Don't copy those files by checking if the linked file exists. + if os.path.isfile( linkSource ) : + source = os.path.abspath( os.path.join( os.path.dirname( linkSource ), sourceFile ) ) + + # Make the source relative to the current directory as SCons expects + source = source.replace( os.getcwd(), "" ).lstrip( os.path.sep ) + + shutil.copy2( source, dest ) + + return + + shutil.copy2( source, dest ) + + env["INSTALL"] = customInstaller + ############################################################################################### # The stuff that actually builds the libraries and python modules ############################################################################################### @@ -1158,10 +1356,12 @@ for libraryName, libraryDef in libraries.items() : # header install - sedSubstitutions = "s/!GAFFER_MILESTONE_VERSION!/$GAFFER_MILESTONE_VERSION/g" - sedSubstitutions += "; s/!GAFFER_MAJOR_VERSION!/$GAFFER_MAJOR_VERSION/g" - sedSubstitutions += "; s/!GAFFER_MINOR_VERSION!/$GAFFER_MINOR_VERSION/g" - sedSubstitutions += "; s/!GAFFER_PATCH_VERSION!/$GAFFER_PATCH_VERSION/g" + fileSubstitutions = { + "!GAFFER_MILESTONE_VERSION!" : "$GAFFER_MILESTONE_VERSION", + "!GAFFER_MAJOR_VERSION!" : "$GAFFER_MAJOR_VERSION", + "!GAFFER_MINOR_VERSION!" : "$GAFFER_MINOR_VERSION", + "!GAFFER_PATCH_VERSION!" : "$GAFFER_PATCH_VERSION", + } headers = ( glob.glob( "include/" + libraryName + "/*.h" ) + @@ -1171,7 +1371,12 @@ for libraryName, libraryDef in libraries.items() : ) for header in headers : - headerInstall = env.Command( os.path.join( installRoot, header ), header, "sed \"" + sedSubstitutions + "\" $SOURCE > $TARGET" ) + headerInstall = env.Substfile( + os.path.join( installRoot, header ), + header, + SUBST_DICT = fileSubstitutions + ) + libEnv.Alias( "build", headerInstall ) # bindings library @@ -1180,7 +1385,7 @@ for libraryName, libraryDef in libraries.items() : pythonEnv.Append( **(libraryDef.get( "pythonEnvAppends", {} )) ) bindingsEnv = pythonEnv.Clone() - bindingsEnv.Append( CXXFLAGS = "-D{0}BINDINGS_EXPORTS".format( libraryName ) ) + bindingsEnv.Append( CXXFLAGS = "-D{0}Bindings_EXPORTS".format( libraryName ) ) bindingsSource = sorted( glob.glob( "src/" + libraryName + "Bindings/*.cpp" ) ) if bindingsSource : @@ -1199,7 +1404,11 @@ for libraryName, libraryDef in libraries.items() : ) for header in bindingsHeaders : - headerInstall = env.Command( os.path.join( installRoot, header ), header, "sed \"" + sedSubstitutions + "\" $SOURCE > $TARGET" ) + headerInstall = env.Substfile( + os.path.join( installRoot, header ), + header, + SUBST_DICT = fileSubstitutions + ) bindingsEnv.Alias( "build", headerInstall ) # python module binary component @@ -1224,6 +1433,8 @@ for libraryName, libraryDef in libraries.items() : # LIBSUFFIXES variable used by the library scanner. pythonModuleEnv["LIBSUFFIXES"].append( pythonModuleEnv.subst( "$SHLIBSUFFIX" ) ) pythonModuleEnv["SHLIBSUFFIX"] = ".so" + elif pythonModuleEnv["PLATFORM"] == "win32" : + pythonModuleEnv["SHLIBSUFFIX"] = ".pyd" pythonModule = pythonModuleEnv.SharedLibrary( "python/" + libraryName + "/_" + libraryName, pythonModuleSource ) pythonModuleEnv.Default( pythonModule ) @@ -1246,7 +1457,11 @@ for libraryName, libraryDef in libraries.items() : pythonFiles = glob.glob( "python/" + libraryName + "/*.py" ) + glob.glob( "python/" + libraryName + "/*/*.py" ) + glob.glob( "python/" + libraryName + "/*/*/*.py" ) for pythonFile in pythonFiles : - pythonFileInstall = env.Command( os.path.join( installRoot, pythonFile ), pythonFile, "sed \"" + sedSubstitutions + "\" $SOURCE > $TARGET" ) + pythonFileInstall = env.Substfile( + os.path.join( installRoot, pythonFile ), + pythonFile, + SUBST_DICT = fileSubstitutions + ) env.Alias( "build", pythonFileInstall ) # apps @@ -1279,9 +1494,16 @@ for libraryName, libraryDef in libraries.items() : # osl shaders - def buildOSL( target, source, env ) : - - subprocess.check_call( [ "oslc", "-I./shaders", "-o", str( target[0] ), str( source[0] ) ], env = env["ENV"] ) + def buildOSL( target, source, env ) : + subprocess.check_call( + [ + shutil.which( "oslc", path = env["ENV"]["PATH"] ), + "-I./shaders", + "-o", + str( target[0] ), str( source[0] ) + ], + env = env["ENV"] + ) for oslShader in libraryDef.get( "oslShaders", [] ) : env.Alias( "build", oslShader ) @@ -1330,19 +1552,15 @@ def buildImageCommand( source, target, env ) : if not os.path.isdir( outputDirectory ) : os.makedirs( outputDirectory ) - args = " ".join( [ - "--export-png={filePath}", - "--export-id={id}", - "--export-width={width:d}", - "--export-height={height:d}", + args = [ + "--export-png={}".format( os.path.abspath( filename ) ), + "--export-id={}".format( substitutions["id"] ), + "--export-width={:d}".format( substitutions["width"] ), + "--export-height={:d}".format( substitutions["height"] ), "--export-background-opacity=0", - "{svgPath}" - ] ).format( - filePath = os.path.abspath( filename ), - svgPath = os.path.abspath( svgFilename ), - **substitutions - ) - subprocess.check_call( env["INKSCAPE"] + " " + args, shell = True ) + os.path.abspath( svgFilename ) + ] + subprocess.check_call( [ env["INKSCAPE"] ] + args, shell = True ) def validateAndFlattenImageOptions( imageOptions, svg ) : @@ -1392,8 +1610,7 @@ def svgQuery( svgFile, id_ ) : objects = {} - queryCommand = env["INKSCAPE"] + " --query-all \"" + filepath + "\"" - output = subprocess.check_output( queryCommand, shell=True ).decode() + output = subprocess.check_output( [ env["INKSCAPE"], "--query-all", filepath ], shell=True, universal_newlines=True ) for line in output.split( "\n" ) : tokens = line.split( "," ) # ,,,, @@ -1714,6 +1931,8 @@ def packager( target, source, env ) : if target.endswith( ".dmg" ) : runCommand( "hdiutil create -volname '%s' -srcfolder '%s' -ov -format UDZO '%s'" % ( os.path.basename( target ), source, target ) ) + elif target.endswith( ".zip" ) : + shutil.make_archive( os.path.splitext( target )[0], "zip", root_dir=d, base_dir=b ) else : runCommand( "tar -czf %s -C %s %s" % ( target, d, b ) ) diff --git a/apps/stats/stats-1.py b/apps/stats/stats-1.py index d1fff81f4d0..793f22fe999 100644 --- a/apps/stats/stats-1.py +++ b/apps/stats/stats-1.py @@ -39,10 +39,14 @@ import sys import time import tempfile -import resource import collections import six +if sys.platform != "win32": + import resource +else: + import subprocess + import IECore import Gaffer @@ -746,6 +750,9 @@ def maxRSS( cls ) : if sys.platform == "darwin" : return cls( resource.getrusage( resource.RUSAGE_SELF ).ru_maxrss ) + elif sys.platform == "win32" : + result = subprocess.check_output( ["wmic", "process", "where", "processid={}".format(os.getpid()), "get", "PeakWorkingSetSize"] ) + return cls( int( result.split()[1] ) * 1024 ) else : return cls( resource.getrusage( resource.RUSAGE_SELF ).ru_maxrss * 1024 ) diff --git a/bin/gaffer.bat b/bin/gaffer.bat new file mode 100644 index 00000000000..e22bb866277 --- /dev/null +++ b/bin/gaffer.bat @@ -0,0 +1,153 @@ +@echo off + +setlocal EnableDelayedExpansion + +set GAFFER_ROOT=%~dp0%.. + +set HOME=%USERPROFILE% + +set GAFFER_JEMALLOC=0 + +call :prependToPath "%GAFFER_ROOT%\glsl" IECOREGL_SHADER_PATHS +call :prependToPath "%GAFFER_ROOT%\glsl" IECOREGL_SHADER_INCLUDE_PATHS + +call :prependToPath "%GAFFER_ROOT%\fonts" IECORE_FONT_PATHS +call :prependToPath "%GAFFER_ROOT%\ops" IECORE_OP_PATHS + +call :prependToPath "%USERPROFILE%\gaffer\opPresets;%GAFFER_ROOT%\opPresets" IECORE_OP_PRESET_PATHS +call :prependToPath "%USERPROFILE%\gaffer\procedurals;%GAFFER_ROOT%\procedurals" IECORE_PROCEDURAL_PATHS +call :prependToPath "%USERPROFILE%\gaffer\proceduralPresets;%GAFFER_ROOT%\proceduralPresets" IECORE_PROCEDURAL_PRESET_PATHS + +set CORTEX_POINTDISTRIBUTION_TILESET=%GAFFER_ROOT%\resources\cortex\tileset_2048.dat + +call :prependToPath "%USERPROFILE%\gaffer\apps;%GAFFER_ROOT%\apps" GAFFER_APP_PATHS + +call :prependToPath "%USERPROFILE%\gaffer\startup" GAFFER_STARTUP_PATHS +call :appendToPath "%GAFFER_ROOT%\startup" GAFFER_STARTUP_PATHS + +call :prependToPath "%GAFFER_ROOT%\graphics" GAFFERUI_IMAGE_PATHS + +set OSLHOME=%GAFFER_ROOT% + +call :prependToPath "%USERPROFILE%\gaffer\shaders;%GAFFER_ROOT%\shaders" OSL_SHADER_PATHS + +set GAFFEROSL_CODE_DIRECTORY=%USERPROFILE%\gaffer\oslCode +call :prependToPath "%GAFFER_OSL_CODE_DIRECTORY%" PATH + +set PYTHONHOME=%GAFFER_ROOT% + +call :prependToPath "%GAFFER_ROOT%\python" PYTHONPATH + +call :prependToPath "%GAFFER_ROOT%\lib" PATH + +set QT_OPENGL=desktop +set QT_QPA_PLATFORM_PLUGIN_PATH=%GAFFER_ROOT%\qt\plugins + +call :prependToPath "%GAFFER_ROOT%\bin" PATH + +rem Appleseed +rem if "%APPLESEED%" == "" ( +rem if EXIST "%GAFFER_ROOT%"\appleseed ( +rem set APPLESEED=%GAFFER_ROOT%\appleseed +rem ) +rem ) + +rem if "%APPLESEED%" NEQ "" ( +rem call :prependToPath "%APPLESEED%\shaders\gaffer" OSL_SHADER_PATHS +rem call :prependToPath "%APPLESEED%\shaders\appleseed" OSL_SHADER_PATHS +rem ) + +rem if "%APPLESEED%" NEQ "" ( +rem call :prependToPath "%APPLESEED%\bin;%APPLESEED%\lib" PATH +rem call :prependToPath "%APPLESEED%\lib\python2.7" PYTHONPATH +rem call :prependToPath "%OSL_SHADER_PATHS%;%GAFFER_ROOT%\appleseedDisplays" APPLESEED_SEARCHPATH +rem ) + +rem Arnold +if "%ARNOLD_ROOT%" NEQ "" ( + call :appendToPath "%ARNOLD_ROOT%\bin" PATH + call :appendToPath "%ARNOLD_ROOT%\python" PYTHONPATH + + if exist "%ARNOLD_ROOT%\include\ai_version.h" ( + for /f "tokens=3" %%A in ('findstr /R /C:"#define *AI_VERSION_ARCH_NUM" "%ARNOLD_ROOT%\include\ai_version.h"') do ( + set ARNOLD_ARCH_NUM=%%A + ) + for /f "tokens=3" %%A in ('findstr /R /C:"#define *AI_VERSION_MAJOR_NUM" "%ARNOLD_ROOT%\include\ai_version.h"') do ( + set ARNOLD_VERSION_NUM=%%A + ) + + set ARNOLD_VERSION=!ARNOLD_ARCH_NUM!.!ARNOLD_VERSION_NUM! + if exist "%GAFFER_ROOT%\arnold\%ARNOLD_VERSION%" ( + call :prependToPath "%GAFFER_ROOT%\arnold\!ARNOLD_VERSION!" GAFFER_EXTENSION_PATHS + call :prependToPath "%GAFFER_ROOT%\arnold\!ARNOLD_VERSION!\arnoldPlugins" ARNOLD_PLUGIN_PATH + call :prependToPath "%ARNOLD_ROOT%\plugins" ARNOLD_PLUGIN_PATH + ) else ( + echo WARNING : GafferArnold extension not available for Arnold %ARNOLD_VERSION% + ) + ) else ( + echo WARNING : Unable to determine Arnold version + ) +) + +rem 3Delight +if "%DELIGHT%" NEQ "" ( + call :appendToPath "%DELIGHT%\bin" PATH + call :appendToPath "%DELIGHT%\python" PYTHONPATH + call :appendToPath "%DELIGHT%\shaders" DL_SHADERS_PATH + call :appendToPath "%DELIGHT%\displays" DL_DISPLAYS_PATH + + call :appendToPath "%DELIGHT%" OSL_SHADER_PATHS + + call :appendToPath "%GAFFER_ROOT%\renderMan\displayDrivers" DL_RESOURCES_PATH +) + +rem Set up 3rd party extensions +rem Batch files are awkward at `for` loops. The default `for`, without `/f` +rem uses semi-colons AND spaces as delimiters, meaning we would not be able +rem to support spaces in extension paths. Bad. Using the `/f` switch lets +rem us specify the delimiter, but it then separates the tokens into a +rem set number that must be known ahead of time (i.e. %%A, %%B, etc.). +rem The accepted pattern seems to be to use recursion to pop the first token +rem then recurse through the remaining tokens until there are none left. + +set EXTENSION_PATH=%GAFFER_EXTENSION_PATHS% +:NextPath +for /f "tokens=1* delims=;" %%A in ("%EXTENSION_PATH%") do ( + if "%%A" NEQ "" ( + call :appendToPath "%%A\bin" PATH + call :appendToPath "%%A\lib" PATH + call :appendToPath "%%A\python" PYTHONPATH + call :appendToPath "%%A\apps" GAFFER_APP_PATHS + call :appendToPath "%%A\graphics" GAFFERUI_IMAGE_PATHS + call :appendToPath "%%A\glsl" IECOREGL_SHADER_PATHS + call :appendToPath "%%A\glsl" IECOREGL_SHADER_INCLUDE_PATHS + call :appendToPath "%%A\shaders" OSL_SHADER_PATHS + call :prependToPath "%%A\startup" GAFFER_STARTUP_PATHS + ) + if "%%B" NEQ "" ( + set EXTENSION_PATH=%%B + goto :NextPath + ) +) + +if "%GAFFER_DEBUG%" NEQ "" ( + %GAFFER_DEBUGGER% /debugexe "%GAFFER_ROOT%\bin\python.exe" "%GAFFER_ROOT%"/bin/__gaffer.py %* +) else ( + "%GAFFER_ROOT%"\bin\python.exe "%GAFFER_ROOT%"/bin/__gaffer.py %* +) + +if %ERRORLEVEL% NEQ 0 ( + echo "Error(s) running Gaffer" + exit /B %ERRORLEVEL% +) + +ENDLOCAL +exit /B 0 + +:prependToPath + set "%~2=%~1;!%~2!" + exit /B 0 + +:appendToPath + set "%~2=!%~2!;%~1" + exit /B 0 \ No newline at end of file diff --git a/doc/source/GettingStarted/TutorialAssemblingTheGafferBot/generate.py b/doc/source/GettingStarted/TutorialAssemblingTheGafferBot/generate.py new file mode 100644 index 00000000000..303a2817bec --- /dev/null +++ b/doc/source/GettingStarted/TutorialAssemblingTheGafferBot/generate.py @@ -0,0 +1,31 @@ +# BuildTarget: images/expansion.png +# BuildTarget: images/plus.png +# BuildTarget: images/nodeSetDriverNodeSelection.png +# BuildTarget: images/nodeSetDriverNodeSet.png +# BuildTarget: images/nodeSetStandardSet.png +# BuildTarget: images/layoutButton.png +# BuildTarget: images/objects.png +# BuildTarget: images/addObjects.png +# BuildTarget: images/replaceObjects.png +# BuildTarget: images/collapsibleArrowRight.png +# BuildTarget: images/timelinePlay.png +# BuildTarget: images/removeObjects.png +# BuildTarget: images/gafferSceneUITranslateTool.png +# BuildTarget: images/gafferSceneUIRotateTool.png + +import shutil +import os + +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "expansion.png" ), os.path.join( "images", "expansion.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "plus.png" ), os.path.join( "images", "plug.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "nodeSetDriverNodeSelection.png" ), os.path.join( "images", "nodeSetDriverNodeSelection.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "nodeSetStandardSet.png" ), os.path.join( "images", "nodeSetStandardSet.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "layoutButton.png" ), os.path.join( "images", "layoutButton.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "objects.png" ), os.path.join( "images", "objects.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "addObjects.png" ), os.path.join( "images", "addObjects.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "replaceObjects.png" ), os.path.join( "images", "replaceObjects.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "collapsibleArrowRight.png" ), os.path.join( "images", "collapsibleArrowRight.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "timelinePlay.png" ), os.path.join( "images", "timelinePlay.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "removeObjects.png" ), os.path.join( "images", "removeObjects.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "gafferSceneUITranslateTool.png" ), os.path.join( "images", "gafferSceneUITranslateTool.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "gafferSceneUIRotateTool.png" ), os.path.join( "images", "gafferSceneUIRotateTool.png" ) ) diff --git a/doc/source/GettingStarted/TutorialAssemblingTheGafferBot/generate.sh b/doc/source/GettingStarted/TutorialAssemblingTheGafferBot/generate.sh deleted file mode 100755 index 0c0d451d5ac..00000000000 --- a/doc/source/GettingStarted/TutorialAssemblingTheGafferBot/generate.sh +++ /dev/null @@ -1,32 +0,0 @@ -#! /bin/bash -# BuildTarget: images/expansion.png -# BuildTarget: images/plus.png -# BuildTarget: images/nodeSetNodeSelection.png -# BuildTarget: images/nodeSetFocusNode.png -# BuildTarget: images/nodeSetStandardSet.png -# BuildTarget: images/layoutButton.png -# BuildTarget: images/objects.png -# BuildTarget: images/addObjects.png -# BuildTarget: images/replaceObjects.png -# BuildTarget: images/collapsibleArrowRight.png -# BuildTarget: images/timelinePlay.png -# BuildTarget: images/removeObjects.png -# BuildTarget: images/gafferSceneUITranslateTool.png -# BuildTarget: images/gafferSceneUIRotateTool.png - -set -e - -cp $GAFFER_ROOT/graphics/expansion.png images -cp $GAFFER_ROOT/graphics/plus.png images -cp $GAFFER_ROOT/graphics/nodeSetNodeSelection.png images -cp $GAFFER_ROOT/graphics/nodeSetFocusNode.png images -cp $GAFFER_ROOT/graphics/nodeSetStandardSet.png images -cp $GAFFER_ROOT/graphics/layoutButton.png images -cp $GAFFER_ROOT/graphics/objects.png images -cp $GAFFER_ROOT/graphics/addObjects.png images -cp $GAFFER_ROOT/graphics/replaceObjects.png images -cp $GAFFER_ROOT/graphics/collapsibleArrowRight.png images -cp $GAFFER_ROOT/graphics/timelinePlay.png images -cp $GAFFER_ROOT/graphics/removeObjects.png images -cp $GAFFER_ROOT/graphics/gafferSceneUITranslateTool.png images -cp $GAFFER_ROOT/graphics/gafferSceneUIRotateTool.png images diff --git a/doc/source/Interface/ControlsAndShortcuts/generate.py b/doc/source/Interface/ControlsAndShortcuts/generate.py new file mode 100644 index 00000000000..53135e2c072 --- /dev/null +++ b/doc/source/Interface/ControlsAndShortcuts/generate.py @@ -0,0 +1,6 @@ +# BuildTarget: images/nodeSetStandardSet.png + +import shutil +import os + +shutil.copyfile(os.path.join( os.environ["GAFFER_ROOT"], "graphics", "nodeSetStandardSet.png" ), os.path.join( "images", "nodeSetStandardSet.png" ) ) diff --git a/doc/source/WorkingWithScenes/Camera/generate.py b/doc/source/WorkingWithScenes/Camera/generate.py new file mode 100644 index 00000000000..5acd7eab9af --- /dev/null +++ b/doc/source/WorkingWithScenes/Camera/generate.py @@ -0,0 +1,16 @@ +# BuildTarget: images/gafferSceneUIRotateTool.png +# BuildTarget: images/gafferSceneUITranslateTool.png +# BuildTarget: images/cameraOff.png +# BuildTarget: images/gafferSceneUICameraTool.png +# BuildTarget: images/toggleOff.png +# BuildTarget: images/plus.png + +import shutil +import os + +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "gafferSceneUIRotateTool.png" ), os.path.join( "images", "gafferSceneUIRotateTool.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "gafferSceneUITranslateTool.png" ), os.path.join( "images", "gafferSceneUITranslateTool.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "cameraOff.png" ), os.path.join( "images", "cameraOff.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "gafferSceneUICameraTool.png" ), os.path.join( "images", "gafferSceneUICameraTool.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "toggleOff.png" ), os.path.join( "images", "toggleOff.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "plus.png" ), os.path.join( "images", "plus.png" ) ) diff --git a/doc/source/WorkingWithScenes/Camera/generate.sh b/doc/source/WorkingWithScenes/Camera/generate.sh deleted file mode 100755 index 358253ceadc..00000000000 --- a/doc/source/WorkingWithScenes/Camera/generate.sh +++ /dev/null @@ -1,16 +0,0 @@ -#! /bin/bash -# BuildTarget: images/gafferSceneUIRotateTool.png -# BuildTarget: images/gafferSceneUITranslateTool.png -# BuildTarget: images/cameraOff.png -# BuildTarget: images/gafferSceneUICameraTool.png -# BuildTarget: images/toggleOff.png -# BuildTarget: images/plus.png - -set -e - -cp $GAFFER_ROOT/graphics/gafferSceneUIRotateTool.png images -cp $GAFFER_ROOT/graphics/gafferSceneUITranslateTool.png images -cp $GAFFER_ROOT/graphics/cameraOff.png images -cp $GAFFER_ROOT/graphics/gafferSceneUICameraTool.png images -cp $GAFFER_ROOT/graphics/toggleOff.png images -cp $GAFFER_ROOT/graphics/plus.png images diff --git a/doc/source/WorkingWithTheNodeGraph/BoxNode/generate.py b/doc/source/WorkingWithTheNodeGraph/BoxNode/generate.py new file mode 100644 index 00000000000..e0661831327 --- /dev/null +++ b/doc/source/WorkingWithTheNodeGraph/BoxNode/generate.py @@ -0,0 +1,12 @@ +# BuildTarget: images/gear.png +# BuildTarget: images/info.png +# BuildTarget: images/plugAdder.png +# BuildTarget: images/valueChanged.png + +import shutil +import os + +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "gear.png" ), os.path.join( "images", "gear.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "info.png" ), os.path.join( "images", "info.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "plugAdder.png" ), os.path.join( "images", "plugAdder.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "valueChanged.png" ), os.path.join( "images", "valueChanged.png" ) ) diff --git a/doc/source/WorkingWithTheNodeGraph/BoxNode/generate.sh b/doc/source/WorkingWithTheNodeGraph/BoxNode/generate.sh deleted file mode 100755 index 09d3523a4c0..00000000000 --- a/doc/source/WorkingWithTheNodeGraph/BoxNode/generate.sh +++ /dev/null @@ -1,12 +0,0 @@ -#! /bin/bash -# BuildTarget: images/gear.png -# BuildTarget: images/info.png -# BuildTarget: images/plugAdder.png -# BuildTarget: images/valueChanged.png - -set -e - -cp $GAFFER_ROOT/graphics/gear.png images -cp $GAFFER_ROOT/graphics/info.png images -cp $GAFFER_ROOT/graphics/plugAdder.png images -cp $GAFFER_ROOT/graphics/valueChanged.png images diff --git a/doc/source/WorkingWithTheNodeGraph/TutorialUsingTheOSLCodeNode/generate.py b/doc/source/WorkingWithTheNodeGraph/TutorialUsingTheOSLCodeNode/generate.py new file mode 100644 index 00000000000..387aa0c22fb --- /dev/null +++ b/doc/source/WorkingWithTheNodeGraph/TutorialUsingTheOSLCodeNode/generate.py @@ -0,0 +1,6 @@ +# BuildTarget: images/plus.png + +import shutil +import os + +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "plus.png" ), os.path.join( "images", "plus.png" ) ) diff --git a/doc/source/WorkingWithTheNodeGraph/TutorialUsingTheOSLCodeNode/generate.sh b/doc/source/WorkingWithTheNodeGraph/TutorialUsingTheOSLCodeNode/generate.sh deleted file mode 100755 index e81010d23d4..00000000000 --- a/doc/source/WorkingWithTheNodeGraph/TutorialUsingTheOSLCodeNode/generate.sh +++ /dev/null @@ -1,6 +0,0 @@ -#! /bin/bash -# BuildTarget: images/plus.png - -set -e - -cp $GAFFER_ROOT/graphics/plus.png images diff --git a/doc/source/WorkingWithThePythonScriptingAPI/ThePythonEditor/generate.py b/doc/source/WorkingWithThePythonScriptingAPI/ThePythonEditor/generate.py new file mode 100644 index 00000000000..75cdf6d0211 --- /dev/null +++ b/doc/source/WorkingWithThePythonScriptingAPI/ThePythonEditor/generate.py @@ -0,0 +1,12 @@ +# BuildTarget: images/plug.png +# BuildTarget: images/values.png +# BuildTarget: images/nodes.png +# BuildTarget: images/objects.png + +import shutil +import os + +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "plug.png" ), os.path.join( "images", "plug.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "values.png" ), os.path.join( "images", "values.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "nodes.png" ), os.path.join( "images", "nodes.png" ) ) +shutil.copyfile( os.path.join( os.environ["GAFFER_ROOT"], "graphics", "objects.png" ), os.path.join( "images", "objects.png" ) ) diff --git a/doc/source/WorkingWithThePythonScriptingAPI/ThePythonEditor/generate.sh b/doc/source/WorkingWithThePythonScriptingAPI/ThePythonEditor/generate.sh deleted file mode 100755 index 50f3cde1f9a..00000000000 --- a/doc/source/WorkingWithThePythonScriptingAPI/ThePythonEditor/generate.sh +++ /dev/null @@ -1,12 +0,0 @@ -#! /bin/bash -# BuildTarget: images/plug.png -# BuildTarget: images/values.png -# BuildTarget: images/nodes.png -# BuildTarget: images/objects.png - -set -e - -cp $GAFFER_ROOT/graphics/plug.png images/plug.png -cp $GAFFER_ROOT/graphics/values.png images/values.png -cp $GAFFER_ROOT/graphics/nodes.png images/nodes.png -cp $GAFFER_ROOT/graphics/objects.png images/objects.png diff --git a/doc/source/WorkingWithThePythonScriptingAPI/TutorialNodeGraphEditingInPython/generate.py b/doc/source/WorkingWithThePythonScriptingAPI/TutorialNodeGraphEditingInPython/generate.py new file mode 100644 index 00000000000..6399c62d2dc --- /dev/null +++ b/doc/source/WorkingWithThePythonScriptingAPI/TutorialNodeGraphEditingInPython/generate.py @@ -0,0 +1,10 @@ +# BuildTarget: images/nodes.png +# BuildTarget: images/plus.png +# BuildTarget: images/values.png + +import shutil +import os + +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "nodes.png" ), os.path.join( "images", "nodes.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "plug.png" ), os.path.join( "images", "plug.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "values.png" ), os.path.join( "images", "values.png" ) ) diff --git a/doc/source/WorkingWithThePythonScriptingAPI/TutorialNodeGraphEditingInPython/generate.sh b/doc/source/WorkingWithThePythonScriptingAPI/TutorialNodeGraphEditingInPython/generate.sh deleted file mode 100755 index 12617fe89d0..00000000000 --- a/doc/source/WorkingWithThePythonScriptingAPI/TutorialNodeGraphEditingInPython/generate.sh +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/bash -# BuildTarget: images/nodes.png -# BuildTarget: images/plus.png -# BuildTarget: images/values.png - -set -e - -cp $GAFFER_ROOT/graphics/nodes.png images -cp $GAFFER_ROOT/graphics/plug.png images -cp $GAFFER_ROOT/graphics/values.png images diff --git a/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig1/generate.py b/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig1/generate.py new file mode 100644 index 00000000000..04ae5618819 --- /dev/null +++ b/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig1/generate.py @@ -0,0 +1,7 @@ +# BuildTarget: images/pathChooser.png + +import shutil +import os + +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "pathChooser.png" ), os.path.join( "images", "pathChooser.png" ) ) + diff --git a/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig1/generate.sh b/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig1/generate.sh deleted file mode 100755 index a1796d92c39..00000000000 --- a/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig1/generate.sh +++ /dev/null @@ -1,7 +0,0 @@ -#! /bin/bash -# BuildTarget: images/pathChooser.png - -set -e - -cp $GAFFER_ROOT/graphics/pathChooser.png images - diff --git a/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig2/generate.py b/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig2/generate.py new file mode 100644 index 00000000000..3a8c07c4b87 --- /dev/null +++ b/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig2/generate.py @@ -0,0 +1,8 @@ +# BuildTarget: images/pathChooser.png +# BuildTarget: images/bookmarks.png + +import shutil +import os + +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "pathChooser.png" ), os.path.join( "images", "pathChooser.png" ) ) +shutil.copyfile( os.path.join( os.environ["$GAFFER_ROOT"], "graphics", "bookmarks.png" ), os.path.join( "images", "bookmarks.png" ) ) diff --git a/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig2/generate.sh b/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig2/generate.sh deleted file mode 100755 index 0659ca0f6cf..00000000000 --- a/doc/source/WorkingWithThePythonScriptingAPI/TutorialStartupConfig2/generate.sh +++ /dev/null @@ -1,8 +0,0 @@ -#! /bin/bash -# BuildTarget: images/pathChooser.png -# BuildTarget: images/bookmarks.png - -set -e - -cp $GAFFER_ROOT/graphics/pathChooser.png images -cp $GAFFER_ROOT/graphics/bookmarks.png images diff --git a/doc/source/generate.py b/doc/source/generate.py new file mode 100644 index 00000000000..b255448df95 --- /dev/null +++ b/doc/source/generate.py @@ -0,0 +1,8 @@ +# BuildTarget: _static/GafferLogo.svg _static/GafferLogoMini.svg +# BuildTarget: _static/GafferLogoMini.svg + +import shutil +import os + +shutil.copyfile( os.path.join( "..", "..", "resources", "GafferLogo.svg" ), os.path.join( "_static", "GafferLogo.svg" ) ) +shutil.copyfile( os.path.join( "..", "..", "resources", "GafferLogoMini.svg" ), os.path.join( "_static", "GafferLogoMini.svg" ) ) diff --git a/doc/source/generate.sh b/doc/source/generate.sh deleted file mode 100755 index 262cc372f4c..00000000000 --- a/doc/source/generate.sh +++ /dev/null @@ -1,8 +0,0 @@ -#! /bin/bash -# BuildTarget: _static/GafferLogo.svg -# BuildTarget: _static/GafferLogoMini.svg - -set -e - -cp ../../resources/GafferLogo.svg _static -cp ../../resources/GafferLogoMini.svg _static diff --git a/include/Gaffer/Animation.h b/include/Gaffer/Animation.h index ee788ada1d2..7fed119d773 100644 --- a/include/Gaffer/Animation.h +++ b/include/Gaffer/Animation.h @@ -105,7 +105,7 @@ class GAFFER_API Animation : public ComputeNode IE_CORE_DECLAREPTR( Interpolator ) // Defines a tangent - class Tangent : private boost::noncopyable + class GAFFER_API Tangent : private boost::noncopyable { public: @@ -200,7 +200,7 @@ class GAFFER_API Animation : public ComputeNode }; /// Defines a single keyframe. - class Key : public IECore::RunTimeTyped + class GAFFER_API Key : public IECore::RunTimeTyped { public : @@ -318,7 +318,7 @@ class GAFFER_API Animation : public ComputeNode /// Defines a curve as a collection of keyframes and methods /// for editing them. Provides methods for evaluating the /// interpolated curve at arbitrary positions. - class CurvePlug : public ValuePlug + class GAFFER_API CurvePlug : public ValuePlug { public : diff --git a/include/Gaffer/ApplicationRoot.h b/include/Gaffer/ApplicationRoot.h index 9511493563f..dc5ac1ffa23 100644 --- a/include/Gaffer/ApplicationRoot.h +++ b/include/Gaffer/ApplicationRoot.h @@ -103,8 +103,9 @@ class GAFFER_API ApplicationRoot : public GraphComponent /// Saves the current preferences value to the specified file. virtual void savePreferences( const std::string &fileName ) const; /// Returns ~/gaffer/startup/appName - the directory in which preferences are - /// stored, and ensures that the directory exists. Other application components - /// may use this location to store settings they wish to persist across invocations. + /// stored, in OS native format, and ensures that the directory exists. + /// Other application components may use this location to store settings they + /// wish to persist across invocations. /// \todo Perhaps this should include a major version number in the future. std::string preferencesLocation() const; //@} diff --git a/include/Gaffer/ArrayPlug.h b/include/Gaffer/ArrayPlug.h index 6572308434b..9b9521f9e1c 100644 --- a/include/Gaffer/ArrayPlug.h +++ b/include/Gaffer/ArrayPlug.h @@ -64,7 +64,7 @@ class GAFFER_API ArrayPlug : public Plug Direction direction = In, PlugPtr element = nullptr, size_t minSize = 1, - size_t maxSize = Imath::limits::max(), + size_t maxSize = std::numeric_limits::max(), unsigned flags = Default, bool resizeWhenInputsChange = true ); diff --git a/include/Gaffer/Container.h b/include/Gaffer/Container.h index ec493bb9629..9f9ecff672a 100644 --- a/include/Gaffer/Container.h +++ b/include/Gaffer/Container.h @@ -43,7 +43,7 @@ namespace Gaffer { template -class GAFFER_API Container : public Base +class Container : public Base { public : diff --git a/include/Gaffer/Context.h b/include/Gaffer/Context.h index 445ebc09833..ac9098ca273 100644 --- a/include/Gaffer/Context.h +++ b/include/Gaffer/Context.h @@ -189,7 +189,7 @@ class GAFFER_API Context : public IECore::RefCounted /// The Scope class is used to push and pop the current context on /// the calling thread. - class Scope : private ThreadState::Scope + class GAFFER_API Scope : private ThreadState::Scope { public : @@ -209,7 +209,7 @@ class GAFFER_API Context : public IECore::RefCounted /// because it is harder to provide the necessary lifetime /// guarantees there, and performance critical code should /// not be implemented in Python in any case. - class EditableScope : private ThreadState::Scope + class GAFFER_API EditableScope : private ThreadState::Scope { public : @@ -307,7 +307,7 @@ class GAFFER_API Context : public IECore::RefCounted // along with the `IECore::TypeId` for `TypedData`, which is used to // validate type-safe access. Does not manage memory or ownership in any // way : this is the responsibility of calling code. - struct Value + struct GAFFER_API Value { Value(); @@ -349,7 +349,7 @@ class GAFFER_API Context : public IECore::RefCounted const void *m_value; IECore::MurmurHash m_hash; - struct TypeFunctions + struct GAFFER_API TypeFunctions { IECore::DataPtr (*makeData)( const Value &value, const void **dataValue ); bool (*isEqual)( const Value &a, const Value &b ); diff --git a/include/Gaffer/ContextAlgo.h b/include/Gaffer/ContextAlgo.h index 3756707eb05..2fea5af28d7 100644 --- a/include/Gaffer/ContextAlgo.h +++ b/include/Gaffer/ContextAlgo.h @@ -62,7 +62,7 @@ class GAFFER_API GlobalScope : boost::noncopyable GlobalScope( const Context *context, const Plug *plug ); ~GlobalScope(); - struct Registration + struct GAFFER_API Registration { Registration( IECore::TypeId plugTypeId, const std::initializer_list &variablesToRemove ); }; diff --git a/include/Gaffer/ContextMonitor.h b/include/Gaffer/ContextMonitor.h index 1cb4effba17..3ea33d6e8e0 100644 --- a/include/Gaffer/ContextMonitor.h +++ b/include/Gaffer/ContextMonitor.h @@ -71,7 +71,7 @@ class GAFFER_API ContextMonitor : public Monitor IE_CORE_DECLAREMEMBERPTR( ContextMonitor ) - struct Statistics + struct GAFFER_API Statistics { size_t numUniqueContexts() const; diff --git a/include/Gaffer/Expression.h b/include/Gaffer/Expression.h index 15c8da2c051..b8b3d6c1020 100644 --- a/include/Gaffer/Expression.h +++ b/include/Gaffer/Expression.h @@ -90,7 +90,7 @@ class GAFFER_API Expression : public ComputeNode /// for use in the Expression node. All methods /// are protected as Engines are for the internal /// use of the Expression node only. - class Engine : public IECore::RefCounted + class GAFFER_API Engine : public IECore::RefCounted { public : diff --git a/include/Gaffer/FileSystemPath.h b/include/Gaffer/FileSystemPath.h index b3d972fe187..292f1a0e804 100644 --- a/include/Gaffer/FileSystemPath.h +++ b/include/Gaffer/FileSystemPath.h @@ -58,6 +58,9 @@ class GAFFER_API FileSystemPath : public Path ~FileSystemPath() override; + /// Sets the path root and names from an OS native path string + void setFromString(const std::string &string) override; + bool isValid( const IECore::Canceller *canceller = nullptr ) const override; bool isLeaf( const IECore::Canceller *canceller = nullptr ) const override; void propertyNames( std::vector &names, const IECore::Canceller *canceller = nullptr ) const override; @@ -82,11 +85,16 @@ class GAFFER_API FileSystemPath : public Path // a FileSequence. IECore::FileSequencePtr fileSequence() const; + std::string string() const override; + // Returns the path converted to the OS native format + std::string nativeString() const; + static PathFilterPtr createStandardFilter( const std::vector &extensions = std::vector(), const std::string &extensionsLabel = "", bool includeSequenceFilter = false ); protected : void doChildren( std::vector &children, const IECore::Canceller *canceller ) const override; + std::string getOwner( const std::string &pathString ) const; private : diff --git a/include/Gaffer/FileSystemPathPlug.h b/include/Gaffer/FileSystemPathPlug.h new file mode 100644 index 00000000000..32f67485fd6 --- /dev/null +++ b/include/Gaffer/FileSystemPathPlug.h @@ -0,0 +1,113 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2011-2012, John Haddon. All rights reserved. +// Copyright (c) 2011-2015, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef GAFFER_FILESYSTEMPATHPLUG_H +#define GAFFER_FILESYSTEMPATHPLUG_H + +#include "Gaffer/Context.h" +#include "Gaffer/StringPlug.h" + +#include "IECore/StringAlgo.h" + + +namespace Gaffer +{ + +/// Plug for providing file system path values. +/// +/// Inherit from StringPlug so all substitutions work and it +/// is backwards compatible with Gaffer scripts from previous versions. +/// +/// Gaffer standardizes on using forward slashes for separating directories +/// in a path in the UI. Pulling on the FileSystemPathPlug returns an OS +/// native format string. Directories are separated by forward slashes on +/// POSIX systems and back slashes on Windows. +/// On Windows, interpret a path starting with a forward slash as a UNC +/// path, converting it to a double back slash. + +class GAFFER_API FileSystemPathPlug : public StringPlug +{ + + public : + + typedef std::string ValueType; + + IE_CORE_DECLARERUNTIMETYPEDEXTENSION( Gaffer::FileSystemPathPlug, FileSystemPathPlugTypeId, StringPlug ); + + + FileSystemPathPlug( + const std::string &name = defaultName(), + Direction direction=In, + const std::string &defaultValue = "", + unsigned flags = Default, + unsigned substitutions = IECore::StringAlgo::AllSubstitutions + ); + ~FileSystemPathPlug() override; + + /// Accepts instances StringPlug or derived classes, + /// which includes FileSystemPath Plug. + bool acceptsInput( const Plug *input ) const override; + PlugPtr createCounterpart( const std::string &name, Direction direction ) const override; + + /// \undoable + void setValue(const std::string &value); + /// Returns the value. See comments in TypedObjectPlug::getValue() + /// for details of the optional precomputedHash argument - and use + /// with care! + std::string getValue( const IECore::MurmurHash *precomputedHash = nullptr, const Context *context = nullptr, const bool forceSubstitutions = false ) const; + + void setFrom(const ValuePlug *other) override; + + IECore::MurmurHash hash() const override; + /// Ensures the method above doesn't mask + /// ValuePlug::hash( h ) + using ValuePlug::hash; +}; + +IE_CORE_DECLAREPTR( FileSystemPathPlug ); + +typedef FilteredChildIterator > FileSystemPathPlugIterator; +typedef FilteredChildIterator > InputFileSystemPathPlugIterator; +typedef FilteredChildIterator > OutputFileSystemPathPlugIterator; + +typedef FilteredRecursiveChildIterator, PlugPredicate<> > RecursiveFileSystemPathPlugIterator; +typedef FilteredRecursiveChildIterator, PlugPredicate<> > RecursiveInputFileSystemPathPlugIterator; +typedef FilteredRecursiveChildIterator, PlugPredicate<> > RecursiveOutputFileSystemPathPlugIterator; + +} // namespace Gaffer + +#endif // GAFFER_FILESYSTEMPATHPLUGPLUG_H diff --git a/include/Gaffer/HiddenFilePathFilter.h b/include/Gaffer/HiddenFilePathFilter.h new file mode 100644 index 00000000000..038b97bd773 --- /dev/null +++ b/include/Gaffer/HiddenFilePathFilter.h @@ -0,0 +1,81 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2022, Hypothetical Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef GAFFER_HIDDENFILEPATHFILTER_H +#define GAFFER_HIDDENFILEPATHFILTER_H + +#include "Gaffer/PathFilter.h" +#include "Gaffer/TypeIds.h" + +namespace Gaffer +{ + +IE_CORE_FORWARDDECLARE( HiddenFilePathFilter ) + +/// HiddenFilePathFilters can filter the results +/// of FileSystemPath::children() to provide a masked view +/// that either includes or excludes hidden files. +class GAFFER_API HiddenFilePathFilter : public PathFilter +{ + + public : + + HiddenFilePathFilter( IECore::CompoundDataPtr userData = nullptr ); + ~HiddenFilePathFilter() override; + + IE_CORE_DECLARERUNTIMETYPEDEXTENSION( Gaffer::HiddenFilePathFilter, HiddenFilePathFilterTypeId, Gaffer::PathFilter ); + + void setInverted( bool inverted ); + bool getInverted() const; + + protected : + + void doFilter( std::vector &paths, const IECore::Canceller *canceller ) const override; + + private : + + bool invert( bool b ) const; + bool remove( PathPtr path ) const; + + bool m_inverted; + +}; + +IE_CORE_DECLAREPTR( HiddenFilePathFilter ) + +} // namespace Gaffer + +#endif // GAFFER_HIDDENFILEPATHFILTER_H diff --git a/include/Gaffer/Monitor.h b/include/Gaffer/Monitor.h index 8355edacb68..e1570380df5 100644 --- a/include/Gaffer/Monitor.h +++ b/include/Gaffer/Monitor.h @@ -59,7 +59,7 @@ class GAFFER_API Monitor : public IECore::RefCounted using MonitorSet = boost::container::flat_set; - class Scope : private ThreadState::Scope + class GAFFER_API Scope : ThreadState::Scope { public : diff --git a/include/Gaffer/Path.h b/include/Gaffer/Path.h index 9a5f7fd3543..5789e8f1c93 100644 --- a/include/Gaffer/Path.h +++ b/include/Gaffer/Path.h @@ -40,6 +40,7 @@ #include "Gaffer/Export.h" #include "Gaffer/TypeIds.h" +#include "Gaffer/PathFilter.h" #include "IECore/CompoundData.h" #include "IECore/InternedString.h" @@ -90,6 +91,7 @@ class GAFFER_API Path : public IECore::RunTimeTyped /// Returns the root of the path - this will be "/" for absolute /// paths and "" for relative paths. const IECore::InternedString &root() const; + void setRoot( IECore::InternedString &newRoot ); /// Returns true if this path is empty. bool isEmpty() const; @@ -141,7 +143,7 @@ class GAFFER_API Path : public IECore::RunTimeTyped /// Sets the path root and names from a "/" /// separated string. - void setFromString( const std::string &string ); + virtual void setFromString( const std::string &string ); /// Returns a copy of this path. Must be reimplemented /// by derived classes so that the copy has the appropriate @@ -180,7 +182,7 @@ class GAFFER_API Path : public IECore::RunTimeTyped /// Returns the path concatenated into a string, using '/' /// as a separator between names. - std::string string() const; + virtual std::string string() const; bool operator == ( const Path &other ) const; bool operator != ( const Path &other ) const; diff --git a/include/Gaffer/PerformanceMonitor.h b/include/Gaffer/PerformanceMonitor.h index d471d39321b..d0930864e8f 100644 --- a/include/Gaffer/PerformanceMonitor.h +++ b/include/Gaffer/PerformanceMonitor.h @@ -65,7 +65,7 @@ class GAFFER_API PerformanceMonitor : public Monitor IE_CORE_DECLAREMEMBERPTR( PerformanceMonitor ) - struct Statistics + struct GAFFER_API Statistics { Statistics( diff --git a/include/Gaffer/Process.h b/include/Gaffer/Process.h index ea1d82517a3..4860a6338f0 100644 --- a/include/Gaffer/Process.h +++ b/include/Gaffer/Process.h @@ -39,6 +39,8 @@ #include "Gaffer/Export.h" #include "Gaffer/ThreadState.h" +#include "Gaffer/Plug.h" +#include "Gaffer/Context.h" #include "IECore/InternedString.h" diff --git a/include/Gaffer/ScriptNode.h b/include/Gaffer/ScriptNode.h index 89b96331d61..9a789cd46df 100644 --- a/include/Gaffer/ScriptNode.h +++ b/include/Gaffer/ScriptNode.h @@ -67,7 +67,7 @@ IE_CORE_FORWARDDECLARE( ApplicationRoot ); IE_CORE_FORWARDDECLARE( Context ); IE_CORE_FORWARDDECLARE( StandardSet ); IE_CORE_FORWARDDECLARE( CompoundDataPlug ); -IE_CORE_FORWARDDECLARE( StringPlug ); +IE_CORE_FORWARDDECLARE( FileSystemPathPlug ); typedef Container ScriptContainer; IE_CORE_DECLAREPTR( ScriptContainer ); @@ -220,8 +220,8 @@ class GAFFER_API ScriptNode : public Node //////////////////////////////////////////////////////////////////// /// Returns the plug which specifies the file used in all load and save /// operations. - StringPlug *fileNamePlug(); - const StringPlug *fileNamePlug() const; + FileSystemPathPlug *fileNamePlug(); + const FileSystemPathPlug *fileNamePlug() const; /// Returns a plug which is used to flag when the script has had changes /// made since the last call to save(). BoolPlug *unsavedChangesPlug(); diff --git a/include/Gaffer/Spreadsheet.h b/include/Gaffer/Spreadsheet.h index eef2156db47..60f87f80101 100644 --- a/include/Gaffer/Spreadsheet.h +++ b/include/Gaffer/Spreadsheet.h @@ -70,7 +70,7 @@ class GAFFER_API Spreadsheet : public ComputeNode /// /// > Note : It is strongly recommended that the child RowPlugs are /// > accessed via their numeric indices and never via their names. - class RowsPlug : public ValuePlug + class GAFFER_API RowsPlug : public ValuePlug { public : @@ -143,7 +143,7 @@ class GAFFER_API Spreadsheet : public ComputeNode /// Defines a single row of the spreadsheet. Access using /// `RowPlug::Range( *rowsPlug() )` or via `rowsPlug()->getChild()`. - class RowPlug : public ValuePlug + class GAFFER_API RowPlug : public ValuePlug { public : @@ -171,7 +171,7 @@ class GAFFER_API Spreadsheet : public ComputeNode /// Defines a single cell in the spreadsheet. Access using /// `CellPlug::Range( *rowPlug->cellsPlug() )` or via /// `rowPlug->cellsPlug()->getChild()`. - class CellPlug : public ValuePlug + class GAFFER_API CellPlug : public ValuePlug { public : diff --git a/include/Gaffer/StringPlug.h b/include/Gaffer/StringPlug.h index 7e581eaf790..59c4c917fdb 100644 --- a/include/Gaffer/StringPlug.h +++ b/include/Gaffer/StringPlug.h @@ -112,7 +112,7 @@ class GAFFER_API StringPlug : public ValuePlug /// Returns the value. See comments in TypedObjectPlug::getValue() /// for details of the optional precomputedHash argument - and use /// with care! - std::string getValue( const IECore::MurmurHash *precomputedHash = nullptr ) const; + virtual std::string getValue( const IECore::MurmurHash *precomputedHash = nullptr ) const; void setFrom( const ValuePlug *other ) override; diff --git a/include/Gaffer/ThreadState.h b/include/Gaffer/ThreadState.h index 9050a27bbc0..37edf862400 100644 --- a/include/Gaffer/ThreadState.h +++ b/include/Gaffer/ThreadState.h @@ -81,7 +81,7 @@ class GAFFER_API ThreadState /// no active monitors, and a default constructed Context. ThreadState(); - class Scope : public boost::noncopyable + class GAFFER_API Scope : public boost::noncopyable { public : diff --git a/include/Gaffer/TypeIds.h b/include/Gaffer/TypeIds.h index d34bdb0b8bf..ee01069e1a2 100644 --- a/include/Gaffer/TypeIds.h +++ b/include/Gaffer/TypeIds.h @@ -142,6 +142,8 @@ enum TypeId M33fVectorDataPlugTypeId = 110095, ScriptNodeFocusSetTypeId = 110096, AnimationKeyTypeId = 110097, + FileSystemPathPlugTypeId = 110098, + HiddenFilePathFilterTypeId = 110099, LastTypeId = 110159, diff --git a/include/Gaffer/TypedObjectPlug.h b/include/Gaffer/TypedObjectPlug.h index d2ca647a002..c6f2d4eb931 100644 --- a/include/Gaffer/TypedObjectPlug.h +++ b/include/Gaffer/TypedObjectPlug.h @@ -120,7 +120,7 @@ class IECORE_EXPORT TypedObjectPlug : public ValuePlug }; -#ifndef Gaffer_EXPORTS +#if !defined( Gaffer_EXPORTS ) && !defined( _MSC_VER ) extern template class TypedObjectPlug; extern template class TypedObjectPlug; diff --git a/include/GafferArnold/ArnoldAtmosphere.h b/include/GafferArnold/ArnoldAtmosphere.h index 90a4069a06b..e682a217b37 100644 --- a/include/GafferArnold/ArnoldAtmosphere.h +++ b/include/GafferArnold/ArnoldAtmosphere.h @@ -45,7 +45,7 @@ namespace GafferArnold { -class GAFFERSCENE_API ArnoldAtmosphere : public GafferScene::GlobalShader +class GAFFERARNOLD_API ArnoldAtmosphere : public GafferScene::GlobalShader { public : diff --git a/include/GafferArnold/ArnoldBackground.h b/include/GafferArnold/ArnoldBackground.h index cf0d56be58d..fc111011a0a 100644 --- a/include/GafferArnold/ArnoldBackground.h +++ b/include/GafferArnold/ArnoldBackground.h @@ -45,7 +45,7 @@ namespace GafferArnold { -class GAFFERSCENE_API ArnoldBackground : public GafferScene::GlobalShader +class GAFFERARNOLD_API ArnoldBackground : public GafferScene::GlobalShader { public : diff --git a/include/GafferArnold/ArnoldColorManager.h b/include/GafferArnold/ArnoldColorManager.h index 7401bbf7f1d..3ee221512fe 100644 --- a/include/GafferArnold/ArnoldColorManager.h +++ b/include/GafferArnold/ArnoldColorManager.h @@ -50,7 +50,7 @@ namespace GafferArnold class ArnoldShader; -class GAFFERSCENE_API ArnoldColorManager : public GafferScene::GlobalsProcessor +class GAFFERARNOLD_API ArnoldColorManager : public GafferScene::GlobalsProcessor { public : diff --git a/include/GafferArnold/ArnoldMeshLight.h b/include/GafferArnold/ArnoldMeshLight.h index 00a4d51f903..3168fe356ee 100644 --- a/include/GafferArnold/ArnoldMeshLight.h +++ b/include/GafferArnold/ArnoldMeshLight.h @@ -42,6 +42,8 @@ #include "GafferScene/FilteredSceneProcessor.h" +#include "GafferArnold/Export.h" + namespace GafferArnold { diff --git a/include/GafferBindings/DataBinding.h b/include/GafferBindings/DataBinding.h index 9b42331bd8a..fa3eb3f55ac 100644 --- a/include/GafferBindings/DataBinding.h +++ b/include/GafferBindings/DataBinding.h @@ -43,6 +43,8 @@ #include "IECore/Data.h" +#include "GafferBindings/Export.h" + namespace GafferBindings { diff --git a/include/GafferBindings/DependencyNodeBinding.h b/include/GafferBindings/DependencyNodeBinding.h index 1ac0e3be7d2..6e877d2ae7c 100644 --- a/include/GafferBindings/DependencyNodeBinding.h +++ b/include/GafferBindings/DependencyNodeBinding.h @@ -40,6 +40,7 @@ #include "boost/python.hpp" +#include "GafferBindings/Export.h" #include "GafferBindings/NodeBinding.h" #include "Gaffer/Context.h" @@ -64,7 +65,7 @@ class DependencyNodeClass : public NodeClass }; -class GAFFER_API DependencyNodeWrapperBase +class GAFFERBINDINGS_API DependencyNodeWrapperBase { protected : diff --git a/include/GafferBindings/MatchPatternPathFilterBinding.h b/include/GafferBindings/MatchPatternPathFilterBinding.h new file mode 100644 index 00000000000..363a286f86e --- /dev/null +++ b/include/GafferBindings/MatchPatternPathFilterBinding.h @@ -0,0 +1,49 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2014, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef GAFFERBINDINGS_MATCHPATTERNPATHFILTERBINDING_H +#define GAFFERBINDINGS_MATCHPATTERNPATHFILTERBINDING_H + +#include "GafferBindings/Export.h" + +namespace GafferBindings +{ + +GAFFERBINDINGS_API void bindMatchPatternPathFilter(); + +} // namespace GafferBindings + +#endif // GAFFERBINDINGS_MATCHPATTERNPATHFILTERBINDING_H diff --git a/include/GafferBindings/MetadataBinding.h b/include/GafferBindings/MetadataBinding.h index ddc442dfa55..19d0eaeae91 100644 --- a/include/GafferBindings/MetadataBinding.h +++ b/include/GafferBindings/MetadataBinding.h @@ -41,6 +41,8 @@ #include "GafferBindings/Serialisation.h" +#include "GafferBindings/Export.h" + namespace GafferBindings { diff --git a/include/GafferBindings/PathBinding.inl b/include/GafferBindings/PathBinding.inl index 3d4242bea08..f30519a39e8 100644 --- a/include/GafferBindings/PathBinding.inl +++ b/include/GafferBindings/PathBinding.inl @@ -179,7 +179,8 @@ PathClass::PathClass( const char *docString ) this->def( "isValid", &Detail::isValid, boost::python::arg( "canceller" ) = boost::python::object() ); this->def( "isLeaf", &Detail::isLeaf, boost::python::arg( "canceller" ) = boost::python::object() ); this->def( "propertyNames", &Detail::propertyNames, boost::python::arg( "canceller" ) = boost::python::object() ); - this->def( "property", &Detail::property, ( boost::python::arg( "name" ), boost::python::arg( "canceller" ) = boost::python::object() ) ); + boost::python::object o = boost::python::object(); + this->def( "property", &Detail::property, ( boost::python::arg( "name" ), boost::python::arg( "canceller" ) = o ) ); this->def( "cancellationSubject", &Detail::cancellationSubject ); // Backwards compatibility with deprecated Path.info() // method from original python implementation. diff --git a/include/GafferBindings/Serialisation.h b/include/GafferBindings/Serialisation.h index 0213d063051..a3d18aa5066 100644 --- a/include/GafferBindings/Serialisation.h +++ b/include/GafferBindings/Serialisation.h @@ -113,7 +113,7 @@ class GAFFERBINDINGS_API Serialisation : boost::noncopyable /// on Serialiser and adding to the methods on Serialisation. The logical conclusion /// may be a single `Serialiser::serialise()` method and various `Serialisation::add*()` /// methods. - class Serialiser : public IECore::RefCounted + class GAFFERBINDINGS_API Serialiser : public IECore::RefCounted { public : diff --git a/include/GafferBindings/SignalBinding.inl b/include/GafferBindings/SignalBinding.inl index 0b28ffab39a..fc3eb014ead 100644 --- a/include/GafferBindings/SignalBinding.inl +++ b/include/GafferBindings/SignalBinding.inl @@ -45,6 +45,8 @@ #include "boost/signals.hpp" #include "boost/version.hpp" +#include "GafferBindings/Export.h" + namespace GafferBindings { diff --git a/include/GafferBindings/TypedObjectPlugBinding.inl b/include/GafferBindings/TypedObjectPlugBinding.inl index e48c268a491..ec2a6ad5316 100644 --- a/include/GafferBindings/TypedObjectPlugBinding.inl +++ b/include/GafferBindings/TypedObjectPlugBinding.inl @@ -143,7 +143,8 @@ TypedObjectPlugClass::TypedObjectPlugClass( const char *docString ) ); this->def( "defaultValue", &Detail::defaultValue, ( boost::python::arg_( "_copy" ) = true ) ); this->def( "setValue", Detail::setValue, ( boost::python::arg_( "value" ), boost::python::arg_( "_copy" ) = true ) ); - this->def( "getValue", Detail::getValue, ( boost::python::arg_( "_precomputedHash" ) = boost::python::object(), boost::python::arg_( "_copy" ) = true ) ); + boost::python::object b = boost::python::object(); + this->def( "getValue", Detail::getValue, ( boost::python::arg_( "_precomputedHash" ) = b, boost::python::arg_( "_copy" ) = true ) ); boost::python::scope s = *this; diff --git a/include/GafferCortex/ExecutableOpHolder.h b/include/GafferCortex/ExecutableOpHolder.h index dcc1bbc190e..fd5f0cdf225 100644 --- a/include/GafferCortex/ExecutableOpHolder.h +++ b/include/GafferCortex/ExecutableOpHolder.h @@ -37,6 +37,7 @@ #ifndef GAFFERCORTEX_EXECUTABLEOPHOLDER_H #define GAFFERCORTEX_EXECUTABLEOPHOLDER_H +#include "GafferCortex/Export.h" #include "GafferCortex/ParameterisedHolder.h" namespace IECore diff --git a/include/GafferCortex/OpHolder.h b/include/GafferCortex/OpHolder.h index 25bdfea0f3a..dc575415acf 100644 --- a/include/GafferCortex/OpHolder.h +++ b/include/GafferCortex/OpHolder.h @@ -37,6 +37,7 @@ #ifndef GAFFERCORTEX_OPHOLDER_H #define GAFFERCORTEX_OPHOLDER_H +#include "GafferCortex/Export.h" #include "GafferCortex/ParameterisedHolder.h" namespace IECore diff --git a/include/GafferCortex/ParameterHandler.h b/include/GafferCortex/ParameterHandler.h index 560f3766487..de842eb30db 100644 --- a/include/GafferCortex/ParameterHandler.h +++ b/include/GafferCortex/ParameterHandler.h @@ -46,6 +46,8 @@ #include +#include "GafferCortex/Export.h" + namespace GafferCortex { diff --git a/include/GafferCortex/ParameterisedHolder.h b/include/GafferCortex/ParameterisedHolder.h index f963aac96f0..ae12dffc2e4 100644 --- a/include/GafferCortex/ParameterisedHolder.h +++ b/include/GafferCortex/ParameterisedHolder.h @@ -86,7 +86,7 @@ class GAFFERCORTEX_API ParameterisedHolder : public BaseType void setParameterisedValues(); /// \todo Is this even needed? Can we just use an UndoScope instead? - class ParameterModificationContext + class GAFFERCORTEX_API ParameterModificationContext { public : ParameterModificationContext( Ptr parameterisedHolder ); diff --git a/include/GafferCortexBindings/Export.h b/include/GafferCortexBindings/Export.h new file mode 100644 index 00000000000..b046072d14a --- /dev/null +++ b/include/GafferCortexBindings/Export.h @@ -0,0 +1,51 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2016, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef GAFFERCORTEXBINDINGS_EXPORT_H +#define GAFFERCORTEXBINDINGS_EXPORT_H + +#include "Gaffer/Export.h" + +// define GAFFERCORTEXBINDINGS_API macro based on whether or not we are compiling +// GafferCortexBindings, or including headers for linking to it. the GAFFERCORTEXBINDINGS_API +// macro is the one that is used in the class definitions. +#ifdef GafferCortexBindings_EXPORTS + #define GAFFERCORTEXBINDINGS_API GAFFER_EXPORT +#else + #define GAFFERCORTEXBINDINGS_API GAFFER_IMPORT +#endif + +#endif // #ifndef GAFFERCORTEXBINDINGS_EXPORT_H diff --git a/include/GafferDelight/IECoreDelightPreview/NodeAlgo.h b/include/GafferDelight/IECoreDelightPreview/NodeAlgo.h index f16463d9cbe..dfaebb35217 100644 --- a/include/GafferDelight/IECoreDelightPreview/NodeAlgo.h +++ b/include/GafferDelight/IECoreDelightPreview/NodeAlgo.h @@ -44,6 +44,10 @@ #include +// Change this to "IECoreDelight/Export.h" and remove the define when it goes into Cortex. +#include "GafferDelight/Export.h" +#define IECOREDELIGHT_API GAFFERDELIGHT_API + namespace IECoreDelight { @@ -55,10 +59,10 @@ namespace NodeAlgo /// Converts the specified IECore::Object into an equivalent /// NSI node with the specified handle, returning true on /// success and false on failure. -bool convert( const IECore::Object *object, NSIContext_t context, const char *handle ); +IECOREDELIGHT_API bool convert( const IECore::Object *object, NSIContext_t context, const char *handle ); /// As above, but converting a moving object. If no motion converter /// is available, the first sample is converted instead. -bool convert( const std::vector &samples, const std::vector &sampleTimes, NSIContext_t context, const char *handle ); +IECOREDELIGHT_API bool convert( const std::vector &samples, const std::vector &sampleTimes, NSIContext_t context, const char *handle ); /// Signature of a function which can convert an IECore::Object /// into an NSI node. @@ -68,7 +72,7 @@ typedef bool (*MotionConverter)( const std::vector &samp /// Registers a converter for a specific type. /// Use the ConverterDescription utility class in preference to /// this, since it provides additional type safety. -void registerConverter( IECore::TypeId fromType, Converter converter, MotionConverter motionConverter = nullptr ); +IECOREDELIGHT_API void registerConverter( IECore::TypeId fromType, Converter converter, MotionConverter motionConverter = nullptr ); /// Class which registers a converter for type T automatically /// when instantiated. @@ -94,10 +98,10 @@ class ConverterDescription }; /// Adds all PrimitiveVariables into a ParameterList for use with NSISetAttribute. -void primitiveVariableParameterList( const IECoreScene::Primitive *primitive, ParameterList ¶meters, const IECore::IntVectorData *vertexIndices = nullptr ); +IECOREDELIGHT_API void primitiveVariableParameterList( const IECoreScene::Primitive *primitive, ParameterList ¶meters, const IECore::IntVectorData *vertexIndices = nullptr ); /// As above, but splits out animated primitive variables into a separate vector of ParameterLists /// for use with NSISetAttributeAtTime. -void primitiveVariableParameterLists( const std::vector &primitives, ParameterList &staticParameters, std::vector &animatedParameters, const IECore::IntVectorData *vertexIndices = nullptr ); +IECOREDELIGHT_API void primitiveVariableParameterLists( const std::vector &primitives, ParameterList &staticParameters, std::vector &animatedParameters, const IECore::IntVectorData *vertexIndices = nullptr ); } // namespace NodeAlgo diff --git a/include/GafferDelight/IECoreDelightPreview/ParameterList.h b/include/GafferDelight/IECoreDelightPreview/ParameterList.h index 7303d0f0686..fa247394e98 100644 --- a/include/GafferDelight/IECoreDelightPreview/ParameterList.h +++ b/include/GafferDelight/IECoreDelightPreview/ParameterList.h @@ -44,6 +44,10 @@ #include +// Change this to "IECoreDelight/Export.h" and remove the define when it goes into Cortex. +#include "GafferDelight/Export.h" +#define IECOREDELIGHT_API GAFFERDELIGHT_API + namespace IECoreDelight { @@ -51,7 +55,7 @@ namespace IECoreDelight /// NSI API. The ParameterList does not copy any of the data passed /// to it; it is the caller's responsibility to keep all data alive /// for as long as the ParameterList is used. -class ParameterList +class IECOREDELIGHT_API ParameterList { public : diff --git a/include/GafferDispatch/Dispatcher.h b/include/GafferDispatch/Dispatcher.h index 7d37543dcc4..52acafef893 100644 --- a/include/GafferDispatch/Dispatcher.h +++ b/include/GafferDispatch/Dispatcher.h @@ -60,6 +60,7 @@ namespace Gaffer { IE_CORE_FORWARDDECLARE( StringPlug ) +IE_CORE_FORWARDDECLARE( FileSystemPathPlug ) } // namespace Gaffer @@ -170,8 +171,8 @@ class GAFFERDISPATCH_API Dispatcher : public Gaffer::Node const Gaffer::StringPlug *jobNamePlug() const; /// Returns the plug which specifies the directory used by dispatchers to store temporary /// files on a per-job basis. - Gaffer::StringPlug *jobsDirectoryPlug(); - const Gaffer::StringPlug *jobsDirectoryPlug() const; + Gaffer::FileSystemPathPlug *jobsDirectoryPlug(); + const Gaffer::FileSystemPathPlug *jobsDirectoryPlug() const; /// At the start of dispatch(), a directory is created under jobsDirectoryPlug + jobNamePlug /// which the dispatcher writes temporary files to. This method returns the most recent created directory. const std::string jobDirectory() const; @@ -224,7 +225,7 @@ class GAFFERDISPATCH_API Dispatcher : public Gaffer::Node /// All tasks within a batch are from the same plug /// and have identical contexts except for the frame /// number. - class TaskBatch : public IECore::RefCounted + class GAFFERDISPATCH_API TaskBatch : public IECore::RefCounted { public : diff --git a/include/GafferDispatch/TaskNode.h b/include/GafferDispatch/TaskNode.h index ce6c6160910..25e4cc1f4be 100644 --- a/include/GafferDispatch/TaskNode.h +++ b/include/GafferDispatch/TaskNode.h @@ -85,7 +85,7 @@ class GAFFERDISPATCH_API TaskNode : public Gaffer::DependencyNode /// the context in which it should be executed. See TaskPlug /// for the main public interface for the execution of /// individual tasks. - class Task + class GAFFERDISPATCH_API Task { public : @@ -121,7 +121,7 @@ class GAFFERDISPATCH_API TaskNode : public Gaffer::DependencyNode /// Plug type used to represent tasks within the /// node graph. This provides the primary public /// interface for querying and executing tasks. - class TaskPlug : public Gaffer::Plug + class GAFFERDISPATCH_API TaskPlug : public Gaffer::Plug { public : diff --git a/include/GafferDispatchBindings/Export.h b/include/GafferDispatchBindings/Export.h new file mode 100644 index 00000000000..a0cd7338074 --- /dev/null +++ b/include/GafferDispatchBindings/Export.h @@ -0,0 +1,51 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2016, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef GAFFERDISPATCHBINDINGS_EXPORT_H +#define GAFFERDISPATCHBINDINGS_EXPORT_H + +#include "Gaffer/Export.h" + +// define GAFFERDISPATCHBINDINGS_API macro based on whether or not we are compiling +// GafferDispatchBindings, or including headers for linking to it. the GAFFERDISPATCHBINDINGS_API +// macro is the one that is used in the class definitions. +#ifdef GafferDispatchBindings_EXPORTS + #define GAFFERDISPATCHBINDINGS_API GAFFER_EXPORT +#else + #define GAFFERDISPATCHBINDINGS_API GAFFER_IMPORT +#endif + +#endif // #ifndef GAFFERDISPATCHBINDINGS_EXPORT_H diff --git a/include/GafferImage/BufferAlgo.h b/include/GafferImage/BufferAlgo.h index 755ecc30528..830f3969bd3 100644 --- a/include/GafferImage/BufferAlgo.h +++ b/include/GafferImage/BufferAlgo.h @@ -37,7 +37,7 @@ #ifndef GAFFERIMAGE_BUFFERALGO_H #define GAFFERIMAGE_BUFFERALGO_H -#include "IECore/Export.h" +#include "GafferImage/Export.h" IECORE_PUSH_DEFAULT_VISIBILITY #include "OpenEXR/ImathBox.h" diff --git a/include/GafferImage/BufferAlgo.inl b/include/GafferImage/BufferAlgo.inl index 1a42407226e..b67be3c147d 100644 --- a/include/GafferImage/BufferAlgo.inl +++ b/include/GafferImage/BufferAlgo.inl @@ -38,6 +38,7 @@ #define GAFFERIMAGE_BUFFERALGO_INL #include +#include namespace GafferImage { diff --git a/include/GafferImage/Catalogue.h b/include/GafferImage/Catalogue.h index 820229108e0..d93556481bd 100644 --- a/include/GafferImage/Catalogue.h +++ b/include/GafferImage/Catalogue.h @@ -41,6 +41,7 @@ #include "Gaffer/NumericPlug.h" #include "Gaffer/StringPlug.h" +#include "Gaffer/FileSystemPathPlug.h" #include "Gaffer/Switch.h" #include "IECoreImage/DisplayDriver.h" @@ -68,7 +69,7 @@ class GAFFERIMAGE_API Catalogue : public ImageNode ~Catalogue() override; /// Plug type used to represent an image in the catalogue. - class Image : public Gaffer::Plug + class GAFFERIMAGE_API Image : public Gaffer::Plug { public : @@ -77,8 +78,8 @@ class GAFFERIMAGE_API Catalogue : public ImageNode Image( const std::string &name = defaultName(), Direction direction = In, unsigned flags = Default ); - Gaffer::StringPlug *fileNamePlug(); - const Gaffer::StringPlug *fileNamePlug() const; + Gaffer::FileSystemPathPlug *fileNamePlug(); + const Gaffer::FileSystemPathPlug *fileNamePlug() const; Gaffer::StringPlug *descriptionPlug(); const Gaffer::StringPlug *descriptionPlug() const; @@ -117,8 +118,8 @@ class GAFFERIMAGE_API Catalogue : public ImageNode Gaffer::StringPlug *namePlug(); const Gaffer::StringPlug *namePlug() const; - Gaffer::StringPlug *directoryPlug(); - const Gaffer::StringPlug *directoryPlug() const; + Gaffer::FileSystemPathPlug *directoryPlug(); + const Gaffer::FileSystemPathPlug *directoryPlug() const; /// All Catalogues share a single DisplayDriverServer instance /// to receive rendered images. To send an image to the catalogues, diff --git a/include/GafferImage/ColorSpace.h b/include/GafferImage/ColorSpace.h index 5e162050be0..e5b6a9439f1 100644 --- a/include/GafferImage/ColorSpace.h +++ b/include/GafferImage/ColorSpace.h @@ -38,6 +38,7 @@ #ifndef GAFFERIMAGE_COLORSPACE_H #define GAFFERIMAGE_COLORSPACE_H +#include "GafferImage/Export.h" #include "GafferImage/OpenColorIOTransform.h" namespace Gaffer diff --git a/include/GafferImage/CopyImageMetadata.h b/include/GafferImage/CopyImageMetadata.h index b6e235b0ff5..4e3e154c4bc 100644 --- a/include/GafferImage/CopyImageMetadata.h +++ b/include/GafferImage/CopyImageMetadata.h @@ -37,6 +37,7 @@ #ifndef GAFFERIMAGE_COPYIMAGEMETADATA_H #define GAFFERIMAGE_COPYIMAGEMETADATA_H +#include "GafferImage/Export.h" #include "GafferImage/MetadataProcessor.h" #include "Gaffer/StringPlug.h" diff --git a/include/GafferImage/Dilate.h b/include/GafferImage/Dilate.h index 3d88a97e715..7f0f5320e29 100644 --- a/include/GafferImage/Dilate.h +++ b/include/GafferImage/Dilate.h @@ -37,6 +37,7 @@ #ifndef GAFFERIMAGE_DILATE_H #define GAFFERIMAGE_DILATE_H +#include "GafferImage/Export.h" #include "GafferImage/RankFilter.h" namespace GafferImage diff --git a/include/GafferImage/Erode.h b/include/GafferImage/Erode.h index 9bfab274e54..243939eed7b 100644 --- a/include/GafferImage/Erode.h +++ b/include/GafferImage/Erode.h @@ -37,6 +37,7 @@ #ifndef GAFFERIMAGE_ERODE_H #define GAFFERIMAGE_ERODE_H +#include "GafferImage/Export.h" #include "GafferImage/RankFilter.h" namespace GafferImage diff --git a/include/GafferImage/FilterAlgo.h b/include/GafferImage/FilterAlgo.h index 5ac83e34330..3fb7699a943 100644 --- a/include/GafferImage/FilterAlgo.h +++ b/include/GafferImage/FilterAlgo.h @@ -60,7 +60,7 @@ GAFFERIMAGE_API const OIIO::Filter2D* acquireFilter( const std::string &name ); // Find the region covered by a filter with a given width, given a position and axis-aligned derivatives // to compute the bounding rectangle -Imath::Box2f filterSupport( const Imath::V2f &p, float dx, float dy, float filterWidth ); +GAFFERIMAGE_API Imath::Box2f filterSupport( const Imath::V2f &p, float dx, float dy, float filterWidth ); // Filter over a rectangle shaped region of the image defined by a center point and two axis-aligned derivatives. // The sampler must have been initialized to cover all pixels with centers lying with the support of the filter, @@ -77,7 +77,7 @@ GAFFERIMAGE_API float sampleParallelogram( Sampler &sampler, const Imath::V2f &p // If you have a point and derivatives defining a region to filter over, but you want to use sampleBox // instead of sampleParallelogram for performance reasons, you can use this function to get axis-aligned // derivatives which will approximate the result of sampleParallelogram -Imath::V2f derivativesToAxisAligned( const Imath::V2f &p, const Imath::V2f &dpdx, const Imath::V2f &dpdy ); +GAFFERIMAGE_API Imath::V2f derivativesToAxisAligned( const Imath::V2f &p, const Imath::V2f &dpdx, const Imath::V2f &dpdy ); } // namespace FilterAlgo diff --git a/include/GafferImage/FlatImageProcessor.h b/include/GafferImage/FlatImageProcessor.h index eae0948746d..076cb7cf99e 100644 --- a/include/GafferImage/FlatImageProcessor.h +++ b/include/GafferImage/FlatImageProcessor.h @@ -58,7 +58,7 @@ class GAFFERIMAGE_API FlatImageProcessor : public ImageProcessor /// Constructs with an ArrayPlug called "in". Use inPlug() as a /// convenience for accessing the first child in the array, and use /// inPlugs() to access the array itself. - FlatImageProcessor( const std::string &name, size_t minInputs, size_t maxInputs = Imath::limits::max() ); + FlatImageProcessor( const std::string &name, size_t minInputs, size_t maxInputs = std::numeric_limits::max() ); ~FlatImageProcessor() override; GAFFER_NODE_DECLARE_TYPE( GafferImage::FlatImageProcessor, FlatImageProcessorTypeId, ImageProcessor ); diff --git a/include/GafferImage/Format.h b/include/GafferImage/Format.h index 56de1c444e5..dcd7dedd8dd 100644 --- a/include/GafferImage/Format.h +++ b/include/GafferImage/Format.h @@ -49,6 +49,8 @@ IECORE_POP_DEFAULT_VISIBILITY #include #include +#include "GafferImage/Export.h" + namespace GafferImage { diff --git a/include/GafferImage/ImageAlgo.h b/include/GafferImage/ImageAlgo.h index 53db9b4d130..859796c34b2 100644 --- a/include/GafferImage/ImageAlgo.h +++ b/include/GafferImage/ImageAlgo.h @@ -50,6 +50,8 @@ IECORE_POP_DEFAULT_VISIBILITY #include +#include "GafferImage/Export.h" + namespace GafferImage { diff --git a/include/GafferImage/ImagePlug.h b/include/GafferImage/ImagePlug.h index 5fad08c1398..11817cb7764 100644 --- a/include/GafferImage/ImagePlug.h +++ b/include/GafferImage/ImagePlug.h @@ -130,7 +130,7 @@ class GAFFERIMAGE_API ImagePlug : public Gaffer::ValuePlug /// with tile/channel specific variables removed. This can be used /// when evaluating plugs which must be global to the whole image, /// and can improve performance by reducing pressure on the hash cache. - struct GlobalScope : public Gaffer::Context::EditableScope + struct GAFFERIMAGE_API GlobalScope : public Gaffer::Context::EditableScope { GlobalScope( const Gaffer::Context *context ); GlobalScope( const Gaffer::ThreadState &threadState ); @@ -139,7 +139,7 @@ class GAFFERIMAGE_API ImagePlug : public Gaffer::ValuePlug /// Utility class to scope a temporary copy of a context, /// with convenient accessors to set tileOrigin and channelName, /// which you often need to do while accessing channelData - struct ChannelDataScope : public Gaffer::Context::EditableScope + struct GAFFERIMAGE_API ChannelDataScope : public Gaffer::Context::EditableScope { ChannelDataScope( const Gaffer::Context *context ); ChannelDataScope( const Gaffer::ThreadState &threadState ); diff --git a/include/GafferImage/ImageProcessor.h b/include/GafferImage/ImageProcessor.h index 9dc016ec26a..695f74f8f99 100644 --- a/include/GafferImage/ImageProcessor.h +++ b/include/GafferImage/ImageProcessor.h @@ -38,6 +38,9 @@ #ifndef GAFFERIMAGE_IMAGEPROCESSOR_H #define GAFFERIMAGE_IMAGEPROCESSOR_H +#include + +#include "GafferImage/Export.h" #include "GafferImage/ImageNode.h" namespace Gaffer @@ -64,7 +67,7 @@ class GAFFERIMAGE_API ImageProcessor : public ImageNode /// Constructs with an ArrayPlug called "in". Use inPlug() as a /// convenience for accessing the first child in the array, and use /// inPlugs() to access the array itself. - ImageProcessor( const std::string &name, size_t minInputs, size_t maxInputs = Imath::limits::max() ); + ImageProcessor( const std::string &name, size_t minInputs, size_t maxInputs = std::numeric_limits::max() ); ~ImageProcessor() override; GAFFER_NODE_DECLARE_TYPE( GafferImage::ImageProcessor, ImageProcessorTypeId, ImageNode ); diff --git a/include/GafferImage/ImageReader.h b/include/GafferImage/ImageReader.h index a8a1b9f14bb..73c116caf9f 100644 --- a/include/GafferImage/ImageReader.h +++ b/include/GafferImage/ImageReader.h @@ -47,6 +47,7 @@ namespace Gaffer { IE_CORE_FORWARDDECLARE( StringPlug ) +IE_CORE_FORWARDDECLARE( FileSystemPathPlug ) } // namespace Gaffer @@ -87,8 +88,8 @@ class GAFFERIMAGE_API ImageReader : public ImageNode ClampToFrame, }; - Gaffer::StringPlug *fileNamePlug(); - const Gaffer::StringPlug *fileNamePlug() const; + Gaffer::FileSystemPathPlug *fileNamePlug(); + const Gaffer::FileSystemPathPlug *fileNamePlug() const; /// Number of times the node has been refreshed. Gaffer::IntPlug *refreshCountPlug(); diff --git a/include/GafferImage/ImageTransform.h b/include/GafferImage/ImageTransform.h index 44aaaef6036..d7bbc470b33 100644 --- a/include/GafferImage/ImageTransform.h +++ b/include/GafferImage/ImageTransform.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_IMAGETRANSFORM_H #define GAFFERSCENE_IMAGETRANSFORM_H +#include "GafferImage/Export.h" #include "GafferImage/FlatImageProcessor.h" namespace Gaffer diff --git a/include/GafferImage/ImageWriter.h b/include/GafferImage/ImageWriter.h index f8cc57c53b4..9db8da3672b 100644 --- a/include/GafferImage/ImageWriter.h +++ b/include/GafferImage/ImageWriter.h @@ -50,6 +50,7 @@ namespace Gaffer { IE_CORE_FORWARDDECLARE( ValuePlug ) IE_CORE_FORWARDDECLARE( StringPlug ) + IE_CORE_FORWARDDECLARE( FileSystemPathPlug ) } // namespace Gaffer namespace GafferImage @@ -74,8 +75,8 @@ class GAFFERIMAGE_API ImageWriter : public GafferDispatch::TaskNode GAFFER_NODE_DECLARE_TYPE( GafferImage::ImageWriter, ImageWriterTypeId, TaskNode ); - Gaffer::StringPlug *fileNamePlug(); - const Gaffer::StringPlug *fileNamePlug() const; + Gaffer::FileSystemPathPlug *fileNamePlug(); + const Gaffer::FileSystemPathPlug *fileNamePlug() const; GafferImage::ImagePlug *inPlug(); const GafferImage::ImagePlug *inPlug() const; diff --git a/include/GafferImage/LUT.h b/include/GafferImage/LUT.h index 9692ce3e19c..f90b672bb3a 100644 --- a/include/GafferImage/LUT.h +++ b/include/GafferImage/LUT.h @@ -44,7 +44,7 @@ namespace Gaffer { -IE_CORE_FORWARDDECLARE( StringPlug ) +IE_CORE_FORWARDDECLARE( FileSystemPathPlug ) } // namespace Gaffer @@ -75,8 +75,8 @@ class GAFFERIMAGE_API LUT : public OpenColorIOTransform Inverse }; - Gaffer::StringPlug *fileNamePlug(); - const Gaffer::StringPlug *fileNamePlug() const; + Gaffer::FileSystemPathPlug *fileNamePlug(); + const Gaffer::FileSystemPathPlug *fileNamePlug() const; Gaffer::IntPlug *interpolationPlug(); const Gaffer::IntPlug *interpolationPlug() const; diff --git a/include/GafferImage/Median.h b/include/GafferImage/Median.h index 40e6c19e0d6..75799d3d68f 100644 --- a/include/GafferImage/Median.h +++ b/include/GafferImage/Median.h @@ -37,6 +37,7 @@ #ifndef GAFFERIMAGE_MEDIAN_H #define GAFFERIMAGE_MEDIAN_H +#include "GafferImage/Export.h" #include "GafferImage/RankFilter.h" namespace GafferImage diff --git a/include/GafferImage/OpenImageIOReader.h b/include/GafferImage/OpenImageIOReader.h index 6d593d97564..5e2eaf5d820 100644 --- a/include/GafferImage/OpenImageIOReader.h +++ b/include/GafferImage/OpenImageIOReader.h @@ -46,6 +46,7 @@ namespace Gaffer { IE_CORE_FORWARDDECLARE( StringPlug ) +IE_CORE_FORWARDDECLARE( FileSystemPathPlug ) } // namespace Gaffer @@ -69,8 +70,8 @@ class GAFFERIMAGE_API OpenImageIOReader : public ImageNode Hold, }; - Gaffer::StringPlug *fileNamePlug(); - const Gaffer::StringPlug *fileNamePlug() const; + Gaffer::FileSystemPathPlug *fileNamePlug(); + const Gaffer::FileSystemPathPlug *fileNamePlug() const; /// Number of times the node has been refreshed. Gaffer::IntPlug *refreshCountPlug(); diff --git a/include/GafferImage/Shuffle.h b/include/GafferImage/Shuffle.h index b8f52368081..1f12075cf2a 100644 --- a/include/GafferImage/Shuffle.h +++ b/include/GafferImage/Shuffle.h @@ -58,7 +58,7 @@ class GAFFERIMAGE_API Shuffle : public ImageProcessor /// A custom plug to hold the name of an output channel and the /// name of an input channel to shuffle into it. Add instances /// of these to the Shuffle::channelsPlug() to define the shuffle. - class ChannelPlug : public Gaffer::ValuePlug + class GAFFERIMAGE_API ChannelPlug : public Gaffer::ValuePlug { public : diff --git a/include/GafferImage/Text.h b/include/GafferImage/Text.h index c0d6e63eaeb..eac8ce46b1f 100644 --- a/include/GafferImage/Text.h +++ b/include/GafferImage/Text.h @@ -40,6 +40,7 @@ #include "GafferImage/Shape.h" #include "Gaffer/BoxPlug.h" +#include "Gaffer/FileSystemPathPlug.h" namespace Gaffer { @@ -79,8 +80,8 @@ class GAFFERIMAGE_API Text : public Shape Gaffer::StringPlug *textPlug(); const Gaffer::StringPlug *textPlug() const; - Gaffer::StringPlug *fontPlug(); - const Gaffer::StringPlug *fontPlug() const; + Gaffer::FileSystemPathPlug *fontPlug(); + const Gaffer::FileSystemPathPlug *fontPlug() const; Gaffer::V2iPlug *sizePlug(); const Gaffer::V2iPlug *sizePlug() const; diff --git a/include/GafferImage/VectorWarp.h b/include/GafferImage/VectorWarp.h index 7ffce9f65b2..757a9745baf 100644 --- a/include/GafferImage/VectorWarp.h +++ b/include/GafferImage/VectorWarp.h @@ -37,6 +37,7 @@ #ifndef GAFFERIMAGE_UVWARP_H #define GAFFERIMAGE_UVWARP_H +#include "GafferImage/Export.h" #include "GafferImage/Warp.h" namespace GafferImage diff --git a/include/GafferImageTest/ContextSanitiser.h b/include/GafferImageTest/ContextSanitiser.h index fe5d6edd34e..f0cbe0abc72 100644 --- a/include/GafferImageTest/ContextSanitiser.h +++ b/include/GafferImageTest/ContextSanitiser.h @@ -37,6 +37,8 @@ #ifndef GAFFERIMAGETEST_CONTEXTSANITISER_H #define GAFFERIMAGETEST_CONTEXTSANITISER_H +#include "GafferImageTest/Export.h" + #include "Gaffer/Monitor.h" #include "Gaffer/Plug.h" @@ -46,7 +48,7 @@ namespace GafferImageTest { /// A monitor which warns about common context handling mistakes. -class GAFFER_API ContextSanitiser : public Gaffer::Monitor +class GAFFERIMAGETEST_API ContextSanitiser : public Gaffer::Monitor { public : diff --git a/include/GafferImageTest/Export.h b/include/GafferImageTest/Export.h new file mode 100644 index 00000000000..3bfc8695000 --- /dev/null +++ b/include/GafferImageTest/Export.h @@ -0,0 +1,51 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2016, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef GAFFERIMAGETEST_EXPORT_H +#define GAFFERIMAGETEST_EXPORT_H + +#include "IECore/Export.h" + +// define GAFFERIMAGETEST_API macro based on whether or not we are compiling +// GafferImageTest, or including headers for linking to it. the GAFFERIMAGETEST_API +// macro is the one that is used in the class definitions. +#ifdef GafferImageTest_EXPORTS + #define GAFFERIMAGETEST_API IECORE_EXPORT +#else + #define GAFFERIMAGETEST_API IECORE_IMPORT +#endif + +#endif // #ifndef GAFFERIMAGETEST_EXPORT_H diff --git a/include/GafferImageUI/ImageGadget.h b/include/GafferImageUI/ImageGadget.h index 9c23075e07a..c883b8279a7 100644 --- a/include/GafferImageUI/ImageGadget.h +++ b/include/GafferImageUI/ImageGadget.h @@ -246,6 +246,7 @@ class GAFFERIMAGEUI_API ImageGadget : public GafferUI::Gadget // be inserted/updated in parallel in a multithreaded // update step. + public: struct TileIndex { TileIndex( const Imath::V2i &tileOrigin, IECore::InternedString channelName ) @@ -277,6 +278,7 @@ class GAFFERIMAGEUI_API ImageGadget : public GafferUI::Gadget IECore::InternedString channelName; }; + private: struct Tile { diff --git a/include/GafferImageUI/ImageView.h b/include/GafferImageUI/ImageView.h index 3f58ce80067..d8ad9d6b301 100644 --- a/include/GafferImageUI/ImageView.h +++ b/include/GafferImageUI/ImageView.h @@ -117,10 +117,10 @@ class GAFFERIMAGEUI_API ImageView : public GafferUI::View static void registeredDisplayTransforms( std::vector &names ); static GafferImage::ImageProcessorPtr createDisplayTransform( const std::string &name ); - class ColorInspectorPlug : public Gaffer::ValuePlug + class GAFFERIMAGEUI_API ColorInspectorPlug : public Gaffer::ValuePlug { public : - enum class Mode + enum class GAFFERIMAGEUI_API Mode { Cursor, Pixel, diff --git a/include/GafferOSL/OSLCode.h b/include/GafferOSL/OSLCode.h index 539c094e2c7..c4774a55011 100644 --- a/include/GafferOSL/OSLCode.h +++ b/include/GafferOSL/OSLCode.h @@ -37,6 +37,7 @@ #ifndef GAFFEROSL_OSLCODE_H #define GAFFEROSL_OSLCODE_H +#include "GafferOSL/Export.h" #include "GafferOSL/OSLShader.h" namespace GafferOSL diff --git a/include/GafferRenderMan/Export.h b/include/GafferRenderMan/Export.h new file mode 100644 index 00000000000..96d9a9f6166 --- /dev/null +++ b/include/GafferRenderMan/Export.h @@ -0,0 +1,51 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2016, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef GAFFERRENDERMAN_EXPORT_H +#define GAFFERRENDERMAN_EXPORT_H + +#include "Gaffer/Export.h" + +// define GAFFERRENDERMAN_API macro based on whether or not we are compiling +// GafferRenderman, or including headers for linking to it. the GAFFERRENDERMAN_API +// macro is the one that is used in the class definitions. +#ifdef GafferRenderMan_EXPORTS + #define GAFFERRENDERMAN_API GAFFER_EXPORT +#else + #define GAFFERRENDERMAN_API GAFFER_IMPORT +#endif + +#endif // #ifndef GAFFERRENDERMAN_EXPORT_H diff --git a/include/GafferScene/AimConstraint.h b/include/GafferScene/AimConstraint.h index 0032b79d952..b070d201b9d 100644 --- a/include/GafferScene/AimConstraint.h +++ b/include/GafferScene/AimConstraint.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_AIMCONSTRAINT_H #define GAFFERSCENE_AIMCONSTRAINT_H +#include "GafferScene/Export.h" #include "GafferScene/Constraint.h" namespace GafferScene diff --git a/include/GafferScene/AttributeProcessor.h b/include/GafferScene/AttributeProcessor.h index cf5332afac1..f48d829b671 100644 --- a/include/GafferScene/AttributeProcessor.h +++ b/include/GafferScene/AttributeProcessor.h @@ -37,7 +37,15 @@ #ifndef GAFFERSCENE_ATTRIBUTEPROCESSOR_H #define GAFFERSCENE_ATTRIBUTEPROCESSOR_H -#include "GafferScene/FilteredSceneProcessor.h" +#include "GafferScene/SceneElementProcessor.h" +#include "GafferScene/Export.h" + +namespace Gaffer +{ + +IE_CORE_FORWARDDECLARE( StringPlug ) + +} // namespace Gaffer namespace GafferScene { diff --git a/include/GafferScene/Camera.h b/include/GafferScene/Camera.h index cc7facbdf0b..523e73aaa2b 100644 --- a/include/GafferScene/Camera.h +++ b/include/GafferScene/Camera.h @@ -38,6 +38,8 @@ #ifndef GAFFERSCENE_CAMERA_H #define GAFFERSCENE_CAMERA_H +#include "GafferScene/Export.h" + #include "Gaffer/CompoundDataPlug.h" #include "GafferScene/ObjectSource.h" diff --git a/include/GafferScene/ClippingPlane.h b/include/GafferScene/ClippingPlane.h index 1c65a65cabb..d421942520e 100644 --- a/include/GafferScene/ClippingPlane.h +++ b/include/GafferScene/ClippingPlane.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_CLIPPINGPLANE_H #define GAFFERSCENE_CLIPPINGPLANE_H +#include "GafferScene/Export.h" #include "GafferScene/ObjectSource.h" namespace GafferScene diff --git a/include/GafferScene/CollectScenes.h b/include/GafferScene/CollectScenes.h index 2f8f91fbdea..38b09611d23 100644 --- a/include/GafferScene/CollectScenes.h +++ b/include/GafferScene/CollectScenes.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_COLLECTSCENES_H #define GAFFERSCENE_COLLECTSCENES_H +#include "GafferScene/Export.h" #include "GafferScene/SceneProcessor.h" namespace Gaffer diff --git a/include/GafferScene/Constraint.h b/include/GafferScene/Constraint.h index 9514881e43b..d9a53d0dea1 100644 --- a/include/GafferScene/Constraint.h +++ b/include/GafferScene/Constraint.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_CONSTRAINT_H #define GAFFERSCENE_CONSTRAINT_H +#include "GafferScene/Export.h" #include "GafferScene/SceneElementProcessor.h" namespace Gaffer diff --git a/include/GafferScene/CoordinateSystem.h b/include/GafferScene/CoordinateSystem.h index fbdf7ef6d6b..68797871d55 100644 --- a/include/GafferScene/CoordinateSystem.h +++ b/include/GafferScene/CoordinateSystem.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_COORDINATESYSTEM_H #define GAFFERSCENE_COORDINATESYSTEM_H +#include "GafferScene/Export.h" #include "GafferScene/ObjectSource.h" namespace GafferScene diff --git a/include/GafferScene/CustomAttributes.h b/include/GafferScene/CustomAttributes.h index 2befbd9ed77..1c28d79729f 100644 --- a/include/GafferScene/CustomAttributes.h +++ b/include/GafferScene/CustomAttributes.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_CUSTOMATTRIBUTES_H #define GAFFERSCENE_CUSTOMATTRIBUTES_H +#include "GafferScene/Export.h" #include "GafferScene/Attributes.h" namespace GafferScene diff --git a/include/GafferScene/Deformer.h b/include/GafferScene/Deformer.h index 2ea623ec160..61085cab9d2 100644 --- a/include/GafferScene/Deformer.h +++ b/include/GafferScene/Deformer.h @@ -70,7 +70,7 @@ class GAFFERSCENE_API Deformer : public ObjectProcessor /// Constructs with an ArrayPlug called "in". Use inPlug() as a /// convenience for accessing the first child in the array, and use /// inPlugs() to access the array itself. - Deformer( const std::string &name, size_t minInputs, size_t maxInputs = Imath::limits::max() ); + Deformer( const std::string &name, size_t minInputs, size_t maxInputs = std::numeric_limits::max() ); /// Used to determine whether adjusted bounds need to be propagated up to /// all ancestor locations. Default implementation checks the value of `adjustBoundsPlug()` diff --git a/include/GafferScene/DeleteAttributes.h b/include/GafferScene/DeleteAttributes.h index 4805292183f..dce31fa32b6 100644 --- a/include/GafferScene/DeleteAttributes.h +++ b/include/GafferScene/DeleteAttributes.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_DELETEATTRIBUTES_H #define GAFFERSCENE_DELETEATTRIBUTES_H +#include "GafferScene/Export.h" #include "GafferScene/AttributeProcessor.h" #include "Gaffer/StringPlug.h" diff --git a/include/GafferScene/DeleteCurves.h b/include/GafferScene/DeleteCurves.h index 7931540e8d1..37a06491b00 100644 --- a/include/GafferScene/DeleteCurves.h +++ b/include/GafferScene/DeleteCurves.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_DELETECURVES_H #define GAFFERSCENE_DELETECURVES_H +#include "GafferScene/Export.h" #include "GafferScene/Deformer.h" namespace Gaffer diff --git a/include/GafferScene/DeleteFaces.h b/include/GafferScene/DeleteFaces.h index 567025fe06a..eb6ffb37e63 100644 --- a/include/GafferScene/DeleteFaces.h +++ b/include/GafferScene/DeleteFaces.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_DELETEFACES_H #define GAFFERSCENE_DELETEFACES_H +#include "GafferScene/Export.h" #include "GafferScene/Deformer.h" namespace Gaffer diff --git a/include/GafferScene/DeleteGlobals.h b/include/GafferScene/DeleteGlobals.h index 6abeba90766..49bcf74fa98 100644 --- a/include/GafferScene/DeleteGlobals.h +++ b/include/GafferScene/DeleteGlobals.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_DELETEGLOBALS_H #define GAFFERSCENE_DELETEGLOBALS_H +#include "GafferScene/Export.h" #include "GafferScene/GlobalsProcessor.h" namespace Gaffer diff --git a/include/GafferScene/DeleteOptions.h b/include/GafferScene/DeleteOptions.h index a1580b552b7..06393d873df 100644 --- a/include/GafferScene/DeleteOptions.h +++ b/include/GafferScene/DeleteOptions.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_DELETEOPTIONS_H #define GAFFERSCENE_DELETEOPTIONS_H +#include "GafferScene/Export.h" #include "GafferScene/DeleteGlobals.h" namespace GafferScene diff --git a/include/GafferScene/DeleteOutputs.h b/include/GafferScene/DeleteOutputs.h index a07f23a0157..434721f5768 100644 --- a/include/GafferScene/DeleteOutputs.h +++ b/include/GafferScene/DeleteOutputs.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_DELETEOUTPUTS_H #define GAFFERSCENE_DELETEOUTPUTS_H +#include "GafferScene/Export.h" #include "GafferScene/DeleteGlobals.h" namespace GafferScene diff --git a/include/GafferScene/DeletePoints.h b/include/GafferScene/DeletePoints.h index 9e3088062a6..d478936e9e1 100644 --- a/include/GafferScene/DeletePoints.h +++ b/include/GafferScene/DeletePoints.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_DELETEPOINTS_H #define GAFFERSCENE_DELETEPOINTS_H +#include "GafferScene/Export.h" #include "GafferScene/Deformer.h" namespace Gaffer diff --git a/include/GafferScene/DeletePrimitiveVariables.h b/include/GafferScene/DeletePrimitiveVariables.h index 618b42e0fd7..ea2e0fa3d92 100644 --- a/include/GafferScene/DeletePrimitiveVariables.h +++ b/include/GafferScene/DeletePrimitiveVariables.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_DELETEPRIMITIVEVARIABLE_H #define GAFFERSCENE_DELETEPRIMITIVEVARIABLE_H +#include "GafferScene/Export.h" #include "GafferScene/PrimitiveVariableProcessor.h" namespace GafferScene diff --git a/include/GafferScene/DeleteSets.h b/include/GafferScene/DeleteSets.h index 8a6f51e30d7..807cbb70f1c 100644 --- a/include/GafferScene/DeleteSets.h +++ b/include/GafferScene/DeleteSets.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_DELETESETS_H #define GAFFERSCENE_DELETESETS_H +#include "GafferScene/Export.h" #include "GafferScene/SceneProcessor.h" namespace Gaffer diff --git a/include/GafferScene/Encapsulate.h b/include/GafferScene/Encapsulate.h index e550174099a..f10b2d1168a 100644 --- a/include/GafferScene/Encapsulate.h +++ b/include/GafferScene/Encapsulate.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_ENCAPSULATE_H #define GAFFERSCENE_ENCAPSULATE_H +#include "GafferScene/Export.h" #include "GafferScene/FilteredSceneProcessor.h" namespace GafferScene diff --git a/include/GafferScene/ExternalProcedural.h b/include/GafferScene/ExternalProcedural.h index 085dfdb9d5f..c9159c6816d 100644 --- a/include/GafferScene/ExternalProcedural.h +++ b/include/GafferScene/ExternalProcedural.h @@ -40,6 +40,7 @@ #include "GafferScene/ObjectSource.h" #include "Gaffer/CompoundDataPlug.h" +#include "Gaffer/FileSystemPathPlug.h" namespace GafferScene { @@ -54,8 +55,8 @@ class GAFFERSCENE_API ExternalProcedural : public ObjectSource ExternalProcedural( const std::string &name=defaultName() ); ~ExternalProcedural() override; - Gaffer::StringPlug *fileNamePlug(); - const Gaffer::StringPlug *fileNamePlug() const; + Gaffer::FileSystemPathPlug *fileNamePlug(); + const Gaffer::FileSystemPathPlug *fileNamePlug() const; Gaffer::Box3fPlug *boundPlug(); const Gaffer::Box3fPlug *boundPlug() const; diff --git a/include/GafferScene/FilterPlug.h b/include/GafferScene/FilterPlug.h index 954cb436ca7..b979ceda5ee 100644 --- a/include/GafferScene/FilterPlug.h +++ b/include/GafferScene/FilterPlug.h @@ -97,7 +97,7 @@ class GAFFERSCENE_API FilterPlug : public Gaffer::IntPlug static const IECore::InternedString inputSceneContextName; /// Provides the input scene for a filter evaluation - struct SceneScope : public Gaffer::Context::EditableScope + struct GAFFERSCENE_API SceneScope : public Gaffer::Context::EditableScope { SceneScope( const Gaffer::Context *context, const ScenePlug *scenePlug ); private : diff --git a/include/GafferScene/FilterProcessor.h b/include/GafferScene/FilterProcessor.h index c1457d3710c..848ab63e377 100644 --- a/include/GafferScene/FilterProcessor.h +++ b/include/GafferScene/FilterProcessor.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_FILTERPROCESSOR_H #define GAFFERSCENE_FILTERPROCESSOR_H +#include "GafferScene/Export.h" #include "GafferScene/Filter.h" namespace Gaffer @@ -62,7 +63,7 @@ class GAFFERSCENE_API FilterProcessor : public Filter /// Constructs with an ArrayPlug called "in". Use inPlug() as a /// convenience for accessing the first child in the array, and use /// inPlugs() to access the array itself. - FilterProcessor( const std::string &name, size_t minInputs, size_t maxInputs = Imath::limits::max() ); + FilterProcessor( const std::string &name, size_t minInputs, size_t maxInputs = std::numeric_limits::max() ); ~FilterProcessor() override; diff --git a/include/GafferScene/FreezeTransform.h b/include/GafferScene/FreezeTransform.h index c6528b5bc70..50b89356304 100644 --- a/include/GafferScene/FreezeTransform.h +++ b/include/GafferScene/FreezeTransform.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_FREEZETRANSFORM_H #define GAFFERSCENE_FREEZETRANSFORM_H +#include "GafferScene/Export.h" #include "GafferScene/FilteredSceneProcessor.h" namespace GafferScene diff --git a/include/GafferScene/GlobalsProcessor.h b/include/GafferScene/GlobalsProcessor.h index 00af82622cf..3f3f290efe5 100644 --- a/include/GafferScene/GlobalsProcessor.h +++ b/include/GafferScene/GlobalsProcessor.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_GLOBALSPROCESSOR_H #define GAFFERSCENE_GLOBALSPROCESSOR_H +#include "GafferScene/Export.h" #include "GafferScene/SceneProcessor.h" namespace GafferScene diff --git a/include/GafferScene/Group.h b/include/GafferScene/Group.h index 19e526beba1..da3d8d22a33 100644 --- a/include/GafferScene/Group.h +++ b/include/GafferScene/Group.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_GROUP_H #define GAFFERSCENE_GROUP_H +#include "GafferScene/Export.h" #include "GafferScene/SceneProcessor.h" namespace Gaffer diff --git a/include/GafferScene/Instancer.h b/include/GafferScene/Instancer.h index ed8a1134b7f..ef4114d6126 100644 --- a/include/GafferScene/Instancer.h +++ b/include/GafferScene/Instancer.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_INSTANCER_H #define GAFFERSCENE_INSTANCER_H +#include "GafferScene/Export.h" #include "GafferScene/BranchCreator.h" namespace GafferScene @@ -52,7 +53,7 @@ class GAFFERSCENE_API Instancer : public BranchCreator /// Compound plug for representing an image format in a way /// easily edited by users, with individual child plugs for /// each aspect of the format. - class ContextVariablePlug : public Gaffer::ValuePlug + class GAFFERSCENE_API ContextVariablePlug : public Gaffer::ValuePlug { public : diff --git a/include/GafferScene/Isolate.h b/include/GafferScene/Isolate.h index ec0b17c8f94..e544d8882b8 100644 --- a/include/GafferScene/Isolate.h +++ b/include/GafferScene/Isolate.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_ISOLATE_H #define GAFFERSCENE_ISOLATE_H +#include "GafferScene/Export.h" #include "GafferScene/FilteredSceneProcessor.h" namespace Gaffer diff --git a/include/GafferScene/Light.h b/include/GafferScene/Light.h index 51eb90778f4..ad5ae413328 100644 --- a/include/GafferScene/Light.h +++ b/include/GafferScene/Light.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_LIGHT_H #define GAFFERSCENE_LIGHT_H +#include "GafferScene/Export.h" #include "GafferScene/ObjectSource.h" #include "Gaffer/CompoundDataPlug.h" diff --git a/include/GafferScene/LightToCamera.h b/include/GafferScene/LightToCamera.h index 04d126483c6..a70e1fa16a7 100644 --- a/include/GafferScene/LightToCamera.h +++ b/include/GafferScene/LightToCamera.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_LIGHTTOCAMERA_H #define GAFFERSCENE_LIGHTTOCAMERA_H +#include "GafferScene/Export.h" #include "GafferScene/SceneElementProcessor.h" namespace GafferScene diff --git a/include/GafferScene/MapOffset.h b/include/GafferScene/MapOffset.h index d3aabe73af9..ef775cbfaaa 100644 --- a/include/GafferScene/MapOffset.h +++ b/include/GafferScene/MapOffset.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_MAPOFFSET_H #define GAFFERSCENE_MAPOFFSET_H +#include "GafferScene/Export.h" #include "GafferScene/ObjectProcessor.h" namespace Gaffer diff --git a/include/GafferScene/MapProjection.h b/include/GafferScene/MapProjection.h index 333576478c3..1fbac650573 100644 --- a/include/GafferScene/MapProjection.h +++ b/include/GafferScene/MapProjection.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_MAPPROJECTION_H #define GAFFERSCENE_MAPPROJECTION_H +#include "GafferScene/Export.h" #include "GafferScene/ObjectProcessor.h" namespace Gaffer diff --git a/include/GafferScene/MeshTangents.h b/include/GafferScene/MeshTangents.h index 95a61cbd431..f5419ec530d 100644 --- a/include/GafferScene/MeshTangents.h +++ b/include/GafferScene/MeshTangents.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_MESHTANGENTS_H #define GAFFERSCENE_MESHTANGENTS_H +#include "GafferScene/Export.h" #include "GafferScene/ObjectProcessor.h" #include "Gaffer/StringPlug.h" diff --git a/include/GafferScene/MeshToPoints.h b/include/GafferScene/MeshToPoints.h index e3d3d868f7e..3ca243b5570 100644 --- a/include/GafferScene/MeshToPoints.h +++ b/include/GafferScene/MeshToPoints.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_MESHTOPOINTS_H #define GAFFERSCENE_MESHTOPOINTS_H +#include "GafferScene/Export.h" #include "GafferScene/Deformer.h" namespace Gaffer diff --git a/include/GafferScene/MeshType.h b/include/GafferScene/MeshType.h index 1e48983fb3b..dedfba609c3 100644 --- a/include/GafferScene/MeshType.h +++ b/include/GafferScene/MeshType.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_MESHTYPE_H #define GAFFERSCENE_MESHTYPE_H +#include "GafferScene/Export.h" #include "GafferScene/ObjectProcessor.h" namespace Gaffer diff --git a/include/GafferScene/ObjectProcessor.h b/include/GafferScene/ObjectProcessor.h index fea4ec68eee..72d57b1767f 100644 --- a/include/GafferScene/ObjectProcessor.h +++ b/include/GafferScene/ObjectProcessor.h @@ -66,7 +66,7 @@ class GAFFERSCENE_API ObjectProcessor : public FilteredSceneProcessor /// Constructs with an ArrayPlug called "in". Use inPlug() as a /// convenience for accessing the first child in the array, and use /// inPlugs() to access the array itself. - ObjectProcessor( const std::string &name, size_t minInputs, size_t maxInputs = Imath::limits::max() ); + ObjectProcessor( const std::string &name, size_t minInputs, size_t maxInputs = std::numeric_limits::max() ); /// Must be implemented by derived classes to return true if `input` is used /// by `computeProcessedObject()`. Overrides must start by calling the base diff --git a/include/GafferScene/ObjectToScene.h b/include/GafferScene/ObjectToScene.h index 7bbc44cd0f0..fee894643d7 100644 --- a/include/GafferScene/ObjectToScene.h +++ b/include/GafferScene/ObjectToScene.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_OBJECTTOSCENE_H #define GAFFERSCENE_OBJECTTOSCENE_H +#include "GafferScene/Export.h" #include "GafferScene/ObjectSource.h" namespace GafferScene diff --git a/include/GafferScene/OpenGLAttributes.h b/include/GafferScene/OpenGLAttributes.h index 798df8aa35c..3628d5f3128 100644 --- a/include/GafferScene/OpenGLAttributes.h +++ b/include/GafferScene/OpenGLAttributes.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_OPENGLATTRIBUTES_H #define GAFFERSCENE_OPENGLATTRIBUTES_H +#include "GafferScene/Export.h" #include "GafferScene/Attributes.h" namespace GafferScene diff --git a/include/GafferScene/OpenGLRender.h b/include/GafferScene/OpenGLRender.h index 52c49294355..301d4cdfac0 100644 --- a/include/GafferScene/OpenGLRender.h +++ b/include/GafferScene/OpenGLRender.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_OPENGLRENDER_H #define GAFFERSCENE_OPENGLRENDER_H +#include "GafferScene/Export.h" #include "GafferScene/Render.h" namespace GafferScene diff --git a/include/GafferScene/OpenGLShader.h b/include/GafferScene/OpenGLShader.h index f3786213362..282a26b9902 100644 --- a/include/GafferScene/OpenGLShader.h +++ b/include/GafferScene/OpenGLShader.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_OPENGLSHADER_H #define GAFFERSCENE_OPENGLSHADER_H +#include "GafferScene/Export.h" #include "GafferScene/Shader.h" namespace GafferScene diff --git a/include/GafferScene/Parent.h b/include/GafferScene/Parent.h index 2877dc4a18e..c9e42ee26ea 100644 --- a/include/GafferScene/Parent.h +++ b/include/GafferScene/Parent.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_PARENT_H #define GAFFERSCENE_PARENT_H +#include "GafferScene/Export.h" #include "GafferScene/BranchCreator.h" #include "Gaffer/ArrayPlug.h" diff --git a/include/GafferScene/PointConstraint.h b/include/GafferScene/PointConstraint.h index f5068f1d377..ff68bd26ac8 100644 --- a/include/GafferScene/PointConstraint.h +++ b/include/GafferScene/PointConstraint.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_POINTCONSTRAINT_H #define GAFFERSCENE_POINTCONSTRAINT_H +#include "GafferScene/Export.h" #include "GafferScene/Constraint.h" namespace GafferScene diff --git a/include/GafferScene/PointsType.h b/include/GafferScene/PointsType.h index 81c57ce4e38..aac6176acf5 100644 --- a/include/GafferScene/PointsType.h +++ b/include/GafferScene/PointsType.h @@ -37,6 +37,8 @@ #ifndef GAFFERSCENE_POINTSTYPE_H #define GAFFERSCENE_POINTSTYPE_H +#include "GafferScene/Export.h" + #include "GafferScene/ObjectProcessor.h" namespace Gaffer diff --git a/include/GafferScene/Private/IECoreScenePreview/CapturingRenderer.h b/include/GafferScene/Private/IECoreScenePreview/CapturingRenderer.h index 18a1f9bfeae..583d8eb7c99 100644 --- a/include/GafferScene/Private/IECoreScenePreview/CapturingRenderer.h +++ b/include/GafferScene/Private/IECoreScenePreview/CapturingRenderer.h @@ -54,7 +54,7 @@ namespace IECoreScenePreview /// If the Bool `cr:unrenderable` attribute is set to true at a location, then /// calls to object, light, lightFilter, camera, etc... for that location will /// return nullptr rather than a valid ObjectInterface. -class IECORESCENE_API CapturingRenderer : public Renderer +class GAFFERSCENE_API CapturingRenderer : public Renderer { public : @@ -71,7 +71,7 @@ class IECORESCENE_API CapturingRenderer : public Renderer /// Introspection /// ============= - class CapturedAttributes : public AttributesInterface + class GAFFERSCENE_API CapturedAttributes : public AttributesInterface { public : @@ -92,7 +92,7 @@ class IECORESCENE_API CapturingRenderer : public Renderer IE_CORE_DECLAREPTR( CapturedAttributes ); - class CapturedObject : public ObjectInterface + class GAFFERSCENE_API CapturedObject : public ObjectInterface { public : diff --git a/include/GafferScene/Private/IECoreScenePreview/Geometry.h b/include/GafferScene/Private/IECoreScenePreview/Geometry.h index 416bcc91d02..3944e861026 100644 --- a/include/GafferScene/Private/IECoreScenePreview/Geometry.h +++ b/include/GafferScene/Private/IECoreScenePreview/Geometry.h @@ -35,6 +35,8 @@ #ifndef IECORE_GEOMETRY_H #define IECORE_GEOMETRY_H +#include "GafferScene/Export.h" + #include "GafferScene/TypeIds.h" #include "IECoreScene/VisibleRenderable.h" @@ -44,7 +46,7 @@ namespace IECoreScenePreview /// Class used to represent additional geometry types supported /// by specific renderers but not present in Cortex (think RiGeometry). -class IECORESCENE_API Geometry : public IECoreScene::VisibleRenderable +class GAFFERSCENE_API Geometry : public IECoreScene::VisibleRenderable { public: diff --git a/include/GafferScene/Private/IECoreScenePreview/Procedural.h b/include/GafferScene/Private/IECoreScenePreview/Procedural.h index 6dddf0c8a84..c882ce14b3d 100644 --- a/include/GafferScene/Private/IECoreScenePreview/Procedural.h +++ b/include/GafferScene/Private/IECoreScenePreview/Procedural.h @@ -37,6 +37,8 @@ #ifndef IECORESCENEPREVIEW_PROCEDURAL_H #define IECORESCENEPREVIEW_PROCEDURAL_H +#include "GafferScene/Export.h" + #include "GafferScene/TypeIds.h" #include "IECoreScene/VisibleRenderable.h" @@ -48,7 +50,7 @@ class Renderer; /// \todo Would it be useful to have a virtual function that returns an /// ExternalProcedural, for use when serialising scenes? -class IECORESCENE_API Procedural : public IECoreScene::VisibleRenderable +class GAFFERSCENE_API Procedural : public IECoreScene::VisibleRenderable { public : diff --git a/include/GafferScene/Private/IECoreScenePreview/Renderer.h b/include/GafferScene/Private/IECoreScenePreview/Renderer.h index a4cb355a2d0..3517985d094 100644 --- a/include/GafferScene/Private/IECoreScenePreview/Renderer.h +++ b/include/GafferScene/Private/IECoreScenePreview/Renderer.h @@ -37,6 +37,8 @@ #ifndef IECORESCENEPREVIEW_RENDERER_H #define IECORESCENEPREVIEW_RENDERER_H +#include "GafferScene/Export.h" + #include "IECoreScene/Camera.h" #include "IECoreScene/Output.h" @@ -70,12 +72,12 @@ namespace IECoreScenePreview /// - Change the python bindings so that the lifetime of the object /// handles and the renderer are tied together, or have the object /// handles keep the renderer alive on the C++ side anyway. -class IECORESCENE_API Renderer : public IECore::RefCounted +class GAFFERSCENE_API Renderer : public IECore::RefCounted { public : - enum RenderType + enum GAFFERSCENE_API RenderType { /// Locations are emitted to the renderer immediately /// and not retained for later editing. @@ -119,7 +121,7 @@ class IECORESCENE_API Renderer : public IECore::RefCounted /// A handle to a block of attributes. Currently all /// AttributesInterfaces _must_ be destroyed prior /// to destruction of the renderer itself. - class AttributesInterface : public IECore::RefCounted + class GAFFERSCENE_API AttributesInterface : public IECore::RefCounted { public : @@ -167,7 +169,7 @@ class IECORESCENE_API Renderer : public IECore::RefCounted /// /// Currently all ObjectInterfaces _must_ be destroyed prior to destruction /// of the renderer itself. - class ObjectInterface : public IECore::RefCounted + class GAFFERSCENE_API ObjectInterface : public IECore::RefCounted { public : diff --git a/include/GafferScene/Prune.h b/include/GafferScene/Prune.h index b10e7af62c7..66fa8c49004 100644 --- a/include/GafferScene/Prune.h +++ b/include/GafferScene/Prune.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_PRUNE_H #define GAFFERSCENE_PRUNE_H +#include "GafferScene/Export.h" #include "GafferScene/FilteredSceneProcessor.h" namespace GafferScene diff --git a/include/GafferScene/Render.h b/include/GafferScene/Render.h index 0780bf39bc3..fbbe051c7d8 100644 --- a/include/GafferScene/Render.h +++ b/include/GafferScene/Render.h @@ -44,6 +44,7 @@ #include "Gaffer/NumericPlug.h" #include "Gaffer/StringPlug.h" +#include "Gaffer/FileSystemPathPlug.h" namespace GafferScene { @@ -75,8 +76,8 @@ class GAFFERSCENE_API Render : public GafferDispatch::TaskNode Gaffer::IntPlug *modePlug(); const Gaffer::IntPlug *modePlug() const; - Gaffer::StringPlug *fileNamePlug(); - const Gaffer::StringPlug *fileNamePlug() const; + Gaffer::FileSystemPathPlug *fileNamePlug(); + const Gaffer::FileSystemPathPlug *fileNamePlug() const; ScenePlug *outPlug(); const ScenePlug *outPlug() const; diff --git a/include/GafferScene/ResamplePrimitiveVariables.h b/include/GafferScene/ResamplePrimitiveVariables.h index 9fab1cfed03..e05a26f1012 100644 --- a/include/GafferScene/ResamplePrimitiveVariables.h +++ b/include/GafferScene/ResamplePrimitiveVariables.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_RESAMPLEPRIMITIVEVARIABLES_H #define GAFFERSCENE_RESAMPLEPRIMITIVEVARIABLES_H +#include "GafferScene/Export.h" #include "GafferScene/PrimitiveVariableProcessor.h" namespace GafferScene diff --git a/include/GafferScene/SceneElementProcessor.h b/include/GafferScene/SceneElementProcessor.h index 60c4c54463e..aca3e5ceab1 100644 --- a/include/GafferScene/SceneElementProcessor.h +++ b/include/GafferScene/SceneElementProcessor.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_SCENEELEMENTPROCESSOR_H #define GAFFERSCENE_SCENEELEMENTPROCESSOR_H +#include "GafferScene/Export.h" #include "GafferScene/FilteredSceneProcessor.h" namespace GafferScene diff --git a/include/GafferScene/ScenePlug.h b/include/GafferScene/ScenePlug.h index f9542b9d13d..a05521da19e 100644 --- a/include/GafferScene/ScenePlug.h +++ b/include/GafferScene/ScenePlug.h @@ -153,7 +153,7 @@ class GAFFERSCENE_API ScenePlug : public Gaffer::ValuePlug /// Utility class to scope a temporary copy of a context, /// specifying the scene path. - struct PathScope : public Gaffer::Context::EditableScope + struct GAFFERSCENE_API PathScope : public Gaffer::Context::EditableScope { /// NOTE : Any of these calls which take a pointer are fast versions which require /// the caller to keep the source memory valid for the lifetime of the PathScope. @@ -178,7 +178,7 @@ class GAFFERSCENE_API ScenePlug : public Gaffer::ValuePlug /// Utility class to scope a temporary copy of a context, /// specifying the set name. - struct SetScope : public Gaffer::Context::EditableScope + struct GAFFERSCENE_API SetScope : public Gaffer::Context::EditableScope { /// NOTE : Any of these calls which take a pointer are fast versions which require /// the caller to keep the source memory valid for the lifetime of the SetScope. @@ -206,7 +206,7 @@ class GAFFERSCENE_API ScenePlug : public Gaffer::ValuePlug /// when evaluating plugs which must not be sensitive /// to such variables, and can improve performance by /// reducing pressure on the hash cache. - struct GlobalScope : public Gaffer::Context::EditableScope + struct GAFFERSCENE_API GlobalScope : public Gaffer::Context::EditableScope { /// Standard constructor, for modifying context on the current thread. GlobalScope( const Gaffer::Context *context ); @@ -302,6 +302,6 @@ IE_CORE_DECLAREPTR( ScenePlug ); } // namespace GafferScene -GAFFERSCENE_API std::ostream &operator << ( std::ostream &o, const GafferScene::ScenePlug::ScenePath &path ); +std::ostream &operator << ( std::ostream &o, const GafferScene::ScenePlug::ScenePath &path ); #endif // GAFFERSCENE_SCENEPLUG_H diff --git a/include/GafferScene/SceneProcessor.h b/include/GafferScene/SceneProcessor.h index 9ba6f50dbe7..2c02c49126d 100644 --- a/include/GafferScene/SceneProcessor.h +++ b/include/GafferScene/SceneProcessor.h @@ -38,6 +38,9 @@ #ifndef GAFFERSCENE_SCENEPROCESSOR_H #define GAFFERSCENE_SCENEPROCESSOR_H +#include + +#include "GafferScene/Export.h" #include "GafferScene/SceneNode.h" namespace Gaffer @@ -63,7 +66,7 @@ class GAFFERSCENE_API SceneProcessor : public SceneNode /// Constructs with an ArrayPlug called "in". Use inPlug() as a /// convenience for accessing the first child in the array, and use /// inPlugs() to access the array itself. - SceneProcessor( const std::string &name, size_t minInputs, size_t maxInputs = Imath::limits::max() ); + SceneProcessor( const std::string &name, size_t minInputs, size_t maxInputs = std::numeric_limits::max() ); ~SceneProcessor() override; diff --git a/include/GafferScene/SceneReader.h b/include/GafferScene/SceneReader.h index 12315c55cd9..fe2aae613f2 100644 --- a/include/GafferScene/SceneReader.h +++ b/include/GafferScene/SceneReader.h @@ -47,6 +47,7 @@ namespace Gaffer { IE_CORE_FORWARDDECLARE( StringPlug ) +IE_CORE_FORWARDDECLARE( FileSystemPathPlug ) IE_CORE_FORWARDDECLARE( TransformPlug ) } // namespace Gaffer @@ -65,8 +66,8 @@ class GAFFERSCENE_API SceneReader : public SceneNode GAFFER_NODE_DECLARE_TYPE( GafferScene::SceneReader, SceneReaderTypeId, SceneNode ) /// Holds the name of the file to be loaded. - Gaffer::StringPlug *fileNamePlug(); - const Gaffer::StringPlug *fileNamePlug() const; + Gaffer::FileSystemPathPlug *fileNamePlug(); + const Gaffer::FileSystemPathPlug *fileNamePlug() const; /// Number of times the node has been refreshed. Gaffer::IntPlug *refreshCountPlug(); diff --git a/include/GafferScene/SceneWriter.h b/include/GafferScene/SceneWriter.h index 13a5ad9702b..91c0061d5d9 100644 --- a/include/GafferScene/SceneWriter.h +++ b/include/GafferScene/SceneWriter.h @@ -44,6 +44,7 @@ #include "Gaffer/TypedPlug.h" #include "Gaffer/StringPlug.h" +#include "Gaffer/FileSystemPathPlug.h" #include "IECoreScene/SceneInterface.h" @@ -60,8 +61,8 @@ class GAFFERSCENE_API SceneWriter : public GafferDispatch::TaskNode GAFFER_NODE_DECLARE_TYPE( GafferScene::SceneWriter, SceneWriterTypeId, GafferDispatch::TaskNode ); - Gaffer::StringPlug *fileNamePlug(); - const Gaffer::StringPlug *fileNamePlug() const; + Gaffer::FileSystemPathPlug *fileNamePlug(); + const Gaffer::FileSystemPathPlug *fileNamePlug() const; ScenePlug *inPlug(); const ScenePlug *inPlug() const; diff --git a/include/GafferScene/Seeds.h b/include/GafferScene/Seeds.h index ddc51fb2e41..6a9e6b5d4e3 100644 --- a/include/GafferScene/Seeds.h +++ b/include/GafferScene/Seeds.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_SEEDS_H #define GAFFERSCENE_SEEDS_H +#include "GafferScene/Export.h" #include "GafferScene/BranchCreator.h" namespace GafferScene diff --git a/include/GafferScene/ShaderAssignment.h b/include/GafferScene/ShaderAssignment.h index c31ef981e77..452137f0486 100644 --- a/include/GafferScene/ShaderAssignment.h +++ b/include/GafferScene/ShaderAssignment.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_SHADERASSIGNMENT_H #define GAFFERSCENE_SHADERASSIGNMENT_H +#include "GafferScene/Export.h" #include "GafferScene/AttributeProcessor.h" #include "GafferScene/ShaderPlug.h" diff --git a/include/GafferScene/StandardAttributes.h b/include/GafferScene/StandardAttributes.h index 77cb597794a..37337c078db 100644 --- a/include/GafferScene/StandardAttributes.h +++ b/include/GafferScene/StandardAttributes.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_STANDARDATTRIBUTES_H #define GAFFERSCENE_STANDARDATTRIBUTES_H +#include "GafferScene/Export.h" #include "GafferScene/Attributes.h" namespace GafferScene diff --git a/include/GafferScene/StandardOptions.h b/include/GafferScene/StandardOptions.h index 914b6cd2647..35f7a9f70fb 100644 --- a/include/GafferScene/StandardOptions.h +++ b/include/GafferScene/StandardOptions.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_STANDARDOPTIONS_H #define GAFFERSCENE_STANDARDOPTIONS_H +#include "GafferScene/Export.h" #include "GafferScene/Options.h" namespace GafferScene diff --git a/include/GafferScene/SubTree.h b/include/GafferScene/SubTree.h index fc7a391a81f..203c26d9e8d 100644 --- a/include/GafferScene/SubTree.h +++ b/include/GafferScene/SubTree.h @@ -38,6 +38,7 @@ #ifndef GAFFERSCENE_SUBTREE_H #define GAFFERSCENE_SUBTREE_H +#include "GafferScene/Export.h" #include "GafferScene/SceneProcessor.h" #include "Gaffer/StringPlug.h" diff --git a/include/GafferScene/Text.h b/include/GafferScene/Text.h index 5dd48a527f6..87776a783db 100644 --- a/include/GafferScene/Text.h +++ b/include/GafferScene/Text.h @@ -37,7 +37,9 @@ #ifndef GAFFERSCENE_TEXT_H #define GAFFERSCENE_TEXT_H +#include "GafferScene/Export.h" #include "GafferScene/ObjectSource.h" +#include "Gaffer/FileSystemPathPlug.h" namespace GafferScene { @@ -55,8 +57,8 @@ class GAFFERSCENE_API Text : public ObjectSource Gaffer::StringPlug *textPlug(); const Gaffer::StringPlug *textPlug() const; - Gaffer::StringPlug *fontPlug(); - const Gaffer::StringPlug *fontPlug() const; + Gaffer::FileSystemPathPlug *fontPlug(); + const Gaffer::FileSystemPathPlug *fontPlug() const; void affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const override; diff --git a/include/GafferScene/UnionFilter.h b/include/GafferScene/UnionFilter.h index 3bb46dabe75..f4d9c5b1fff 100644 --- a/include/GafferScene/UnionFilter.h +++ b/include/GafferScene/UnionFilter.h @@ -37,6 +37,7 @@ #ifndef GAFFERSCENE_UNIONFILTER_H #define GAFFERSCENE_UNIONFILTER_H +#include "GafferScene/Export.h" #include "GafferScene/FilterProcessor.h" namespace GafferScene diff --git a/include/GafferSceneTest/ContextSanitiser.h b/include/GafferSceneTest/ContextSanitiser.h index 4fa8bb0ec53..33d86c3740b 100644 --- a/include/GafferSceneTest/ContextSanitiser.h +++ b/include/GafferSceneTest/ContextSanitiser.h @@ -37,6 +37,8 @@ #ifndef GAFFERSCENETEST_CONTEXTSANITISER_H #define GAFFERSCENETEST_CONTEXTSANITISER_H +#include "GafferSceneTest/Export.h" + #include "Gaffer/Monitor.h" #include "Gaffer/Plug.h" @@ -46,7 +48,7 @@ namespace GafferSceneTest { /// A monitor which warns about common context handling mistakes. -class GAFFER_API ContextSanitiser : public Gaffer::Monitor +class GAFFERSCENETEST_API ContextSanitiser : public Gaffer::Monitor { public : diff --git a/include/GafferSceneUI/TransformTool.h b/include/GafferSceneUI/TransformTool.h index 9c00db9c831..ab534fc2a4a 100644 --- a/include/GafferSceneUI/TransformTool.h +++ b/include/GafferSceneUI/TransformTool.h @@ -73,7 +73,7 @@ class GAFFERSCENEUI_API TransformTool : public GafferSceneUI::SelectionTool Gaffer::FloatPlug *sizePlug(); const Gaffer::FloatPlug *sizePlug() const; - struct Selection + struct GAFFERSCENEUI_API Selection { // Constructs an empty selection. diff --git a/include/GafferSceneUI/UVView.h b/include/GafferSceneUI/UVView.h index 32be86f8ce9..c5928745cc1 100644 --- a/include/GafferSceneUI/UVView.h +++ b/include/GafferSceneUI/UVView.h @@ -48,6 +48,7 @@ #include "Gaffer/BackgroundTask.h" #include "Gaffer/StringPlug.h" +#include "Gaffer/FileSystemPathPlug.h" #include @@ -71,8 +72,8 @@ class GAFFERSCENEUI_API UVView : public GafferUI::View Gaffer::StringPlug *uvSetPlug(); const Gaffer::StringPlug *uvSetPlug() const; - Gaffer::StringPlug *textureFileNamePlug(); - const Gaffer::StringPlug *textureFileNamePlug() const; + Gaffer::FileSystemPathPlug *textureFileNamePlug(); + const Gaffer::FileSystemPathPlug *textureFileNamePlug() const; Gaffer::StringPlug *displayTransformPlug(); const Gaffer::StringPlug *displayTransformPlug() const; diff --git a/include/GafferUI/ButtonEvent.h b/include/GafferUI/ButtonEvent.h index 8b46fc0139d..51eb3ec19f7 100644 --- a/include/GafferUI/ButtonEvent.h +++ b/include/GafferUI/ButtonEvent.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_BUTTONEVENT_H #define GAFFERUI_BUTTONEVENT_H +#include "GafferUI/Export.h" #include "GafferUI/ModifiableEvent.h" #include "IECore/LineSegment.h" diff --git a/include/GafferUI/ContainerGadget.h b/include/GafferUI/ContainerGadget.h index cb1c29ac73d..b42a3bebc5b 100644 --- a/include/GafferUI/ContainerGadget.h +++ b/include/GafferUI/ContainerGadget.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_CONTAINERGADGET_H #define GAFFERUI_CONTAINERGADGET_H +#include "GafferUI/Export.h" #include "GafferUI/Gadget.h" namespace GafferUI diff --git a/include/GafferUI/DragDropEvent.h b/include/GafferUI/DragDropEvent.h index a920ea4ddb1..ebf176d52a1 100644 --- a/include/GafferUI/DragDropEvent.h +++ b/include/GafferUI/DragDropEvent.h @@ -37,6 +37,7 @@ #ifndef GAFFERUI_DRAGDROPEVENT_H #define GAFFERUI_DRAGDROPEVENT_H +#include "GafferUI/Export.h" #include "GafferUI/ButtonEvent.h" #include "IECore/RunTimeTyped.h" diff --git a/include/GafferUI/Frame.h b/include/GafferUI/Frame.h index ebb4ef8a0a6..f6f32888803 100644 --- a/include/GafferUI/Frame.h +++ b/include/GafferUI/Frame.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_FRAME_H #define GAFFERUI_FRAME_H +#include "GafferUI/Export.h" #include "GafferUI/IndividualContainer.h" namespace GafferUI diff --git a/include/GafferUI/GraphGadget.h b/include/GafferUI/GraphGadget.h index 2327583d3a0..6e127035105 100644 --- a/include/GafferUI/GraphGadget.h +++ b/include/GafferUI/GraphGadget.h @@ -144,24 +144,24 @@ class GAFFERUI_API GraphGadget : public ContainerGadget /// \note Here "upstream" nodes are defined as nodes at the end of input /// connections as shown in the graph - auxiliary connections and /// invisible nodes are not considered at all. - size_t upstreamNodeGadgets( const Gaffer::Node *node, std::vector &upstreamNodeGadgets, size_t degreesOfSeparation = Imath::limits::max() ); - size_t upstreamNodeGadgets( const Gaffer::Node *node, std::vector &upstreamNodeGadgets, size_t degreesOfSeparation = Imath::limits::max() ) const; + size_t upstreamNodeGadgets( const Gaffer::Node *node, std::vector &upstreamNodeGadgets, size_t degreesOfSeparation = std::numeric_limits::max() ); + size_t upstreamNodeGadgets( const Gaffer::Node *node, std::vector &upstreamNodeGadgets, size_t degreesOfSeparation = std::numeric_limits::max() ) const; /// Finds all the downstream NodeGadgets connected to the specified node /// and appends them to the specified vector. Returns the new size of the vector. /// \note Here "downstream" nodes are defined as nodes at the end of output /// connections as shown in the graph - auxiliary connections and /// invisible nodes are not considered at all. - size_t downstreamNodeGadgets( const Gaffer::Node *node, std::vector &downstreamNodeGadgets, size_t degreesOfSeparation = Imath::limits::max() ); - size_t downstreamNodeGadgets( const Gaffer::Node *node, std::vector &downstreamNodeGadgets, size_t degreesOfSeparation = Imath::limits::max() ) const; + size_t downstreamNodeGadgets( const Gaffer::Node *node, std::vector &downstreamNodeGadgets, size_t degreesOfSeparation = std::numeric_limits::max() ); + size_t downstreamNodeGadgets( const Gaffer::Node *node, std::vector &downstreamNodeGadgets, size_t degreesOfSeparation = std::numeric_limits::max() ) const; /// Finds all the NodeGadgets connected to the specified node /// and appends them to the specified vector. Returns the new size of the vector. /// \note Here "connected" nodes are defined as nodes at the end of /// connections as shown in the graph - auxiliary connections and /// invisible nodes are not considered at all. - size_t connectedNodeGadgets( const Gaffer::Node *node, std::vector &connectedNodeGadgets, Gaffer::Plug::Direction direction = Gaffer::Plug::Invalid, size_t degreesOfSeparation = Imath::limits::max() ); - size_t connectedNodeGadgets( const Gaffer::Node *node, std::vector &connectedNodeGadgets, Gaffer::Plug::Direction direction = Gaffer::Plug::Invalid, size_t degreesOfSeparation = Imath::limits::max() ) const; + size_t connectedNodeGadgets( const Gaffer::Node *node, std::vector &connectedNodeGadgets, Gaffer::Plug::Direction direction = Gaffer::Plug::Invalid, size_t degreesOfSeparation = std::numeric_limits::max() ); + size_t connectedNodeGadgets( const Gaffer::Node *node, std::vector &connectedNodeGadgets, Gaffer::Plug::Direction direction = Gaffer::Plug::Invalid, size_t degreesOfSeparation = std::numeric_limits::max() ) const; /// Finds all the NodeGadgets which haven't been given an explicit position /// using setNodePosition(). diff --git a/include/GafferUI/Handle.h b/include/GafferUI/Handle.h index 029047e0896..e8352e53431 100644 --- a/include/GafferUI/Handle.h +++ b/include/GafferUI/Handle.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_HANDLE_H #define GAFFERUI_HANDLE_H +#include "GafferUI/Export.h" #include "GafferUI/Gadget.h" #include "GafferUI/Style.h" @@ -85,7 +86,7 @@ class GAFFERUI_API Handle : public Gadget // Helper for performing linear drags. Should be constructed // in `dragBegin()` and then `position()` should be used // to measure the progress of the drag. - struct LinearDrag + struct GAFFERUI_API LinearDrag { LinearDrag( bool processModifiers = true ); @@ -117,7 +118,7 @@ class GAFFERUI_API Handle : public Gadget }; // Helper for performing drags in a plane. - struct PlanarDrag + struct GAFFERUI_API PlanarDrag { PlanarDrag( bool processModifiers = true ); diff --git a/include/GafferUI/IndividualContainer.h b/include/GafferUI/IndividualContainer.h index 0f5946d3850..a14981f6c78 100644 --- a/include/GafferUI/IndividualContainer.h +++ b/include/GafferUI/IndividualContainer.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_INDIVIDUALCONTAINER_H #define GAFFERUI_INDIVIDUALCONTAINER_H +#include "GafferUI/Export.h" #include "GafferUI/ContainerGadget.h" namespace GafferUI diff --git a/include/GafferUI/KeyEvent.h b/include/GafferUI/KeyEvent.h index 20a16e23f18..d12a7e2a70f 100644 --- a/include/GafferUI/KeyEvent.h +++ b/include/GafferUI/KeyEvent.h @@ -37,6 +37,7 @@ #ifndef GAFFERUI_KEYEVENT_H #define GAFFERUI_KEYEVENT_H +#include "GafferUI/Export.h" #include "GafferUI/ModifiableEvent.h" #include "IECore/Export.h" diff --git a/include/GafferUI/LinearContainer.h b/include/GafferUI/LinearContainer.h index a6cc43738a8..16f49c2a3a8 100644 --- a/include/GafferUI/LinearContainer.h +++ b/include/GafferUI/LinearContainer.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_LINEARCONTAINER_H #define GAFFERUI_LINEARCONTAINER_H +#include "GafferUI/Export.h" #include "GafferUI/ContainerGadget.h" namespace GafferUI diff --git a/include/GafferUI/ModifiableEvent.h b/include/GafferUI/ModifiableEvent.h index 604f387f2a6..84fa2b95766 100644 --- a/include/GafferUI/ModifiableEvent.h +++ b/include/GafferUI/ModifiableEvent.h @@ -37,6 +37,7 @@ #ifndef GAFFERUI_MODIFIABLEEVENT_H #define GAFFERUI_MODIFIABLEEVENT_H +#include "GafferUI/Export.h" #include "GafferUI/Event.h" namespace GafferUI diff --git a/include/GafferUI/NameGadget.h b/include/GafferUI/NameGadget.h index 2a8d1f142d6..c9fb48ae900 100644 --- a/include/GafferUI/NameGadget.h +++ b/include/GafferUI/NameGadget.h @@ -37,6 +37,7 @@ #ifndef GAFFERUI_NAMEGADGET_H #define GAFFERUI_NAMEGADGET_H +#include "GafferUI/Export.h" #include "GafferUI/TextGadget.h" #include "IECoreScene/Font.h" diff --git a/include/GafferUI/NodeGadget.h b/include/GafferUI/NodeGadget.h index c615b39a76c..dbf40585555 100644 --- a/include/GafferUI/NodeGadget.h +++ b/include/GafferUI/NodeGadget.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_NODEGADGET_H #define GAFFERUI_NODEGADGET_H +#include "GafferUI/Export.h" #include "GafferUI/IndividualContainer.h" #include "Gaffer/Set.h" diff --git a/include/GafferUI/PlugGadget.h b/include/GafferUI/PlugGadget.h index 94cbd6bb16e..56b9bbc86e4 100644 --- a/include/GafferUI/PlugGadget.h +++ b/include/GafferUI/PlugGadget.h @@ -37,6 +37,7 @@ #ifndef GAFFERUI_PLUGGADGET_H #define GAFFERUI_PLUGGADGET_H +#include "GafferUI/Export.h" #include "GafferUI/ContainerGadget.h" namespace Gaffer diff --git a/include/GafferUI/Pointer.h b/include/GafferUI/Pointer.h index ab19d0e68b3..e8fd55afcef 100644 --- a/include/GafferUI/Pointer.h +++ b/include/GafferUI/Pointer.h @@ -43,6 +43,8 @@ #include "boost/signals.hpp" +#include "GafferUI/Export.h" + namespace GafferUI { diff --git a/include/GafferUI/RotateHandle.h b/include/GafferUI/RotateHandle.h index d1dc78480a9..72140183c36 100644 --- a/include/GafferUI/RotateHandle.h +++ b/include/GafferUI/RotateHandle.h @@ -37,6 +37,7 @@ #ifndef GAFFERUI_ROTATEHANDLE_H #define GAFFERUI_ROTATEHANDLE_H +#include "GafferUI/Export.h" #include "GafferUI/Handle.h" IECORE_PUSH_DEFAULT_VISIBILITY diff --git a/include/GafferUI/ScaleHandle.h b/include/GafferUI/ScaleHandle.h index 709f1ee4e19..86660886126 100644 --- a/include/GafferUI/ScaleHandle.h +++ b/include/GafferUI/ScaleHandle.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_SCALEHANDLE_H #define GAFFERUI_SCALEHANDLE_H +#include "GafferUI/Export.h" #include "GafferUI/Handle.h" namespace GafferUI diff --git a/include/GafferUI/SpacerGadget.h b/include/GafferUI/SpacerGadget.h index 1269d3b6410..18042af4752 100644 --- a/include/GafferUI/SpacerGadget.h +++ b/include/GafferUI/SpacerGadget.h @@ -37,6 +37,7 @@ #ifndef GAFFERUI_SPACERGADGET_H #define GAFFERUI_SPACERGADGET_H +#include "GafferUI/Export.h" #include "GafferUI/Gadget.h" namespace GafferUI diff --git a/include/GafferUI/StandardGraphLayout.h b/include/GafferUI/StandardGraphLayout.h index 800263d54d4..6e0a128ee1d 100644 --- a/include/GafferUI/StandardGraphLayout.h +++ b/include/GafferUI/StandardGraphLayout.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_STANDARDGRAPHLAYOUT_H #define GAFFERUI_STANDARDGRAPHLAYOUT_H +#include "GafferUI/Export.h" #include "GafferUI/GraphLayout.h" namespace Gaffer diff --git a/include/GafferUI/TextGadget.h b/include/GafferUI/TextGadget.h index b1f6a177e02..d5fc89bd1f5 100644 --- a/include/GafferUI/TextGadget.h +++ b/include/GafferUI/TextGadget.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_TEXTGADGET_H #define GAFFERUI_TEXTGADGET_H +#include "GafferUI/Export.h" #include "GafferUI/Gadget.h" #include "IECoreScene/Font.h" diff --git a/include/GafferUI/TranslateHandle.h b/include/GafferUI/TranslateHandle.h index 46056cda857..8af2a99b1aa 100644 --- a/include/GafferUI/TranslateHandle.h +++ b/include/GafferUI/TranslateHandle.h @@ -38,6 +38,7 @@ #ifndef GAFFERUI_TRANSLATEHANDLE_H #define GAFFERUI_TRANSLATEHANDLE_H +#include "GafferUI/Export.h" #include "GafferUI/Handle.h" namespace GafferUI diff --git a/include/GafferUI/ViewportGadget.h b/include/GafferUI/ViewportGadget.h index d978cc8858a..a495edcb952 100644 --- a/include/GafferUI/ViewportGadget.h +++ b/include/GafferUI/ViewportGadget.h @@ -183,7 +183,7 @@ class GAFFERUI_API ViewportGadget : public Gadget /// The SelectionScope class can be used by child Gadgets to perform /// OpenGL selection from event signal callbacks. - class SelectionScope : boost::noncopyable + class GAFFERUI_API SelectionScope : boost::noncopyable { public : @@ -225,7 +225,7 @@ class GAFFERUI_API ViewportGadget : public Gadget }; /// The RasterScope class can be used to perform drawing in raster space. - class RasterScope : boost::noncopyable + class GAFFERUI_API RasterScope : boost::noncopyable { public : diff --git a/include/GafferUIBindings/Export.h b/include/GafferUIBindings/Export.h new file mode 100644 index 00000000000..bddaf8e5bba --- /dev/null +++ b/include/GafferUIBindings/Export.h @@ -0,0 +1,51 @@ +////////////////////////////////////////////////////////////////////////// +// +// Copyright (c) 2016, Image Engine Design Inc. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above +// copyright notice, this list of conditions and the following +// disclaimer. +// +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided with +// the distribution. +// +// * Neither the name of John Haddon nor the names of +// any other contributors to this software may be used to endorse or +// promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +////////////////////////////////////////////////////////////////////////// + +#ifndef GAFFERUIBINDINGS_EXPORT_H +#define GAFFERUIBINDINGS_EXPORT_H + +#include "Gaffer/Export.h" + +// define GAFFERUIBINDINGS_API macro based on whether or not we are compiling +// GafferUIBindings, or including headers for linking to it. the GAFFERUIBINDINGS_API +// macro is the one that is used in the class definitions. +#ifdef GafferUIBindings_EXPORTS + #define GAFFERUIBINDINGS_API GAFFER_EXPORT +#else + #define GAFFERUIBINDINGS_API GAFFER_IMPORT +#endif + +#endif // #ifndef GAFFERUIBINDINGS_EXPORT_H diff --git a/include/GafferVDB/SphereLevelSet.h b/include/GafferVDB/SphereLevelSet.h index d8821112548..81d73f8f06c 100644 --- a/include/GafferVDB/SphereLevelSet.h +++ b/include/GafferVDB/SphereLevelSet.h @@ -37,6 +37,8 @@ #ifndef GAFFERSCENE_SPHERELEVELSET_H #define GAFFERSCENE_SPHERELEVELSET_H +#include "GafferVDB/Export.h" + #include "GafferScene/ObjectSource.h" #include "Gaffer/CompoundNumericPlug.h" @@ -46,7 +48,7 @@ namespace GafferVDB { -class GAFFERSCENE_API SphereLevelSet : public GafferScene::ObjectSource +class GAFFERVDB_API SphereLevelSet : public GafferScene::ObjectSource { public : diff --git a/python/GafferAppleseedTest/AppleseedRenderTest.py b/python/GafferAppleseedTest/AppleseedRenderTest.py index faf2b196af8..f92cdbe7337 100644 --- a/python/GafferAppleseedTest/AppleseedRenderTest.py +++ b/python/GafferAppleseedTest/AppleseedRenderTest.py @@ -36,7 +36,11 @@ import os import re -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import time import unittest diff --git a/python/GafferAppleseedTest/AppleseedTest.py b/python/GafferAppleseedTest/AppleseedTest.py index aa2cb1090bb..86598bbca53 100644 --- a/python/GafferAppleseedTest/AppleseedTest.py +++ b/python/GafferAppleseedTest/AppleseedTest.py @@ -35,7 +35,11 @@ ########################################################################## import os -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess def appleseedProjectSchemaPath(): diff --git a/python/GafferAppleseedUI/ShaderMenu.py b/python/GafferAppleseedUI/ShaderMenu.py index 4da85efbee3..6ce93d3fc16 100644 --- a/python/GafferAppleseedUI/ShaderMenu.py +++ b/python/GafferAppleseedUI/ShaderMenu.py @@ -62,7 +62,7 @@ def appendShaders( menuDefinition ) : q = asr.ShaderQuery() - for path in os.environ["APPLESEED_SEARCHPATH"].split( ":" ) : + for path in os.environ["APPLESEED_SEARCHPATH"].split( os.path.pathsep ) : for shader in glob.glob( os.path.join( path, "*.oso" ) ) : shaderFilename = os.path.basename( shader ) diff --git a/python/GafferArnold/__init__.py b/python/GafferArnold/__init__.py index 0fe758bb220..49183be131c 100644 --- a/python/GafferArnold/__init__.py +++ b/python/GafferArnold/__init__.py @@ -49,15 +49,19 @@ import sys import ctypes - originalDLOpenFlags = sys.getdlopenflags() - sys.setdlopenflags( originalDLOpenFlags & ~ctypes.RTLD_GLOBAL ) + import os + + if os.name == "posix": + originalDLOpenFlags = sys.getdlopenflags() + sys.setdlopenflags( originalDLOpenFlags & ~ctypes.RTLD_GLOBAL ) from ._GafferArnold import * finally : - sys.setdlopenflags( originalDLOpenFlags ) - del sys, ctypes, originalDLOpenFlags + if os.name == "posix": + sys.setdlopenflags( originalDLOpenFlags ) + del sys, ctypes, originalDLOpenFlags from .ArnoldShaderBall import ArnoldShaderBall from .ArnoldTextureBake import ArnoldTextureBake diff --git a/python/GafferArnoldTest/ArnoldRenderTest.py b/python/GafferArnoldTest/ArnoldRenderTest.py index 4a3a2d7a925..0e5408eb05c 100644 --- a/python/GafferArnoldTest/ArnoldRenderTest.py +++ b/python/GafferArnoldTest/ArnoldRenderTest.py @@ -38,8 +38,11 @@ import os import inspect import unittest -import subprocess32 as subprocess import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import threading import arnold diff --git a/python/GafferArnoldTest/ArnoldShaderTest.py b/python/GafferArnoldTest/ArnoldShaderTest.py index 7bb4acde32d..481debc7ab7 100644 --- a/python/GafferArnoldTest/ArnoldShaderTest.py +++ b/python/GafferArnoldTest/ArnoldShaderTest.py @@ -59,10 +59,10 @@ def withMetadata( func ) : def wrapper( self ) : metadataPath = os.path.join( os.path.dirname( __file__ ), "metadata" ) - if metadataPath not in os.environ["ARNOLD_PLUGIN_PATH"].split( ":" ) : + if metadataPath not in os.environ["ARNOLD_PLUGIN_PATH"].split( os.pathsep ) : env = os.environ.copy() - env["ARNOLD_PLUGIN_PATH"] = env["ARNOLD_PLUGIN_PATH"] + ":" + metadataPath + env["ARNOLD_PLUGIN_PATH"] = env["ARNOLD_PLUGIN_PATH"] + os.pathsep + metadataPath try : subprocess.check_output( diff --git a/python/GafferArnoldUI/ArnoldShaderUI.py b/python/GafferArnoldUI/ArnoldShaderUI.py index 691b1b73474..9a3f14d1586 100644 --- a/python/GafferArnoldUI/ArnoldShaderUI.py +++ b/python/GafferArnoldUI/ArnoldShaderUI.py @@ -56,7 +56,7 @@ def __aiMetadataGetStr( nodeEntry, paramName, name, defaultValue = None ) : - value = arnold.AtStringReturn() + value = arnold.AtStringStruct() if arnold.AiMetaDataGetStr( nodeEntry, paramName, name, value ) : return arnold.AtStringToStr( value ) diff --git a/python/GafferArnoldUI/ShaderMenu.py b/python/GafferArnoldUI/ShaderMenu.py index 159d127be9f..69589cb6370 100644 --- a/python/GafferArnoldUI/ShaderMenu.py +++ b/python/GafferArnoldUI/ShaderMenu.py @@ -136,7 +136,7 @@ def __colorManagerCreator( colorManagerName, nodeName ) : def __aiMetadataGetStr( nodeEntry, paramName, name ) : - value = arnold.AtStringReturn() + value = arnold.AtStringStruct() if arnold.AiMetaDataGetStr( nodeEntry, paramName, name, value ) : return arnold.AtStringToStr( value ) diff --git a/python/GafferDispatch/LocalDispatcher.py b/python/GafferDispatch/LocalDispatcher.py index 6806af4f936..85d81718317 100644 --- a/python/GafferDispatch/LocalDispatcher.py +++ b/python/GafferDispatch/LocalDispatcher.py @@ -38,7 +38,11 @@ import errno import signal import shlex -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import threading import time import traceback @@ -259,8 +263,9 @@ def __doBackgroundDispatch( self, batch ) : taskContext = batch.context() frames = str( IECore.frameListFromList( [ int(x) for x in batch.frames() ] ) ) - args = [ - "gaffer", "execute", + args = [ "gaffer.bat" ] if os.name == "nt" else [ "gaffer" ] + args = args + [ + "execute", "-script", self.__scriptFile, "-nodes", batch.blindData()["nodeName"].value, "-frames", frames, @@ -281,7 +286,10 @@ def __doBackgroundDispatch( self, batch ) : self.__setStatus( batch, LocalDispatcher.Job.Status.Running ) IECore.msg( IECore.MessageHandler.Level.Info, self.__messageTitle, " ".join( args ) ) - process = subprocess.Popen( args, start_new_session=True ) + if os.name == "nt": + process = subprocess.Popen( args ) + else: + process = subprocess.Popen( args, start_new_session=True ) batch.blindData()["pid"] = IECore.IntData( process.pid ) while process.poll() is None : diff --git a/python/GafferDispatch/SystemCommand.py b/python/GafferDispatch/SystemCommand.py index c77fc934b12..526e9e12258 100644 --- a/python/GafferDispatch/SystemCommand.py +++ b/python/GafferDispatch/SystemCommand.py @@ -36,7 +36,11 @@ import os import shlex -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import IECore diff --git a/python/GafferDispatchTest/DispatchApplicationTest.py b/python/GafferDispatchTest/DispatchApplicationTest.py index df60d32a6fb..a7a11fd4baf 100644 --- a/python/GafferDispatchTest/DispatchApplicationTest.py +++ b/python/GafferDispatchTest/DispatchApplicationTest.py @@ -35,7 +35,11 @@ ########################################################################## import os -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import unittest import Gaffer diff --git a/python/GafferDispatchTest/ExecuteApplicationTest.py b/python/GafferDispatchTest/ExecuteApplicationTest.py index 10d9e81238c..39aa43e2f8f 100644 --- a/python/GafferDispatchTest/ExecuteApplicationTest.py +++ b/python/GafferDispatchTest/ExecuteApplicationTest.py @@ -36,7 +36,11 @@ ########################################################################## import os -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import unittest import glob import inspect diff --git a/python/GafferDispatchTest/StatsApplicationTest.py b/python/GafferDispatchTest/StatsApplicationTest.py index 8571a6fa4c0..d17dd81e783 100644 --- a/python/GafferDispatchTest/StatsApplicationTest.py +++ b/python/GafferDispatchTest/StatsApplicationTest.py @@ -36,7 +36,12 @@ import inspect import unittest -import subprocess32 as subprocess +import os +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import Gaffer import GafferTest diff --git a/python/GafferDispatchTest/SystemCommandTest.py b/python/GafferDispatchTest/SystemCommandTest.py index 0405efddb52..725b90b9362 100644 --- a/python/GafferDispatchTest/SystemCommandTest.py +++ b/python/GafferDispatchTest/SystemCommandTest.py @@ -35,7 +35,11 @@ ########################################################################## import os -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import unittest import IECore diff --git a/python/GafferImageTest/ColorSpaceTest.py b/python/GafferImageTest/ColorSpaceTest.py index f827fac64b9..c4ab739e072 100644 --- a/python/GafferImageTest/ColorSpaceTest.py +++ b/python/GafferImageTest/ColorSpaceTest.py @@ -37,7 +37,11 @@ import os import unittest -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import imath import IECore diff --git a/python/GafferImageTest/DisplayTest.py b/python/GafferImageTest/DisplayTest.py index afe336b0a47..dd2019c1f12 100644 --- a/python/GafferImageTest/DisplayTest.py +++ b/python/GafferImageTest/DisplayTest.py @@ -38,7 +38,11 @@ import unittest import random import threading -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import imath import IECore diff --git a/python/GafferImageTest/DisplayTransformTest.py b/python/GafferImageTest/DisplayTransformTest.py index 0bce3fb29ec..e4d9e68b01f 100644 --- a/python/GafferImageTest/DisplayTransformTest.py +++ b/python/GafferImageTest/DisplayTransformTest.py @@ -36,7 +36,11 @@ import os import unittest -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import imath import IECore diff --git a/python/GafferImageTest/ImageReaderTest.py b/python/GafferImageTest/ImageReaderTest.py index 6ad9975bfb4..557eecebd56 100644 --- a/python/GafferImageTest/ImageReaderTest.py +++ b/python/GafferImageTest/ImageReaderTest.py @@ -49,13 +49,14 @@ class ImageReaderTest( GafferImageTest.ImageTestCase ) : - fileName = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/circles.exr" ) - colorSpaceFileName = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/circles_as_cineon.exr" ) - offsetDataWindowFileName = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/rgb.100x100.exr" ) - jpgFileName = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/circles.jpg" ) - largeFileName = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/colorbars_max_clamp.exr" ) - def setUp( self ) : + gaffer_root = os.environ["GAFFER_ROOT"] + + self.fileName = Gaffer.FileSystemPath( gaffer_root + "/python/GafferImageTest/images/circles.exr" ).nativeString() + self.colorSpaceFileName = Gaffer.FileSystemPath( gaffer_root + "/python/GafferImageTest/images/circles_as_cineon.exr" ).nativeString() + self.offsetDataWindowFileName = Gaffer.FileSystemPath( gaffer_root + "/python/GafferImageTest/images/rgb.100x100.exr" ).nativeString() + self.jpgFileName = Gaffer.FileSystemPath( gaffer_root + "/python/GafferImageTest/images/circles.jpg" ).nativeString() + self.largeFileName = Gaffer.FileSystemPath( gaffer_root + "/python/GafferImageTest/images/colorbars_max_clamp.exr" ).nativeString() GafferImageTest.ImageTestCase.setUp( self ) self.__defaultColorSpaceFunction = GafferImage.ImageReader.getDefaultColorSpaceFunction() diff --git a/python/GafferImageTest/ImageWriterTest.py b/python/GafferImageTest/ImageWriterTest.py index 976a1b8af12..6faba043c53 100644 --- a/python/GafferImageTest/ImageWriterTest.py +++ b/python/GafferImageTest/ImageWriterTest.py @@ -54,15 +54,21 @@ class ImageWriterTest( GafferImageTest.ImageTestCase ) : - __largeFilePath = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/large.exr" ) - __rgbFilePath = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/rgb.100x100" ) - __negativeDataWindowFilePath = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/checkerWithNegativeDataWindow.200x150" ) - __representativeDeepPath = os.path.expandvars( "$GAFFER_ROOT/python/GafferImageTest/images/representativeDeepImage.exr" ) - longMessage = True def setUp( self ) : + if os.name == "nt": + gaffer_root = os.path.expandvars( "%GAFFER_ROOT%" ) + else: + gaffer_root = os.path.expandvars( "$GAFFER_ROOT" ) + + self.__largeFilePath = os.path.abspath( gaffer_root + "/python/GafferImageTest/images/large.exr" ) + self.__rgbFilePath = os.path.abspath( gaffer_root + "/python/GafferImageTest/images/rgb.100x100" ) + self.__negativeDataWindowFilePath = os.path.abspath( gaffer_root + "/python/GafferImageTest/images/checkerWithNegativeDataWindow.200x150" ) + self.__representativeDeepPath = os.path.abspath( gaffer_root + "/python/GafferImageTest/images/representativeDeepImage.exr" ) + + GafferImageTest.ImageTestCase.setUp( self ) self.__defaultColorSpaceFunction = GafferImage.ImageWriter.getDefaultColorSpaceFunction() @@ -477,7 +483,11 @@ def __testExtension( self, ext, formatName, options = {}, metadataToIgnore = [] # the writer adds several standard attributes that aren't in the original file expectedMetadata["Software"] = IECore.StringData( "Gaffer " + Gaffer.About.versionString() ) expectedMetadata["HostComputer"] = IECore.StringData( platform.node() ) - expectedMetadata["Artist"] = IECore.StringData( os.environ["USER"] ) + if os.name == "nt": + user_key = "username" + else: + user_key = "USER" + expectedMetadata["Artist"] = IECore.StringData( os.environ[user_key] ) expectedMetadata["DocumentName"] = IECore.StringData( "untitled" ) for key in overrideMetadata : @@ -784,7 +794,11 @@ def __testMetadataDoesNotAffectPixels( self, ext, overrideMetadata = {}, metadat expectedMetadata["DateTime"] = regularReaderMetadata["DateTime"] expectedMetadata["Software"] = IECore.StringData( "Gaffer " + Gaffer.About.versionString() ) expectedMetadata["HostComputer"] = IECore.StringData( platform.node() ) - expectedMetadata["Artist"] = IECore.StringData( os.environ["USER"] ) + if os.name == "nt": + user_key = "username" + else: + user_key = "USER" + expectedMetadata["Artist"] = IECore.StringData( os.environ[user_key] ) expectedMetadata["DocumentName"] = IECore.StringData( "untitled" ) expectedMetadata["fileFormat"] = regularReaderMetadata["fileFormat"] expectedMetadata["dataType"] = regularReaderMetadata["dataType"] @@ -983,7 +997,13 @@ def testFileNamesWithSubstitutions( self ) : with context : s["w"]["task"].execute() - self.assertTrue( os.path.isfile( self.temporaryDirectory() + "/test.tif" ) ) + self.assertTrue( os.path.isfile( os.path.join( self.temporaryDirectory(), "test.tif" ) ) ) + + s["w"]["fileName"].setValue( self.temporaryDirectory() + "/test.#.tif" ) + context.setFrame( 5 ) + with context : + s["w"]["task"].execute() + self.assertTrue( os.path.isfile( os.path.join( self.temporaryDirectory(), "test.5.tif" ) ) ) def testErrorMessages( self ) : @@ -1070,7 +1090,7 @@ def __init__( self, name = "DerivedImageWriter" ) : GafferImage.ImageWriter.__init__( self, name ) - self["copyFileName"] = Gaffer.StringPlug() + self["copyFileName"] = Gaffer.FileSystemPathPlug() def execute( self ) : @@ -1112,7 +1132,7 @@ def testStringMetadata( self ) : def __testFile( self, mode, channels, ext ) : - return self.temporaryDirectory() + "/test." + channels + "." + str( mode ) + "." + str( ext ) + return os.path.join(self.temporaryDirectory(), "test." + channels + "." + str( mode ) + "." + str( ext )) def testJpgChroma( self ): @@ -1127,7 +1147,7 @@ def testJpgChroma( self ): chromaSubSamplings = ( "4:4:4", "4:2:2", "4:2:0", "4:1:1", "" ) for chromaSubSampling in chromaSubSamplings: - testFile = os.path.join( self.temporaryDirectory(), "chromaSubSampling.{0}.jpg".format( chromaSubSampling ) ) + testFile = os.path.join( self.temporaryDirectory(), "chromaSubSampling.{0}.jpg".format( chromaSubSampling.replace(":", ".") ) ) w["fileName"].setValue( testFile ) w["jpeg"]["chromaSubSampling"].setValue( chromaSubSampling ) diff --git a/python/GafferOSLTest/OSLTestCase.py b/python/GafferOSLTest/OSLTestCase.py index 93beb96495a..404d4826492 100644 --- a/python/GafferOSLTest/OSLTestCase.py +++ b/python/GafferOSLTest/OSLTestCase.py @@ -35,7 +35,11 @@ ########################################################################## import os -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import GafferSceneTest @@ -47,7 +51,7 @@ def compileShader( self, sourceFileName ) : subprocess.check_call( [ "oslc", "-q" ] + - [ "-I" + p for p in os.environ.get( "OSL_SHADER_PATHS", "" ).split( ":" ) ] + + [ "-I" + p for p in os.environ.get( "OSL_SHADER_PATHS", "" ).split( os.pathsep ) ] + [ "-o", outputFileName, sourceFileName ] ) diff --git a/python/GafferSceneUI/CameraUI.py b/python/GafferSceneUI/CameraUI.py index 000e4ef508d..4663203c49c 100644 --- a/python/GafferSceneUI/CameraUI.py +++ b/python/GafferSceneUI/CameraUI.py @@ -169,17 +169,17 @@ "layout:visibilityActivator", "perspectiveModeFocalLength", - "preset:Academy 35mm 21.946 × 16.000", imath.V2f( 21.946, 16 ), - "preset:Super 35mm 24.892 × 18.669", imath.V2f( 24.892, 18.669 ), - "preset:Micro Four Thirds 17.30 × 13.00", imath.V2f( 17.3, 13 ), - "preset:APS-C 22.30 × 14.90", imath.V2f( 22.3, 14.9 ), - "preset:Full Frame 35mm 36.00 × 24.00", imath.V2f( 36, 24 ), - "preset:Alexa SXT 4:3 2.8k 23.76 × 17.82", imath.V2f( 23.76, 17.82 ), - "preset:Alexa SXT Open Gate 3.4k 28.25 × 18.17", imath.V2f( 28.25, 18.17 ), - "preset:Alexa 65 16:9 5.1k 42.24 × 23.76", imath.V2f( 42.24, 23.76 ), - "preset:Alexa 65 Open Gate 6.5k 54.12 × 25.58", imath.V2f( 54.12, 25.58 ), - "preset:RED EPIC-W 5K S35 30.72 × 18.00", imath.V2f( 30.72, 18 ), - "preset:RED EPIC-W 8K S35 29.90 × 15.77", imath.V2f( 29.9, 15.77 ), + "preset:Academy 35mm 21.946 \u00D7 16.000", imath.V2f( 21.946, 16 ), + "preset:Super 35mm 24.892 \u00D7 18.669", imath.V2f( 24.892, 18.669 ), + "preset:Micro Four Thirds 17.30 \u00D7 13.00", imath.V2f( 17.3, 13 ), + "preset:APS-C 22.30 \u00D7 14.90", imath.V2f( 22.3, 14.9 ), + "preset:Full Frame 35mm 36.00 \u00D7 24.00", imath.V2f( 36, 24 ), + "preset:Alexa SXT 4:3 2.8k 23.76 \u00D7 17.82", imath.V2f( 23.76, 17.82 ), + "preset:Alexa SXT Open Gate 3.4k 28.25 \u00D7 18.17", imath.V2f( 28.25, 18.17 ), + "preset:Alexa 65 16:9 5.1k 42.24 \u00D7 23.76", imath.V2f( 42.24, 23.76 ), + "preset:Alexa 65 Open Gate 6.5k 54.12 \u00D7 25.58", imath.V2f( 54.12, 25.58 ), + "preset:RED EPIC-W 5K S35 30.72 \u00D7 18.00", imath.V2f( 30.72, 18 ), + "preset:RED EPIC-W 8K S35 29.90 \u00D7 15.77", imath.V2f( 29.9, 15.77 ), "presetsPlugValueWidget:allowCustom", True, diff --git a/python/GafferSceneUI/ShaderUI.py b/python/GafferSceneUI/ShaderUI.py index b283bf54494..52213c918e2 100644 --- a/python/GafferSceneUI/ShaderUI.py +++ b/python/GafferSceneUI/ShaderUI.py @@ -284,10 +284,10 @@ def __shaderSubMenu( searchPaths, extensions, nodeCreator, matchExpression, sear if path in pathsVisited : continue - for root, dirs, files in os.walk( path ) : + for root, dirs, files in os.walk( path ) : for file in files : if os.path.splitext( file )[1][1:] in extensions : - shaderPath = os.path.join( root, file ).partition( path )[-1].lstrip( "/" ) + shaderPath = os.path.join( root, file ).partition( path )[-1].lstrip( os.path.sep ) if __hiddenShadersPathMatcher.match( shaderPath ) & IECore.PathMatcher.Result.ExactMatch : continue if shaderPath not in shaders and matchExpression.match( shaderPath ) : @@ -296,18 +296,18 @@ def __shaderSubMenu( searchPaths, extensions, nodeCreator, matchExpression, sear pathsVisited.add( path ) shaders = sorted( list( shaders ) ) - categorisedShaders = [ x for x in shaders if "/" in x ] - uncategorisedShaders = [ x for x in shaders if "/" not in x ] + categorisedShaders = [ x for x in shaders if os.path.sep in x ] + uncategorisedShaders = [ x for x in shaders if os.path.sep not in x ] shadersAndMenuPaths = [] for shader in categorisedShaders : - shadersAndMenuPaths.append( ( shader, "/" + shader ) ) + shadersAndMenuPaths.append( ( shader.replace("\\", "/"), "/" + shader.replace("\\", "/") ) ) for shader in uncategorisedShaders : if not categorisedShaders : - shadersAndMenuPaths.append( ( shader, "/" + shader ) ) + shadersAndMenuPaths.append( ( shader.replace("\\", "/"), "/" + shader.replace("\\", "/") ) ) else : - shadersAndMenuPaths.append( ( shader, "/Other/" + shader ) ) + shadersAndMenuPaths.append( ( shader.replace("\\", "/"), "/Other/" + shader.replace("\\", "/") ) ) result = IECore.MenuDefinition() for shader, menuPath in shadersAndMenuPaths : diff --git a/python/GafferSceneUI/StandardOptionsUI.py b/python/GafferSceneUI/StandardOptionsUI.py index 9f1231e3cf4..5d46679acf7 100644 --- a/python/GafferSceneUI/StandardOptionsUI.py +++ b/python/GafferSceneUI/StandardOptionsUI.py @@ -252,7 +252,7 @@ def __statisticsSummary( plug ) : sides of the rendered image. Overscan can be useful when camera shake or blur will be added - as a post-process. This plug just enables overscan as a whole – + as a post-process. This plug just enables overscan as a whole \u2013 use the _Overscan Top_, _Overscan Bottom_, _Overscan Left_ and _Overscan Right_ plugs to specify the amount of overscan on each side of the image. diff --git a/python/GafferTest/AboutTest.py b/python/GafferTest/AboutTest.py index 45f5806e9c7..9d618b8153e 100644 --- a/python/GafferTest/AboutTest.py +++ b/python/GafferTest/AboutTest.py @@ -63,7 +63,7 @@ def test( self ) : # builds and mark the test as being an expected failure, so as to cut # down on noise. packagedWithDependencies = False -for f in glob.glob( os.path.expandvars( "$GAFFER_ROOT/lib/*" ) ) : +for f in glob.glob( os.path.join( os.environ["GAFFER_ROOT"], "lib", "*" ) ) : if "Gaffer" not in os.path.basename( f ) : packagedWithDependencies = True diff --git a/python/GafferTest/AnimationTest.py b/python/GafferTest/AnimationTest.py index bfc9740ba5a..6be9ad1ce29 100644 --- a/python/GafferTest/AnimationTest.py +++ b/python/GafferTest/AnimationTest.py @@ -34,6 +34,7 @@ # ########################################################################## +import os import unittest import IECore @@ -2707,7 +2708,7 @@ def testAnimationWithinAReference( self ) : c.setTime( 1 ) self.assertEqual( s["b"]["sum"].getValue(), 1 ) - fileName = self.temporaryDirectory() + "/reference.grf" + fileName = os.path.join( self.temporaryDirectory(), "reference.grf" ) s["b"].exportForReference( fileName ) s["r"] = Gaffer.Reference() @@ -2891,7 +2892,7 @@ def testSerialisationCreatedInVersion0_60( self ) : import os s = Gaffer.ScriptNode() - s["fileName"].setValue( os.path.dirname( __file__ ) + "/scripts/animationVersion-0.60.9.0.gfr" ) + s["fileName"].setValue( os.path.join( os.path.dirname( __file__ ), "scripts", "animationVersion-0.60.9.0.gfr" ) ) s.load() def assertAnimation( script ) : diff --git a/python/GafferTest/ApplicationRootTest.py b/python/GafferTest/ApplicationRootTest.py index dd622528521..e35000aa8c8 100644 --- a/python/GafferTest/ApplicationRootTest.py +++ b/python/GafferTest/ApplicationRootTest.py @@ -35,6 +35,8 @@ ########################################################################## import os +import stat +import tempfile import unittest import imath @@ -44,8 +46,11 @@ class ApplicationRootTest( GafferTest.TestCase ) : - __defaultPreferencesFile = os.path.expanduser( "~/gaffer/startup/testApp/preferences.py" ) - __preferencesFile = "/tmp/testPreferences.py" + def setUp( self ) : + GafferTest.TestCase.setUp( self ) + + self.__defaultPreferencesFile = os.path.expanduser( os.path.join( "~", "gaffer", "startup", "testApp", "preferences.py" ) ) + self.__preferencesFile = os.path.join( self.temporaryDirectory(), "testPreferences.py" ) class testApp( Gaffer.Application ) : @@ -101,6 +106,7 @@ def testPreferencesPermissionsErrors( self ) : a.savePreferences( self.__preferencesFile ) os.chmod( self.__preferencesFile, 0 ) self.assertRaises( RuntimeError, a.savePreferences, self.__preferencesFile ) + os.chmod( self.__preferencesFile, stat.S_IWRITE) def testPreferencesLocation( self ) : @@ -145,5 +151,6 @@ def tearDown( self ) : if os.path.exists( f ) : os.remove( f ) + if __name__ == "__main__": unittest.main() diff --git a/python/GafferTest/ApplicationTest.py b/python/GafferTest/ApplicationTest.py index 214409e07ba..9c241e5268d 100644 --- a/python/GafferTest/ApplicationTest.py +++ b/python/GafferTest/ApplicationTest.py @@ -36,7 +36,11 @@ import os import time -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import IECore import Gaffer diff --git a/python/GafferTest/BoxIOTest.py b/python/GafferTest/BoxIOTest.py index 50daae3cf25..a8b5d05bab4 100644 --- a/python/GafferTest/BoxIOTest.py +++ b/python/GafferTest/BoxIOTest.py @@ -129,7 +129,7 @@ def testInsertWithNonSerialisableOutput( self ) : def testLoadOutsideBoxVersion0_52( self ) : s = Gaffer.ScriptNode() - s["fileName"].setValue( os.path.dirname( __file__ ) + "/scripts/boxIOOutsideBoxVersion-0.52.0.0.gfr" ) + s["fileName"].setValue( os.path.join( os.path.dirname( __file__ ), "scripts", "boxIOOutsideBoxVersion-0.52.0.0.gfr" ) ) s.load() self.assertIsInstance( s["BoxIn"], Gaffer.BoxIn ) @@ -141,7 +141,7 @@ def testImportIntoBoxVersion0_52( self ) : s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() - s.executeFile( os.path.dirname( __file__ ) + "/scripts/boxIOOutsideBoxVersion-0.52.0.0.gfr", parent = s["b"] ) + s.executeFile( os.path.join( os.path.dirname( __file__ ), "scripts", "boxIOOutsideBoxVersion-0.52.0.0.gfr" ), parent = s["b"] ) self.assertIn( "in", s["b"] ) self.assertIn( "out", s["b"] ) self.assertIn( "passThrough", s["b"]["BoxOut"] ) diff --git a/python/GafferTest/BoxInTest.py b/python/GafferTest/BoxInTest.py index dffa9bd1447..6f07ad575a4 100644 --- a/python/GafferTest/BoxInTest.py +++ b/python/GafferTest/BoxInTest.py @@ -470,7 +470,7 @@ def testSerialisationWithReferenceSibling( self ) : s1["b"]["i"].setup( Gaffer.IntPlug()) s1["r"] = Gaffer.Reference() - s1["r"].load( os.path.dirname( __file__ ) + "/references/empty.grf" ) + s1["r"].load( os.path.join( os.path.dirname( __file__ ), "references", "empty.grf" ) ) s2 = Gaffer.ScriptNode() s2.execute( s1.serialise() ) diff --git a/python/GafferTest/BoxTest.py b/python/GafferTest/BoxTest.py index 7713deb8eda..84c702ece25 100644 --- a/python/GafferTest/BoxTest.py +++ b/python/GafferTest/BoxTest.py @@ -1054,7 +1054,7 @@ def testCanBoxNodesWithInternalNodeNetworkAndHiddenPlug( self ) : def testPassThroughCreatedInVersion0_52( self ) : s = Gaffer.ScriptNode() - s["fileName"].setValue( os.path.dirname( __file__ ) + "/scripts/boxPassThroughVersion-0.52.0.0.gfr" ) + s["fileName"].setValue( os.path.join( os.path.dirname( __file__ ), "scripts", "boxPassThroughVersion-0.52.0.0.gfr" ) ) s.load() def assertPassThrough( script ) : @@ -1082,7 +1082,7 @@ def assertPassThrough( script ) : def testAddPassThroughToBoxFromVersion0_52( self ) : s = Gaffer.ScriptNode() - s["fileName"].setValue( os.path.dirname( __file__ ) + "/scripts/boxVersion-0.52.0.0.gfr" ) + s["fileName"].setValue( os.path.join( os.path.dirname( __file__ ), "scripts", "boxVersion-0.52.0.0.gfr" ) ) s.load() # The original Box had no pass-through behaviour defined, diff --git a/python/GafferTest/DependencyNodeTest.py b/python/GafferTest/DependencyNodeTest.py index d69909fc30f..9c40a60d880 100644 --- a/python/GafferTest/DependencyNodeTest.py +++ b/python/GafferTest/DependencyNodeTest.py @@ -39,6 +39,7 @@ import threading import collections import six +import os import IECore @@ -691,7 +692,10 @@ def affects( self, input ) : self.assertEqual( len( mh.messages ), 1 ) self.assertEqual( mh.messages[0].level, IECore.Msg.Level.Error ) self.assertEqual( mh.messages[0].context, "BadAffects::affects()" ) - self.assertEqual( mh.messages[0].message, "TypeError: No registered converter was able to extract a C++ reference to type Gaffer::Plug from this Python object of type NoneType\n" ) + m = "TypeError: No registered converter was able to extract a C++ reference to type Gaffer::Plug from this Python object of type NoneType\n" + if os.name == "nt" : + m = "TypeError: No registered converter was able to extract a C++ reference to type class Gaffer::Plug from this Python object of type NoneType\n" + self.assertEqual( mh.messages[0].message, m ) def testDependencyCyclesDontStopPlugsDirtying( self ) : diff --git a/python/GafferTest/ExpressionTest.py b/python/GafferTest/ExpressionTest.py index fdbc4e69935..683f5ab09e0 100644 --- a/python/GafferTest/ExpressionTest.py +++ b/python/GafferTest/ExpressionTest.py @@ -1469,11 +1469,11 @@ def testNoneOutput( self ) : ) s["e"].setExpression( "import math; parent['n']['user']['p'] = math" ) - six.assertRaisesRegex( self, - Gaffer.ProcessException, - ".*TypeError: Unsupported type for result \"\" for expression output \"n.user.p\"" + if os.name == "nt" : + r = ".*TypeError: Unsupported type for result \"\" for expression output \"n.user.p\"" + six.assertRaisesRegex( self, Gaffer.ProcessException, r, s["n"]["user"]["p"].getValue ) @GafferTest.TestRunner.PerformanceTestMethod() def testParallelPerformance( self ): diff --git a/python/GafferTest/FileSequencePathFilterTest.py b/python/GafferTest/FileSequencePathFilterTest.py index d0aac28bd8d..b992a7b3f22 100644 --- a/python/GafferTest/FileSequencePathFilterTest.py +++ b/python/GafferTest/FileSequencePathFilterTest.py @@ -35,162 +35,163 @@ ########################################################################## import os +import tempfile import shutil import unittest +if os.name == "nt" : + import ctypes import Gaffer import GafferTest class FileSequencePathFilterTest( GafferTest.TestCase ) : - __dir = "/tmp/gafferFileSequencePathFilterTest" - def test( self ) : p = Gaffer.FileSystemPath( self.__dir, includeSequences = True ) self.assertTrue( p.getIncludeSequences() ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", - self.__dir + "/a.###.txt", - self.__dir + "/b.###.txt" + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), + os.path.join( self.__dir, "a.###.txt" ), + os.path.join( self.__dir, "b.###.txt" ) ] ) ) p.setFilter( Gaffer.FileSequencePathFilter( mode = Gaffer.FileSequencePathFilter.Keep.Files ) ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Files ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "dir" ) ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.SequentialFiles ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.SequentialFiles ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ) ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.Sequences ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Sequences ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/dir", - self.__dir + "/a.###.txt", - self.__dir + "/b.###.txt" + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "dir" ), + os.path.join( self.__dir, "a.###.txt" ), + os.path.join( self.__dir, "b.###.txt" ) ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.Concise ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Concise ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/dir", - self.__dir + "/a.###.txt", - self.__dir + "/b.###.txt" + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "dir" ), + os.path.join( self.__dir, "a.###.txt" ), + os.path.join( self.__dir, "b.###.txt" ) ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.Verbose ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Verbose ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ) ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.All ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.All ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", - self.__dir + "/a.###.txt", - self.__dir + "/b.###.txt" + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), + os.path.join( self.__dir, "a.###.txt" ), + os.path.join( self.__dir, "b.###.txt" ) ] ) ) p = Gaffer.FileSystemPath( self.__dir, includeSequences = True ) self.assertTrue( p.getIncludeSequences() ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", - self.__dir + "/a.###.txt", - self.__dir + "/b.###.txt" + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), + os.path.join( self.__dir, "a.###.txt" ), + os.path.join( self.__dir, "b.###.txt" ) ] ) ) p.setFilter( Gaffer.FileSequencePathFilter( mode = Gaffer.FileSequencePathFilter.Keep.Files ) ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Files ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "dir" ) ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.SequentialFiles ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.SequentialFiles ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.Sequences ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Sequences ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/dir", - self.__dir + "/a.###.txt", - self.__dir + "/b.###.txt" + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "dir" ), + os.path.join( self.__dir, "a.###.txt" ), + os.path.join( self.__dir, "b.###.txt" ) ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.Concise ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Concise ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/dir", - self.__dir + "/a.###.txt", - self.__dir + "/b.###.txt" + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "dir" ), + os.path.join( self.__dir, "a.###.txt" ), + os.path.join( self.__dir, "b.###.txt" ) ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.Verbose ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Verbose ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.All ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.All ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", - self.__dir + "/a.###.txt", - self.__dir + "/b.###.txt" + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), + os.path.join( self.__dir, "a.###.txt" ), + os.path.join( self.__dir, "b.###.txt" ) ] ) ) def testNoSequences( self ) : @@ -203,66 +204,66 @@ def testNoSequences( self ) : p = Gaffer.FileSystemPath( self.__dir, includeSequences = False ) self.assertFalse( p.getIncludeSequences() ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), ] ) ) p.setFilter( Gaffer.FileSequencePathFilter( mode = Gaffer.FileSequencePathFilter.Keep.Files ) ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Files ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "dir" ), ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.SequentialFiles ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.SequentialFiles ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.Sequences ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Sequences ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "dir" ), ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.Concise ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Concise ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "dir" ) ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.Verbose ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Verbose ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), ] ) ) p.getFilter().setMode( Gaffer.FileSequencePathFilter.Keep.All ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.All ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), ] ) ) def testEnabled( self ) : @@ -272,36 +273,51 @@ def testEnabled( self ) : p.setFilter( Gaffer.FileSequencePathFilter( mode = Gaffer.FileSequencePathFilter.Keep.Files ) ) self.assertEqual( p.getFilter().getMode(), Gaffer.FileSequencePathFilter.Keep.Files ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/dir", + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "dir" ), ] ) ) p.getFilter().setEnabled( False ) - self.assertEqual( set( [ str( c ) for c in p.children() ] ), set( [ - self.__dir + "/singleFile.txt", - self.__dir + "/a.001.txt", - self.__dir + "/a.002.txt", - self.__dir + "/a.004.txt", - self.__dir + "/b.003.txt", - self.__dir + "/dir", - self.__dir + "/a.###.txt", - self.__dir + "/b.###.txt" + self.assertEqual( set( [ c.nativeString() for c in p.children() ] ), set( [ + os.path.join( self.__dir, "singleFile.txt" ), + os.path.join( self.__dir, "a.001.txt" ), + os.path.join( self.__dir, "a.002.txt" ), + os.path.join( self.__dir, "a.004.txt" ), + os.path.join( self.__dir, "b.003.txt" ), + os.path.join( self.__dir, "dir" ), + os.path.join( self.__dir, "a.###.txt" ), + os.path.join( self.__dir, "b.###.txt" ) ] ) ) def setUp( self ) : GafferTest.TestCase.setUp( self ) + self.__dir = os.path.join( tempfile.gettempdir(), "gafferFileSequencePathFilterTest" ) + # clear out old files and make empty directory # to work in if os.path.exists( self.__dir ) : shutil.rmtree( self.__dir ) os.mkdir( self.__dir ) - os.mkdir( self.__dir + "/dir" ) + # On Windows, Python returns a temporary directory in Windows 8.3 file + # naming format, which is a shortened version of the full filename. + # This name contains numbers, which causes the test to fail when + # IECore::findSequences thinks it finds a sequence due to the number + # in the directory name. + # The only way to expand the shortened name is either the Win32 Python + # extensions, or calling the needed function through ctypes. We choose + # ctypes to eliminate the need for additional modules. + if os.name == "nt" : + buffer = ctypes.create_unicode_buffer( 4096 ) + ctypes.windll.kernel32.GetLongPathNameW( self.__dir, buffer, 4096 ) + self.__dir = buffer.value + + os.mkdir( os.path.join( self.__dir, "dir" ) ) for n in [ "singleFile.txt", "a.001.txt", "a.002.txt", "a.004.txt", "b.003.txt" ] : - with open( self.__dir + "/" + n, "w" ) as f : + with open( os.path.join( self.__dir, n ), "w" ) as f : f.write( "AAAA" ) def tearDown( self ) : diff --git a/.github/workflows/main/installArnold.sh b/python/GafferTest/FileSystemPathInOutNode.py old mode 100755 new mode 100644 similarity index 58% rename from .github/workflows/main/installArnold.sh rename to python/GafferTest/FileSystemPathInOutNode.py index 73a2c7e077e..c2748100464 --- a/.github/workflows/main/installArnold.sh +++ b/python/GafferTest/FileSystemPathInOutNode.py @@ -1,7 +1,6 @@ -#! /bin/bash ########################################################################## # -# Copyright (c) 2019, Cinesite VFX Ltd. All rights reserved. +# Copyright (c) 2012, John Haddon. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are @@ -16,7 +15,7 @@ # disclaimer in the documentation and/or other materials provided with # the distribution. # -# * Neither the name of Cinesite VFX Ltd. nor the names of +# * Neither the name of John Haddon nor the names of # any other contributors to this software may be used to endorse or # promote products derived from this software without specific prior # written permission. @@ -35,32 +34,42 @@ # ########################################################################## -set -e +import IECore +import Gaffer -if [ -z $1 ] ; then - echo "Usage : installArnold.sh arnoldVersion" >&2 - exit 1 -fi +class FileSystemPathInOutNode( Gaffer.ComputeNode ) : -arnoldVersion=$1 + def __init__( self, name="FileSystemPathInOutNode", defaultValue="", substitutions = Gaffer.Context.Substitutions.AllSubstitutions ) : -if [[ `uname` = "Linux" ]] ; then - arnoldPlatform=linux -else - arnoldPlatform=darwin -fi + Gaffer.ComputeNode.__init__( self, name ) -url=forgithubci.solidangle.com/arnold/Arnold-${arnoldVersion}-${arnoldPlatform}.tgz + self.addChild( Gaffer.FileSystemPathPlug( "in", Gaffer.Plug.Direction.In, defaultValue, substitutions = substitutions ) ) + self.addChild( Gaffer.FileSystemPathPlug( "out", Gaffer.Plug.Direction.Out ) ) -# Configure the login information, if this has been supplied. -login="" -if [ ! -z "${ARNOLD_LOGIN}" ] && [ ! -z "${ARNOLD_PASSWORD}" ] ; then - login="${ARNOLD_LOGIN}:${ARNOLD_PASSWORD}@" -fi + self.numHashCalls = 0 + self.numComputeCalls = 0 -mkdir -p arnoldRoot/$arnoldVersion && cd arnoldRoot/$arnoldVersion + def affects( self, input ) : -echo Downloading Arnold "https://${url}" -curl -L https://${login}${url} -o Arnold-${arnoldVersion}-${arnoldPlatform}.tgz + outputs = Gaffer.ComputeNode.affects( self, input ) -tar -xzf Arnold-${arnoldVersion}-${arnoldPlatform}.tgz + if input.isSame( self["in"] ) : + outputs.append( self["out"] ) + + return outputs + + def hash( self, output, context, h ) : + + if output.isSame( self["out"] ) : + self["in"].hash( h ) + + self.numHashCalls += 1 + + def compute( self, plug, context ) : + + if plug.isSame( self["out"] ) : + plug.setValue( self["in"].getValue() ) + + self.numComputeCalls += 1 + +IECore.registerRunTimeTyped( FileSystemPathInOutNode, typeName = "GafferTest::FileSystemPathInOutNode" ) diff --git a/python/GafferTest/FileSystemPathPlugTest.py b/python/GafferTest/FileSystemPathPlugTest.py new file mode 100644 index 00000000000..bad933a1802 --- /dev/null +++ b/python/GafferTest/FileSystemPathPlugTest.py @@ -0,0 +1,406 @@ +########################################################################## +# +# Copyright (c) 2012, John Haddon. All rights reserved. +# Copyright (c) 2013, Image Engine Design Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided with +# the distribution. +# +# * Neither the name of John Haddon nor the names of +# any other contributors to this software may be used to endorse or +# promote products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +########################################################################## + +import os +import inspect +import unittest + +import IECore + +import Gaffer +import GafferTest + +class FileSystemPathPlugTest( GafferTest.TestCase ) : + + def testSlashConversion( self ) : + n = GafferTest.FileSystemPathInOutNode() + self.assertHashesValid( n ) + + n["in"].setValue( "C:/path/test.exr" ) + if os.name == "nt" : + self.assertEqual( n["out"].getValue(), os.path.join( "C:", os.path.sep, "path", "test.exr" ) ) + else : + self.assertEqual( n["out"].getValue(), os.path.join( "C:", "path", "test.exr" ) ) + + n2 = GafferTest.FileSystemPathInOutNode() + self.assertHashesValid( n2 ) + + n2["in"].setInput( n["out"] ) + if os.name == "nt" : + self.assertEqual( n2["out"].getValue(), os.path.join( "C:", os.path.sep, "path", "test.exr") ) + else : + self.assertEqual( n2["out"].getValue(), os.path.join( "C:", "path", "test.exr") ) + + n3 = GafferTest.FileSystemPathInOutNode() + self.assertHashesValid( n3 ) + n3["in"].setValue( "relative/path/test.exr" ) + self.assertEqual( n3["out"].getValue(), os.path.join( "relative", "path", "test.exr" ) ) + + n4 = GafferTest.FileSystemPathInOutNode() + self.assertHashesValid( n4 ) + n4["in"].setValue( "C:\\backslash\\should\\work\\too.exr" ) + if os.name == "nt" : + self.assertEqual( n4["out"].getValue(), os.path.join("C:", os.path.sep, "backslash", "should", "work", "too.exr")) + else : + self.assertEqual( n4["out"].getValue(), os.path.join("C:", "backslash", "should", "work", "too.exr")) + + n5 = GafferTest.FileSystemPathInOutNode() + self.assertHashesValid( n5 ) + n4["in"].setValue( "/rooted/path/works.exr" ) + if os.name == "nt" : + self.assertEqual( n4["out"].getValue(), os.path.sep + os.path.sep + os.path.join( "rooted", "path", "works.exr" ) ) + else : + self.assertEqual( n4["out"].getValue(), os.path.join( os.path.sep, "rooted", "path", "works.exr" ) ) + + def testUNC( self ) : + n = GafferTest.FileSystemPathInOutNode() + self.assertHashesValid( n ) + + n["in"].setValue( "//test.server/path/test.exr" ) + self.assertEqual( n["out"].getValue(), os.path.sep + os.path.sep + os.path.join( "test.server", "path", "test.exr" ) ) + + n["in"].setValue( "\\\\back.slash\\should\\work\\too.exr" ) + self.assertEqual( n["out"].getValue(), os.path.sep + os.path.sep + os.path.join( "back.slash", "should", "work", "too.exr" ) ) + + def testStringNodeCompatibility( self ): + n = GafferTest.FileSystemPathInOutNode() + s = GafferTest.StringInOutNode() + s["in"].setValue( "test/string.exr" ) + + n["in"].setInput( s["out"] ) + + self.assertEqual( n["out"].getValue(), os.path.join( "test", "string.exr" ) ) + + def testExpansion( self ) : + + n = GafferTest.FileSystemPathInOutNode() + self.assertHashesValid( n ) + + # nothing should be expanded when we're in a non-computation context + n["in"].setValue( "testyTesty.##.exr" ) + self.assertEqual( n["in"].getValue(), "testyTesty.##.exr" ) + + n["in"].setValue( "${a}/$b/${a:b}" ) + self.assertEqual( n["in"].getValue(), os.path.join("${a}", "$b", "${a:b}" ) ) + + # but expansions should happen magically when the compute() + # calls getValue(). + context = Gaffer.Context() + context.setFrame( 10 ) + n["in"].setValue( "testyTesty.###.exr" ) + with context : + self.assertEqual( n["out"].getValue(), "testyTesty.010.exr" ) + + context["A"] = "apple" + n["in"].setValue( "what/a/lovely/$A" ) + with context : + self.assertEqual( n["out"].getValue(), os.path.join( "what", "a", "lovely", "apple" ) ) + n["in"].setValue( "what/a/lovely/${A}" ) + with context : + self.assertEqual( n["out"].getValue(), os.path.join( "what", "a", "lovely", "apple" ) ) + context["A"] = "peach" + with context : + self.assertEqual( n["out"].getValue(), os.path.join( "what", "a", "lovely", "peach" ) ) + + context["env:dir"] = "a/path" + n["in"].setValue( "a/${env:dir}/b" ) + with context : + self.assertEqual( n["out"].getValue(), os.path.join( "a", "a", "path", "b" ) ) + + n["in"].setValue( "$dontExist" ) + with context : + self.assertEqual( n["out"].getValue(), "" ) + + # once again, nothing should be expanded when we're in a + # non-computation context + n["in"].setValue( "testyTesty.##.exr" ) + self.assertEqual( n["in"].getValue(), "testyTesty.##.exr" ) + + def testRecursiveExpansion( self ) : + + n = GafferTest.FileSystemPathInOutNode() + n["in"].setValue( "$a" ) + + context = Gaffer.Context() + context["a"] = "a$b" + context["b"] = "b" + + with context : + self.assertEqual( n["out"].getValue(), "ab" ) + + def testRecursiveExpansionCycles( self ) : + + n = GafferTest.FileSystemPathInOutNode() + n["in"].setValue( "$a" ) + + context = Gaffer.Context() + context["a"] = "a$b" + context["b"] = "b$a" + + with context : + self.assertRaises( RuntimeError, n["out"].getValue ) + + def testDefaultValueExpansion( self ) : + + n = GafferTest.FileSystemPathInOutNode( defaultValue = "${A}" ) + context = Gaffer.Context() + context["A"] = "b" + with context : + self.assertEqual( n["out"].getValue(), "b" ) + + def testExpansionFromInputConnection( self ) : + + p = Gaffer.FileSystemPathPlug() + p.setValue( "${foo}" ) + + n = GafferTest.FileSystemPathInOutNode() + n["in"].setInput( p ) + + c = Gaffer.Context() + with c : + self.assertEqual( n["out"].getValue(), "" ) + h = n["out"].hash() + + c["foo"] = "foo" + with c : + self.assertNotEqual( n["out"].hash(), h ) + self.assertEqual( n["out"].getValue(), "foo" ) + + def testExpansionMask( self ) : + + n1 = GafferTest.FileSystemPathInOutNode( substitutions = Gaffer.Context.Substitutions.AllSubstitutions ) + n2 = GafferTest.FileSystemPathInOutNode( substitutions = Gaffer.Context.Substitutions.AllSubstitutions & ~Gaffer.Context.Substitutions.FrameSubstitutions ) + + n1["in"].setValue( "hello.####.${ext}" ) + n2["in"].setValue( "hello.####.${ext}" ) + self.assertEqual( n1["out"].getValue(), os.path.expanduser( "hello.0001." ) ) + self.assertEqual( n2["out"].getValue(), os.path.expanduser( "hello.####." ) ) + + c = Gaffer.Context() + c["ext"] = "cob" + c.setFrame( 10 ) + with c : + self.assertEqual( n1["out"].getValue(), os.path.expanduser( "hello.0010.cob" ) ) + self.assertEqual( n2["out"].getValue(), os.path.expanduser( "hello.####.cob" ) ) + + def testSubstitutionsSerialisation( self ) : + + s = Gaffer.ScriptNode() + s["n"] = Gaffer.Node() + s["n"]["p"] = Gaffer.FileSystemPathPlug( + "p", + flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic, + substitutions = Gaffer.Context.Substitutions.AllSubstitutions & ~Gaffer.Context.Substitutions.FrameSubstitutions + ) + self.assertEqual( s["n"]["p"].substitutions(), Gaffer.Context.Substitutions.AllSubstitutions & ~Gaffer.Context.Substitutions.FrameSubstitutions ) + + s2 = Gaffer.ScriptNode() + s2.execute( s.serialise() ) + self.assertEqual( s["n"]["p"].substitutions(), s2["n"]["p"].substitutions() ) + + def testSubstitutionsRepr( self ) : + + p = Gaffer.FileSystemPathPlug( + substitutions = Gaffer.Context.Substitutions.TildeSubstitutions | Gaffer.Context.Substitutions.FrameSubstitutions + ) + + p2 = eval( repr( p ) ) + self.assertEqual( p.substitutions(), p2.substitutions() ) + + def testSubstitutionsCounterpart( self ) : + + p = Gaffer.FileSystemPathPlug( + substitutions = Gaffer.Context.Substitutions.TildeSubstitutions | Gaffer.Context.Substitutions.FrameSubstitutions + ) + + p2 = p.createCounterpart( "p2", p.Direction.In ) + self.assertEqual( p.substitutions(), p2.substitutions() ) + + def testTildeExpansion( self ) : + + n = GafferTest.FileSystemPathInOutNode() + + n["in"].setValue( "~" ) + self.assertEqual( n["out"].getValue(), os.path.expanduser( "~" ) ) + + n["in"].setValue( "~/something.tif" ) + self.assertEqual( n["out"].getValue(), os.path.join( os.path.expanduser( "~"), "something.tif" ) ) + + # ~ shouldn't be expanded unless it's at the front - it would + # be meaningless in other cases. + n["in"].setValue( "in/~1900" ) + self.assertEqual( n["out"].getValue(), os.path.join("in", "~1900" ) ) + + def testEnvironmentExpansion( self ) : + + n = GafferTest.FileSystemPathInOutNode() + + n["in"].setValue( "${NOT_AN_ENVIRONMENT_VARIABLE}" ) + h1 = n["out"].hash() + self.assertEqual( n["out"].getValue(), "" ) + + n["in"].setValue( "${GAFFER_ROOT}" ) + self.assertEqual( n["out"].getValue(), os.environ["GAFFER_ROOT"] ) + h2 = n["out"].hash() + self.assertNotEqual( h1, h2 ) + + context = Gaffer.Context() + context["GAFFER_ROOT"] = "b" + with context : + # context should win against environment + self.assertEqual( n["out"].getValue(), "b" ) + self.assertNotEqual( n["out"].hash(), h1 ) + self.assertNotEqual( n["out"].hash(), h2 ) + + def testSubstitutionsFromExpressionInput( self ) : + + s = Gaffer.ScriptNode() + + # Should output a substituted version of the input. + s["substitionsOn"] = GafferTest.FileSystemPathInOutNode() + + # Should pass through the input directly, without substitutions. + s["substitionsOff"] = GafferTest.FileSystemPathInOutNode( substitutions = Gaffer.Context.Substitutions.NoSubstitutions ) + + # The third case is trickier. The "in" plug on the node + # itself requests no substitutions, but it receives its + # input via an indirect connection with substitutions + # turned on. We resolve this by defining substitutions + # to occur only when observing a value inside a compute, + # and to always be determined by the plug used to access + # the value. A chain of connections can be thought of as + # carrying an unsubstituted string all the way along + # internally, with each plug along the way determining + # the substitutions applied when peeking in to see the value + # at that point. + # + # In practice this works best because typically it is only + # nodes that know when a substitution is relevant, and the + # user shouldn't be burdened with the job of thinking about + # them when making intermediate connections to that node. + s["substitionsOnIndirectly"] = GafferTest.FileSystemPathInOutNode( substitutions = Gaffer.Context.Substitutions.NoSubstitutions ) + s["substitionsOnIndirectly"]["user"]["in"] = Gaffer.FileSystemPathPlug() + s["substitionsOnIndirectly"]["in"].setInput( s["substitionsOnIndirectly"]["user"]["in"] ) + + # All three nodes above receive their input from this expression + # which outputs a sequence value to be substituted (or not). + + s["e"] = Gaffer.Expression() + s["e"].setExpression( inspect.cleandoc( + """ + parent["substitionsOn"]["in"] = "test.#.exr" + parent["substitionsOff"]["in"] = "test.#.exr" + parent["substitionsOnIndirectly"]["user"]["in"] = "test.#.exr" + """ + ) ) + + with Gaffer.Context() as c : + + # Frame 1 + ######### + + c.setFrame( 1 ) + + # The output of the expression itself is not substituted. + # Substitutions occur only on input plugs. + + self.assertEqual( s["substitionsOn"]["in"].getInput().getValue(), "test.#.exr" ) + self.assertEqual( s["substitionsOff"]["in"].getInput().getValue(), "test.#.exr" ) + self.assertEqual( s["substitionsOnIndirectly"]["user"]["in"].getInput().getValue(), "test.#.exr" ) + + # We should get frame numbers out of the substituting node. + + self.assertEqual( s["substitionsOn"]["out"].getValue(), "test.1.exr" ) + substitutionsOnHash1 = s["substitionsOn"]["out"].hash() + self.assertEqual( s["substitionsOn"]["out"].getValue( _precomputedHash = substitutionsOnHash1 ), "test.1.exr" ) + + # We should get sequences out of the non-substituting node. + + self.assertEqual( s["substitionsOff"]["out"].getValue(), "test.#.exr" ) + substitutionsOffHash1 = s["substitionsOff"]["out"].hash() + self.assertEqual( s["substitionsOff"]["out"].getValue( _precomputedHash = substitutionsOffHash1 ), "test.#.exr" ) + self.assertNotEqual( substitutionsOnHash1, substitutionsOffHash1 ) + + # We shouldn't get frame numbers out of the third node, because the + # requirements of the node (no substitutions) trump any upstream opinions. + # Substitutions are performed by the plug during value access, and do not + # affect the actual data flow. + + self.assertEqual( s["substitionsOnIndirectly"]["out"].getValue(), "test.#.exr" ) + substitionsOnIndirectlyHash1 = s["substitionsOnIndirectly"]["out"].hash() + self.assertEqual( s["substitionsOnIndirectly"]["out"].getValue( _precomputedHash = substitionsOnIndirectlyHash1 ), "test.#.exr" ) + + # Frame 2 + ######### + + c.setFrame( 2 ) + + # The output of the expression itself is not substituted. + # Substitutions occur only on input plugs. + + self.assertEqual( s["substitionsOn"]["in"].getInput().getValue(), "test.#.exr" ) + self.assertEqual( s["substitionsOff"]["in"].getInput().getValue(), "test.#.exr" ) + self.assertEqual( s["substitionsOnIndirectly"]["user"]["in"].getInput().getValue(), "test.#.exr" ) + + # We should get frame numbers out of the substituting node. + # The hash must has changed to make this possible. + + self.assertEqual( s["substitionsOn"]["out"].getValue(), "test.2.exr" ) + substitutionsOnHash2 = s["substitionsOn"]["out"].hash() + self.assertEqual( s["substitionsOn"]["out"].getValue( _precomputedHash = substitutionsOnHash2 ), "test.2.exr" ) + self.assertNotEqual( substitutionsOnHash2, substitutionsOnHash1 ) + + # We should still get sequences out of the non-substituting node, + # and it should have the same output hash as it had on frame 1. + + self.assertEqual( s["substitionsOff"]["out"].getValue(), "test.#.exr" ) + substitutionsOffHash2 = s["substitionsOff"]["out"].hash() + self.assertEqual( s["substitionsOff"]["out"].getValue( _precomputedHash = substitutionsOffHash2 ), "test.#.exr" ) + self.assertEqual( substitutionsOffHash1, substitutionsOffHash2 ) + self.assertNotEqual( substitutionsOnHash2, substitutionsOffHash2 ) + + # The third node should still be non-substituting. + + self.assertEqual( s["substitionsOnIndirectly"]["out"].getValue(), "test.#.exr" ) + substitionsOnIndirectlyHash2 = s["substitionsOnIndirectly"]["out"].hash() + self.assertEqual( s["substitionsOnIndirectly"]["out"].getValue( _precomputedHash = substitionsOnIndirectlyHash2 ), "test.#.exr" ) + self.assertEqual( substitionsOnIndirectlyHash2, substitionsOnIndirectlyHash1 ) + + + +if __name__ == "__main__": + unittest.main() diff --git a/python/GafferTest/FileSystemPathTest.py b/python/GafferTest/FileSystemPathTest.py index 82147dcf327..5b657a5462a 100644 --- a/python/GafferTest/FileSystemPathTest.py +++ b/python/GafferTest/FileSystemPathTest.py @@ -38,9 +38,10 @@ import unittest import time import datetime -import pwd -import grp import os +if os.name is not "nt": + import pwd + import grp import IECore @@ -76,6 +77,7 @@ def testConstructWithFilter( self ) : p = Gaffer.FileSystemPath( __file__, filter = f ) self.assertTrue( p.getFilter().isSame( f ) ) + @unittest.skipIf( os.name == "nt", "Windows does not support symbolic links." ) def testBrokenSymbolicLinks( self ) : os.symlink( self.temporaryDirectory() + "/nonExistent", self.temporaryDirectory() + "/broken" ) @@ -97,6 +99,7 @@ def testBrokenSymbolicLinks( self ) : # since we said it was valid, it ought to have some info self.assertIsNotNone( l.info() ) + @unittest.skipIf( os.name == "nt", "Windows does not support symbolic links." ) def testSymLinkInfo( self ) : with open( self.temporaryDirectory() + "/a", "w" ) as f : @@ -121,11 +124,13 @@ def testCopy( self ) : self.assertEqual( p, p2 ) self.assertEqual( str( p ), str( p2 ) ) + self.assertEqual( p.nativeString(), p2.nativeString() ) def testEmptyPath( self ) : p = Gaffer.FileSystemPath() self.assertEqual( str( p ), "" ) + self.assertEqual( p.nativeString(), "" ) self.assertTrue( p.isEmpty() ) self.assertFalse( p.isValid() ) @@ -133,26 +138,59 @@ def testRelativePath( self ) : os.chdir( self.temporaryDirectory() ) - with open( self.temporaryDirectory() + "/a", "w" ) as f : + with open( os.path.join( self.temporaryDirectory(), "a" ), "w" ) as f : f.write( "AAAA" ) p = Gaffer.FileSystemPath( "a" ) self.assertEqual( str( p ), "a" ) + self.assertEqual( p.nativeString(), "a" ) self.assertFalse( p.isEmpty() ) self.assertTrue( p.isValid() ) p2 = Gaffer.FileSystemPath( "nonexistent" ) self.assertEqual( str( p2 ), "nonexistent" ) + self.assertEqual( p2.nativeString(), "nonexistent" ) self.assertFalse( p2.isEmpty() ) self.assertFalse( p2.isValid() ) + def testDriveLetterPath( self ) : + p = Gaffer.FileSystemPath( "C:\\this\\path\\does\\not\\exist.ext" ) + + self.assertEqual( str( p ), "C:/this/path/does/not/exist.ext" ) + if os.name == "nt": + self.assertEqual( p.nativeString(), "C:\\this\\path\\does\\not\\exist.ext") + self.assertFalse( p.isEmpty() ) + self.assertFalse( p.isValid() ) + + def testUNCPath( self ) : + p = Gaffer.FileSystemPath( "\\\\this.server\\path\\does\\not\\exist.ext" ) + + self.assertEqual( str( p ), "//this.server/path/does/not/exist.ext" ) + if os.name == "nt": + self.assertEqual( p.nativeString(), "\\\\this.server\\path\\does\\not\\exist.ext") + self.assertFalse( p.isEmpty() ) + self.assertFalse( p.isValid() ) + + def testPosixPath( self ) : + p = Gaffer.FileSystemPath( "/this/path/does/not/exist.ext" ) + + if os.name == "nt": + self.assertEqual( str( p ), "//this/path/does/not/exist.ext" ) + else: + self.assertEqual( str( p ), "/this/path/does/not/exist.ext" ) + + if os.name is not "nt": + self.assertEqual( p.nativeString(), "/this/path/does/not/exist.ext") + self.assertFalse( p.isEmpty() ) + self.assertFalse( p.isValid() ) + def testRelativePathChildren( self ) : os.chdir( self.temporaryDirectory() ) os.mkdir( "dir" ) - with open( self.temporaryDirectory() + "/dir/a", "w" ) as f : + with open( os.path.join( self.temporaryDirectory(), "dir", "a" ), "w" ) as f : f.write( "AAAA" ) p = Gaffer.FileSystemPath( "dir" ) @@ -160,6 +198,10 @@ def testRelativePathChildren( self ) : c = p.children() self.assertEqual( len( c ), 1 ) self.assertEqual( str( c[0] ), "dir/a" ) + if os.name == "nt": + self.assertEqual( c[0].nativeString(), "dir\\a" ) + else: + self.assertEqual( c[0].nativeString(), "dir/a" ) self.assertTrue( c[0].isValid() ) def testChildrenOfFile( self ) : @@ -172,7 +214,7 @@ def testModificationTimes( self ) : p = Gaffer.FileSystemPath( self.temporaryDirectory() ) p.append( "t" ) - with open( str( p ), "w" ) as f : + with open( p.nativeString(), "w" ) as f : f.write( "AAAA" ) mt = p.property( "fileSystem:modificationTime" ) @@ -181,7 +223,7 @@ def testModificationTimes( self ) : time.sleep( 1 ) - with open( str( p ), "w" ) as f : + with open( p.nativeString(), "w" ) as f : f.write( "BBBB" ) mt = p.property( "fileSystem:modificationTime" ) @@ -193,24 +235,26 @@ def testOwner( self ) : p = Gaffer.FileSystemPath( self.temporaryDirectory() ) p.append( "t" ) - with open( str( p ), "w" ) as f : + with open( p.nativeString(), "w" ) as f : f.write( "AAAA" ) o = p.property( "fileSystem:owner" ) self.assertTrue( isinstance( o, str ) ) - self.assertEqual( o, pwd.getpwuid( os.stat( str( p ) ).st_uid ).pw_name ) + self.assertEqual( o, self.getFileOwner( p.nativeString() ) ) + + @unittest.skipIf( os.name == "nt", "Windows does separate group ownership." ) def testGroup( self ) : p = Gaffer.FileSystemPath( self.temporaryDirectory() ) p.append( "t" ) - with open( str( p ), "w" ) as f : + with open( p.nativeString(), "w" ) as f : f.write( "AAAA" ) g = p.property( "fileSystem:group" ) self.assertTrue( isinstance( g, str ) ) - self.assertEqual( g, grp.getgrgid( os.stat( str( p ) ).st_gid ).gr_name ) + self.assertEqual( g, grp.getgrgid( os.stat( p.nativeString() ).st_gid ).gr_name ) def testPropertyNames( self ) : @@ -230,9 +274,9 @@ def testPropertyNames( self ) : def testSequences( self ) : - os.mkdir( self.temporaryDirectory() + "/dir" ) + os.mkdir( os.path.join( self.temporaryDirectory(), "dir" ) ) for n in [ "singleFile.txt", "a.001.txt", "a.002.txt", "a.004.txt", "b.003.txt" ] : - with open( self.temporaryDirectory() + "/" + n, "w" ) as f : + with open( os.path.join( self.temporaryDirectory(), n ), "w" ) as f : f.write( "AAAA" ) p = Gaffer.FileSystemPath( self.temporaryDirectory(), includeSequences = True ) @@ -242,29 +286,38 @@ def testSequences( self ) : self.assertEqual( len( c ), 8 ) s = sorted( c, key=str ) - self.assertEqual( str(s[0]), self.temporaryDirectory() + "/a.###.txt" ) - self.assertEqual( str(s[1]), self.temporaryDirectory() + "/a.001.txt" ) - self.assertEqual( str(s[2]), self.temporaryDirectory() + "/a.002.txt" ) - self.assertEqual( str(s[3]), self.temporaryDirectory() + "/a.004.txt" ) - self.assertEqual( str(s[4]), self.temporaryDirectory() + "/b.###.txt" ) - self.assertEqual( str(s[5]), self.temporaryDirectory() + "/b.003.txt" ) - self.assertEqual( str(s[6]), self.temporaryDirectory() + "/dir" ) - self.assertEqual( str(s[7]), self.temporaryDirectory() + "/singleFile.txt" ) + self.assertEqual( str(s[0]), self.temporaryDirectory().replace( "\\", "/" ) + "/a.###.txt" ) + self.assertEqual( s[0].nativeString(), os.path.join( self.temporaryDirectory(), "a.###.txt" ) ) + self.assertEqual( str(s[1]), self.temporaryDirectory().replace( "\\", "/" ) + "/a.001.txt" ) + self.assertEqual( s[1].nativeString(), os.path.join( self.temporaryDirectory(), "a.001.txt" ) ) + self.assertEqual( str(s[2]), self.temporaryDirectory().replace( "\\", "/" ) + "/a.002.txt" ) + self.assertEqual( s[2].nativeString(), os.path.join( self.temporaryDirectory(), "a.002.txt" ) ) + self.assertEqual( str(s[3]), self.temporaryDirectory().replace( "\\", "/" ) + "/a.004.txt" ) + self.assertEqual( s[3].nativeString(), os.path.join( self.temporaryDirectory(), "a.004.txt" ) ) + self.assertEqual( str(s[4]), self.temporaryDirectory().replace( "\\", "/" ) + "/b.###.txt" ) + self.assertEqual( s[4].nativeString(), os.path.join( self.temporaryDirectory(), "b.###.txt" ) ) + self.assertEqual( str(s[5]), self.temporaryDirectory().replace( "\\", "/" ) + "/b.003.txt" ) + self.assertEqual( s[5].nativeString(), os.path.join( self.temporaryDirectory(), "b.003.txt" ) ) + self.assertEqual( str(s[6]), self.temporaryDirectory().replace( "\\", "/" ) + "/dir" ) + self.assertEqual( s[6].nativeString(), os.path.join( self.temporaryDirectory(), "dir" ) ) + self.assertEqual( str(s[7]), self.temporaryDirectory().replace( "\\", "/" ) + "/singleFile.txt" ) + self.assertEqual( s[7].nativeString(), os.path.join( self.temporaryDirectory(), "singleFile.txt" ) ) for x in s : self.assertTrue( x.isValid() ) - if not os.path.isdir( str(x) ) : + if not os.path.isdir( x.nativeString() ) : self.assertTrue( x.isLeaf() ) - self.assertEqual( x.property( "fileSystem:owner" ), pwd.getpwuid( os.stat( str( p ) ).st_uid ).pw_name ) - self.assertEqual( x.property( "fileSystem:group" ), grp.getgrgid( os.stat( str( p ) ).st_gid ).gr_name ) + self.assertEqual( x.property( "fileSystem:owner" ), self.getFileOwner( p.nativeString() ) ) + if os.name is not "nt": + self.assertEqual( x.property( "fileSystem:group" ), grp.getgrgid( os.stat( str( p ) ).st_gid ).gr_name ) self.assertLess( (datetime.datetime.utcnow() - x.property( "fileSystem:modificationTime" )).total_seconds(), 2 ) - if "###" not in str(x) : + if "###" not in str( x ) : self.assertFalse( x.isFileSequence() ) self.assertEqual( x.fileSequence(), None ) self.assertEqual( x.property( "fileSystem:frameRange" ), "" ) - if os.path.isdir( str(x) ) : + if os.path.isdir( x.nativeString() ) : self.assertEqual( x.property( "fileSystem:size" ), 0 ) else : self.assertEqual( x.property( "fileSystem:size" ), 4 ) @@ -272,13 +325,13 @@ def testSequences( self ) : self.assertEqual( s[0].property( "fileSystem:frameRange" ), "1-2,4" ) self.assertTrue( s[0].isFileSequence() ) self.assertTrue( isinstance( s[0].fileSequence(), IECore.FileSequence ) ) - self.assertEqual( s[0].fileSequence(), IECore.FileSequence( str(s[0]), IECore.frameListFromList( [ 1, 2, 4 ] ) ) ) + self.assertEqual( s[0].fileSequence(), IECore.FileSequence( s[0].nativeString(), IECore.frameListFromList( [ 1, 2, 4 ] ) ) ) self.assertEqual( s[0].property( "fileSystem:size" ), 4 * 3 ) self.assertEqual( s[4].property( "fileSystem:frameRange" ), "3" ) self.assertTrue( s[4].isFileSequence() ) self.assertTrue( isinstance( s[4].fileSequence(), IECore.FileSequence ) ) - self.assertEqual( s[4].fileSequence(), IECore.FileSequence( str(s[4]), IECore.frameListFromList( [ 3 ] ) ) ) + self.assertEqual( s[4].fileSequence(), IECore.FileSequence( s[4].nativeString(), IECore.frameListFromList( [ 3 ] ) ) ) self.assertEqual( s[4].property( "fileSystem:size" ), 4 ) # make sure we can copy @@ -294,12 +347,18 @@ def testSequences( self ) : self.assertEqual( len( c ), 6 ) s = sorted( c, key=str ) - self.assertEqual( str(s[0]), self.temporaryDirectory() + "/a.001.txt" ) - self.assertEqual( str(s[1]), self.temporaryDirectory() + "/a.002.txt" ) - self.assertEqual( str(s[2]), self.temporaryDirectory() + "/a.004.txt" ) - self.assertEqual( str(s[3]), self.temporaryDirectory() + "/b.003.txt" ) - self.assertEqual( str(s[4]), self.temporaryDirectory() + "/dir" ) - self.assertEqual( str(s[5]), self.temporaryDirectory() + "/singleFile.txt" ) + self.assertEqual( str(s[0]), self.temporaryDirectory().replace( "\\", "/" ) + "/a.001.txt" ) + self.assertEqual( s[0].nativeString(), os.path.join( self.temporaryDirectory(), "a.001.txt" ) ) + self.assertEqual( str(s[1]), self.temporaryDirectory().replace( "\\", "/" ) + "/a.002.txt" ) + self.assertEqual( s[1].nativeString(), os.path.join( self.temporaryDirectory(), "a.002.txt" ) ) + self.assertEqual( str(s[2]), self.temporaryDirectory().replace( "\\", "/" ) + "/a.004.txt" ) + self.assertEqual( s[2].nativeString(), os.path.join( self.temporaryDirectory(), "a.004.txt" ) ) + self.assertEqual( str(s[3]), self.temporaryDirectory().replace( "\\", "/" ) + "/b.003.txt" ) + self.assertEqual( s[3].nativeString(), os.path.join( self.temporaryDirectory(), "b.003.txt" ) ) + self.assertEqual( str(s[4]), self.temporaryDirectory().replace( "\\", "/" ) + "/dir" ) + self.assertEqual( s[4].nativeString(), os.path.join( self.temporaryDirectory(), "dir" ) ) + self.assertEqual( str(s[5]), self.temporaryDirectory().replace( "\\", "/" ) + "/singleFile.txt" ) + self.assertEqual( s[5].nativeString(), os.path.join( self.temporaryDirectory(), "singleFile.txt" ) ) # and we can include them again p.setIncludeSequences( True ) @@ -340,6 +399,11 @@ def testCancellation( self ) : with self.assertRaises( IECore.Cancelled ) : p.property( "fileSystem:modificationTime", c ) + def testTruncateUntilValid( self ): + + p = Gaffer.FileSystemPath( "T" ) + self.assertEqual( str( p.truncateUntilValid() ), "" ) + def setUp( self ) : GafferTest.TestCase.setUp( self ) @@ -348,9 +412,21 @@ def setUp( self ) : def tearDown( self ) : + os.chdir( self.__originalCWD ) + GafferTest.TestCase.tearDown( self ) - os.chdir( self.__originalCWD ) + def getFileOwner( self, filepath ): + + # Windows Python does not have a reliable native method to get the owner + # without installing the Win32 package. Since the files being tested + # are created within the test process, assume the current user is + # an acceptable standin for the file owner + if os.name is not "nt" : + return pwd.getpwuid( os.stat( filepath ).st_uid ).pw_name + else : + return os.environ["USERNAME"] + if __name__ == "__main__": unittest.main() diff --git a/python/GafferTest/HiddenFilePathFilterTest.py b/python/GafferTest/HiddenFilePathFilterTest.py new file mode 100644 index 00000000000..d8e75d547f1 --- /dev/null +++ b/python/GafferTest/HiddenFilePathFilterTest.py @@ -0,0 +1,77 @@ +########################################################################## +# +# Copyright (c) 2022 Hypothetical Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above +# copyright notice, this list of conditions and the following +# disclaimer. +# +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided with +# the distribution. +# +# * Neither the name of John Haddon nor the names of +# any other contributors to this software may be used to endorse or +# promote products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +########################################################################## + +import os +import subprocess +import tempfile +import unittest + +import Gaffer +import GafferTest + +class HiddenFilePathFilterTest( GafferTest.TestCase ) : + + def test( self ) : + + hiddenFile = Gaffer.FileSystemPath( os.path.join( self.temporaryDirectory(), ".sneaky.txt" ) ) + with open( hiddenFile.nativeString(), "w" ) as f : + f.write( "Can't see me" ) + if os.name == "nt" : + subprocess.check_call( [ "attrib", "+H", hiddenFile.nativeString() ] ) + + visibleFile = Gaffer.FileSystemPath( os.path.join( self.temporaryDirectory(), "frank.txt" ) ) + with open( visibleFile.nativeString(), "w" ) as f : + f.write( "Can see me" ) + + p = Gaffer.FileSystemPath( os.path.dirname( hiddenFile.nativeString() ) ) + + self.assertEqual( + sorted( [ str( i ) for i in p.children() ] ), + sorted( [ str( hiddenFile ), str( visibleFile ) ] ) + ) + + h = Gaffer.HiddenFilePathFilter() + p.setFilter( h ) + + self.assertEqual( p.children(), [ hiddenFile ] ) + + h.setInverted( True ) + + self.assertEqual( p.children(), [ visibleFile ] ) + + +if __name__ == "__main__": + unittest.main() diff --git a/python/GafferTest/MetadataAlgoTest.py b/python/GafferTest/MetadataAlgoTest.py index 0bf85be36ec..70b0f1573f0 100644 --- a/python/GafferTest/MetadataAlgoTest.py +++ b/python/GafferTest/MetadataAlgoTest.py @@ -541,11 +541,11 @@ def testNumericBookmarksInReferences( self ) : Gaffer.MetadataAlgo.setNumericBookmark( s, 1, s["box"]["n"] ) - s["box"].exportForReference( self.temporaryDirectory() + "/bookmarked.grf" ) + s["box"].exportForReference( os.path.join( self.temporaryDirectory(), "bookmarked.grf" ) ) # Bring reference back in s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/bookmarked.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "bookmarked.grf" ) ) # Clashing Metadata was completely removed self.assertEqual( Gaffer.Metadata.value( s["r"]["n"], "numericBookmark1" ), None ) @@ -557,7 +557,7 @@ def testNumericBookmarksInReferences( self ) : Gaffer.MetadataAlgo.setNumericBookmark( s, 1, None ) s["r2"] = Gaffer.Reference() - s["r2"].load( self.temporaryDirectory() + "/bookmarked.grf" ) + s["r2"].load( os.path.join( self.temporaryDirectory(), "bookmarked.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s["r2"]["n"], "numericBookmark1" ), None ) self.assertEqual( Gaffer.MetadataAlgo.numericBookmark( s["r2"]["n"] ), 0 ) @@ -573,12 +573,12 @@ def testNumericBookmarksInReadOnlyBox( self ) : Gaffer.MetadataAlgo.setNumericBookmark( s, 1, s["box"]["n"] ) - s["box"].exportForReference( self.temporaryDirectory() + "/bookmarked.grf" ) + s["box"].exportForReference( os.path.join( self.temporaryDirectory(), "bookmarked.grf" ) ) # Bring the box back in, not as a Reference, but as read-only Box s["b1"] = Gaffer.Box() Gaffer.MetadataAlgo.setChildNodesAreReadOnly( s["b1"], True ) - s.executeFile( self.temporaryDirectory() + "/bookmarked.grf", parent = s["b1"], continueOnError = True) + s.executeFile( os.path.join( self.temporaryDirectory(), "bookmarked.grf" ), parent = s["b1"], continueOnError = True) # Clashing Metadata was completely removed self.assertEqual( Gaffer.Metadata.value( s["b1"]["n"], "numericBookmark1" ), None ) @@ -591,7 +591,7 @@ def testNumericBookmarksInReadOnlyBox( self ) : s["b2"] = Gaffer.Box() Gaffer.MetadataAlgo.setChildNodesAreReadOnly( s["b2"], True ) - s.executeFile( self.temporaryDirectory() + "/bookmarked.grf", parent = s["b2"], continueOnError = True) + s.executeFile( os.path.join( self.temporaryDirectory(), "bookmarked.grf" ), parent = s["b2"], continueOnError = True) self.assertEqual( Gaffer.Metadata.value( s["b2"]["n"], "numericBookmark1" ), None ) self.assertEqual( Gaffer.MetadataAlgo.numericBookmark( s["b2"]["n"] ), 0 ) @@ -600,7 +600,7 @@ def testNumericBookmarksInReadOnlyBox( self ) : # But loading it without the read-only flag results in the bookmark being set s["b3"] = Gaffer.Box() - s.executeFile( self.temporaryDirectory() + "/bookmarked.grf", parent = s["b3"], continueOnError = True) + s.executeFile( os.path.join( self.temporaryDirectory(), "bookmarked.grf" ), parent = s["b3"], continueOnError = True) self.assertEqual( Gaffer.Metadata.value( s["b3"]["n"], "numericBookmark1" ), True ) self.assertEqual( Gaffer.MetadataAlgo.numericBookmark( s["b3"]["n"] ), 1 ) diff --git a/python/GafferTest/MetadataTest.py b/python/GafferTest/MetadataTest.py index 90d3057f5e0..ceaa8d9ded8 100644 --- a/python/GafferTest/MetadataTest.py +++ b/python/GafferTest/MetadataTest.py @@ -1052,7 +1052,7 @@ def testOverloadedMethods( self ) : @staticmethod def testPythonUnload() : - subprocess.check_call( [ "gaffer", "python", os.path.dirname( __file__ ) + "/pythonScripts/unloadExceptionScript.py" ] ) + subprocess.check_call( [ "gaffer", "python", os.path.join( os.path.dirname( __file__ ), "pythonScripts", "unloadExceptionScript.py" ) ] ) def testWildcardsAndDot( self ) : diff --git a/python/GafferTest/PathFilterTest.py b/python/GafferTest/PathFilterTest.py index 7fc5075c4aa..913fd22c010 100644 --- a/python/GafferTest/PathFilterTest.py +++ b/python/GafferTest/PathFilterTest.py @@ -35,6 +35,7 @@ # ########################################################################## +import os import unittest import glob @@ -49,28 +50,28 @@ def setUp( self ) : GafferTest.TestCase.setUp( self ) - open( self.temporaryDirectory() + "/a", "w" ) - open( self.temporaryDirectory() + "/b.txt", "w" ) + open( os.path.join( self.temporaryDirectory(), "a" ), "w" ) + open( os.path.join( self.temporaryDirectory(), "b.txt" ), "w" ) def test( self ) : # First, check that we have a mix of extensions in # our test directory. Otherwise we can't test anything. - self.assertTrue( len( glob.glob( self.temporaryDirectory() + "/*" ) ) != len( glob.glob( self.temporaryDirectory() + "/*.txt" ) ) ) + self.assertTrue( len( glob.glob( os.path.join( self.temporaryDirectory(), "*" ) ) ) != len( glob.glob( os.path.join( self.temporaryDirectory(), "*.txt" ) ) ) ) # Check that an unfiltered path can see all the files path = Gaffer.FileSystemPath( self.temporaryDirectory() ) children = path.children() - self.assertEqual( len( children ), len( glob.glob( self.temporaryDirectory() + "/*" ) ) ) + self.assertEqual( len( children ), len( glob.glob( os.path.join( self.temporaryDirectory(), "*" ) ) ) ) # Attach a filter, and check that the files are filtered txtFilter = Gaffer.FileNamePathFilter( [ "*.txt" ] ) path.setFilter( txtFilter ) children = path.children() - self.assertEqual( len( children ), len( glob.glob( self.temporaryDirectory() + "/*.txt" ) ) ) + self.assertEqual( len( children ), len( glob.glob( os.path.join( self.temporaryDirectory(), "*.txt" ) ) ) ) # Copy the path and check the filter is working on the copy pathCopy = path.copy() @@ -79,7 +80,7 @@ def test( self ) : # Detach the filter and check that behaviour has reverted path.setFilter( None ) children = path.children() - self.assertEqual( len( children ), len( glob.glob( self.temporaryDirectory() + "/*" ) ) ) + self.assertEqual( len( children ), len( glob.glob( os.path.join( self.temporaryDirectory(), "*" ) ) ) ) def testEnabledState( self ) : @@ -89,15 +90,15 @@ def testEnabledState( self ) : self.assertEqual( f.getEnabled(), True ) path.setFilter( f ) - self.assertEqual( len( path.children() ), len( glob.glob( self.temporaryDirectory() + "/*.txt" ) ) ) + self.assertEqual( len( path.children() ), len( glob.glob( os.path.join( self.temporaryDirectory(), "*.txt" ) ) ) ) f.setEnabled( False ) self.assertEqual( f.getEnabled(), False ) - self.assertEqual( len( path.children() ), len( glob.glob( self.temporaryDirectory() + "/*" ) ) ) + self.assertEqual( len( path.children() ), len( glob.glob( os.path.join( self.temporaryDirectory(), "*" ) ) ) ) f.setEnabled( True ) self.assertEqual( f.getEnabled(), True ) - self.assertEqual( len( path.children() ), len( glob.glob( self.temporaryDirectory() + "/*.txt" ) ) ) + self.assertEqual( len( path.children() ), len( glob.glob( os.path.join( self.temporaryDirectory(), "*.txt" ) ) ) ) def testChangedSignal( self ) : diff --git a/python/GafferTest/PythonApplicationTest.py b/python/GafferTest/PythonApplicationTest.py index 1688a096cda..d2c9fdf6e70 100644 --- a/python/GafferTest/PythonApplicationTest.py +++ b/python/GafferTest/PythonApplicationTest.py @@ -35,7 +35,11 @@ ########################################################################## import os -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import unittest import GafferTest @@ -44,12 +48,12 @@ class PythonApplicationTest( GafferTest.TestCase ) : def testVariableScope( self ) : - subprocess.check_call( [ "gaffer", "python", os.path.dirname( __file__ ) + "/pythonScripts/variableScope.py" ] ) + subprocess.check_call( [ "gaffer", "python", os.path.join( os.path.dirname( __file__ ), "pythonScripts", "variableScope.py" ) ] ) def testErrorReturnStatus( self ) : p = subprocess.Popen( - [ "gaffer", "python", os.path.dirname( __file__ ) + "/pythonScripts/exception.py" ], + [ "gaffer", "python", os.path.join( os.path.dirname( __file__ ), "pythonScripts", "exception.py" ) ], stderr = subprocess.PIPE, universal_newlines = True, ) @@ -60,11 +64,11 @@ def testErrorReturnStatus( self ) : def testFlagArguments( self ) : - subprocess.check_call( [ "gaffer", "python", os.path.dirname( __file__ ) + "/pythonScripts/flagArguments.py", "-arguments", "-flag1", "-flag2" ] ) + subprocess.check_call( [ "gaffer", "python", os.path.join( os.path.dirname( __file__ ), "pythonScripts", "flagArguments.py" ), "-arguments", "-flag1", "-flag2" ] ) def testName( self ) : - subprocess.check_call( [ "gaffer", "python", os.path.dirname( __file__ ) + "/pythonScripts/name.py" ] ) + subprocess.check_call( [ "gaffer", "python", os.path.join( os.path.dirname( __file__ ), "pythonScripts", "name.py" ) ] ) if __name__ == "__main__": unittest.main() diff --git a/python/GafferTest/ReferenceTest.py b/python/GafferTest/ReferenceTest.py index ab09d14f7b1..feb601bb6fe 100644 --- a/python/GafferTest/ReferenceTest.py +++ b/python/GafferTest/ReferenceTest.py @@ -68,10 +68,10 @@ def testLoad( self ) : b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n1"] ] ) ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( "n1" in s["r"] ) self.assertTrue( s["r"]["sum"].getInput().isSame( s["r"]["n1"]["sum"] ) ) @@ -86,11 +86,11 @@ def testSerialisation( self ) : b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n1"] ] ) ) Gaffer.PlugAlgo.promote( b["n1"]["op1"] ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s = Gaffer.ScriptNode() s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( "n1" in s["r"] ) self.assertTrue( s["r"]["n1"]["op1"].getInput().isSame( s["r"]["op1"] ) ) @@ -127,14 +127,14 @@ def testReload( self ) : b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n2"] ] ) ) Gaffer.PlugAlgo.promote( b["n2"]["op2"] ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2 = Gaffer.ScriptNode() s2["n1"] = GafferTest.AddNode() s2["n3"] = GafferTest.AddNode() s2["n4"] = GafferTest.AddNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2["r"]["op1"].setInput( s2["n1"]["sum"] ) s2["r"]["op2"].setValue( 1001 ) @@ -153,9 +153,9 @@ def testReload( self ) : b["anotherNode"] = GafferTest.AddNode() Gaffer.PlugAlgo.promote( b["anotherNode"]["op2"] ) - s.serialiseToFile( self.temporaryDirectory() + "/test.grf", b ) + s.serialiseToFile( os.path.join( self.temporaryDirectory(), "test.grf" ), b ) - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( "n2" in s2["r"] ) self.assertEqual( set( s2["r"].keys() ), set( originalReferencedNames + [ "anotherNode", "op3" ] ) ) @@ -180,15 +180,15 @@ def testReloadDoesntRemoveCustomPlugs( self ) : s["n2"]["op1"].setInput( s["n1"]["sum"] ) b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n1"] ] ) ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2 = Gaffer.ScriptNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2["r"]["__mySpecialPlug"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( "__mySpecialPlug" in s2["r"] ) @@ -203,11 +203,11 @@ def testLoadScriptWithReference( self ) : b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n2"] ] ) ) Gaffer.PlugAlgo.promote( b["n2"]["op2"] ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2 = Gaffer.ScriptNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2["a"] = GafferTest.AddNode() s2["r"]["op2"].setValue( 123 ) @@ -217,11 +217,11 @@ def testLoadScriptWithReference( self ) : self.assertTrue( "sum" in s2["r"] ) self.assertTrue( s2["r"]["op1"].getInput().isSame( s2["a"]["sum"] ) ) - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.save() s3 = Gaffer.ScriptNode() - s3["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s3["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s3.load() self.assertEqual( s3["r"].keys(), s2["r"].keys() ) @@ -238,11 +238,11 @@ def testReferenceExportCustomPlugsFromBoxes( self ) : b["myCustomPlug"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) b["__invisiblePlugThatShouldntGetExported"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2 = Gaffer.ScriptNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( "myCustomPlug" in s2["r"] ) self.assertTrue( "__invisiblePlugThatShouldntGetExported" not in s2["r"] ) @@ -257,11 +257,11 @@ def testPlugMetadata( self ) : Gaffer.Metadata.registerValue( p, "description", "ppp" ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2 = Gaffer.ScriptNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s2["r"].descendant( p.relativeName( b ) ), "description" ), "ppp" ) @@ -279,11 +279,11 @@ def testMetadataIsntResaved( self ) : Gaffer.Metadata.registerValue( p, "description", "ppp" ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2 = Gaffer.ScriptNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( "description" not in s2.serialise() ) @@ -295,10 +295,10 @@ def testSinglePlugWithMetadata( self ) : Gaffer.Metadata.registerValue( s["b"]["p"], "description", "ddd" ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s["r"]["p"], "description" ), "ddd" ) @@ -315,13 +315,13 @@ def testEditPlugMetadata( self ) : Gaffer.Metadata.registerValue( p, "test", "referenced" ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # Reference it, and check it loaded. s2 = Gaffer.ScriptNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s2["r"]["p"], "test" ), "referenced" ) @@ -338,7 +338,7 @@ def testEditPlugMetadata( self ) : # Reload the reference, and check the edit stays in place. - s3["r"].load( self.temporaryDirectory() + "/test.grf" ) + s3["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s3["r"]["p"], "test" ), "edited" ) def testStaticMetadataRegistrationIsntAnEdit( self ) : @@ -349,12 +349,12 @@ def testStaticMetadataRegistrationIsntAnEdit( self ) : s["b"] = Gaffer.Box() s["b"]["staticMetadataTestPlug"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # Reference it s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # Make a static metadata registration. Although this will # be signalled as a metadata change, it must not be considered @@ -375,13 +375,13 @@ def testAddPlugMetadata( self ) : p = Gaffer.PlugAlgo.promote( b["n1"]["op1"] ) p.setName( "p" ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # Reference it, and check it loaded. s2 = Gaffer.ScriptNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # Add some metadata to the Reference node (not the reference file) @@ -396,7 +396,7 @@ def testAddPlugMetadata( self ) : # Reload the reference, and check the edit stays in place. - s3["r"].load( self.temporaryDirectory() + "/test.grf" ) + s3["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s3["r"]["p"], "test" ), "added" ) def testReloadWithUnconnectedPlugs( self ) : @@ -404,10 +404,10 @@ def testReloadWithUnconnectedPlugs( self ) : s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["p"] = Gaffer.Plug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( s["r"].keys(), [ "user", "p" ] ) @@ -421,17 +421,17 @@ def testReloadRefreshesMetadata( self ) : s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["p"] = Gaffer.Plug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s["r"]["p"], "test" ), None ) Gaffer.Metadata.registerValue( s["b"]["p"], "test", 10 ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s["r"]["p"], "test" ), 10 ) @@ -441,7 +441,7 @@ def testLoadThrowsExceptionsOnError( self ) : s["b"] = Gaffer.Box() s["b"]["n"] = GafferTest.StringInOutNode() - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) del GafferTest.StringInOutNode # induce a failure during loading @@ -449,7 +449,7 @@ def testLoadThrowsExceptionsOnError( self ) : s2["r"] = Gaffer.Reference() with IECore.CapturingMessageHandler() as mh : - self.assertRaises( Exception, s2["r"].load, self.temporaryDirectory() + "/test.grf" ) + self.assertRaises( Exception, s2["r"].load, os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( len( mh.messages ), 2 ) self.assertTrue( "has no attribute 'StringInOutNode'" in mh.messages[0].message ) @@ -464,13 +464,13 @@ def testErrorTolerantLoading( self ) : s["b"]["s"] = GafferTest.StringInOutNode() s["b"]["a"] = GafferTest.AddNode() - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # import it into a script. s2 = Gaffer.ScriptNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( "a" in s2["r"] ) self.assertTrue( isinstance( s2["r"]["a"], GafferTest.AddNode ) ) @@ -478,7 +478,7 @@ def testErrorTolerantLoading( self ) : # save that script, and then mysteriously # disable GafferTest.StringInOutNode. - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.save() del GafferTest.StringInOutNode @@ -487,7 +487,7 @@ def testErrorTolerantLoading( self ) : # load in the other referenced node. s3 = Gaffer.ScriptNode() - s3["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s3["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) with IECore.CapturingMessageHandler() as mh : s3.load( continueOnError=True ) @@ -512,38 +512,38 @@ def testDependencyNode( self ) : s["b"] = Gaffer.Box() s["b"]["n"] = GafferTest.AddNode() Gaffer.PlugAlgo.promote( s["b"]["n"]["sum"] ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # load onto reference: - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( s["r"].correspondingInput( s["r"]["sum"] ), None ) self.assertEqual( s["r"].enabledPlug(), None ) # Wire it up to support enabledPlug() and correspondingInput() Gaffer.PlugAlgo.promote( s["b"]["n"]["op1"] ) s["b"]["n"]["op2"].setValue( 10 ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # reload reference and test: - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( s["r"].correspondingInput( s["r"]["sum"] ), None ) self.assertEqual( s["r"].enabledPlug(), None ) # add an enabled plug: s["b"]["enabled"] = Gaffer.BoolPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # reload reference and test that's now visible via enabledPlug(): - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( s["r"].correspondingInput( s["r"]["sum"] ), None ) self.assertTrue( s["r"].enabledPlug().isSame( s["r"]["enabled"] ) ) # hook up the enabled plug inside the box: s["b"]["n"]["enabled"].setInput( s["b"]["enabled"] ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # reload reference and test that's now visible via enabledPlug(): - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( s["r"].enabledPlug().isSame( s["r"]["enabled"] ) ) self.assertTrue( s["r"].correspondingInput( s["r"]["sum"] ).isSame( s["r"]["op1"] ) ) @@ -565,13 +565,13 @@ def testPlugFlagsOnReload( self ): s["b"]["s"] = GafferTest.StringInOutNode() s["b"]["a"] = GafferTest.AddNode() - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # import it into a script. s2 = Gaffer.ScriptNode() s2["r"] = Gaffer.Reference() - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s2["r"]["__pluggy"] = Gaffer.Plug( flags = Gaffer.Plug.Flags.Dynamic | Gaffer.Plug.Flags.Default ) s2["r"]["__pluggy"]["int"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Dynamic | Gaffer.Plug.Flags.Default ) s2["r"]["__pluggy"]["compound"] = Gaffer.Plug( flags = Gaffer.Plug.Flags.Dynamic | Gaffer.Plug.Flags.Default ) @@ -582,7 +582,7 @@ def testPlugFlagsOnReload( self ): self.assertEqual( s2["r"]["__pluggy"]["compound"].getFlags(), Gaffer.Plug.Flags.Dynamic | Gaffer.Plug.Flags.Default ) self.assertEqual( s2["r"]["__pluggy"]["compound"]["int"].getFlags(), Gaffer.Plug.Flags.Dynamic | Gaffer.Plug.Flags.Default ) - s2["r"].load( self.temporaryDirectory() + "/test.grf" ) + s2["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( s2["r"]["__pluggy"].getFlags(), Gaffer.Plug.Flags.Dynamic | Gaffer.Plug.Flags.Default ) self.assertEqual( s2["r"]["__pluggy"]["int"].getFlags(), Gaffer.Plug.Flags.Dynamic | Gaffer.Plug.Flags.Default ) @@ -597,10 +597,10 @@ def testDefaultValues( self ) : s["b"]["p"].setValue( 2 ) s["b"]["c"] = Gaffer.Color3fPlug( defaultValue = imath.Color3f( 1 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s["b"]["c"].setValue( imath.Color3f( 0.5 ) ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # The value at the time of box export should be ignored, # and the box itself should not be modified by the export @@ -619,7 +619,7 @@ def testDefaultValues( self ) : # And we should be able to save and reload the script # and have that still be the case. - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s.load() @@ -642,8 +642,8 @@ def testDefaultValues( self ) : s["b"]["p"].resetDefault() s["b"]["c"].setValue( imath.Color3f( 0.25 ) ) s["b"]["c"].resetDefault() - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( s["r"]["p"].getValue(), 3 ) self.assertEqual( s["r"]["p"].defaultValue(), 3 ) @@ -708,8 +708,8 @@ def testDefaultValues( self ) : s["b"]["p"].resetDefault() s["b"]["c"].setValue( imath.Color3f( 4 ) ) s["b"]["c"].resetDefault() - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( s["r"]["p"].getValue(), 100 ) self.assertEqual( s["r"]["p"].defaultValue(), 4 ) @@ -738,7 +738,7 @@ def testDefaultValues( self ) : # And there shouldn't be a single setValue() call in the exported file. - e = "".join( open( self.temporaryDirectory() + "/test.grf" ).readlines() ) + e = "".join( open( os.path.join( self.temporaryDirectory(), "test.grf" ) ).readlines() ) self.assertTrue( "setValue" not in e ) def testInternalNodeDefaultValues( self ) : @@ -748,10 +748,10 @@ def testInternalNodeDefaultValues( self ) : s["b"]["n"] = Gaffer.Node() s["b"]["n"]["p"] = Gaffer.IntPlug( defaultValue = 1, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s["b"]["n"]["p"].setValue( 2 ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # Nothing at all should have changed about the # values and defaults on the internal nodes. @@ -762,7 +762,7 @@ def testInternalNodeDefaultValues( self ) : # And we should be able to save and reload the script # and have that still be the case. - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s.load() @@ -777,10 +777,10 @@ def testNodeMetadata( self ) : Gaffer.Metadata.registerValue( s["b"], "description", "Test description" ) Gaffer.Metadata.registerValue( s["b"], "nodeGadget:color", imath.Color3f( 1, 0, 0 ) ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s["r"], "description" ), "Test description" ) self.assertEqual( Gaffer.Metadata.value( s["r"], "nodeGadget:color" ), imath.Color3f( 1, 0, 0 ) ) @@ -789,10 +789,10 @@ def testVersionMetadata( self ) : s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s["r"], "serialiser:milestoneVersion" ), Gaffer.About.milestoneVersion() ) self.assertEqual( Gaffer.Metadata.value( s["r"], "serialiser:majorVersion" ), Gaffer.About.majorVersion() ) @@ -858,22 +858,22 @@ def testPlugCalledFileName( self ) : s["b"] = Gaffer.Box() s["b"]["fileName"] = Gaffer.StringPlug( defaultValue = "iAmUsingThisForMyOwnPurposes", flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( s["r"]["fileName"].getValue(), "iAmUsingThisForMyOwnPurposes" ) def testLoadScriptWithReferenceFromVersion0_14( self ) : shutil.copyfile( - os.path.dirname( __file__ ) + "/references/version-0.14.0.0.grf", - "/tmp/test.grf" + os.path.join( os.path.dirname( __file__ ), "references", "version-0.14.0.0.grf" ), + os.path.join( self.temporaryDirectory(), "test.grf" ) ) s = Gaffer.ScriptNode() - s["fileName"].setValue( os.path.dirname( __file__ ) + "/scripts/referenceVersion-0.14.0.0.gfr" ) + s["fileName"].setValue( os.path.join( os.path.dirname( __file__ ), "scripts", "referenceVersion-0.14.0.0.gfr" ) ) with IECore.CapturingMessageHandler() as mh : s.load( continueOnError = True ) @@ -890,20 +890,20 @@ def testFileNameAccessor( self ) : s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["p"] = Gaffer.Plug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() self.assertEqual( s["r"].fileName(), "" ) - s["r"].load( self.temporaryDirectory() + "/test.grf" ) - self.assertEqual( s["r"].fileName(), self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) + self.assertEqual( s["r"].fileName(), os.path.join( self.temporaryDirectory(), "test.grf" ) ) def testUndo( self ) : s = Gaffer.ScriptNode() s["b"] = Gaffer.Box() s["b"]["p"] = Gaffer.Plug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() self.assertEqual( s["r"].fileName(), "" ) @@ -917,12 +917,12 @@ def referenceLoaded( node ) : c = s["r"].referenceLoadedSignal().connect( referenceLoaded ) with Gaffer.UndoScope( s ) : - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( "p" in s["r"] ) - self.assertEqual( s["r"].fileName(), self.temporaryDirectory() + "/test.grf" ) + self.assertEqual( s["r"].fileName(), os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( len( states ), 1 ) - self.assertEqual( states[0], State( [ "user", "p" ], self.temporaryDirectory() + "/test.grf" ) ) + self.assertEqual( states[0], State( [ "user", "p" ], os.path.join( self.temporaryDirectory(), "test.grf" ) ) ) s.undo() self.assertEqual( s["r"].fileName(), "" ) @@ -932,9 +932,9 @@ def referenceLoaded( node ) : s.redo() self.assertTrue( "p" in s["r"] ) - self.assertEqual( s["r"].fileName(), self.temporaryDirectory() + "/test.grf" ) + self.assertEqual( s["r"].fileName(), os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( len( states ), 3 ) - self.assertEqual( states[2], State( [ "user", "p" ], self.temporaryDirectory() + "/test.grf" ) ) + self.assertEqual( states[2], State( [ "user", "p" ], os.path.join( self.temporaryDirectory(), "test.grf" ) ) ) def testUserPlugsNotReferenced( self ) : @@ -943,10 +943,10 @@ def testUserPlugsNotReferenced( self ) : s["b"] = Gaffer.Box() s["b"]["user"]["a"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) self.assertTrue( "a" in s["b"]["user"] ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( "a" not in s["r"]["user"] ) a = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) @@ -956,7 +956,7 @@ def testUserPlugsNotReferenced( self ) : self.assertTrue( s["r"]["user"]["a"].isSame( a ) ) self.assertTrue( s["r"]["user"]["b"].isSame( b ) ) - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( s["r"]["user"]["a"].isSame( a ) ) self.assertTrue( s["r"]["user"]["b"].isSame( b ) ) @@ -975,10 +975,10 @@ def testCopyPaste( self ) : s["b"]["a2"] = GafferTest.AddNode() s["b"]["a2"]["op1"].setInput( s["b"]["a1"]["sum"] ) Gaffer.PlugAlgo.promote( s["b"]["a1"]["op1"] ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s.execute( s.serialise( parent = s["r"], filter = Gaffer.StandardSet( [ s["r"]["a1"], s["r"]["a2"] ] ) ) ) @@ -993,18 +993,18 @@ def testReloadWithNestedInputConnections( self ) : s["b"] = Gaffer.Box() s["b"]["array"] = Gaffer.ArrayPlug( element = Gaffer.IntPlug(), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s["b"]["color"] = Gaffer.Color3fPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["a"] = GafferTest.AddNode() s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"]["array"][0].setInput( s["a"]["sum"] ) s["r"]["array"][1].setInput( s["a"]["sum"] ) s["r"]["color"]["g"].setInput( s["a"]["sum"] ) - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( s["r"]["array"][0].getInput().isSame( s["a"]["sum"] ) ) self.assertTrue( s["r"]["array"][1].getInput().isSame( s["a"]["sum"] ) ) @@ -1019,16 +1019,16 @@ def testReloadWithNestedOutputConnections( self ) : direction = Gaffer.Plug.Direction.Out, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["a"] = GafferTest.AddNode() s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["a"]["op1"].setInput( s["r"]["color"]["g"] ) - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( s["a"]["op1"].getInput().isSame( s["r"]["color"]["g"] ) ) @@ -1049,7 +1049,7 @@ def testReloadWithBoxIO( self ) : s["b"]["o"].setup( s["b"]["a"]["sum"] ) s["b"]["o"]["in"].setInput( s["b"]["a"]["sum"] ) - referenceFileName = self.temporaryDirectory() + "/test.grf" + referenceFileName = os.path.join( self.temporaryDirectory(), "test.grf" ) s["b"].exportForReference( referenceFileName ) s["a1"] = GafferTest.AddNode() @@ -1132,10 +1132,10 @@ def testHasMetadataEdit( self ) : Gaffer.Metadata.registerValue( s["b"]["p1"], "referenced", "original" ) Gaffer.Metadata.registerValue( s["b"]["p2"], "referenced", "original" ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertFalse( s["r"].hasMetadataEdit( s["r"]["p1"], "referenced" ) ) self.assertFalse( s["r"].hasMetadataEdit( s["r"]["p2"], "referenced" ) ) @@ -1201,10 +1201,10 @@ def testHasMetadataEditAfterReload( self ) : s["b"]["p"] = Gaffer.IntPlug( defaultValue = 1, flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) Gaffer.Metadata.registerValue( s["b"]["p"], "referenced", "original" ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertFalse( s["r"].hasMetadataEdit( s["r"]["p"], "referenced" ) ) self.assertEqual( Gaffer.Metadata.value( s["r"]["p"], "referenced" ), "original" ) @@ -1214,7 +1214,7 @@ def testHasMetadataEditAfterReload( self ) : self.assertTrue( s["r"].hasMetadataEdit( s["r"]["p"], "referenced" ) ) self.assertEqual( Gaffer.Metadata.value( s["r"]["p"], "referenced" ), "override" ) - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # The old plug doesn't have an edit any more, because # it doesn't even belong to the reference any more. @@ -1234,10 +1234,10 @@ def testPlugMetadataOverrides( self ) : Gaffer.Metadata.registerValue( s["b"]["p"], "preset:Green", 1 ) Gaffer.Metadata.registerValue( s["b"]["p"], "preset:Blue", 2 ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # Make sure the metadata exported on the plug was loaded by the Reference self.assertEqual( Gaffer.Metadata.value( s["r"]["p"], "preset:Red" ), 0 ) @@ -1255,8 +1255,8 @@ def testPlugMetadataOverrides( self ) : # When creating new Reference, the data on the new instance is as per the referenced box. Gaffer.Metadata.registerValue( s["b"]["p"], "preset:Blue", 42 ) - s["b"].exportForReference( self.temporaryDirectory() + "/test2.grf" ) - s["r"].load( self.temporaryDirectory() + "/test2.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test2.grf" ) ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test2.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s["r"]["p"], "preset:Red" ), 0 ) self.assertEqual( Gaffer.Metadata.value( s["r"]["p"], "preset:Green" ), 100 ) @@ -1304,10 +1304,10 @@ def testChildPlugMetadata( self ) : s["b"] = Gaffer.Box() s["b"]["p"] = Gaffer.Color3fPlug( defaultValue = imath.Color3f( 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) Gaffer.Metadata.registerValue( s["r"]["p"]["r"], "isRed", True ) @@ -1318,7 +1318,7 @@ def testChildPlugMetadata( self ) : self.assertEqual( Gaffer.Metadata.value( s2["r"]["p"]["r"], "isRed" ), True ) # It also needs to be transferred on reload - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( Gaffer.Metadata.value( s["r"]["p"]["r"], "isRed" ), True ) def testUserPlugMetadataSerialisation( self ) : @@ -1350,12 +1350,12 @@ def testPlugPromotionPreservesMetadata( self ) : s["b"]["p"] = Gaffer.Color3fPlug( defaultValue = imath.Color3f( 0 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) Gaffer.Metadata.registerValue( s["b"]["p"], "isColor", True ) - s["b"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + s["b"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["b2"] = Gaffer.Box() s["b2"]["r"] = Gaffer.Reference() - s["b2"]["r"].load( self.temporaryDirectory() + "/test.grf" ) + s["b2"]["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) Gaffer.PlugAlgo.promote( s["b2"]["r"]["p"] ) @@ -1384,10 +1384,10 @@ def testPromotedSpreadsheetDefaultValues( self ) : Gaffer.PlugAlgo.promote( script["box"]["spreadsheet"]["rows"] ) script["box"]["rows"].resetDefault() - script["box"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + script["box"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) script["reference"] = Gaffer.Reference() - script["reference"].load( self.temporaryDirectory() + "/test.grf" ) + script["reference"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertEqual( len( script["reference"]["rows"] ), len( script["box"]["rows"] ) ) self.assertEqual( script["reference"]["rows"][0].keys(), script["box"]["rows"][0].keys() ) @@ -1426,10 +1426,10 @@ def testPromotedSpreadsheetCopyPaste( self ) : script["box"]["spreadsheet"]["rows"].addRow() Gaffer.PlugAlgo.promote( script["box"]["spreadsheet"]["rows"] ) - script["box"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + script["box"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) script["reference"] = Gaffer.Reference() - script["reference"].load( self.temporaryDirectory() + "/test.grf" ) + script["reference"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) script["reference"]["rows"][1]["cells"]["string"]["value"].setValue( "test" ) script.execute( script.serialise( filter = Gaffer.StandardSet( [ script["reference"] ] ) ) ) @@ -1448,10 +1448,10 @@ def testTransformPlugs( self ) : script["box"]["t3"] = Gaffer.TransformPlug( defaultTranslate = imath.V3f( 10, 11, 12 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) script["box"]["t3"]["rotate"].setValue( imath.V3f( 1, 2, 3 ) ) - script["box"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + script["box"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) script["reference"] = Gaffer.Reference() - script["reference"].load( self.temporaryDirectory() + "/test.grf" ) + script["reference"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( script["reference"]["t2"].isSetToDefault() ) for name in script["reference"]["t2"].keys() : @@ -1475,10 +1475,10 @@ def testCompoundDataPlugs( self ) : script["box"]["p"]["m"]["value"].setValue( 11 ) script["box"]["p"]["m"]["enabled"].setValue( False ) - script["box"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + script["box"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) script["reference"] = Gaffer.Reference() - script["reference"].load( self.temporaryDirectory() + "/test.grf" ) + script["reference"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( script["reference"]["p"].isSetToDefault() ) self.assertEqual( script["reference"]["p"].defaultHash(), script["box"]["p"].defaultHash() ) @@ -1497,13 +1497,13 @@ def testPromotedSpreadsheetDuplicateAsBox( self ) : Gaffer.PlugAlgo.promote( script["box"]["spreadsheet"]["rows"] ) script["box"]["rows"].resetDefault() - script["box"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + script["box"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) # Reference and then duplicate as box. This is using the same # method as used by the "Duplicate as Box" menu in the UI. script["reference"] = Gaffer.Reference() - script["reference"].load( self.temporaryDirectory() + "/test.grf" ) + script["reference"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) script["duplicate"] = Gaffer.Box() script.executeFile( script["reference"].fileName(), parent = script["duplicate"] ) @@ -1537,10 +1537,10 @@ def testSpreadsheetWithMixedDefaultAndValueEdits( self ) : promoted[1]["cells"]["c1"]["value"]["z"].setValue( 4 ) promoted[1]["cells"]["c1"]["value"]["z"].resetDefault() # Modified default. Should be preserved on export. - script["box"].exportForReference( self.temporaryDirectory() + "/test.grf" ) + script["box"].exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) script["reference"] = Gaffer.Reference() - script["reference"].load( self.temporaryDirectory() + "/test.grf" ) + script["reference"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( script["reference"]["rows"].isSetToDefault() ) self.assertEqual( script["reference"]["rows"][1]["cells"]["c1"]["value"]["x"].getValue(), 1 ) @@ -1774,20 +1774,20 @@ def testChildNodesAreReadOnlyMetadata( self ) : b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n1"] ] ) ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r1"] = Gaffer.Reference() - s["r1"].load( self.temporaryDirectory() + "/test.grf" ) + s["r1"].load( os.path.join( self.temporaryDirectory(), "test.grf" ) ) self.assertTrue( Gaffer.MetadataAlgo.getChildNodesAreReadOnly( s["r1"] ) ) # bake in the metadata into the Box to test if it will be handled by the Reference Gaffer.MetadataAlgo.setChildNodesAreReadOnly( b, False ) - b.exportForReference( self.temporaryDirectory() + "/testWithMetadata.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "testWithMetadata.grf" ) ) s["r2"] = Gaffer.Reference() - s["r2"].load( self.temporaryDirectory() + "/testWithMetadata.grf" ) + s["r2"].load( os.path.join( self.temporaryDirectory(), "testWithMetadata.grf" ) ) self.assertTrue( Gaffer.MetadataAlgo.getChildNodesAreReadOnly( s["r2"] ) ) @@ -1798,7 +1798,7 @@ def tearDown( self ) : GafferTest.StringInOutNode = self.__StringInOutNode for f in ( - "/tmp/test.grf", + os.path.join( self.temporaryDirectory(), "test.grf" ), ) : if os.path.exists( f ) : os.remove( f ) diff --git a/python/GafferTest/ScriptNodeTest.py b/python/GafferTest/ScriptNodeTest.py index 0ac4bb462f7..3ffc38779ca 100644 --- a/python/GafferTest/ScriptNodeTest.py +++ b/python/GafferTest/ScriptNodeTest.py @@ -67,7 +67,7 @@ def test( self ) : s = Gaffer.ScriptNode() self.assertEqual( s.getName(), "ScriptNode" ) - self.assertEqual( s["fileName"].typeName(), "Gaffer::StringPlug" ) + self.assertEqual( s["fileName"].typeName(), "Gaffer::FileSystemPathPlug" ) def testExecution( self ) : @@ -210,11 +210,11 @@ def testSaveAndLoad( self ) : s["a2"]["op1"].setInput( s["a1"]["sum"] ) s["a2"]["op2"].setValue( 10 ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s2 = Gaffer.ScriptNode() - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.load() self.assertTrue( s2["a2"]["op1"].getInput().isSame( s2["a1"]["sum"] ) ) @@ -224,7 +224,7 @@ def testLoadClearsFirst( self ) : s = Gaffer.ScriptNode() s["a1"] = GafferTest.AddNode() - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s.load() @@ -405,11 +405,11 @@ def testFrameRangeLoadAndSave( self ) : self.assertEqual( s["frameRange"]["start"].getValue(), 110 ) self.assertEqual( s["frameRange"]["end"].getValue(), 200 ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s2 = Gaffer.ScriptNode() - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.load() self.assertEqual( s2["frameRange"]["start"].getValue(), 110 ) @@ -610,11 +610,11 @@ def testDynamicPlugSaveAndLoad( self ) : s["customSetting"] = Gaffer.IntPlug( flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) s["customSetting"].setValue( 100 ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s2 = Gaffer.ScriptNode() - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.load() self.assertEqual( s2["customSetting"].getValue(), 100 ) @@ -815,16 +815,16 @@ def testLoadingMovedScriptDoesntKeepOldFileName( self ) : s = Gaffer.ScriptNode() s["n"] = Gaffer.Node() - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() - shutil.move( self.temporaryDirectory() + "/test.gfr", self.temporaryDirectory() + "/test2.gfr" ) + shutil.move( os.path.join( self.temporaryDirectory(), "test.gfr" ), os.path.join( self.temporaryDirectory(), "test2.gfr" ) ) s = Gaffer.ScriptNode() - s["fileName"].setValue( self.temporaryDirectory() + "/test2.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test2.gfr" ) ) s.load() - self.assertEqual( s["fileName"].getValue(), self.temporaryDirectory() + "/test2.gfr" ) + self.assertEqual( s["fileName"].getValue(), os.path.join( self.temporaryDirectory(), "test2.gfr" ) ) def testUnsavedChanges( self ) : @@ -842,7 +842,7 @@ def testUnsavedChanges( self ) : s["node"] = GafferTest.AddNode() self.assertEqual( s["unsavedChanges"].getValue(), True ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() self.assertEqual( s["unsavedChanges"].getValue(), False ) @@ -897,20 +897,20 @@ def testSerialiseToFile( self ) : s["n2"] = GafferTest.AddNode() s["n2"]["op1"].setInput( s["n1"]["sum"] ) - s.serialiseToFile( self.temporaryDirectory() + "/test.gfr" ) + s.serialiseToFile( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2 = Gaffer.ScriptNode() - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.load() self.assertTrue( "n1" in s2 ) self.assertTrue( "n2" in s2 ) self.assertTrue( s2["n2"]["op1"].getInput().isSame( s2["n1"]["sum"] ) ) - s.serialiseToFile( self.temporaryDirectory() + "/test.gfr", filter = Gaffer.StandardSet( [ s["n2"] ] ) ) + s.serialiseToFile( os.path.join( self.temporaryDirectory(), "test.gfr" ), filter = Gaffer.StandardSet( [ s["n2"] ] ) ) s3 = Gaffer.ScriptNode() - s3["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s3["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s3.load() self.assertTrue( "n1" not in s3 ) @@ -924,13 +924,13 @@ def testExecuteFile( self ) : s["n2"] = GafferTest.AddNode() s["n2"]["op1"].setInput( s["n1"]["sum"] ) - s.serialiseToFile( self.temporaryDirectory() + "/test.gfr" ) + s.serialiseToFile( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2 = Gaffer.ScriptNode() self.assertRaises( RuntimeError, s2.executeFile, "thisFileDoesntExist.gfr" ) - s2.executeFile( self.temporaryDirectory() + "/test.gfr" ) + s2.executeFile( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) self.assertTrue( s2["n2"]["op1"].getInput().isSame( s2["n1"]["sum"] ) ) @@ -997,11 +997,11 @@ def testCustomVariables( self ) : p["value"].setValue( 20 ) self.assertEqual( s.context().get( "test" ), 20 ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s2 = Gaffer.ScriptNode() - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.load() self.assertEqual( s2["variables"][p.getName()]["value"].getValue(), 20 ) @@ -1012,7 +1012,7 @@ def testFileNameVariables( self ) : s = Gaffer.ScriptNode() self.assertEqual( s.context().get( "script:name" ), "" ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) self.assertEqual( s.context().get( "script:name" ), "test" ) def testReloadWithCustomVariables( self ) : @@ -1020,7 +1020,7 @@ def testReloadWithCustomVariables( self ) : s = Gaffer.ScriptNode() s["variables"].addChild( Gaffer.NameValuePlug( "test", IECore.IntData( 10 ), flags = Gaffer.Plug.Flags.Default | Gaffer.Plug.Flags.Dynamic ) ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s["variables"][0]["value"].setValue( 100 ) @@ -1037,11 +1037,11 @@ def testLoadCustomVariablesWithDefaultValues( self ) : s["variables"].addChild( p ) self.assertEqual( s.context().get( "test" ), 10 ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s2 = Gaffer.ScriptNode() - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.load() self.assertEqual( s2["variables"][p.getName()]["value"].getValue(), 10 ) @@ -1146,7 +1146,7 @@ def testErrorTolerantExecution( self ) : s["n"] = GafferTest.AddNode() with IECore.CapturingMessageHandler() as c : - s.execute( 'parent["n"]["op1"].setValue( 101 )\niWillFail(); parent["n"]["op2"].setValue( 102 )', continueOnError=True ) + s.execute( 'parent["n"]["op1"].setValue( 101 )\niWillFail()\nparent["n"]["op2"].setValue( 102 )', continueOnError=True ) self.assertEqual( s["n"]["op1"].getValue(), 101 ) self.assertEqual( s["n"]["op2"].getValue(), 102 ) @@ -1180,7 +1180,7 @@ def testFileVersioning( self ) : self.assertEqual( Gaffer.Metadata.value( s, "serialiser:minorVersion" ), None ) self.assertEqual( Gaffer.Metadata.value( s, "serialiser:patchVersion" ), None ) - s.serialiseToFile( self.temporaryDirectory() + "/test.gfr" ) + s.serialiseToFile( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) self.assertEqual( Gaffer.Metadata.value( s, "serialiser:milestoneVersion" ), None ) self.assertEqual( Gaffer.Metadata.value( s, "serialiser:majorVersion" ), None ) @@ -1188,7 +1188,7 @@ def testFileVersioning( self ) : self.assertEqual( Gaffer.Metadata.value( s, "serialiser:patchVersion" ), None ) s2 = Gaffer.ScriptNode() - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.load() self.assertEqual( Gaffer.Metadata.value( s2, "serialiser:milestoneVersion" ), Gaffer.About.milestoneVersion() ) @@ -1196,7 +1196,7 @@ def testFileVersioning( self ) : self.assertEqual( Gaffer.Metadata.value( s2, "serialiser:minorVersion" ), Gaffer.About.minorVersion() ) self.assertEqual( Gaffer.Metadata.value( s2, "serialiser:patchVersion" ), Gaffer.About.patchVersion() ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s2.load() @@ -1217,11 +1217,11 @@ def testFileVersioningUpdatesOnSave( self ) : self.assertEqual( Gaffer.Metadata.value( s, "serialiser:minorVersion" ), 0 ) self.assertEqual( Gaffer.Metadata.value( s, "serialiser:patchVersion" ), 0 ) - s["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s.save() s2 = Gaffer.ScriptNode() - s2["fileName"].setValue( self.temporaryDirectory() + "/test.gfr" ) + s2["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test.gfr" ) ) s2.load() self.assertEqual( Gaffer.Metadata.value( s2, "serialiser:milestoneVersion" ), Gaffer.About.milestoneVersion() ) @@ -1306,7 +1306,7 @@ def testLineNumberForExecutionSyntaxError( self ) : def testFileNameInExecutionError( self ) : - fileName = self.temporaryDirectory() + "/test.gfr" + fileName = os.path.join( self.temporaryDirectory(), "test.gfr" ) with open( fileName, "w" ) as f : f.write( "a = 10\n" ) f.write( "a = iDontExist\n" ) @@ -1350,10 +1350,11 @@ def f( script, child ) : b = Gaffer.Box.create( s, Gaffer.StandardSet( [ s["n1"] ] ) ) Gaffer.PlugAlgo.promote( b["n1"]["op1"] ) - b.exportForReference( self.temporaryDirectory() + "/test.grf" ) + b.exportForReference( os.path.join( self.temporaryDirectory(), "test.grf" ) ) s["r"] = Gaffer.Reference() - s["r"].load( self.temporaryDirectory() + "/test.grf" ) + # since this will be a Gaffer native path, ensure it only has / on all OS + s["r"].load( os.path.join( self.temporaryDirectory(), "test.grf" ).replace( "\\", "/" ) ) s["r"]["op1"].setInput( s["n"]["sum"] ) @@ -1474,7 +1475,7 @@ def testImport( self ) : s1["frameRange"]["end"].setValue( 101 ) s1["variables"].addChild( Gaffer.NameValuePlug( "test", "test" ) ) - fileName = self.temporaryDirectory() + "/toImport.gfr" + fileName = os.path.join( self.temporaryDirectory(), "toImport.gfr" ) s1.serialiseToFile( fileName ) s2 = Gaffer.ScriptNode() @@ -1489,7 +1490,7 @@ def testImport( self ) : def testReadOnlyMetadata( self ) : - fileName = self.temporaryDirectory() + "/test.gfr" + fileName = os.path.join( self.temporaryDirectory(), "test.gfr" ) s = Gaffer.ScriptNode() self.assertFalse( Gaffer.MetadataAlgo.getReadOnly( s ) ) @@ -1511,7 +1512,7 @@ def testReadOnlyMetadata( self ) : s.load() self.assertTrue( Gaffer.MetadataAlgo.getReadOnly( s ) ) - s["fileName"].setValue( self.temporaryDirectory() + "/test2.gfr" ) + s["fileName"].setValue( os.path.join( self.temporaryDirectory(), "test2.gfr" ) ) self.assertFalse( Gaffer.MetadataAlgo.getReadOnly( s ) ) def testDisableContextVariable( self ) : diff --git a/python/GafferTest/StatsApplicationTest.py b/python/GafferTest/StatsApplicationTest.py index c2af1410812..55b4972e165 100644 --- a/python/GafferTest/StatsApplicationTest.py +++ b/python/GafferTest/StatsApplicationTest.py @@ -36,7 +36,12 @@ import re import unittest -import subprocess32 as subprocess +import os +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import Gaffer import GafferTest @@ -55,10 +60,11 @@ def test( self ) : script["b"] = Gaffer.Box() script["b"]["n"] = GafferTest.AddNode() - script["fileName"].setValue( self.temporaryDirectory() + "/script.gfr" ) + script["fileName"].setValue( os.path.join( self.temporaryDirectory(), "script.gfr" ) ) script.save() - o = subprocess.check_output( [ "gaffer", "stats", script["fileName"].getValue() ], universal_newlines = True ) + executable = "gaffer" if os.name != "nt" else "gaffer.bat" + o = subprocess.check_output( [ executable, "stats", script["fileName"].getValue() ], universal_newlines = True ) self.assertTrue( Gaffer.About.versionString() in o ) self.assertTrue( re.search( r"frameRange\.start\s*10", o ) ) diff --git a/python/GafferTest/__init__.py b/python/GafferTest/__init__.py index a4c0db0176e..5fdc743348f 100644 --- a/python/GafferTest/__init__.py +++ b/python/GafferTest/__init__.py @@ -164,6 +164,9 @@ def inCI( platforms = set() ) : from .SpreadsheetTest import SpreadsheetTest from .ShufflePlugTest import ShufflePlugTest from .EditScopeTest import EditScopeTest +from .FileSystemPathInOutNode import FileSystemPathInOutNode +from .FileSystemPathPlugTest import FileSystemPathPlugTest +from .HiddenFilePathFilterTest import HiddenFilePathFilterTest from .IECorePreviewTest import * diff --git a/python/GafferUI/ApplicationMenu.py b/python/GafferUI/ApplicationMenu.py index ff51abad6ed..aa5b21d06c7 100644 --- a/python/GafferUI/ApplicationMenu.py +++ b/python/GafferUI/ApplicationMenu.py @@ -47,7 +47,7 @@ def appendDefinitions( menuDefinition, prefix ) : menuDefinition.append( prefix + "/About Gaffer...", { "command" : about } ) menuDefinition.append( prefix + "/Preferences...", { "command" : preferences } ) - menuDefinition.append( prefix + "/Documentation...", { "command" : functools.partial( GafferUI.showURL, os.path.expandvars( "$GAFFER_ROOT/doc/gaffer/html/index.html" ) ) } ) + menuDefinition.append( prefix + "/Documentation...", { "command" : functools.partial( GafferUI.showURL, os.path.join( os.environ["GAFFER_ROOT"], "doc", "gaffer", "html", "index.html" ) ) } ) menuDefinition.append( prefix + "/Quit", { "command" : quit, "shortCut" : "Ctrl+Q" } ) def quit( menu ) : diff --git a/python/GafferUI/Backups.py b/python/GafferUI/Backups.py index a61ffda15ee..a9a3429d73b 100644 --- a/python/GafferUI/Backups.py +++ b/python/GafferUI/Backups.py @@ -46,6 +46,9 @@ import stat import weakref +if os.name == "nt": + import ctypes + class Backups( object ) : def __init__( self, applicationRoot ) : @@ -95,6 +98,11 @@ def backup( self, script ) : dirName = os.path.dirname( fileName ) try : os.makedirs( dirName ) + # Avoid the win32 module dependency by using ctypes to make directory hidden + # The magic number 2 comes from https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-setfileattributesa + if os.name == "nt": + ctypes.windll.kernel32.SetFileAttributesW( unicode( dirName, "utf-8" ), 2 ) + except OSError : # makedirs very unhelpfully raises an exception if # the directory already exists, but it might also @@ -266,7 +274,7 @@ def __potentialFileNames( self, script ) : context = Gaffer.Context() context["script:name"] = os.path.splitext( os.path.basename( fileName ) )[0] - context["script:directory"] = os.path.dirname( os.path.abspath( fileName ) ) + context["script:directory"] = os.path.dirname( os.path.abspath( fileName ) ).replace( "\\", "/" ) pattern = self.__settings["fileName"].getValue() fileNames = [] diff --git a/python/GafferUI/DocumentationAlgo.py b/python/GafferUI/DocumentationAlgo.py index 1da75d8306e..a357e8b9f0f 100644 --- a/python/GafferUI/DocumentationAlgo.py +++ b/python/GafferUI/DocumentationAlgo.py @@ -318,6 +318,11 @@ def __cmark() : return __cmarkDLL __cmarkDLL.cmark_markdown_to_html.restype = ctypes.c_char_p - __cmarkDLL.cmark_markdown_to_html.argtypes = [ctypes.c_char_p, ctypes.c_long, ctypes.c_long] + # The second argument is 'size_t len', the length of the markdown string + # MSVC defines size_t as unsigned int64 + if sys == "Windows" : + __cmarkDLL.cmark_markdown_to_html.argtypes = [ctypes.c_char_p, ctypes.c_ulonglong, ctypes.c_long] + else: + __cmarkDLL.cmark_markdown_to_html.argtypes = [ctypes.c_char_p, ctypes.c_long, ctypes.c_long] return __cmarkDLL diff --git a/python/GafferUI/FileSystemPathPlugValueWidget.py b/python/GafferUI/FileSystemPathPlugValueWidget.py index 0a40d60a64a..6fe0ada2519 100644 --- a/python/GafferUI/FileSystemPathPlugValueWidget.py +++ b/python/GafferUI/FileSystemPathPlugValueWidget.py @@ -130,3 +130,5 @@ def __metadataValue( self, name ) : v = Gaffer.Metadata.value( self.getPlug(), "fileSystemPathPlugValueWidget:" + name ) return v + +GafferUI.PlugValueWidget.registerType( Gaffer.FileSystemPathPlug, FileSystemPathPlugValueWidget ) diff --git a/python/GafferUI/GLWidget.py b/python/GafferUI/GLWidget.py index 9ece1f99357..806af0049fb 100644 --- a/python/GafferUI/GLWidget.py +++ b/python/GafferUI/GLWidget.py @@ -35,6 +35,7 @@ # ########################################################################## +import os import sys import logging import collections @@ -255,8 +256,9 @@ def resizeEvent( self, event ) : # clear any existing errors that may trigger # error checking code in _resize implementations. - while GL.glGetError() : - pass + if os.name == 'posix': + while GL.glGetError() : + pass owner._makeCurrent() diff --git a/python/GafferUI/NodeUI.py b/python/GafferUI/NodeUI.py index 4c226ce3e9f..93b04d13503 100644 --- a/python/GafferUI/NodeUI.py +++ b/python/GafferUI/NodeUI.py @@ -45,7 +45,7 @@ def __documentationURL( node ) : - fileName = "$GAFFER_ROOT/doc/gaffer/html/Reference/NodeReference/" + node.typeName().replace( "::", "/" ) + ".html" + fileName = os.path.join( os.environ["GAFFER_ROOT"], "doc", "gaffer", "html", "Reference", "NodeReference", node.typeName().replace( "::", os.sep ) + ".html" ) fileName = os.path.expandvars( fileName ) return "file://" + fileName if os.path.isfile( fileName ) else "" diff --git a/python/GafferUI/UserPlugs.py b/python/GafferUI/UserPlugs.py index 30de2a130fd..142cc955ae5 100644 --- a/python/GafferUI/UserPlugs.py +++ b/python/GafferUI/UserPlugs.py @@ -53,6 +53,7 @@ def appendPlugCreationMenuDefinitions( plugParent, menuDefinition, prefix = "" ) menuDefinition.append( prefix + "/NumericDivider", { "divider" : True } ) menuDefinition.append( prefix + "/String", { "command" : functools.partial( __addPlug, plugParent, Gaffer.StringPlug ), "active" : active } ) + menuDefinition.append( prefix + "/FileSystemPath", { "command" : functools.partial(__addPlug, plugParent, Gaffer.FileSystemPathPlug ), "active" : active } ) menuDefinition.append( prefix + "/StringDivider", { "divider" : True } ) menuDefinition.append( prefix + "/V2i", { "command" : functools.partial( __addPlug, plugParent, Gaffer.V2iPlug ), "active" : active } ) diff --git a/python/GafferUI/_StyleSheet.py b/python/GafferUI/_StyleSheet.py index ad1c5c8889e..57da2f9c377 100644 --- a/python/GafferUI/_StyleSheet.py +++ b/python/GafferUI/_StyleSheet.py @@ -139,7 +139,7 @@ } substitutions = { - "GAFFER_ROOT" : os.environ["GAFFER_ROOT"] + "GAFFER_ROOT" : os.environ["GAFFER_ROOT"] if os.name == 'posix' else os.environ["GAFFER_ROOT"].replace("\\", "/"), } for k, v in _styleColors.items() : diff --git a/python/GafferVDBTest/VDBTestCase.py b/python/GafferVDBTest/VDBTestCase.py index f00c6975789..96a47113a14 100644 --- a/python/GafferVDBTest/VDBTestCase.py +++ b/python/GafferVDBTest/VDBTestCase.py @@ -35,7 +35,11 @@ ########################################################################## import os -import subprocess32 as subprocess +import sys +if os.name == 'posix' and sys.version_info[0] < 3: + import subprocess32 as subprocess +else: + import subprocess import IECore import GafferScene diff --git a/python/IECoreArnold/__init__.py b/python/IECoreArnold/__init__.py index 4d4e111728a..12b47d48954 100644 --- a/python/IECoreArnold/__init__.py +++ b/python/IECoreArnold/__init__.py @@ -39,14 +39,16 @@ # See comments in `GafferArnold/__init__.py` import sys import ctypes - originalDLOpenFlags = sys.getdlopenflags() - sys.setdlopenflags( originalDLOpenFlags & ~ctypes.RTLD_GLOBAL ) + if sys.platform != "win32": + originalDLOpenFlags = sys.getdlopenflags() + sys.setdlopenflags( originalDLOpenFlags & ~ctypes.RTLD_GLOBAL ) from ._IECoreArnold import * finally : - - sys.setdlopenflags( originalDLOpenFlags ) - del sys, ctypes, originalDLOpenFlags + if sys.platform != "win32": + sys.setdlopenflags( originalDLOpenFlags ) + del originalDLOpenFlags + del sys, ctypes from .UniverseBlock import UniverseBlock diff --git a/src/Gaffer/ApplicationRoot.cpp b/src/Gaffer/ApplicationRoot.cpp index f005b4f8105..b993bde15bc 100644 --- a/src/Gaffer/ApplicationRoot.cpp +++ b/src/Gaffer/ApplicationRoot.cpp @@ -36,6 +36,7 @@ ////////////////////////////////////////////////////////////////////////// #include "Gaffer/ApplicationRoot.h" +#include "Gaffer/FileSystemPath.h" #include "Gaffer/Preferences.h" @@ -129,15 +130,19 @@ std::string ApplicationRoot::preferencesLocation() const throw IECore::Exception( "$HOME environment variable not set" ); } - std::string result = home; - result += "/gaffer/startup/" + getName().string(); + FileSystemPath result( home ); + result.append( "gaffer" ); + result.append( "startup" ); + result.append( getName().string() ); - boost::filesystem::create_directories( result ); + boost::filesystem::create_directories( result.string() ); - return result; + return result.nativeString(); } std::string ApplicationRoot::defaultPreferencesFileName() const { - return preferencesLocation() + "/preferences.py"; + FileSystemPath result( preferencesLocation() ); + result.append( "preferences.py" ); + return result.nativeString(); } diff --git a/src/Gaffer/Context.cpp b/src/Gaffer/Context.cpp index 31c447e49cf..b6306c4ee08 100644 --- a/src/Gaffer/Context.cpp +++ b/src/Gaffer/Context.cpp @@ -48,6 +48,7 @@ #ifdef __APPLE__ #include static char **environ = *_NSGetEnviron(); +#elif _MSC_VER #else #include #endif @@ -167,7 +168,7 @@ void Context::Value::validate( const IECore::InternedString &name ) const typeFunctions( m_typeId ).validate( name, *this ); } -Context::Value::TypeMap &Context::Value::typeMap() +GAFFER_API Context::Value::TypeMap &Context::Value::typeMap() { static TypeMap m_map; return m_map; diff --git a/src/Gaffer/FileSystemPath.cpp b/src/Gaffer/FileSystemPath.cpp index 38fb4a8c171..5dc6b394fb8 100644 --- a/src/Gaffer/FileSystemPath.cpp +++ b/src/Gaffer/FileSystemPath.cpp @@ -39,6 +39,7 @@ #include "Gaffer/CompoundPathFilter.h" #include "Gaffer/FileSequencePathFilter.h" +#include "Gaffer/HiddenFilePathFilter.h" #include "Gaffer/MatchPatternPathFilter.h" #include "Gaffer/PathFilter.h" @@ -50,9 +51,19 @@ #include "boost/date_time/posix_time/conversion.hpp" #include "boost/filesystem.hpp" #include "boost/filesystem/operations.hpp" +#include "boost/regex.hpp" + +#ifndef _MSC_VER + #include + #include +#else +#include +#include +#include +#include "accctrl.h" +#include "aclapi.h" +#endif -#include -#include #include using namespace std; @@ -70,6 +81,12 @@ static InternedString g_modificationTimePropertyName( "fileSystem:modificationTi static InternedString g_sizePropertyName( "fileSystem:size" ); static InternedString g_frameRangePropertyName( "fileSystem:frameRange" ); +static InternedString g_windowsSeparator( "\\" ); +static InternedString g_genericSeparator( "/" ); +static InternedString g_uncPrefix( "\\\\" ); +static InternedString g_uncGenericPrefix( "//" ); +static boost::regex g_driveLetterPattern{ "[A-Za-z]:" }; + FileSystemPath::FileSystemPath( PathFilterPtr filter, bool includeSequences ) : Path( filter ), m_includeSequences( includeSequences ) { @@ -78,6 +95,7 @@ FileSystemPath::FileSystemPath( PathFilterPtr filter, bool includeSequences ) FileSystemPath::FileSystemPath( const std::string &path, PathFilterPtr filter, bool includeSequences ) : Path( path, filter ), m_includeSequences( includeSequences ) { + setFromString( path ); } FileSystemPath::FileSystemPath( const Names &names, const IECore::InternedString &root, PathFilterPtr filter, bool includeSequences ) @@ -89,6 +107,60 @@ FileSystemPath::~FileSystemPath() { } +// Create a path that is aware of differences in OS naming schemes. +// Linux and MacOS can have a relative path with no root, or a path rooted at "/" : +// Windows can have a relative path with no root, a path rooted at a drive letter followed by a colon +// or a path rooted at a server name and share name (UNC paths). + +void FileSystemPath::setFromString(const std::string &string) +{ + Names newNames; + std::string sanitizedString = string; + + boost::replace_all( sanitizedString, g_windowsSeparator.c_str(), g_genericSeparator.c_str() ); + +#ifdef _MSC_VER + // If `string` is coming from a PathMatcher, it will always have a single leading slash. + // On Windows, interpret that to be the start of a UNC path. + if( sanitizedString.size() && sanitizedString[0] == '/' && !boost::starts_with( sanitizedString, "//" ) ) + { + sanitizedString = "/" + sanitizedString; + } +#endif + + StringAlgo::tokenize(sanitizedString, '/', back_inserter(newNames)); + + InternedString newRoot; + if ( newNames.size() && boost::regex_match( newNames[0].string(), g_driveLetterPattern ) ) + { + newRoot = newNames[0]; + newNames.erase( newNames.begin() ); + } + else if ( boost::starts_with( sanitizedString, "//" ) ) + { + // The server name and share name are both required before the path is valid. + if( newNames.size() > 1 ) + { + newRoot = newNames[0].string() + g_genericSeparator.string() + newNames[1].string(); + newNames.erase( newNames.begin(), newNames.begin() + 2 ); + } + } + else if( sanitizedString.size() && sanitizedString[0] == '/' ) + { + newRoot = g_genericSeparator; + } + + if (newRoot == this->root() && newNames == this->names() ) + { + return; + } + + set( 0, this->names().size(), newNames ); + setRoot( newRoot ); + + emitPathChanged(); +} + bool FileSystemPath::isValid( const IECore::Canceller *canceller ) const { if( !Path::isValid() ) @@ -101,7 +173,11 @@ bool FileSystemPath::isValid( const IECore::Canceller *canceller ) const return true; } +#ifndef _MSC_VER const file_type t = symlink_status( path( this->string() ) ).type(); +#else + const file_type t = status( path( this->string() ) ).type(); +#endif return t != status_error && t != file_not_found; } @@ -147,7 +223,7 @@ FileSequencePtr FileSystemPath::fileSequence() const FileSequencePtr sequence = nullptr; /// \todo Add cancellation support to `ls`. - IECore::ls( this->string(), sequence, /* minSequenceSize = */ 1 ); + IECore::ls( this->nativeString(), sequence, /* minSequenceSize = */ 1 ); return sequence; } @@ -186,10 +262,7 @@ IECore::ConstRunTimeTypedPtr FileSystemPath::property( const IECore::InternedStr for( std::vector::iterator it = files.begin(); it != files.end(); ++it ) { IECore::Canceller::check( canceller ); - struct stat s; - stat( it->c_str(), &s ); - struct passwd *pw = getpwuid( s.st_uid ); - std::string value = pw ? pw->pw_name : ""; + std::string value = getOwner( it->c_str() ); std::pair::iterator,bool> oIt = ownerCounter.insert( std::pair( value, 0 ) ); oIt.first->second++; if( oIt.first->second > maxCount ) @@ -203,10 +276,8 @@ IECore::ConstRunTimeTypedPtr FileSystemPath::property( const IECore::InternedStr } std::string n = this->string(); - struct stat s; - stat( n.c_str(), &s ); - struct passwd *pw = getpwuid( s.st_uid ); - return new StringData( pw ? pw->pw_name : "" ); + + return new StringData( getOwner( n.c_str() ) ); } else if( name == g_groupPropertyName ) { @@ -228,8 +299,12 @@ IECore::ConstRunTimeTypedPtr FileSystemPath::property( const IECore::InternedStr IECore::Canceller::check( canceller ); struct stat s; stat( it->c_str(), &s ); + #ifndef _MSC_VER struct group *gr = getgrgid( s.st_gid ); std::string value = gr ? gr->gr_name : ""; + #else + std::string value = ""; + #endif std::pair::iterator,bool> oIt = ownerCounter.insert( std::pair( value, 0 ) ); oIt.first->second++; if( oIt.first->second > maxCount ) @@ -245,8 +320,12 @@ IECore::ConstRunTimeTypedPtr FileSystemPath::property( const IECore::InternedStr std::string n = this->string(); struct stat s; stat( n.c_str(), &s ); + #ifndef _MSC_VER struct group *gr = getgrgid( s.st_gid ); return new StringData( gr ? gr->gr_name : "" ); + #else + return new StringData( "" ); + #endif } else if( name == g_modificationTimePropertyName ) { @@ -350,7 +429,7 @@ void FileSystemPath::doChildren( std::vector &children, const IECore::C { IECore::Canceller::check( canceller ); std::vector sequences; - IECore::ls( p.string(), sequences, /* minSequenceSize */ 1 ); + IECore::ls( this->nativeString(), sequences, /* minSequenceSize */ 1 ); for( std::vector::iterator it = sequences.begin(); it != sequences.end(); ++it ) { IECore::Canceller::check( canceller ); @@ -407,8 +486,7 @@ PathFilterPtr FileSystemPath::createStandardFilter( const std::vector