nautobot 2.4.5__py3-none-any.whl → 2.4.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. nautobot/core/api/mixins.py +10 -0
  2. nautobot/core/celery/encoders.py +2 -2
  3. nautobot/core/forms/fields.py +21 -5
  4. nautobot/core/forms/utils.py +1 -0
  5. nautobot/core/jobs/bulk_actions.py +1 -1
  6. nautobot/core/management/commands/generate_test_data.py +1 -1
  7. nautobot/core/models/name_color_content_types.py +9 -0
  8. nautobot/core/models/validators.py +7 -0
  9. nautobot/core/settings.py +0 -14
  10. nautobot/core/settings.yaml +0 -28
  11. nautobot/core/tables.py +6 -1
  12. nautobot/core/templates/generic/object_retrieve.html +1 -1
  13. nautobot/core/testing/api.py +18 -0
  14. nautobot/core/tests/nautobot_config.py +0 -2
  15. nautobot/core/tests/runner.py +17 -140
  16. nautobot/core/tests/test_api.py +4 -4
  17. nautobot/core/tests/test_authentication.py +83 -4
  18. nautobot/core/tests/test_forms.py +11 -8
  19. nautobot/core/tests/test_graphql.py +9 -0
  20. nautobot/core/tests/test_jobs.py +7 -0
  21. nautobot/core/ui/object_detail.py +31 -0
  22. nautobot/dcim/factory.py +2 -0
  23. nautobot/dcim/filters/__init__.py +5 -0
  24. nautobot/dcim/forms.py +17 -1
  25. nautobot/dcim/migrations/0068_alter_softwareimagefile_download_url.py +19 -0
  26. nautobot/dcim/migrations/0069_softwareimagefile_external_integration.py +25 -0
  27. nautobot/dcim/models/devices.py +9 -2
  28. nautobot/dcim/tables/devices.py +1 -0
  29. nautobot/dcim/templates/dcim/softwareimagefile_retrieve.html +4 -0
  30. nautobot/dcim/tests/test_api.py +74 -31
  31. nautobot/dcim/tests/test_filters.py +2 -0
  32. nautobot/dcim/tests/test_models.py +65 -0
  33. nautobot/dcim/tests/test_views.py +3 -0
  34. nautobot/extras/forms/forms.py +7 -3
  35. nautobot/extras/plugins/marketplace_manifest.yml +18 -0
  36. nautobot/extras/tables.py +4 -5
  37. nautobot/extras/templates/extras/inc/panel_changelog.html +1 -1
  38. nautobot/extras/templates/extras/inc/panel_jobhistory.html +1 -1
  39. nautobot/extras/templates/extras/status.html +1 -37
  40. nautobot/extras/tests/integration/test_notes.py +1 -1
  41. nautobot/extras/tests/test_api.py +22 -7
  42. nautobot/extras/tests/test_changelog.py +4 -4
  43. nautobot/extras/tests/test_customfields.py +3 -0
  44. nautobot/extras/tests/test_plugins.py +19 -13
  45. nautobot/extras/tests/test_relationships.py +9 -0
  46. nautobot/extras/tests/test_tags.py +2 -2
  47. nautobot/extras/tests/test_views.py +15 -6
  48. nautobot/extras/urls.py +1 -30
  49. nautobot/extras/views.py +10 -54
  50. nautobot/ipam/tables.py +6 -2
  51. nautobot/ipam/templates/ipam/namespace_retrieve.html +0 -41
  52. nautobot/ipam/templates/ipam/service.html +2 -46
  53. nautobot/ipam/templates/ipam/service_edit.html +1 -17
  54. nautobot/ipam/templates/ipam/service_retrieve.html +7 -0
  55. nautobot/ipam/tests/migration/__init__.py +0 -0
  56. nautobot/ipam/tests/migration/test_migrations.py +510 -0
  57. nautobot/ipam/tests/test_api.py +66 -36
  58. nautobot/ipam/tests/test_filters.py +0 -10
  59. nautobot/ipam/tests/test_views.py +44 -2
  60. nautobot/ipam/urls.py +2 -47
  61. nautobot/ipam/utils/migrations.py +185 -152
  62. nautobot/ipam/utils/testing.py +177 -0
  63. nautobot/ipam/views.py +95 -157
  64. nautobot/project-static/docs/code-reference/nautobot/apps/models.html +47 -0
  65. nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +18 -0
  66. nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +63 -0
  67. nautobot/project-static/docs/development/apps/api/testing.html +0 -87
  68. nautobot/project-static/docs/development/apps/migration/dependency-updates.html +1 -1
  69. nautobot/project-static/docs/development/core/best-practices.html +3 -3
  70. nautobot/project-static/docs/development/core/getting-started.html +78 -107
  71. nautobot/project-static/docs/development/core/release-checklist.html +1 -1
  72. nautobot/project-static/docs/development/core/style-guide.html +1 -1
  73. nautobot/project-static/docs/development/core/testing.html +24 -198
  74. nautobot/project-static/docs/media/user-guide/administration/getting-started/nautobot-cloud.png +0 -0
  75. nautobot/project-static/docs/objects.inv +0 -0
  76. nautobot/project-static/docs/overview/application_stack.html +1 -1
  77. nautobot/project-static/docs/release-notes/version-2.4.html +226 -1
  78. nautobot/project-static/docs/search/search_index.json +1 -1
  79. nautobot/project-static/docs/sitemap.xml +290 -290
  80. nautobot/project-static/docs/sitemap.xml.gz +0 -0
  81. nautobot/project-static/docs/user-guide/administration/configuration/settings.html +2 -48
  82. nautobot/project-static/docs/user-guide/administration/guides/permissions.html +71 -0
  83. nautobot/project-static/docs/user-guide/administration/installation/http-server.html +3 -1
  84. nautobot/project-static/docs/user-guide/administration/installation/index.html +257 -16
  85. nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +1 -1
  86. nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +2 -2
  87. nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +4 -0
  88. nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +11 -11
  89. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +8 -8
  90. nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +1 -0
  91. nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +40 -25
  92. nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +4 -4
  93. nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +1 -1
  94. nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +77 -5
  95. nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +1 -1
  96. nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +0 -1
  97. nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +1 -1
  98. nautobot/project-static/docs/user-guide/index.html +89 -2
  99. nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +207 -122
  100. nautobot/virtualization/forms.py +20 -0
  101. nautobot/virtualization/templates/virtualization/clustergroup.html +1 -39
  102. nautobot/virtualization/templates/virtualization/clustertype.html +1 -0
  103. nautobot/virtualization/tests/test_api.py +14 -3
  104. nautobot/virtualization/tests/test_views.py +10 -2
  105. nautobot/virtualization/urls.py +10 -93
  106. nautobot/virtualization/views.py +33 -72
  107. {nautobot-2.4.5.dist-info → nautobot-2.4.6.dist-info}/METADATA +6 -5
  108. {nautobot-2.4.5.dist-info → nautobot-2.4.6.dist-info}/RECORD +113 -108
  109. {nautobot-2.4.5.dist-info → nautobot-2.4.6.dist-info}/WHEEL +1 -1
  110. nautobot/core/tests/performance_baselines.yml +0 -8900
  111. nautobot/ipam/tests/test_migrations.py +0 -462
  112. /nautobot/ipam/templates/ipam/{namespace_ipaddresses.html → namespace_ip_addresses.html} +0 -0
  113. {nautobot-2.4.5.dist-info → nautobot-2.4.6.dist-info}/LICENSE.txt +0 -0
  114. {nautobot-2.4.5.dist-info → nautobot-2.4.6.dist-info}/NOTICE +0 -0
  115. {nautobot-2.4.5.dist-info → nautobot-2.4.6.dist-info}/entry_points.txt +0 -0
