diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:47:37 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:47:37 +0000 |
commit | 00e2eb4fd0266c5be01e3a527a66aaad5ab4b634 (patch) | |
tree | a6a58bd544eb0b76b9d3acc678ea88791acca045 /src/python | |
parent | Initial commit. (diff) | |
download | libixion-00e2eb4fd0266c5be01e3a527a66aaad5ab4b634.tar.xz libixion-00e2eb4fd0266c5be01e3a527a66aaad5ab4b634.zip |
Adding upstream version 0.19.0.upstream/0.19.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/python')
-rw-r--r-- | src/python/Makefile.am | 35 | ||||
-rw-r--r-- | src/python/Makefile.in | 1145 | ||||
-rw-r--r-- | src/python/document.cpp | 313 | ||||
-rw-r--r-- | src/python/document.hpp | 21 | ||||
-rw-r--r-- | src/python/global.cpp | 39 | ||||
-rw-r--r-- | src/python/global.hpp | 45 | ||||
-rw-r--r-- | src/python/python.cpp | 174 | ||||
-rw-r--r-- | src/python/sheet.cpp | 376 | ||||
-rw-r--r-- | src/python/sheet.hpp | 44 | ||||
-rw-r--r-- | src/python/test-env.sh | 9 |
10 files changed, 2201 insertions, 0 deletions
diff --git a/src/python/Makefile.am b/src/python/Makefile.am new file mode 100644 index 0000000..1dc98c4 --- /dev/null +++ b/src/python/Makefile.am @@ -0,0 +1,35 @@ +if BUILD_PYTHON + +EXTRA_DIST = test-env.sh + +pyexec_LTLIBRARIES = ixion.la +ixion_la_SOURCES = \ + document.hpp \ + document.cpp \ + global.hpp \ + global.cpp \ + python.cpp \ + sheet.hpp \ + sheet.cpp + +ixion_la_LDFLAGS = -module -avoid-version -export-symbols-regex PyInit_ixion +ixion_la_CPPFLAGS = -I$(top_srcdir)/include $(PYTHON_CFLAGS) $(MDDS_CFLAGS) +ixion_la_LIBADD = \ + ../libixion/libixion-@IXION_API_VERSION@.la \ + $(PYTHON_LIBS) + +if OSX + +TESTS = ../../bin/run-python-test-osx.sh + +else + +AM_TESTS_ENVIRONMENT = . $(srcdir)/test-env.sh; + +TESTS = \ + ../../test/python/document.py \ + ../../test/python/module.py + +endif + +endif diff --git a/src/python/Makefile.in b/src/python/Makefile.in new file mode 100644 index 0000000..11b660a --- /dev/null +++ b/src/python/Makefile.in @@ -0,0 +1,1145 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/python +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \ + $(top_srcdir)/m4/ax_cxx_compile_stdcxx_17.m4 \ + $(top_srcdir)/m4/boost.m4 $(top_srcdir)/m4/libtool.m4 \ + $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ + $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +am__installdirs = "$(DESTDIR)$(pyexecdir)" +LTLIBRARIES = $(pyexec_LTLIBRARIES) +am__DEPENDENCIES_1 = +@BUILD_PYTHON_TRUE@ixion_la_DEPENDENCIES = ../libixion/libixion-@IXION_API_VERSION@.la \ +@BUILD_PYTHON_TRUE@ $(am__DEPENDENCIES_1) +am__ixion_la_SOURCES_DIST = document.hpp document.cpp global.hpp \ + global.cpp python.cpp sheet.hpp sheet.cpp +@BUILD_PYTHON_TRUE@am_ixion_la_OBJECTS = ixion_la-document.lo \ +@BUILD_PYTHON_TRUE@ ixion_la-global.lo ixion_la-python.lo \ +@BUILD_PYTHON_TRUE@ ixion_la-sheet.lo +ixion_la_OBJECTS = $(am_ixion_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +ixion_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(ixion_la_LDFLAGS) $(LDFLAGS) -o $@ +@BUILD_PYTHON_TRUE@am_ixion_la_rpath = -rpath $(pyexecdir) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/ixion_la-document.Plo \ + ./$(DEPDIR)/ixion_la-global.Plo \ + ./$(DEPDIR)/ixion_la-python.Plo ./$(DEPDIR)/ixion_la-sheet.Plo +am__mv = mv -f +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) +LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CXXFLAGS) $(CXXFLAGS) +AM_V_CXX = $(am__v_CXX_@AM_V@) +am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@) +am__v_CXX_0 = @echo " CXX " $@; +am__v_CXX_1 = +CXXLD = $(CXX) +CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CXXLD = $(am__v_CXXLD_@AM_V@) +am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@) +am__v_CXXLD_0 = @echo " CXXLD " $@; +am__v_CXXLD_1 = +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(ixion_la_SOURCES) +DIST_SOURCES = $(am__ixion_la_SOURCES_DIST) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red='[0;31m'; \ + grn='[0;32m'; \ + lgn='[1;32m'; \ + blu='[1;34m'; \ + mgn='[0;35m'; \ + brg='[1m'; \ + std='[m'; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' +RECHECK_LOGS = $(TEST_LOGS) +AM_RECURSIVE_TARGETS = check recheck +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \ + $(top_srcdir)/test-driver +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AS = @AS@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BOOST_CPPFLAGS = @BOOST_CPPFLAGS@ +BOOST_FILESYSTEM_LDFLAGS = @BOOST_FILESYSTEM_LDFLAGS@ +BOOST_FILESYSTEM_LDPATH = @BOOST_FILESYSTEM_LDPATH@ +BOOST_FILESYSTEM_LIBS = @BOOST_FILESYSTEM_LIBS@ +BOOST_LDPATH = @BOOST_LDPATH@ +BOOST_PROGRAM_OPTIONS_LDFLAGS = @BOOST_PROGRAM_OPTIONS_LDFLAGS@ +BOOST_PROGRAM_OPTIONS_LDPATH = @BOOST_PROGRAM_OPTIONS_LDPATH@ +BOOST_PROGRAM_OPTIONS_LIBS = @BOOST_PROGRAM_OPTIONS_LIBS@ +BOOST_ROOT = @BOOST_ROOT@ +BOOST_SYSTEM_LDFLAGS = @BOOST_SYSTEM_LDFLAGS@ +BOOST_SYSTEM_LDPATH = @BOOST_SYSTEM_LDPATH@ +BOOST_SYSTEM_LIBS = @BOOST_SYSTEM_LIBS@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DISTCHECK_CONFIGURE_FLAGS = @DISTCHECK_CONFIGURE_FLAGS@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +GREP = @GREP@ +HAVE_CXX17 = @HAVE_CXX17@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +IXION_API_VERSION = @IXION_API_VERSION@ +IXION_MAJOR_API_VERSION = @IXION_MAJOR_API_VERSION@ +IXION_MAJOR_VERSION = @IXION_MAJOR_VERSION@ +IXION_MICRO_VERSION = @IXION_MICRO_VERSION@ +IXION_MINOR_API_VERSION = @IXION_MINOR_API_VERSION@ +IXION_MINOR_VERSION = @IXION_MINOR_VERSION@ +IXION_VERSION = @IXION_VERSION@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MDDS_CFLAGS = @MDDS_CFLAGS@ +MDDS_LIBS = @MDDS_LIBS@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +POW_LIB = @POW_LIB@ +PYTHON = @PYTHON@ +PYTHON_CFLAGS = @PYTHON_CFLAGS@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_LIBS = @PYTHON_LIBS@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VULKAN_CFLAGS = @VULKAN_CFLAGS@ +VULKAN_LIBS = @VULKAN_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +@BUILD_PYTHON_TRUE@EXTRA_DIST = test-env.sh +@BUILD_PYTHON_TRUE@pyexec_LTLIBRARIES = ixion.la +@BUILD_PYTHON_TRUE@ixion_la_SOURCES = \ +@BUILD_PYTHON_TRUE@ document.hpp \ +@BUILD_PYTHON_TRUE@ document.cpp \ +@BUILD_PYTHON_TRUE@ global.hpp \ +@BUILD_PYTHON_TRUE@ global.cpp \ +@BUILD_PYTHON_TRUE@ python.cpp \ +@BUILD_PYTHON_TRUE@ sheet.hpp \ +@BUILD_PYTHON_TRUE@ sheet.cpp + +@BUILD_PYTHON_TRUE@ixion_la_LDFLAGS = -module -avoid-version -export-symbols-regex PyInit_ixion +@BUILD_PYTHON_TRUE@ixion_la_CPPFLAGS = -I$(top_srcdir)/include $(PYTHON_CFLAGS) $(MDDS_CFLAGS) +@BUILD_PYTHON_TRUE@ixion_la_LIBADD = \ +@BUILD_PYTHON_TRUE@ ../libixion/libixion-@IXION_API_VERSION@.la \ +@BUILD_PYTHON_TRUE@ $(PYTHON_LIBS) + +@BUILD_PYTHON_TRUE@@OSX_FALSE@TESTS = \ +@BUILD_PYTHON_TRUE@@OSX_FALSE@ ../../test/python/document.py \ +@BUILD_PYTHON_TRUE@@OSX_FALSE@ ../../test/python/module.py + +@BUILD_PYTHON_TRUE@@OSX_TRUE@TESTS = ../../bin/run-python-test-osx.sh +@BUILD_PYTHON_TRUE@@OSX_FALSE@AM_TESTS_ENVIRONMENT = . $(srcdir)/test-env.sh; +all: all-am + +.SUFFIXES: +.SUFFIXES: .cpp .lo .log .o .obj .test .test$(EXEEXT) .trs +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/python/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/python/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +install-pyexecLTLIBRARIES: $(pyexec_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(pyexecdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pyexecdir)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pyexecdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pyexecdir)"; \ + } + +uninstall-pyexecLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(pyexec_LTLIBRARIES)'; test -n "$(pyexecdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pyexecdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pyexecdir)/$$f"; \ + done + +clean-pyexecLTLIBRARIES: + -test -z "$(pyexec_LTLIBRARIES)" || rm -f $(pyexec_LTLIBRARIES) + @list='$(pyexec_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } + +ixion.la: $(ixion_la_OBJECTS) $(ixion_la_DEPENDENCIES) $(EXTRA_ixion_la_DEPENDENCIES) + $(AM_V_CXXLD)$(ixion_la_LINK) $(am_ixion_la_rpath) $(ixion_la_OBJECTS) $(ixion_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_la-document.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_la-global.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_la-python.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ixion_la-sheet.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.cpp.o: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $< + +.cpp.obj: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.cpp.lo: +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $< + +ixion_la-document.lo: document.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_la-document.lo -MD -MP -MF $(DEPDIR)/ixion_la-document.Tpo -c -o ixion_la-document.lo `test -f 'document.cpp' || echo '$(srcdir)/'`document.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_la-document.Tpo $(DEPDIR)/ixion_la-document.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='document.cpp' object='ixion_la-document.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_la-document.lo `test -f 'document.cpp' || echo '$(srcdir)/'`document.cpp + +ixion_la-global.lo: global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_la-global.lo -MD -MP -MF $(DEPDIR)/ixion_la-global.Tpo -c -o ixion_la-global.lo `test -f 'global.cpp' || echo '$(srcdir)/'`global.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_la-global.Tpo $(DEPDIR)/ixion_la-global.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='global.cpp' object='ixion_la-global.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_la-global.lo `test -f 'global.cpp' || echo '$(srcdir)/'`global.cpp + +ixion_la-python.lo: python.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_la-python.lo -MD -MP -MF $(DEPDIR)/ixion_la-python.Tpo -c -o ixion_la-python.lo `test -f 'python.cpp' || echo '$(srcdir)/'`python.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_la-python.Tpo $(DEPDIR)/ixion_la-python.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='python.cpp' object='ixion_la-python.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_la-python.lo `test -f 'python.cpp' || echo '$(srcdir)/'`python.cpp + +ixion_la-sheet.lo: sheet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ixion_la-sheet.lo -MD -MP -MF $(DEPDIR)/ixion_la-sheet.Tpo -c -o ixion_la-sheet.lo `test -f 'sheet.cpp' || echo '$(srcdir)/'`sheet.cpp +@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ixion_la-sheet.Tpo $(DEPDIR)/ixion_la-sheet.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='sheet.cpp' object='ixion_la-sheet.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ixion_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ixion_la-sheet.lo `test -f 'sheet.cpp' || echo '$(srcdir)/'`sheet.cpp + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ + done; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ + else \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ + fi; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ + else \ + color_start= color_end=; \ + fi; \ + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary"$(AM_TESTSUITE_SUMMARY_HEADER)"$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 + +check-TESTS: + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +../../test/python/document.py.log: ../../test/python/document.py + @p='../../test/python/document.py'; \ + b='../../test/python/document.py'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +../../test/python/module.py.log: ../../test/python/module.py + @p='../../test/python/module.py'; \ + b='../../test/python/module.py'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +../../bin/run-python-test-osx.sh.log: ../../bin/run-python-test-osx.sh + @p='../../bin/run-python-test-osx.sh'; \ + b='../../bin/run-python-test-osx.sh'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile $(LTLIBRARIES) +installdirs: + for dir in "$(DESTDIR)$(pyexecdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-pyexecLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/ixion_la-document.Plo + -rm -f ./$(DEPDIR)/ixion_la-global.Plo + -rm -f ./$(DEPDIR)/ixion_la-python.Plo + -rm -f ./$(DEPDIR)/ixion_la-sheet.Plo + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-pyexecLTLIBRARIES + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/ixion_la-document.Plo + -rm -f ./$(DEPDIR)/ixion_la-global.Plo + -rm -f ./$(DEPDIR)/ixion_la-python.Plo + -rm -f ./$(DEPDIR)/ixion_la-sheet.Plo + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-pyexecLTLIBRARIES + +.MAKE: check-am install-am install-strip + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-TESTS \ + check-am clean clean-generic clean-libtool \ + clean-pyexecLTLIBRARIES cscopelist-am ctags ctags-am distclean \ + distclean-compile distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am html html-am info info-am \ + install install-am install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-pyexecLTLIBRARIES install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + recheck tags tags-am uninstall uninstall-am \ + uninstall-pyexecLTLIBRARIES + +.PRECIOUS: Makefile + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/python/document.cpp b/src/python/document.cpp new file mode 100644 index 0000000..48d1073 --- /dev/null +++ b/src/python/document.cpp @@ -0,0 +1,313 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "document.hpp" +#include "sheet.hpp" +#include "global.hpp" + +#include "ixion/formula.hpp" +#include "ixion/exceptions.hpp" +#include "ixion/config.hpp" + +#include <iostream> +#include <vector> +#include <algorithm> +#include <sstream> + +using namespace std; + +namespace ixion { namespace python { + +namespace { + +/** non-python part of the document data */ +struct document_data +{ + document_global m_global; + vector<PyObject*> m_sheets; + + ~document_data(); +}; + +struct free_pyobj +{ + void operator() (PyObject* p) + { + Py_XDECREF(p); + } +}; + +document_data::~document_data() +{ + for_each(m_sheets.begin(), m_sheets.end(), free_pyobj()); +} + +/** + * Python Document object. + */ +struct pyobj_document +{ + PyObject_HEAD + + document_data* m_data; +}; + +void document_dealloc(pyobj_document* self) +{ + delete self->m_data; + Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); +} + +PyObject* document_new(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwargs*/) +{ + pyobj_document* self = (pyobj_document*)type->tp_alloc(type, 0); + self->m_data = new document_data; + return reinterpret_cast<PyObject*>(self); +} + +int document_init(pyobj_document* self, PyObject* /*args*/, PyObject* /*kwargs*/) +{ + return 0; +} + +PyObject* document_append_sheet(pyobj_document* self, PyObject* args) +{ + char* sheet_name = nullptr; + if (!PyArg_ParseTuple(args, "s", &sheet_name)) + { + PyErr_SetString(PyExc_TypeError, "The method must be given a sheet name string"); + return nullptr; + } + + assert(sheet_name); + + PyTypeObject* sheet_type = get_sheet_type(); + if (!sheet_type) + return nullptr; + + PyObject* obj_sheet = sheet_type->tp_new(sheet_type, args, 0); + if (!obj_sheet) + { + PyErr_SetString(PyExc_RuntimeError, + "Failed to allocate memory for the new sheet object."); + return nullptr; + } + + sheet_type->tp_init(obj_sheet, args, 0); + + // Pass model_context to the sheet object. + sheet_data* sd = get_sheet_data(obj_sheet); + sd->m_global = &self->m_data->m_global; + ixion::model_context& cxt = sd->m_global->m_cxt; + try + { + sd->m_sheet_index = cxt.append_sheet(sheet_name); + } + catch (const model_context_error& e) + { + // Most likely the sheet name already exists in this document. + Py_XDECREF(obj_sheet); + switch (e.get_error_type()) + { + case model_context_error::sheet_name_conflict: + PyErr_SetString(get_python_document_error(), e.what()); + break; + default: + PyErr_SetString(get_python_document_error(), + "Sheet insertion failed for unknown reason."); + } + return nullptr; + } + catch (const general_error& e) + { + Py_XDECREF(obj_sheet); + ostringstream os; + os << "Sheet insertion failed and the reason is '" << e.what() << "'"; + PyErr_SetString(get_python_document_error(), os.str().c_str()); + return nullptr; + } + + // Append this sheet instance to the document. + Py_INCREF(obj_sheet); + self->m_data->m_sheets.push_back(obj_sheet); + + return obj_sheet; +} + +const char* doc_document_calculate = +"Document.calculate([threads])\n" +"\n" +"(Re-)calculate all modified formula cells in the document.\n" +"\n" +"Keyword arguments:\n" +"\n" +"threads -- number of threads to use besides the main thread, or 0 if all\n" +" calculations are to be performed on the main thread. (default 0)\n" +; + +PyObject* document_calculate(pyobj_document* self, PyObject* args, PyObject* kwargs) +{ + static const char* kwlist[] = { "threads", nullptr }; + + long threads = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", const_cast<char**>(kwlist), &threads)) + { + PyErr_SetString(PyExc_TypeError, "Failed to parse the arguments for Document.calculate()"); + return nullptr; + } + + document_global& dg = self->m_data->m_global; + + // Query additional dirty formula cells and add them to the current set. + std::vector<abs_range_t> sorted = ixion::query_and_sort_dirty_cells( + dg.m_cxt, dg.m_modified_cells, &dg.m_dirty_formula_cells); + ixion::calculate_sorted_cells(dg.m_cxt, sorted, threads); + + dg.m_modified_cells.clear(); + dg.m_dirty_formula_cells.clear(); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* document_get_sheet(pyobj_document* self, PyObject* arg) +{ + const vector<PyObject*>& sheets = self->m_data->m_sheets; + if (PyLong_Check(arg)) + { + long index = PyLong_AsLong(arg); + if (index == -1 && PyErr_Occurred()) + return nullptr; + + if (index < 0 || static_cast<size_t>(index) >= sheets.size()) + { + PyErr_SetString(PyExc_IndexError, "Out-of-bound sheet index"); + return nullptr; + } + + PyObject* sheet_obj = sheets[index]; + Py_INCREF(sheet_obj); + return sheet_obj; + } + + // Not a python int object. See if it's a string object. + const char* name = PyUnicode_AsUTF8(arg); + if (!name) + { + PyErr_SetString(PyExc_TypeError, + "The 'arg' value must be either of type int or type str."); + return nullptr; + } + + // Iterate through all sheets to find a match. + // TODO : Use string hash to speed up the lookup. + for (PyObject* sh : sheets) + { + PyObject* obj = get_sheet_name(sh); + if (!obj) + continue; + + const char* this_name = PyUnicode_AsUTF8(obj); + if (!this_name) + continue; + + if (!strcmp(name, this_name)) + { + Py_INCREF(sh); + return sh; + } + } + + ostringstream os; + os << "No sheet named '" << name << "' found"; + PyErr_SetString(PyExc_IndexError, os.str().c_str()); + return nullptr; +} + +PyObject* document_getter_sheet_names(pyobj_document* self, void* closure) +{ + model_context& cxt = self->m_data->m_global.m_cxt; + const vector<PyObject*>& sheets = self->m_data->m_sheets; + size_t n = sheets.size(); + PyObject* t = PyTuple_New(n); + for (size_t i = 0; i < n; ++i) + { + std::string name = cxt.get_sheet_name(i); + PyObject* o = PyUnicode_FromString(name.c_str()); + PyTuple_SetItem(t, i, o); + } + + return t; +} + +PyMethodDef document_methods[] = +{ + { "append_sheet", (PyCFunction)document_append_sheet, METH_VARARGS, "append new sheet to the document" }, + { "calculate", (PyCFunction)document_calculate, METH_VARARGS | METH_KEYWORDS, doc_document_calculate }, + { "get_sheet", (PyCFunction)document_get_sheet, METH_O, "get a sheet object either by index or name" }, + { nullptr } +}; + +PyGetSetDef document_getset[] = +{ + { "sheet_names", (getter)document_getter_sheet_names, (setter)nullptr, "A tuple of sheet names", nullptr }, + { nullptr } +}; + +PyTypeObject document_type = +{ + PyVarObject_HEAD_INIT(nullptr, 0) + "ixion.Document", // tp_name + sizeof(pyobj_document), // tp_basicsize + 0, // tp_itemsize + (destructor)document_dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags + "ixion document object", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + document_methods, // tp_methods + 0, // tp_members + document_getset, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + (initproc)document_init, // tp_init + 0, // tp_alloc + document_new, // tp_new +}; + +} + +PyTypeObject* get_document_type() +{ + return &document_type; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/python/document.hpp b/src/python/document.hpp new file mode 100644 index 0000000..b024000 --- /dev/null +++ b/src/python/document.hpp @@ -0,0 +1,21 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_PYTHON_DOCUMENT_HPP +#define INCLUDED_IXION_PYTHON_DOCUMENT_HPP + +#include <Python.h> + +namespace ixion { namespace python { + +PyTypeObject* get_document_type(); + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/python/global.cpp b/src/python/global.cpp new file mode 100644 index 0000000..4d9a76b --- /dev/null +++ b/src/python/global.cpp @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "ixion/config.hpp" +#include "global.hpp" + +namespace ixion { namespace python { + +document_global::document_global() : + m_cxt(), + m_resolver(ixion::formula_name_resolver::get(formula_name_resolver_t::excel_a1, &m_cxt)) +{ +} + +PyObject* get_python_document_error() +{ + static PyObject* p = PyErr_NewException(const_cast<char*>("ixion.DocumentError"), NULL, NULL); + return p; +} + +PyObject* get_python_sheet_error() +{ + static PyObject* p = PyErr_NewException(const_cast<char*>("ixion.SheetError"), NULL, NULL); + return p; +} + +PyObject* get_python_formula_error() +{ + static PyObject* p = PyErr_NewException(const_cast<char*>("ixion.FormulaError"), NULL, NULL); + return p; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/python/global.hpp b/src/python/global.hpp new file mode 100644 index 0000000..d0a917f --- /dev/null +++ b/src/python/global.hpp @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_PYTHON_GLOBAL_HPP +#define INCLUDED_IXION_PYTHON_GLOBAL_HPP + +#include <Python.h> + +#include "ixion/model_context.hpp" +#include "ixion/formula_name_resolver.hpp" +#include "ixion/address.hpp" + +namespace ixion { namespace python { + +struct document_global +{ + model_context m_cxt; + + /** + * positions of all modified cells (formula and non-formula cells) since + * last calculation. + */ + abs_range_set_t m_modified_cells; + + /** positions of all dirty formula cells since last calculation. */ + abs_range_set_t m_dirty_formula_cells; + + std::unique_ptr<formula_name_resolver> m_resolver; + + document_global(); +}; + +PyObject* get_python_document_error(); +PyObject* get_python_sheet_error(); +PyObject* get_python_formula_error(); + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/python/python.cpp b/src/python/python.cpp new file mode 100644 index 0000000..1c8b5bf --- /dev/null +++ b/src/python/python.cpp @@ -0,0 +1,174 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "document.hpp" +#include "sheet.hpp" +#include "global.hpp" + +#include "ixion/env.hpp" +#include "ixion/info.hpp" + +#include <iostream> +#include <string> + +#define IXION_DEBUG_PYTHON 0 +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) + +using namespace std; + +namespace ixion { namespace python { + +namespace { + +#if IXION_DEBUG_PYTHON +void print_args(PyObject* args) +{ + string args_str; + PyObject* repr = PyObject_Repr(args); + if (repr) + { + Py_INCREF(repr); + args_str = PyBytes_AsString(repr); + Py_DECREF(repr); + } + cout << args_str << "\n"; +} +#endif + +PyObject* info(PyObject*, PyObject*) +{ + cout << "ixion version: " + << ixion::get_version_major() << '.' + << ixion::get_version_minor() << '.' + << ixion::get_version_micro() << endl; + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* column_label(PyObject* /*module*/, PyObject* args, PyObject* kwargs) +{ + int start; + int stop; + int resolver_index = 1; // Excel A1 by default + static const char* kwlist[] = { "start", "stop", "resolver", nullptr }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i", const_cast<char**>(kwlist), &start, &stop, &resolver_index)) + return nullptr; + + if (start >= stop) + { + PyErr_SetString( + PyExc_IndexError, + "Start position is larger or equal to the stop position."); + return nullptr; + } + + if (start < 0) + { + PyErr_SetString( + PyExc_IndexError, + "Start position should be larger than or equal to 0."); + return nullptr; + } + + auto resolver = formula_name_resolver::get( + static_cast<formula_name_resolver_t>(resolver_index), nullptr); + if (!resolver) + { + PyErr_SetString( + get_python_formula_error(), "Specified resolver type is invalid."); + return nullptr; + } + + int size = stop - start; + PyObject* t = PyTuple_New(size); + + for (int i = start; i < stop; ++i) + { + string s = resolver->get_column_name(i); + PyObject* o = PyUnicode_FromString(s.c_str()); + PyTuple_SetItem(t, i-start, o); + } + + return t; +} + +PyMethodDef ixion_methods[] = +{ + { "info", (PyCFunction)info, METH_NOARGS, "Print ixion module information." }, + { "column_label", (PyCFunction)column_label, METH_VARARGS | METH_KEYWORDS, + "Return a list of column label strings based on specified column range values." }, + { nullptr, nullptr, 0, nullptr } +}; + +struct module_state +{ + PyObject* error; +}; + +int ixion_traverse(PyObject* m, visitproc visit, void* arg) +{ + Py_VISIT(GETSTATE(m)->error); + return 0; +} + +int ixion_clear(PyObject* m) +{ + Py_CLEAR(GETSTATE(m)->error); + return 0; +} + +} + +struct PyModuleDef moduledef = +{ + PyModuleDef_HEAD_INIT, + "ixion", + nullptr, + sizeof(struct module_state), + ixion_methods, + nullptr, + ixion_traverse, + ixion_clear, + nullptr +}; + +}} + +extern "C" { + +IXION_DLLPUBLIC PyObject* PyInit_ixion() +{ + PyTypeObject* doc_type = ixion::python::get_document_type(); + if (PyType_Ready(doc_type) < 0) + return nullptr; + + PyTypeObject* sheet_type = ixion::python::get_sheet_type(); + if (PyType_Ready(sheet_type) < 0) + return nullptr; + + PyObject* m = PyModule_Create(&ixion::python::moduledef); + + Py_INCREF(doc_type); + PyModule_AddObject(m, "Document", reinterpret_cast<PyObject*>(doc_type)); + + Py_INCREF(sheet_type); + PyModule_AddObject(m, "Sheet", reinterpret_cast<PyObject*>(sheet_type)); + + PyModule_AddObject( + m, "DocumentError", ixion::python::get_python_document_error()); + PyModule_AddObject( + m, "SheetError", ixion::python::get_python_sheet_error()); + PyModule_AddObject( + m, "FormulaError", ixion::python::get_python_formula_error()); + + return m; +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/python/sheet.cpp b/src/python/sheet.cpp new file mode 100644 index 0000000..873004a --- /dev/null +++ b/src/python/sheet.cpp @@ -0,0 +1,376 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "sheet.hpp" +#include "global.hpp" + +#include <ixion/model_context.hpp> +#include <ixion/formula_name_resolver.hpp> +#include <ixion/formula.hpp> +#include <ixion/cell.hpp> +#include <ixion/exceptions.hpp> + +#include <structmember.h> + +#include <iostream> + +using namespace std; + +namespace ixion { namespace python { + +sheet_data::sheet_data() : m_global(nullptr), m_sheet_index(-1) {} + +namespace { + +struct sheet +{ + PyObject_HEAD + PyObject* name; // sheet name + + sheet_data* m_data; +}; + +void sheet_dealloc(sheet* self) +{ + delete self->m_data; + + Py_XDECREF(self->name); + Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self)); +} + +PyObject* sheet_new(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwargs*/) +{ + sheet* self = (sheet*)type->tp_alloc(type, 0); + if (!self) + return nullptr; + + self->m_data = new sheet_data; + + self->name = PyUnicode_FromString(""); + if (!self->name) + { + Py_DECREF(self); + return nullptr; + } + return reinterpret_cast<PyObject*>(self); +} + +int sheet_init(sheet* self, PyObject* args, PyObject* kwargs) +{ + PyObject* name = nullptr; + static const char* kwlist[] = { "name", nullptr }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", (char**)kwlist, &name)) + return -1; + + if (name) + { + PyObject* tmp = self->name; + Py_INCREF(name); + self->name = name; + Py_XDECREF(tmp); + } + + return 0; +} + +PyObject* sheet_set_numeric_cell(sheet* self, PyObject* args, PyObject* kwargs) +{ + int col = -1; + int row = -1; + double val = 0.0; + + static const char* kwlist[] = { "row", "column", "value", nullptr }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iid", const_cast<char**>(kwlist), &row, &col, &val)) + return nullptr; + + sheet_data* sd = get_sheet_data(reinterpret_cast<PyObject*>(self)); + if (!sd->m_global) + { + PyErr_SetString(get_python_sheet_error(), + "This Sheet object does not belong to a Document object."); + return nullptr; + } + + ixion::model_context& cxt = sd->m_global->m_cxt; + ixion::abs_address_t pos(sd->m_sheet_index, row, col); + sd->m_global->m_modified_cells.insert(pos); + cxt.set_numeric_cell(pos, val); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* sheet_set_string_cell(sheet* self, PyObject* args, PyObject* kwargs) +{ + int col = -1; + int row = -1; + char* val = nullptr; + + static const char* kwlist[] = { "row", "column", "value", nullptr }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iis", const_cast<char**>(kwlist), &row, &col, &val)) + return nullptr; + + sheet_data* sd = get_sheet_data(reinterpret_cast<PyObject*>(self)); + if (!sd->m_global) + { + PyErr_SetString(get_python_sheet_error(), + "This Sheet object does not belong to a Document object."); + return nullptr; + } + + ixion::model_context& cxt = sd->m_global->m_cxt; + ixion::abs_address_t pos(sd->m_sheet_index, row, col); + sd->m_global->m_modified_cells.insert(pos); + cxt.set_string_cell(pos, val); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* sheet_set_formula_cell(sheet* self, PyObject* args, PyObject* kwargs) +{ + int col = -1; + int row = -1; + char* formula = nullptr; + + static const char* kwlist[] = { "row", "column", "value", nullptr }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iis", const_cast<char**>(kwlist), &row, &col, &formula)) + return nullptr; + + sheet_data* sd = get_sheet_data(reinterpret_cast<PyObject*>(self)); + if (!sd->m_global) + { + PyErr_SetString(get_python_sheet_error(), + "This Sheet object does not belong to a Document object."); + return nullptr; + } + + ixion::model_context& cxt = sd->m_global->m_cxt; + + ixion::abs_address_t pos(sd->m_sheet_index, row, col); + sd->m_global->m_dirty_formula_cells.insert(pos); + + ixion::formula_tokens_t tokens = + ixion::parse_formula_string(cxt, pos, *sd->m_global->m_resolver, formula); + + auto ts = formula_tokens_store::create(); + ts->get() = std::move(tokens); + cxt.set_formula_cell(pos, ts); + + // Put this formula cell in a dependency chain. + ixion::register_formula_cell(cxt, pos); + + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* sheet_get_numeric_value(sheet* self, PyObject* args, PyObject* kwargs) +{ + int col = -1; + int row = -1; + + static const char* kwlist[] = { "row", "column", nullptr }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", const_cast<char**>(kwlist), &row, &col)) + return nullptr; + + sheet_data* sd = get_sheet_data(reinterpret_cast<PyObject*>(self)); + if (!sd->m_global) + { + PyErr_SetString(get_python_sheet_error(), + "This Sheet object does not belong to a Document object."); + return nullptr; + } + + ixion::model_context& cxt = sd->m_global->m_cxt; + double val = 0.0; + try + { + val = cxt.get_numeric_value(ixion::abs_address_t(sd->m_sheet_index, row, col)); + } + catch (const formula_error&) + { + PyErr_SetString(PyExc_TypeError, "The formula cell has yet to be calculated"); + return nullptr; + } + + return PyFloat_FromDouble(val); +} + +PyObject* sheet_get_string_value(sheet* self, PyObject* args, PyObject* kwargs) +{ + int col = -1; + int row = -1; + + static const char* kwlist[] = { "row", "column", nullptr }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", const_cast<char**>(kwlist), &row, &col)) + return nullptr; + + sheet_data* sd = get_sheet_data(reinterpret_cast<PyObject*>(self)); + if (!sd->m_global) + { + PyErr_SetString(get_python_sheet_error(), + "This Sheet object does not belong to a Document object."); + return nullptr; + } + + ixion::model_context& cxt = sd->m_global->m_cxt; + std::string_view s = cxt.get_string_value(ixion::abs_address_t(sd->m_sheet_index, row, col)); + if (s.empty()) + return PyUnicode_FromStringAndSize(nullptr, 0); + + return PyUnicode_FromStringAndSize(s.data(), s.size()); +} + +PyObject* sheet_get_formula_expression(sheet* self, PyObject* args, PyObject* kwargs) +{ + int col = -1; + int row = -1; + + static const char* kwlist[] = { "row", "column", nullptr }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", const_cast<char**>(kwlist), &row, &col)) + return nullptr; + + sheet_data* sd = get_sheet_data(reinterpret_cast<PyObject*>(self)); + if (!sd->m_global) + { + PyErr_SetString(get_python_sheet_error(), + "This Sheet object does not belong to a Document object."); + return nullptr; + } + + ixion::model_context& cxt = sd->m_global->m_cxt; + ixion::abs_address_t pos(sd->m_sheet_index, row, col); + const ixion::formula_cell* fc = cxt.get_formula_cell(pos); + + if (!fc) + { + PyErr_SetString(get_python_sheet_error(), "No formula cell at specified position."); + return nullptr; + } + + const ixion::formula_tokens_t& ft = fc->get_tokens()->get(); + + string str = ixion::print_formula_tokens(cxt, pos, *sd->m_global->m_resolver, ft); + if (str.empty()) + return PyUnicode_FromString(""); + + return PyUnicode_FromStringAndSize(str.data(), str.size()); +} + +PyObject* sheet_erase_cell(sheet* self, PyObject* args, PyObject* kwargs) +{ + PyErr_SetString(PyExc_RuntimeError, "erase_cell() method has been deprecated. Please use empty_cell() instead."); + return nullptr; +} + +PyObject* sheet_empty_cell(sheet* self, PyObject* args, PyObject* kwargs) +{ + int col = -1; + int row = -1; + + static const char* kwlist[] = { "row", "column", nullptr }; + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", const_cast<char**>(kwlist), &row, &col)) + return nullptr; + + sheet_data* sd = get_sheet_data(reinterpret_cast<PyObject*>(self)); + if (!sd->m_global) + { + PyErr_SetString(get_python_sheet_error(), + "This Sheet object does not belong to a Document object."); + return nullptr; + } + + ixion::model_context& cxt = sd->m_global->m_cxt; + abs_address_t pos(sd->m_sheet_index, row, col); + sd->m_global->m_modified_cells.insert(pos); + cxt.empty_cell(pos); + + Py_INCREF(Py_None); + return Py_None; +} + +PyMethodDef sheet_methods[] = +{ + { "set_numeric_cell", (PyCFunction)sheet_set_numeric_cell, METH_VARARGS | METH_KEYWORDS, "set numeric value to specified cell" }, + { "set_formula_cell", (PyCFunction)sheet_set_formula_cell, METH_VARARGS | METH_KEYWORDS, "set formula to specified cell" }, + { "set_string_cell", (PyCFunction)sheet_set_string_cell, METH_VARARGS | METH_KEYWORDS, "set string to specified cell" }, + { "get_numeric_value", (PyCFunction)sheet_get_numeric_value, METH_VARARGS | METH_KEYWORDS, "get numeric value from specified cell" }, + { "get_string_value", (PyCFunction)sheet_get_string_value, METH_VARARGS | METH_KEYWORDS, "get string value from specified cell" }, + { "get_formula_expression", (PyCFunction)sheet_get_formula_expression, METH_VARARGS | METH_KEYWORDS, "get formula expression string from specified cell position" }, + { "empty_cell", (PyCFunction)sheet_empty_cell, METH_VARARGS | METH_KEYWORDS, "empty cell at specified position" }, + { "erase_cell", (PyCFunction)sheet_erase_cell, METH_VARARGS | METH_KEYWORDS, "erase cell at specified position" }, + { nullptr } +}; + +PyMemberDef sheet_members[] = +{ + { (char*)"name", T_OBJECT_EX, offsetof(sheet, name), READONLY, (char*)"sheet name" }, + { nullptr } +}; + +PyTypeObject sheet_type = +{ + PyVarObject_HEAD_INIT(nullptr, 0) + "ixion.Sheet", // tp_name + sizeof(sheet), // tp_basicsize + 0, // tp_itemsize + (destructor)sheet_dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags + "ixion sheet object", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + sheet_methods, // tp_methods + sheet_members, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + (initproc)sheet_init, // tp_init + 0, // tp_alloc + sheet_new, // tp_new +}; + +} + +PyTypeObject* get_sheet_type() +{ + return &sheet_type; +} + +sheet_data* get_sheet_data(PyObject* obj) +{ + return reinterpret_cast<sheet*>(obj)->m_data; +} + +PyObject* get_sheet_name(PyObject* obj) +{ + return reinterpret_cast<sheet*>(obj)->name; +} + +}} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/python/sheet.hpp b/src/python/sheet.hpp new file mode 100644 index 0000000..e85596e --- /dev/null +++ b/src/python/sheet.hpp @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef INCLUDED_IXION_PYTHON_SHEET_HPP +#define INCLUDED_IXION_PYTHON_SHEET_HPP + +#include <Python.h> + +#include "ixion/types.hpp" + +namespace ixion { namespace python { + +struct document_global; + +struct sheet_data +{ + document_global* m_global; + ixion::sheet_t m_sheet_index; + + sheet_data(); +}; + +PyTypeObject* get_sheet_type(); + +sheet_data* get_sheet_data(PyObject* obj); + +/** + * Get the sheet name of a python sheet object. + * + * @param obj python sheet object. + * + * @return python string object storing the sheet name. + */ +PyObject* get_sheet_name(PyObject* obj); + +}} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/src/python/test-env.sh b/src/python/test-env.sh new file mode 100644 index 0000000..fc3f6cb --- /dev/null +++ b/src/python/test-env.sh @@ -0,0 +1,9 @@ + +PYTHONPATH=.libs:$PYTHONPATH + +# Ensure that the libixion shared library built as part of the current build +# is discovered first. +LD_LIBRARY_PATH=../libixion/.libs:$LD_LIBRARY_PATH + +export PYTHONPATH LD_LIBRARY_PATH + |