[Jython-checkins] jython: Added PyShadowString.java. I had forgotten to call hg add on that file when I

stefan.richthofer jython-checkins at python.org
Sun Feb 26 19:22:33 EST 2017


https://hg.python.org/jython/rev/0d2b840f6df8
changeset:   8036:0d2b840f6df8
user:        Stefan Richthofer <stefan.richthofer at gmx.de>
date:        Mon Feb 27 01:22:01 2017 +0100
summary:
  Added PyShadowString.java. I had forgotten to call hg add on that file when I committed https://hg.python.org/jython/rev/a01c366576b8

files:
  src/org/python/core/PyShadowString.java |  283 ++++++++++++
  1 files changed, 283 insertions(+), 0 deletions(-)


diff --git a/src/org/python/core/PyShadowString.java b/src/org/python/core/PyShadowString.java
new file mode 100644
--- /dev/null
+++ b/src/org/python/core/PyShadowString.java
@@ -0,0 +1,283 @@
+package org.python.core;
+
+import org.python.expose.ExposedMethod;
+import org.python.expose.ExposedNew;
+import org.python.expose.ExposedType;
+import org.python.expose.MethodType;
+
+ at Untraversable
+ at ExposedType(name = "shadowstr", base = PyString.class, isBaseType = false)
+public class PyShadowString extends PyString {
+    public static final PyType TYPE = PyType.fromClass(PyShadowString.class);
+
+    protected PyList targets;
+
+    /**
+     * The shadow string is additionally used for some comparisons, especially for __eq__.
+     * __eq__ will evaluate positive if the other string equals the actual value
+     * *or* the shadow. The shadow persists slicing (is sliced accordingly)
+     * and is taken into account by startswith.
+     */
+    protected String shadow;
+    
+    // for PyJavaClass.init()
+    public PyShadowString() {
+        this(TYPE, "", "");
+        targets = new PyList();
+    }
+
+    public PyShadowString(String str, String shadow) {
+        super(TYPE, str);
+        this.shadow = shadow;
+        targets = new PyList();
+    }
+
+    public PyShadowString(String str, String shadow, boolean isBytes) {
+        super(TYPE, str, isBytes);
+        this.shadow = shadow;
+        targets = new PyList();
+    }
+    
+    public PyShadowString(String str, String shadow, boolean isBytes, PyList targets) {
+        super(TYPE, str, isBytes);
+        this.shadow = shadow;
+        this.targets = targets;
+    }
+
+    public PyShadowString(PyObject str, String shadow) {
+        super(str.toString());
+        this.shadow = shadow;
+        targets = new PyList();
+    }
+
+    public PyShadowString(PyType subtype, String str, String shadow) {
+        super(subtype, str);
+        this.shadow = shadow;
+        targets = new PyList();
+    }
+
+    public PyShadowString(PyType subtype, PyObject str, String shadow) {
+        super(subtype, str.toString());
+        this.shadow = shadow;
+        targets = new PyList();
+    }
+
+    @ExposedNew
+    static PyObject shadowstr_new(PyNewWrapper new_, boolean init, PyType subtype,
+            PyObject[] args, String[] keywords) {
+        ArgParser ap = new ArgParser("shadowstr", args, keywords,
+                new String[] {"string", "shadow"}, 0);
+        PyObject S = ap.getPyObject(0, null);
+        PyObject Sh = ap.getPyObject(1, null);
+        // Get the textual representation of the object into str/bytes form
+        String str, shd;
+        if (S == null) {
+            str = "";
+        } else {
+            // Let the object tell us its representation: this may be str or unicode.
+            S = S.__str__();
+            if (S instanceof PyUnicode) {
+                // Encoding will raise UnicodeEncodeError if not 7-bit clean.
+                str = codecs.encode((PyUnicode)S, null, null);
+            } else {
+                // Must be str/bytes, and should be 8-bit clean already.
+                str = S.toString();
+            }
+        }
+        if (Sh == null) {
+            shd = "";
+        } else {
+            // Let the object tell us its representation: this may be str or unicode.
+            Sh = Sh.__str__();
+            if (Sh instanceof PyUnicode) {
+                // Encoding will raise UnicodeEncodeError if not 7-bit clean.
+                shd = codecs.encode((PyUnicode)Sh, null, null);
+            } else {
+                // Must be str/bytes, and should be 8-bit clean already.
+                shd = Sh.toString();
+            }
+        }
+        return new PyShadowString(str, shd);
+    }
+
+    private boolean isTarget() {
+        Exception exc = new Exception();
+        PyObject obj;
+        boolean result;
+        for (StackTraceElement ste: exc.getStackTrace()) {
+            for (PyObject itm: targets.getList()) {
+                result = true;
+                obj = ((PyTuple) itm).__finditem__(0);
+                if (obj != null && obj != Py.None) {
+                    if (!ste.getClassName().matches(obj.toString())) {
+                        result = false;
+                    }
+                }
+                if (result) {
+                    obj = ((PyTuple) itm).__finditem__(1);
+                    if (obj != null && obj != Py.None) {
+                        if (!ste.getMethodName().matches(obj.toString())) {
+                            result = false;
+                        }
+                    }
+                }
+                if (result) {
+                    // we have a match
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public String getShadow() {
+        return shadow;
+    }
+
+    public PyString getshadow() {
+        return (PyString) shadowstr_getshadow();
+    }
+
+    @ExposedMethod
+    public final PyObject shadowstr_getshadow() {
+        return Py.newString(shadow);
+    }
+
+    public void addTarget(String className, String methodName) {
+        PyString classname = className == null ? null : Py.newString(className);
+        PyString methodname = methodName == null ? null : Py.newString(methodName);
+        shadowstr_addtarget(classname, methodname);
+    }
+
+    @ExposedMethod(defaults = {"null"})
+    public final void shadowstr_addtarget(PyObject classname, PyObject methodname) {
+        targets.add(methodname != null ?
+                new PyTuple(classname == null ? Py.None : classname, methodname) :
+                new PyTuple(classname == null ? Py.None : classname));
+    }
+
+    public PyList getTargets() {
+        return (PyList) shadowstr_gettargets();
+    }
+
+    @ExposedMethod
+    public final PyObject shadowstr_gettargets() {
+        return targets;
+    }
+
+    @Override
+    public PyObject __eq__(PyObject other) {
+        if (!isTarget()) {
+            return str___eq__(other);
+        }
+        return shadowstr___eq__(other);
+    }
+
+    @ExposedMethod(type = MethodType.BINARY)
+    final PyObject shadowstr___eq__(PyObject other) {
+        String s = other.toString();
+        if (s != null && s.equals(shadow)) return Py.True;
+        return str___eq__(other);
+    }
+
+    @Override
+    protected PyShadowString fromSubstring(int begin, int end) {
+        // Method is overridden in PyUnicode, so definitely a PyString
+        int shadowBegin = begin, shadowEnd = end;
+        if (begin > shadow.length()) {
+            shadowBegin = shadow.length();
+        }
+        if (end > shadow.length()) {
+            shadowEnd = shadow.length();
+        }
+        return new PyShadowString(getString().substring(begin, end),
+                shadow.substring(shadowBegin, shadowEnd), true, targets);
+    }
+
+    @Override
+    protected PyObject getslice(int start, int stop, int step) {
+        if (step > 0 && stop < start) {
+            stop = start;
+        }
+        if (step == 1) {
+            return fromSubstring(start, stop);
+        } else {
+            int n = sliceLength(start, stop, step);
+            char new_chars[] = new char[n];
+            int j = 0;
+            for (int i = start; j < n; i += step) {
+                new_chars[j++] = getString().charAt(i);
+            }
+            char new_shadow_chars[] = new char[n];
+            j = 0;
+            try {
+                for (int i = start; j < n; i += step) {
+                    new_chars[j] = shadow.charAt(i);
+                    j++; // separate line, so in exception case j is clearly before increment
+                }
+            } catch (IndexOutOfBoundsException ioobe)
+            {
+                return new PyShadowString(new String(new_chars),
+                        new String(new_shadow_chars, 0, j), true, targets);
+            }
+            return new PyShadowString(new String(new_chars),
+                    new String(new_shadow_chars), true, targets);
+        }
+    }
+
+    @Override
+    public boolean startswith(PyObject prefix) {
+        return shadowstr_startswith(prefix, null, null);
+    }
+
+    @Override
+    public boolean startswith(PyObject prefix, PyObject start) {
+        return shadowstr_startswith(prefix, start, null);
+    }
+
+    @Override
+    public boolean startswith(PyObject prefix, PyObject start, PyObject end) {
+        return shadowstr_startswith(prefix, start, end);
+    }
+
+    @ExposedMethod(defaults = {"null", "null"})
+    final boolean shadowstr_startswith(PyObject prefix, PyObject startObj, PyObject endObj) {
+        if (!isTarget()) {
+            return str_startswith(prefix, startObj, endObj);
+        }
+        int[] indices = translateIndices(startObj, endObj);
+        int start = indices[0];
+        int sliceLen = indices[1] - start;
+
+        if (!(prefix instanceof PyTuple)) {
+            // It ought to be PyUnicode or some kind of bytes with the buffer API.
+            String s = asUTF16StringOrError(prefix);
+            // If s is non-BMP, and this is a PyString (bytes), result will correctly be false.
+            return sliceLen >= s.length() &&
+                    (getString().startsWith(s, start) || shadow.startsWith(s, start));
+        } else {
+            // Loop will return true if this slice starts with any prefix in the tuple
+            for (PyObject prefixObj : ((PyTuple)prefix).getArray()) {
+                // It ought to be PyUnicode or some kind of bytes with the buffer API.
+                String s = asUTF16StringOrError(prefixObj);
+                // If s is non-BMP, and this is a PyString (bytes), result will correctly be false.
+                if (sliceLen >= s.length() &&
+                        (getString().startsWith(s, start) || shadow.startsWith(s, start))) {
+                    return true;
+                }
+            }
+            // None matched
+            return false;
+        }
+    }
+
+    @Override
+    public PyString __repr__() {
+        return shadowstr___repr__();
+    }
+
+    @ExposedMethod
+    final PyString shadowstr___repr__() {
+        return new PyString(encode_UnicodeEscape(getString()+" ( =="+shadow+" for targets )", true));
+    }
+}

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list