Skip to content
Snippets Groups Projects
class_maker.py 11.1 KiB
Newer Older
#!/usr/bin/env python
""" Utility for generating a class file, header, and test file """

import sys
import os
import argparse
import datetime
import cmakelists_utils
from cmakelists_utils import *


#======================================================================
def write_header(subproject, classname, filename, args):
    """Write a class header file"""
    print "Writing header file to %s" % filename
    f = open(filename, 'w')
    
    guard = "MANTID_%s_%s_H_" % (subproject.upper(), classname.upper())
    
    # Create an Algorithm header; will not use it if 
    algorithm_header = """
    /// Algorithm's name for identification 
    virtual const std::string name() const { return "%s";};
    /// Algorithm's version for identification 
    virtual int version() const { return 1;};
    /// Algorithm's category for identification
    virtual const std::string category() const { return "General";}
    
  private:
    /// Sets documentation strings for this algorithm
    virtual void initDocs();
    /// Initialise the properties
    /// Run the algorithm
    void exec();

""" % classname
        
    alg_class_declare = " : public API::Algorithm"
    alg_include = """#include "MantidAPI/Algorithm.h" """
    
        algorithm_header = ""
        alg_class_declare = ""
        alg_include = ""
    
    # The full text
/*WIKI*
TODO: Enter wiki description here.
*WIKI*/
    
    @author
    @date %s

    Copyright © %s ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory

    This file is part of Mantid.

    Mantid 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 3 of the License, or
    (at your option) any later version.

    Mantid 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, see <http://www.gnu.org/licenses/>.

    File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
    Code Documentation is available at: <http://doxygen.mantidproject.org>
  */
""" % (guard, guard, alg_include, subproject, classname, datetime.datetime.now().date(), datetime.datetime.now().date().year, classname, alg_class_declare, classname, classname, algorithm_header, subproject, guard)




#======================================================================
def write_source(subproject, classname, filename, args):
    """Write a class source file"""
    print "Writing source file to %s" % filename
    f = open(filename, 'w')
    
    algorithm_top = """
  // Register the algorithm into the AlgorithmFactory
  DECLARE_ALGORITHM(%s)
  
""" % (classname)

    algorithm_source = """
  //----------------------------------------------------------------------------------------------
  /// Sets documentation strings for this algorithm
  void %s::initDocs()
  {
    this->setWikiSummary("TODO: Enter a quick description of your algorithm.");
    this->setOptionalMessage("TODO: Enter a quick description of your algorithm.");
  }

  //----------------------------------------------------------------------------------------------
  /** Initialize the algorithm's properties.
   */
  void %s::init()
  {
    declareProperty(new WorkspaceProperty<>("InputWorkspace","",Direction::Input), "An input workspace.");
    declareProperty(new WorkspaceProperty<>("OutputWorkspace","",Direction::Output), "An output workspace.");
  }

  //----------------------------------------------------------------------------------------------
  /** Execute the algorithm.
   */
  void %s::exec()
  {
    // TODO Auto-generated execute stub
  }

    s = """#include "Mantid%s/%s%s.h"
using namespace Mantid::Kernel;
using namespace Mantid::API;


  //----------------------------------------------------------------------------------------------
  /** Constructor
   */
  %s::%s()
  {
    // TODO Auto-generated constructor stub
  }
    
  //----------------------------------------------------------------------------------------------
  /** Destructor
   */
  %s::~%s()
  {
    // TODO Auto-generated destructor stub
  }
""" % (subproject, args.subfolder, classname, subproject, algorithm_top, classname, classname, classname, classname, algorithm_source, subproject)
    f.write(s)
    f.close()


    
#======================================================================
def write_test(subproject, classname, filename, args):
    """Write a class test file"""
    print "Writing test file to %s" % filename
    f = open(filename, 'w')

    guard = "MANTID_%s_%sTEST_H_" % (subproject.upper(), classname.upper())
    algorithm_test = """
  void test_Init()
  {
    %s alg;
    TS_ASSERT_THROWS_NOTHING( alg.initialize() )
    TS_ASSERT( alg.isInitialized() )
  }
  
  void test_exec()
  {
    // Name of the output workspace.
    std::string outWSName("%sTest_OutputWS");
  
    %s alg;
    TS_ASSERT_THROWS_NOTHING( alg.initialize() )
    TS_ASSERT( alg.isInitialized() )
    TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("REPLACE_PROPERTY_NAME_HERE!!!!", "value") );
    TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", outWSName) );
    TS_ASSERT_THROWS_NOTHING( alg.execute(); );
    TS_ASSERT( alg.isExecuted() );
    
    // Retrieve the workspace from data service. TODO: Change to your desired type
    Workspace_sptr ws;
    TS_ASSERT_THROWS_NOTHING( ws = boost::dynamic_pointer_cast<Workspace>(AnalysisDataService::Instance().retrieve(outWSName)) );
    TS_ASSERT(ws);
    if (!ws) return;
    
    // TODO: Check the results
    
    // Remove workspace from the data service.
    AnalysisDataService::Instance().remove(outWSName);
  }
  """ % (classname,classname,classname);
