<commit_before>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include "PythonGeneratedDatasetReaction.h"
#include "vtkPython.h" // must be first

#include "ActiveObjects.h"
#include "DataSource.h"
#include "ModuleManager.h"
#include "Utilities.h"
#include "pqActiveObjects.h"
#include "pqRenderView.h"
#include "vtkImageData.h"
#include "vtkNew.h"
#include "vtkPythonInterpreter.h"
#include "vtkPythonUtil.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMSourceProxy.h"
#include "vtkSmartPointer.h"
#include "vtkSmartPyObject.h"
#include "vtkTrivialProducer.h"

#include <QDebug>
#include <QDialog>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QSpinBox>
#include <QVBoxLayout>

#include <limits>

namespace {

class PythonGeneratedDataSource : public QObject
{
  Q_OBJECT
  typedef QObject Superclass;

public:
  PythonGeneratedDataSource(const QString& l, QObject* p = nullptr)
    : Superclass(p), label(l)
  {
  }

  ~PythonGeneratedDataSource() {}

  void setScript(const QString& script)
  {
    vtkPythonInterpreter::Initialize();

    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      this->OperatorModule.TakeReference(PyImport_ImportModule("tomviz.utils"));
    }
    if (!this->OperatorModule) {
      qCritical() << "Failed to import tomviz.utils module.";
      tomviz::checkForPythonError();
    }

    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      this->Code.TakeReference(Py_CompileString(
        script.toLatin1().data(), this->label.toLatin1().data(),
        Py_file_input /*Py_eval_input*/));
    }
    if (!this->Code) {
      tomviz::checkForPythonError();
      qCritical()
        << "Invalid script. Please check the traceback message for details.";
      return;
    }

