Skip to content

Commit

Permalink
Fix Django plugin and corresponding tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Sebastian Simon committed Sep 23, 2024
1 parent 90f0bb4 commit e7ad256
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 59 deletions.
77 changes: 21 additions & 56 deletions src/cfgnet/plugins/concept/django_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.
import ast
import logging
from typing import Optional
from cfgnet.plugins.plugin import Plugin
from cfgnet.network.nodes import (
Expand Down Expand Up @@ -63,65 +62,41 @@ def _parse_config_file(

settings = {}

for node in ast.walk(tree):
for node in ast.iter_child_nodes(tree):
if isinstance(node, ast.Assign):
if len(node.targets) == 1 and isinstance(
node.targets[0], ast.Name
):
key = node.targets[0]
settings[key] = node.value

if isinstance(node, ast.AnnAssign):
if (
isinstance(node.target, ast.Name)
and node.value is not None
):
key = node.target
settings[key] = node.value

for key, value in settings.items():
if isinstance(value, ast.Constant):
self.__parse_constant(artifact, key, value)
elif isinstance(value, ast.Name):
dict_id = value.id
match = next(
filter(lambda x: x.id == dict_id, settings.keys())
)
item = settings[match]
if isinstance(item, ast.List):
self.__parse_list(artifact, key, item)
else:
logging.warning(
'Failed to parse ast type "%s".', type(value)
)
elif isinstance(value, ast.BinOp):
self.__parse_operation(artifact, key, value)
elif isinstance(value, ast.List):
self.__parse_list(artifact, key, value)
elif isinstance(value, ast.Dict):
if not key.id.isupper():
continue
if isinstance(value, ast.Dict):
self.__parse_dict(artifact, key, value)
else:
logging.warning('Failed to parse ast type "%s".', type(value))
self.__parse(artifact, key, value)

return artifact

def __parse_constant(self, parent, key, value) -> None:
config_type = self.get_config_type(option_name=key.id)
option_node = OptionNode(
name=key.id, location=key.lineno, config_type=config_type
)
parent.add_child(option_node)
value_node = ValueNode(name=ast.literal_eval(value))
option_node.add_child(value_node)

def __parse_operation(self, parent, key, value) -> None:
config_type = self.get_config_type(option_name=key.id)
def __parse(self, parent, key, value) -> None:
config_type = self.get_config_type(option_name=ast.unparse(key))
option_node = OptionNode(
name=key.id, location=key.lineno, config_type=config_type
name=ast.unparse(key).replace("'", ""),
location=key.lineno,
config_type=config_type,
)
parent.add_child(option_node)
value_node = ValueNode(name=ast.unparse(value))
option_node.add_child(value_node)

def __parse_list(self, parent, key, value) -> None:
config_type = self.get_config_type(option_name=key.id)
option_node = OptionNode(
name=key.id, location=key.lineno, config_type=config_type
)
parent.add_child(option_node)
value_node = ValueNode(name=ast.unparse(value))
value_node = ValueNode(name=ast.unparse(value).replace("'", ""))
option_node.add_child(value_node)

def __parse_dict(self, parent, key, value) -> None:
Expand All @@ -135,18 +110,8 @@ def __parse_dict(self, parent, key, value) -> None:
for option, option_value in zip(value.keys, value.values):
if isinstance(option_value, ast.Dict):
self.__parse_dict(option_node, option, option_value)
if isinstance(option_value, ast.Constant):
config_type = self.get_config_type(
option_name=ast.literal_eval(option)
)
sub_option_node = OptionNode(
name=ast.literal_eval(option),
location=key.lineno,
config_type=config_type,
)
option_node.add_child(sub_option_node)
value_node = ValueNode(name=ast.literal_eval(option_value))
sub_option_node.add_child(value_node)
else:
self.__parse(option_node, option, option_value)

# pylint: disable=too-many-return-statements
def get_config_type(self, option_name: str) -> ConfigType: # noqa: C901
Expand Down
4 changes: 1 addition & 3 deletions tests/cfgnet/plugins/concept/test_django_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def test_parse_django_file(get_plugin):
assert make_id("settings.py", "LANGUAGE_CODE", "en-us") in ids
assert make_id("settings.py", "STORAGES", "default", "BACKEND", "django.core.files.storage.FileSystemStorage") in ids
assert make_id("settings.py", "STORAGES", "staticfiles", "BACKEND", "django.contrib.staticfiles.storage.StaticFilesStorage") in ids
assert make_id("settings.py", "FILE_UPLOAD_HANDLERS", "['django.core.files.uploadhandler.MemoryFileUploadHandler', 'django.core.files.uploadhandler.TemporaryFileUploadHandler']") in ids
assert make_id("settings.py", "FILE_UPLOAD_HANDLERS", "[django.core.files.uploadhandler.MemoryFileUploadHandler, django.core.files.uploadhandler.TemporaryFileUploadHandler]") in ids
assert make_id("settings.py", "FILE_UPLOAD_MAX_MEMORY_SIZE", "2621440") in ids
assert make_id("settings.py", "FILE_UPLOAD_DIRECTORY_PERMISSIONS", "None") in ids
assert make_id("settings.py", "DATE_FORMAT", "N j, Y") in ids
Expand All @@ -78,13 +78,11 @@ def test_django_config_types(get_plugin):
language_node = next(filter(lambda x: x.id == make_id("settings.py", "LANGUAGE_CODE", "en-us"), nodes))
url_node = next(filter(lambda x: x.id == make_id("settings.py", "LOGIN_URL", "/accounts/login/"), nodes))
size_node = next(filter(lambda x: x.id == make_id("settings.py", "FILE_UPLOAD_MAX_MEMORY_SIZE", "2621440"), nodes))
class_node = next(filter(lambda x: x.id == make_id("settings.py", "STORAGES", "default", "BACKEND", "django.core.files.storage.FileSystemStorage"), nodes))
pattern_node = next(filter(lambda x: x.id == make_id("settings.py", "DATE_FORMAT", "N j, Y"), nodes))
boolean_node = next(filter(lambda x: x.id == make_id("settings.py", "DEBUG", "False"), nodes))

assert url_node.config_type == ConfigType.URL
assert language_node.config_type == ConfigType.LANGUAGE
assert size_node.config_type == ConfigType.SIZE
assert class_node.config_type == ConfigType.CLASS
assert pattern_node.config_type == ConfigType.PATTERN
assert boolean_node.config_type == ConfigType.BOOLEAN

0 comments on commit e7ad256

Please sign in to comment.