Skip to content

Conversation

G-Rath
Copy link
Contributor

@G-Rath G-Rath commented May 28, 2025

So it turns out in some advisories some of these fields are actually empty arrays which I think is because PHP uses associative arrays for what are "objects" in JavaScript, dicts in Python, and hashes in Ruby. This means an empty associative array is the same as an empty indexed array, so when being turned into JSON PHP cannot know if it should be an actual array or an empty object so it goes with the former.

While that sounds reasonable, what I'm unsure of is why Drupal would be returning an empty array rather than null when there isn't a value for an optional relationship - so this might actually be a bug on the upstreams end, but ultimately we need to handle it here so I've introduced a utility function for loading advisories from JSON which normalizes these properties.

Note that right now this isn't actually fixing anything specific because we're not using any of the properties that actually are arrays in some advisories, but we will do in future as part of processing credits.

Also, having bitten the bullet on introducing a utils.py also means we can relocate some of our other utility functions that current live in the main scripts

transformed to make it easier to work with
"""

field_project: EntityReferenceField | None
Copy link
Contributor Author

Choose a reason for hiding this comment

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

note: I've included this field as its technically possible, even though I think its required on the upstreams end



class Advisory(Node):
class AdvisoryBase(Node):
Copy link
Contributor Author

Choose a reason for hiding this comment

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

note: I've had to split this into three types because Python doesn't allow you to change the type of a field when inheriting, regardless of the variance of the type

i.e. ideally we'd do something like

class AdvisoryRaw(Node):
  field_sa_description: RichTextField | list[None]

class Advisory(AdvisoryRaw):
  field_sa_description: RichTextField

but that is not supported

# https://youtrack.jetbrains.com/issue/PY-58714/False-positive-TypedDict-has-missing-key-when-using-unpacking
sa_advisory: drupal.Advisory = {
**raw_advisory,
'field_project': None,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

note: since this represents a relationship with another entity whose ID we will look sometimes, I didn't think it was a good idea to try and have a fallback for this

for the other fields though I felt that was safe and worth doing as it lets us avoid changing most other code

jonholdsworth
jonholdsworth previously approved these changes May 28, 2025
Copy link

@jonholdsworth jonholdsworth left a comment

Choose a reason for hiding this comment

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

Yup, all makes sense

@G-Rath
Copy link
Contributor Author

G-Rath commented May 28, 2025

Converting to draft for now because having through about it a bit further I'm thinking it might be better for now to just handle this in the specific place the fields are being used since that'll actually only be one place currently (when we build the credits) as the project field should never ever be missing 🤔

(it is important that the types reflect the actual structure of the JSON though so either way we def want that part of the change)

@G-Rath G-Rath marked this pull request as draft May 28, 2025 20:58
Unifex
Unifex previously approved these changes May 28, 2025
Copy link
Contributor

@Unifex Unifex left a comment

Choose a reason for hiding this comment

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

LGTM. +1 on the utils.py

@G-Rath G-Rath force-pushed the normalize branch 3 times, most recently from cece987 to 71f9ca8 Compare June 2, 2025 19:45
G-Rath added a commit that referenced this pull request Jun 2, 2025
So it turns out in some advisories some instances of this field are
actually empty arrays which I think is because PHP uses associative
arrays for what are "objects" in JavaScript, `dict`s in Python, and
hashes in Ruby. This means an empty associative array is the same as an
empty indexed array, so when being turned into JSON PHP cannot know if
it should be an actual array or an empty object so it goes with the
former.

While that sounds reasonable, what I'm unsure of is why Drupal would be
returning an empty array rather than `null` when there isn't a value for
an optional relationship - so this might actually be a bug on the
upstreams end, but either way our types should represent the JSON we
have today.

The check we currently have for this field does guard against this, but
technically does not narrow the type in a way that `mypy` can understand
so I've changed it to use `isinstance`.

(this is a smaller version of #56 which is focused on the impacted field
that we're currently using)
@G-Rath G-Rath dismissed stale reviews from Unifex and jonholdsworth via feb4a99 July 2, 2025 19:02
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.

3 participants