Source: object.js

  1. /**
  2. * @constructor
  3. * Sk.builtin.object
  4. *
  5. * @description
  6. * Constructor for Python object. All Python classes (builtin and user-defined)
  7. * should inherit from this class.
  8. *
  9. * @return {Sk.builtin.object} Python object
  10. */
  11. Sk.builtin.object = function () {
  12. if (!(this instanceof Sk.builtin.object)) {
  13. return new Sk.builtin.object();
  14. }
  15. return this;
  16. };
  17. Sk.builtin.object.prototype.__init__ = function __init__() {
  18. return Sk.builtin.none.none$;
  19. };
  20. Sk.builtin.object.prototype.__init__.co_kwargs = 1;
  21. Sk.builtin._tryGetSubscript = function(dict, pyName) {
  22. try {
  23. return dict.mp$subscript(pyName);
  24. } catch (x) {
  25. return undefined;
  26. }
  27. };
  28. Sk.exportSymbol("Sk.builtin._tryGetSubscript", Sk.builtin._tryGetSubscript);
  29. /**
  30. * Get an attribute
  31. * @param {Object} pyName Python string name of the attribute
  32. * @param {boolean=} canSuspend Can we return a suspension?
  33. * @return {undefined}
  34. */
  35. Sk.builtin.object.prototype.GenericGetAttr = function (pyName, canSuspend) {
  36. var res;
  37. var f;
  38. var descr;
  39. var tp;
  40. var dict;
  41. var getf;
  42. var jsName = pyName.$jsstr();
  43. tp = this.ob$type;
  44. Sk.asserts.assert(tp !== undefined, "object has no ob$type!");
  45. dict = this["$d"] || this.constructor["$d"];
  46. //print("getattr", tp.tp$name, name);
  47. // todo; assert? force?
  48. if (dict) {
  49. if (dict.mp$lookup) {
  50. res = dict.mp$lookup(pyName);
  51. } else if (dict.mp$subscript) {
  52. res = Sk.builtin._tryGetSubscript(dict, pyName);
  53. } else if (typeof dict === "object") {
  54. res = dict[jsName];
  55. }
  56. if (res !== undefined) {
  57. return res;
  58. }
  59. }
  60. descr = Sk.builtin.type.typeLookup(tp, pyName);
  61. // otherwise, look in the type for a descr
  62. if (descr !== undefined && descr !== null) {
  63. f = descr.tp$descr_get;
  64. // todo - data descriptors (ie those with tp$descr_set too) get a different lookup priority
  65. if (f) {
  66. // non-data descriptor
  67. return f.call(descr, this, this.ob$type, canSuspend);
  68. }
  69. }
  70. if (descr !== undefined) {
  71. return descr;
  72. }
  73. // OK, try __getattr__
  74. descr = Sk.builtin.type.typeLookup(tp, Sk.builtin.str.$getattr);
  75. if (descr !== undefined && descr !== null) {
  76. f = descr.tp$descr_get;
  77. if (f) {
  78. getf = f.call(descr, this, this.ob$type);
  79. } else {
  80. getf = descr;
  81. }
  82. res = Sk.misceval.tryCatch(function() {
  83. return Sk.misceval.callsimOrSuspendArray(getf, [pyName]);
  84. }, function(e) {
  85. if (e instanceof Sk.builtin.AttributeError) {
  86. return undefined;
  87. } else {
  88. throw e;
  89. }
  90. });
  91. return canSuspend ? res : Sk.misceval.retryOptionalSuspensionOrThrow(res);
  92. }
  93. return undefined;
  94. };
  95. Sk.exportSymbol("Sk.builtin.object.prototype.GenericGetAttr", Sk.builtin.object.prototype.GenericGetAttr);
  96. Sk.builtin.object.prototype.GenericPythonGetAttr = function(self, pyName) {
  97. var r = Sk.builtin.object.prototype.GenericGetAttr.call(self, pyName, true);
  98. if (r === undefined) {
  99. throw new Sk.builtin.AttributeError(pyName);
  100. }
  101. return r;
  102. };
  103. Sk.exportSymbol("Sk.builtin.object.prototype.GenericPythonGetAttr", Sk.builtin.object.prototype.GenericPythonGetAttr);
  104. /**
  105. * @param {Object} pyName
  106. * @param {Object} value
  107. * @param {boolean=} canSuspend
  108. * @return {undefined}
  109. */
  110. Sk.builtin.object.prototype.GenericSetAttr = function (pyName, value, canSuspend) {
  111. var objname = Sk.abstr.typeName(this);
  112. var jsName = pyName.$jsstr();
  113. var dict;
  114. var tp = this.ob$type;
  115. var descr;
  116. var f;
  117. Sk.asserts.assert(tp !== undefined, "object has no ob$type!");
  118. dict = this["$d"] || this.constructor["$d"];
  119. if (jsName == "__class__") {
  120. if (value.tp$mro === undefined || value.tp$name === undefined) {
  121. throw new Sk.builtin.TypeError(
  122. "attempted to assign non-class to __class__");
  123. }
  124. this.ob$type = value;
  125. this.tp$name = value.tp$name;
  126. return;
  127. }
  128. descr = Sk.builtin.type.typeLookup(tp, pyName);
  129. // otherwise, look in the type for a descr
  130. if (descr !== undefined && descr !== null) {
  131. f = descr.tp$descr_set;
  132. // todo; is this the right lookup priority for data descriptors?
  133. if (f) {
  134. return f.call(descr, this, value, canSuspend);
  135. }
  136. }
  137. if (dict.mp$ass_subscript) {
  138. if (this instanceof Sk.builtin.object && !(this.ob$type.sk$klass) &&
  139. dict.mp$lookup(pyName) === undefined) {
  140. // Cannot add new attributes to a builtin object
  141. throw new Sk.builtin.AttributeError("'" + objname + "' object has no attribute '" + Sk.unfixReserved(jsName) + "'");
  142. }
  143. dict.mp$ass_subscript(pyName, value);
  144. } else if (typeof dict === "object") {
  145. dict[jsName] = value;
  146. }
  147. };
  148. Sk.exportSymbol("Sk.builtin.object.prototype.GenericSetAttr", Sk.builtin.object.prototype.GenericSetAttr);
  149. Sk.builtin.object.prototype.GenericPythonSetAttr = function(self, pyName, value) {
  150. return Sk.builtin.object.prototype.GenericSetAttr.call(self, pyName, value, true);
  151. };
  152. Sk.exportSymbol("Sk.builtin.object.prototype.GenericPythonSetAttr", Sk.builtin.object.prototype.GenericPythonSetAttr);
  153. Sk.builtin.object.prototype.HashNotImplemented = function () {
  154. throw new Sk.builtin.TypeError("unhashable type: '" + Sk.abstr.typeName(this) + "'");
  155. };
  156. Sk.builtin.object.prototype.tp$getattr = Sk.builtin.object.prototype.GenericGetAttr;
  157. Sk.builtin.object.prototype.tp$setattr = Sk.builtin.object.prototype.GenericSetAttr;
  158. // Although actual attribute-getting happens in pure Javascript via tp$getattr, classes
  159. // overriding __getattribute__ etc need to be able to call object.__getattribute__ etc from Python
  160. Sk.builtin.object.prototype["__getattribute__"] = Sk.builtin.object.prototype.GenericPythonGetAttr;
  161. Sk.builtin.object.prototype["__setattr__"] = Sk.builtin.object.prototype.GenericPythonSetAttr;
  162. /**
  163. * The name of this class.
  164. * @type {string}
  165. */
  166. Sk.builtin.object.prototype.tp$name = "object";
  167. /**
  168. * The type object of this class.
  169. * @type {Sk.builtin.type|Object}
  170. */
  171. Sk.builtin.object.prototype.ob$type = Sk.builtin.type.makeIntoTypeObj("object", Sk.builtin.object);
  172. Sk.builtin.object.prototype.ob$type.sk$klass = undefined; // Nonsense for closure compiler
  173. Sk.builtin.object.prototype.tp$descr_set = undefined; // Nonsense for closure compiler
  174. /** Default implementations of dunder methods found in all Python objects */
  175. /**
  176. * Default implementation of __new__ just calls the class constructor
  177. * @name __new__
  178. * @memberOf Sk.builtin.object.prototype
  179. * @instance
  180. */
  181. Sk.builtin.object.prototype["__new__"] = function (cls) {
  182. Sk.builtin.pyCheckArgsLen("__new__", arguments.length, 1, 1, false, false);
  183. return new cls([], []);
  184. };
  185. /**
  186. * Python wrapper for `__repr__` method.
  187. * @name __repr__
  188. * @memberOf Sk.builtin.object.prototype
  189. * @instance
  190. */
  191. Sk.builtin.object.prototype["__repr__"] = function (self) {
  192. Sk.builtin.pyCheckArgsLen("__repr__", arguments.length, 0, 0, false, true);
  193. return self["$r"]();
  194. };
  195. Sk.builtin.object.prototype["__format__"] = function (self, format_spec) {
  196. var formatstr;
  197. Sk.builtin.pyCheckArgsLen("__format__", arguments.length, 2, 2);
  198. if (!Sk.builtin.checkString(format_spec)) {
  199. if (Sk.__future__.exceptions) {
  200. throw new Sk.builtin.TypeError("format() argument 2 must be str, not " + Sk.abstr.typeName(format_spec));
  201. } else {
  202. throw new Sk.builtin.TypeError("format expects arg 2 to be string or unicode, not " + Sk.abstr.typeName(format_spec));
  203. }
  204. } else {
  205. formatstr = Sk.ffi.remapToJs(format_spec);
  206. if (formatstr !== "") {
  207. throw new Sk.builtin.NotImplementedError("format spec is not yet implemented");
  208. }
  209. }
  210. return new Sk.builtin.str(self);
  211. };
  212. /**
  213. * Python wrapper for `__str__` method.
  214. * @name __str__
  215. * @memberOf Sk.builtin.object.prototype
  216. * @instance
  217. */
  218. Sk.builtin.object.prototype["__str__"] = function (self) {
  219. Sk.builtin.pyCheckArgsLen("__str__", arguments.length, 0, 0, false, true);
  220. return self["$r"]();
  221. };
  222. /**
  223. * Python wrapper for `__hash__` method.
  224. * @name __hash__
  225. * @memberOf Sk.builtin.object.prototype
  226. * @instance
  227. */
  228. Sk.builtin.object.prototype["__hash__"] = function (self) {
  229. Sk.builtin.pyCheckArgsLen("__hash__", arguments.length, 0, 0, false, true);
  230. return self.tp$hash();
  231. };
  232. /**
  233. * Python wrapper for `__eq__` method.
  234. * @name __eq__
  235. * @memberOf Sk.builtin.object.prototype
  236. * @instance
  237. */
  238. Sk.builtin.object.prototype["__eq__"] = function (self, other) {
  239. Sk.builtin.pyCheckArgsLen("__eq__", arguments.length, 1, 1, false, true);
  240. return self.ob$eq(other);
  241. };
  242. /**
  243. * Python wrapper for `__ne__` method.
  244. * @name __ne__
  245. * @memberOf Sk.builtin.object.prototype
  246. * @instance
  247. */
  248. Sk.builtin.object.prototype["__ne__"] = function (self, other) {
  249. Sk.builtin.pyCheckArgsLen("__ne__", arguments.length, 1, 1, false, true);
  250. return self.ob$ne(other);
  251. };
  252. /**
  253. * Python wrapper for `__lt__` method.
  254. * @name __lt__
  255. * @memberOf Sk.builtin.object.prototype
  256. * @instance
  257. */
  258. Sk.builtin.object.prototype["__lt__"] = function (self, other) {
  259. Sk.builtin.pyCheckArgsLen("__lt__", arguments.length, 1, 1, false, true);
  260. return self.ob$lt(other);
  261. };
  262. /**
  263. * Python wrapper for `__le__` method.
  264. * @name __le__
  265. * @memberOf Sk.builtin.object.prototype
  266. * @instance
  267. */
  268. Sk.builtin.object.prototype["__le__"] = function (self, other) {
  269. Sk.builtin.pyCheckArgsLen("__le__", arguments.length, 1, 1, false, true);
  270. return self.ob$le(other);
  271. };
  272. /**
  273. * Python wrapper for `__gt__` method.
  274. * @name __gt__
  275. * @memberOf Sk.builtin.object.prototype
  276. * @instance
  277. */
  278. Sk.builtin.object.prototype["__gt__"] = function (self, other) {
  279. Sk.builtin.pyCheckArgsLen("__gt__", arguments.length, 1, 1, false, true);
  280. return self.ob$gt(other);
  281. };
  282. /**
  283. * Python wrapper for `__ge__` method.
  284. * @name __ge__
  285. * @memberOf Sk.builtin.object.prototype
  286. * @instance
  287. */
  288. Sk.builtin.object.prototype["__ge__"] = function (self, other) {
  289. Sk.builtin.pyCheckArgsLen("__ge__", arguments.length, 1, 1, false, true);
  290. return self.ob$ge(other);
  291. };
  292. /** Default implementations of Javascript functions used in dunder methods */
  293. /**
  294. * Return the string representation of this instance.
  295. *
  296. * Javascript function, returns Python object.
  297. *
  298. * @name $r
  299. * @memberOf Sk.builtin.object.prototype
  300. * @return {Sk.builtin.str} The Python string representation of this instance.
  301. */
  302. Sk.builtin.object.prototype["$r"] = function () {
  303. return new Sk.builtin.str("<object>");
  304. };
  305. Sk.builtin.hashCount = 1;
  306. Sk.builtin.idCount = 1;
  307. /**
  308. * Return the hash value of this instance.
  309. *
  310. * Javascript function, returns Python object.
  311. *
  312. * @return {Sk.builtin.int_} The hash value
  313. */
  314. Sk.builtin.object.prototype.tp$hash = function () {
  315. if (!this.$savedHash_) {
  316. this.$savedHash_ = new Sk.builtin.int_(Sk.builtin.hashCount++);
  317. }
  318. return this.$savedHash_;
  319. };
  320. /**
  321. * Perform equality check between this instance and a Python object (i.e. this == other).
  322. *
  323. * Implements `__eq__` dunder method.
  324. *
  325. * Javascript function, returns Python object.
  326. *
  327. * @param {Object} other The Python object to check for equality.
  328. * @return {(Sk.builtin.bool|Sk.builtin.NotImplemented)} true if equal, false otherwise
  329. */
  330. Sk.builtin.object.prototype.ob$eq = function (other) {
  331. if (this === other) {
  332. return Sk.builtin.bool.true$;
  333. }
  334. return Sk.builtin.NotImplemented.NotImplemented$;
  335. };
  336. /**
  337. * Perform non-equality check between this instance and a Python object (i.e. this != other).
  338. *
  339. * Implements `__ne__` dunder method.
  340. *
  341. * Javascript function, returns Python object.
  342. *
  343. * @param {Object} other The Python object to check for non-equality.
  344. * @return {(Sk.builtin.bool|Sk.builtin.NotImplemented)} true if not equal, false otherwise
  345. */
  346. Sk.builtin.object.prototype.ob$ne = function (other) {
  347. if (this === other) {
  348. return Sk.builtin.bool.false$;
  349. }
  350. return Sk.builtin.NotImplemented.NotImplemented$;
  351. };
  352. /**
  353. * Determine if this instance is less than a Python object (i.e. this < other).
  354. *
  355. * Implements `__lt__` dunder method.
  356. *
  357. * Javascript function, returns Python object.
  358. *
  359. * @param {Object} other The Python object to compare.
  360. * @return {(Sk.builtin.bool|Sk.builtin.NotImplemented)} true if this < other, false otherwise
  361. */
  362. Sk.builtin.object.prototype.ob$lt = function (other) {
  363. return Sk.builtin.NotImplemented.NotImplemented$;
  364. };
  365. /**
  366. * Determine if this instance is less than or equal to a Python object (i.e. this <= other).
  367. *
  368. * Implements `__le__` dunder method.
  369. *
  370. * Javascript function, returns Python object.
  371. *
  372. * @param {Object} other The Python object to compare.
  373. * @return {(Sk.builtin.bool|Sk.builtin.NotImplemented)} true if this <= other, false otherwise
  374. */
  375. Sk.builtin.object.prototype.ob$le = function (other) {
  376. return Sk.builtin.NotImplemented.NotImplemented$;
  377. };
  378. /**
  379. * Determine if this instance is greater than a Python object (i.e. this > other).
  380. *
  381. * Implements `__gt__` dunder method.
  382. *
  383. * Javascript function, returns Python object.
  384. *
  385. * @param {Object} other The Python object to compare.
  386. * @return {(Sk.builtin.bool|Sk.builtin.NotImplemented)} true if this > other, false otherwise
  387. */
  388. Sk.builtin.object.prototype.ob$gt = function (other) {
  389. return Sk.builtin.NotImplemented.NotImplemented$;
  390. };
  391. /**
  392. * Determine if this instance is greater than or equal to a Python object (i.e. this >= other).
  393. *
  394. * Implements `__ge__` dunder method.
  395. *
  396. * Javascript function, returns Python object.
  397. *
  398. * @param {Object} other The Python object to compare.
  399. * @return {(Sk.builtin.bool|Sk.builtin.NotImplemented)} true if this >= other, false otherwise
  400. */
  401. Sk.builtin.object.prototype.ob$ge = function (other) {
  402. return Sk.builtin.NotImplemented.NotImplemented$;
  403. };
  404. // Wrap the following functions in Sk.builtin.func once that class is initialized
  405. /**
  406. * Array of all the Python functions which are methods of this class.
  407. * @type {Array}
  408. */
  409. Sk.builtin.object.pythonFunctions = [
  410. "__repr__", "__str__", "__hash__",
  411. "__eq__", "__ne__", "__lt__", "__le__",
  412. "__gt__", "__ge__", "__getattribute__",
  413. "__setattr__", "__format__"
  414. ];
  415. /**
  416. * @constructor
  417. * Sk.builtin.none
  418. *
  419. * @extends {Sk.builtin.object}
  420. */
  421. Sk.builtin.none = function () {
  422. this.v = null;
  423. };
  424. Sk.abstr.setUpInheritance("NoneType", Sk.builtin.none, Sk.builtin.object);
  425. /** @override */
  426. Sk.builtin.none.prototype["$r"] = function () { return new Sk.builtin.str("None"); };
  427. /** @override */
  428. Sk.builtin.none.prototype.tp$hash = function () {
  429. return new Sk.builtin.int_(0);
  430. };
  431. /**
  432. * Python None constant.
  433. * @type {Sk.builtin.none}
  434. */
  435. Sk.builtin.none.none$ = new Sk.builtin.none();
  436. /**
  437. * @constructor
  438. * Sk.builtin.NotImplemented
  439. *
  440. * @extends {Sk.builtin.object}
  441. */
  442. Sk.builtin.NotImplemented = function() { };
  443. Sk.abstr.setUpInheritance("NotImplementedType", Sk.builtin.NotImplemented, Sk.builtin.object);
  444. /** @override */
  445. Sk.builtin.NotImplemented.prototype["$r"] = function () { return new Sk.builtin.str("NotImplemented"); };
  446. /**
  447. * Python NotImplemented constant.
  448. * @type {Sk.builtin.NotImplemented}
  449. */
  450. Sk.builtin.NotImplemented.NotImplemented$ = new Sk.builtin.NotImplemented();
  451. Sk.exportSymbol("Sk.builtin.none", Sk.builtin.none);
  452. Sk.exportSymbol("Sk.builtin.NotImplemented", Sk.builtin.NotImplemented);