@@ -8498,48 +8498,6 @@
8498
8498
  </ul>
8499
8499
  </nav>
8500
8500
 
8501
- </li>
8502
-
8503
- <li class="md-nav__item">
8504
- <a href="#performance-tests" class="md-nav__link">
8505
- <span class="md-ellipsis">
8506
- Performance Tests
8507
- </span>
8508
- </a>
8509
-
8510
- <nav class="md-nav" aria-label="Performance Tests">
8511
- <ul class="md-nav__list">
8512
-
8513
- <li class="md-nav__item">
8514
- <a href="#running-performance-tests" class="md-nav__link">
8515
- <span class="md-ellipsis">
8516
- Running Performance Tests
8517
- </span>
8518
- </a>
8519
-
8520
- </li>
8521
-
8522
- <li class="md-nav__item">
8523
- <a href="#gathering-performance-test-baseline-data" class="md-nav__link">
8524
- <span class="md-ellipsis">
8525
- Gathering Performance Test Baseline Data
8526
- </span>
8527
- </a>
8528
-
8529
- </li>
8530
-
8531
- <li class="md-nav__item">
8532
- <a href="#caveats" class="md-nav__link">
8533
- <span class="md-ellipsis">
8534
- Caveats
8535
- </span>
8536
- </a>
8537
-
8538
- </li>
8539
-
8540
- </ul>
8541
- </nav>
8542
-
8543
8501
  </li>
8544
8502
 
8545
8503
  <li class="md-nav__item">
@@ -9404,48 +9362,6 @@
9404
9362
  </ul>
9405
9363
  </nav>
9406
9364
 
9407
- </li>
9408
-
9409
- <li class="md-nav__item">
9410
- <a href="#performance-tests" class="md-nav__link">
9411
- <span class="md-ellipsis">
9412
- Performance Tests
9413
- </span>
9414
- </a>
9415
-
9416
- <nav class="md-nav" aria-label="Performance Tests">
9417
- <ul class="md-nav__list">
9418
-
9419
- <li class="md-nav__item">
9420
- <a href="#running-performance-tests" class="md-nav__link">
9421
- <span class="md-ellipsis">
9422
- Running Performance Tests
9423
- </span>
9424
- </a>
9425
-
9426
- </li>
9427
-
9428
- <li class="md-nav__item">
9429
- <a href="#gathering-performance-test-baseline-data" class="md-nav__link">
9430
- <span class="md-ellipsis">
9431
- Gathering Performance Test Baseline Data
9432
- </span>
9433
- </a>
9434
-
9435
- </li>
9436
-
9437
- <li class="md-nav__item">
9438
- <a href="#caveats" class="md-nav__link">
9439
- <span class="md-ellipsis">
9440
- Caveats
9441
- </span>
9442
- </a>
9443
-
9444
- </li>
9445
-
9446
- </ul>
9447
- </nav>
9448
-
9449
9365
  </li>
9450
9366
 
9451
9367
  <li class="md-nav__item">
@@ -9476,10 +9392,11 @@
9476
9392
 
9477
9393
 
9478
9394
  <h1 id="testing-nautobot">Testing Nautobot<a class="headerlink" href="#testing-nautobot" title="Permanent link">&para;</a></h1>
