Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KeyError with attribute type dict #41

Closed
jakubkrysl opened this issue May 2, 2022 · 4 comments
Closed

KeyError with attribute type dict #41

jakubkrysl opened this issue May 2, 2022 · 4 comments
Assignees

Comments

@jakubkrysl
Copy link

Environment

  • Python version: 3.6.15
  • Nautobot version: 1.2.10
  • nautobot-ssot version: 1.1.0

Expected Behavior

Being able to open job history detail in SSoT

Observed Behavior

image

08:44:37.325 ERROR   django.request :
  Internal Server Error: /plugins/ssot/history/82d43bc2-fcac-46b4-aee4-237fd6a58c73/
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/nautobot/utilities/views.py", line 94, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/nautobot/core/views/generic.py", line 124, in get
    **self.get_extra_context(request, instance),
  File "/usr/local/lib/python3.6/site-packages/django/shortcuts.py", line 19, in render
    content = loader.render_to_string(template_name, context, request, using=using)
  File "/usr/local/lib/python3.6/site-packages/django/template/loader.py", line 62, in render_to_string
    return template.render(context, request)
  File "/usr/local/lib/python3.6/site-packages/django/template/backends/django.py", line 61, in render
    return self.template.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 170, in render
    return self._render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 150, in render
    return compiled_parent._render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 162, in _render
    return self.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/loader_tags.py", line 62, in render
    result = block.nodelist.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 938, in render
    bit = node.render_annotated(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/base.py", line 905, in render_annotated
    return self.render(context)
  File "/usr/local/lib/python3.6/site-packages/django/template/library.py", line 192, in render
    output = self.func(*resolved_args, **resolved_kwargs)
  File "/usr/local/lib/python3.6/site-packages/nautobot_ssot/templatetags/render_diff.py", line 66, in render_diff
    return format_html(result)
  File "/usr/local/lib/python3.6/site-packages/django/utils/html.py", line 115, in format_html
    return mark_safe(format_string.format(*args_safe, **kwargs_safe))
KeyError: "'asw_owner'"

Steps to Reproduce

  1. add attribute type dict to DiffSyncModel class _attributes with some default value (no need to fill data later, dict must contain at least 1 key)
    cfs: typing.Dict[str, str] = {"asw_owner": ""}
  2. run job
  3. go to run detail in SSoT
@chadell
Copy link
Contributor

chadell commented May 2, 2022

Hi @Thetacz ,

I added it to the example RegionModel:

class RegionModel(DiffSyncModel):
    """Shared data model representing a Region in either of the local or remote Nautobot instances."""
   ...
    _attributes = ("slug", "description", "parent_name", "cfs")
    cfs: Dict[str, str] = {"asw_owner": ""}

and I can confirm that I got the error when accessing the SSoT Sync Details

@progala
Copy link
Contributor

progala commented May 3, 2022

@chadell

I also stumbled upon this bug. The issue seems to be with the below line in render_diff.py

    return format_html(result)

https://github.com/nautobot/nautobot-plugin-ssot/blob/develop/nautobot_ssot/templatetags/render_diff.py#L66

Which in turn is caused by the below line in django.utils.html.format_html

return mark_safe(format_string.format(*args_safe, **kwargs_safe))

https://github.com/django/django/blob/main/django/utils/html.py#L103

I was able to make it working, when testing locally against format_html(), by escaping { and } characters in string passed to the function.

result = result.replace("{", "{{").replace("}", "}}"

@chadell
Copy link
Contributor

chadell commented May 4, 2022

Yes @progala , this replace idea works. Will raise the PR

@chadell
Copy link
Contributor

chadell commented May 7, 2022

Fixed in #42

@chadell chadell closed this as completed May 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants