← Back to team overview

kicad-developers team mailing list archive

Re: Enabling Python scripting for Eeschema

 

On 23/08/16 08:46, Trygve Laugstøl wrote:
> Hi
> 
> I've been wanting to automate the generation of PCB and schematic plots.
> I've been able to do the PCB parts with the existing Python interface
> (though a bit of a hassle to find), but I want the same for eeschema too
> but that doesn't seem to exist but could help get that working.
> 
> It seems that the code in scripting/ and pcbnew/scripting is too tightly
> coupled to easily copy the CMake setup from pcbnew to eeschema.
> 
> I know my way around CMake and C++ but I would appreciate some some
> pointers to the best way to get started with building a scripting
> interface for eeschema? I heard from IRC that there is work going on for
> a better general API for the Python code so I guess I would make a
> specialized plotting API.
> 

An update on this project:

* The wrappers are built with swig
* The python code (see demos/python_scripts_examples/eeschema-plot.py)
is able to import eeschema and call functions. So far I've only exported
my own 'createPlot' function.
* The python/c++ interaction seems to work fine, but it fails when it is
trying to access the current project through the current kiway instance.

How should this work when eeschema is started through a python script? I
see that I can use 'new' to create a new Kiway instance, but is that the
correct way to do it? If it is, should I create my own PGM_BASE subclass
or reuse eeschema's? Or should I go in a different direction and use
some other code to get the current kiface/kiway instance?

I've looked at lot at the equivalent code for pcbnew but it doesn't seem
to require a kiway/kiface or project instance.

Any help would be appreciated. I'm on irc if this is easier done in real
time.

An online version of the patch:
https://gist.github.com/trygvis/6f9f1ccc342eabb966872cd574e3f3c7

-- 
Trygve

diff --git a/common/page_layout/title_block_shapes.cpp b/common/page_layout/title_block_shapes.cpp
index c7a8385..a2fd957 100644
--- a/common/page_layout/title_block_shapes.cpp
+++ b/common/page_layout/title_block_shapes.cpp
@@ -137,7 +137,9 @@ void WS_DRAW_ITEM_LIST::BuildWorkSheetGraphicList(
                 wsText->m_FullText = wsText->m_TextBase;
             else
             {
-                wsText->m_FullText = BuildFullText( wsText->m_TextBase );
+                std::cout << "wsText->m_TextBase=" << wsText->m_TextBase << std::endl;
+//                wsText->m_FullText = BuildFullText( wsText->m_TextBase );
+                wsText->m_FullText = wsText->m_TextBase;
                 multilines = wsText->ReplaceAntiSlashSequence();
             }
 
diff --git a/common/worksheet.cpp b/common/worksheet.cpp
index 3e9255d..48a3b4a 100644
--- a/common/worksheet.cpp
+++ b/common/worksheet.cpp
@@ -168,9 +168,15 @@ wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
                 msg += m_titleBlock->GetRevision();
                 break;
 
-            case 'K':
+            case 'K': {
+                auto pgm = &Pgm();
+                std::cout << "pgm: " << static_cast<void*>(pgm) << std::endl;
+                wxApp* app = &pgm->App();
+                std::cout << "app: " << static_cast<void*>(app) << std::endl;
+                std::cout << "name: " << app->GetAppName() << std::endl;
                 msg += productName + Pgm().App().GetAppName();
                 msg += wxT( " " ) + GetBuildVersion();
+                }
                 break;
 
             case 'Z':
diff --git a/demos/python_scripts_examples/eeschema-plot.py b/demos/python_scripts_examples/eeschema-plot.py
new file mode 100644
index 0000000..43854f9
--- /dev/null
+++ b/demos/python_scripts_examples/eeschema-plot.py
@@ -0,0 +1,17 @@
+# print "loading module"
+import eeschema
+import sys
+
+if 0:
+    print "all keys:" + str(len(eeschema.__dict__))
+
+    for key, value in sorted(eeschema.__dict__.items()):
+        print key
+
+schemaFile = sys.argv[1]
+outputDir = sys.argv[2]
+
+print "py: schemaFile: " + schemaFile
+print "py: outputDir: " + outputDir
+
+eeschema.createPlot(schemaFile, outputDir)
diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt
index 4279d30..ae34665 100644
--- a/eeschema/CMakeLists.txt
+++ b/eeschema/CMakeLists.txt
@@ -4,6 +4,33 @@ if( KICAD_SPICE )
     set( INC_AFTER ${INC_AFTER} ${NGSPICE_INCLUDE_DIR} )
 endif()
 
+if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES )
+    file( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/scripting )
+
+    # SWIG 3.0 or later require for C++11 support.
+    find_package( SWIG 3.0 REQUIRED )
+    include( ${SWIG_USE_FILE} )
+
+    # Infrequently needed headers go at end of search paths, append to INC_AFTER
+    set( INC_AFTER ${INC_AFTER} ${CMAKE_CURRENT_SOURCE_DIR}/scripting ../polygon)
+
+endif()
+
+set( EESCHEMA_SCRIPTING_PYTHON_HELPERS
+        ../scripting/wx_python_helpers.cpp
+        ../scripting/python_scripting.cpp
+        scripting/eeschema_scripting_helpers.cpp
+        )
+
+if( KICAD_SCRIPTING )
+    set( EESCHEMA_SCRIPTING_SRCS
+            ${EESCHEMA_SCRIPTING_DIALOGS}
+#            eeschema_wrap.cxx pcbnew has this, dunno why. it is identical to pcbnewPYTHON_wrap.cxx
+            eeschemaPYTHON_wrap.cxx
+            ${EESCHEMA_SCRIPTING_PYTHON_HELPERS}
+            )
+endif()
+
 include_directories( BEFORE ${INC_BEFORE} )
 include_directories(
     ${CMAKE_CURRENT_BINARY_DIR}
@@ -282,6 +309,7 @@ target_link_libraries( eeschema
 add_library( eeschema_kiface MODULE
     ${EESCHEMA_SRCS}
     ${EESCHEMA_COMMON_SRCS}
+    ${EESCHEMA_SCRIPTING_SRCS}
     )
 target_link_libraries( eeschema_kiface
     common
@@ -291,6 +319,7 @@ target_link_libraries( eeschema_kiface
     ${wxWidgets_LIBRARIES}
     ${GDI_PLUS_LIBRARIES}
     ${NGSPICE_LIBRARY}
+    ${PYTHON_LIBRARIES}
     )
 set_target_properties( eeschema_kiface PROPERTIES
     # Decorate OUTPUT_NAME with PREFIX and SUFFIX, creating something like
@@ -417,3 +446,115 @@ add_custom_target(
 add_dependencies( eeschema_kiface dialog_bom_cfg_lexer_source_files )
 
 add_subdirectory( plugins )
+
+if( KICAD_SCRIPTING OR KICAD_SCRIPTING_MODULES )
+
+    set( SWIG_FLAGS
+            -I${CMAKE_CURRENT_SOURCE_DIR}/../..
+            -I${CMAKE_CURRENT_SOURCE_DIR}
+            -I${CMAKE_CURRENT_SOURCE_DIR}/../include
+            -I${CMAKE_CURRENT_SOURCE_DIR}/../scripting
+            )
+
+    if( DEBUG )
+        set( SWIG_FLAGS ${SWIG_FLAGS} -DDEBUG )
+    endif()
+
+    # collect CFLAGS , and pass them to swig later
+
+    get_directory_property( DirDefs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS )
+    foreach( d ${DirDefs} )
+        set( SWIG_FLAGS ${SWIG_FLAGS} -D${d} )
+    endforeach()
+
+endif()
+
+if( KICAD_SCRIPTING )
+    if( NOT APPLE )
+        install( FILES ${CMAKE_BINARY_DIR}/eeschema/eeschema.py DESTINATION ${PYTHON_DEST} )
+    else()
+        # put into bundle at build time, it is relocated at install
+        add_custom_target( ScriptingEeschemaPyCopy ALL
+                COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/eeschema/eeschema.py" "${PYTHON_DEST}/"
+                DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/eeschema.py
+                COMMENT "Copying eeschema.py into ${PYTHON_DEST}"
+                )
+        add_dependencies( ScriptingEeschemaPyCopy ScriptingWxpythonCopy )
+    endif()
+
+#    # scripting plugins
+#    install( DIRECTORY ${PROJECT_SOURCE_DIR}/eeschema/scripting/plugins/
+#            DESTINATION ${KICAD_DATA}/scripting/plugins
+#            FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ
+#            )
+#
+#    # scripting python shell
+#    install( DIRECTORY ${PROJECT_SOURCE_DIR}/eeschema/scripting/kicad_pyshell/
+#            DESTINATION ${KICAD_DATA}/scripting/kicad_pyshell
+#            FILE_PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ
+#            )
+endif()
+
+if( KICAD_SCRIPTING_MODULES )
+    add_custom_target( FixSwigImportsModuleScriptingEeschema ALL
+            COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripting/build_tools/fix_swig_imports.py ${CMAKE_CURRENT_BINARY_DIR}/eeschema.py
+            DEPENDS _eeschema
+            COMMENT "Fixing swig_import_helper in Kicad scripting modules"
+            )
+
+    if( MINGW )
+        install( FILES ${CMAKE_BINARY_DIR}/eeschema/_eeschema.pyd DESTINATION ${PYTHON_DEST} )
+    elseif( APPLE )
+        # put everything into bundle at build time, it is relocated at install
+        add_custom_target( ScriptingModulesEeschemaSoCopy ALL
+                COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/eeschema/_eeschema.so" "${PYTHON_DEST}/"
+                DEPENDS _eeschema
+                COMMENT "Copying _eeschema.so into ${PYTHON_DEST}"
+                )
+        add_dependencies( ScriptingModulesEeschemaSoCopy ScriptingWxpythonCopy )
+    else()
+        install( FILES ${CMAKE_BINARY_DIR}/eeschema/_eeschema.so DESTINATION ${PYTHON_DEST} )
+    endif()
+endif()
+
+if( KICAD_SCRIPTING_MODULES )
+
+    #message( "building eeschema scripting" )
+
+    set( CMAKE_SWIG_FLAGS ${SWIG_FLAGS} )
+#    message( "CMAKE_SWIG_FLAGS: ${CMAKE_SWIG_FLAGS}" )
+    set_source_files_properties( scripting/eeschema.i PROPERTIES CPLUSPLUS ON )
+
+    swig_add_module( eeschema
+            python
+            scripting/eeschema.i
+            ${EESCHEMA_SCRIPTING_PYTHON_HELPERS}
+            eeschema.cpp
+            ${EESCHEMA_SRCS}
+            ${EESCHEMA_COMMON_SRCS}
+            )
+
+    swig_link_libraries( eeschema
+            common
+            bitmaps
+            polygon
+            gal
+            ${wxWidgets_LIBRARIES}
+            ${GDI_PLUS_LIBRARIES}
+            ${NGSPICE_LIBRARY}
+            ${PYTHON_LIBRARIES}
+            ${Boost_LIBRARIES}      # must follow GITHUB
+            )
+
+#    if( MAKE_LINK_MAPS )
+#        set_target_properties( _eeschema PROPERTIES
+#                LINK_FLAGS "${TO_LINKER},-cref ${TO_LINKER},-Map=eeschema.so.map"
+#                )
+#    endif()
+
+#    if( ${OPENMP_FOUND} )
+#        set_property( TARGET _eeschema APPEND_STRING
+#                PROPERTY LINK_FLAGS " ${OpenMP_CXX_FLAGS}"
+#                )
+#    endif()
+endif()
diff --git a/eeschema/dialogs/dialog_plot_schematic.h b/eeschema/dialogs/dialog_plot_schematic.h
index 69cf6c0..8b7f51e 100644
--- a/eeschema/dialogs/dialog_plot_schematic.h
+++ b/eeschema/dialogs/dialog_plot_schematic.h
@@ -34,6 +34,7 @@
 #include <schframe.h>
 #include <dialog_plot_schematic_base.h>
 #include <reporter.h>
+#include <sch_sheet_path.h>
 
 
 enum PageFormatReq {
@@ -154,4 +155,14 @@ public:
     static bool plotOneSheetSVG( EDA_DRAW_FRAME* aFrame, const wxString& aFileName,
                                  SCH_SCREEN* aScreen,
                                  bool aPlotBlackAndWhite, bool aPlotFrameRef );
+
+    static bool plotOneSheetSVG(const TITLE_BLOCK& aTitleBlock,
+                                const PAGE_INFO&   aPageInfo,
+                                const wxString&    aScreenDesc,
+                                const wxString&    aFileName,
+                                SCH_SCREEN*        aScreen,
+                                bool               aPlotBlackAndWhite,
+                                bool               aPlotFrameRef);
+
+    void createSVGFile2(bool aPrintAll, bool aPrintFrameRef, REPORTER &reporter, const wxFileName &outputDirectory );
 };
diff --git a/eeschema/plot_schematic_SVG.cpp b/eeschema/plot_schematic_SVG.cpp
index d0835a7..8b34a61 100644
--- a/eeschema/plot_schematic_SVG.cpp
+++ b/eeschema/plot_schematic_SVG.cpp
@@ -41,6 +41,68 @@
 #include <dialog_plot_schematic.h>
 #include <wx_html_report_panel.h>
 
+void DIALOG_PLOT_SCHEMATIC::createSVGFile2(bool aPrintAll, bool aPrintFrameRef, REPORTER &reporter, const wxFileName &outputDirectory)
+{
+    wxString        msg;
+//    REPORTER&       reporter = m_MessagesBox->Reporter();
+//    SCH_SHEET_PATH  oldsheetpath = m_parent->GetCurrentSheet();
+    SCH_SHEET_LIST  sheetList;
+
+    if( aPrintAll )
+        sheetList.BuildSheetList( g_RootSheet );
+    else
+        sheetList.push_back( m_parent->GetCurrentSheet() );
+
+    for( unsigned i = 0; i < sheetList.size(); i++ )
+    {
+        SCH_SCREEN*  screen;
+        m_parent->SetCurrentSheet( sheetList[i] );
+        m_parent->GetCurrentSheet().UpdateAllScreenReferences();
+        m_parent->SetSheetNumberAndCount();
+        screen = m_parent->GetCurrentSheet().LastScreen();
+
+        try
+        {
+            wxString fname = m_parent->GetUniqueFilenameForCurrentSheet();
+            wxString ext = SVG_PLOTTER::GetDefaultFileExtension();
+            wxFileName plotFileName = outputDirectory;
+            plotFileName.AppendDir(fname + wxT(".") + ext);
+//            wxFileName plotFileName = createPlotFileName( m_outputDirectoryName,
+//                                                          fname, ext, &reporter );
+//            wxFileName plotFileName = createPlotFileName( m_outputDirectoryName,
+//                                                          fname, ext, &reporter );
+
+            bool success = plotOneSheetSVG( m_parent, plotFileName.GetFullPath(), screen,
+                                            getModeColor() ? false : true,
+                                            aPrintFrameRef );
+
+            if( !success )
+            {
+                msg.Printf( _( "Cannot create file '%s'.\n" ),
+                            GetChars( plotFileName.GetFullPath() ) );
+                reporter.Report( msg, REPORTER::RPT_ERROR );
+            }
+            else
+            {
+                msg.Printf( _( "Plot: '%s' OK.\n" ),
+                            GetChars( plotFileName.GetFullPath() ) );
+                reporter.Report( msg, REPORTER::RPT_ACTION );
+            }
+        }
+        catch( const IO_ERROR& e )
+        {
+            // Cannot plot SVG file
+            msg.Printf( wxT( "SVG Plotter exception: %s" ), GetChars( e.errorText ) );
+            reporter.Report( msg, REPORTER::RPT_ERROR );
+            break;
+        }
+    }
+
+//    m_parent->SetCurrentSheet( oldsheetpath );
+//    m_parent->GetCurrentSheet().UpdateAllScreenReferences();
+//    m_parent->SetSheetNumberAndCount();
+}
+
 void DIALOG_PLOT_SCHEMATIC::createSVGFile( bool aPrintAll, bool aPrintFrameRef )
 {
     wxString        msg;
@@ -106,44 +168,60 @@ bool DIALOG_PLOT_SCHEMATIC::plotOneSheetSVG( EDA_DRAW_FRAME*    aFrame,
                                              bool               aPlotBlackAndWhite,
                                              bool               aPlotFrameRef )
 {
-    SVG_PLOTTER* plotter = new SVG_PLOTTER();
+    return plotOneSheetSVG( aFrame->GetTitleBlock(),
+                            aFrame->GetPageSettings(),
+                            aFrame->GetScreenDesc(),
+                            aFileName,
+                            aScreen,
+                            aPlotBlackAndWhite,
+                            aPlotFrameRef);
+}
+
+bool DIALOG_PLOT_SCHEMATIC::plotOneSheetSVG( // EDA_DRAW_FRAME*    aFrame,
+                                             const TITLE_BLOCK& aTitleBlock,
+                                             const PAGE_INFO&   aPageInfo,
+                                             const wxString&    aScreenDesc,
+                                             const wxString&    aFileName,
+                                             SCH_SCREEN*        aScreen,
+                                             bool               aPlotBlackAndWhite,
+                                             bool               aPlotFrameRef )
+{
+    SVG_PLOTTER plotter;
 
-    const PAGE_INFO&   pageInfo = aScreen->GetPageSettings();
-    plotter->SetPageSettings( pageInfo );
-    plotter->SetDefaultLineWidth( GetDefaultLineThickness() );
-    plotter->SetColorMode( aPlotBlackAndWhite ? false : true );
+    PAGE_INFO pageInfo = aScreen->GetPageSettings();
+    plotter.SetPageSettings( pageInfo );
+    plotter.SetDefaultLineWidth( GetDefaultLineThickness() );
+    plotter.SetColorMode( !aPlotBlackAndWhite );
     wxPoint plot_offset;
     double scale = 1.0;
     // Currently, plot units are in decimil
-    plotter->SetViewport( plot_offset, IU_PER_MILS/10, scale, false );
+    plotter.SetViewport( plot_offset, IU_PER_MILS/10, scale, false );
 
     // Init :
-    plotter->SetCreator( wxT( "Eeschema-SVG" ) );
+    plotter.SetCreator( wxT( "Eeschema-SVG" ) );
 
-    if( ! plotter->OpenFile( aFileName ) )
+    if( ! plotter.OpenFile( aFileName ) )
     {
-        delete plotter;
         return false;
     }
 
     LOCALE_IO   toggle;
 
-    plotter->StartPlot();
+    plotter.StartPlot();
 
     if( aPlotFrameRef )
     {
-        plotter->SetColor( BLACK );
-        PlotWorkSheet( plotter, aFrame->GetTitleBlock(),
-                       aFrame->GetPageSettings(),
+        plotter.SetColor( BLACK );
+        PlotWorkSheet( &plotter, aTitleBlock,
+                       aPageInfo,
                        aScreen->m_ScreenNumber, aScreen->m_NumberOfScreens,
-                       aFrame->GetScreenDesc(),
+                       aScreenDesc,
                        aScreen->GetFileName() );
     }
 
-    aScreen->Plot( plotter );
+    aScreen->Plot( &plotter );
 
-    plotter->EndPlot();
-    delete plotter;
+    plotter.EndPlot();
 
     return true;
 }
diff --git a/eeschema/sch_legacy_plugin.cpp b/eeschema/sch_legacy_plugin.cpp
index 7b92a1d..b183e76 100644
--- a/eeschema/sch_legacy_plugin.cpp
+++ b/eeschema/sch_legacy_plugin.cpp
@@ -465,7 +465,9 @@ void SCH_LEGACY_PLUGIN::init( KIWAY* aKiway, const PROPERTIES* aProperties )
 SCH_SHEET* SCH_LEGACY_PLUGIN::Load( const wxString& aFileName, KIWAY* aKiway,
                                     SCH_SHEET* aAppendToMe, const PROPERTIES* aProperties )
 {
-    wxASSERT( !aFileName || aKiway != NULL );
+    std::cout << "aFileName=" << aFileName << std::endl;
+    wxASSERT( !aFileName );
+    wxASSERT( aKiway != NULL );
 
     LOCALE_IO   toggle;     // toggles on, then off, the C locale.
     SCH_SHEET*  sheet;
diff --git a/eeschema/scripting/eeschema.i b/eeschema/scripting/eeschema.i
new file mode 100644
index 0000000..4165e3e
--- /dev/null
+++ b/eeschema/scripting/eeschema.i
@@ -0,0 +1,67 @@
+/*
+ * This program source code file is part of KiCad, a free EDA CAD application.
+ *
+ * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you may find one here:
+ * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
+ * or you may search the http://www.gnu.org website for the version 2 license,
+ * or you may write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
+ */
+
+/**
+ * @file eeschema.i
+ * @brief Specific eeschema wrappers
+ */
+
+%module eeschema
+
+// %include "kicad.i"
+
+%include <std_string.i>
+
+%exception {
+    try{
+        $action
+    }
+    catch( IO_ERROR e )
+    {
+        std::string str = TO_UTF8( e.errorText );
+        str += '\n';
+        PyErr_SetString( PyExc_IOError, str.c_str() );
+        return NULL;
+    }
+    catch( std::exception &e )
+    {
+        std::string str = e.what();
+        str += '\n';
+        PyErr_SetString( PyExc_IOError, str.c_str() );
+        return NULL;
+    }
+    catch( ... )
+    {
+        SWIG_fail;
+    }
+}
+%include exception.i
+
+%{
+#include <macros.h>
+#include <richio.h>
+
+void createPlot(std::string schemaFile, std::string outputDir);
+%}
+
+%include <eeschema_scripting_helpers.h>
diff --git a/eeschema/scripting/eeschema_scripting_helpers.cpp b/eeschema/scripting/eeschema_scripting_helpers.cpp
new file mode 100644
index 0000000..44f9c43
--- /dev/null
+++ b/eeschema/scripting/eeschema_scripting_helpers.cpp
@@ -0,0 +1,70 @@
+#include "eeschema_scripting_helpers.h"
+
+#include "schframe.h"
+#include "sch_io_mgr.h"
+#include "dialog_plot_schematic.h"
+#include "properties.h"
+#include "kiway.h"
+#include "pgm_base.h"
+#include <string>
+#include <iostream>
+
+using namespace std;
+
+/*
+class EESCHEMA_PY_PGM : public PGM_BASE {
+    bool OnPgmInit(wxApp *aWxApp) override {
+    }
+
+    void OnPgmExit() override {
+    }
+
+    void MacOpenFile(const wxString &aFileName) override {
+    }
+};
+*/
+
+void createPlot(string schemaFile, string outputDir) {
+    cout << "outputDir: " << endl;
+
+    bool plotFrameRef = true;
+    bool plotBlackAndWhite = false;
+
+    SCH_IO_MGR::SCH_FILE_T fileType = SCH_IO_MGR::SCH_FILE_T::SCH_LEGACY;
+    PROPERTIES properties;
+    SCH_SHEET *appendToMe = nullptr;
+//    EESCHEMA_PY_PGM pgm;
+//    KIWAY *kiway = new KIWAY(static_cast<PGM_BASE *>(&pgm), 0);
+    KIWAY *kiway = nullptr;
+
+    wxFileName schFileName(schemaFile);
+    schFileName.MakeAbsolute();
+    schemaFile = schFileName.GetLongPath();
+    cout << "schemaFile: " << schemaFile << endl;
+    SCH_SHEET *sheet = SCH_IO_MGR::Load(fileType,
+                                        schemaFile,
+                                        kiway,
+                                        appendToMe,
+                                        &properties);
+
+    wxFileName svgFileName(outputDir);
+    svgFileName.SetFullName("foo.svg");
+    wxString svgFilePath = svgFileName.GetLongPath();
+    cout << "svgFilePath: " << svgFilePath << endl;
+
+    SCH_SCREEN *schScreen = sheet->GetScreen();
+
+    TITLE_BLOCK titleBlock;
+    PAGE_INFO pageInfo;
+    wxString schScreenDesc = "screen desc";
+
+    DIALOG_PLOT_SCHEMATIC::plotOneSheetSVG(titleBlock,
+                                           pageInfo,
+                                           schScreenDesc,
+                                           svgFilePath,
+                                           schScreen,
+                                           plotBlackAndWhite,
+                                           plotFrameRef);
+
+    delete sheet;
+}
diff --git a/eeschema/scripting/eeschema_scripting_helpers.h b/eeschema/scripting/eeschema_scripting_helpers.h
new file mode 100644
index 0000000..31ea6af
--- /dev/null
+++ b/eeschema/scripting/eeschema_scripting_helpers.h
@@ -0,0 +1,8 @@
+#ifndef __EESCHEMA_SCRIPTING_HELPERS_H
+#define __EESCHEMA_SCRIPTING_HELPERS_H
+
+#include <string>
+
+void createPlot(std::string schemaFile, std::string fileName);
+
+#endif
diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt
index 21eaec9..28c1d2e 100644
--- a/pcbnew/CMakeLists.txt
+++ b/pcbnew/CMakeLists.txt
@@ -691,7 +691,7 @@ if( KICAD_SCRIPTING )
 endif()
 
 if( KICAD_SCRIPTING_MODULES )
-    add_custom_target( FixSwigImportsModuleScripting ALL
+    add_custom_target( FixSwigImportsModuleScriptingPcbnew ALL
         COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_SOURCE_DIR}/scripting/build_tools/fix_swig_imports.py ${CMAKE_CURRENT_BINARY_DIR}/pcbnew.py
         DEPENDS _pcbnew
         COMMENT "Fixing swig_import_helper in Kicad scripting modules"
diff --git a/pcbnew/pcbnew.cpp b/pcbnew/pcbnew.cpp
index dc6eb63..105a528 100644
--- a/pcbnew/pcbnew.cpp
+++ b/pcbnew/pcbnew.cpp
@@ -199,6 +199,7 @@ PGM_BASE& Pgm()
 
 
 #if defined( KICAD_SCRIPTING )
+// TODO: This is copied directly from pcbnew. if useful, share the code properly.
 static bool scriptingSetup()
 {
     wxString path_frag;
diff --git a/scripting/python_scripting.cpp b/scripting/python_scripting.cpp
index f2b3d22..ad1bdd9 100644
--- a/scripting/python_scripting.cpp
+++ b/scripting/python_scripting.cpp
@@ -39,10 +39,10 @@
 
 /* init functions defined by swig */
 
-extern "C" void init_kicad( void );
-
 extern "C" void init_pcbnew( void );
 
+extern "C" void init_eeschema( void );
+
 #define EXTRA_PYTHON_MODULES 10     // this is the number of python
                                     // modules that we want to add into the list
 
@@ -108,7 +108,13 @@ static void swigAddBuiltin()
 
 static void swigAddModules()
 {
+#ifdef EESCHEMA
+    swigAddModule( "_eeschema", init_eeschema );
+#endif
+
+#ifdef PCBNEW
     swigAddModule( "_pcbnew", init_pcbnew );
+#endif
 
     // finally it seems better to include all in just one module
     // but in case we needed to include any other modules,

References