9479
- <p>Best practices for developing and maintaining Nautobot's automated unit/integration test suites.</p>
9480
- <p>Unit tests are automated tests written and run to ensure that a section of the Nautobot application (known as the "unit") meets its design and behaves as intended and expected. Most commonly as a developer of or contributor to Nautobot you will be writing unit tests to exercise the code you have written. Unit tests are not meant to test how the application behaves, only the individual blocks of code, therefore use of mock data and phony connections is common in unit test code. As a guiding principle, unit tests should be fast, because they will be executed quite often.</p>
9481
- <p>Integration tests are automated tests written and run to ensure that the Nautobot application behaves as expected when being used as it would be in practice. By contrast to unit tests, where individual units of code are being tested, integration tests rely upon the server code actually running, and web UI clients or API clients to make real connections to the service to exercise actual workflows, such as navigating to the login page, filling out the username/passwords fields, and clicking the "Log In" button.</p>
9395
+ <p>Best practices for developing and maintaining Nautobot's automated test suites.</p>
9396
+ <p><strong>Unit tests</strong> are automated tests written and run to ensure that a section of the Nautobot application (known as the "unit") meets its design and behaves as intended and expected. Most commonly as a developer of or contributor to Nautobot you will be writing unit tests to exercise the code you have written. Unit tests are not meant to test how the application behaves, only the individual blocks of code, therefore use of mock data and phony connections is common in unit test code. As a guiding principle, unit tests should be fast, because they will be executed quite often.</p>
9397
+ <p><strong>Integration tests</strong> are automated tests written and run to ensure that the Nautobot application behaves as expected when being used as it would be in practice. By contrast to unit tests, where individual units of code are being tested, integration tests rely upon the server code actually running, and web UI clients or API clients to make real connections to the service to exercise actual workflows, such as navigating to the login page, filling out the username/passwords fields, and clicking the "Log In" button.</p>
9482
9398
  <p>Integration testing is much more involved, and builds on top of the foundation laid by unit testing. As a guiding principle, integration tests should be comprehensive, because they are the last mile to asserting that Nautobot does what it is advertised to do. Without integration testing, we have to do it all manually, and that's no fun for anyone!</p>
9399
+ <p><strong>Migration tests</strong> are automated tests written and run to ensure that Nautobot database migrations (primarily "data" migrations in particular, as opposed to "schema" migrations) correctly handle various data scenarios. These are "before/after" tests that bring the database to a particular historical state, populate data into this database state, then run the database migrations (simulating an in-place update of Nautobot) and verify that the final state of the database is as expected.</p>
9483
9400
  <h2 id="tagging-tests">Tagging Tests<a class="headerlink" href="#tagging-tests" title="Permanent link">&para;</a></h2>
9484
9401
  <p>By Nautobot convention, <strong>unit</strong> tests must be <a href="https://docs.djangoproject.com/en/stable/topics/testing/tools/#tagging-tests">tagged</a> with <code>unit</code>. The base test case class <code>nautobot.core.testing.TestCase</code> has this tag, therefore any test cases inheriting from that class do not need to be explicitly tagged. All existing view and API test cases in the Nautobot test suite inherit from this class.</p>
9485
9402
  <p>By Nautobot convention, <strong>integration</strong> tests must be <a href="https://docs.djangoproject.com/en/stable/topics/testing/tools/#tagging-tests">tagged</a> with <code>integration</code>. The base test case class <code>nautobot.core.testing.integration.SeleniumTestCase</code> has this tag, therefore any test cases inheriting from that class do not need to be explicitly tagged. All existing integration test cases in the Nautobot test suite inherit from this class.</p>
@@ -9487,7 +9404,11 @@
9487
9404
  <summary>Changed in version 2.0.0</summary>
9488
9405
  <p>The base test classes moved from <code>nautobot.utilities.testing</code> to <code>nautobot.core.testing</code>.</p>
9489
9406
  </details>
9490
- <p>The <code>invoke unittest</code> and <code>invoke integration-test</code> commands are intentionally distinct, and the correct tagging of test cases is essential to enforcing the division between these two test categories. We never want to risk running the unit tests and integration tests at the same time. The isolation from each other is critical to a clean and manageable continuous development cycle.</p>
9407
+ <p>Nautobot's Python-based <strong>migration</strong> tests are built around the <code>django-test-migrations</code> library and its <code>MigratorTestCase</code> class, which has the tag <code>migration_test</code>, therefore any test cases inheriting from that class do not need to be explicitly tagged.</p>
9408
+ <div class="admonition info">
9409
+ <p class="admonition-title">Info</p>
9410
+ <p>There are also a set of "holistic" migration tests executable by the <code>invoke migration-test</code> command; these "tests" consist of nothing more than historical SQL dumps (in the <code>development/datasets/</code> directory) of a fully populated database state that can be used to populate an empty database before running a <code>nautobot-server migrate</code> command and confirming that it raises no errors. This sort of test is fairly crude; in most cases writing a specific <code>MigratorTestCase</code> subclass is to be preferred.</p>
9411
+ </div>
9491
9412
  <h2 id="base-classes-and-code-location">Base Classes and Code Location<a class="headerlink" href="#base-classes-and-code-location" title="Permanent link">&para;</a></h2>
9492
9413
  <table>
9493
9414
  <thead>
@@ -9495,6 +9416,7 @@
9495
9416
  <th>Test Type</th>
9496
9417
  <th>Base Class</th>
9497
9418
  <th>Code Location</th>
9419
+ <th>Test Execution</th>
9498
9420
  </tr>
9499
9421
  </thead>
9500
9422
  <tbody>
@@ -9502,16 +9424,24 @@
9502
9424
  <td>Unit</td>
9503
9425
  <td><code>nautobot.core.testing.TestCase</code> or subclass (see below)</td>
9504
9426
  <td><code>nautobot/APP/tests/test_*.py</code></td>
9427
+ <td><code>invoke tests</code></td>
9505
9428
  </tr>
9506
9429
  <tr>
9507
9430
  <td>Integration</td>
9508
9431
  <td><code>nautobot.core.testing.integration.SeleniumTestCase</code></td>
