Skip to content

patchman 4#654

Merged
furlongm merged 154 commits intomasterfrom
develop
Mar 20, 2025
Merged

patchman 4#654
furlongm merged 154 commits intomasterfrom
develop

Conversation

@furlongm
Copy link
Owner

@furlongm furlongm commented Feb 11, 2025

  • switch to django4
  • 2024/2025 distro support
  • additional errata sources, new errata module
  • support for cves and cwes
  • switch from obsolete django-tagging to django-taggit
  • improved operating system support
  • preliminary gentoo support

Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some food for thought. View full project report here.

class CWE(models.Model):

cwe_id = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name = models.CharField(max_length=255, blank=True, null=True)
name = models.CharField(max_length=255, blank=True, default='')

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". Explained here.


cwe_id = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, blank=True, null=True)
description = models.CharField(max_length=65535, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description = models.CharField(max_length=65535, blank=True, null=True)
description = models.TextField(blank=True, default='')

TextField might be better used here, instead of CharField with a huge max_length. More.

Again, consider replacing null=True with default="" (and blank=True to pass validation checks).


class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
score = models.DecimalField(max_digits=3, decimal_places=1, null=True, blank=True)

Expect unwanted behavior if null and blank are different values: null controls if the database allows no value for score and blank controls if the application allows no value for score. Consider setting null and blank to the same value for score. More.

class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
severity = models.CharField(max_length=255, blank=True, null=True)
severity = models.CharField(max_length=255, blank=True, default='')

Same as above: consider replacing null=True with default="" (and blank=True to pass validation checks).

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
version = models.DecimalField(max_digits=2, decimal_places=1)
vector_string = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
vector_string = models.CharField(max_length=255, blank=True, null=True)
vector_string = models.CharField(max_length=255, blank=True, default='')

As above, consider replacing null=True with default="" (and blank=True to pass validation checks).

arch = models.ForeignKey(MachineArchitecture, blank=True, null=True, on_delete=models.CASCADE)
osgroup = models.ForeignKey(OSGroup, blank=True, null=True,
on_delete=models.SET_NULL)
osrelease = models.ForeignKey(OSRelease, blank=True, null=True, on_delete=models.SET_NULL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django automatically creates a related_name if it's not set. If it were set then a more readable and explicit relationship is set up. More.

choices=PACKAGE_TYPES,
blank=True,
null=True)
packagetype = models.CharField(max_length=1, choices=PACKAGE_TYPES, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". More details.

blank=True,
null=True)
packagetype = models.CharField(max_length=1, choices=PACKAGE_TYPES, blank=True, null=True)
category = models.ForeignKey(PackageCategory, blank=True, null=True, on_delete=models.SET_NULL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django automatically creates a related_name if it's not set. If it were set then a more readable and explicit relationship is set up. More.

release = models.CharField(max_length=255, blank=True, null=True)
arch = models.CharField(max_length=255)
packagetype = models.CharField(max_length=1, blank=True, null=True)
category = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
category = models.CharField(max_length=255, blank=True, null=True)
category = models.CharField(max_length=255, blank=True, default='')

Similarly, consider replacing null=True with default="" (and blank=True to pass validation checks).

path('', views.package_list, name='package_list'),
path('<str:packagename>/', views.package_detail, name='package_detail'),
path('', views.package_name_list, name='package_name_list'),
path('name/', views.package_name_list, name='package_name_list'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL names must be unique but multiple urls.py entires are called package_name_list. If reverse("package_name_list") or {% url package_name_list %} is ran then only one of those urls will be returned. The user will probably be sent to the wrong view. More info.

errata/utils.py Outdated
er_type = 'Mailing List'
if er_type == 'bugzilla' or 'bug' in url.hostname or 'bugs' in url.path:
er_type = 'Bug Tracker'
if ('ubuntu.com' in url.hostname and 'usn/' in url.path) or url.hostname == 'usn.ubuntu.com':

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization

The string [ubuntu.com](1) may be at an arbitrary position in the sanitized URL.

Copilot Autofix

AI 12 months ago

To fix the problem, we need to ensure that the URL's hostname is properly parsed and checked to confirm that it belongs to the intended domain. Instead of using a substring check, we should use a more robust method to verify the hostname. Specifically, we can use the urlparse function to parse the URL and then check if the hostname ends with the intended domain, ensuring that it handles arbitrary subdomain sequences correctly.

We will modify the code in errata/utils.py to use the urlparse function and check if the hostname ends with .ubuntu.com instead of using the substring check 'ubuntu.com' in url.hostname.

Suggested changeset 1
errata/utils.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/errata/utils.py b/errata/utils.py
--- a/errata/utils.py
+++ b/errata/utils.py
@@ -67,3 +67,3 @@
         er_type = 'Bug Tracker'
-    if ('ubuntu.com' in url.hostname and 'usn/' in url.path) or url.hostname == 'usn.ubuntu.com':
+    if (url.hostname and url.hostname.endswith('.ubuntu.com') and 'usn/' in url.path) or url.hostname == 'usn.ubuntu.com':
         netloc = url.netloc.replace('usn.', '').replace('www.', '')
EOF
@@ -67,3 +67,3 @@
er_type = 'Bug Tracker'
if ('ubuntu.com' in url.hostname and 'usn/' in url.path) or url.hostname == 'usn.ubuntu.com':
if (url.hostname and url.hostname.endswith('.ubuntu.com') and 'usn/' in url.path) or url.hostname == 'usn.ubuntu.com':
netloc = url.netloc.replace('usn.', '').replace('www.', '')
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
errata/utils.py Outdated
url = url._replace(netloc=netloc, path=path)
if url.hostname == 'ubuntu.com' and url.path.startswith('/security/notices/USN'):
er_type = 'USN'
if 'launchpad.net' in url.hostname:

Check failure

Code scanning / CodeQL

Incomplete URL substring sanitization

The string [launchpad.net](1) may be at an arbitrary position in the sanitized URL.

Copilot Autofix

AI 12 months ago

To fix the problem, we need to ensure that the hostname is exactly launchpad.net or a valid subdomain of it. This can be achieved by parsing the URL and performing a proper check on the hostname.

  • Use the urlparse function to parse the URL and extract the hostname.
  • Check if the hostname is exactly launchpad.net or ends with .launchpad.net to allow valid subdomains.
  • Update the relevant lines in the fixup_erratum_reference function to use this secure check.
Suggested changeset 1
errata/utils.py

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/errata/utils.py b/errata/utils.py
--- a/errata/utils.py
+++ b/errata/utils.py
@@ -76,3 +76,3 @@
         er_type = 'USN'
-    if 'launchpad.net' in url.hostname:
+    if url.hostname == 'launchpad.net' or (url.hostname and url.hostname.endswith('.launchpad.net')):
         er_type = 'Bug Tracker'
EOF
@@ -76,3 +76,3 @@
er_type = 'USN'
if 'launchpad.net' in url.hostname:
if url.hostname == 'launchpad.net' or (url.hostname and url.hostname.endswith('.launchpad.net')):
er_type = 'Bug Tracker'
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
@furlongm furlongm force-pushed the develop branch 5 times, most recently from 5b82c72 to 96cd496 Compare February 13, 2025 03:21
Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth considering. View full project report here.

if verbose:
text = 'Processing report '
text += f'{self.id!s} - {self.host!s}'
text = 'Processing report {self.id} - {self.host}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
text = 'Processing report {self.id} - {self.host}'
text = f'Processing report {self.id} - {self.host}'

If this was meant to be f-string then f prefix is missing. More details.

if verbose:
text = 'Finding updates for report '
text += f'{self.id!s} - {self.host!s}'
text = 'Finding updates for report {self.id} - {self.host}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
text = 'Finding updates for report {self.id} - {self.host}'
text = f'Finding updates for report {self.id} - {self.host}'

Likewise, Missing f prefix?

else:
text = 'Error: OS, kernel or arch not sent '
text += f'with report {self.id!s}'
text = 'Error: OS, kernel or arch not sent with report {self.id}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
text = 'Error: OS, kernel or arch not sent with report {self.id}'
text = f'Error: OS, kernel or arch not sent with report {self.id}'

Again, Missing f prefix?

repos/models.py Outdated
else:
text = 'Error: unknown repo type for repo '
text += f'{self.id!s}: {self.repotype!s}'
text = 'Error: unknown repo type for repo {self.id}: {self.repotype}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
text = 'Error: unknown repo type for repo {self.id}: {self.repotype}'
text = f'Error: unknown repo type for repo {self.id}: {self.repotype}'

If this was meant to be f-string then f prefix is missing. Read more.

class OSRelease(models.Model):

name = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, unique=True, blank=False, null=False)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name = models.CharField(max_length=255, unique=True, blank=False, null=False)
name = models.CharField(max_length=255, unique=True)

False is the default value Django uses for blank, so blank=False can be removed. More details.

Again, redundant default arguments can be removed.

name = models.CharField(max_length=255, unique=True, blank=False, null=False)
repos = models.ManyToManyField(Repository, blank=True)
codename = models.CharField(max_length=255, blank=True)
cpe_name = models.CharField(max_length=255, null=True, blank=True, unique=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". More.

page = paginator.page(paginator.num_pages)

empty_oses = list(OS.objects.filter(host__isnull=True))
nohost_osvariants = OSVariant.objects.filter(host__isnull=True).count() >= 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
nohost_osvariants = OSVariant.objects.filter(host__isnull=True).count() >= 1
nohost_osvariants = OSVariant.objects.filter(host__isnull=True).exists()

Comparing OSVariant.objects.filter(host__isnull=True).count() is less efficient than checking OSVariant.objects.filter(host__isnull=True).exists() More details.

for os in oses:
os.delete()
text = f'{len(oses)!s} OS\'s have been deleted'
if not osvariants:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, consider osvariants.exists()

return redirect(reverse('operatingsystems:osvariant_list'))
for osvariant in osvariants:
osvariant.delete()
text = f'{len(osvariants)} OS Variants have been deleted'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

len(queryset) reads all the records from the database and checks the length at application level. It would probably be more efficient to do this at database level via queryset.count(). More details.

@furlongm furlongm force-pushed the develop branch 2 times, most recently from fccc3bf to 1d056a5 Compare February 26, 2025 05:28
Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some food for thought. View full project report here.

if verbose:
text = 'Processing report '
text += f'{self.id!s} - {self.host!s}'
text = 'Processing report {self.id} - {self.host}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
text = 'Processing report {self.id} - {self.host}'
text = f'Processing report {self.id} - {self.host}'

If this was meant to be f-string then f prefix is missing. Explained here.

if verbose:
text = 'Finding updates for report '
text += f'{self.id!s} - {self.host!s}'
text = 'Finding updates for report {self.id} - {self.host}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
text = 'Finding updates for report {self.id} - {self.host}'
text = f'Finding updates for report {self.id} - {self.host}'

Again, Missing f prefix?

else:
text = 'Error: OS, kernel or arch not sent '
text += f'with report {self.id!s}'
text = 'Error: OS, kernel or arch not sent with report {self.id}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
text = 'Error: OS, kernel or arch not sent with report {self.id}'
text = f'Error: OS, kernel or arch not sent with report {self.id}'

Same as above: Missing f prefix?

repos/models.py Outdated
else:
text = 'Error: unknown repo type for repo '
text += f'{self.id!s}: {self.repotype!s}'
text = 'Error: unknown repo type for repo {self.id}: {self.repotype}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
text = 'Error: unknown repo type for repo {self.id}: {self.repotype}'
text = f'Error: unknown repo type for repo {self.id}: {self.repotype}'

If this was meant to be f-string then f prefix is missing. More info.

path('', views.package_list, name='package_list'),
path('<str:packagename>/', views.package_detail, name='package_detail'),
path('', views.package_name_list, name='package_name_list'),
path('name/', views.package_name_list, name='package_name_list'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL names must be unique but multiple urls.py entires are called package_name_list. If reverse("package_name_list") or {% url package_name_list %} is ran then only one of those urls will be returned. The user will probably be sent to the wrong view. More details.

class CWE(models.Model):

cwe_id = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name = models.CharField(max_length=255, blank=True, null=True)
name = models.CharField(max_length=255, blank=True, default='')

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". Explained here.


cwe_id = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, blank=True, null=True)
description = models.CharField(max_length=65535, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description = models.CharField(max_length=65535, blank=True, null=True)
description = models.TextField(blank=True, default='')

TextField might be better used here, instead of CharField with a huge max_length. More info.

Likewise, consider replacing null=True with default="" (and blank=True to pass validation checks).


class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
score = models.DecimalField(max_digits=3, decimal_places=1, null=True, blank=True)

Expect unwanted behavior if null and blank are different values: null controls if the database allows no value for score and blank controls if the application allows no value for score. Consider setting null and blank to the same value for score. Explained here.

class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
severity = models.CharField(max_length=255, blank=True, null=True)
severity = models.CharField(max_length=255, blank=True, default='')

Again, consider replacing null=True with default="" (and blank=True to pass validation checks).

Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Worth considering though. View full project report here.

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
version = models.DecimalField(max_digits=2, decimal_places=1)
vector_string = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
vector_string = models.CharField(max_length=255, blank=True, null=True)
vector_string = models.CharField(max_length=255, blank=True, default='')

Likewise, consider replacing null=True with default="" (and blank=True to pass validation checks).

class CVE(models.Model):

cve_id = models.CharField(max_length=255, unique=True)
title = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
title = models.CharField(max_length=255, blank=True, null=True)
title = models.CharField(max_length=255, blank=True, default='')

Similarly, consider replacing null=True with default="" (and blank=True to pass validation checks).


cve_id = models.CharField(max_length=255, unique=True)
title = models.CharField(max_length=255, blank=True, null=True)
description = models.CharField(max_length=65535)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
description = models.CharField(max_length=65535)
description = models.TextField()

Similarly, consider using a TextField.

@furlongm furlongm force-pushed the develop branch 7 times, most recently from ccb2b38 to 02f90f7 Compare February 27, 2025 20:27
Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some food for thought. View full project report here.

class CWE(models.Model):

cwe_id = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name = models.CharField(max_length=255, blank=True, null=True)
name = models.CharField(max_length=255, blank=True, default='')

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". More details.


class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
score = models.DecimalField(max_digits=3, decimal_places=1, null=True, blank=True)

Expect unwanted behavior if null and blank are different values: null controls if the database allows no value for score and blank controls if the application allows no value for score. Consider setting null and blank to the same value for score. More details.

class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
severity = models.CharField(max_length=255, blank=True, null=True)
severity = models.CharField(max_length=255, blank=True, default='')

As above, consider replacing null=True with default="" (and blank=True to pass validation checks).

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
version = models.DecimalField(max_digits=2, decimal_places=1)
vector_string = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
vector_string = models.CharField(max_length=255, blank=True, null=True)
vector_string = models.CharField(max_length=255, blank=True, default='')

Same as above: consider replacing null=True with default="" (and blank=True to pass validation checks).

class CVE(models.Model):

cve_id = models.CharField(max_length=255, unique=True)
title = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
title = models.CharField(max_length=255, blank=True, null=True)
title = models.CharField(max_length=255, blank=True, default='')

Same as above: consider replacing null=True with default="" (and blank=True to pass validation checks).

for os in oses:
os.delete()
text = f'{len(oses)!s} OS\'s have been deleted'
if not osvariants:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparing osvariants.count() is less efficient than checking osvariants.exists() More details.

choices=PACKAGE_TYPES,
blank=True,
null=True)
packagetype = models.CharField(max_length=1, choices=PACKAGE_TYPES, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". Read more.

blank=True,
null=True)
packagetype = models.CharField(max_length=1, choices=PACKAGE_TYPES, blank=True, null=True)
category = models.ForeignKey(PackageCategory, blank=True, null=True, on_delete=models.SET_NULL)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Django automatically creates a related_name if it's not set. If it were set then a more readable and explicit relationship is set up. Explained here.

release = models.CharField(max_length=255, blank=True, null=True)
arch = models.CharField(max_length=255)
packagetype = models.CharField(max_length=1, blank=True, null=True)
category = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
category = models.CharField(max_length=255, blank=True, null=True)
category = models.CharField(max_length=255, blank=True, default='')

As above, consider replacing null=True with default="" (and blank=True to pass validation checks).

path('', views.package_list, name='package_list'),
path('<str:packagename>/', views.package_detail, name='package_detail'),
path('', views.package_name_list, name='package_name_list'),
path('name/', views.package_name_list, name='package_name_list'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL names must be unique but multiple urls.py entires are called package_name_list. If reverse("package_name_list") or {% url package_name_list %} is ran then only one of those urls will be returned. The user will probably be sent to the wrong view. Read more.

Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some food for thought. View full project report here.

url = models.CharField(max_length=255, unique=True)
last_access_ok = models.BooleanField(default=False)
file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, default='')

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". Explained here.

last_access_ok = models.BooleanField(default=False)
file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, default='')

Again, consider replacing null=True with default="" (and blank=True to pass validation checks).

file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
errata_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
errata_checksum = models.CharField(max_length=255, blank=True, null=True)
errata_checksum = models.CharField(max_length=255, blank=True, default='')

Likewise, consider replacing null=True with default="" (and blank=True to pass validation checks).

Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth considering. View full project report here.

class CWE(models.Model):

cwe_id = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name = models.CharField(max_length=255, blank=True, null=True)
name = models.CharField(max_length=255, blank=True, default='')

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". More.


class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
score = models.DecimalField(max_digits=3, decimal_places=1, null=True, blank=True)

Expect unwanted behavior if null and blank are different values: null controls if the database allows no value for score and blank controls if the application allows no value for score. Consider setting null and blank to the same value for score. Explained here.

class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
severity = models.CharField(max_length=255, blank=True, null=True)
severity = models.CharField(max_length=255, blank=True, default='')

Same as above: consider replacing null=True with default="" (and blank=True to pass validation checks).

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
version = models.DecimalField(max_digits=2, decimal_places=1)
vector_string = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
vector_string = models.CharField(max_length=255, blank=True, null=True)
vector_string = models.CharField(max_length=255, blank=True, default='')

Likewise, consider replacing null=True with default="" (and blank=True to pass validation checks).

class CVE(models.Model):

cve_id = models.CharField(max_length=255, unique=True)
title = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
title = models.CharField(max_length=255, blank=True, null=True)
title = models.CharField(max_length=255, blank=True, default='')

Similarly, consider replacing null=True with default="" (and blank=True to pass validation checks).

release = models.CharField(max_length=255, blank=True, null=True)
arch = models.CharField(max_length=255)
packagetype = models.CharField(max_length=1, blank=True, null=True)
category = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
category = models.CharField(max_length=255, blank=True, null=True)
category = models.CharField(max_length=255, blank=True, default='')

Same as above: consider replacing null=True with default="" (and blank=True to pass validation checks).

path('', views.package_list, name='package_list'),
path('<str:packagename>/', views.package_detail, name='package_detail'),
path('', views.package_name_list, name='package_name_list'),
path('name/', views.package_name_list, name='package_name_list'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL names must be unique but multiple urls.py entires are called package_name_list. If reverse("package_name_list") or {% url package_name_list %} is ran then only one of those urls will be returned. The user will probably be sent to the wrong view. More.

url = models.CharField(max_length=255, unique=True)
last_access_ok = models.BooleanField(default=False)
file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, default='')

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". More info.

last_access_ok = models.BooleanField(default=False)
file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, default='')

Same as above: consider replacing null=True with default="" (and blank=True to pass validation checks).

file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
errata_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
errata_checksum = models.CharField(max_length=255, blank=True, null=True)
errata_checksum = models.CharField(max_length=255, blank=True, default='')

Again, consider replacing null=True with default="" (and blank=True to pass validation checks).

Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some food for thought. View full project report here.

class CWE(models.Model):

cwe_id = models.CharField(max_length=255, unique=True)
name = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name = models.CharField(max_length=255, blank=True, null=True)
name = models.CharField(max_length=255, blank=True, default='')

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". Read more.


class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
score = models.DecimalField(max_digits=3, decimal_places=1, null=True, blank=True)

Expect unwanted behavior if null and blank are different values: null controls if the database allows no value for score and blank controls if the application allows no value for score. Consider setting null and blank to the same value for score. More details.

class CVSS(models.Model):

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
severity = models.CharField(max_length=255, blank=True, null=True)
severity = models.CharField(max_length=255, blank=True, default='')

As above, consider replacing null=True with default="" (and blank=True to pass validation checks).

score = models.DecimalField(max_digits=3, decimal_places=1, null=True)
severity = models.CharField(max_length=255, blank=True, null=True)
version = models.DecimalField(max_digits=2, decimal_places=1)
vector_string = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
vector_string = models.CharField(max_length=255, blank=True, null=True)
vector_string = models.CharField(max_length=255, blank=True, default='')

Likewise, consider replacing null=True with default="" (and blank=True to pass validation checks).

class CVE(models.Model):

cve_id = models.CharField(max_length=255, unique=True)
title = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
title = models.CharField(max_length=255, blank=True, null=True)
title = models.CharField(max_length=255, blank=True, default='')

Same as above: consider replacing null=True with default="" (and blank=True to pass validation checks).

release = models.CharField(max_length=255, blank=True, null=True)
arch = models.CharField(max_length=255)
packagetype = models.CharField(max_length=1, blank=True, null=True)
category = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
category = models.CharField(max_length=255, blank=True, null=True)
category = models.CharField(max_length=255, blank=True, default='')

Similarly, consider replacing null=True with default="" (and blank=True to pass validation checks).

path('', views.package_list, name='package_list'),
path('<str:packagename>/', views.package_detail, name='package_detail'),
path('', views.package_name_list, name='package_name_list'),
path('name/', views.package_name_list, name='package_name_list'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL names must be unique but multiple urls.py entires are called package_name_list. If reverse("package_name_list") or {% url package_name_list %} is ran then only one of those urls will be returned. The user will probably be sent to the wrong view. More.

url = models.CharField(max_length=255, unique=True)
last_access_ok = models.BooleanField(default=False)
file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, default='')

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". Explained here.

last_access_ok = models.BooleanField(default=False)
file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, default='')

