0001: package org.python.core;
0002:
0003: import java.io.Serializable;
0004: import java.lang.reflect.Constructor;
0005: import java.lang.reflect.Field;
0006: import java.lang.reflect.Method;
0007: import java.lang.reflect.Modifier;
0008: import java.util.ArrayList;
0009: import java.util.HashMap;
0010: import java.util.Iterator;
0011: import java.util.List;
0012:
0013: /**
0014: * first-class Python type.
0015: *
0016: */
0017: public class PyType extends PyObject implements Serializable {
0018: //~ BEGIN GENERATED REGION -- DO NOT EDIT SEE gexpose.py
0019: /* type info */
0020:
0021: public static final String exposed_name = "type";
0022:
0023: public static void typeSetup(PyObject dict, PyType.Newstyle marker) {
0024: dict.__setitem__("__dict__", new PyGetSetDescr("__dict__",
0025: PyType.class, "getDict", "setDict", "delDict"));
0026: dict.__setitem__("__name__", new PyGetSetDescr("__name__",
0027: PyType.class, "fastGetName", null, null));
0028: dict.__setitem__("__base__", new PyGetSetDescr("__base__",
0029: PyType.class, "getBase", null, null));
0030: dict.__setitem__("__bases__", new PyGetSetDescr("__bases__",
0031: PyType.class, "getBases", "setBases", "delBases"));
0032: dict.__setitem__("__mro__", new PyGetSetDescr("__mro__",
0033: PyType.class, "getMro", null, null));
0034: class exposed_mro extends PyBuiltinMethodNarrow {
0035:
0036: exposed_mro(PyObject self, PyBuiltinFunction.Info info) {
0037: super (self, info);
0038: }
0039:
0040: public PyBuiltinFunction bind(PyObject self) {
0041: return new exposed_mro(self, info);
0042: }
0043:
0044: public PyObject __call__(PyObject arg0) {
0045: return ((PyType) self).type_mro(arg0);
0046: }
0047:
0048: public PyObject __call__() {
0049: return ((PyType) self).type_mro();
0050: }
0051:
0052: }
0053: dict.__setitem__("mro", new PyMethodDescr("mro", PyType.class,
0054: 0, 1, new exposed_mro(null, null)));
0055: class exposed___getattribute__ extends PyBuiltinMethodNarrow {
0056:
0057: exposed___getattribute__(PyObject self,
0058: PyBuiltinFunction.Info info) {
0059: super (self, info);
0060: }
0061:
0062: public PyBuiltinFunction bind(PyObject self) {
0063: return new exposed___getattribute__(self, info);
0064: }
0065:
0066: public PyObject __call__(PyObject arg0) {
0067: try {
0068: String name = (arg0.asName(0));
0069: PyObject ret = ((PyType) self)
0070: .type___findattr__(name);
0071: if (ret == null)
0072: ((PyType) self).noAttributeError(name);
0073: return ret;
0074: } catch (PyObject.ConversionException e) {
0075: String msg;
0076: switch (e.index) {
0077: case 0:
0078: msg = "attribute name must be a string";
0079: break;
0080: default:
0081: msg = "xxx";
0082: }
0083: throw Py.TypeError(msg);
0084: }
0085: }
0086:
0087: }
0088: dict.__setitem__("__getattribute__", new PyMethodDescr(
0089: "__getattribute__", PyType.class, 1, 1,
0090: new exposed___getattribute__(null, null)));
0091: class exposed___setattr__ extends PyBuiltinMethodNarrow {
0092:
0093: exposed___setattr__(PyObject self,
0094: PyBuiltinFunction.Info info) {
0095: super (self, info);
0096: }
0097:
0098: public PyBuiltinFunction bind(PyObject self) {
0099: return new exposed___setattr__(self, info);
0100: }
0101:
0102: public PyObject __call__(PyObject arg0, PyObject arg1) {
0103: try {
0104: ((PyType) self).type___setattr__(arg0.asName(0),
0105: arg1);
0106: return Py.None;
0107: } catch (PyObject.ConversionException e) {
0108: String msg;
0109: switch (e.index) {
0110: case 0:
0111: msg = "attribute name must be a string";
0112: break;
0113: default:
0114: msg = "xxx";
0115: }
0116: throw Py.TypeError(msg);
0117: }
0118: }
0119:
0120: }
0121: dict.__setitem__("__setattr__", new PyMethodDescr(
0122: "__setattr__", PyType.class, 2, 2,
0123: new exposed___setattr__(null, null)));
0124: class exposed___delattr__ extends PyBuiltinMethodNarrow {
0125:
0126: exposed___delattr__(PyObject self,
0127: PyBuiltinFunction.Info info) {
0128: super (self, info);
0129: }
0130:
0131: public PyBuiltinFunction bind(PyObject self) {
0132: return new exposed___delattr__(self, info);
0133: }
0134:
0135: public PyObject __call__(PyObject arg0) {
0136: try {
0137: ((PyType) self).type___delattr__(arg0.asName(0));
0138: return Py.None;
0139: } catch (PyObject.ConversionException e) {
0140: String msg;
0141: switch (e.index) {
0142: case 0:
0143: msg = "attribute name must be a string";
0144: break;
0145: default:
0146: msg = "xxx";
0147: }
0148: throw Py.TypeError(msg);
0149: }
0150: }
0151:
0152: }
0153: dict.__setitem__("__delattr__", new PyMethodDescr(
0154: "__delattr__", PyType.class, 1, 1,
0155: new exposed___delattr__(null, null)));
0156: class exposed___subclasses__ extends PyBuiltinMethodNarrow {
0157:
0158: exposed___subclasses__(PyObject self,
0159: PyBuiltinFunction.Info info) {
0160: super (self, info);
0161: }
0162:
0163: public PyBuiltinFunction bind(PyObject self) {
0164: return new exposed___subclasses__(self, info);
0165: }
0166:
0167: public PyObject __call__() {
0168: return ((PyType) self).type_getSubclasses();
0169: }
0170:
0171: }
0172: dict.__setitem__("__subclasses__", new PyMethodDescr(
0173: "__subclasses__", PyType.class, 0, 0,
0174: new exposed___subclasses__(null, null)));
0175: class exposed___call__ extends PyBuiltinMethod {
0176:
0177: exposed___call__(PyObject self, PyBuiltinFunction.Info info) {
0178: super (self, info);
0179: }
0180:
0181: public PyBuiltinFunction bind(PyObject self) {
0182: return new exposed___call__(self, info);
0183: }
0184:
0185: public PyObject __call__(PyObject[] args) {
0186: return __call__(args, Py.NoKeywords);
0187: }
0188:
0189: public PyObject __call__(PyObject[] args, String[] keywords) {
0190: return ((PyType) self).type___call__(args, keywords);
0191: }
0192:
0193: }
0194: dict
0195: .__setitem__("__call__", new PyMethodDescr("__call__",
0196: PyType.class, -1, -1, new exposed___call__(
0197: null, null)));
0198: dict.__setitem__("__new__", new PyNewWrapper(PyType.class,
0199: "__new__", -1, -1) {
0200:
0201: public PyObject new_impl(boolean init, PyType subtype,
0202: PyObject[] args, String[] keywords) {
0203: return type_new(this , init, subtype, args, keywords);
0204: }
0205:
0206: });
0207: }
0208:
0209: //~ END GENERATED REGION -- DO NOT EDIT SEE gexpose.py
0210:
0211: public static PyObject type_new(PyNewWrapper new_, boolean init,
0212: PyType subtype, PyObject[] args, String[] keywords) {
0213: if (args.length == 1 && keywords.length == 0) {
0214: return args[0].getType();
0215: }
0216: if (args.length + keywords.length != 3)
0217: throw Py.TypeError("type() takes exactly 1 or 3 arguments");
0218: ArgParser ap = new ArgParser("type()", args, keywords, "name",
0219: "bases", "dict");
0220: String name = ap.getString(0);
0221: PyObject bases = ap.getPyObject(1);
0222: if (!(bases instanceof PyTuple))
0223: throw Py.TypeError("type(): bases must be tuple");
0224: PyObject dict = ap.getPyObject(2);
0225: if (!(dict instanceof PyDictionary || dict instanceof PyStringMap))
0226: throw Py.TypeError("type(): dict must be dict");
0227: return newType(new_, subtype, name, (PyTuple) bases, dict);
0228:
0229: }
0230:
0231: private Object writeReplace() {
0232: //System.err.println("replace type");
0233: return new TypeResolver(underlying_class, getModule()
0234: .toString(), name);
0235: }
0236:
0237: static class TypeResolver implements Serializable {
0238: private Class underlying_class;
0239: private String module;
0240: private String name;
0241:
0242: TypeResolver(Class underlying_class, String module, String name) {
0243: this .underlying_class = underlying_class;
0244: this .module = module;
0245: this .name = name;
0246: }
0247:
0248: private Object readResolve() {
0249: //System.err.println("resolve: "+module+"."+name);
0250: if (underlying_class != null)
0251: return PyType.fromClass(underlying_class);
0252: PyObject mod = imp.importName(module.intern(), false);
0253: PyObject pytyp = mod.__getattr__(name.intern());
0254: if (!(pytyp instanceof PyType)) {
0255: throw Py.TypeError(module + "." + name
0256: + " must be a type for deserialization");
0257: }
0258: return (PyType) pytyp;
0259: }
0260:
0261: }
0262:
0263: public PyObject getStatic() {
0264: PyType cur = this ;
0265: while (cur.underlying_class == null) {
0266: cur = cur.base;
0267: }
0268: return cur;
0269: }
0270:
0271: /**
0272: * Checks that the physical layout between this type and <code>other</code>
0273: * are compatible.
0274: */
0275: public boolean layoutAligns(PyType other) {
0276: return getLayout().equals(other.getLayout())
0277: && needs_userdict == other.needs_userdict
0278: && needs_finalizer == other.needs_finalizer;
0279: }
0280:
0281: /**
0282: * Gets the most parent PyType that determines the layout of this type ie
0283: * has slots or an underlying_class. Can by this PyType.
0284: */
0285: private PyType getLayout() {
0286: if (underlying_class != null) {
0287: return this ;
0288: } else if (numSlots != base.numSlots) {
0289: return this ;
0290: }
0291: return base.getLayout();
0292: }
0293:
0294: public PyObject getBase() {
0295: if (base == null)
0296: return Py.None;
0297: return base;
0298: }
0299:
0300: public PyObject getBases() {
0301: if (bases == null)
0302: return new PyTuple();
0303: return new PyTuple(bases);
0304: }
0305:
0306: public void delBases() {
0307: throw Py.TypeError("Can't delete __bases__ attribute");
0308: }
0309:
0310: public void setBases(PyObject newBasesTuple) {
0311: if (!(newBasesTuple instanceof PyTuple)) {
0312: throw Py.TypeError("bases must be a tuple");
0313: }
0314: PyObject[] newBases = ((PyTuple) newBasesTuple).getArray();
0315: if (newBases.length == 0) {
0316: throw Py
0317: .TypeError("can only assign non-empty tuple to __bases__, not "
0318: + newBasesTuple);
0319: }
0320: for (int i = 0; i < newBases.length; i++) {
0321: if (!(newBases[i] instanceof PyType)) {
0322: if (!(newBases[i] instanceof PyClass)) {
0323: throw Py
0324: .TypeError(name
0325: + ".__bases__ must be a tuple of old- or new-style classes, not "
0326: + newBases[i]);
0327: }
0328: } else {
0329: if (((PyType) newBases[i]).isSubType(this )) {
0330: throw Py
0331: .TypeError("a __bases__ item causes an inheritance cycle");
0332: }
0333: }
0334: }
0335: PyType newBase = best_base(newBases);
0336: if (!newBase.layoutAligns(base)) {
0337: throw Py.TypeError("'" + base + "' layout differs from '"
0338: + newBase + "'");
0339: }
0340: PyObject[] savedBases = bases;
0341: PyType savedBase = base;
0342: PyObject[] savedMro = mro;
0343: List savedSubMros = new ArrayList();
0344: try {
0345: bases = newBases;
0346: base = newBase;
0347: mro_internal();
0348: mro_subclasses(savedSubMros);
0349: for (int i = 0; i < savedBases.length; i++) {
0350: if (savedBases[i] instanceof PyType) {
0351: ((PyType) savedBases[i]).detachSubclass(this );
0352: }
0353: }
0354: for (int i = 0; i < newBases.length; i++) {
0355: if (newBases[i] instanceof PyType) {
0356: ((PyType) newBases[i]).attachSubclass(this );
0357: }
0358: }
0359: } catch (PyException t) {
0360: for (Iterator it = savedSubMros.iterator(); it.hasNext();) {
0361: PyType subtype = (PyType) it.next();
0362: PyObject[] subtypeSavedMro = (PyObject[]) it.next();
0363: subtype.mro = subtypeSavedMro;
0364: }
0365: bases = savedBases;
0366: base = savedBase;
0367: mro = savedMro;
0368: throw t;
0369: }
0370:
0371: }
0372:
0373: private void mro_internal() {
0374: if (getType().underlying_class != PyType.class
0375: && getType().lookup("mro") != null) {
0376: mro = Py.make_array(getType().lookup("mro").__get__(null,
0377: getType()).__call__(this ));
0378: } else {
0379: mro = compute_mro();
0380: }
0381: }
0382:
0383: /**
0384: * Collects the subclasses and current mro of this type in currentMroSaver. If
0385: * this type has subclasses C and D, and D has a subclass E current mro saver will equal
0386: * [C, C.__mro__, D, D.__mro__, E, E.__mro__] after this call.
0387: */
0388: private void mro_subclasses(List mroCollector) {
0389: for (java.util.Iterator iter = subclasses.iterator(); iter
0390: .hasNext();) {
0391: java.lang.ref.WeakReference type_ref = (java.lang.ref.WeakReference) iter
0392: .next();
0393: PyType subtype = (PyType) type_ref.get();
0394: if (subtype == null)
0395: continue;
0396: mroCollector.add(subtype);
0397: mroCollector.add(subtype.mro);
0398: subtype.mro_internal();
0399: subtype.mro_subclasses(mroCollector);
0400: }
0401: }
0402:
0403: public PyObject instDict() {
0404: if (needs_userdict) {
0405: return new PyStringMap();
0406: }
0407: return null;
0408: }
0409:
0410: private String name;
0411: private PyType base;
0412: private PyObject[] bases;
0413: private PyObject dict;
0414: private PyObject[] mro = new PyObject[0];
0415: private Class underlying_class;
0416:
0417: boolean builtin = false;
0418:
0419: private boolean non_instantiable = false;
0420:
0421: boolean has_set, has_delete;
0422:
0423: private boolean needs_finalizer;
0424: private int numSlots;
0425: private boolean needs_userdict = true;
0426:
0427: private java.lang.ref.ReferenceQueue subclasses_refq = new java.lang.ref.ReferenceQueue();
0428: private java.util.HashSet subclasses = new java.util.HashSet();
0429:
0430: private void cleanup_subclasses() {
0431: java.lang.ref.Reference ref;
0432: while ((ref = subclasses_refq.poll()) != null) {
0433: subclasses.remove(ref);
0434: }
0435: }
0436:
0437: public PyTuple getMro() {
0438: return new PyTuple(mro);
0439: }
0440:
0441: public synchronized final PyObject type_getSubclasses() {
0442: PyList result = new PyList();
0443: cleanup_subclasses();
0444: for (java.util.Iterator iter = subclasses.iterator(); iter
0445: .hasNext();) {
0446: java.lang.ref.WeakReference type_ref = (java.lang.ref.WeakReference) iter
0447: .next();
0448: PyType subtype = (PyType) type_ref.get();
0449: if (subtype == null)
0450: continue;
0451: result.append(subtype);
0452: }
0453: return result;
0454: }
0455:
0456: private synchronized void attachSubclass(PyType subtype) {
0457: cleanup_subclasses();
0458: subclasses.add(new java.lang.ref.WeakReference(subtype,
0459: subclasses_refq));
0460: }
0461:
0462: private synchronized void detachSubclass(PyType subtype) {
0463: cleanup_subclasses();
0464: for (java.util.Iterator iter = subclasses.iterator(); iter
0465: .hasNext();) {
0466: java.lang.ref.WeakReference type_ref = (java.lang.ref.WeakReference) iter
0467: .next();
0468: PyType refType = (PyType) type_ref.get();
0469: if (refType == subtype) {
0470: subclasses.remove(type_ref);
0471: break;
0472: }
0473: }
0474: }
0475:
0476: private interface OnType {
0477: boolean onType(PyType type);
0478: }
0479:
0480: private synchronized void traverse_hierarchy(boolean top,
0481: OnType behavior) {
0482: boolean stop = false;
0483: if (!top) {
0484: stop = behavior.onType(this );
0485: }
0486: if (stop)
0487: return;
0488: for (java.util.Iterator iter = subclasses.iterator(); iter
0489: .hasNext();) {
0490: java.lang.ref.WeakReference type_ref = (java.lang.ref.WeakReference) iter
0491: .next();
0492: PyType subtype = (PyType) type_ref.get();
0493: if (subtype == null)
0494: continue;
0495: subtype.traverse_hierarchy(false, behavior);
0496: }
0497: }
0498:
0499: private static void fill_classic_mro(ArrayList acc,
0500: PyClass classic_cl) {
0501: if (!acc.contains(classic_cl))
0502: acc.add(classic_cl);
0503: PyObject[] bases = classic_cl.__bases__.getArray();
0504: for (int i = 0; i < bases.length; i++) {
0505: fill_classic_mro(acc, (PyClass) bases[i]);
0506: }
0507: }
0508:
0509: private static PyObject[] classic_mro(PyClass classic_cl) {
0510: ArrayList acc = new ArrayList();
0511: fill_classic_mro(acc, classic_cl);
0512: return (PyObject[]) acc.toArray(new PyObject[0]);
0513: }
0514:
0515: private static boolean tail_contains(PyObject[] lst, int whence,
0516: PyObject o) {
0517: int n = lst.length;
0518: for (int i = whence + 1; i < n; i++) {
0519: if (lst[i] == o)
0520: return true;
0521: }
0522: return false;
0523: }
0524:
0525: private static PyException mro_error(PyObject[][] to_merge,
0526: int[] remain) {
0527: StringBuffer msg = new StringBuffer(
0528: "Cannot create a"
0529: + " consistent method resolution\norder (MRO) for bases ");
0530: PyDictionary set = new PyDictionary();
0531: for (int i = 0; i < to_merge.length; i++) {
0532: PyObject[] lst = to_merge[i];
0533: if (remain[i] < lst.length)
0534: set.__setitem__(lst[remain[i]], Py.None);
0535: }
0536: PyObject iter = set.__iter__();
0537: PyObject cur;
0538: boolean subq = false;
0539: while ((cur = iter.__iternext__()) != null) {
0540: PyObject name = cur.__findattr__("__name__");
0541: if (!subq) {
0542: subq = true;
0543: } else {
0544: msg.append(", ");
0545: }
0546: msg.append(name == null ? "?" : name.toString());
0547: }
0548: return Py.TypeError(msg.toString());
0549: }
0550:
0551: private static void debug(PyObject[] objs) {
0552: System.out.println(new PyList(objs).toString());
0553: }
0554:
0555: final PyList type_mro() {
0556: return new PyList(compute_mro());
0557:
0558: }
0559:
0560: final PyList type_mro(PyObject o) {
0561: return ((PyType) o).type_mro();
0562: }
0563:
0564: final PyObject[] compute_mro() {
0565: PyObject[] bases = this .bases;
0566: int n = bases.length;
0567: for (int i = 0; i < n; i++) {
0568: PyObject cur = bases[i];
0569: for (int j = i + 1; j < n; j++) {
0570: if (bases[j] == cur) {
0571: PyObject name = cur.__findattr__("__name__");
0572: throw Py.TypeError("duplicate base class "
0573: + (name == null ? "?" : name.toString()));
0574: }
0575: }
0576: }
0577:
0578: int nmerge = n + 1;
0579:
0580: PyObject[][] to_merge = new PyObject[nmerge][];
0581: int[] remain = new int[nmerge];
0582:
0583: for (int i = 0; i < n; i++) {
0584: PyObject cur = bases[i];
0585: remain[i] = 0;
0586: if (cur instanceof PyType) {
0587: to_merge[i] = ((PyType) cur).mro;
0588: } else if (cur instanceof PyClass) {
0589: to_merge[i] = classic_mro((PyClass) cur);
0590: }
0591: }
0592:
0593: to_merge[n] = bases;
0594: remain[n] = 0;
0595:
0596: ArrayList acc = new ArrayList();
0597: acc.add(this );
0598:
0599: int empty_cnt = 0;
0600:
0601: scan: for (int i = 0; i < nmerge; i++) {
0602: PyObject candidate;
0603: PyObject[] cur = to_merge[i];
0604: if (remain[i] >= cur.length) {
0605: empty_cnt++;
0606: continue scan;
0607: }
0608:
0609: candidate = cur[remain[i]];
0610: for (int j = 0; j < nmerge; j++)
0611: if (tail_contains(to_merge[j], remain[j], candidate))
0612: continue scan;
0613: acc.add(candidate);
0614: for (int j = 0; j < nmerge; j++) {
0615: if (remain[j] < to_merge[j].length
0616: && to_merge[j][remain[j]] == candidate)
0617: remain[j]++;
0618: }
0619: // restart scan
0620: i = -1;
0621: empty_cnt = 0;
0622: }
0623: if (empty_cnt == nmerge) {
0624: return (PyObject[]) acc.toArray(bases);
0625: }
0626: throw mro_error(to_merge, remain);
0627: }
0628:
0629: /**
0630: * Finds the parent of base with an underlying_class or with slots
0631: *
0632: * @raises Py.TypeError if there is no solid base for base
0633: */
0634: private static PyType solid_base(PyType base) {
0635: PyObject[] mro = base.mro;
0636: for (int i = 0; i < mro.length; i++) {
0637: PyObject parent = mro[i];
0638: if (parent instanceof PyType) {
0639: PyType parent_type = (PyType) parent;
0640: if (isSolidBase(parent_type))
0641: return parent_type;
0642: }
0643: }
0644: throw Py.TypeError("base without solid base");
0645: }
0646:
0647: private static boolean isSolidBase(PyType type) {
0648: return type.underlying_class != null || type.numSlots != 0;
0649: }
0650:
0651: /**
0652: * Finds the base in bases with the most derived solid_base, ie the most base type
0653: *
0654: * @throws Py.TypeError if the bases don't all derive from the same solid_base
0655: * @throws Py.TypeError if at least one of the bases isn't a new-style class
0656: */
0657: private static PyType best_base(PyObject[] bases) {
0658: PyType winner = null;
0659: PyType candidate = null;
0660: PyType best = null;
0661: for (int i = 0; i < bases.length; i++) {
0662: PyObject base_proto = bases[i];
0663: if (base_proto instanceof PyClass)
0664: continue;
0665: if (!(base_proto instanceof PyType))
0666: throw Py.TypeError("bases must be types");
0667: PyType base = (PyType) base_proto;
0668: candidate = solid_base(base);
0669: if (winner == null) {
0670: winner = candidate;
0671: best = base;
0672: } else if (winner.isSubType(candidate)) {
0673: ;
0674: } else if (candidate.isSubType(winner)) {
0675: winner = candidate;
0676: best = base;
0677: } else {
0678: throw Py
0679: .TypeError("multiple bases have instance lay-out conflict");
0680: }
0681: }
0682: if (best == null)
0683: throw Py
0684: .TypeError("a new-style class can't have only classic bases");
0685: return best;
0686: }
0687:
0688: public static PyObject newType(PyNewWrapper new_, PyType metatype,
0689: String name, PyTuple bases, PyObject dict) {
0690: PyType object_type = fromClass(PyObject.class);
0691:
0692: PyObject[] bases_list = bases.getArray();
0693: PyType winner = findMostDerivedMetatype(bases_list, metatype);
0694: if (winner != metatype) {
0695: PyObject winner_new_ = winner.lookup("__new__");
0696: if (winner_new_ != null && winner_new_ != new_) {
0697: return invoke_new_(new_, winner, false, new PyObject[] {
0698: new PyString(name), bases, dict },
0699: Py.NoKeywords);
0700: }
0701: metatype = winner;
0702: }
0703: if (bases_list.length == 0) {
0704: bases_list = new PyObject[] { object_type };
0705: }
0706:
0707: // xxx can be subclassed ?
0708: if (dict.__finditem__("__module__") == null) {
0709: PyFrame frame = Py.getFrame();
0710: if (frame != null) {
0711: PyObject globals = frame.f_globals;
0712: PyObject modname;
0713: if ((modname = globals.__finditem__("__name__")) != null) {
0714: dict.__setitem__("__module__", modname);
0715: }
0716: }
0717: }
0718: // xxx also __doc__ __module__
0719:
0720: PyType newtype;
0721: if (new_.for_type == metatype) {
0722: newtype = new PyType(); // xxx set metatype
0723: } else {
0724: newtype = new PyTypeDerived(metatype);
0725: }
0726: newtype.dict = dict;
0727: newtype.name = name;
0728: newtype.base = best_base(bases_list);
0729: newtype.numSlots = newtype.base.numSlots;
0730: newtype.bases = bases_list;
0731:
0732: PyObject slots = dict.__finditem__("__slots__");
0733: if (slots != null) {
0734: newtype.needs_userdict = false;
0735: if (slots instanceof PyString) {
0736: addSlot(newtype, slots);
0737: } else {
0738: PyObject iter = slots.__iter__();
0739: PyObject slotname;
0740: for (; (slotname = iter.__iternext__()) != null;) {
0741: addSlot(newtype, slotname);
0742: }
0743: }
0744: }
0745: if (!newtype.needs_userdict) {
0746: newtype.needs_userdict = necessitatesUserdict(bases_list);
0747: }
0748:
0749: // special case __new__, if function => static method
0750: PyObject tmp = dict.__finditem__("__new__");
0751: if (tmp != null && tmp instanceof PyFunction) { // xxx java functions?
0752: dict.__setitem__("__new__", new PyStaticMethod(tmp));
0753: }
0754:
0755: newtype.mro_internal();
0756: // __dict__ descriptor
0757: if (newtype.needs_userdict
0758: && newtype.lookup("__dict__") == null) {
0759: dict.__setitem__("__dict__", new PyGetSetDescr(newtype,
0760: "__dict__", PyObject.class, "getDict", "setDict",
0761: "delDict"));
0762: }
0763:
0764: newtype.has_set = newtype.lookup("__set__") != null;
0765: newtype.has_delete = newtype.lookup("__delete__") != null;
0766: newtype.needs_finalizer = newtype.lookup("__del__") != null;
0767:
0768: for (int i = 0; i < bases_list.length; i++) {
0769: PyObject cur = bases_list[i];
0770: if (cur instanceof PyType)
0771: ((PyType) cur).attachSubclass(newtype);
0772: }
0773: return newtype;
0774: }
0775:
0776: private static boolean necessitatesUserdict(PyObject[] bases_list) {
0777: for (int i = 0; i < bases_list.length; i++) {
0778: PyObject cur = bases_list[i];
0779: if ((cur instanceof PyType && ((PyType) cur).needs_userdict && ((PyType) cur).numSlots > 0)
0780: || cur instanceof PyClass) {
0781: return true;
0782: }
0783: }
0784: return false;
0785: }
0786:
0787: /**
0788: * Finds the most derived subtype of initialMetatype in the types of bases, or initialMetatype if
0789: * it is already the most derived.
0790: *
0791: * @raises Py.TypeError if the all the metaclasses don't descend from the same base
0792: * @raises Py.TypeError if one of the bases is a PyJavaClass or a PyClass with no proxyClass
0793: */
0794: private static PyType findMostDerivedMetatype(
0795: PyObject[] bases_list, PyType initialMetatype) {
0796: PyType winner = initialMetatype;
0797: for (int i = 0; i < bases_list.length; i++) {
0798: PyObject bases_i = bases_list[i];
0799: if (bases_i instanceof PyJavaClass)
0800: throw Py
0801: .TypeError("can't mix new-style and java classes");
0802: if (bases_i instanceof PyClass) {
0803: if (((PyClass) bases_i).proxyClass != null)
0804: throw Py
0805: .TypeError("can't mix new-style and java classes");
0806: continue;
0807: }
0808: PyType curtype = bases_i.getType();
0809: if (winner.isSubType(curtype))
0810: continue;
0811: if (curtype.isSubType(winner)) {
0812: winner = curtype;
0813: continue;
0814: }
0815: throw Py.TypeError("metaclass conflict: "
0816: + "the metaclass of a derived class "
0817: + "must be a (non-strict) subclass "
0818: + "of the metaclasses of all its bases");
0819: }
0820: return winner;
0821: }
0822:
0823: private static void addSlot(PyType newtype, PyObject slotname) {
0824: confirmIdentifier(slotname);
0825: String slotstring = mangleName(newtype.name, slotname
0826: .toString());
0827: if (slotstring.equals("__dict__")) {
0828: newtype.needs_userdict = true;
0829: } else {
0830: newtype.dict.__setitem__(slotstring, new PySlot(newtype,
0831: slotstring, newtype.numSlots++));
0832: }
0833: }
0834:
0835: public String fastGetName() {
0836: return name;
0837: }
0838:
0839: public boolean isSubType(PyType super type) {
0840: PyObject[] mro = this .mro;
0841: for (int i = 0; i < mro.length; i++) {
0842: if (mro[i] == super type)
0843: return true;
0844: }
0845: return false;
0846: }
0847:
0848: /**
0849: * INTERNAL lookup for name through mro objects' dicts
0850: *
0851: * @param name
0852: * attribute name (must be interned)
0853: * @return found object or null
0854: */
0855: public PyObject lookup(String name) {
0856: PyObject[] mro = this .mro;
0857: for (int i = 0; i < mro.length; i++) {
0858: PyObject dict = mro[i].fastGetDict();
0859: if (dict != null) {
0860: PyObject obj = dict.__finditem__(name);
0861: if (obj != null)
0862: return obj;
0863: }
0864: }
0865: return null;
0866: }
0867:
0868: public PyObject lookup_where(String name, PyObject[] where) {
0869: PyObject[] mro = this .mro;
0870: for (int i = 0; i < mro.length; i++) {
0871: PyObject t = mro[i];
0872: PyObject dict = t.fastGetDict();
0873: if (dict != null) {
0874: PyObject obj = dict.__finditem__(name);
0875: if (obj != null) {
0876: where[0] = t;
0877: return obj;
0878: }
0879: }
0880: }
0881: return null;
0882: }
0883:
0884: public PyObject super _lookup(PyType ref, String name) {
0885: PyObject[] mro = this .mro;
0886: int i;
0887: for (i = 0; i < mro.length; i++) {
0888: if (mro[i] == ref)
0889: break;
0890: }
0891: i++;
0892: for (; i < mro.length; i++) {
0893: PyObject dict = mro[i].fastGetDict();
0894: if (dict != null) {
0895: PyObject obj = dict.__finditem__(name);
0896: if (obj != null)
0897: return obj;
0898: }
0899: }
0900: return null;
0901: }
0902:
0903: private PyType(boolean dummy) {
0904: super (true);
0905: }
0906:
0907: private PyType() {
0908: }
0909:
0910: PyType(PyType subtype) {
0911: super (subtype);
0912: }
0913:
0914: private static String decapitalize(String s) {
0915: char c0 = s.charAt(0);
0916: if (Character.isUpperCase(c0)) {
0917: if (s.length() > 1 && Character.isUpperCase(s.charAt(1)))
0918: return s;
0919: char[] cs = s.toCharArray();
0920: cs[0] = Character.toLowerCase(c0);
0921: return new String(cs);
0922: } else {
0923: return s;
0924: }
0925: }
0926:
0927: private static String normalize_name(String name) {
0928: if (name.endsWith("$"))
0929: name = name.substring(0, name.length() - 1);
0930: return name.intern();
0931: }
0932:
0933: private static Object exposed_decl_get_object(Class c, String name) {
0934: try {
0935: return c.getDeclaredField("exposed_" + name).get(null);
0936: } catch (NoSuchFieldException e) {
0937: return null;
0938: } catch (Exception e) {
0939: throw error(e);
0940: }
0941: }
0942:
0943: private final static String[] EMPTY = new String[0];
0944:
0945: private static PyException error(Exception e) {
0946: return Py.JavaError(e);
0947: }
0948:
0949: private static Method get_non_static_method(Class c, String name,
0950: Class[] parmtypes) {
0951: try {
0952: Method meth = c.getMethod(name, parmtypes);
0953: if (!Modifier.isStatic(meth.getModifiers()))
0954: return meth;
0955: } catch (NoSuchMethodException e) {
0956: }
0957: return null;
0958: }
0959:
0960: private static Method get_descr_method(Class c, String name,
0961: Class[] parmtypes) {
0962: Method meth = get_non_static_method(c, name, parmtypes);
0963: if (meth != null && meth.getDeclaringClass() != PyObject.class) {
0964: return meth;
0965: }
0966: return null;
0967: }
0968:
0969: private static boolean ignore(Method meth) {
0970: Class[] exceptions = meth.getExceptionTypes();
0971: for (int j = 0; j < exceptions.length; j++) {
0972: if (exceptions[j] == PyIgnoreMethodTag.class) {
0973: return true;
0974: }
0975: }
0976: return false;
0977: }
0978:
0979: private final static Class[] O = { PyObject.class };
0980: private final static Class[] OO = { PyObject.class, PyObject.class };
0981:
0982: private static void fillFromClass(PyType newtype, String name,
0983: Class c, Class base, boolean newstyle, Method setup,
0984: String[] exposed_methods) {
0985:
0986: if (base == null) {
0987: base = c.getSuperclass();
0988: }
0989: if (name == null) {
0990: name = c.getName();
0991: }
0992: if (name.startsWith("org.python.core.Py")) {
0993: name = name.substring("org.python.core.Py".length())
0994: .toLowerCase();
0995: } else {
0996: int lastdot = name.lastIndexOf('.');
0997: if (lastdot != -1) {
0998: name = name.substring(lastdot + 1);
0999: }
1000: }
1001: newtype.name = name;
1002: newtype.underlying_class = c;
1003: newtype.builtin = true;
1004: boolean top = false;
1005: // basic mro, base, bases
1006: PyType[] mro = null;
1007: if (base == Object.class) {
1008: mro = new PyType[] { newtype };
1009: top = true;
1010: } else {
1011: PyType basetype = fromClass(base);
1012: mro = new PyType[basetype.mro.length + 1];
1013: System.arraycopy(basetype.mro, 0, mro, 1,
1014: basetype.mro.length);
1015: mro[0] = newtype;
1016: newtype.base = basetype;
1017: newtype.bases = new PyObject[] { basetype };
1018: }
1019: newtype.mro = mro;
1020: PyObject dict = new PyStringMap();
1021: if (newstyle) {
1022: fillInNewstyle(newtype, setup, exposed_methods, dict);
1023: } else {
1024: fillInClassic(c, base, dict);
1025: }
1026: boolean has_set = false, has_delete = false;
1027: if (!top) {
1028: if (get_descr_method(c, "__set__", OO) != null || /* backw comp */
1029: get_descr_method(c, "_doset", OO) != null) {
1030: has_set = true;
1031: }
1032: if (get_descr_method(c, "__delete__", O) != null || /* backw comp */
1033: get_descr_method(c, "_dodel", O) != null) {
1034: has_delete = true;
1035: }
1036: }
1037: newtype.has_set = has_set;
1038: newtype.has_delete = has_delete;
1039: newtype.dict = dict;
1040: }
1041:
1042: private static void fillInClassic(Class c, Class base, PyObject dict) {
1043: HashMap propnames = new HashMap();
1044: Method[] methods = c.getMethods();
1045: for (int i = 0; i < methods.length; i++) {
1046: Method meth = methods[i];
1047: Class declaring = meth.getDeclaringClass();
1048: if (declaring != base && base.isAssignableFrom(declaring)
1049: && !ignore(meth)) {
1050: String methname = meth.getName();
1051: String nmethname = normalize_name(methname);
1052: PyReflectedFunction reflfunc = (PyReflectedFunction) dict
1053: .__finditem__(nmethname);
1054: boolean added = false;
1055: if (reflfunc == null) {
1056: dict.__setitem__(nmethname,
1057: new PyReflectedFunction(meth));
1058: added = true;
1059: } else {
1060: reflfunc.addMethod(meth);
1061: added = true;
1062: }
1063: if (added && !Modifier.isStatic(meth.getModifiers())) {
1064: // check for xxxX.*
1065: int n = meth.getParameterTypes().length;
1066: if (methname.startsWith("get") && n == 0) {
1067: propnames.put(methname.substring(3), "getter");
1068: } else if (methname.startsWith("is") && n == 0
1069: && meth.getReturnType() == Boolean.TYPE) {
1070: propnames.put(methname.substring(2), "getter");
1071: } else if (methname.startsWith("set") && n == 1) {
1072: propnames.put(methname.substring(3), meth);
1073: }
1074: }
1075: }
1076: }
1077: for (int i = 0; i < methods.length; i++) {
1078: Method meth = methods[i];
1079: String nmethname = normalize_name(meth.getName());
1080: PyReflectedFunction reflfunc = (PyReflectedFunction) dict
1081: .__finditem__(nmethname);
1082: if (reflfunc != null) {
1083: reflfunc.addMethod(meth);
1084: }
1085: }
1086: Field[] fields = c.getFields();
1087: for (int i = 0; i < fields.length; i++) {
1088: Field field = fields[i];
1089: Class declaring = field.getDeclaringClass();
1090: if (declaring != base && base.isAssignableFrom(declaring)) {
1091: String fldname = field.getName();
1092: int fldmods = field.getModifiers();
1093: Class fldtype = field.getType();
1094: if (Modifier.isStatic(fldmods)) {
1095: // ignore static PyClass __class__
1096: if (fldname.equals("__class__")
1097: && fldtype == PyClass.class) {
1098: continue;
1099: } else if (fldname.startsWith("__doc__")
1100: && fldname.length() > 7
1101: && fldtype == PyString.class) {
1102: String fname = fldname.substring(7).intern();
1103: PyObject memb = dict.__finditem__(fname);
1104: if (memb != null
1105: && memb instanceof PyReflectedFunction) {
1106: PyString doc = null;
1107: try {
1108: doc = (PyString) field.get(null);
1109: } catch (IllegalAccessException e) {
1110: throw error(e);
1111: }
1112: ((PyReflectedFunction) memb).__doc__ = doc;
1113: }
1114: }
1115: }
1116: dict.__setitem__(normalize_name(fldname),
1117: new PyReflectedField(field));
1118: }
1119: }
1120: for (Iterator iter = propnames.keySet().iterator(); iter
1121: .hasNext();) {
1122: String propname = (String) iter.next();
1123: String npropname = normalize_name(decapitalize(propname));
1124: PyObject prev = dict.__finditem__(npropname);
1125: if (prev != null && prev instanceof PyReflectedFunction) {
1126: continue;
1127: }
1128: Method getter = null;
1129: Method setter = null;
1130: Class proptype = null;
1131: getter = get_non_static_method(c, "get" + propname,
1132: new Class[] {});
1133: if (getter == null)
1134: getter = get_non_static_method(c, "is" + propname,
1135: new Class[] {});
1136: if (getter != null) {
1137: proptype = getter.getReturnType();
1138: setter = get_non_static_method(c, "set" + propname,
1139: new Class[] { proptype });
1140: } else {
1141: Object o = propnames.get(propname);
1142: if (o instanceof Method) {
1143: setter = (Method) o;
1144: proptype = setter.getParameterTypes()[0];
1145: }
1146: }
1147: if (setter != null || getter != null) {
1148: dict.__setitem__(npropname, new PyBeanProperty(
1149: npropname, proptype, getter, setter));
1150: } else {
1151: // xxx error
1152: }
1153: }
1154: Constructor[] ctrs = c.getConstructors();
1155: if (ctrs.length != 0) {
1156: final PyReflectedConstructor reflctr = new PyReflectedConstructor(
1157: "_new_impl");
1158: for (int i = 0; i < ctrs.length; i++) {
1159: reflctr.addConstructor(ctrs[i]);
1160: }
1161: PyObject new_ = new PyNewWrapper(c, "__new__", -1, -1) {
1162:
1163: public PyObject new_impl(boolean init, PyType subtype,
1164: PyObject[] args, String[] keywords) {
1165: return reflctr.make(args, keywords);
1166: }
1167: };
1168: dict.__setitem__("__new__", new_);
1169: }
1170: if (ClassDictInit.class.isAssignableFrom(c)
1171: && c != ClassDictInit.class) {
1172: try {
1173: Method m = c.getMethod("classDictInit",
1174: new Class[] { PyObject.class });
1175: m.invoke(null, new Object[] { dict });
1176: } catch (Exception exc) {
1177: throw error(exc);
1178: }
1179: }
1180: }
1181:
1182: private static void fillInNewstyle(PyType newtype, Method setup,
1183: String[] exposed_methods, PyObject dict) {
1184: for (int i = 0; i < exposed_methods.length; i++) {
1185: String methname = exposed_methods[i];
1186: dict.__setitem__(normalize_name(methname),
1187: new PyReflectedFunction(methname));
1188: }
1189: if (setup != null) {
1190: try {
1191: setup.invoke(null, new Object[] { dict, null });
1192: } catch (Exception e) {
1193: throw error(e);
1194: }
1195: }
1196: newtype.non_instantiable = dict.__finditem__("__new__") == null;
1197: }
1198:
1199: private static HashMap class_to_type;
1200:
1201: public static interface Newstyle {
1202: }
1203:
1204: private static PyType addFromClass(Class c) {
1205: Method setup = null;
1206: boolean newstyle = Newstyle.class.isAssignableFrom(c);
1207: Class base = null;
1208: String name = null;
1209: String[] exposed_methods = null;
1210: try {
1211: setup = c.getDeclaredMethod("typeSetup", new Class[] {
1212: PyObject.class, Newstyle.class });
1213: newstyle = true;
1214: } catch (NoSuchMethodException e) {
1215: } catch (Exception e) {
1216: throw error(e);
1217: }
1218: if (newstyle) { // newstyle
1219: base = (Class) exposed_decl_get_object(c, "base");
1220: name = (String) exposed_decl_get_object(c, "name");
1221: if (base == null) {
1222: Class cur = c;
1223: while (cur != PyObject.class) {
1224: Class exposed_as = (Class) exposed_decl_get_object(
1225: cur, "as");
1226: if (exposed_as != null) {
1227: PyType exposed_as_type = fromClass(exposed_as);
1228: class_to_type.put(c, exposed_as_type);
1229: return exposed_as_type;
1230: }
1231: cur = cur.getSuperclass();
1232: }
1233: }
1234: exposed_methods = (String[]) exposed_decl_get_object(c,
1235: "methods");
1236: if (exposed_methods == null)
1237: exposed_methods = EMPTY;
1238: }
1239: PyType newtype = (PyType) class_to_type.get(c);
1240: if (newtype == null) {
1241: newtype = c == PyType.class ? new PyType(true)
1242: : new PyType();
1243: class_to_type.put(c, newtype);
1244: fillFromClass(newtype, name, c, base, newstyle, setup,
1245: exposed_methods);
1246: }
1247: return newtype;
1248: }
1249:
1250: static PyType TypeType = fromClass(PyType.class);
1251:
1252: /*
1253: * considers:
1254: * if c implements Newstyle => c and all subclasses
1255: * are considered newstyle
1256: *
1257: * if c has static typeSetup(PyObject dict, Newstyle marker)
1258: * => c is considired newstyle, subclasses are not automatically;
1259: * typeSetup is invoked to populate dict which will become
1260: * type's __dict__
1261: *
1262: * Class exposed_base
1263: * String exposed_name
1264: *
1265: * Class exposed_as => instances are exposed as implementing
1266: * just this superclass
1267: *
1268: * (String[] exposed_methods)
1269: *
1270: */
1271:
1272: public static synchronized PyType fromClass(Class c) {
1273: if (class_to_type == null) {
1274: class_to_type = new HashMap();
1275: addFromClass(PyType.class);
1276: }
1277: PyType type = (PyType) class_to_type.get(c);
1278: if (type != null)
1279: return type;
1280: return addFromClass(c);
1281: }
1282:
1283: // name must be interned
1284: final PyObject type___findattr__(String name) {
1285: PyType metatype = getType();
1286:
1287: PyObject metaattr = metatype.lookup(name);
1288: PyObject res = null;
1289:
1290: if (metaattr != null) {
1291: if (metaattr.isDataDescr()) {
1292: res = metaattr.__get__(this , metatype);
1293: if (res != null)
1294: return res;
1295: }
1296: }
1297:
1298: PyObject attr = lookup(name);
1299:
1300: if (attr != null) {
1301: res = attr.__get__(null, this );
1302: if (res != null)
1303: return res;
1304: }
1305:
1306: if (metaattr != null) {
1307: return metaattr.__get__(this , metatype);
1308: }
1309:
1310: return null;
1311: }
1312:
1313: final void type___setattr__(String name, PyObject value) {
1314: super .__setattr__(name, value);
1315: if (name == "__set__") {
1316: if (!has_set && lookup("__set__") != null) {
1317: traverse_hierarchy(false, new OnType() {
1318: public boolean onType(PyType type) {
1319: boolean old = type.has_set;
1320: type.has_set = true;
1321: return old;
1322: }
1323: });
1324: }
1325: } else if (name == "__delete__") {
1326: if (!has_delete && lookup("__delete__") != null) {
1327: traverse_hierarchy(false, new OnType() {
1328: public boolean onType(PyType type) {
1329: boolean old = type.has_delete;
1330: type.has_delete = true;
1331: return old;
1332: }
1333: });
1334: }
1335: }
1336:
1337: }
1338:
1339: final void type___delattr__(String name) {
1340: super .__delattr__(name);
1341: if (name == "__set__") {
1342: if (has_set && lookup("__set__") == null) {
1343: traverse_hierarchy(false, new OnType() {
1344: public boolean onType(PyType type) {
1345: boolean absent = type.getDict().__finditem__(
1346: "__set__") == null;
1347: if (absent) {
1348: type.has_set = false;
1349: return false;
1350: }
1351: return true;
1352: }
1353: });
1354: }
1355: } else if (name == "__delete__") {
1356: if (has_set && lookup("__delete__") == null) {
1357: traverse_hierarchy(false, new OnType() {
1358: public boolean onType(PyType type) {
1359: boolean absent = type.getDict().__finditem__(
1360: "__delete__") == null;
1361: if (absent) {
1362: type.has_delete = false;
1363: return false;
1364: }
1365: return true;
1366: }
1367: });
1368: }
1369: }
1370: }
1371:
1372: protected void __rawdir__(PyDictionary accum) {
1373: PyObject[] mro = this .mro;
1374: for (int i = 0; i < mro.length; i++) {
1375: mro[i].addKeys(accum, "__dict__");
1376: }
1377: }
1378:
1379: /**
1380: * @see org.python.core.PyObject#fastGetDict()
1381: */
1382: public PyObject fastGetDict() {
1383: return dict;
1384: }
1385:
1386: public PyObject getDict() { // xxx return dict-proxy
1387: return dict;
1388: }
1389:
1390: public void setDict(PyObject newDict) {
1391: throw Py.TypeError("can't set attribute '__dict__' of type '"
1392: + name + "'");
1393: }
1394:
1395: public void delDict() {
1396: throw Py
1397: .TypeError("can't delete attribute '__dict__' of type '"
1398: + name + "'");
1399: }
1400:
1401: public Object __tojava__(Class c) {
1402: if (underlying_class != null
1403: && (c == Object.class || c == Class.class || c == Serializable.class)) {
1404: return underlying_class;
1405: }
1406: return super .__tojava__(c);
1407: }
1408:
1409: public PyObject getModule() {
1410: if (underlying_class != null)
1411: return new PyString("__builtin__");
1412: return dict.__finditem__("__module__");
1413: }
1414:
1415: public int getNumSlots() {
1416: return numSlots;
1417: }
1418:
1419: public String getFullName() {
1420: if (underlying_class != null)
1421: return name;
1422: PyObject mod = getModule();
1423: if (mod != null)
1424: return mod.__str__() + "." + name;
1425: return name;
1426: }
1427:
1428: public String toString() {
1429: if (underlying_class != null)
1430: return "<type '" + name + "'>";
1431: return "<class '" + getFullName() + "'>";
1432: }
1433:
1434: /**
1435: * @see org.python.core.PyObject#__findattr__(java.lang.String)
1436: */
1437: public PyObject __findattr__(String name) {
1438: return type___findattr__(name);
1439: }
1440:
1441: /**
1442: * @see org.python.core.PyObject#__delattr__(java.lang.String)
1443: */
1444: public void __delattr__(String name) {
1445: type___delattr__(name);
1446: }
1447:
1448: /**
1449: * @see org.python.core.PyObject#__setattr__(java.lang.String, org.python.core.PyObject)
1450: */
1451: public void __setattr__(String name, PyObject value) {
1452: type___setattr__(name, value);
1453: }
1454:
1455: /**
1456: * @see org.python.core.PyObject#safeRepr()
1457: */
1458: public String safeRepr() throws PyIgnoreMethodTag {
1459: return "type object '" + name + "'"; // xxx use fullname
1460: }
1461:
1462: private static PyObject invoke_new_(PyObject new_, PyType type,
1463: boolean init, PyObject[] args, String[] keywords) {
1464: PyObject newobj;
1465: if (new_ instanceof PyNewWrapper) {
1466: newobj = ((PyNewWrapper) new_).new_impl(init, type, args,
1467: keywords);
1468: } else {
1469: int n = args.length;
1470: PyObject[] type_prepended = new PyObject[n + 1];
1471: System.arraycopy(args, 0, type_prepended, 1, n);
1472: type_prepended[0] = type;
1473: newobj = new_.__get__(null, type).__call__(type_prepended,
1474: keywords);
1475: }
1476: /* special case type(x) */
1477: if (type == TypeType && args.length == 1
1478: && keywords.length == 0) {
1479: return newobj;
1480: }
1481: newobj.dispatch__init__(type, args, keywords);
1482: return newobj;
1483: }
1484:
1485: /**
1486: * @see org.python.core.PyObject#__call__(org.python.core.PyObject[], java.lang.String[])
1487: */
1488: public PyObject __call__(PyObject[] args, String[] keywords) {
1489: return type___call__(args, keywords);
1490: }
1491:
1492: final PyObject type___call__(PyObject[] args, String[] keywords) {
1493: PyObject new_ = lookup("__new__");
1494: if (non_instantiable || new_ == null) {
1495: throw Py
1496: .TypeError("cannot create '" + name + "' instances");
1497: // xxx fullname
1498: }
1499:
1500: return invoke_new_(new_, this , true, args, keywords);
1501: }
1502:
1503: //XXX: consider pulling this out into a generally accessible place
1504: // I bet this is duplicated more or less in other places.
1505: private static void confirmIdentifier(PyObject o) {
1506: String msg = "__slots__ must be identifiers";
1507: if (o == Py.None) {
1508: throw Py.TypeError(msg);
1509: }
1510: String identifier = o.toString();
1511: if (identifier == null
1512: || identifier.length() < 1
1513: || (!Character.isLetter(identifier.charAt(0)) && identifier
1514: .charAt(0) != '_')) {
1515: throw Py.TypeError(msg);
1516: }
1517: char[] chars = identifier.toCharArray();
1518: for (int i = 0; i < chars.length; i++) {
1519: if (!Character.isLetterOrDigit(chars[i]) && chars[i] != '_') {
1520: throw Py.TypeError(msg);
1521: }
1522: }
1523: }
1524:
1525: //XXX: copied from CodeCompiler.java and changed variable names.
1526: // Maybe this should go someplace for all classes to use.
1527: private static String mangleName(String classname, String methodname) {
1528: if (classname != null && methodname.startsWith("__")
1529: && !methodname.endsWith("__")) {
1530: //remove leading '_' from classname
1531: int i = 0;
1532: while (classname.charAt(i) == '_')
1533: i++;
1534: return ("_" + classname.substring(i) + methodname).intern();
1535: }
1536: return methodname;
1537: }
1538:
1539: }
|