9509
9432
  <td><code>nautobot/APP/tests/integration/test_*.py</code></td>
9433
+ <td><code>invoke tests --tag integration</code></td>
9434
+ </tr>
9435
+ <tr>
9436
+ <td>Migration</td>
9437
+ <td><code>django_test_migrations.contrib.unittest_case.MigratorTestCase</code></td>
9438
+ <td><code>nautobot/APP/tests/migration/test_*.py</code></td>
9439
+ <td><code>invoke tests --tag migration_test</code></td>
9510
9440
  </tr>
9511
9441
  </tbody>
9512
9442
  </table>
9513
9443
  <ul>
9514
- <li>New unit tests <strong>must always</strong> inherit from <code>nautobot.core.testing.TestCase</code> or one of its subclasses. Do not use <code>django.test.TestCase</code>.<ul>
9444
+ <li>New unit tests <strong>must always</strong> inherit from <code>nautobot.core.testing.TestCase</code> or one of its subclasses. Do not use <code>django.test.TestCase</code> or <code>unittest.TestCase</code>.<ul>
9515
9445
  <li>API view test cases should generally inherit from one or more of the classes in <code>nautobot.core.testing.api.APIViewTestCases</code>.</li>
9516
9446
  <li>Filterset test cases should generally inherit from <code>nautobot.core.testing.filters.FilterTestCases.FilterTestCase</code>.</li>
9517
9447
  <li>Form test cases should generally inherit from <code>nautobot.core.testing.forms.FormTestCases.BaseFormTestCase</code>.</li>
@@ -9525,6 +9455,9 @@
9525
9455
  <summary>Changed in version 2.0.0</summary>
9526
9456
  <p>The base test classes moved from <code>nautobot.utilities.testing</code> to <code>nautobot.core.testing</code>.</p>
9527
9457
  </details>
9458
+ <ul>
9459
+ <li>New migration tests <strong>should generally</strong> inherit from <code>django_test_migrations.contrib.unittest_case.MigratorTestCase</code>; if any other base class is used, you <strong>must</strong> explicitly tag it with the <code>migration_test</code> tag.</li>
9460
+ </ul>
9528
9461
  <h2 id="generic-filter-tests">Generic Filter Tests<a class="headerlink" href="#generic-filter-tests" title="Permanent link">&para;</a></h2>
9529
9462
  <details class="version-added">
9530
9463
  <summary>Added in version 2.0.0</summary>
@@ -9577,14 +9510,14 @@
9577
9510
  <p>In short, we should only have one place in our tests where factories are called, and that's the <code>generate_test_data</code> management command. Individual tests should use standard <code>create()</code> or <code>save()</code> model methods, never factories.</p>
9578
9511
  </div>
9579
9512
  <h3 id="factory-caching">Factory Caching<a class="headerlink" href="#factory-caching" title="Permanent link">&para;</a></h3>
9580
- <p>To reduce the time taken between multiple test runs, a new argument has been added to the <code>nautobot-server test</code> command: <code>--cache-test-fixtures</code>. When running tests with <code>--cache-test-fixtures</code> for the first time, after the factory data has been generated it will be saved to a <code>factory_dump.json</code> file in the <code>development</code> directory. On subsequent runs of unit or integration tests, if <code>--cache-test-fixtures</code> is again specified (hint: it is included by default when running <code>invoke unittest</code> or <code>invoke integration-test</code>), the factory data will be loaded from the file instead of being generated again. This can significantly reduce the time taken to run tests.</p>
9513
+ <p>To reduce the time taken between multiple test runs, a new argument has been added to the <code>nautobot-server test</code> command: <code>--cache-test-fixtures</code>. When running tests with <code>--cache-test-fixtures</code> for the first time, after the factory data has been generated it will be saved to a <code>factory_dump.json</code> file in the <code>development</code> directory. On subsequent runs of unit or integration tests, if <code>--cache-test-fixtures</code> is again specified (hint: it is included by default when running <code>invoke tests</code>), the factory data will be loaded from the file instead of being generated again. This can significantly reduce the time taken to run tests.</p>
9581
9514
  <details class="version-changed">
9582
9515
  <summary>Changed in version 2.2.7 — Hashing of migrations in the factory dump</summary>
9583
9516
  <p>The test runner now calculates a hash of applied database migrations and uses that as a key when creating/locating the factory data file. This serves as a way to avoid inadvertently using cached test data from the wrong branch or wrong set of migrations, and reduces the frequency with which you might need to manually delete the fixture file. For example, the set of migrations present in <code>develop</code> might result in a <code>factory_dump.966e2e1ed4ae5f924d54.json</code>, while those in <code>next</code> might result in <code>factory_dump.72b71317c5f5c047493e.json</code> - both files can coexist, and when you switch between branches during development, the correct one will automatically be selected.</p>
9584
9517
  </details>
9585
9518
  <details class="version-changed">
9586
9519
  <summary>Changed in version 2.3.4 — Factory caching is enabled by default in invoke tasks</summary>
9587
- <p>Factory caching is now enabled by default with the <code>invoke unittest</code> and <code>invoke integration-test</code> commands. To bypass it, either use the <code>--no-cache-test-fixtures</code> argument to <code>invoke unittest</code> or <code>invoke integration-test</code>, or manually remove the <code>development/factory_dump.*.json</code> cache file(s).</p>
9520
+ <p>Factory caching is now enabled by default with the <code>invoke tests</code> command. To bypass it, either use the <code>--no-cache-test-fixtures</code> argument to <code>invoke tests</code>, or manually remove the <code>development/factory_dump.*.json</code> cache file(s).</p>
9588
9521
  </details>
9589
9522
  <div class="admonition tip">
