Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attachments with same name are not retrievable via pyral #198

Open
jamespet77 opened this issue Aug 7, 2024 · 1 comment
Open

Attachments with same name are not retrievable via pyral #198

jamespet77 opened this issue Aug 7, 2024 · 1 comment

Comments

@jamespet77
Copy link

When you have multiple attachments with the same name the getAttachments function fails to retrieve them.

I added a try/except around the code in pyral to allow for the app not to crash, but the images are still not able to be returned. For example I have two image.png attached to a task. When calling getAttachments the app will crash. Adding the try/except allowed one of them to be returned, but an exception was called on the other. I have included screenshots and the code that I updated with the try/except. This is clearly related to the names being the same since in getAttachment it uses the filename as a variable. This seems to be the root cause of the issue. I might suggest having getAttachments iterate via OID or some other mandatory distinct value.

Screenshot_20240807_081002
Screenshot_20240807_081049

Screenshot_20240807_080744
Screenshot_20240807_081856

@jamespet77
Copy link
Author

jamespet77 commented Aug 7, 2024

I have tested and working with OID.

 def getAttachmentOIDs(self, artifact):
        """
            For the given Artifact, return the oids of the Attachments
        """
        oids = []
        if artifact.Attachments:
            oids = [att.oid for att in artifact.Attachments]
        return oids
#attachment_names = self.getAttachmentNames(artifact)
attachment_oids = self.getAttachmentOIDs(artifact)
# attachments = [self.getAttachment(artifact, attachment_name) for attachment_name in attachment_names]
attachments = [self.getAttachmentByOID(artifact, attachment_oid) for attachment_oid in attachment_oids]
    def getAttachmentByOID(self, artifact, oid):
        """
            Given a real artifact instance or the FormattedID of an existing artifact,
            obtain the attachment named by oid.  If there is such an attachment,
            return an Attachment instance with hydration for  Name, Size, ContentType, Content,
            CreationDate and the User that supplied the attachment.
            If no such attachment is present, return None
        """
        art_type, artifact = self._realizeArtifact(artifact)
        if not art_type:
            return False

        current_attachments = [att for att in artifact.Attachments]
        hits = [att for att in current_attachments if att.oid == oid]
        if not hits:
            return None
        att = hits.pop(0)
        if not att._hydrated:
            getattr(att, 'Description')  # forces the hydration to occur

        # For reasons that are unclear, a "normal" pyral GET on 'AttachmentContent' comes
        # back as empty even if the specific OID for an AttachmentContent item exists.
        # The target URL of the GET has to be constructed in a particular manner.
        # Fortunately, our _getResourceByOID method fills this need.
        # But, we have to turn the raw response into a RallyRESTResponse ourselves here.

        context, augments = self.contextHelper.identifyContext()
        try:
            resp = self._getResourceByOID(context, 'AttachmentContent', att.Content.oid, project=None)
            if resp.status_code not in [200, 201, 202]:
                return None
        except:
            print(f'Unable to retrieve attachment {filename}')
            return None

        response = RallyRESTResponse(self.session, context, "AttachmentContent.x", resp, "full", 1)
        if response.errors or response.resultCount != 1:
            return None
        att_content = response.next()
        att.Content = base64.b64decode(att_content.Content)  # contrib by jfthuong
        return att

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

No branches or pull requests

1 participant