python.django.maintainability.duplicate-path-assignment.conflicting-path-assignment

profile photo of semgrepsemgrep
Author
851
Download Count*

The path for $URL is assigned once to view $VIEW and once to $DIFFERENT_VIEW, which can lead to unexpected behavior. Verify what the intended target view is and delete the other route.

Run Locally

Run in CI

Defintion

rules:
  - id: conflicting-path-assignment
    languages:
      - python
    message: The path for `$URL` is assigned once to view `$VIEW` and once to
      `$DIFFERENT_VIEW`, which can lead to unexpected behavior. Verify what the
      intended target view is and delete the other route.
    metadata:
      category: maintainability
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      technology:
        - django
    patterns:
      - pattern: >
          [..., django.urls.path('$URL', $VIEW, ...), ...,
          django.urls.path('$URL', $DIFFERENT_VIEW, ...), ...]
      - pattern-not: >
          [..., django.urls.path('$URL', $VIEW, ...), ...,
          django.urls.path('$URL', $VIEW, ...), ...]
    severity: ERROR

Examples

duplicate-path-assignment.py

from django.urls import path

# ruleid: duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, name="test"),
    path('path/to/view', views.example_view, name="test"),
]

# ruleid: duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, name="test"),
    path('path/to/other_view', view.other_view, name="hello"),
    path('path/to/view', views.example_view, name="test"),
]

# ruleid: duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view),
    path('path/to/view', views.example_view),
]

# ruleid: duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}),
    path('path/to/view', views.example_view, {'abc': 'def'}),
]

# ruleid: duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}),
    path('path/to/view', views.example_view, {'def': 'abc'}),
]

# ruleid: duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}, name="test123"),
    path('path/to/view', views.example_view, {'abc': 'def'}, name="test123"),
]

# ruleid: duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}, name="test123"),
    path('path/to/view', views.example_view, {'def': 'abc'}),
]

# ruleid: duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}, name="test123"),
    path('path/to/view', views.example_view),
]

# ruleid: conflicting-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, name="test"),
    path('path/to/view', views.other_view, name="test"),
]

# ruleid: conflicting-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, name="test"),
    path('path/to/other_view', view.other_view, name="hello"),
    path('path/to/view', views.other_view, name="test"),
]

# ruleid: conflicting-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view),
    path('path/to/view', views.other_view),
]

# ruleid: conflicting-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}),
    path('path/to/view', views.other_view, {'abc': 'def'}),
]

# ruleid: conflicting-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}),
    path('path/to/view', views.other_view, {'def': 'abc'}),
]

# I would prefer duplicate-path-assignment to not match the following test cases
# to avoid giving two messages for the same issue, but could not find a way yet.
# todook: duplicate-path-assignment
# ruleid: duplicate-path-assignment-different-names, duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, name="test"),
    path('path/to/view', views.example_view, name="other_name"),
]

# todook: duplicate-path-assignment
# ruleid: duplicate-path-assignment-different-names, duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}, name="test"),
    path('path/to/view', views.example_view, {'abc': 'def'}, name="other_name"),
]

# todook: duplicate-path-assignment
# ruleid: duplicate-path-assignment-different-names, duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}, name="test"),
    path('path/to/other/view', views.other_view, {'abc': 'def'}, name="some_test"),
    path('path/to/view', views.example_view, {'abc': 'def'}, name="other_name"),
]

# todook: duplicate-path-assignment
# ruleid: duplicate-path-assignment-different-names, duplicate-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, {'abc': 'def'}, name="test123"),
    path('path/to/view', views.example_view, {'def': 'abc'}, name="test456"),
]

# ruleid: duplicate-name-assignment
urlpatterns = [
    path('path/to/view', views.example_view, name="test123"),
    path('path/to/other/view', views.other_view, name="test123"),
]

# ruleid: conflicting-path-assignment
urlpatterns = [
    path('path/to/view', views.example_view, name="test123"),
    path('path/to/view', views.other_view, name="test123"),
]

# ruleid: duplicate-name-assignment
urlpatterns = [
    path('path/to/view', views.example_view, name="test123"),
    path('path/to/other/view', views.other_view, name="test123"),
]

# ok: duplicate-path-assignment-different-names, conflicting-path-assignment, duplicate-path-assignment
urlpatterns = [
    path('path/to/other_view', views.example_view, name="test"),
    path('path/to/view', views.example_view, name="test"),
]

# ok: duplicate-path-assignment-different-names, conflicting-path-assignment, duplicate-path-assignment
urlpatterns = [
    path('path/to/other_view', views.example_view, name="test"),
    path('path/to/view', views.other_view, name="test_abc"),
]