#include "MantidKernel/Timer.h"
#include "MantidKernel/System.h"
#include "Mantid%s/%s%s.h"
using namespace Mantid;
  // This pair of boilerplate methods prevent the suite being created statically
  // This means the constructor isn't called when running other tests
  static %sTest *createSuite() { return new %sTest(); }
  static void destroySuite( %sTest *suite ) { delete suite; }

""" % (guard, guard, subproject, args.subfolder, classname, subproject, classname, classname, classname, classname, algorithm_test, guard)
#======================================================================
def generate(subproject, classname, overwrite, args):
    basedir, header_folder = find_basedir(args.project, subproject)
    headerfile = os.path.join(basedir, "inc", header_folder, args.subfolder + classname + ".h")
    sourcefile = os.path.join(basedir, "src", args.subfolder + classname + ".cpp")
    testfile = os.path.join(basedir, "test", classname + "Test.h")
    if args.header and not overwrite and os.path.exists(headerfile):
        print "\nError! Header file %s already exists. Use --force to overwrite.\n" % headerfile
        return
    if args.cpp and not overwrite and os.path.exists(sourcefile):
        print "\nError! Source file %s already exists. Use --force to overwrite.\n" % sourcefile
        return
    if args.test and not overwrite and os.path.exists(testfile):
        print "\nError! Test file %s already exists. Use --force to overwrite.\n" % testfile
        write_header(subproject, classname, headerfile, args)
        write_source(subproject, classname, sourcefile, args)
        write_test(subproject, classname, testfile, args)
    # Insert into the cmake list
    add_to_cmake(subproject, classname, args, args.subfolder)
Janik Zikovsky's avatar
Janik Zikovsky committed
    print "\n   Files were added to Framework/%s/CMakeLists.txt !" % (subproject)
#    if not test_only:
#        print "\tsrc/%s.cpp" % (classname)
#        print "\tinc/Mantid%s/%s.h" % (subproject, classname)
#    print "\ttest/%sTest.h" % (classname)
#    print  
#======================================================================
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Utility to create Mantid class files: header, source and test.')
    parser.add_argument('subproject', metavar='SUBPROJECT', type=str,
                        help='The subproject under Framework/; e.g. Kernel')
    parser.add_argument('classname', metavar='CLASSNAME', type=str,
                        help='Name of the class to create')
    parser.add_argument('--force', dest='force', action='store_const',
                        const=True, default=False,
                        help='Force overwriting existing files. Use with caution!')
    parser.add_argument('--no-header', dest='header', action='store_const',
                        const=False, default=True,
                        help="Don't create the header file")
    parser.add_argument('--no-test', dest='test', action='store_const',
                        const=False, default=True,
                        help="Don't create the test file")
    parser.add_argument('--no-cpp', dest='cpp', action='store_const',
                        const=False, default=True,
                        help="Don't create the cpp file")
    parser.add_argument('--alg', dest='alg', action='store_const',
                        const=True, default=False,
                        help='Create an Algorithm stub. This adds some methods common to algorithms.')
    parser.add_argument('--subfolder', dest='subfolder', 
                        default="",
                        help='Put the source under a subfolder below the main part of the project, e.g. Geometry/Instrument.')
    parser.add_argument('--project', dest='project', 
                        default="Framework",
                        help='The project in which this goes. Default: Framework. Can be MantidQt, Vates')
    args = parser.parse_args()
    subproject = args.subproject
    classname = args.classname
    overwrite = args.force

    # Make sure the subfolders end with a /
    if args.subfolder != "":
        if args.subfolder[-1:] != "/":
            args.subfolder += "/"
    generate(subproject, classname, overwrite, args)