Skip to content

Commit 91bcd98

Browse files
authored
✨ NEW: Transformer for removing dict and list keywords (#4)
1 parent be64a11 commit 91bcd98

File tree

5 files changed

+85
-7
lines changed

5 files changed

+85
-7
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ Currently, `aiida-upgrade` performs the following code refactoring:
3434

3535
* Look for deprecated `aiida-core` entry points loaded by plugin factories and add the `core.` prefix, see [the corresponding section in the plugin migration guide](https://github.com/aiidateam/aiida-core/wiki/AiiDA-2.0-plugin-migration-guide#entry-points).
3636
* Similarly, find and correct full deprecated entry point strings e.g. `'aiida.data:structure'`.
37+
* Remove `dict` and `list` keywords from the `Dict` and `List` node constructors, respectively.
38+
See [PR #5165 on `aiida-core`](https://github.com/aiidateam/aiida-core/pull/5165), which removed the requirement of using these keywords.
3739

3840
Migration steps that are not (yet) supported are:
3941

aiida_upgrade/methods.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# -*- coding: utf-8 -*-
2+
###########################################################################
3+
# Copyright (c), The AiiDA team. All rights reserved. #
4+
# This file is part of the AiiDA code. #
5+
# #
6+
# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core #
7+
# For further information on the license, see the LICENSE.txt file #
8+
# For further information please visit http://www.aiida.net #
9+
###########################################################################
10+
"""Transformers for upgrading AiiDA methods."""
11+
import libcst as cst
12+
from libcst import matchers
13+
14+
15+
class DictListNoKeywordTransformer(cst.CSTTransformer):
16+
"""Remove ``dict`` and ``list`` keywords from constructors of ``Dict`` and ``List`` nodes."""
17+
18+
dict_constructor = matchers.Name("Dict")
19+
list_constructor = matchers.Name("List")
20+
21+
dict_keyword = matchers.Name("dict")
22+
list_keyword = matchers.Name("list")
23+
24+
def leave_Call(self, original_node: cst.Call, updated_node: cst.Call) -> cst.Call:
25+
26+
if matchers.matches(
27+
original_node.func, self.dict_constructor | self.list_constructor
28+
):
29+
30+
# Empty `Dict` or `List` constructor
31+
if len(original_node.args) == 0:
32+
return original_node
33+
# `Dict` or `List` constructor without keyword
34+
elif original_node.args[0].keyword is None:
35+
return original_node
36+
# `Dict` or `List` constructor with `dict` or `list` keyword
37+
elif matchers.matches(
38+
original_node.args[0].keyword, self.dict_keyword | self.list_keyword
39+
):
40+
arguments = list(updated_node.args)
41+
arguments[0] = updated_node.args[0].with_changes(
42+
equal=cst.MaybeSentinel.DEFAULT, keyword=None
43+
)
44+
return updated_node.with_changes(args=arguments)
45+
46+
return original_node

aiida_upgrade/migrate.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import libcst as cst
44

55
from .entry_points import FactoryCoreTransformer, FullEntryPointTransformer
6+
from .methods import DictListNoKeywordTransformer
67

78

89
def migrate_path(path: Path):
@@ -16,11 +17,9 @@ def migrate_path(path: Path):
1617
with path.open("r") as handle:
1718
cst_tree = cst.parse_module(handle.read())
1819

19-
factory_transformer = FactoryCoreTransformer()
20-
cst_tree = cst_tree.visit(factory_transformer)
21-
22-
fullentry_transformer = FullEntryPointTransformer()
23-
cst_tree = cst_tree.visit(fullentry_transformer)
20+
cst_tree = cst_tree.visit(FactoryCoreTransformer())
21+
cst_tree = cst_tree.visit(FullEntryPointTransformer())
22+
cst_tree = cst_tree.visit(DictListNoKeywordTransformer())
2423

2524
with path.open("w") as handle:
2625
handle.write(cst_tree.code)

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ license = {file = "LICENSE"}
1010
classifiers = ["License :: OSI Approved :: MIT License"]
1111
dynamic = ["version", "description"]
1212
dependencies = [
13-
"click"
13+
"click",
14+
"libcst"
1415
]
1516

1617
[project.urls]
@@ -20,7 +21,7 @@ Home = "https://github.com/aiidateam/aiida-upgrade"
2021
aiida-upgrade = "aiida_upgrade.__main__:main"
2122

2223
[project.optional-dependencies]
23-
testing = [
24+
tests = [
2425
"pytest",
2526
]
2627

tests/test_methods.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# -*- coding: utf-8 -*-
2+
###########################################################################
3+
# Copyright (c), The AiiDA team. All rights reserved. #
4+
# This file is part of the AiiDA code. #
5+
# #
6+
# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core #
7+
# For further information on the license, see the LICENSE.txt file #
8+
# For further information please visit http://www.aiida.net #
9+
###########################################################################
10+
"""Tests for the transformers for upgrading AiiDA entry points."""
11+
import libcst as cst
12+
import pytest
13+
14+
15+
@pytest.mark.parametrize(
16+
("expression", "result"),
17+
(
18+
("Dict()", "Dict()"),
19+
("Dict(dict={'a': 1})", "Dict({'a': 1})"),
20+
("Dict(value={'a': 1})", "Dict(value={'a': 1})"),
21+
("List(list=[1, 2, 3])", "List([1, 2, 3])"),
22+
("List(value=[1, 2, 3])", "List(value=[1, 2, 3])"),
23+
),
24+
)
25+
def test_dict_list_no_keyword(expression, result):
26+
"""Test the ``DictListNoKeywordTransformer`` class."""
27+
from aiida_upgrade.methods import DictListNoKeywordTransformer
28+
29+
cst_tree = cst.parse_module(expression)
30+
assert cst_tree.visit(DictListNoKeywordTransformer()).code == result

0 commit comments

Comments
 (0)