Merge branch 'develop' into feature

This commit is contained in:
Arthur 2024-06-06 11:17:43 -07:00
commit 1952d3e63a
30 changed files with 28059 additions and 24523 deletions

View File

@ -26,7 +26,7 @@ body:
attributes:
label: NetBox Version
description: What version of NetBox are you currently running?
placeholder: v4.0.3
placeholder: v4.0.5
validations:
required: true
- type: dropdown

View File

@ -14,7 +14,7 @@ body:
attributes:
label: NetBox version
description: What version of NetBox are you currently running?
placeholder: v4.0.3
placeholder: v4.0.5
validations:
required: true
- type: dropdown

View File

@ -323,6 +323,7 @@
"100base-tx",
"100base-t1",
"1000base-t",
"1000base-tx",
"2.5gbase-t",
"5gbase-t",
"10gbase-t",

View File

@ -65,12 +65,6 @@ class AnotherCustomScript(Script):
script_order = (MyCustomScript, AnotherCustomScript)
```
## Module Attributes
### `name`
You can define `name` within a script module (the Python file which contains one or more scripts) to set the module name. If `name` is not defined, the module's file name will be used.
## Script Attributes
Script attributes are defined under a class named `Meta` within the script. These are optional, but encouraged.

View File

@ -1,18 +1,34 @@
# NetBox v4.0
## v4.0.4 (FUTURE)
## v4.0.6 (FUTURE)
---
## v4.0.5 (2024-06-06)
### Enhancements
* [#14810](https://github.com/netbox-community/netbox/issues/14810) - Enable contact assignment for services
* [#15489](https://github.com/netbox-community/netbox/issues/15489) - Add 1000Base-TX interface type
* [#15873](https://github.com/netbox-community/netbox/issues/15873) - Improve readability of allocates resource numbers for clusters
* [#16290](https://github.com/netbox-community/netbox/issues/16290) - Capture entire object in changelog data (but continue to display only non-internal attributes)
* [#16353](https://github.com/netbox-community/netbox/issues/16353) - Enable plugins to extend object change view with custom content
### Bug Fixes
* [#13422](https://github.com/netbox-community/netbox/issues/13422) - Rebuild MPTT trees for applicable models after merging staged changes
* [#14567](https://github.com/netbox-community/netbox/issues/14567) - Apply active quicksearch value when exporting "current view" from object list
* [#15194](https://github.com/netbox-community/netbox/issues/15194) - Avoid enqueuing duplicate event triggers for a modified object
* [#16039](https://github.com/netbox-community/netbox/issues/16039) - Fix row highlighting for front & rear port connections under device view
* [#16050](https://github.com/netbox-community/netbox/issues/16050) - Fix display of names & descriptions defined for custom scripts
* [#16083](https://github.com/netbox-community/netbox/issues/16083) - Disable font ligatures to avoid peculiarities in rendered text
* [#16202](https://github.com/netbox-community/netbox/issues/16202) - Fix site map button URL for certain localizations
* [#16261](https://github.com/netbox-community/netbox/issues/16261) - Fix GraphQL filtering for certain multi-value filters
* [#16286](https://github.com/netbox-community/netbox/issues/16286) - Fix global search support for provider accounts
* [#16312](https://github.com/netbox-community/netbox/issues/16312) - Fix object list navigation for dashboard widgets
* [#16315](https://github.com/netbox-community/netbox/issues/16315) - Fix filtering change log & journal entries by object type in UI
* [#16376](https://github.com/netbox-community/netbox/issues/16376) - Update change log for the terminating object (e.g. interface) when attaching a cable
* [#16400](https://github.com/netbox-community/netbox/issues/16400) - Fix AttributeError when attempting to restore a previous configuration revision after deleting the current one
---

View File

@ -224,7 +224,7 @@ class ConfigRevisionRestoreView(ContentTypePermissionRequiredMixin, View):
for param in PARAMS:
params.append((
param.name,
current_config.data.get(param.name, None),
current_config.data.get(param.name, None) if current_config else None,
candidate_config.data.get(param.name, None)
))

View File

@ -355,11 +355,11 @@ class CableTermination(ChangeLoggedModel):
super().save(*args, **kwargs)
# Set the cable on the terminating object
termination_model = self.termination._meta.model
termination_model.objects.filter(pk=self.termination_id).update(
cable=self.cable,
cable_end=self.cable_end
)
termination = self.termination._meta.model.objects.get(pk=self.termination_id)
termination.snapshot()
termination.cable = self.cable
termination.cable_end = self.cable_end
termination.save()
def delete(self, *args, **kwargs):

View File

@ -25,7 +25,7 @@ from utilities.string import trailing_slash
# Environment setup
#
VERSION = '4.0.4-dev'
VERSION = '4.0.6-dev'
HOSTNAME = platform.node()
# Set the base directory two levels up
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@ -368,6 +368,8 @@ INSTALLED_APPS = [
'drf_spectacular',
'drf_spectacular_sidecar',
]
if not DEBUG:
INSTALLED_APPS.remove('debug_toolbar')
if not DJANGO_ADMIN_ENABLED:
INSTALLED_APPS.remove('django.contrib.admin')

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -27,10 +27,10 @@
"bootstrap": "5.3.3",
"clipboard": "2.0.11",
"flatpickr": "4.6.13",
"gridstack": "10.1.2",
"gridstack": "10.2.0",
"htmx.org": "1.9.12",
"query-string": "9.0.0",
"sass": "1.77.2",
"sass": "1.77.4",
"tom-select": "2.3.1",
"typeface-inter": "3.18.1",
"typeface-roboto-mono": "1.1.13"

View File

@ -7,38 +7,74 @@ import { isTruthy } from './util';
*/
function quickSearchEventHandler(event: Event): void {
const quicksearch = event.currentTarget as HTMLInputElement;
const clearbtn = document.getElementById("quicksearch_clear") as HTMLAnchorElement;
const clearbtn = document.getElementById('quicksearch_clear') as HTMLAnchorElement;
if (isTruthy(clearbtn)) {
if (quicksearch.value === "") {
clearbtn.classList.add("invisible");
if (quicksearch.value === '') {
clearbtn.classList.add('invisible');
} else {
clearbtn.classList.remove("invisible");
clearbtn.classList.remove('invisible');
}
}
}
/**
* Clear the existing search parameters in the link to export Current View.
*/
function clearLinkParams(): void {
const link = document.getElementById('export_current_view') as HTMLLinkElement;
const linkUpdated = link?.href.split('&')[0];
link.setAttribute('href', linkUpdated);
}
/**
* Update the Export View link to add the Quick Search parameters.
* @param event
*/
function handleQuickSearchParams(event: Event): void {
const quickSearchParameters = event.currentTarget as HTMLInputElement;
// Clear the existing search parameters
clearLinkParams();
if (quickSearchParameters != null) {
const link = document.getElementById('export_current_view') as HTMLLinkElement;
const search_parameter = `q=${quickSearchParameters.value}`;
const linkUpdated = link?.href + '&' + search_parameter;
link.setAttribute('href', linkUpdated);
}
}
/**
* Initialize Quicksearch Event listener/handlers.
*/
export function initQuickSearch(): void {
const quicksearch = document.getElementById("quicksearch") as HTMLInputElement;
const clearbtn = document.getElementById("quicksearch_clear") as HTMLAnchorElement;
const quicksearch = document.getElementById('quicksearch') as HTMLInputElement;
const clearbtn = document.getElementById('quicksearch_clear') as HTMLAnchorElement;
if (isTruthy(quicksearch)) {
quicksearch.addEventListener("keyup", quickSearchEventHandler, {
passive: true
})
quicksearch.addEventListener("search", quickSearchEventHandler, {
passive: true
})
quicksearch.addEventListener('keyup', quickSearchEventHandler, {
passive: true,
});
quicksearch.addEventListener('search', quickSearchEventHandler, {
passive: true,
});
quicksearch.addEventListener('change', handleQuickSearchParams, {
passive: true,
});
if (isTruthy(clearbtn)) {
clearbtn.addEventListener("click", async () => {
clearbtn.addEventListener(
'click',
async () => {
const search = new Event('search');
quicksearch.value = '';
await new Promise(f => setTimeout(f, 100));
quicksearch.dispatchEvent(search);
}, {
passive: true
})
clearLinkParams();
},
{
passive: true,
},
);
}
}
}

View File

@ -39,3 +39,8 @@ table a {
// Adjust table anchor link contrast as not enough contrast in dark mode
filter: brightness(110%);
}
// Override background color alpha value
[data-bs-theme=dark] ::selection {
background-color: rgba(var(--tblr-primary-rgb),.48)
}

View File

@ -1754,10 +1754,10 @@ graphql@16.8.1:
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.8.1.tgz#1930a965bef1170603702acdb68aedd3f3cf6f07"
integrity sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==
gridstack@10.1.2:
version "10.1.2"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-10.1.2.tgz#58b5ae0057a8aa5e4f6563041c4ca2def3aa4268"
integrity sha512-Nn27XGQ68WtBC513cKQQ4t/dA2uuN/xnNUU50puXEJv6IFk5SzT0Dnsq68GpopO1n0tXUKZKm1Rw7uOUMDz1KQ==
gridstack@10.2.0:
version "10.2.0"
resolved "https://registry.yarnpkg.com/gridstack/-/gridstack-10.2.0.tgz#4ba9c7ee69a730851721a9f5cb33dc55026ded1f"
integrity sha512-svKAOq/dfinpvhe/nnxdyZOOEd9qynXiOPHvL96PALE0yWChWp/6lechnqKwud0tL/rRyAfMJ6Hh/z2fS13pBA==
has-bigints@^1.0.1, has-bigints@^1.0.2:
version "1.0.2"
@ -2482,10 +2482,10 @@ safe-regex-test@^1.0.3:
es-errors "^1.3.0"
is-regex "^1.1.4"
sass@1.77.2:
version "1.77.2"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.2.tgz#18d4ed2eefc260cdc8099c5439ec1303fd5863aa"
integrity sha512-eb4GZt1C3avsX3heBNlrc7I09nyT00IUuo4eFhAbeXWU2fvA7oXI53SxODVAA+zgZCk9aunAZgO+losjR3fAwA==
sass@1.77.4:
version "1.77.4"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.4.tgz#92059c7bfc56b827c56eb116778d157ec017a5cd"
integrity sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"

View File

@ -5,7 +5,7 @@
<div class="row mb-3">
<div class="col col-md-12">
<div class="card">
<div class="card-body table-responsive">
<div class="table-responsive">
{% render_table table 'inc/table.html' %}
{% include 'inc/paginator.html' with paginator=table.paginator page=table.page %}
</div>

View File

@ -4,7 +4,7 @@
{% load log_levels %}
{% load i18n %}
{% block title %}{{ script }}{% endblock %}
{% block title %}{{ script.python_class.name }}{% endblock %}
{% block object_identifier %}
{{ script.full_name }}
@ -17,7 +17,7 @@
{% block subtitle %}
<div class="text-secondary fs-5">
{{ script.Meta.description|markdown }}
{{ script.python_class.Meta.description|markdown }}
</div>
{% endblock subtitle %}

View File

@ -56,15 +56,15 @@
<tr>
<td>
{% if script.is_executable %}
<a href="{% url 'extras:script' script.pk %}" id="{{ script.module }}.{{ script.class_name }}">{{ script.name }}</a>
<a href="{% url 'extras:script' script.pk %}" id="{{ script.module }}.{{ script.class_name }}">{{ script.python_class.name }}</a>
{% else %}
<a href="{% url 'extras:script_jobs' script.pk %}" id="{{ script.module }}.{{ script.class_name }}">{{ script.name }}</a>
<a href="{% url 'extras:script_jobs' script.pk %}" id="{{ script.module }}.{{ script.class_name }}">{{ script.python_class.name }}</a>
<span class="text-danger">
<i class="mdi mdi-alert" title="{% trans "Script is no longer present in the source file" %}"></i>
</span>
{% endif %}
</td>
<td>{{ script.description|markdown|placeholder }}</td>
<td>{{ script.python_class.Meta.description|markdown|placeholder }}</td>
{% if last_job %}
<td>
<a href="{% url 'extras:script_result' job_pk=last_job.pk %}">{{ last_job.created|isodatetime }}</a>

View File

@ -59,7 +59,7 @@
<th scope="row"><i class="mdi mdi-chip"></i> {% trans "Memory" %}</th>
<td>
{% if memory_sum %}
{{ memory_sum|humanize_megabytes }}
<span title={{ memory_sum }}>{{ memory_sum|humanize_megabytes }}</span>
{% else %}
{{ ''|placeholder }}
{% endif %}

View File

@ -125,7 +125,7 @@
<th scope="row"><i class="mdi mdi-chip"></i> {% trans "Memory" %}</th>
<td>
{% if object.memory %}
{{ object.memory|humanize_megabytes }}
<span title={{ object.memory }}>{{ object.memory|humanize_megabytes }}</span>
{% else %}
{{ ''|placeholder }}
{% endif %}

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-06-04 05:02+0000\n"
"POT-Creation-Date: 2024-06-05 05:02+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -965,7 +965,7 @@ msgstr ""
#: netbox/extras/forms/filtersets.py:143 netbox/extras/forms/filtersets.py:183
#: netbox/extras/forms/filtersets.py:199 netbox/extras/forms/filtersets.py:230
#: netbox/extras/forms/filtersets.py:254 netbox/extras/forms/filtersets.py:450
#: netbox/extras/forms/filtersets.py:488 netbox/ipam/forms/filtersets.py:99
#: netbox/extras/forms/filtersets.py:485 netbox/ipam/forms/filtersets.py:99
#: netbox/ipam/forms/filtersets.py:266 netbox/ipam/forms/filtersets.py:307
#: netbox/ipam/forms/filtersets.py:382 netbox/ipam/forms/filtersets.py:475
#: netbox/ipam/forms/filtersets.py:534 netbox/ipam/forms/filtersets.py:552
@ -1577,9 +1577,9 @@ msgid "Creation"
msgstr ""
#: netbox/core/forms/filtersets.py:71 netbox/extras/forms/filtersets.py:470
#: netbox/extras/forms/filtersets.py:513 netbox/extras/tables/tables.py:183
#: netbox/extras/forms/filtersets.py:510 netbox/extras/tables/tables.py:183
#: netbox/extras/tables/tables.py:504 netbox/templates/core/job.html:20
#: netbox/templates/extras/objectchange.html:51
#: netbox/templates/extras/objectchange.html:52
#: netbox/tenancy/tables/contacts.py:90 netbox/vpn/tables/l2vpn.py:59
msgid "Object Type"
msgstr ""
@ -1619,9 +1619,9 @@ msgstr ""
#: netbox/core/forms/filtersets.py:123 netbox/dcim/forms/bulk_edit.py:361
#: netbox/dcim/forms/filtersets.py:353 netbox/dcim/forms/filtersets.py:397
#: netbox/dcim/forms/model_forms.py:258 netbox/extras/forms/filtersets.py:465
#: netbox/extras/forms/filtersets.py:508
#: netbox/extras/forms/filtersets.py:505
#: netbox/templates/dcim/rackreservation.html:58
#: netbox/templates/extras/objectchange.html:35
#: netbox/templates/extras/objectchange.html:36
#: netbox/templates/extras/savedfilter.html:21
#: netbox/templates/inc/user_menu.html:15 netbox/templates/users/token.html:21
#: netbox/templates/users/user.html:6 netbox/templates/users/user.html:14
@ -1976,7 +1976,7 @@ msgstr ""
#: netbox/extras/tables/tables.py:509 netbox/extras/tables/tables.py:574
#: netbox/netbox/tables/tables.py:243 netbox/templates/extras/eventrule.html:84
#: netbox/templates/extras/journalentry.html:18
#: netbox/templates/extras/objectchange.html:57
#: netbox/templates/extras/objectchange.html:58
#: netbox/tenancy/tables/contacts.py:93 netbox/vpn/tables/l2vpn.py:64
msgid "Object"
msgstr ""
@ -4172,7 +4172,7 @@ msgid "Connection"
msgstr ""
#: netbox/dcim/forms/filtersets.py:1254 netbox/extras/forms/bulk_edit.py:316
#: netbox/extras/forms/bulk_import.py:242 netbox/extras/forms/filtersets.py:476
#: netbox/extras/forms/bulk_import.py:242 netbox/extras/forms/filtersets.py:473
#: netbox/extras/forms/model_forms.py:551 netbox/extras/tables/tables.py:512
#: netbox/templates/extras/journalentry.html:30
msgid "Kind"
@ -7144,23 +7144,23 @@ msgstr ""
msgid "Tenant groups"
msgstr ""
#: netbox/extras/forms/filtersets.py:454 netbox/extras/forms/filtersets.py:492
#: netbox/extras/forms/filtersets.py:454 netbox/extras/forms/filtersets.py:489
msgid "After"
msgstr ""
#: netbox/extras/forms/filtersets.py:459 netbox/extras/forms/filtersets.py:497
#: netbox/extras/forms/filtersets.py:459 netbox/extras/forms/filtersets.py:494
msgid "Before"
msgstr ""
#: netbox/extras/forms/filtersets.py:487 netbox/extras/tables/tables.py:456
#: netbox/extras/forms/filtersets.py:484 netbox/extras/tables/tables.py:456
#: netbox/extras/tables/tables.py:542 netbox/extras/tables/tables.py:567
#: netbox/templates/extras/objectchange.html:31
#: netbox/templates/extras/objectchange.html:32
msgid "Time"
msgstr ""
#: netbox/extras/forms/filtersets.py:501 netbox/extras/forms/model_forms.py:282
#: netbox/extras/forms/filtersets.py:498 netbox/extras/forms/model_forms.py:282
#: netbox/extras/tables/tables.py:470 netbox/templates/extras/eventrule.html:77
#: netbox/templates/extras/objectchange.html:45
#: netbox/templates/extras/objectchange.html:46
msgid "Action"
msgstr ""
@ -8256,7 +8256,7 @@ msgid "Full Name"
msgstr ""
#: netbox/extras/tables/tables.py:483
#: netbox/templates/extras/objectchange.html:67
#: netbox/templates/extras/objectchange.html:68
msgid "Request ID"
msgstr ""
@ -10275,7 +10275,7 @@ msgid "Journal Entries"
msgstr ""
#: netbox/netbox/navigation/menu.py:359
#: netbox/templates/extras/objectchange.html:8
#: netbox/templates/extras/objectchange.html:9
#: netbox/templates/extras/objectchange_list.html:4
msgid "Change Log"
msgstr ""
@ -10734,8 +10734,8 @@ msgstr ""
#: netbox/templates/extras/configcontext.html:70
#: netbox/templates/extras/eventrule.html:72
#: netbox/templates/extras/htmx/script_result.html:56
#: netbox/templates/extras/objectchange.html:123
#: netbox/templates/extras/objectchange.html:141
#: netbox/templates/extras/objectchange.html:124
#: netbox/templates/extras/objectchange.html:142
#: netbox/templates/extras/webhook.html:67
#: netbox/templates/extras/webhook.html:79
#: netbox/templates/inc/panel_table.html:13
@ -12308,48 +12308,48 @@ msgstr ""
msgid "New Journal Entry"
msgstr ""
#: netbox/templates/extras/objectchange.html:28
#: netbox/templates/extras/objectchange.html:29
#: netbox/templates/users/objectpermission.html:42
msgid "Change"
msgstr ""
#: netbox/templates/extras/objectchange.html:78
#: netbox/templates/extras/objectchange.html:79
msgid "Difference"
msgstr ""
#: netbox/templates/extras/objectchange.html:81
#: netbox/templates/extras/objectchange.html:82
msgid "Previous"
msgstr ""
#: netbox/templates/extras/objectchange.html:84
#: netbox/templates/extras/objectchange.html:85
msgid "Next"
msgstr ""
#: netbox/templates/extras/objectchange.html:92
#: netbox/templates/extras/objectchange.html:93
msgid "Object Created"
msgstr ""
#: netbox/templates/extras/objectchange.html:94
#: netbox/templates/extras/objectchange.html:95
msgid "Object Deleted"
msgstr ""
#: netbox/templates/extras/objectchange.html:96
#: netbox/templates/extras/objectchange.html:97
msgid "No Changes"
msgstr ""
#: netbox/templates/extras/objectchange.html:110
#: netbox/templates/extras/objectchange.html:111
msgid "Pre-Change Data"
msgstr ""
#: netbox/templates/extras/objectchange.html:121
#: netbox/templates/extras/objectchange.html:122
msgid "Warning: Comparing non-atomic change to previous change record"
msgstr ""
#: netbox/templates/extras/objectchange.html:130
#: netbox/templates/extras/objectchange.html:131
msgid "Post-Change Data"
msgstr ""
#: netbox/templates/extras/objectchange.html:153
#: netbox/templates/extras/objectchange.html:162
#, python-format
msgid "See All %(count)s Changes"
msgstr ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
<i class="mdi mdi-download"></i> {% trans "Export" %}
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li><a class="dropdown-item" href="?{% if url_params %}{{ url_params }}&{% endif %}export=table">{% trans "Current View" %}</a></li>
<li><a id="export_current_view" class="dropdown-item" href="?{% if url_params %}{{ url_params }}&{% endif %}export=table">{% trans "Current View" %}</a></li>
<li><a class="dropdown-item" href="?{% if url_params %}{{ url_params }}&{% endif %}export">{% trans "All Data" %} ({{ data_format }})</a></li>
{% if export_templates %}
<li>

View File

@ -1,14 +1,9 @@
import datetime
import json
from typing import Dict, Any
from urllib.parse import quote
from django import template
from django.conf import settings
from django.template.defaultfilters import date
from django.urls import NoReverseMatch, reverse
from django.utils import timezone
from django.utils.safestring import mark_safe
from core.models import ObjectType
from utilities.forms import get_selected_values, TableConfigForm
@ -92,15 +87,22 @@ def humanize_speed(speed):
@register.filter()
def humanize_megabytes(mb):
"""
Express a number of megabytes in the most suitable unit (e.g. gigabytes or terabytes).
Express a number of megabytes in the most suitable unit (e.g. gigabytes, terabytes, etc.).
"""
if not mb:
return ''
if not mb % 1048576: # 1024^2
return f'{int(mb / 1048576)} TB'
if not mb % 1024:
return f'{int(mb / 1024)} GB'
return f'{mb} MB'
return ""
PB_SIZE = 1000000000
TB_SIZE = 1000000
GB_SIZE = 1000
if mb >= PB_SIZE:
return f"{mb / PB_SIZE:.2f} PB"
if mb >= TB_SIZE:
return f"{mb / TB_SIZE:.2f} TB"
if mb >= GB_SIZE:
return f"{mb / GB_SIZE:.2f} GB"
return f"{mb} MB"
@register.filter()

View File

@ -1,6 +1,6 @@
Django==5.0.6
django-cors-headers==4.3.1
django-debug-toolbar==4.3.0
django-debug-toolbar==4.4.2
django-filter==24.2
django-htmx==1.17.3
django-graphiql-debug-toolbar==0.2.0
@ -15,23 +15,23 @@ django-tables2==2.7.0
django-timezone-field==6.1.0
djangorestframework==3.15.1
drf-spectacular==0.27.2
drf-spectacular-sidecar==2024.5.1
drf-spectacular-sidecar==2024.6.1
feedparser==6.0.11
gunicorn==22.0.0
Jinja2==3.1.4
Markdown==3.6
mkdocs-material==9.5.24
mkdocs-material==9.5.26
mkdocstrings[python-legacy]==0.25.1
netaddr==1.2.1
netaddr==1.3.0
nh3==0.2.17
Pillow==10.3.0
psycopg[c,pool]==3.1.19
PyYAML==6.0.1
requests==2.32.2
requests==2.32.3
social-auth-app-django==5.4.1
social-auth-core==4.5.4
strawberry-graphql==0.230.0
strawberry-graphql-django==0.40.0
strawberry-graphql==0.234.0
strawberry-graphql-django==0.42.0
svgwrite==1.4.3
tablib==3.6.1
tzdata==2024.1