Skip to content
This repository has been archived by the owner on Jan 10, 2023. It is now read-only.

Fix svg exporting #32

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions pcbdl/netlistsvg.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import pcbdl.small_parts as small_parts

import collections
import logging
import json
import os
import re
Expand Down Expand Up @@ -274,7 +275,7 @@ def add_parts(self, indent_depth=""):
"type": self.svg_type
}

print(indent_depth + str(part))
logging.debug(f"Added part to SVG: {indent_depth + str(part)}")

# Make sure the other related parts are squeezed on this page
for other_part in parts_to_bring_on_page:
Expand Down Expand Up @@ -355,7 +356,7 @@ def generate(self):
"-o",
netlistsvg_output.name
]
print(netlistsvg_command)
logging.debug(f"Called SVG with command: {netlistsvg_command}")
subprocess.call(netlistsvg_command)

svg_contents = netlistsvg_output.read()
Expand All @@ -368,7 +369,24 @@ def generate(self):
return svg_contents


def generate_svg(*args, **kwargs):
def generate_svg(filename: str, *args, multi_filename_ending: str="_{0}", **kwargs):
"""Generates an SVG or a series of SVG files to a given file. If multiple
SVG pages are created, then each SVG is named according to the scheme
'filename'+'multi_filename_ending'.format(i) where i is the page number.

Args:
filename: The file name to write the SVG to. If multiple SVGs are written
then the multi_filename_ending will be concatenated.
multi_filename_ending: The ending to concatenate to filename in order to
name multiple generated SVG files sequentially. The ending is
evaluated like 'multi_filename_ending'.format(i) where i is the page
number. Defaults to "_{0}".
"""
# Force SVG file
if not filename.lower().endswith(('.svg')):
filename += ".svg"

svg_arr = []
pins_to_skip = []
while True:
n = SVGPage(*args, **kwargs, pins_to_skip=pins_to_skip)
Expand All @@ -378,4 +396,17 @@ def generate_svg(*args, **kwargs):
break
pins_to_skip += n.pins_drawn

yield svg_contents
svg_arr.append(svg_contents)

# Write a single file with the SVG name
assert len(svg_arr) > 0, "No SVG generated, check inputs."
if len(svg_arr) == 1:
with open(filename, "w") as svg_file:
svg_file.write(svg_arr[0])
logging.info(f"Wrote SVG file: {filename}")
if len(svg_arr) > 1:
for i, svg in enumerate(svg_arr):
svg_filename = filename + multi_filename_ending.format(i)
with open(svg_filename, "w") as svg_file:
svg_file.write(svg)
logging.info(f"Wrote SVG file: {svg_filename}")
Empty file added test/__init__.py
Empty file.
84 changes: 84 additions & 0 deletions test/svg_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import unittest
import os
import glob

from pcbdl import *

class SVGTest(unittest.TestCase):

@classmethod
def setUpClass(cls):
super().setUpClass()
cls.ac_coupling_value = "1000u"
cls.subcircuit_id = 0
cls.vcc, cls.gnd = Net("vcc"), Net("gnd")

def _add_sub_circuit(self):
"""Adds a simple sub-circuit to the schematic, naming local subnets
with a convention based on an incrementing id.
"""
transistor = BJT("2n3904")

C = C_POL

transistor.BASE << (
C(self.ac_coupling_value, to=Net(f"vin_{self.subcircuit_id}")),
R("1k", to=self.vcc),
R("1k", to=self.gnd),
)

transistor.COLLECTOR << (
C(self.ac_coupling_value, to=Net(f"vout_{self.subcircuit_id}")),
R("100", to=self.vcc),
)

transistor.EMITTER << (
R("100", to=self.gnd),
C("1u", to=self.gnd),
)

SVGTest.subcircuit_id += 1


def test_empty_page_write(self):
"""Ensure that an AssertionError is created when no objects exist
to write to an SVG
"""
self.assertRaises(AssertionError, generate_svg, "test")

def test_single_page_write(self):
"""Ensure a SVG is generated when a sub circuit is added, and then
delete the SVG file.
"""
# TODO: Ensure that this works on Windows which doesn't have a tmp
# directory
self._add_sub_circuit()
file_name = "/tmp/test"
generate_svg(file_name)
gen_filename = file_name + ".svg"
self.assertTrue(os.path.isfile(gen_filename), "SVG was not generated")
os.remove(gen_filename)

def test_multi_page_write(self):
"""Generates a large circuit and tests whether multiple SVG pages are
created.
"""
# Should be enough sub-circuits to trigger multi-page writing.
for _ in range(100):
self._add_sub_circuit()

file_name = "/tmp/test"
multi_filename_ending = "_{0}"
generate_svg(file_name, multi_filename_ending=multi_filename_ending)
gen_filename = file_name + multi_filename_ending.format(0) + ".svg"
self.assertTrue(os.path.isfile(gen_filename),
"Multiple SVGs were not generated.")

rem_files = glob.glob(file_name + "*.svg", recursive=True)
# Remove all generated files
for rem_file in rem_files:
os.remove(rem_file)


if __name__ == "__main__":
unittest.main()