From b21b1c5158b4ef2c7fa621501399d4a39aad27bc Mon Sep 17 00:00:00 2001 From: Martin Jambon Date: Thu, 24 Mar 2022 22:43:45 -0700 Subject: [PATCH 1/5] Best effort to deduplicate the @dataclass decorator --- atdpy.opam | 1 + atdpy/src/lib/Codegen.ml | 18 ++++++++++++++---- atdpy/src/lib/dune | 1 + dune-project | 1 + 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/atdpy.opam b/atdpy.opam index 9411514c..5be386ad 100644 --- a/atdpy.opam +++ b/atdpy.opam @@ -66,6 +66,7 @@ depends: [ "atd" {>= "2.3.0"} "atdgen" {>= "2.3.0"} "cmdliner" {>= "1.1.0"} + "re" "alcotest" {with-test} "conf-python-3" {with-test} "odoc" {with-doc} diff --git a/atdpy/src/lib/Codegen.ml b/atdpy/src/lib/Codegen.ml index e7dd9988..ed834d95 100644 --- a/atdpy/src/lib/Codegen.ml +++ b/atdpy/src/lib/Codegen.ml @@ -847,7 +847,6 @@ let record env ~class_decorators loc name (fields : field list) an = in [ Inline class_decorators; - Line "@dataclass"; Line (sprintf "class %s:" py_class_name); Block (spaced [ Line (sprintf {|"""Original type: %s = { ... }"""|} name); @@ -880,7 +879,6 @@ let alias_wrapper env ~class_decorators name type_expr = let value_type = type_name_of_expr env type_expr in [ Inline class_decorators; - Line "@dataclass"; Line (sprintf "class %s:" py_class_name); Block [ Line (sprintf {|"""Original type: %s"""|} name); @@ -1058,7 +1056,6 @@ let sum_container env ~class_decorators loc name cases = in [ Inline class_decorators; - Line "@dataclass"; Line (sprintf "class %s:" py_class_name); Block [ Line (sprintf {|"""Original type: %s = [ ... ]"""|} name); @@ -1122,11 +1119,24 @@ let sum env ~class_decorators loc name cases = ] |> double_spaced +let uses_dataclass_decorator = + let rex = Re.Pcre.regexp "\\A[ \t\r\n]*dataclass(\\(|[ \t\r\n]|\\z)" in + fun s -> Re.Pcre.pmatch ~rex s + +let get_class_decorators an = + let decorators = Python_annot.get_python_decorators an in + (* Avoid duplicate use of the @dataclass decorator, which doesn't work + if some options like frozen=True are used. *) + if List.exists uses_dataclass_decorator decorators then + decorators + else + decorators @ ["dataclass"] + let type_def env ((loc, (name, param, an), e) : A.type_def) : B.t = if param <> [] then not_implemented loc "parametrized type"; let class_decorators = - Python_annot.get_python_decorators an + get_class_decorators an |> List.map (fun s -> Line ("@" ^ s)) in let rec unwrap e = diff --git a/atdpy/src/lib/dune b/atdpy/src/lib/dune index 60be53e3..324e4a5d 100644 --- a/atdpy/src/lib/dune +++ b/atdpy/src/lib/dune @@ -1,6 +1,7 @@ (library (name atdpy) (libraries + re atd atdgen_emit ) diff --git a/dune-project b/dune-project index dd26c6b5..177d8117 100644 --- a/dune-project +++ b/dune-project @@ -166,6 +166,7 @@ automatically handled") (atd (>= 2.3.0)) (atdgen (>= 2.3.0)) (cmdliner (>= 1.1.0)) + re (alcotest :with-test) (conf-python-3 :with-test) (odoc :with-doc))) From c923f0fca22be907de2f6a7320e4d557cc31e015 Mon Sep 17 00:00:00 2001 From: Martin Jambon Date: Thu, 24 Mar 2022 22:45:12 -0700 Subject: [PATCH 2/5] Accept new test output --- atdpy/test/python-expected/everything.py | 1 - 1 file changed, 1 deletion(-) diff --git a/atdpy/test/python-expected/everything.py b/atdpy/test/python-expected/everything.py index c3c1dc13..c82ad381 100644 --- a/atdpy/test/python-expected/everything.py +++ b/atdpy/test/python-expected/everything.py @@ -441,7 +441,6 @@ def to_json_string(self, **kw: Any) -> str: @deco.deco1 @deco.deco2(42) @dataclass(order=True) -@dataclass class RequireField: """Original type: require_field = { ... }""" From 800d64f096d2cd088877d07b5b5d30bc78246a53 Mon Sep 17 00:00:00 2001 From: Martin Jambon Date: Thu, 24 Mar 2022 22:58:07 -0700 Subject: [PATCH 3/5] Update changelog --- CHANGES.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 35b92108..03822e00 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,10 @@ +Next +----------------- + +* atdpy: don't apply the `@dataclass` decorator twice if explicitly + added by the user via an ATD annotation such as + ``. + 2.4.0 (2022-03-24) ----------------- From db9acc245688d079620a0de146b8cc1e2f51e750 Mon Sep 17 00:00:00 2001 From: Martin Jambon Date: Thu, 24 Mar 2022 22:59:38 -0700 Subject: [PATCH 4/5] Add PR reference to changelog --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 03822e00..862bb47d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,7 +3,7 @@ Next * atdpy: don't apply the `@dataclass` decorator twice if explicitly added by the user via an ATD annotation such as - ``. + `` (#267) 2.4.0 (2022-03-24) ----------------- From 59e8322ea58b56b563dba529472726dcd68d65b8 Mon Sep 17 00:00:00 2001 From: Martin Jambon Date: Fri, 25 Mar 2022 12:25:51 -0700 Subject: [PATCH 5/5] Update atdpy/src/lib/Codegen.ml Co-authored-by: Louis --- atdpy/src/lib/Codegen.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atdpy/src/lib/Codegen.ml b/atdpy/src/lib/Codegen.ml index ed834d95..a4077806 100644 --- a/atdpy/src/lib/Codegen.ml +++ b/atdpy/src/lib/Codegen.ml @@ -1120,7 +1120,7 @@ let sum env ~class_decorators loc name cases = |> double_spaced let uses_dataclass_decorator = - let rex = Re.Pcre.regexp "\\A[ \t\r\n]*dataclass(\\(|[ \t\r\n]|\\z)" in + let rex = Re.Pcre.regexp {|\A[ \t\r\n]*dataclass(\(|[ \t\r\n]|\z)|} in fun s -> Re.Pcre.pmatch ~rex s let get_class_decorators an =