Add metaclass support, support PEP 3115 and PEP 487

This commit is contained in:
Simon Gomizelj 2018-02-11 18:26:29 -05:00 committed by Kodi Arfer
parent 75af667fa1
commit c663d38e33
5 changed files with 43 additions and 2 deletions

View File

@ -19,6 +19,8 @@ Other Breaking Changes
New Features
------------------------------
* Added `mangle` and `unmangle` as core functions
* `defclass` in Python 3 now supports specifying metaclasses and other
keyword arguments
Bug Fixes
------------------------------

View File

@ -2057,11 +2057,12 @@ class HyASTCompiler(object):
bases_expr = []
bases = Result()
keywords = []
if expressions:
base_list = expressions.pop(0)
if not isinstance(base_list, HyList):
raise HyTypeError(base_list, "Base classes must be a list.")
bases_expr, bases, _ = self._compile_collect(base_list)
bases_expr, bases, keywords = self._compile_collect(base_list, with_kwargs=PY3)
body = Result()
@ -2092,7 +2093,7 @@ class HyASTCompiler(object):
expressions,
decorator_list=[],
name=ast_str(class_name),
keywords=[],
keywords=keywords,
starargs=None,
kwargs=None,
bases=bases_expr,

View File

@ -214,6 +214,13 @@ def test_ast_good_defclass():
can_compile("(defclass a [])")
@pytest.mark.skipif(not PY3, reason="Python 3 supports class keywords")
def test_ast_good_defclass_with_metaclass():
"Make sure AST can compile valid defclass with keywords"
can_compile("(defclass a [:metaclass b])")
can_compile("(defclass a [:b c])")
def test_ast_bad_defclass():
"Make sure AST can't compile invalid defclass"
cant_compile("(defclass)")

View File

@ -37,3 +37,11 @@
(setv x (+ x a))
(else (setv x (+ x 50))))
(assert (= x 53)))))
(defn test-pep-487 []
(defclass QuestBase []
[--init-subclass-- (fn [cls swallow &kwargs kwargs]
(setv cls.swallow swallow))])
(defclass Quest [QuestBase :swallow "african"])
(assert (= (. (Quest) swallow) "african")))

View File

@ -84,3 +84,26 @@
(assert (= (foo :b 20 :a 10 :c 30)
(, 10 20 30)))))
(defn test-pep-3115 []
(defclass member-table [dict]
[--init-- (fn [self] (setv self.member-names []))
--setitem-- (fn [self key value]
(if (not-in key self)
(.append self.member-names key))
(dict.--setitem-- self key value))])
(defclass OrderedClass [type]
[--prepare-- (classmethod (fn [metacls name bases] (member-table)))
--new-- (fn [cls name bases classdict]
(setv result (type.--new-- cls name bases (dict classdict)))
(setv result.member-names classdict.member-names)
result)])
(defclass MyClass [:metaclass OrderedClass]
[method1 (fn [self] (pass))
method2 (fn [self] (pass))])
(assert (= (. (MyClass) member-names)
["__module__" "__qualname__" "method1" "method2"])))