9590
9523
  <p class="admonition-title">Tip</p>
@@ -9594,113 +9527,6 @@
9594
9527
  <li>When the definition of a factory is changed or a new factory is added.</li>
9595
9528
  </ol>
9596
9529
  </div>
9597
- <h2 id="performance-tests">Performance Tests<a class="headerlink" href="#performance-tests" title="Permanent link">&para;</a></h2>
9598
- <h3 id="running-performance-tests">Running Performance Tests<a class="headerlink" href="#running-performance-tests" title="Permanent link">&para;</a></h3>
9599
- <p>Nautobot uses <a href="https://pypi.org/project/django-slowtests/"><code>django-slowtests</code></a> to run performance tests. To run performance tests, you need to install the <code>django-slowtests</code> package.
9600
- Once you install the package, you can do <code>invoke performance-test</code> or <code>invoke unittest --performance-test</code> to run unit tests with <code>NautobotPerformanceTestRunner</code>. The invoke commands will automatically add <code>--testrunner nautobot.core.tests.runner.NautobotPerformanceTestRunner</code> to the <code>coverage run</code> command and this flag will replace the default <code>NautobotTestRunner</code> while retaining all its functionalities with the addition of performance evaluation after test runs.</p>
9601
- <p><code>NautobotPerformanceTestRunner</code> which inherits from <code>DiscoverSlowestTestsRunner</code> will only be available when <code>django-slowtests</code> is installed. The runner measures the time to run unit tests against baselines stored in a designated .yml file (defaults to <code>nautobot/core/tests/performance_baselines.yml</code>) in addition to running the unit tests themselves.</p>
9602
- <div class="admonition warning">
9603
- <p class="admonition-title">Warning</p>
9604
- <p>This functionality requires the installation of the <a href="https://pypi.org/project/django-slowtests/"><code>django-slowtests</code></a> Python package, which is present in Nautobot's own development environment, but is <em>not</em> an inherent dependency of the Nautobot package when installed otherwise, such as into an App's development environment.</p>
9605
- </div>
9606
- <div class="admonition info">
9607
- <p class="admonition-title">Info</p>
9608
- <p><code>invoke performance-test</code> is enabled when <code>django-slowtests</code> is installed and when called, it will run and evaluate the performance of specific unit tests that are tagged with <code>performance</code> i.e. <code>@tag("performance")</code>. <code>invoke unittest --performance-report</code> and <code>invoke integration-test --performance-report</code> will also be enabled and when called, they will generate a performance report for all the tests ran in the terminal.
9609
- If performance baselines for tests are not available:</p>
9610
- </div>
9611
- <div class="highlight"><pre><span></span><code><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a>175 abnormally slower tests:
9612
- <a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a>Performance baseline for test_account (nautobot.circuits.tests.test_filters.ProviderTestCase) is not available. Test took 0.0758s to run
9613
- <a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a>Performance baseline for test_asn (nautobot.circuits.tests.test_filters.ProviderTestCase) is not available. Test took 0.0427s to run
9614
- <a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.CircuitTerminationTest) is not available. Test took 0.2900s to run
9615
- <a id="__codelineno-2-5" name="__codelineno-2-5" href="#__codelineno-2-5"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.CircuitTest) is not available. Test took 0.2292s to run
9616
- <a id="__codelineno-2-6" name="__codelineno-2-6" href="#__codelineno-2-6"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.CircuitTypeTest) is not available. Test took 0.1596s to run
9617
- <a id="__codelineno-2-7" name="__codelineno-2-7" href="#__codelineno-2-7"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.ProviderNetworkTest) is not available. Test took 0.1897s to run
9618
- <a id="__codelineno-2-8" name="__codelineno-2-8" href="#__codelineno-2-8"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.ProviderTest) is not available. Test took 0.2092s to run
9619
- <a id="__codelineno-2-9" name="__codelineno-2-9" href="#__codelineno-2-9"></a>Performance baseline for test_bulk_delete_objects (nautobot.circuits.tests.test_api.CircuitTerminationTest) is not available. Test took 0.1168s to run
9620
- <a id="__codelineno-2-10" name="__codelineno-2-10" href="#__codelineno-2-10"></a>Performance baseline for test_bulk_delete_objects (nautobot.circuits.tests.test_api.CircuitTest) is not available. Test took 0.2762s to run
9621
- <a id="__codelineno-2-11" name="__codelineno-2-11" href="#__codelineno-2-11"></a>Performance baseline for test_bulk_delete_objects (nautobot.circuits.tests.test_api.CircuitTypeTest) is not available. Test took 0.0663s to run
9622
- <a id="__codelineno-2-12" name="__codelineno-2-12" href="#__codelineno-2-12"></a>Performance baseline for test_bulk_delete_objects (nautobot.circuits.tests.test_api.ProviderNetworkTest) is not available. Test took 0.0875s to run
9623
- <a id="__codelineno-2-13" name="__codelineno-2-13" href="#__codelineno-2-13"></a>...
9624
- </code></pre></div>
9625
- <div class="admonition info">
9626
- <p class="admonition-title">Info</p>
9627
- <p>If performance baselines for tests are available and the time it take to run tests are siginificantly slower than baselines:</p>
9628
- </div>
9629
- <div class="highlight"><pre><span></span><code><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a>12 abnormally slower tests:
9630
- <a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a>0.9838s test_bulk_import_objects_with_constrained_permission (nautobot.ipam.tests.test_views.VLANTestCase) is significantly slower than the baseline 0.3692s
9631
- <a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a>1.2548s test_create_multiple_objects_with_constrained_permission (nautobot.dcim.tests.test_views.ConsolePortTestCase) is significantly slower than the baseline 0.5385s
9632
- <a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a>1.4289s test_create_multiple_objects_with_constrained_permission (nautobot.dcim.tests.test_views.DeviceBayTestCase) is significantly slower than the baseline 0.5616s
9633
- <a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a>1.1551s test_create_multiple_objects_with_constrained_permission (nautobot.dcim.tests.test_views.InventoryItemTestCase) is significantly slower than the baseline 0.5822s
9634
- <a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a>1.4712s test_create_multiple_objects_with_constrained_permission (nautobot.dcim.tests.test_views.RearPortTestCase) is significantly slower than the baseline 0.5695s
9635
- <a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a>1.5958s test_create_multiple_objects_with_constrained_permission (nautobot.virtualization.tests.test_views.VMInterfaceTestCase) is significantly slower than the baseline 1.0020s
9636
- <a id="__codelineno-3-8" name="__codelineno-3-8" href="#__codelineno-3-8"></a>1.0566s test_create_object_with_constrained_permission (nautobot.virtualization.tests.test_views.VirtualMachineTestCase) is significantly slower than the baseline 0.3627s
9637
- <a id="__codelineno-3-9" name="__codelineno-3-9" href="#__codelineno-3-9"></a>...
9638
- </code></pre></div>
9639
- <div class="admonition info">
9640
- <p class="admonition-title">Info</p>
9641
- <p>To output the performance evaluation to a file for later use, i.e. as performance baselines for future test runs, do <code>invoke performance-test --performance-snapshot</code>. This command will collect the <code>names</code> of the test and their <code>execution_time</code> and store them in a .yml file default to <code>report.yml</code>. Subsequently, the data in that file will have to be manually added to the baseline file set at <a href="../../user-guide/administration/configuration/settings.html#test_performance_baseline_file"><code>TEST_PERFORMANCE_BASELINE_FILE</code></a> to be used as baselines in performance tests.</p>
9642
- </div>
9643
- <p>Example output of <code>invoke performance-test --performance-snapshot</code>:</p>
9644
- <div class="highlight"><pre><span></span><code><a id="__codelineno-4-1" name="__codelineno-4-1" href="#__codelineno-4-1"></a><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">tests</span><span class="p">:</span>
9645
- <a id="__codelineno-4-2" name="__codelineno-4-2" href="#__codelineno-4-2"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_account (nautobot.circuits.tests.test_filters.ProviderTestCase)</span>
9646
- <a id="__codelineno-4-3" name="__codelineno-4-3" href="#__codelineno-4-3"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.07075</span>
9647
- <a id="__codelineno-4-4" name="__codelineno-4-4" href="#__codelineno-4-4"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_asn (nautobot.circuits.tests.test_filters.ProviderTestCase)</span>
9648
- <a id="__codelineno-4-5" name="__codelineno-4-5" href="#__codelineno-4-5"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.041262</span>
9649
- <a id="__codelineno-4-6" name="__codelineno-4-6" href="#__codelineno-4-6"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_cabled (nautobot.circuits.tests.test_filters.CircuitTerminationTestCase)</span>
9650
- <a id="__codelineno-4-7" name="__codelineno-4-7" href="#__codelineno-4-7"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.268673</span>
9651
- <a id="__codelineno-4-8" name="__codelineno-4-8" href="#__codelineno-4-8"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_cid (nautobot.circuits.tests.test_filters.CircuitTestCase)</span>
9652
- <a id="__codelineno-4-9" name="__codelineno-4-9" href="#__codelineno-4-9"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.116057</span>
9653
- <a id="__codelineno-4-10" name="__codelineno-4-10" href="#__codelineno-4-10"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_circuit_id (nautobot.circuits.tests.test_filters.CircuitTerminationTestCase)</span>
9654
- <a id="__codelineno-4-11" name="__codelineno-4-11" href="#__codelineno-4-11"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.042665</span>
9655
- <a id="__codelineno-4-12" name="__codelineno-4-12" href="#__codelineno-4-12"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_commit_rate (nautobot.circuits.tests.test_filters.CircuitTestCase)</span>
9656
- <a id="__codelineno-4-13" name="__codelineno-4-13" href="#__codelineno-4-13"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.047894</span>
9657
- <a id="__codelineno-4-14" name="__codelineno-4-14" href="#__codelineno-4-14"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_connected (nautobot.circuits.tests.test_filters.CircuitTerminationTestCase)</span>
9658
- <a id="__codelineno-4-15" name="__codelineno-4-15" href="#__codelineno-4-15"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.056196</span>
9659
- <a id="__codelineno-4-16" name="__codelineno-4-16" href="#__codelineno-4-16"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_id (nautobot.circuits.tests.test_filters.CircuitTerminationTestCase)</span>
9660
- <a id="__codelineno-4-17" name="__codelineno-4-17" href="#__codelineno-4-17"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.03598</span>
9661
- <a id="__codelineno-4-18" name="__codelineno-4-18" href="#__codelineno-4-18"></a><span class="nn">...</span>
9662
- </code></pre></div>
9663
- <h3 id="gathering-performance-test-baseline-data">Gathering Performance Test Baseline Data<a class="headerlink" href="#gathering-performance-test-baseline-data" title="Permanent link">&para;</a></h3>
9664
- <p><code>TEST_PERFORMANCE_BASELINE_FILE</code> specifies the file in which performance baselines are stored, defaults to <code>nautobot/core/tests/performance_baselines.yml</code>. Currently, only baselines for those unit tests tagged with <code>performance</code> are stored.</p>
9665
- <p>You can add baselines for your own test to <code>nautobot/core/tests/performance_baselines.yml</code> or have your own baseline yaml file for performance testing by specifying a different file path for <code>TEST_PERFORMANCE_BASELINE_FILE</code> in an App's development/test <code>nautobot_config.py</code>, and store the output of <code>invoke performance-test --performance-snapshot</code> in that file.
9666
- <code>--performance-snapshot</code> flag will store the results of your performance test to a new <code>report.yml</code> and all you need to do is copy/paste the results to the file set by <code>TEST_PERFORMANCE_BASELINE_FILE</code>. Now you have baselines for your own tests!</p>
9667
- <p>Example output of <code>invoke performance-test --performance-snapshot</code>:</p>
9668
- <div class="highlight"><pre><span></span><code><a id="__codelineno-5-1" name="__codelineno-5-1" href="#__codelineno-5-1"></a><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">tests</span><span class="p">:</span>
9669
- <a id="__codelineno-5-2" name="__codelineno-5-2" href="#__codelineno-5-2"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_account (nautobot.circuits.tests.test_filters.ProviderTestCase)</span>
9670
- <a id="__codelineno-5-3" name="__codelineno-5-3" href="#__codelineno-5-3"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.07075</span>
9671
- <a id="__codelineno-5-4" name="__codelineno-5-4" href="#__codelineno-5-4"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_asn (nautobot.circuits.tests.test_filters.ProviderTestCase)</span>
9672
- <a id="__codelineno-5-5" name="__codelineno-5-5" href="#__codelineno-5-5"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.041262</span>
9673
- <a id="__codelineno-5-6" name="__codelineno-5-6" href="#__codelineno-5-6"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_cabled (nautobot.circuits.tests.test_filters.CircuitTerminationTestCase)</span>
9674
- <a id="__codelineno-5-7" name="__codelineno-5-7" href="#__codelineno-5-7"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.268673</span>
9675
- <a id="__codelineno-5-8" name="__codelineno-5-8" href="#__codelineno-5-8"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_cid (nautobot.circuits.tests.test_filters.CircuitTestCase)</span>
9676
- <a id="__codelineno-5-9" name="__codelineno-5-9" href="#__codelineno-5-9"></a><span class="w"> </span><span class="nt">execution_time</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">0.116057</span>
9677
- <a id="__codelineno-5-10" name="__codelineno-5-10" href="#__codelineno-5-10"></a><span class="w"> </span><span class="p p-Indicator">-</span><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l l-Scalar l-Scalar-Plain">test_circuit_id (nautobot.circuits.tests.test_filters.CircuitTerminationTestCase)</span>
9678
- <a id="__codelineno-5-11" name="__codelineno-5-11" href="#__codelineno-5-11"></a><span class="nn">...</span>
9679
- </code></pre></div>
9680
- <p>if you decide to run <code>invoke unittest --performance-test</code> which will run tests that currently do not have their baselines present in the file, your output could look something like this:</p>
9681
- <div class="highlight"><pre><span></span><code><a id="__codelineno-6-1" name="__codelineno-6-1" href="#__codelineno-6-1"></a>175 abnormally slower tests:
9682
- <a id="__codelineno-6-2" name="__codelineno-6-2" href="#__codelineno-6-2"></a>Performance baseline for test_account (nautobot.circuits.tests.test_filters.ProviderTestCase) is not available. Test took 0.0758s to run
9683
- <a id="__codelineno-6-3" name="__codelineno-6-3" href="#__codelineno-6-3"></a>Performance baseline for test_asn (nautobot.circuits.tests.test_filters.ProviderTestCase) is not available. Test took 0.0427s to run
9684
- <a id="__codelineno-6-4" name="__codelineno-6-4" href="#__codelineno-6-4"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.CircuitTerminationTest) is not available. Test took 0.2900s to run
9685
- <a id="__codelineno-6-5" name="__codelineno-6-5" href="#__codelineno-6-5"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.CircuitTest) is not available. Test took 0.2292s to run
9686
- <a id="__codelineno-6-6" name="__codelineno-6-6" href="#__codelineno-6-6"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.CircuitTypeTest) is not available. Test took 0.1596s to run
9687
- <a id="__codelineno-6-7" name="__codelineno-6-7" href="#__codelineno-6-7"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.ProviderNetworkTest) is not available. Test took 0.1897s to run
9688
- <a id="__codelineno-6-8" name="__codelineno-6-8" href="#__codelineno-6-8"></a>Performance baseline for test_bulk_create_objects (nautobot.circuits.tests.test_api.ProviderTest) is not available. Test took 0.2092s to run
9689
- <a id="__codelineno-6-9" name="__codelineno-6-9" href="#__codelineno-6-9"></a>Performance baseline for test_bulk_delete_objects (nautobot.circuits.tests.test_api.CircuitTerminationTest) is not available. Test took 0.1168s to run
9690
- <a id="__codelineno-6-10" name="__codelineno-6-10" href="#__codelineno-6-10"></a>Performance baseline for test_bulk_delete_objects (nautobot.circuits.tests.test_api.CircuitTest) is not available. Test took 0.2762s to run
9691
- <a id="__codelineno-6-11" name="__codelineno-6-11" href="#__codelineno-6-11"></a>Performance baseline for test_bulk_delete_objects (nautobot.circuits.tests.test_api.CircuitTypeTest) is not available. Test took 0.0663s to run
9692
- <a id="__codelineno-6-12" name="__codelineno-6-12" href="#__codelineno-6-12"></a>Performance baseline for test_bulk_delete_objects (nautobot.circuits.tests.test_api.ProviderNetworkTest) is not available. Test took 0.0875s to run
9693
- <a id="__codelineno-6-13" name="__codelineno-6-13" href="#__codelineno-6-13"></a>...
9694
- </code></pre></div>
9695
- <h3 id="caveats">Caveats<a class="headerlink" href="#caveats" title="Permanent link">&para;</a></h3>
9696
- <div class="admonition warning">
9697
- <p class="admonition-title">Warning</p>
9698
- <p><code>django-slowtests</code> is only a <em>development</em> dependency of Nautobot. You cannot run performance tests in a production deployment of Nautobot unless you directly <code>pip install django-slowtests</code> into such a deployment.</p>
9699
- </div>
9700
- <div class="admonition info">
9701
- <p class="admonition-title">Info</p>
9702
- <p>Because Apps also commonly use Nautobot's default test runner <code>NautobotTestRunner</code>, in order to use <code>NautobotPerformanceTestRunner</code> you need to add <code>django-slowtests</code> as a part of your App dev dependencies.</p>
9703
- </div>
9704
9530
  <h2 id="test-code-style">Test Code Style<a class="headerlink" href="#test-code-style" title="Permanent link">&para;</a></h2>
