public void __delete__(PyObject obj) {
   PyType self_type = getType();
   PyObject impl = self_type.lookup("__delete__");
   if (impl != null) {
     impl.__get__(this, self_type).__call__(obj);
     return;
   }
   super.__delete__(obj);
 }
 public void __delattr__(String name) {
   PyType self_type = getType();
   PyObject impl = self_type.lookup("__delattr__");
   if (impl != null) {
     impl.__get__(this, self_type).__call__(PyString.fromInterned(name));
     return;
   }
   super.__delattr__(name);
 }
 public void __delitem__(PyObject key) { // ???
   PyType self_type = getType();
   PyObject impl = self_type.lookup("__delitem__");
   if (impl != null) {
     impl.__get__(this, self_type).__call__(key);
     return;
   }
   super.__delitem__(key);
 }
 public void __delslice__(PyObject start, PyObject stop, PyObject step) {
   if (step != null) {
     __delitem__(new PySlice(start, stop, step));
     return;
   }
   PyType self_type = getType();
   PyObject impl = self_type.lookup("__delslice__");
   if (impl != null) {
     PyObject[] indices = PySlice.indices2(this, start, stop);
     impl.__get__(this, self_type).__call__(indices[0], indices[1]);
     return;
   }
   super.__delslice__(start, stop, step);
 }
  public PythonRunner(
      Map<String, String> environment,
      Repositories repositories,
      Scheduler scheduler,
      Hierarchy loggerRepository,
      String pythonPath,
      BufferedWriter out,
      BufferedWriter err)
      throws Exception {

    init();

    this.staticContext = new StaticContext(scheduler, loggerRepository).repository(repositories);
    this.environment = environment;

    final PySystemState systemState = new PySystemState();
    interpreter = new PythonInterpreter(null, systemState);
    for (String path : pythonPath.split(":")) {
      systemState.path.add(new PyString(path));
    }
    interpreter.setOut(out);
    interpreter.setErr(err);
    scriptContext = staticContext.scriptContext();

    // XPM module
    final PyModule xpmModule = new PyModule("xpm", (PyObject) null);
    systemState.modules.__setitem__("xpm", xpmModule);

    // Add classes
    for (PyType type : TYPES.values()) {
      xpmModule.__setattr__(type.getName(), type);
    }

    // Add constants
    Scripting.forEachConstant(
        (name, value) -> {
          xpmModule.__setattr__(name, wrap(value));
        });

    // Add functions
    Scripting.forEachFunction(
        m -> {
          xpmModule.__setattr__(m.getKey(), new PythonMethod(null, m));
        });

    // Add Python specific functions
    for (MethodFunction m : Scripting.getMethodFunctions(PythonFunctions.class)) {
      xpmModule.__setattr__(m.getKey(), new PythonMethod(null, m));
    }

    // XPM object: wrap properties
    final XPM xpm = new XPM();
    ClassDescription xpmDescription = ClassDescription.analyzeClass(XPM.class);
    for (Map.Entry<Object, MethodFunction> x : xpmDescription.getMethods().entrySet()) {
      final Object key = x.getKey();
      if (key instanceof String) {
        xpmModule.__setattr__((String) key, new PythonMethod(xpm, x.getValue()));
      } else {
        throw new XPMRuntimeException("Could not handle key ", key);
      }
    }

    // Add properties
    xpmModule.__setattr__("tasks", wrap(new Tasks()));
    xpmModule.__setattr__("logger", wrap(new ScriptingLogger("xpm")));
    xpmModule.__setattr__("env", wrap(environment));
  }