nautobot 2.4.17__py3-none-any.whl → 2.4.19__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.
Potentially problematic release.
This version of nautobot might be problematic. Click here for more details.
- nautobot/apps/ui.py +6 -0
- nautobot/apps/views.py +2 -0
- nautobot/circuits/tables.py +1 -1
- nautobot/circuits/templates/circuits/circuit_create.html +7 -7
- nautobot/circuits/templates/circuits/circuit_retrieve.html +1 -5
- nautobot/circuits/templates/circuits/circuittermination_create.html +26 -26
- nautobot/circuits/templates/circuits/circuittermination_retrieve.html +1 -8
- nautobot/circuits/templates/circuits/inc/circuit_termination.html +20 -20
- nautobot/circuits/templates/circuits/inc/circuit_termination_header_extra_content.html +3 -3
- nautobot/circuits/templates/circuits/inc/circuit_termination_speed_fragment.html +9 -0
- nautobot/circuits/templates/circuits/providernetwork_retrieve.html +1 -3
- nautobot/circuits/tests/integration/test_circuit.py +2 -2
- nautobot/circuits/views.py +49 -15
- nautobot/cloud/templates/cloud/cloudaccount_retrieve.html +1 -4
- nautobot/cloud/templates/cloud/cloudnetwork_retrieve.html +1 -7
- nautobot/cloud/templates/cloud/cloudresourcetype_retrieve.html +1 -3
- nautobot/cloud/templates/cloud/cloudservice_retrieve.html +1 -5
- nautobot/cloud/views.py +45 -0
- nautobot/core/filters.py +2 -2
- nautobot/core/graphql/generators.py +5 -2
- nautobot/core/jobs/bulk_actions.py +48 -85
- nautobot/core/models/querysets.py +2 -1
- nautobot/core/settings.py +1 -0
- nautobot/core/settings.yaml +9 -0
- nautobot/core/tables.py +21 -23
- nautobot/core/templates/40x.html +15 -15
- nautobot/core/templates/500.html +21 -21
- nautobot/core/templates/admin/app_index.html +8 -8
- nautobot/core/templates/admin/base.html +104 -104
- nautobot/core/templates/admin/change_form.html +65 -65
- nautobot/core/templates/admin/change_list.html +60 -60
- nautobot/core/templates/admin/change_list_results.html +39 -39
- nautobot/core/templates/admin/config/config.html +47 -47
- nautobot/core/templates/admin/delete_confirmation.html +47 -47
- nautobot/core/templates/admin/edit_inline/stacked.html +124 -124
- nautobot/core/templates/admin/edit_inline/tabular.html +60 -60
- nautobot/core/templates/admin/includes/fieldset.html +4 -4
- nautobot/core/templates/admin/index.html +60 -60
- nautobot/core/templates/admin/prepopulated_fields_js.html +18 -18
- nautobot/core/templates/admin/submit_line.html +4 -4
- nautobot/core/templates/base_django.html +46 -46
- nautobot/core/templates/buttons/consolidated_bulk_action_buttons.html +8 -8
- nautobot/core/templates/buttons/consolidated_detail_view_action_buttons.html +8 -8
- nautobot/core/templates/buttons/export.html +3 -3
- nautobot/core/templates/components/breadcrumbs.html +19 -0
- nautobot/core/templates/components/button/default.html +3 -3
- nautobot/core/templates/components/button/dropdown.html +7 -7
- nautobot/core/templates/components/button/formbutton.html +4 -4
- nautobot/core/templates/components/panel/body_content_data_table.html +1 -1
- nautobot/core/templates/components/panel/body_wrapper_generic_table.html +3 -0
- nautobot/core/templates/components/panel/footer_content_table.html +3 -1
- nautobot/core/templates/components/panel/header_extra_content_table.html +10 -1
- nautobot/core/templates/components/tab/content_wrapper.html +1 -1
- nautobot/core/templates/components/tab/label_wrapper.html +1 -1
- nautobot/core/templates/components/tab/label_wrapper_distinct_view.html +10 -3
- nautobot/core/templates/generic/object_bulk_add_component.html +40 -40
- nautobot/core/templates/generic/object_bulk_create.html +3 -3
- nautobot/core/templates/generic/object_bulk_destroy.html +6 -6
- nautobot/core/templates/generic/object_bulk_update.html +52 -52
- nautobot/core/templates/generic/object_changelog.html +0 -2
- nautobot/core/templates/generic/object_import.html +33 -33
- nautobot/core/templates/generic/object_list.html +271 -268
- nautobot/core/templates/generic/object_notes.html +0 -2
- nautobot/core/templates/generic/object_retrieve.html +264 -257
- nautobot/core/templates/graphene/graphiql.html +127 -127
- nautobot/core/templates/home.html +62 -62
- nautobot/core/templates/inc/computed_fields/panel_data.html +13 -13
- nautobot/core/templates/inc/created_updated.html +8 -8
- nautobot/core/templates/inc/custom_fields/panel_data.html +13 -13
- nautobot/core/templates/inc/dynamic_groups_panel.html +11 -11
- nautobot/core/templates/inc/footer.html +19 -19
- nautobot/core/templates/inc/javascript.html +1 -1
- nautobot/core/templates/inc/media.html +46 -46
- nautobot/core/templates/inc/nav_menu.html +1 -1
- nautobot/core/templates/inc/relationships_table_rows.html +22 -22
- nautobot/core/templates/inc/tenant_table_row.html +1 -1
- nautobot/core/templates/login.html +77 -77
- nautobot/core/templates/media_failure.html +38 -38
- nautobot/core/templates/panel_table.html +1 -1
- nautobot/core/templates/rest_framework/api.html +3 -3
- nautobot/core/templates/search.html +1 -1
- nautobot/core/templates/swagger_ui.html +9 -9
- nautobot/core/templates/utilities/confirmation_form.html +18 -18
- nautobot/core/templates/utilities/render_field.html +1 -1
- nautobot/core/templates/utilities/render_jinja2.html +43 -43
- nautobot/core/templates/utilities/templatetags/filter_form_modal.html +56 -56
- nautobot/core/templates/utilities/templatetags/utilization_graph.html +1 -1
- nautobot/core/templates/utilities/theme_preview.html +799 -799
- nautobot/core/templates/utilities/worker_status.html +122 -122
- nautobot/core/templates/widgets/clearable_file.html +3 -3
- nautobot/core/templates/widgets/sluginput.html +1 -1
- nautobot/core/templatetags/buttons.py +8 -2
- nautobot/core/templatetags/helpers.py +24 -0
- nautobot/core/templatetags/ui_framework.py +40 -5
- nautobot/core/testing/filters.py +37 -21
- nautobot/core/testing/integration.py +7 -4
- nautobot/core/testing/views.py +49 -5
- nautobot/core/tests/test_breadcrumbs.py +78 -4
- nautobot/core/tests/test_commands.py +7 -4
- nautobot/core/tests/test_graphql.py +20 -5
- nautobot/core/tests/test_jobs.py +34 -21
- nautobot/core/tests/test_tables.py +43 -6
- nautobot/core/tests/test_templatetags_ui_framework.py +146 -0
- nautobot/core/tests/test_titles.py +2 -2
- nautobot/core/tests/test_ui.py +188 -1
- nautobot/core/tests/test_utils.py +35 -0
- nautobot/core/tests/test_views.py +45 -0
- nautobot/core/tests/test_views_generic.py +43 -0
- nautobot/core/tests/test_views_utils.py +239 -5
- nautobot/core/ui/breadcrumbs.py +220 -28
- nautobot/core/ui/bulk_buttons.py +8 -0
- nautobot/core/ui/object_detail.py +181 -60
- nautobot/core/ui/titles.py +10 -5
- nautobot/core/utils/requests.py +27 -2
- nautobot/core/views/__init__.py +24 -3
- nautobot/core/views/generic.py +70 -35
- nautobot/core/views/mixins.py +226 -122
- nautobot/core/views/utils.py +270 -1
- nautobot/dcim/api/serializers.py +8 -2
- nautobot/dcim/constants.py +1 -0
- nautobot/dcim/factory.py +4 -3
- nautobot/dcim/filters/mixins.py +1 -2
- nautobot/dcim/forms.py +5 -1
- nautobot/dcim/migrations/0074_alter_rack_u_height.py +21 -0
- nautobot/dcim/models/devices.py +30 -1
- nautobot/dcim/models/racks.py +2 -2
- nautobot/dcim/tables/__init__.py +2 -0
- nautobot/dcim/tables/devices.py +24 -0
- nautobot/dcim/tables/power.py +2 -2
- nautobot/dcim/templates/dcim/cable.html +53 -53
- nautobot/dcim/templates/dcim/cable_connect.html +182 -182
- nautobot/dcim/templates/dcim/cable_trace.html +1 -1
- nautobot/dcim/templates/dcim/console_port_connection_list.html +5 -5
- nautobot/dcim/templates/dcim/consoleport.html +86 -86
- nautobot/dcim/templates/dcim/consoleserverport.html +86 -86
- nautobot/dcim/templates/dcim/controller_create.html +34 -34
- nautobot/dcim/templates/dcim/controllermanageddevicegroup_create.html +68 -68
- nautobot/dcim/templates/dcim/device/base.html +1 -114
- nautobot/dcim/templates/dcim/device/config.html +17 -17
- nautobot/dcim/templates/dcim/device/consoleports.html +1 -52
- nautobot/dcim/templates/dcim/device/consoleserverports.html +1 -52
- nautobot/dcim/templates/dcim/device/devicebays.html +1 -48
- nautobot/dcim/templates/dcim/device/frontports.html +1 -52
- nautobot/dcim/templates/dcim/device/interfaces.html +1 -56
- nautobot/dcim/templates/dcim/device/inventory.html +1 -48
- nautobot/dcim/templates/dcim/device/lldp_neighbors.html +64 -64
- nautobot/dcim/templates/dcim/device/modulebays.html +1 -48
- nautobot/dcim/templates/dcim/device/poweroutlets.html +1 -52
- nautobot/dcim/templates/dcim/device/powerports.html +1 -52
- nautobot/dcim/templates/dcim/device/rearports.html +1 -52
- nautobot/dcim/templates/dcim/device/status.html +66 -66
- nautobot/dcim/templates/dcim/device/wireless.html +1 -72
- nautobot/dcim/templates/dcim/device.html +4 -422
- nautobot/dcim/templates/dcim/device_component.html +0 -19
- nautobot/dcim/templates/dcim/device_component_add.html +25 -25
- nautobot/dcim/templates/dcim/device_create.html +229 -0
- nautobot/dcim/templates/dcim/device_edit.html +2 -227
- nautobot/dcim/templates/dcim/devicebay.html +41 -41
- nautobot/dcim/templates/dcim/devicebay_populate.html +32 -32
- nautobot/dcim/templates/dcim/devicetype_component_add.html +28 -28
- nautobot/dcim/templates/dcim/devicetype_retrieve.html +1 -3
- nautobot/dcim/templates/dcim/frontport.html +84 -84
- nautobot/dcim/templates/dcim/inc/cable_toggle_buttons.html +1 -1
- nautobot/dcim/templates/dcim/inc/device_interface_filter.html +8 -0
- nautobot/dcim/templates/dcim/inc/device_napalm_tabs.html +1 -15
- nautobot/dcim/templates/dcim/inc/location_hierarchy.html +22 -22
- nautobot/dcim/templates/dcim/interface.html +206 -206
- nautobot/dcim/templates/dcim/interface_connection_list.html +5 -5
- nautobot/dcim/templates/dcim/interfaceredundancygroupassociation_create.html +6 -6
- nautobot/dcim/templates/dcim/inventoryitem.html +44 -44
- nautobot/dcim/templates/dcim/inventoryitem_add.html +32 -32
- nautobot/dcim/templates/dcim/inventoryitem_edit.html +22 -22
- nautobot/dcim/templates/dcim/location_migrate_data_to_contact.html +46 -46
- nautobot/dcim/templates/dcim/location_retrieve.html +1 -7
- nautobot/dcim/templates/dcim/locationtype.html +1 -6
- nautobot/dcim/templates/dcim/locationtype_retrieve.html +1 -7
- nautobot/dcim/templates/dcim/module/base.html +85 -85
- nautobot/dcim/templates/dcim/module_interfaces.html +1 -1
- nautobot/dcim/templates/dcim/module_modulebays.html +1 -1
- nautobot/dcim/templates/dcim/module_retrieve.html +52 -52
- nautobot/dcim/templates/dcim/module_update.html +61 -61
- nautobot/dcim/templates/dcim/modulebay_destroy.html +1 -1
- nautobot/dcim/templates/dcim/modulebay_retrieve.html +83 -99
- nautobot/dcim/templates/dcim/modulebay_update.html +33 -33
- nautobot/dcim/templates/dcim/modulefamily_retrieve.html +1 -1
- nautobot/dcim/templates/dcim/moduletype_retrieve.html +140 -144
- nautobot/dcim/templates/dcim/platform_create.html +38 -38
- nautobot/dcim/templates/dcim/power_port_connection_list.html +5 -5
- nautobot/dcim/templates/dcim/powerfeed_retrieve.html +1 -8
- nautobot/dcim/templates/dcim/poweroutlet.html +85 -85
- nautobot/dcim/templates/dcim/powerpanel_retrieve.html +1 -8
- nautobot/dcim/templates/dcim/powerport.html +91 -91
- nautobot/dcim/templates/dcim/rack_elevation_list.html +18 -18
- nautobot/dcim/templates/dcim/rack_retrieve.html +264 -274
- nautobot/dcim/templates/dcim/rackreservation_retrieve.html +0 -3
- nautobot/dcim/templates/dcim/rearport.html +78 -78
- nautobot/dcim/templates/dcim/virtualchassis_retrieve.html +1 -50
- nautobot/dcim/templates/dcim/virtualdevicecontext_retrieve.html +1 -5
- nautobot/dcim/tests/integration/test_device_bulk_operations.py +3 -2
- nautobot/dcim/tests/integration/test_location_bulk_operations.py +6 -2
- nautobot/dcim/tests/test_api.py +33 -1
- nautobot/dcim/tests/test_views.py +189 -4
- nautobot/dcim/ui.py +29 -0
- nautobot/dcim/urls.py +1 -109
- nautobot/dcim/utils.py +30 -0
- nautobot/dcim/views.py +1149 -550
- nautobot/extras/filters/mixins.py +1 -1
- nautobot/extras/forms/forms.py +15 -0
- nautobot/extras/models/groups.py +10 -1
- nautobot/extras/models/jobs.py +2 -2
- nautobot/extras/plugins/views.py +18 -5
- nautobot/extras/tables.py +24 -2
- nautobot/extras/templates/extras/computedfield_edit.html +4 -4
- nautobot/extras/templates/extras/configcontext_update.html +1 -1
- nautobot/extras/templates/extras/configcontextschema_retrieve.html +32 -32
- nautobot/extras/templates/extras/customfield_retrieve.html +1 -128
- nautobot/extras/templates/extras/customfield_update.html +23 -23
- nautobot/extras/templates/extras/dynamicgroup.html +2 -99
- nautobot/extras/templates/extras/dynamicgroup_edit.html +2 -199
- nautobot/extras/templates/extras/dynamicgroup_retrieve.html +99 -0
- nautobot/extras/templates/extras/dynamicgroup_update.html +199 -0
- nautobot/extras/templates/extras/gitrepository.html +2 -82
- nautobot/extras/templates/extras/gitrepository_list.html +10 -10
- nautobot/extras/templates/extras/gitrepository_object_edit.html +2 -13
- nautobot/extras/templates/extras/gitrepository_retrieve.html +82 -0
- nautobot/extras/templates/extras/gitrepository_update.html +13 -0
- nautobot/extras/templates/extras/graphqlquery_retrieve.html +73 -73
- nautobot/extras/templates/extras/inc/configcontext_format.html +2 -2
- nautobot/extras/templates/extras/inc/job_table.html +10 -10
- nautobot/extras/templates/extras/inc/jobresult.html +21 -21
- nautobot/extras/templates/extras/inc/jobresult_js.html +6 -6
- nautobot/extras/templates/extras/inc/tags_panel.html +10 -10
- nautobot/extras/templates/extras/job.html +64 -64
- nautobot/extras/templates/extras/job_approval_request.html +9 -9
- nautobot/extras/templates/extras/job_bulk_edit.html +13 -13
- nautobot/extras/templates/extras/job_edit.html +45 -45
- nautobot/extras/templates/extras/job_list.html +4 -4
- nautobot/extras/templates/extras/jobresult_retrieve.html +0 -25
- nautobot/extras/templates/extras/marketplace.html +101 -101
- nautobot/extras/templates/extras/metadatatype_create.html +20 -20
- nautobot/extras/templates/extras/note_retrieve.html +0 -52
- nautobot/extras/templates/extras/object_assign_contact_or_team.html +18 -18
- nautobot/extras/templates/extras/object_configcontext.html +1 -3
- nautobot/extras/templates/extras/objectchange.html +2 -165
- nautobot/extras/templates/extras/objectchange_retrieve.html +165 -0
- nautobot/extras/templates/extras/plugin_detail.html +44 -48
- nautobot/extras/templates/extras/plugins_list.html +9 -11
- nautobot/extras/templates/extras/plugins_tiles.html +26 -26
- nautobot/extras/templates/extras/relationship_edit.html +4 -4
- nautobot/extras/templates/extras/role_retrieve.html +13 -13
- nautobot/extras/templates/extras/scheduled_jobs_approval_queue_list.html +21 -21
- nautobot/extras/templates/extras/scheduledjob.html +128 -128
- nautobot/extras/templates/extras/secret_create.html +53 -53
- nautobot/extras/templates/extras/secretsgroup_update.html +13 -13
- nautobot/extras/templates/extras/templatetags/plugin_object_detail_tabs.html +3 -3
- nautobot/extras/templates/extras/webhook.html +79 -79
- nautobot/extras/tests/integration/test_relationships.py +6 -6
- nautobot/extras/tests/test_dynamicgroups.py +73 -18
- nautobot/extras/tests/test_filters.py +1 -1
- nautobot/extras/tests/test_jobs.py +2 -0
- nautobot/extras/tests/test_views.py +8 -3
- nautobot/extras/urls.py +3 -97
- nautobot/extras/views.py +524 -456
- nautobot/ipam/filters.py +2 -2
- nautobot/ipam/migrations/0053_alter_vrfdeviceassignment_options_and_more.py +20 -0
- nautobot/ipam/models.py +34 -0
- nautobot/ipam/querysets.py +3 -3
- nautobot/ipam/signals.py +6 -1
- nautobot/ipam/tables.py +3 -1
- nautobot/ipam/templates/ipam/inc/prefix_header_extra_content_table.html +4 -0
- nautobot/ipam/templates/ipam/inc/toggle_available.html +8 -8
- nautobot/ipam/templates/ipam/inc/vlangroup_header.html +4 -4
- nautobot/ipam/templates/ipam/ipaddress.html +119 -123
- nautobot/ipam/templates/ipam/ipaddress_assign.html +10 -10
- nautobot/ipam/templates/ipam/ipaddress_edit.html +1 -1
- nautobot/ipam/templates/ipam/ipaddress_merge.html +180 -180
- nautobot/ipam/templates/ipam/ipaddresstointerface_retrieve.html +48 -48
- nautobot/ipam/templates/ipam/prefix.html +2 -115
- nautobot/ipam/templates/ipam/prefix_create.html +34 -0
- nautobot/ipam/templates/ipam/prefix_edit.html +1 -34
- nautobot/ipam/templates/ipam/prefix_retrieve.html +3 -0
- nautobot/ipam/templates/ipam/service_retrieve.html +1 -6
- nautobot/ipam/templates/ipam/vlan_retrieve.html +1 -7
- nautobot/ipam/templates/ipam/vrf_edit.html +1 -1
- nautobot/ipam/tests/test_api.py +5 -0
- nautobot/ipam/tests/test_models.py +387 -0
- nautobot/ipam/tests/test_querysets.py +46 -0
- nautobot/ipam/tests/test_views.py +34 -0
- nautobot/ipam/ui.py +145 -0
- nautobot/ipam/urls.py +1 -46
- nautobot/ipam/utils/__init__.py +26 -0
- nautobot/ipam/utils/migrations.py +1 -1
- nautobot/ipam/views.py +234 -112
- nautobot/project-static/docs/404.html +11 -11
- nautobot/project-static/docs/apps/index.html +11 -11
- nautobot/project-static/docs/apps/nautobot-apps.html +11 -11
- nautobot/project-static/docs/assets/javascripts/{bundle.92b07e13.min.js → bundle.f55a23d4.min.js} +2 -2
- nautobot/project-static/docs/assets/javascripts/{bundle.92b07e13.min.js.map → bundle.f55a23d4.min.js.map} +2 -2
- nautobot/project-static/docs/assets/stylesheets/{main.7e37652d.min.css → main.e53b48f4.min.css} +1 -1
- nautobot/project-static/docs/assets/stylesheets/{main.7e37652d.min.css.map → main.e53b48f4.min.css.map} +1 -1
- nautobot/project-static/docs/code-reference/nautobot/apps/__init__.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/admin.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/api.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/change_logging.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/choices.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/config.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/constants.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/datasources.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/events.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/exceptions.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/factory.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/filters.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/forms.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/graphql.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/jobs.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/models.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/querysets.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/secrets.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/tables.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/testing.html +83 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/ui.html +1265 -281
- nautobot/project-static/docs/code-reference/nautobot/apps/urls.html +11 -11
- nautobot/project-static/docs/code-reference/nautobot/apps/utils.html +12 -12
- nautobot/project-static/docs/code-reference/nautobot/apps/views.html +452 -29
- nautobot/project-static/docs/development/apps/api/configuration-view.html +11 -11
- nautobot/project-static/docs/development/apps/api/database-backend-config.html +11 -11
- nautobot/project-static/docs/development/apps/api/models/django-admin.html +11 -11
- nautobot/project-static/docs/development/apps/api/models/global-search.html +11 -11
- nautobot/project-static/docs/development/apps/api/models/graphql.html +11 -11
- nautobot/project-static/docs/development/apps/api/models/index.html +11 -11
- nautobot/project-static/docs/development/apps/api/nautobot-app-config.html +12 -12
- nautobot/project-static/docs/development/apps/api/platform-features/custom-validators.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/filter-extensions.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/git-repository-content.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/index.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/jinja2-filters.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/jobs.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/prepopulating-data.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/secrets-providers.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/table-extensions.html +11 -11
- nautobot/project-static/docs/development/apps/api/platform-features/uniquely-identify-objects.html +11 -11
- nautobot/project-static/docs/development/apps/api/prometheus.html +11 -11
- nautobot/project-static/docs/development/apps/api/setup.html +11 -11
- nautobot/project-static/docs/development/apps/api/testing.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/banners.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/home-page.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/index.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/navigation.html +11 -11
- nautobot/project-static/docs/development/apps/api/ui-extensions/object-views.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/base-template.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/core-view-overrides.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/django-generic-views.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/help-documentation.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/index.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/nautobot-generic-views.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewset.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/nautobotuiviewsetrouter.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/notes.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/rest-api.html +11 -11
- nautobot/project-static/docs/development/apps/api/views/urls.html +11 -11
- nautobot/project-static/docs/development/apps/index.html +11 -11
- nautobot/project-static/docs/development/apps/migration/code-updates.html +11 -11
- nautobot/project-static/docs/development/apps/migration/dependency-updates.html +11 -11
- nautobot/project-static/docs/development/apps/migration/from-v1.html +11 -11
- nautobot/project-static/docs/development/apps/migration/model-updates/dcim.html +11 -11
- nautobot/project-static/docs/development/apps/migration/model-updates/extras.html +11 -11
- nautobot/project-static/docs/development/apps/migration/model-updates/global.html +11 -11
- nautobot/project-static/docs/development/apps/migration/model-updates/ipam.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/best-practices.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/breadcrumbs-titles.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/custom-content.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/index.html +11 -11
- nautobot/project-static/docs/development/apps/migration/ui-component-framework/migration-steps.html +11 -11
- nautobot/project-static/docs/development/apps/porting-from-netbox.html +11 -11
- nautobot/project-static/docs/development/core/application-registry.html +11 -11
- nautobot/project-static/docs/development/core/best-practices.html +11 -11
- nautobot/project-static/docs/development/core/bootstrap-ui.html +11 -11
- nautobot/project-static/docs/development/core/caching.html +11 -11
- nautobot/project-static/docs/development/core/controllers.html +11 -11
- nautobot/project-static/docs/development/core/docker-compose-advanced-use-cases.html +11 -11
- nautobot/project-static/docs/development/core/generic-views.html +11 -11
- nautobot/project-static/docs/development/core/getting-started.html +50 -63
- nautobot/project-static/docs/development/core/homepage.html +11 -11
- nautobot/project-static/docs/development/core/index.html +11 -11
- nautobot/project-static/docs/development/core/minikube-dev-environment-for-k8s-jobs.html +11 -11
- nautobot/project-static/docs/development/core/model-checklist.html +11 -11
- nautobot/project-static/docs/development/core/model-features.html +11 -11
- nautobot/project-static/docs/development/core/natural-keys.html +11 -11
- nautobot/project-static/docs/development/core/navigation-menu.html +11 -11
- nautobot/project-static/docs/development/core/release-checklist.html +11 -11
- nautobot/project-static/docs/development/core/role-internals.html +11 -11
- nautobot/project-static/docs/development/core/settings.html +11 -11
- nautobot/project-static/docs/development/core/style-guide.html +15 -11
- nautobot/project-static/docs/development/core/templates.html +11 -11
- nautobot/project-static/docs/development/core/testing.html +11 -11
- nautobot/project-static/docs/development/core/ui-component-framework.html +17 -22
- nautobot/project-static/docs/development/core/user-preferences.html +11 -11
- nautobot/project-static/docs/development/index.html +11 -11
- nautobot/project-static/docs/development/jobs/getting-started.html +11 -11
- nautobot/project-static/docs/development/jobs/index.html +11 -11
- nautobot/project-static/docs/development/jobs/installation.html +11 -11
- nautobot/project-static/docs/development/jobs/job-extensions.html +11 -11
- nautobot/project-static/docs/development/jobs/job-logging.html +11 -11
- nautobot/project-static/docs/development/jobs/job-patterns.html +11 -11
- nautobot/project-static/docs/development/jobs/job-structure.html +11 -11
- nautobot/project-static/docs/development/jobs/migration/from-v1.html +11 -11
- nautobot/project-static/docs/development/jobs/testing.html +11 -11
- nautobot/project-static/docs/index.html +11 -11
- nautobot/project-static/docs/objects.inv +0 -0
- nautobot/project-static/docs/overview/application_stack.html +11 -11
- nautobot/project-static/docs/overview/design_philosophy.html +11 -11
- nautobot/project-static/docs/release-notes/index.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.0.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.1.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.2.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.3.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.4.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.5.html +11 -11
- nautobot/project-static/docs/release-notes/version-1.6.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.0.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.1.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.2.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.3.html +11 -11
- nautobot/project-static/docs/release-notes/version-2.4.html +418 -11
- nautobot/project-static/docs/search/search_index.json +1 -1
- nautobot/project-static/docs/sitemap.xml +300 -300
- nautobot/project-static/docs/sitemap.xml.gz +0 -0
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/ldap.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/remote.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/authentication/sso.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/index.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/redis.html +11 -11
- nautobot/project-static/docs/user-guide/administration/configuration/settings.html +38 -11
- nautobot/project-static/docs/user-guide/administration/configuration/time-zones.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/celery-queues.html +89 -14
- nautobot/project-static/docs/user-guide/administration/guides/docker.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/health-checks.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/permissions.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/prometheus-metrics.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/replicating-nautobot.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/request-profiling.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/s3-django-storage.html +11 -11
- nautobot/project-static/docs/user-guide/administration/guides/selinux-troubleshooting.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/app-install.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/external-authentication.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/http-server.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/index.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/install_system.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/nautobot.html +11 -11
- nautobot/project-static/docs/user-guide/administration/installation/services.html +11 -11
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-netbox.html +11 -11
- nautobot/project-static/docs/user-guide/administration/migration/migrating-from-postgresql.html +11 -11
- nautobot/project-static/docs/user-guide/administration/security/index.html +11 -11
- nautobot/project-static/docs/user-guide/administration/security/notices.html +11 -11
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-server.html +11 -11
- nautobot/project-static/docs/user-guide/administration/tools/nautobot-shell.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/database-backup.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/after-you-upgrade.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/before-you-upgrade.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/for-developers.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/index.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/ipam/whats-changed.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/region-and-site-data-migration-guide.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/from-v1/upgrading-from-nautobot-v1.html +11 -11
- nautobot/project-static/docs/user-guide/administration/upgrading/upgrading.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuit.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittermination.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/circuittype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/provider.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/circuits/providernetwork.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloud.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudaccount.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetwork.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudnetworkprefixassignment.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudresourcetype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservice.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/cloud/cloudservicenetworkassignment.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/cable.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/consoleserverporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controller.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/controllermanageddevicegroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/device.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebay.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicebaytemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicefamily.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/deviceredundancygroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/devicetype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/frontporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interface.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfaceredundancygroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/interfacetemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/inventoryitem.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/location.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/locationtype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/manufacturer.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/module.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebay.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulebaytemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/modulefamily.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/moduletype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/platform.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerfeed.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlet.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/poweroutlettemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerpanel.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/powerporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rack.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackgroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rackreservation.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearport.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/rearporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareimagefile.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/softwareversion.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualchassis.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/dcim/virtualdevicecontext.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontext.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/extras/configcontextschema.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/extras/contact.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/extras/team.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/ipaddress.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/namespace.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/prefix.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/rir.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/routetarget.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/service.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlan.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vlangroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/ipam/vrf.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/overview/introduction.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenant.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/tenancy/tenantgroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/cluster.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustergroup.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/clustertype.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/virtualmachine.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/virtualization/vminterface.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/wireless/index.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/wireless/radioprofile.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/wireless/supporteddatarate.html +11 -11
- nautobot/project-static/docs/user-guide/core-data-model/wireless/wirelessnetwork.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/contacts-and-teams.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/custom-fields.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-devices.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/creating-location-types-and-locations.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/index.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/interfaces.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/ipam.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/platforms.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/search-bar.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/tenants.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/getting-started/vlans-and-vlan-groups.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/git-data-source.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/graphql.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/ip-address-merge-tool.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/relationships.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/software-image-files-and-versions.html +11 -11
- nautobot/project-static/docs/user-guide/feature-guides/wireless-networks-and-controllers.html +11 -11
- nautobot/project-static/docs/user-guide/index.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/change-logging.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/computedfield.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/customfield.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/customlink.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/dynamicgroup.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/events.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/exporttemplate.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/externalintegration.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/gitrepository.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/graphql.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/graphqlquery.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/imageattachment.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/index.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/job-scheduling-and-approvals.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobbutton.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobhook.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/jobqueue.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/kubernetes-job-support.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/managing-jobs.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/jobs/models.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/napalm.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/note.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/objectmetadata.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/relationship.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rendering-jinja-templates.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/authentication.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/filtering.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/overview.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/rest-api/ui-related-endpoints.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/role.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/savedview.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/secret.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/staticgroupassociation.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/status.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/tag.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/template-filters.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/users/objectpermission.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/users/token.html +11 -11
- nautobot/project-static/docs/user-guide/platform-functionality/webhook.html +11 -11
- nautobot/project-static/img/nautobot_icon.svg +32 -34
- nautobot/project-static/js/table_sorting_indicator.js +0 -2
- nautobot/tenancy/templates/tenancy/tenant.html +1 -7
- nautobot/tenancy/views.py +13 -0
- nautobot/users/templates/users/api_tokens.html +4 -4
- nautobot/users/templates/users/base.html +28 -28
- nautobot/virtualization/templates/virtualization/cluster.html +64 -64
- nautobot/virtualization/templates/virtualization/inc/virtualmachine_vminterface_filter.html +8 -0
- nautobot/virtualization/templates/virtualization/virtualmachine_component_add.html +25 -25
- nautobot/virtualization/templates/virtualization/virtualmachine_retrieve.html +1 -251
- nautobot/virtualization/templates/virtualization/vminterface.html +70 -70
- nautobot/virtualization/urls.py +0 -12
- nautobot/virtualization/views.py +158 -54
- nautobot/wireless/templates/wireless/wirelessnetwork_create.html +13 -13
- nautobot/wireless/tests/integration/test_radio_profile.py +1 -1
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/METADATA +4 -4
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/RECORD +623 -607
- nautobot/core/templates/inc/breadcrumbs.html +0 -14
- nautobot/ipam/templates/ipam/prefix_ipaddresses.html +0 -11
- nautobot/ipam/templates/ipam/prefix_prefixes.html +0 -11
- nautobot/project-static/docs/requirements.txt +0 -14
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/LICENSE.txt +0 -0
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/NOTICE +0 -0
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/WHEEL +0 -0
- {nautobot-2.4.17.dist-info → nautobot-2.4.19.dist-info}/entry_points.txt +0 -0
nautobot/core/utils/requests.py
CHANGED
|
@@ -156,7 +156,7 @@ def normalize_querydict(querydict, form_class=None, filterset=None):
|
|
|
156
156
|
does not inherently preserve multiple values as lists.
|
|
157
157
|
|
|
158
158
|
Args:
|
|
159
|
-
querydict (QueryDict): The QueryDict to be normalized.
|
|
159
|
+
querydict (QueryDict): The QueryDict or dictionary as produced by `convert_querydict_to_dict` to be normalized.
|
|
160
160
|
form_class (forms.Form, optional): A form class to identify fields that should be treated as
|
|
161
161
|
lists (e.g., `MultipleChoiceField` or `ModelMultipleChoiceField`).
|
|
162
162
|
filterset (django_filters.FilterSet, optional): A FilterSet instance to identify filters that
|
|
@@ -171,7 +171,13 @@ def normalize_querydict(querydict, form_class=None, filterset=None):
|
|
|
171
171
|
result = {}
|
|
172
172
|
|
|
173
173
|
if querydict:
|
|
174
|
-
|
|
174
|
+
# check if true QueryDict or standard dict in format of querydict, e.g. from `convert_querydict_to_dict`
|
|
175
|
+
if hasattr(querydict, "lists"):
|
|
176
|
+
items = querydict.lists()
|
|
177
|
+
else:
|
|
178
|
+
items = querydict.items()
|
|
179
|
+
|
|
180
|
+
for key, value_list in items:
|
|
175
181
|
if len(value_list) > 1:
|
|
176
182
|
# More than one value in the querydict for this key, so keep it as a list
|
|
177
183
|
# TODO: we could check here and de-listify value_list if the form_class field is a single-value one?
|
|
@@ -198,3 +204,22 @@ def add_nautobot_version_query_param_to_url(url):
|
|
|
198
204
|
params["version"] = settings.VERSION
|
|
199
205
|
updated_query = urlencode(params, doseq=True)
|
|
200
206
|
return parsed_url._replace(query=updated_query).geturl()
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def convert_querydict_to_dict(request_querydict):
|
|
210
|
+
"""
|
|
211
|
+
Convert QueryDict to standard json serializable dictionary.
|
|
212
|
+
|
|
213
|
+
This is useful when you want to serialize a QueryDict to JSON format such as
|
|
214
|
+
when sending to a Job form or sending it over an API. This is not the same as
|
|
215
|
+
`normalize_querydict` which preserves single values as singletons and multi-values
|
|
216
|
+
as lists. This function preserves all values as lists.
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
request_querydict (QueryDict): QueryDict to convert.
|
|
220
|
+
|
|
221
|
+
Examples:
|
|
222
|
+
>>> convert_querydict_to_dict(QueryDict('foo=1&bar=2&bar=3&baz='))
|
|
223
|
+
>>> {'foo': ['1'], 'bar': ['2', '3'], 'baz': ['']}
|
|
224
|
+
"""
|
|
225
|
+
return {key: value for key, value in request_querydict.lists()} # pylint: disable=unnecessary-comprehension
|
nautobot/core/views/__init__.py
CHANGED
|
@@ -15,6 +15,7 @@ from django.contrib import messages
|
|
|
15
15
|
from django.contrib.auth.decorators import permission_required
|
|
16
16
|
from django.contrib.auth.mixins import AccessMixin, LoginRequiredMixin, UserPassesTestMixin
|
|
17
17
|
from django.contrib.contenttypes.models import ContentType
|
|
18
|
+
from django.core.cache import cache
|
|
18
19
|
from django.http import HttpResponseForbidden, HttpResponseServerError, JsonResponse
|
|
19
20
|
from django.shortcuts import get_object_or_404, render
|
|
20
21
|
from django.template import loader, RequestContext, Template
|
|
@@ -51,6 +52,11 @@ from nautobot.core.releases import get_latest_release
|
|
|
51
52
|
from nautobot.core.utils.config import get_settings_or_config
|
|
52
53
|
from nautobot.core.utils.lookup import get_route_for_model
|
|
53
54
|
from nautobot.core.utils.permissions import get_permission_for_model
|
|
55
|
+
from nautobot.core.views.utils import (
|
|
56
|
+
generate_latest_with_cache,
|
|
57
|
+
is_metrics_experimental_caching_enabled,
|
|
58
|
+
METRICS_CACHE_KEY,
|
|
59
|
+
)
|
|
54
60
|
from nautobot.extras.forms import GraphQLQueryForm
|
|
55
61
|
from nautobot.extras.models import FileProxy, GraphQLQuery, Status
|
|
56
62
|
from nautobot.extras.registry import registry
|
|
@@ -435,8 +441,17 @@ class NautobotAppMetricsCollector(Collector):
|
|
|
435
441
|
def collect(self):
|
|
436
442
|
"""Collect metrics from plugins."""
|
|
437
443
|
start = time.time()
|
|
438
|
-
|
|
439
|
-
|
|
444
|
+
cached_lines = cache.get(METRICS_CACHE_KEY)
|
|
445
|
+
if not is_metrics_experimental_caching_enabled() or not cached_lines:
|
|
446
|
+
# If caching is disabled or no cache is found, generate metrics
|
|
447
|
+
for metric_generator in registry["app_metrics"]:
|
|
448
|
+
yield from metric_generator()
|
|
449
|
+
else:
|
|
450
|
+
# We stash the cached lines on the instance of the collector so that we can
|
|
451
|
+
# avoid a potential race condition where the cache expires between
|
|
452
|
+
# the time we check for it and the time we go to use it
|
|
453
|
+
# in generate_latest_with_cache()
|
|
454
|
+
self.local_cache = cached_lines
|
|
440
455
|
gauge = GaugeMetricFamily("nautobot_app_metrics_processing_ms", "Time in ms to generate the app metrics")
|
|
441
456
|
duration = time.time() - start
|
|
442
457
|
gauge.add_metric([], format(duration * 1000, ".5f"))
|
|
@@ -485,7 +500,13 @@ class NautobotMetricsView(APIView):
|
|
|
485
500
|
except ValueError:
|
|
486
501
|
# Collector already registered, we are running without multiprocessing
|
|
487
502
|
pass
|
|
488
|
-
|
|
503
|
+
|
|
504
|
+
if is_metrics_experimental_caching_enabled():
|
|
505
|
+
# Use the vendored version of generate_latest with Caching support
|
|
506
|
+
metrics_page = generate_latest_with_cache(prometheus_registry)
|
|
507
|
+
else:
|
|
508
|
+
# Use the original version of generate_latest to generate the metrics
|
|
509
|
+
metrics_page = generate_latest(prometheus_registry)
|
|
489
510
|
return Response(metrics_page, content_type=CONTENT_TYPE_LATEST)
|
|
490
511
|
|
|
491
512
|
|
nautobot/core/views/generic.py
CHANGED
|
@@ -44,15 +44,22 @@ from nautobot.core.templatetags.helpers import bettertitle, validated_viewname
|
|
|
44
44
|
from nautobot.core.utils.config import get_settings_or_config
|
|
45
45
|
from nautobot.core.utils.permissions import get_permission_for_model
|
|
46
46
|
from nautobot.core.utils.requests import (
|
|
47
|
+
convert_querydict_to_dict,
|
|
47
48
|
convert_querydict_to_factory_formset_acceptable_querydict,
|
|
48
49
|
get_filterable_params_from_filter_params,
|
|
49
50
|
normalize_querydict,
|
|
50
51
|
)
|
|
51
|
-
from nautobot.core.views.mixins import
|
|
52
|
+
from nautobot.core.views.mixins import (
|
|
53
|
+
BulkEditAndBulkDeleteModelMixin,
|
|
54
|
+
GetReturnURLMixin,
|
|
55
|
+
ObjectPermissionRequiredMixin,
|
|
56
|
+
UIComponentsMixin,
|
|
57
|
+
)
|
|
52
58
|
from nautobot.core.views.paginator import EnhancedPaginator, get_paginate_count
|
|
53
59
|
from nautobot.core.views.utils import (
|
|
54
60
|
check_filter_for_display,
|
|
55
61
|
common_detail_view_context,
|
|
62
|
+
get_bulk_queryset_from_view,
|
|
56
63
|
get_csv_form_fields_from_serializer_class,
|
|
57
64
|
get_saved_views_for_user,
|
|
58
65
|
handle_protectederror,
|
|
@@ -63,7 +70,7 @@ from nautobot.core.views.utils import (
|
|
|
63
70
|
from nautobot.extras.models import ExportTemplate, SavedView, UserSavedViewAssociation
|
|
64
71
|
|
|
65
72
|
|
|
66
|
-
class GenericView(LoginRequiredMixin, View):
|
|
73
|
+
class GenericView(UIComponentsMixin, LoginRequiredMixin, View):
|
|
67
74
|
"""
|
|
68
75
|
Base class for non-object-related views.
|
|
69
76
|
|
|
@@ -71,7 +78,7 @@ class GenericView(LoginRequiredMixin, View):
|
|
|
71
78
|
"""
|
|
72
79
|
|
|
73
80
|
|
|
74
|
-
class ObjectView(ObjectPermissionRequiredMixin, View):
|
|
81
|
+
class ObjectView(UIComponentsMixin, ObjectPermissionRequiredMixin, View):
|
|
75
82
|
"""
|
|
76
83
|
Retrieve a single object for display.
|
|
77
84
|
|
|
@@ -115,21 +122,28 @@ class ObjectView(ObjectPermissionRequiredMixin, View):
|
|
|
115
122
|
Generic GET handler for accessing an object.
|
|
116
123
|
"""
|
|
117
124
|
instance = get_object_or_404(self.queryset, **kwargs)
|
|
125
|
+
model = self.queryset.model
|
|
118
126
|
content_type = ContentType.objects.get_for_model(self.queryset.model)
|
|
119
127
|
context = {
|
|
120
128
|
"object": instance,
|
|
121
129
|
"content_type": content_type,
|
|
122
|
-
"verbose_name":
|
|
123
|
-
"verbose_name_plural":
|
|
130
|
+
"verbose_name": model._meta.verbose_name,
|
|
131
|
+
"verbose_name_plural": model._meta.verbose_name_plural,
|
|
124
132
|
"object_detail_content": self.object_detail_content,
|
|
133
|
+
"breadcrumbs": self.get_breadcrumbs(model, view_type=""),
|
|
125
134
|
**common_detail_view_context(request, instance),
|
|
126
135
|
**self.get_extra_context(request, instance),
|
|
127
136
|
}
|
|
128
137
|
|
|
138
|
+
# Some of the legacy views overriding title in `get_extra_context` method.
|
|
139
|
+
# But if not, we will generate the default `title` using the default `Titles` class or one set in class under `view_titles`.
|
|
140
|
+
if context.get("title") is None:
|
|
141
|
+
context["title"] = self.get_view_titles(model, view_type="").render(context)
|
|
142
|
+
|
|
129
143
|
return render(request, self.get_template_name(), context)
|
|
130
144
|
|
|
131
145
|
|
|
132
|
-
class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
146
|
+
class ObjectListView(UIComponentsMixin, ObjectPermissionRequiredMixin, View):
|
|
133
147
|
"""
|
|
134
148
|
List a series of objects.
|
|
135
149
|
|
|
@@ -378,11 +392,13 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
378
392
|
"dynamic_filter_form": dynamic_filter_form,
|
|
379
393
|
"search_form": search_form,
|
|
380
394
|
"list_url": list_url,
|
|
381
|
-
"title": bettertitle(model._meta.verbose_name_plural),
|
|
382
395
|
"new_changes_not_applied": new_changes_not_applied,
|
|
383
396
|
"current_saved_view": current_saved_view,
|
|
384
397
|
"saved_views": saved_views,
|
|
385
398
|
"model": model,
|
|
399
|
+
"verbose_name_plural": model._meta.verbose_name_plural,
|
|
400
|
+
"view_action": "list",
|
|
401
|
+
"breadcrumbs": self.get_breadcrumbs(model),
|
|
386
402
|
}
|
|
387
403
|
|
|
388
404
|
# `extra_context()` would require `request` access, however `request` parameter cannot simply be
|
|
@@ -392,6 +408,11 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
392
408
|
setattr(self, "request", request)
|
|
393
409
|
context.update(self.extra_context())
|
|
394
410
|
|
|
411
|
+
# Some of the legacy views overriding title in `extra_context` method.
|
|
412
|
+
# But if not, we will generate the default `title` using the default `Titles` class or one set in class under `view_titles`.
|
|
413
|
+
if context.get("title") is None:
|
|
414
|
+
context["title"] = self.get_view_titles(model).render(context)
|
|
415
|
+
|
|
395
416
|
return render(request, self.template_name, context)
|
|
396
417
|
|
|
397
418
|
def alter_queryset(self, request):
|
|
@@ -402,7 +423,7 @@ class ObjectListView(ObjectPermissionRequiredMixin, View):
|
|
|
402
423
|
return {}
|
|
403
424
|
|
|
404
425
|
|
|
405
|
-
class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
426
|
+
class ObjectEditView(UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
406
427
|
"""
|
|
407
428
|
Create or edit a single object.
|
|
408
429
|
|
|
@@ -550,7 +571,7 @@ class ObjectEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
550
571
|
)
|
|
551
572
|
|
|
552
573
|
|
|
553
|
-
class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
574
|
+
class ObjectDeleteView(UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
554
575
|
"""
|
|
555
576
|
Delete a single object.
|
|
556
577
|
|
|
@@ -627,7 +648,7 @@ class ObjectDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
627
648
|
)
|
|
628
649
|
|
|
629
650
|
|
|
630
|
-
class BulkCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
651
|
+
class BulkCreateView(UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
631
652
|
"""
|
|
632
653
|
Create new objects in bulk.
|
|
633
654
|
|
|
@@ -741,7 +762,7 @@ class BulkCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
741
762
|
)
|
|
742
763
|
|
|
743
764
|
|
|
744
|
-
class ObjectImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
765
|
+
class ObjectImportView(UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
745
766
|
"""
|
|
746
767
|
Import a single object (YAML or JSON format).
|
|
747
768
|
|
|
@@ -888,7 +909,9 @@ class ObjectImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
888
909
|
)
|
|
889
910
|
|
|
890
911
|
|
|
891
|
-
class BulkImportView(
|
|
912
|
+
class BulkImportView(
|
|
913
|
+
UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|
914
|
+
): # 3.0 TODO: remove as it's no longer used
|
|
892
915
|
"""
|
|
893
916
|
Import objects in bulk (CSV format).
|
|
894
917
|
|
|
@@ -997,7 +1020,9 @@ class BulkImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View): #
|
|
|
997
1020
|
)
|
|
998
1021
|
|
|
999
1022
|
|
|
1000
|
-
class BulkEditView(
|
|
1023
|
+
class BulkEditView(
|
|
1024
|
+
UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditAndBulkDeleteModelMixin, View
|
|
1025
|
+
):
|
|
1001
1026
|
"""
|
|
1002
1027
|
Edit objects in bulk.
|
|
1003
1028
|
|
|
@@ -1033,15 +1058,19 @@ class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditAnd
|
|
|
1033
1058
|
if self.queryset is None or self.form is None or self.table is None:
|
|
1034
1059
|
raise RuntimeError("self.queryset, self.form, and self.table must not be None")
|
|
1035
1060
|
model = self.queryset.model
|
|
1036
|
-
|
|
1061
|
+
pk_list = list(request.POST.getlist("pk"))
|
|
1062
|
+
edit_all = bool(self.request.POST.get("_all"))
|
|
1063
|
+
saved_view_id = request.GET.get("saved_view", "")
|
|
1064
|
+
|
|
1065
|
+
self.key_params = {
|
|
1066
|
+
"content_type": ContentType.objects.get_for_model(model),
|
|
1067
|
+
"edit_all": edit_all,
|
|
1068
|
+
"filter_query_params": convert_querydict_to_dict(request.GET),
|
|
1069
|
+
"pk_list": pk_list,
|
|
1070
|
+
"saved_view_id": saved_view_id,
|
|
1071
|
+
}
|
|
1037
1072
|
|
|
1038
|
-
|
|
1039
|
-
if edit_all:
|
|
1040
|
-
pk_list = []
|
|
1041
|
-
queryset = self._get_bulk_edit_delete_all_queryset(request)
|
|
1042
|
-
else:
|
|
1043
|
-
pk_list = request.POST.getlist("pk")
|
|
1044
|
-
queryset = self.queryset.filter(pk__in=pk_list)
|
|
1073
|
+
queryset = get_bulk_queryset_from_view(user=request.user, action="change", **self.key_params)
|
|
1045
1074
|
|
|
1046
1075
|
if "_apply" in request.POST:
|
|
1047
1076
|
form = self.form(model, request.POST, edit_all=edit_all) # pylint: disable=not-callable
|
|
@@ -1049,7 +1078,7 @@ class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditAnd
|
|
|
1049
1078
|
|
|
1050
1079
|
if form.is_valid():
|
|
1051
1080
|
logger.debug("Form validation was successful")
|
|
1052
|
-
return self.send_bulk_edit_objects_to_job(request, form.cleaned_data
|
|
1081
|
+
return self.send_bulk_edit_objects_to_job(request, form.cleaned_data)
|
|
1053
1082
|
else:
|
|
1054
1083
|
logger.debug("Form validation failed")
|
|
1055
1084
|
|
|
@@ -1093,7 +1122,7 @@ class BulkEditView(GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditAnd
|
|
|
1093
1122
|
return {}
|
|
1094
1123
|
|
|
1095
1124
|
|
|
1096
|
-
class BulkRenameView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
1125
|
+
class BulkRenameView(UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
1097
1126
|
"""
|
|
1098
1127
|
An extendable view for renaming objects in bulk.
|
|
1099
1128
|
"""
|
|
@@ -1193,7 +1222,9 @@ class BulkRenameView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
|
1193
1222
|
return ""
|
|
1194
1223
|
|
|
1195
1224
|
|
|
1196
|
-
class BulkDeleteView(
|
|
1225
|
+
class BulkDeleteView(
|
|
1226
|
+
UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditAndBulkDeleteModelMixin, View
|
|
1227
|
+
):
|
|
1197
1228
|
"""
|
|
1198
1229
|
Delete objects in bulk.
|
|
1199
1230
|
|
|
@@ -1221,15 +1252,19 @@ class BulkDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditA
|
|
|
1221
1252
|
if self.queryset is None or self.table is None:
|
|
1222
1253
|
raise RuntimeError("self.queryset and self.table must not be None")
|
|
1223
1254
|
model = self.queryset.model
|
|
1224
|
-
|
|
1255
|
+
pk_list = list(request.POST.getlist("pk"))
|
|
1256
|
+
delete_all = bool(request.POST.get("_all"))
|
|
1257
|
+
saved_view_id = request.GET.get("saved_view", "")
|
|
1225
1258
|
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1259
|
+
self.key_params = {
|
|
1260
|
+
"content_type": ContentType.objects.get_for_model(model),
|
|
1261
|
+
"delete_all": delete_all,
|
|
1262
|
+
"filter_query_params": convert_querydict_to_dict(request.GET),
|
|
1263
|
+
"pk_list": pk_list,
|
|
1264
|
+
"saved_view_id": saved_view_id,
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
queryset = get_bulk_queryset_from_view(user=request.user, action="delete", **self.key_params)
|
|
1233
1268
|
|
|
1234
1269
|
form_cls = self.get_form()
|
|
1235
1270
|
|
|
@@ -1241,7 +1276,7 @@ class BulkDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditA
|
|
|
1241
1276
|
|
|
1242
1277
|
if form.is_valid():
|
|
1243
1278
|
logger.debug("Form validation was successful")
|
|
1244
|
-
return self.send_bulk_delete_objects_to_job(request
|
|
1279
|
+
return self.send_bulk_delete_objects_to_job(request)
|
|
1245
1280
|
else:
|
|
1246
1281
|
logger.debug("Form validation failed")
|
|
1247
1282
|
|
|
@@ -1304,7 +1339,7 @@ class BulkDeleteView(GetReturnURLMixin, ObjectPermissionRequiredMixin, BulkEditA
|
|
|
1304
1339
|
|
|
1305
1340
|
|
|
1306
1341
|
# TODO: Replace with BulkCreateView
|
|
1307
|
-
class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
1342
|
+
class ComponentCreateView(UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
1308
1343
|
"""
|
|
1309
1344
|
Add one or more components (e.g. interfaces, console ports, etc.) to a Device or VirtualMachine.
|
|
1310
1345
|
"""
|
|
@@ -1410,7 +1445,7 @@ class ComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View
|
|
|
1410
1445
|
)
|
|
1411
1446
|
|
|
1412
1447
|
|
|
1413
|
-
class BulkComponentCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
1448
|
+
class BulkComponentCreateView(UIComponentsMixin, GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|
1414
1449
|
"""
|
|
1415
1450
|
Add one or more components (e.g. interfaces, console ports, etc.) to a set of Devices or VirtualMachines.
|
|
1416
1451
|
"""
|