    vtkSmartPyObject module;
    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      module.TakeReference(PyImport_ExecCodeModule(
        // Don't let these be the same, even for similar scripts.  Seems to
        // cause python crashes.
        QString("tomviz_%1%2")
          .arg(this->label)
          .arg(number_of_scripts++)
          .toLatin1()
          .data(),
        this->Code));
    }
    if (!module) {
      tomviz::checkForPythonError();
      qCritical() << "Failed to create module.";
      return;
    }
    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      this->GenerateFunction.TakeReference(
        PyObject_GetAttrString(module, "generate_dataset"));
    }
    if (!this->GenerateFunction) {
      tomviz::checkForPythonError();
      qCritical() << "Script does not have a 'generate_dataset' function.";
      return;
    }
    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      this->MakeDatasetFunction.TakeReference(
        PyObject_GetAttrString(this->OperatorModule, "make_dataset"));
    }
    if (!this->MakeDatasetFunction) {
      tomviz::checkForPythonError();
      qCritical() << "Could not find make_dataset function in tomviz.utils";
      return;
    }
    tomviz::checkForPythonError();
    this->pythonScript = script;
  }

  vtkSmartPointer<vtkSMSourceProxy> createDataSource(const int shape[3])
  {
    vtkNew<vtkImageData> image;
    vtkSmartPointer<vtkSMSourceProxy> retVal;
    vtkSmartPyObject args;
    vtkSmartPyObject result;
    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      args.TakeReference(PyTuple_New(5));
      PyTuple_SET_ITEM(args.GetPointer(), 0, PyInt_FromLong(shape[0]));
      PyTuple_SET_ITEM(args.GetPointer(), 1, PyInt_FromLong(shape[1]));
      PyTuple_SET_ITEM(args.GetPointer(), 2, PyInt_FromLong(shape[2]));
      PyTuple_SET_ITEM(args.GetPointer(), 3,
                       vtkPythonUtil::GetObjectFromPointer(image.Get()));
      PyTuple_SET_ITEM(args.GetPointer(), 4, this->GenerateFunction);
<commit_msg>Ensure the reference count is incremented before "steal"<commit_after>/******************************************************************************

  This source file is part of the tomviz project.

  Copyright Kitware, Inc.

  This source code is released under the New BSD License, (the "License").

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

******************************************************************************/

#include "PythonGeneratedDatasetReaction.h"
#include "vtkPython.h" // must be first

#include "ActiveObjects.h"
#include "DataSource.h"
#include "ModuleManager.h"
#include "Utilities.h"
#include "pqActiveObjects.h"
#include "pqRenderView.h"
#include "vtkImageData.h"
#include "vtkNew.h"
#include "vtkPythonInterpreter.h"
#include "vtkPythonUtil.h"
#include "vtkSMSessionProxyManager.h"
#include "vtkSMSourceProxy.h"
#include "vtkSmartPointer.h"
#include "vtkSmartPyObject.h"
#include "vtkTrivialProducer.h"

#include <QDebug>
#include <QDialog>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QHBoxLayout>
#include <QLabel>
#include <QSpinBox>
#include <QVBoxLayout>

#include <limits>

namespace {

class PythonGeneratedDataSource : public QObject
{
  Q_OBJECT
  typedef QObject Superclass;

public:
  PythonGeneratedDataSource(const QString& l, QObject* p = nullptr)
    : Superclass(p), label(l)
  {
  }

  ~PythonGeneratedDataSource() {}

  void setScript(const QString& script)
  {
    vtkPythonInterpreter::Initialize();

    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      this->OperatorModule.TakeReference(PyImport_ImportModule("tomviz.utils"));
    }
    if (!this->OperatorModule) {
      qCritical() << "Failed to import tomviz.utils module.";
      tomviz::checkForPythonError();
    }

    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      this->Code.TakeReference(Py_CompileString(
        script.toLatin1().data(), this->label.toLatin1().data(),
        Py_file_input /*Py_eval_input*/));
    }
    if (!this->Code) {
      tomviz::checkForPythonError();
      qCritical()
        << "Invalid script. Please check the traceback message for details.";
      return;
    }

    vtkSmartPyObject module;
    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      module.TakeReference(PyImport_ExecCodeModule(
        // Don't let these be the same, even for similar scripts.  Seems to
        // cause python crashes.
        QString("tomviz_%1%2")
          .arg(this->label)
          .arg(number_of_scripts++)
          .toLatin1()
          .data(),
        this->Code));
    }
    if (!module) {
      tomviz::checkForPythonError();
      qCritical() << "Failed to create module.";
      return;
    }
    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      this->GenerateFunction.TakeReference(
        PyObject_GetAttrString(module, "generate_dataset"));
    }
    if (!this->GenerateFunction) {
      tomviz::checkForPythonError();
      qCritical() << "Script does not have a 'generate_dataset' function.";
      return;
    }
    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      this->MakeDatasetFunction.TakeReference(
        PyObject_GetAttrString(this->OperatorModule, "make_dataset"));
    }
    if (!this->MakeDatasetFunction) {
      tomviz::checkForPythonError();
      qCritical() << "Could not find make_dataset function in tomviz.utils";
      return;
    }
    tomviz::checkForPythonError();
    this->pythonScript = script;
  }

  vtkSmartPointer<vtkSMSourceProxy> createDataSource(const int shape[3])
  {
    vtkNew<vtkImageData> image;
    vtkSmartPointer<vtkSMSourceProxy> retVal;
    vtkSmartPyObject args;
    vtkSmartPyObject result;
    {
      vtkPythonScopeGilEnsurer gilEnsurer(true);
      args.TakeReference(PyTuple_New(5));
      PyTuple_SET_ITEM(args.GetPointer(), 0, PyInt_FromLong(shape[0]));
      PyTuple_SET_ITEM(args.GetPointer(), 1, PyInt_FromLong(shape[1]));
      PyTuple_SET_ITEM(args.GetPointer(), 2, PyInt_FromLong(shape[2]));
      PyTuple_SET_ITEM(args.GetPointer(), 3,
                       vtkPythonUtil::GetObjectFromPointer(image.Get()));
      // PyTuple_SET_ITEM will "steal" a reference to this->GenerateFunction so
      // we need to increment the reference count before calling
      // PyTuple_SET_ITEM.
      PyTuple_SET_ITEM(args.GetPointer(), 4,
                       this->GenerateFunction.GetAndIncreaseReferenceCount());

{'fraction_non_alphanumeric': 0.14280969777482563, 'fraction_numerical': 0.0033211557622052474, 'mean_word_length': 3.7976633032395113, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 56, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3421545', 'n_tokens_mistral': 2834, 'n_tokens_neox': 2718, 'n_words': 597}