9705
9531
  <ul>
9706
9532
  <li>Use more specific/feature-rich test assertion methods where available (e.g. <code>self.assertInHTML(fragment, html)</code> rather than <code>self.assertTrue(re.search(fragment, html))</code> or <code>assert re.search(fragment, html) is not None</code>).</li>
Binary file
@@ -9267,7 +9267,7 @@
9267
9267
  </tr>
9268
9268
  <tr>
9269
9269
  <td>Application</td>
9270
- <td><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11.146 0h3.924v18.166c-2.013.382-3.491.535-5.096.535-4.791 0-7.288-2.166-7.288-6.32 0-4.002 2.65-6.6 6.753-6.6.637 0 1.121.05 1.707.203zm0 9.143a3.9 3.9 0 0 0-1.325-.204c-1.988 0-3.134 1.223-3.134 3.365 0 2.09 1.096 3.236 3.109 3.236.433 0 .79-.025 1.35-.102V9.142zM21.314 6.06v9.098c0 3.134-.229 4.638-.917 5.937-.637 1.249-1.478 2.039-3.211 2.905l-3.644-1.733c1.733-.815 2.574-1.53 3.109-2.625.561-1.121.739-2.421.739-5.835V6.059zM17.39.021h3.924v4.026H17.39z"/></svg></span> Django <br> <span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19.14 7.5A2.86 2.86 0 0 1 22 10.36v3.78A2.86 2.86 0 0 1 19.14 17H12c0 .39.32.96.71.96H17v1.68a2.86 2.86 0 0 1-2.86 2.86H9.86A2.86 2.86 0 0 1 7 19.64v-3.75a2.85 2.85 0 0 1 2.86-2.85h5.25a2.85 2.85 0 0 0 2.85-2.86V7.5zm-4.28 11.79c-.4 0-.72.3-.72.89s.32.71.72.71a.71.71 0 0 0 .71-.71c0-.59-.32-.89-.71-.89m-10-1.79A2.86 2.86 0 0 1 2 14.64v-3.78A2.86 2.86 0 0 1 4.86 8H12c0-.39-.32-.96-.71-.96H7V5.36A2.86 2.86 0 0 1 9.86 2.5h4.28A2.86 2.86 0 0 1 17 5.36v3.75a2.85 2.85 0 0 1-2.86 2.85H8.89a2.85 2.85 0 0 0-2.85 2.86v2.68zM9.14 5.71c.4 0 .72-.3.72-.89s-.32-.71-.72-.71c-.39 0-.71.12-.71.71s.32.89.71.89"/></svg></span> Python 3.9 - 3.12 supported</td>
9270
+ <td><span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M11.146 0h3.924v18.166c-2.013.382-3.491.535-5.096.535-4.791 0-7.288-2.166-7.288-6.32 0-4.002 2.65-6.6 6.753-6.6.637 0 1.121.05 1.707.203zm0 9.143a3.9 3.9 0 0 0-1.325-.204c-1.988 0-3.134 1.223-3.134 3.365 0 2.09 1.096 3.236 3.109 3.236.433 0 .79-.025 1.35-.102V9.142zM21.314 6.06v9.098c0 3.134-.229 4.638-.917 5.937-.637 1.249-1.478 2.039-3.211 2.905l-3.644-1.733c1.733-.815 2.574-1.53 3.109-2.625.561-1.121.739-2.421.739-5.835V6.059zM17.39.021h3.924v4.026H17.39z"/></svg></span> Django <br> <span class="twemoji"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19.14 7.5A2.86 2.86 0 0 1 22 10.36v3.78A2.86 2.86 0 0 1 19.14 17H12c0 .39.32.96.71.96H17v1.68a2.86 2.86 0 0 1-2.86 2.86H9.86A2.86 2.86 0 0 1 7 19.64v-3.75a2.85 2.85 0 0 1 2.86-2.85h5.25a2.85 2.85 0 0 0 2.85-2.86V7.5zm-4.28 11.79c-.4 0-.72.3-.72.89s.32.71.72.71a.71.71 0 0 0 .71-.71c0-.59-.32-.89-.71-.89m-10-1.79A2.86 2.86 0 0 1 2 14.64v-3.78A2.86 2.86 0 0 1 4.86 8H12c0-.39-.32-.96-.71-.96H7V5.36A2.86 2.86 0 0 1 9.86 2.5h4.28A2.86 2.86 0 0 1 17 5.36v3.75a2.85 2.85 0 0 1-2.86 2.85H8.89a2.85 2.85 0 0 0-2.85 2.86v2.68zM9.14 5.71c.4 0 .72-.3.72-.89s-.32-.71-.72-.71c-.39 0-.71.12-.71.71s.32.89.71.89"/></svg></span> Python 3.9.2 - 3.12 supported</td>
9271
9271
  </tr>
9272
9272
  <tr>
9273
9273
  <td>Database</td>