Again, consider replacing null=True with default="" (and blank=True to pass validation checks).

file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
errata_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
errata_checksum = models.CharField(max_length=255, blank=True, null=True)
errata_checksum = models.CharField(max_length=255, blank=True, default='')

Same as above: consider replacing null=True with default="" (and blank=True to pass validation checks).

Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Worth considering though. View full project report here.

url = models.CharField(max_length=255, unique=True)
last_access_ok = models.BooleanField(default=False)
file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, default='')

null=True on a string field causes inconsistent data types because the value can be either str or None. This adds complexity and maybe bugs, but can be solved by replacing null=True with default="". More.

last_access_ok = models.BooleanField(default=False)
file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, default='')

Same as above: consider replacing null=True with default="" (and blank=True to pass validation checks).

file_checksum = models.CharField(max_length=255, blank=True, null=True)
packages_checksum = models.CharField(max_length=255, blank=True, null=True)
modules_checksum = models.CharField(max_length=255, blank=True, null=True)
errata_checksum = models.CharField(max_length=255, blank=True, null=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
errata_checksum = models.CharField(max_length=255, blank=True, null=True)
errata_checksum = models.CharField(max_length=255, blank=True, default='')

Likewise, consider replacing null=True with default="" (and blank=True to pass validation checks).

Copy link
Contributor

@code-review-doctor code-review-doctor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some food for thought. View full project report here.

Comment on lines +145 to +154
if refs:
ref = refs.first()
if ref.url != reference.get('url') and update_ref_type:
ref.ref_type = ref_type
ref.save()
else:
ref, created = Reference.objects.get_or_create(
ref_type=reference.get('ref_type'),
url=reference.get('url'),
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if refs:
ref = refs.first()
if ref.url != reference.get('url') and update_ref_type:
ref.ref_type = ref_type
ref.save()
else:
ref, created = Reference.objects.get_or_create(
ref_type=reference.get('ref_type'),
url=reference.get('url'),
)
if refs.exists():
ref = refs.first()
if ref.url != reference.get('url') and update_ref_type:
ref.ref_type = ref_type
ref.save()
else:
(ref, created) = Reference.objects.get_or_create(
ref_type=reference.get('ref_type'), url=reference.get('url')
)

Checking refs truthiness is less efficient than checking refs.exists() or refs is not None. Checking queryset truthiness evaluates the queryset, therefore reading the records from the database. More info.

@furlongm furlongm merged commit bb0fc18 into master Mar 20, 2025
2 of 3 checks passed
@furlongm furlongm deleted the develop branch March 20, 2025 20:42
@furlongm furlongm restored the develop branch March 21, 2025 21:38
@furlongm furlongm deleted the develop branch March 21, 2025 21:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments