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

Error ByteIO #379

Open
hatersDuck opened this issue Jun 17, 2023 · 3 comments
Open

Error ByteIO #379

hatersDuck opened this issue Jun 17, 2023 · 3 comments

Comments

@hatersDuck
Copy link

There is such a function:

def get_pdf(post_data, folder):
    pdf = canvas.Canvas('ex1.pdf', pagesize=landscape(A4))
    x_offset = 0
    y_offset = 0
    width, height = landscape(A4)

    for i in  range(1, 
                    post_data["uniqueTemplates"][post_data["selectedTemplate"]]['countList']+1):
        template_path = f'{post_data["selectedTemplate"]}-{i}.svg'
        path = os.path.join(folder, template_path)

        with open(path) as card:
            root = etree.fromstring(card.read())
        for e in update_svg_template(root, post_data, i-1, os.path.join("/".join(path.split("/")[:-2]))):
            root.append(e)
        
        svg_data = etree.tostring(root)
        svg_file_buffer = io.BytesIO(svg_data)
        drawing = svglib.svg2rlg(svg_file_buffer)

        drawing_scale_x = width / drawing.width
        drawing_scale_y = height / drawing.height
        drawing.scale(drawing_scale_x, drawing_scale_y)

        renderPDF.draw(drawing, pdf, x_offset, y_offset)

        if i != post_data["uniqueTemplates"][post_data["selectedTemplate"]]['countList']:
            pdf.showPage()

    return pdf

It gives such an error:

Unable to resolve image path '../client/public/static/logo_1.png' as the SVG source is not a file system path.
Unable to resolve image path '../client/public/static/logo_2.png' as the SVG source is not a file system path.
Unable to resolve image path '../client/public/static/logo_1.png' as the SVG source is not a file system path.
Unable to resolve image path '../client/public/static/logo_2.png' as the SVG source is not a file system path.

The images are present along these paths, but okay, I rewrote the string to an absolute path.

Unable to resolve image path '/home/danila/codes/Prod/form-converter-to-pdf/client/public/static/logo_1.png' as the SVG source is not a file system path.
Unable to resolve image path '/home/danila/codes/Prod/form-converter-to-pdf/client/public/static/logo_2.png' as the SVG source is not a file system path.
Unable to resolve image path '/home/danila/codes/Prod/form-converter-to-pdf/client/public/static/logo_1.png' as the SVG source is not a file system path.
Unable to resolve image path '/home/danila/codes/Prod/form-converter-to-pdf/client/public/static/logo_2.png' as the SVG source is not a file system path.

I checked lib and i find there was an isinstance check for str, and I had byteIO there.

So I replaced everything with a different approach, which I will attach if it helps someone.

        with tempfile.NamedTemporaryFile(suffix='.svg') as tmp:
            tmp.write(svg_data)
            tmp.flush()
            drawing = svglib.svg2rlg(tmp.name)

So what was my problem?

@github-actions
Copy link

Thank you for raising your first issue! Your help to improve svglib is much appreciated!

@claudep
Copy link
Collaborator

claudep commented Jun 17, 2023

You are right, if paths in the content are absolute paths, we should not fail with that message (around

if iri:
). Do you want to suggest a patch to fix this?

@hatersDuck
Copy link
Author

hatersDuck commented Jun 20, 2023

I suck at handling forked changes, so I'm just gonna dump the code here.

These changes really helped me out. Write that up as lit.

reworked lines 707-722

        if iri:
            import io
            # Only local relative paths and BytesIO objects are supported
            if not isinstance(self.source_path, (str, io.BytesIO)):
                logger.error(
                    "Unable to resolve image path %r as the SVG source is not "
                    "a file system path or BytesIO object.",
                    iri
                )
                return None
            
            if isinstance(self.source_path, str):
                path = os.path.normpath(os.path.join(os.path.dirname(self.source_path), iri))
                if not os.access(path, os.R_OK):
                    return None
                if path == self.source_path:
                    # Self-referencing, ignore the IRI part
                    iri = None
            else:
                # self.source_path is of type io.BytesIO
                # We need to read the data from BytesIO object so that it can be accessed like a regular file system path.
                try:
                    path = self.source_path.name
                except AttributeError:
                    path = '<BytesIO>'
                with open(path, 'wb') as f:
                    f.write(self.source_path.read())
                
                path = os.path.normpath(os.path.join(os.path.dirname(path), iri))
                if path == '<BytesIO>':
                    iri = None
                elif not os.access(path, os.R_OK):
                    return None

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

2 participants