From 9c2c6b22a8df745d38b0c23f5523d70172d4b602 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Mon, 27 Feb 2023 17:16:56 -0500 Subject: [PATCH 01/52] docstring --- schemascii/inline_config.py | 1 + 1 file changed, 1 insertion(+) diff --git a/schemascii/inline_config.py b/schemascii/inline_config.py index 9b3855c..f72acbe 100644 --- a/schemascii/inline_config.py +++ b/schemascii/inline_config.py @@ -5,6 +5,7 @@ def get_inline_configs(grid: Grid) -> dict: + "Extract all the inline config options into a dict and blank them out." out = {} for y, line in enumerate(grid.lines): for m in INLINE_CONFIG_RE.finditer(line): From aba1c99d5ad34fc03eaee191b21abdc239788801 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Mon, 6 Mar 2023 16:10:32 +0000 Subject: [PATCH 02/52] add transistors --- .vscode/settings.json | 3 ++ format.md | 4 +-- schemascii/components_render.py | 58 +++++++++++++++++++++++++++++++-- schemascii/utils.py | 44 +++++++++++++++++++++---- test_data/test1.txt | 36 +++++++++++++++++--- 5 files changed, 131 insertions(+), 14 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 898ba0c..883f778 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,9 @@ { "cSpell.words": [ "Cbox", + "MOSFET", + "NFET", + "PFET", "polylinegon", "rendec", "schemascii", diff --git a/format.md b/format.md index 3046a91..0f9f7b1 100644 --- a/format.md +++ b/format.md @@ -51,12 +51,12 @@ Components are able to accept "flags", which are other punctuation characters an To include component values, pin numbers, etc, somewhere in the drawing but not touching any wires or other components, you can write component values - these are formatted as the reference designator (same as in circuit) followed by a `:` and the value parameter (which stops at the first whitespace). *I usually put these in a "BOM section" below the circuit itself but you could also put them right next to the component.* -For simple components, this is usually just a value rating, but *without* the units (only the Metric prefix). For more specific components (mostly semiconductor devices) this is usually the part number. +For simple components, this is usually just a value rating, but *without* the units (only the Metric prefix). For more specific components (mostly semiconductor devices) this is usually the part number and/or some string to determine how to draw the component. Examples: * `C33:2.2u` -- "2.2 µF" -* `Q1001:TIP102` -- just the part number; printed verbatim +* `Q1001:pnp:TIP102` -- "pnp" or "npn" to determine what kind of transistor, just the part number; printed verbatim * `L51:0.33` -- this is rewritten to "330 mH" so that it has no decimal point. * `F3:1500m` -- rewritten: "1.5 A" * `D7:1N4001` -- again, part number diff --git a/schemascii/components_render.py b/schemascii/components_render.py index c10a18c..1b43c1f 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -2,10 +2,10 @@ from cmath import phase, rect from math import pi from warnings import warn -from .utils import (Cbox, Terminal, BOMData, XML, Side, +from .utils import (Cbox, Terminal, BOMData, XML, Side, arrow_points, polylinegon, id_text, make_text_point, bunch_o_lines, deep_transform, make_plus, make_variable, - sort_counterclockwise, light_arrows) + sort_counterclockwise, light_arrows, sort_for_flags, is_clockwise) from .errors import TerminalsError, BOMError, UnsupportedComponentError RENDERERS = {} @@ -291,6 +291,60 @@ def jack( + id_text(box, bom_data, terminals, None, sc_text_pt, **options)) +@component("Q", "MOSFET", "MOS", "FET") +@n_terminal(3) +@no_ambiguous +def transistor( + box: Cbox, + terminals: list[Terminal], + bom_data: BOMData, + **options): + "Draw a bipolar transistor (PNP/NPN) or FET (NFET/PFET)" + if all(x not in bom_data.data.lower() for x in ("pnp:", "npn:", "nfet:", "pfet:")): + raise BOMError( + f"Need type of transistor for {box.type}{box.id}") + silicon_type, part_num = bom_data.data.split(":") + silicon_type = silicon_type.lower() + bom_data = BOMData(bom_data.type, bom_data.id, part_num) + if 'fet' in silicon_type: + ae, se, ctl = sort_for_flags(terminals, box, "s", "d", "g") + else: + ae, se, ctl = sort_for_flags(terminals, box, "e", "c", "b") + ap, sp = ae.pt, se.pt + mid = (ap + sp) / 2 # TODO: slide this to line up with middle + theta = phase(ap - sp) + backwards = 1 if is_clockwise([ae, se, ctl]) else -1 + thetaquarter = theta + (backwards * pi / 2) + out_lines = [ + (ap, mid + rect(.8, theta)), # Lead in + (sp, mid - rect(.8, theta)), # Lead out + ] + if 'fet' in silicon_type: + arr = mid + rect(.8, theta), mid + rect(.8, theta) + rect(.7, thetaquarter) + if 'nfet' == silicon_type: + arr = arr[1], arr[0] + out_lines.extend([ + *arrow_points(*arr), + (mid - rect(.8, theta), mid - rect(.8, theta) + rect(.7, thetaquarter)), + (mid + rect(1, theta) + rect(.7, thetaquarter), + mid - rect(1, theta) + rect(.7, thetaquarter)), + (mid + rect(.5, theta) + rect(1, thetaquarter), + mid - rect(.5, theta) + rect(1, thetaquarter)), + ]) + else: + arr = mid + rect(.8, theta), mid + rect(.4, theta) + rect(1, thetaquarter) + if 'npn' == silicon_type: + arr = arr[1], arr[0] + out_lines.extend([ + *arrow_points(*arr), + (mid - rect(.8, theta), mid - rect(.4, theta) + rect(1, thetaquarter)), + (mid + rect(1, theta) + rect(1, thetaquarter), + mid - rect(1, theta) + rect(1, thetaquarter)), + ]) + text_pt = make_text_point(ap, sp, **options) + return (id_text(box, bom_data, [ae, se], None, text_pt, **options) + + bunch_o_lines(out_lines, **options)) + # code for drawing stuff # https://github.com/pfalstad/circuitjs1/tree/master/src/com/lushprojects/circuitjs1/client # https://github.com/KenKundert/svg_schematic/blob/0abb5dc/svg_schematic.py diff --git a/schemascii/utils.py b/schemascii/utils.py index 8f1a713..9357b79 100644 --- a/schemascii/utils.py +++ b/schemascii/utils.py @@ -4,8 +4,9 @@ from math import pi from cmath import phase, rect from typing import Callable -from .metric import format_metric_unit import re +from .metric import format_metric_unit +from .errors import TerminalsError Cbox = namedtuple('Cbox', 'p1 p2 type id') BOMData = namedtuple('BOMData', 'type id data') @@ -114,7 +115,8 @@ def mk_tag(*contents, **attrs) -> str: if isinstance(v, float): v = fix_number(v) elif isinstance(v, str): - v = re.sub(r"\d+(\.\d+)", lambda m: fix_number(float(m.group())), v) + v = re.sub(r"\d+(\.\d+)", + lambda m: fix_number(float(m.group())), v) out += f'{k.removesuffix("_").replace("__", "-")}="{v}" ' out = out.rstrip() + '>' + ''.join(contents) return out + f'' @@ -293,7 +295,37 @@ def sort_counterclockwise(terminals: list[Terminal]) -> list[Terminal]: terminals, lambda t: t.side)} return list(chain( - sorted(partitioned[Side.LEFT], key=lambda t: t.pt.imag), - sorted(partitioned[Side.BOTTOM], key=lambda t: t.pt.real), - sorted(partitioned[Side.RIGHT], key=lambda t: -t.pt.imag), - sorted(partitioned[Side.TOP], key=lambda t: -t.pt.real))) + sorted(partitioned.get(Side.LEFT, []), key=lambda t: t.pt.imag), + sorted(partitioned.get(Side.BOTTOM, []), key=lambda t: t.pt.real), + sorted(partitioned.get(Side.RIGHT, []), key=lambda t: -t.pt.imag), + sorted(partitioned.get(Side.TOP, []), key=lambda t: -t.pt.real))) + + +def is_clockwise(terminals: list[Terminal]) -> bool: + "Return true if the terminals are clockwise order." + sort = sort_counterclockwise(terminals) + for _ in range(len(sort)): + if sort == terminals: + return True + sort = sort[1:] + [sort[0]] + return False + + +def sort_for_flags(terminals: list[Terminal], box: Cbox, *flags: list[str]) -> list[Terminal]: + """Sorts out the terminals in the specified order using the flags. + Raises and error if the flags are absent.""" + out = () + for flag in flags: + matching_terminals = list(filter(lambda t: t.flag == flag, terminals)) + if len(matching_terminals) > 1: + raise TerminalsError( + f"Multiple terminals with the same flag {flag} " + f"on component {box.type}{box.id}") + if len(matching_terminals) == 0: + raise TerminalsError( + f"Need a terminal with the flag {flag} " + f"on component {box.type}{box.id}") + terminal, = matching_terminals + out = *out, terminal + terminals.remove(terminal) + return out diff --git a/test_data/test1.txt b/test_data/test1.txt index 0b036fe..086787a 100644 --- a/test_data/test1.txt +++ b/test_data/test1.txt @@ -1,4 +1,32 @@ ------LED1+----- -LED1:red ------VR1###------ -VR1:10k \ No newline at end of file +-------sMOSFET1d----- + g MOSFET1:nfet:2N7000 + *-------- + +-------eQ1c----- + b Q1:pnp:TIP102 + *------ + +-------dMOSFET2s----- + g MOSFET2:pfet:2N7001 + *-------- + +-------cQ2e----- + b Q2:npn:TIP103 + *------ + +-------dMOSFET3s----- + g MOSFET3:nfet:2N7000 + *-------- + +-------cQ3e----- + b Q3:pnp:TIP102 + *------ + +-------sMOSFET4d----- + g MOSFET4:pfet:2N7001 + *-------- + +-------eQ4c----- + b Q4:npn:TIP103 + *------ +!padding=30! \ No newline at end of file From e3a80df8fd37ac55c52e32a3986ae05201718abc Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Mon, 6 Mar 2023 16:10:57 +0000 Subject: [PATCH 03/52] formatter --- schemascii/components_render.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/schemascii/components_render.py b/schemascii/components_render.py index 1b43c1f..0950dcc 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -311,7 +311,7 @@ def transistor( else: ae, se, ctl = sort_for_flags(terminals, box, "e", "c", "b") ap, sp = ae.pt, se.pt - mid = (ap + sp) / 2 # TODO: slide this to line up with middle + mid = (ap + sp) / 2 # TODO: slide this to line up with middle theta = phase(ap - sp) backwards = 1 if is_clockwise([ae, se, ctl]) else -1 thetaquarter = theta + (backwards * pi / 2) @@ -320,7 +320,8 @@ def transistor( (sp, mid - rect(.8, theta)), # Lead out ] if 'fet' in silicon_type: - arr = mid + rect(.8, theta), mid + rect(.8, theta) + rect(.7, thetaquarter) + arr = mid + rect(.8, theta), mid + rect(.8, theta) + \ + rect(.7, thetaquarter) if 'nfet' == silicon_type: arr = arr[1], arr[0] out_lines.extend([ @@ -332,7 +333,8 @@ def transistor( mid - rect(.5, theta) + rect(1, thetaquarter)), ]) else: - arr = mid + rect(.8, theta), mid + rect(.4, theta) + rect(1, thetaquarter) + arr = mid + rect(.8, theta), mid + rect(.4, theta) + \ + rect(1, thetaquarter) if 'npn' == silicon_type: arr = arr[1], arr[0] out_lines.extend([ From 67b1c4305080e7ca2f99938068402776b6363bae Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Mon, 6 Mar 2023 17:21:47 +0000 Subject: [PATCH 04/52] transistors are done! --- dist/schemascii-0.2.1-py3-none-any.whl | Bin 0 -> 45621 bytes dist/schemascii-0.2.1.tar.gz | Bin 0 -> 56043 bytes format.md | 2 +- pyproject.toml | 2 +- schemascii/__init__.py | 2 +- schemascii/components_render.py | 20 +++++++++++++++++++- schemascii/utils.py | 6 ++++-- test_data/test1.txt | 17 +++++++++++++++++ 8 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 dist/schemascii-0.2.1-py3-none-any.whl create mode 100644 dist/schemascii-0.2.1.tar.gz diff --git a/dist/schemascii-0.2.1-py3-none-any.whl b/dist/schemascii-0.2.1-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..20eff88e83e46cf48f04731ce91aa9fabf87b5bf GIT binary patch literal 45621 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%0DC4tV)(l;Vbe%Q@~$y4A+OmPucjqBxxT~?hQ zzzwEo`PP7hNqz@Lc3 zVPjA11qRh-GDct;YpZl|ql>S}^Jex21Fbb@DbGf9@XVmCOKljAD`SSCGz|arz0KLG zS$BF9+>a4R^b`5EHDi6yg!Gq?Xc8nQXF52Ne}hj_xHdV9`SY_(<;DxK6V^q8%9dj5 z;yk~g+*H=k(kCg#_tT1fdLI2aGX^&{9jtmyFve8_et%5yYqa8nz}W@IS%8w@UX%~` z>j94q134kA7r7D`3rvRKuTJEEHN}2eK!q>g2pjN0ahgMJzVLb_Jj`oxL@w-|Yw1Oo zUUfnN)1>Xq{x{iA?3dPILP+JFhXY!DRe}jxc2KB~PQv?sqNQ}}9l3G$5DCC@EA8FN;fmi8BE-}FdWBs7_F{)FlZpmfz&v1pB7#@dfY+dsx zl#|Z;V)=H8U5(BlMjf-S+N$i~>9ovUl0=;hxislnA%v4FPQ`~*nxHs0Jb=0#uxOO$ zzTZG{Es|{Czv79EId@S?7>1La&c#8%Ts@A&MRO|*&kPn9na^bpxU@@g+*ffj zQI{Sekn0JUV9uEF-?^y28x1DbmcO9t-Fl6Zs{^xH{cT8|BQ8|yGjG~v7;>MZmVBsu z?t4FFNDoFss8eXt{UgU>x^7eNvr;oOaB@q3|%WbkAhhLfUQvs938gI^m` zJT6bBaU}WFWZ`KnS}J9}X|_@$hi(UoR7`#U+o{(S7@o&z!Q{r-;3i|Pg1H-7!p&jH z^m8i3fm<3?@6H^(!eVpC=PR( z>P6P&Bo2Iwg%v)$s&hu6cY>T|9uuTV$gbr_Lc!}GRKTf*k@lQRduN0?F~TyAYlQIw zn0nZhIi_j_sqP%V*ifp_vETf8aer64ZX(w<%x9m^$lVt&Pr!M%n{R(b@N!Lie%uUI35nOLd8enf)qv3(p4moLTq(J5MhLS5`_tq z%g%lbJ4{oFWd4FgIxHgy^RfNtX;Y?dQ}BplD*z@Q{%cGuesE!k%xESh4Ck>j-4%+# zhX6*TWpxTlQnG9g!rNl=G-7}Gn2P`=jf2N}E6wmt(LTXpO-nrrv~!Z0krHklG_6Td zqYK#3bEk0^Sh7M6W#OJ&EW%K(n<5R^_L&r9iP=oYtlVHsDwJzEEUF_trWY-;Etv+8 zI>_w1p@Ovcz7{>9p78X*b>{YU&L19=Lu?kL)xoY+=k?eConWAa(L%o3H^AlN~xPYcg7wYktcaN8TLn~OR9&YGJF~)zO-ZaMQrOf4)u!j7Q`}$j?Sn&DOfMD z1Zh}~dfE%Q7&={J( zj3pxG1Fs@U ze4OrpJAB}E%56z0`HTfVPbWQ;3d2skfk+EQv|7A#CiQa#kM_+&cu7Y6kh9)xLZ-gY3@ zA%tlLbH%kVg=AYWkx{ywR!)Yndz$I=2i3t=Z+^JIaI5?986&#y8?4yA;xBXM_14>O zqj`T4qR4elnLYFVA&;}`c`}ToGZOnT0()+?iVcMid9ey*`F@LIDYw0!Z%2rPy2ZXB zHgx*ki)enzXB)hr8LIfU*6{|uwX7|+ec5IHJ26tJcQBc25EAesQhcWvA{Bh}_?oJh zgSdPe{!sw&4Kp5oG7c4anF!Q!059gmeRrLFy9%~0dGr{e;{7-_fkF#ruy_)lrMF1H zY!j7lMx~hArJ|p!lUQIt8-M0UR|+4x7+@*5;GAe!H(+9^&h#~E!{)Jcn$epdFHq4P ztxSBEVg?Vge(CcR|Eog4U{H=nq*UKjB4I?vL4Lw(qrsOav_AFdXEj~~-)cLV*k~rs z<%qLh)8PxF4>)LV%<&RrPQ|B1`hy7+T&NRT=njOe@pZMn*80%g{|l#^nvi(=k?Vn0 zu9336WSD>Ox`K-(MFa`7iWjXPm+mT|m%m-uJ4ZK6aR2VoZ!e9)BS6!sZxKpms}3M* zbT$3J7BY-!!I(exsV^2XpCO$C!0CT^z#-vyunx|L3T;2G4-=AhMN@=sUaeXTQ7?9G z0HqWW;)NU?B_)4DM?Po5TZE4qiA@Z2CwV4Mo`f5jjLOCXsHvx;<6is|Rgb}fq4LXw z;&QD4_10i0A(j`09bF?_nGvog8rDSh1f{K%yYhE!5>>@JD%ocQF9I^4dX z%0p-Zgz`CvF$A6xVxV+DHzv}}VPRab*#%Fqc83`Crrv21isfUgP3^N3ei4p81^CP{ z_!7GIsy&79-~x$a{@BYG7U?f=Ggv0bC#%ep8-CC11=7b7TDb4)`LXn?R)ZW8vV-l)ZX9DFBkX+{hjEM2;fRkb$w4~#nsX;bP+qF zJH`qiPPs?(nHT{Cczvw51Pg!Hwfi$nkWMQpuRw>+ZyOfj& z8<>RdSpuLvM!1OoF9xcvls&7@j&V$@vX)LzG`9S~-$-Z;Vp_|#F3~^FgOkPlfQ?=} z6=eeZk(fzhgT+G9L2poOEEpmpwmVA(^q~CA@<)qF+mFY(9{G>xlJEJ%7YO5jALYAF zGe(h=b3ORd@~=>N*JP|J0Bw>%((n4PFYp|{O6;{A0~@Rx-GbfC@Hg-@3pjpFJc}M+unZq8@oS~VAD+CENfWA?rL`GB);IM=dAlM+m%0M3)@tQ>z_a; zzwc+fCFg(DayyYOy=)4%Mg}Dd!-+INe(|eLCGu9*+2y(YC#KW=N;~ipwQt}1RrY<* z@3s1}jlp&Q623P+xa6Yq{-CBDq;KeWM)5@}Ico?0g*N=0w&ADVjX4M{#5xLTKRO$> zo1PzfHW$Yc5YHLDU9~}a!8hr!H!hYvU8hW?g+J=eHE0lTvb_y`wV0s6Yx&@36jsu9 zHMYD6xu*;-8x5~}C!Qcyc*zgq@=2u@+SLQ8Ws@|vV_C%romp}Rb z{OTeuH)iOlJ6M>z68lJGa=_obg0OSwiVmTKx9N7PS1BNbe1w)Z`yJwqoG-NDGlU*K zh9SJI1n56kpSC&=C&Hcxcv^e2W=kYwwxiJWTbnIk0Y+JP$M&tN_uoD*;`n3zjspYK zbFjfq$YLV8Sk`|`LgA!>%*Cdtwd7qLF?PL2NrMKg<7W{3C;eP=&P82ta7l8=_trS= zg%LqeA+qruB4b~_=URFfxGePZQ@e%=UghW z!xv;t2>M8^TRJX`#6)^QGCOP+zfA4_&?emyiDb@DBG%N%WIFw@*IwK0WbiL{c7jP6 z8zP{&wn!jBC|f$YNF6kU(M0QeMCzb>DgB!JZpggKHlvsSAdW!6oNIU;(MqQ za#?;PUxT4K+;fBaVQ$Dm5zU|6#q(zWny~!3eB6~6n{Hdu<@`TTO9KQH000080H}&) zR_xGp+%-4=00poB03!eZ0CQt#Wo=<|V`*tEFfKAKF)n0jb960fZf0*UO+{2eL_t(R z&3$Qe+enh=cl`#7Nq8lWNB-S9n#UYuy^X9j| zys9b-1Z4MqT19kQB7v%`tgO5<>y4@7B(CGpJ5yF^k)K7+#-~SD@z$J0)pBFDakWg- zBlqpoF@8U9w%fSepGCJOPfQt2=I687C@yPxr%snuR2R|w-K(QXQ*VlL1fQnaS(KFV zy2zIWy!G_kAEKX5pPoK_cKYqno!cE@$Tv{5QRtPmiLkY-ttkOu0?#+9ZgmB}@~=c@iaQRhQ|asZ9jWE@0p-ewmuek5a6ndIKY5 zjEE>Hmd)1W^)Q0>qU9#e*J-|v(i*49i#m$4tavcVxMO{f{M?i#-YzoJ_14|SF#1hy z$~cQ|ngu`;$=2Y!akK(F4QXYWS=A2ORZ+TuDvL#2dQoqHls=|;QsELGit=OC2{KMD zqg6Ouv@NQ-Yph)vFM$*RJ{l~-Zxd6c>)a%6JivY(e}vZ_;(fF)nvwudiYB<-I(Q0)J;XU;4hKu?D&o@?Mekw9a0UG|4o~6}Zn#I*>b3@; z#MRlEe?-{g-7W*F1_-J`uQ$&3vU`YTSVCsv3Xz2rk6X0Z6T~sG6@>Xi(L~EQrxEcx zJsM$E@KeFkilURE-fv7EJpkf%CjN-vBE}rNL;MQyP@0t~OFUbEY1ykGo-jAmu7tG% zOxG}NH&#L_jDjtzH*t+1yWuwRJ(HXwNyQ+rb2NZTk~;S|wBT5V2- zZc13&(xmq|NK-Cx=)^>@e~8$%sfn4a0@xmaZsB7!1U{>di310QL8<{*mkccqmPfgH zaDx&2exDG2H|)o}cyQw<1&&QL2>Z~(9||0*Hp`m#pZIr0yO_KCumkgOI7|fL94yaFC z+(HnusEEPaaVcU%heK)A;aT^Y$}BZ-29z*o)=p}a=Pr0F38n*{ZYJx z2Z$p8UTYNnfSAaQOW37mi&O#1&EZ zflWeP0@YOj07wTk{_PH!1Yk-?9R`b2k zlr(Tsftnn#zpGJh2^^3(L2`uyifSxF34`9JmRS%8b_5)9)gVF63LYmq^_Wn7O;l|+JtSR9>do~Gzr?Fg8A1<07PQ5U@reZLZmSjQ6i+qHz^;&px zm_*)^Mq9uktcfonsiRN=mZ0Pk5}@Ys%+Ho&xxg#9i(hU7-%W4d%%jQGMRb0Bbuqh} zU0=<+UVb_TvA#-khOBe^!JU%112!Xwj_m1v?#@E5HPt<^b59J|klLCUu;cWBQI^6M zXYqr`Gd7W6;?UOiIz3vpLt%|@1k5%?qyq~f6dV9&W$;LV^n^dN zl&D(U*lE7PT{R>Un81l2FX>6Y*KjC7Tzx{F0RAz{rWT(a@-VMJiI9k#vW-un!Ij>} zY>DCC-^lurut1~A8c-q}e{_QdeDau(0mBL!0%mzKv;-I5$7x2OvytYpMcj!E3?S?Z zbx;s5In02jA#FD5CHHKG!jXM2S=PIQfYW=^K4!>2kVlC&=9Wmj%;X4`Or>N{Y0X~R zJ=Ac;v%yv?VCxO(W;viWCgX$YA}0L;6$aF4y~y=@keeETW6D7bqz3z=Lc5CGaBL)r z%azvy80%cLZAv;rehhQVoU&kzvM%)@h z&JkqnC45`LSe*oRItHtdTpH)-(&*E%2FmX-5EqSRpR9(V(-U|#e7)_IYvku;cA=RF zTbeZr>FdRR8j@5vjX&F{12P19tSuj>#{|qAO_8`vqM1d$A69J$^9dF_DScP006Nf{ zL!$;qN>GP`Rf1^{Bg-h(pc}y7_5m>ci)4@9x1rsVWgKezZsLm7bCPh3RANiZCX1an zdW-1FKzncEH9GZj6Drf_?FPcm_N+w5+X9~Vo)kh4Nep3!cBuZno|8EYguEzYWYPoH zCPeyp^-Oq&6Pv>pi*-5)J&hy`=5CQ0If2LV2}e0-l*A${hm8gPCHt%R_3~r9W})^b z{!c*GIk4Lzci}8&Tq9TYsufH`kGp}?Ys8BdCm^ZIdlV2k>%1&5#6c>2u_-r(wc`YcZCnK@$+zMJ^SE82282;@8j5gK1ibc^P*(G zc!J*<`P|9!BAEThe@+25!H2}ZE`G4gC2y@)H|tT)c^>~=#;vdjj9)|4%fbSSWNDD2l( zsYc(KmbM3hq8l5yqqq!e=dkMgf{j(HTQfbQS2WQK$NJ*%wXLbGi{HY70UXe^(9VcK z>p~|Ug|(VIOSh>WD~vT+o_Odb5GMy1t6-1uZo|VlDGv%T?|UEzi2S|Shv*`$AY}sK z5r-HBGbl-_fUlAYK+fZ|Zfdcq{3PvlgF=%R51C2UhF9zcvti^_w2D)XiK9h81dHeP zKF(NwsXXcz%7cbJgH8gW_$Qb#o}r$_*4i#+Tdu9qCoXE5fZ4Iy- zv!-GvHVy@FlH?LhhN%n4%YozD82O6hV7V7R;s{kIz~(rB?t<|h7$IQ(?4@oQi--m1 z2q5<$^4~ILJy?Vp?}QsnoCm~;-Odw@ad4oioG(xV-P+{9HglnD3dIGOf+I&8x-gqK zTMdP;&`0d^0^E962>aj>v>`DNS~G_pR6uIWN7Fix*ayt{0&Xap!7a}u9x*_9HpGar zbd&M^ZqglZ8@$X;?yV9P;CeZHg&nli>z3qP*uK(n9?dd zZk1CL*iy7=GSG@LqDw%~T27@rkH)W3eos%WXnsGtxmFCW#$X+cofNy8e9qCcr_lwV zZM%SBPXGMp@9|7~`3iyrO==2oSQ4~HLqc@qVGqzHvETOEx@9kAhVj8C?iKQW&SiOs z5pjqV$(;aVAd3+W-y&5qvkgXoYX?WmrAHcE@T&F^@W!#A05hXprbL(`YC6;eIz%ob zsAy5WURo?!FiBc1GmOaN3MqN97Ew)t+!}_YMRteYw7E_G0=BK-W0RwlASVNeDm0$D zOcK%ohs-oM*P~3Vr}ryCx~$k?{Q%p_HQ9yr&fWiZtoX`1n~!_Wj^xKAu~17Zh1ViN z^qH@!K!s%C>a_)NTVskHMvegaaA?zJ+bx#zYL_k>P9_QRT)f*B!@J16stukjgYh-V zJATx;`=cA{qcJ1W-(UwFE(QKZjBr5qt}7A8(l zxuHnEc_F`}aQ54vHxm`HK<@5kJkH~)n%%BI=3RP6x=*I^xptkPeW!`~jn%Qm!g=>t zqEU;wb;Rz#pb%}Y?GQfj^`xT72QQ1y&^m+lDX}cgsPinUmnE5RyH1FN$Bl$(i9jkX z=+C-V49Gtrql3NTs6;IR;d|wz?>q!9D>GGg4*sO#pOl2Vm=c`tF_jjq^6q_|18^tH z_vmA5v$1X4&c?QF=NsF$cVlOhjcwc3#Xrs`3HDld7~jNWMN*MX_$UL+n&#`NGfjk z`M?B8l_D?T|L;3&f5i3`i&!y-sC~j2ZKS{F{=6nk~47H1GJK#2%$e43+m=R zsvNv^D6YUYevN?nVUi6F7wS>C48X_C6g0fQ%`$rKhROXqlMd~;N;v#EsD!*x+V$9 z=JTvqrA(Bh8Nr|7TOzC+7$((JMxUA)y7G`rw&Cxeq_?FFdeMaEIKMyYtd@TXiOAOZ z84FKiBrByx1N@Y~(1QS=Ynw2EJT2(Is6TfAAIT}fr8fX{${#@Cdg1zG7ZWnv%<+*J zG@^*$R*uFnNP1MDLuOK*q%Tun8L8+;a z7dS_X`vVz@?Ipq*TjB#Ag8SZq-SVxNQ0>GezBpSQJ1W0`ayi!8 zY|CF*0s*IK$&n2;6E!0F(FxE+MDF%b_U(h*{%fdoi^zxK#L6=Rk;R}U=OJ}Yz}8cL z+wb;pDTKljF`;pxC!O-^PNO3oM+syjc}(zAag*ZT-N=Hxy;bxBH2oF^^>_--B7oVn zBsdr<4rumCOo`ZjDRttRbPoXuke`R;?XoWh>^i})1@O;~Em$jX@HIo4nv)Hi))ZF> zJ=2vD+Q?5F-Ge=T4fQbw4Y$G<;4b@c3gjvKk2P?Npq;x(xx*-{Q7jWq1ji$=jGQm5 zW}Nhr9zpBS?RN>7#cVCv6QqC--L}R|Ki8uPhY(Us#-A1zCYe8Rawtr|9#)G~iY zf!EE7^>4yTKKUT(H1g2EL~Hj5K{JDCj0V&x1rg z`_-Rsqo^mbdzn#X)8uf0Fn{PaYa--zkK1TOK_}``Pxi$5=cbETz?Hp;#l$APwYnK>8APt;UBr3GfvhHw0HK$Q%vC{A8?OFxvveu_w5gNXPB7v+C zjY>4XdprpIdThGnu(EGaH#^SwHat;+j$iEU2073m!#O1|czN}=VhchIFX7G{=O`h- zN@w&b7TYWvtVL#s7jm4x|6FejYiEJtu4>x(!dwgwPg^dzgL`2(M7u&`L8`n% zck|n9mWd~28`5!?=`!tTO2SjrtPzn!66ETp>o{!-?j1!!M6zNxhMa zjLl3*meh3f15+WBXNmNfH%{8nd@3QdwuoQ5>G-w%5-_tap%l5;u%c?#(xBa5k3N`W zRHkS+J%;-&5GY;{H-01bEyn3OptjUsTZfArC&UCzEtzT!r{T9ATWld`iJ&#`*Q@PA zfdOT-qp#Rnu^x5HowIME+?N;p;j{za^C!^WeCZ-ffq1v^TIymt~LkwVrjur3c%QdmR%Y<}N{J658^ zABu_-P8E)jp_I{R(Q=Z9$ooYk5V&jT%Uc-ajy-);sh$!WaMNMAQ@#p(QB8USNAhkk z*EqKEHyPPiJvc=CIKc&>F=YiYqBV=5kghow$~R-SK00Y#`eGr)Vbe z!7tI(2|j3pneeJ)6~^75cSO*hcA4}r&OR;?BvmV)Cs-P!ElC7^5erY;i1U4${7}uo ztJ?f@^MRG+QSe}kQdElPg!EJhUw6&iLmOvymgr(y!jxQcIqKy~%gLxpBO3ZzMbp;q z1DHwwR=W7}bcYWG*VO#Q+Ya7Dt{HEk#ZO+XxP}HBw+M9hlwlWnKSTm9)h(320zt1( zv-Gqge>OMHlmJOcsIi#z?e``HP$uw6sMRf>wuV&T22hVKa3CQ;OUSzUU5ttX5kjXfsf1MZsm!G}0~{GIoV$rza14lJO8l@s z$LpCx6fqtx#Sg&dx@+&U->{+G4SsW8d^(!EkB4njS|f|<>q}fKWED0=2uaFNO<$Z% z3&voF4M)P9OMg8_V@%|M_bM8LQ4@wLx|Kz!Ra|6|Y>Sf`k@}LWxBN-e@(9V+&P4rV zzC=8!R$-wPmo{HmT_c6nDD=?W^_77r8BNucwhF+3qXkr|L3kZYg_G_>Dbl)d+(3~9 zRy#7~JlWfUh>%;QRT0MFd-bjVc7g&aL_=@^wu_wI*=18og0b=Ju6-W~$+yY_EOSqs z2l;e@RS$P>@9;j)$WS!(OFpc#nVqP!LCDriRnghUKFEim!eTdPa+aaNpk_o;cF|Wm zV_?_8v|b)7N$RTdPKx*G?+^QCXTxRX@i-++b447hA&Cu$vfSt7qBRM-ziwXjNpWHA zl?CRV4X4})PYp!n0w@D_Ep2s3KVyWCH1*WUKbP`Dxf6!x?5b2*m|+YKEU_im7O6r5 z_>{C#W?e8E5*tbnZ@G~XiZ>b!UKCCq&o(#8t?~u;E!;2qn(4b$46qTJTUojp>I0@v zxtzWzFZ{ZBIx4)cA93zUEe9lzQv-(ldjv}NQrn`!ZN9{p;pL|2SSF|)ksKLL_d zEekjRyD}@N=h<*5C~o|26S22&oSs?lH3gH8IER;`sOxwDVccc7SW)Nua~RsX0qIM} zviO6%DrH>GuSz)ou^rlv9t-g~>T)ac%*jEz5_}*)fWO94SV17{Y`r z`b|QQ`zo5vP9ogiROf&!)btp1r3ya}waju_SnYVAlVzvly!>Q>0Cj=^I{<&bDHo*_ z2SBUyR)Fs!IWPpNFfXOh+=}2ayCW=d~|}t z5Y07A3b=uJax)Ydeac;u93`-{I;$D#250z_1HRtvu?(InSA_`T@YV>>=ZN5MMKdec z$8c>3x>`b3I)*Ll=V7I>u*w<>(fe1{Zz0d;3=~VfiO@85R(0h(CN);BDxQ zBJ`@YLNy=sWNr|+0Y-RlC*ip-KVihjqzxU94;1A!e1Ql3vE5KsV$)1wmFo8^GCeej z3$i3H(~7ee0pZ({Rup0moG={(q1+gUI&yGJE(6NkbmF1^Ul2sAt}TzHh`U-;3WMknrGEuY#0e#Fpc`HEQu3L^8s?q$9y2ZY$Ge?z(&=spop`SW$IzI22*i ziVq!g!}WZ-h*3iEN_T?zu|~N>VPHZ?=`X%#`YEm94TUDfj^8{%=xR&W)RVI1F38Gj zISos}JN&W3Rvq~>rga?s=5Z`Ri`tAI-yKEMJu3rqf0uEPut`?Qag0yWi9>@Nb0HZA zJy*addO=?k>?e>e_E++=X688U3O3~>#va9 zkhw)wF@XCyZJ?V25R6P2U{y!EP@)X zi5?D5MWnpCrFM?J0!iL7mf4{}e3&QD4RO2*&Iq+u;~=A|EZ&N*Xy*3UV~Fl^5y=Xm zlP^JXJrKF)vocwhmHRDHz!@R1`*I5e88f1}I*pIZex15MxFL8M5bn;1&kjnUDr|Ld zh-o1+B#l+6rGwvoeJ6g$-HpQ~b1@-)oVnj5ILMo4f>t3t7M?SE1S{|D3rAv5hmAeJ za7&laINgyZIt`YL-VZ!AI0-DPL_g9s0%=Vk4DDvwa!v!nKq;5sbniREN{cC(@qaJc zq;D88p9&5&c&K+qbDv$u*1S$Y7YL8FM9_E!N#FU^n>%TbSn&|S++1lYwOqKpHZPOy zz?bc|qO|7j!4+e>V)M)znV%thzk?8Y-ommpN{9NQGHDH&xckL$$QcEt`a zkI4i3JC0Ui5^wS5H#*LWGA%H6Q-E%;)$E$qEN0tLI`8pWA_d#^-loxH5I)JM@?-nR zjr>rp$beZO!YZX#^=>Rhw;M zSFVSQcm@w_cU@QE$~=mFw%QPdX;>ogf^uC$|or*(JX{8kk!1upc|s?uA(_E*3ioz zVPFX=@TluN^oo;yam@dTyP8KIB z?Fbt(fhb4H1Z@(MVRRS{EDFc^=j{*S(STt}sqywJ2@Bq0udta$OGDWLlN*Ss`1DOK zC}pM^hVPogc7z!F-KAEEF2CZ&W0Ikx>wj)RUuD2~>d?*MgM*iw#i< zj$j4gn81*{Q?`@3heF3e81?#z#S3&M9Qdy(se{zqGn_!e7h6;vXhr2A&(uFij6&7lc1% z!OjP*fpZ_pWn^{oLY_1Udlt_7ms|lu@7phIc-h0)2pEc+^#6E$218#fvLDLqiFlJ; zIEmmOk+@E~DO75~B6T>I?TA3&=QA(}>lW~f)FcO!m1sUHhL13UKkpDx9k<3#FCFit zge?g47ti@>z`AQC+0>)}wO*?=o;%m?ieQFVeNzGFt$ebaoyYC~-5QzN^swh_tLRx6 z;%LXRRDU>nqRG{O zHj~ld%k(VL{p~VFde6jKeZK(zB8TuD>e^!_%Gx-b8Fh00giX&dYKr*B=Hb#aWQmTm za3(b8?~>cQUeQdEgueiny1KwMHy9ka?t_-Y2@3K@3mU>`KbIs46Y+ z($9saCQ=h+POHYw))zK=aA$!rjhS?$tA>-RQTbv~@;iFyj2=iA$Btq!n{KIGtm9U# z477-Yv;-4J0B37fAGbx;6%36Kg~+9q6Q@g^QOIIOs&!yH;GI<}R0{nns$jiR(dwKO z{BNoj(~^s~BVp$~pTXm})ZoGIRY{q?P8>Hj4;V~88tHJ!Wye+<4qM&1eQbmALiS%Y zhg|t4Bl+YEHENyi;Rh!gO4S8&FZV+w$0!>(vEk4J!vleSm|AQ znED>xR|->y?tDNxr~*tcvI6gT6A-(lrcLoG1wU;N8*qh$?-LkhH5-j9;A-)`#g;T- z{JgEcE**-MJaGpWTGh?88@I^|oi7317 zn)O~glNtdlebbWAC6IIINwb$tBqh%)haiWaJ*v33SH#TBh!JlZ2AXk0wfaS3ruc=9 zJvbU|rF)3}coSY2_A`F59QX`12LVt{pPXmM1x|-xZM+-0p7+{-&AcF*jbm4C!PNLd z=N3vSb<3O&ou*~U`3g}mkEj>~frTnfdB%6~(UcxUJ^@K=xUkN2cVBjwLIvrT zi$adlbd%1kb=mx7o|cxFbvau*ay3`{ywt_UM^Pt$=i9N%wJFA$&g{l)=bB9Ad0zU_ zS^B5H#x0S@RX03qb8~Y>rkt*}Z2su5XB*>_-N9^n>*3qUk&09FY+Lqt@${>00R2Qo z-a}(;>+(D`*5m8*e(%}o{0TSv?~{|!$RpY{w>PkyT;RO);j=YsF0rQdak?U`0dt1$ zy-X0(FUxBuCylPQjJACzsSKb0L@R5{A`MtFr~N*~`7L_@0D{_2YxhT$-Wpw=f7)Ax z^|Qff_lvKnxX2sD{Dpzn+Il~OX_o4GY7K=mc4O+{`HuCT(Uzt&0hH}#^Dw%+hAJ)E zlzAyRv7sw#%M0q`=?UP?j&axTx`AWccVYXm0;5iZe~fMX%1&?!5_M0L_=X3Uv>1d0pC_1Q$ z89oa&=WF+7=O*V_leHtO)#}@Rx;vwdaq*s)$=Zl*ZW;lnptq@)VJ~hK8p-GoZt?VV z4##NAd>_>6f>+dwJhp!yE?cFvNy=knUw^@*0s7hXB?D8D{^0)FTA@YB<(7RSLOSO@gf_(sogw$4=r zAzoPjm@Pfe+vrx&&6OiltC#00nRU=EmVA`(SA#O#9rAthcQ2x8k=j&-yC~V9u@m!GC5S#_*%EPh4R|5%uzYb5ejWb2j%Ze6T25nA=)Cnez4) z6p{x$g}oILd17NUAnOCl&h*x1V-7oJ&2 zmYiqz6DjK60`r?NQEzAEsJxpg3eAo8SQiH z^4Pa?7?K6GrOj&OWaf4hGkYU2B(ho0TNH|?TJ(_j&FuWv;q|q*)^v|i+x#kRGg5=7%?b_oq*K<-EAa_zD(+Ytu@T*- zo;JyjDv5kF(?Ij!ylt<+-wJX|;hz$RifY!rg96+(orZw9O!}fBTSaAo?|qjmV#@~B zbo|S-b7iK5`}numrra9PYkOwZP?Hfyl_Qy0siWcs;%x>f{Y$UtyVDM2S9$sP!+m=F5W@(1~x#Ywh3Dg1G@(`0&+TgOD8Eb z%3VX73p4#;jvHYbhV@v#$(8>RIcRic=W0ee(V zJ<`YT;Q`YDSzUM!r>cIvA((n(&lXCHt;eUsiJ_sPS6p@jqRl>rH(Ob+Gr&h+fTrqF z)rY0t3TGM=3iNXF{;sAD|xjCRLJBKOuOnu0KEId4ZXr9hjTU7^vM=vo1n~~lA*XQfA zwcG1JHVa=8!!KOj9hqd$-wa)LS|&MC7h^r1 z_tdbeV#bA2k4-y;KX~`Z<$qubC~-bQv$6j`@-Rui_?g0_TX%xZrpHeF@DYa-p7zO3eS6o$Erh4Yo+1qd zNN0*8ry{RPa$W)tW6^60xTzvWv%1#?)x$xgQi%~b6MPRAEYZl7@espYAFk8u7_xFj zf9^)hnJQUrmJVMRA{+IIAaYrPA;vPCfXEyv*>y_xO`uU$Q8!asU=uA{Y{81gFV|cU z8)@0s9$v4dQ?V-SeCzhnfpm}bBN=d1{IdFQc6RiWT@*_{a7k~MfETOYO&LR!9!V&7 zSak(~puC^Y5as;l#@Q-TEIe-2Y6th7=QaB9L2fWSauwi@_(tmR$SkDOePYHVrbD%} zMA5DJ5Lm~DlE@=)J>f-o+!#Rdg#A137jy8G&K zV`NivUfJDLkfWSxA@8$4V#KZ*4>}*7u8w9mQR{Xn;jL##D1+O#em*7mcss)GLlxP9 z*=YklzKv1t4QvOYVhn9)7vgtPyZC)|+lPmszAB1Ky9^m#suJzKn4`H#o@2~?nnaOG#|F;j`nuVTz=D|-+=h@M?PSJ9DmJUnG3XjQ|S$C71)68Fy4CU zkaUTxYPt62Xx_`i=~gUlQekC!Y+YvQEPRsIHL9$jkK{zv)V5!6FpYDOufOt^>m`^{JsxV$UeKxs1(9tu7|#Y z4W2Gex2txYduf61cjmW-j;_z+=3t%Ei0?0V)BKqvuf@*~*~d4lO0OS}dLPe=9FG~k z+`S(G4sKrWUM$c1ub48gJ@T)cDs!60>xEI7?6O z{WylVQgk~IEUtTJceA>!Po!!HJ=^Ym^Wj!6f@Dr|_)Dy9^(Kr%e=#Q&ro(TAJ$}Ud5d8jZkO)e);li<1vYjL}b-0WP{&z-mC@-fVTKu+7u#o2Ejj_CT!Sp8i zW)Q^SCQc-cVk7Q|v)s7zt^qe!zQ(uwX|JGm%|6sp@5_3dIUHcn*L_zDQI@G`W`5Gb zxGH-342Te6IkwBj4bE<+@PJO%HY4E8!@$Q%L#x}5d(YJCbYq>AX}j)V=DXtO#?2K) zb&!jBPG+0?YgSYw3PzRp=y%^Dg4lPyl~>UB2ZRqbefgus)Y?(Xch(gHI2@N_Q%CAt8*eZH{m>>st#Avug`I00*g1Tt0$eZzTW(;O`hc)$&(+`TX3OfHEzHtPyDI9 zuD!0QAF;Zlu+LS;9>n9mqF1h9T!@(Kx~FdOJpqt?@cPDT%4{)+#R)Ax6>1eQi&>wg zu5M=f5l~0S#JUw&R^ald&5dd@eMF`0t1u7KX;-2ZiB0(8EA?*?Hfqfn-6pYD%au{y zS~k#dAkWNSTkxbUxuNcas6Nzkxn-f!PFY}g*jmQT* z>QDq7M!G(9kAKoqJyghIDG+)&by3^RSc%$Dy~9%lcsIF>77H3W zc^@`w=HZ)^<5{2&By1PG`8`w);&|DCA%6b~_5I!JIq8F}^!4eM`$;N(VRG`;j2{t= zK!<;XqK=v$k#1vn!v)dT2RZ}CX@_4jhbjds3a4VkW~7;Rp`RF#dS05J&#tYY`FyWM zQQQdus2ZSot}MT`7eWDt^ckILMhop2?`x!s*{J)46r6ceK@A61^-ZP+fmAtB3$yUh zFg#|@IwLiTL|0)Fk?scdpE-ESwJ1H(RJ`FELOEobzS*yq}$Gqt% zH!ejhNi$4eqbM#pOhXq=5BXDJieZYmVTyTr7iMIVe)^7P0iJ?Za(r02Mv;P&N@fp6 zLb_3rqJ(8(d~{N3US_OpcN+xgpORsc0#h@6O2qS7sQ+Cu6I&-ocRhPM3tJ}uos*kW zr0m2b^~9t^G`%d{2n_{g%pR5Og!s4&jqJpja+QjJ{q6P+;4AaZ_D*>MfT>%W?vJM3 zWp;Ky^Q8m9ein*AO`BU0UBWa#01A7LIWkz21u`W55JF(>3$t^wf@Q?xp*Pf z(JnBV>&N(j6V~41gX914{Wt=O=sb0Uw65j~w7cRBK#zOge?H5iI7z(xMdkUhPUg3p zX$PAI3>42pzLuj&P#HU2=&{UC^OtQHf9s>Dc%XbchyhF?24n~bkub{8d zi_8g;AS=e7**pWIbdn-@gqAw`?(WbHzr=?tnq5J#c*w=O@Cjq zSc8?`=p50zLpJDW>(d3zw}|7p75BLX8viJbFXh#J-``eaMa?8?1VhMPltp4NsECsY zArGXdv+GkT-dRT+Cn=v6-%8=vF)pA6{F z(f$vHje&*j|Hbe(6;uU#^qH#!0|Jsl1OmeNTZqqngMZ>D^}iTKb~g5Qwx6@zU#UR< zTN267-q=4`40Ip>0bQ~I0pb6H;s*2oq3Ai9*czKS{sBu)QCF=x$BUu+>_8?o5D@A= zU;xZNV78_fW`D|KT*R+RJJC!(`>B}&C?Fv8e<0>?{(&$tHv3exqt%}f@hEjwO$s`~ z^Uuo9z(7EM-MGKE2LIomef%%gm^eDxIsQqA4_8-h>M8ZL|5R=a91sxl-_<|&4gRkL z{~(w-S{VPK2@Pv))n?HCx}Tq|(|&3L`ycf)NdHma!q(ct)0g8weQXNC{ zapd|Ggy-{a{Ie@Qk9-#8S&i)q#syYS$ literal 0 HcmV?d00001 diff --git a/dist/schemascii-0.2.1.tar.gz b/dist/schemascii-0.2.1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..d7768e722ab9e06272e88f4b3322bd0a55d53d28 GIT binary patch literal 56043 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 YWcm32??r0+5`lKw%I1ZVj)wAo0M9s=w*UYD literal 0 HcmV?d00001 diff --git a/format.md b/format.md index 0f9f7b1..ca749b0 100644 --- a/format.md +++ b/format.md @@ -56,7 +56,7 @@ For simple components, this is usually just a value rating, but *without* the un Examples: * `C33:2.2u` -- "2.2 µF" -* `Q1001:pnp:TIP102` -- "pnp" or "npn" to determine what kind of transistor, just the part number; printed verbatim +* `Q1001:pnp:TIP102` -- "pnp", "npn", "pfet", or "nfet" to determine what kind of transistor, plus the part number; printed verbatim * `L51:0.33` -- this is rewritten to "330 mH" so that it has no decimal point. * `F3:1500m` -- rewritten: "1.5 A" * `D7:1N4001` -- again, part number diff --git a/pyproject.toml b/pyproject.toml index 5743437..a62d208 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "schemascii" -version = "0.2.0" +version = "0.2.1" description = "Render ASCII-art schematics to SVG" readme = "README.md" authors = [{ name = "dragoncoder047", email = "101021094+dragoncoder047@users.noreply.github.com" }] diff --git a/schemascii/__init__.py b/schemascii/__init__.py index 9206c36..a371b3f 100644 --- a/schemascii/__init__.py +++ b/schemascii/__init__.py @@ -8,7 +8,7 @@ from .utils import XML from .errors import * -__version__ = "0.2.0" +__version__ = "0.2.1" def render(filename: str, text: str = None, **options) -> str: diff --git a/schemascii/components_render.py b/schemascii/components_render.py index 0950dcc..7b9598a 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -8,6 +8,8 @@ sort_counterclockwise, light_arrows, sort_for_flags, is_clockwise) from .errors import TerminalsError, BOMError, UnsupportedComponentError +# pylint: disable=unbalanced-tuple-unpacking + RENDERERS = {} @@ -311,7 +313,22 @@ def transistor( else: ae, se, ctl = sort_for_flags(terminals, box, "e", "c", "b") ap, sp = ae.pt, se.pt - mid = (ap + sp) / 2 # TODO: slide this to line up with middle + diff = sp - ap + try: + slope = diff.imag / diff.real + except ZeroDivisionError: + mid = complex(ap.real, ctl.pt.imag) + else: + try: + diff.real / diff.imag + except ZeroDivisionError: + mid = complex(ctl.pt.real, ap.imag) + else: + # From wolfram alpha "solve m*(x-x1)+y1=(-1/m)*(x-x2)+y2 for x" + # x = (m^2 x1 - m y1 + m y2 + x2)/(m^2 + 1) + mid_x = (slope ** 2 * ap.real - slope * ap.imag + slope * + ctl.pt.imag + ctl.pt.real) / (slope ** 2 + 1) + mid = complex(mid_x, slope * (mid_x - ap.real) + ap.imag) theta = phase(ap - sp) backwards = 1 if is_clockwise([ae, se, ctl]) else -1 thetaquarter = theta + (backwards * pi / 2) @@ -343,6 +360,7 @@ def transistor( (mid + rect(1, theta) + rect(1, thetaquarter), mid - rect(1, theta) + rect(1, thetaquarter)), ]) + out_lines.append((mid + rect(1, thetaquarter), ctl.pt)) text_pt = make_text_point(ap, sp, **options) return (id_text(box, bom_data, [ae, se], None, text_pt, **options) + bunch_o_lines(out_lines, **options)) diff --git a/schemascii/utils.py b/schemascii/utils.py index 9357b79..60dd48b 100644 --- a/schemascii/utils.py +++ b/schemascii/utils.py @@ -157,12 +157,14 @@ def find_dots(points: list[tuple[complex, complex]]) -> list[complex]: def bunch_o_lines(points: list[tuple[complex, complex]], **options): - "Return a for each pair of points." + "Return a for each pair of points." out = '' scale = options['scale'] w = options["stroke_width"] c = options["stroke"] for p1, p2 in points: + if abs(p1 - p2) == 0: + continue out += XML.polyline( points=f"{p1.real * scale}," f"{p1.imag * scale} " @@ -243,7 +245,7 @@ def make_plus( def arrow_points(p1: complex, p2: complex) -> list[tuple[complex, complex]]: "Return points to make an arrow from p1 pointing to p2." angle = phase(p2 - p1) - tick_len = min(0.25, abs(p2 - p1)) + tick_len = min(0.5, abs(p2 - p1)) return [ (p2, p1), (p2, p2 - rect(tick_len, angle + pi/5)), diff --git a/test_data/test1.txt b/test_data/test1.txt index 086787a..328345e 100644 --- a/test_data/test1.txt +++ b/test_data/test1.txt @@ -29,4 +29,21 @@ -------eQ4c----- b Q4:npn:TIP103 *------ + +--------* + e + .~~~~~. + : : +-------b: Q9 : Q9:pnp:7476 + : : + : : + : : + .~~~~~. + c + | + | + + + + !padding=30! \ No newline at end of file From ed132966b620b9cea9ae12c80ce06e8ca1ddbb1a Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Tue, 7 Mar 2023 14:53:04 +0000 Subject: [PATCH 05/52] autogenerate documentation --- designators.md | 142 ++++++++++++++++--------------- schemascii/components_render.py | 52 ++++++----- scripts/cdoc.py | 53 ++++++++++++ release.py => scripts/release.py | 0 supported-components.md | 17 ++++ 5 files changed, 174 insertions(+), 90 deletions(-) create mode 100755 scripts/cdoc.py rename release.py => scripts/release.py (100%) create mode 100644 supported-components.md diff --git a/designators.md b/designators.md index edd5fef..cc347da 100644 --- a/designators.md +++ b/designators.md @@ -1,71 +1,75 @@ +# Possible Designators + (copied from and edited lightly) -| Designator | Component type | Implemented? | -|:--:|:--|:--:| -| A, ASSY | Separable assembly or sub-assembly || -| AE | Aerial, antenna || -| AT | Attenuator or isolator || -| B, BT, BAT | Battery | Yes | -| BR | Bridge rectifier || -| C | Capacitor | Yes | -| CV, VC | Variable capacitor | Yes | -| CN | Connector || -| CRT | Cathode ray tube || -| D, LED, CR | Diode (all types, including LED), thyristor | Yes | -| DL | Delay line || -| DS | Display, general light source, lamp, signal light || -| DSP | Digital signal processor || -| F | Fuse || -| FB | Ferrite bead || -| FD | Fiducial || -| FET | Field-effect transistor || -| FL | Filter || -| G | Generator or oscillator || -| GDT, SVP | Gas discharge tube, Surge Voltage Protector || -| GN | General network || -| H | Pin header || -| HY | Circulator or directional coupler || -| IC, U | Integrated circuit | Partial | -| IR | Infrared Diode | Yes | -| J | Jack (least-movable connector of a connector pair) || -| J, JW | Wire link ("jumper") || -| JFET | Junction gate field-effect transistor || -| JP | Jumper (Link) || -| K, RY, RLA | Relay or contactor || -| L | Inductor or coil or ferrite bead || -| LA | Lightning arrester || -| LCD | Liquid crystal display || -| LDR | Light-dependent resistor || -| LS | Loudspeaker or buzzer || -| M | Motor || -| MCB | Miniature circuit breaker || -| MIC, MK | Microphone || -| MOSFET | Metal-oxide-semiconductor field-effect transistor || -| MP | Mechanical part (including screws and fasteners) || -| NE | Neon lamp || -| OP | Opto-isolator || -| P | Plug (most-movable connector of a connector pair) || -| PCB | Printed circuit board || -| PLC | Programmable logic controller || -| PS | Power supply || -| PU | Pickup || -| Q | Transistor (all types) || -| R | Resistor | Yes | -| RV, VR | Variable resistor (potentiometer or rheostat) | Yes | -| RN | Resistor network || -| RT | Thermistor || -| S, SW | Switch (all types, including buttons) || -| SCR | Silicon-controlled rectifier || -| SUS | Silicon unilateral switch || -| T | Transformer || -| TC | Thermocouple || -| TFT | Thin-film transistor (display) || -| TH | Thermistor || -| TP | Test point || -| TUN | Tuner || -| V | Vacuum tube || -| VDR, MOV | Voltage-dependent resistor (varistor) || -| VFD | Vacuum fluorescent display || -| VT | Voltage transformer || -| W | Wire | (implicit) | -| X, XTAL, Y | Crystal oscillator, ceramic resonator || +This is a list of all components that Schemascii *might* support. For a complete list of all supported components, (generated from the implementation file), please see [supported-components.md](./supported-components.md). If a component you want is not supported, have a look at [#3](https://github.com/dragoncoder047/schemascii/issues/3) or fork and implement it yourself. + +| Designator | Component type | +|:--:|:--| +| A, ASSY | Separable assembly or sub-assembly | +| AE | Aerial, antenna | +| AT | Attenuator or isolator | +| B, BT, BAT | Battery | +| BR | Bridge rectifier | +| C | Capacitor | +| CV, VC | Variable capacitor | +| CN | Connector | +| CRT | Cathode ray tube | +| D, LED, CR | Diode (all types, including LED), thyristor | +| DL | Delay line | +| DS | Display, general light source, lamp, signal light | +| DSP | Digital signal processor | +| F | Fuse | +| FB | Ferrite bead | +| FD | Fiducial | +| FET | Field-effect transistor | +| FL | Filter | +| G | Generator or oscillator | +| GDT, SVP | Gas discharge tube, Surge Voltage Protector | +| GN | General network | +| H | Pin header | +| HY | Circulator or directional coupler | +| IC, U | Integrated circuit | +| IR | Infrared Diode | +| J | Jack (least-movable connector of a connector pair) | +| J, JW | Wire link ("jumper") | +| JFET | Junction gate field-effect transistor | +| JP | Jumper (Link) | +| K, RY, RLA | Relay or contactor | +| L | Inductor or coil or ferrite bead | +| LA | Lightning arrester | +| LCD | Liquid crystal display | +| LDR | Light-dependent resistor | +| LS | Loudspeaker or buzzer | +| M | Motor | +| MCB | Miniature circuit breaker | +| MIC, MK | Microphone | +| MOSFET | Metal-oxide-semiconductor field-effect transistor | +| MP | Mechanical part (including screws and fasteners) | +| NE | Neon lamp | +| OP | Opto-isolator | +| P | Plug (most-movable connector of a connector pair) | +| PCB | Printed circuit board | +| PLC | Programmable logic controller | +| PS | Power supply | +| PU | Pickup | +| Q | Transistor (all types) | +| R | Resistor | +| RV, VR | Variable resistor (potentiometer or rheostat) | +| RN | Resistor network | +| RT | Thermistor | +| S, SW | Switch (all types, including buttons) | +| SCR | Silicon-controlled rectifier | +| SUS | Silicon unilateral switch | +| T | Transformer | +| TC | Thermocouple | +| TFT | Thin-film transistor (display) | +| TH | Thermistor | +| TP | Test point | +| TUN | Tuner | +| V | Vacuum tube | +| VDR, MOV | Voltage-dependent resistor (varistor) | +| VFD | Vacuum fluorescent display | +| VT | Voltage transformer | +| W | Wire | +| X, XTAL, Y | Crystal oscillator, ceramic resonator | diff --git a/schemascii/components_render.py b/schemascii/components_render.py index 7b9598a..46d06b4 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -39,6 +39,7 @@ def n_check( f"{box.type}{box.id} component can only " f"have {n_terminals} terminals") return func(box, terminals, bom_data, **options) + n_check.__doc__ = func.__doc__ return n_check return n_inner @@ -60,6 +61,7 @@ def de_ambiguous( terminals, bom_data[0], **options) + de_ambiguous.__doc__ = func.__doc__ return de_ambiguous @@ -82,6 +84,7 @@ def sort_terminals( terminals, bom_data, **options) + sort_terminals.__doc__ = func.__doc__ return sort_terminals @@ -90,7 +93,8 @@ def resistor( terminals: list[Terminal], bom_data: BOMData, **options): - "Draw a resistor" + """Resistor, Variable resistor, etc. + bom:ohms[,watts]""" t1, t2 = terminals[0].pt, terminals[1].pt vec = t1 - t2 mid = (t1 + t2) / 2 @@ -122,7 +126,9 @@ def capacitor( terminals: list[Terminal], bom_data: BOMData, **options): - "Draw a capacitor" + """Draw a capacitor, variable capacitor, etc. + bom:farads[,volts] + flags:+=positive""" t1, t2 = terminals[0].pt, terminals[1].pt mid = (t1 + t2) / 2 angle = phase(t1 - t2) @@ -149,7 +155,9 @@ def battery( terminals: list[Terminal], bom_data: BOMData, **options): - "Draw a battery cell" + """Draw a battery cell. + bom:volts[,amp-hours] + flags:+=positive""" t1, t2 = terminals[0].pt, terminals[1].pt mid = (t1 + t2) / 2 angle = phase(t1 - t2) @@ -176,7 +184,9 @@ def diode( terminals: list[Terminal], bom_data: BOMData, **options): - "Draw a diode or LED" + """Draw a diode or LED. + bom:part-number + flags:+=positive""" t1, t2 = terminals[0].pt, terminals[1].pt mid = (t1 + t2) / 2 angle = phase(t1 - t2) @@ -209,7 +219,8 @@ def integrated_circuit( terminals: list[Terminal], bom_data: BOMData, **options): - "Draw an IC" + """Draw an IC. + bom:part-number[,pin1-label[,pin2-label[,...]]]""" label_style = options["label"] scale = options["scale"] sz = (box.p2 - box.p1) * scale @@ -270,7 +281,8 @@ def jack( terminals: list[Terminal], bom_data: BOMData, **options): - "Draw a jack connector or plug" + """Draw a jack connector or plug. + bom:label""" scale = options["scale"] sc_t1 = terminals[0].pt * scale sc_t2 = sc_t1 + rect(scale, SIDE_TO_ANGLE_MAP[terminals[0].side]) @@ -301,8 +313,10 @@ def transistor( terminals: list[Terminal], bom_data: BOMData, **options): - "Draw a bipolar transistor (PNP/NPN) or FET (NFET/PFET)" - if all(x not in bom_data.data.lower() for x in ("pnp:", "npn:", "nfet:", "pfet:")): + """Draw a bipolar transistor (PNP/NPN) or FET (NFET/PFET). + bom:{npn/pnp/nfet/pfet}:part-number + flags:s=source,d=drain,g=gate,e=emitter,c=collector,b=base""" + if not any(bom_data.data.lower().startswith(x) for x in ("pnp:", "npn:", "nfet:", "pfet:")): raise BOMError( f"Need type of transistor for {box.type}{box.id}") silicon_type, part_num = bom_data.data.split(":") @@ -314,21 +328,17 @@ def transistor( ae, se, ctl = sort_for_flags(terminals, box, "e", "c", "b") ap, sp = ae.pt, se.pt diff = sp - ap - try: - slope = diff.imag / diff.real - except ZeroDivisionError: + if diff.real == 0: mid = complex(ap.real, ctl.pt.imag) + elif diff.imag == 0: + mid = complex(ctl.pt.real, ap.imag) else: - try: - diff.real / diff.imag - except ZeroDivisionError: - mid = complex(ctl.pt.real, ap.imag) - else: - # From wolfram alpha "solve m*(x-x1)+y1=(-1/m)*(x-x2)+y2 for x" - # x = (m^2 x1 - m y1 + m y2 + x2)/(m^2 + 1) - mid_x = (slope ** 2 * ap.real - slope * ap.imag + slope * - ctl.pt.imag + ctl.pt.real) / (slope ** 2 + 1) - mid = complex(mid_x, slope * (mid_x - ap.real) + ap.imag) + # From wolfram alpha "solve m*(x-x1)+y1=(-1/m)*(x-x2)+y2 for x" + # x = (m^2 x1 - m y1 + m y2 + x2)/(m^2 + 1) + slope = diff.imag / diff.real + mid_x = (slope ** 2 * ap.real - slope * ap.imag + slope * + ctl.pt.imag + ctl.pt.real) / (slope ** 2 + 1) + mid = complex(mid_x, slope * (mid_x - ap.real) + ap.imag) theta = phase(ap - sp) backwards = 1 if is_clockwise([ae, se, ctl]) else -1 thetaquarter = theta + (backwards * pi / 2) diff --git a/scripts/cdoc.py b/scripts/cdoc.py new file mode 100755 index 0000000..0be1791 --- /dev/null +++ b/scripts/cdoc.py @@ -0,0 +1,53 @@ +#! /usr/bin/env python3 +import re +from itertools import groupby +from schemascii.components_render import RENDERERS + +# pylint: disable=unspecified-encoding,missing-function-docstring,invalid-name,not-an-iterable +# cSpell:ignore siht etareneg redner iicsa stpircs +# cSpell:ignore mehcs daetsn detareneg yllacitamotua codc stnenopmoc + +TOP = ("# Supported Schemascii Components\n\n\n\n| Reference Designators | Description | BOM Syntax | Supported Flags |" + "\n|:--:|:--|:--:|:--|\n") + + +def group_components_by_func(): + items = groupby(list(RENDERERS.items()), lambda x: x[1]) + out = {} + for x, g in items: + out[x] = [p[0] for p in g] + return out + + +def parse_docstring(d): + out = [None, None, None] + if fs := re.search(r"flags:(.*?)$", d, re.M): + out[2] = [f.split("=") for f in fs.group(1).split(",")] + d = d.replace(fs.group(), "") + if b := re.search(r"bom:(.*?)$", d, re.M): + out[1] = b.group(1) + d = d.replace(b.group(), "") + out[0] = d.strip() + return out + + +def main(): + content = TOP + for func, rds in group_components_by_func().items(): + data = parse_docstring(func.__doc__) + content += "| " + ", ".join(f"`{x}`" for x in rds) + " | " + content += data[0].replace("\n", "
") + " | " + content += "`" + data[1] + "` | " + content += "
".join(f"`{x[0]}` = {x[1]}" for x in (data[2] or [])) + content += " |\n" + with open("supported-components.md", "w") as f: + f.write(content) + + +if __name__ == '__main__': + main() diff --git a/release.py b/scripts/release.py similarity index 100% rename from release.py rename to scripts/release.py diff --git a/supported-components.md b/supported-components.md new file mode 100644 index 0000000..f4f3ccb --- /dev/null +++ b/supported-components.md @@ -0,0 +1,17 @@ +# Supported Schemascii Components + + + +| Reference Designators | Description | BOM Syntax | Supported Flags | +|:--:|:--|:--:|:--| +| `R`, `RV`, `VR` | Resistor, Variable resistor, etc. | `ohms[,watts]` | | +| `C`, `CV`, `VC` | Draw a capacitor, variable capacitor, etc. | `farads[,volts]` | `+` = positive | +| `B`, `BT`, `BAT` | Draw a battery cell. | `volts[,amp-hours]` | `+` = positive | +| `D`, `LED`, `CR`, `IR` | Draw a diode or LED. | `part-number` | `+` = positive | +| `U`, `IC` | Draw an IC. | `part-number[,pin1-label[,pin2-label[,...]]]` | | +| `J`, `P` | Draw a jack connector or plug. | `label` | | +| `Q`, `MOSFET`, `MOS`, `FET` | Draw a bipolar transistor (PNP/NPN) or FET (NFET/PFET). | `{npn/pnp/nfet/pfet}:part-number` | `s` = source
`d` = drain
`g` = gate
`e` = emitter
`c` = collector
`b` = base | From 61e4251b6706c982fff7b40d8f75dc5b1e0d7e6b Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Mon, 20 Mar 2023 13:25:06 +0000 Subject: [PATCH 06/52] inductors --- dist/schemascii-0.2.2-py3-none-any.whl | Bin 0 -> 45793 bytes dist/schemascii-0.2.2.tar.gz | Bin 0 -> 56230 bytes pyproject.toml | 2 +- schemascii/__init__.py | 2 +- schemascii/components_render.py | 67 +++++++++++++++++-------- supported-components.md | 1 + test_data/test1.txt | 53 ++----------------- 7 files changed, 53 insertions(+), 72 deletions(-) create mode 100644 dist/schemascii-0.2.2-py3-none-any.whl create mode 100644 dist/schemascii-0.2.2.tar.gz diff --git a/dist/schemascii-0.2.2-py3-none-any.whl b/dist/schemascii-0.2.2-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..1185ff40af1d2791fe418acbad3925acfd6da972 GIT binary patch literal 45793 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 literal 0 HcmV?d00001 diff --git a/pyproject.toml b/pyproject.toml index a62d208..39cf0ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "schemascii" -version = "0.2.1" +version = "0.2.2" description = "Render ASCII-art schematics to SVG" readme = "README.md" authors = [{ name = "dragoncoder047", email = "101021094+dragoncoder047@users.noreply.github.com" }] diff --git a/schemascii/__init__.py b/schemascii/__init__.py index a371b3f..24a839f 100644 --- a/schemascii/__init__.py +++ b/schemascii/__init__.py @@ -8,7 +8,7 @@ from .utils import XML from .errors import * -__version__ = "0.2.1" +__version__ = "0.2.2" def render(filename: str, text: str = None, **options) -> str: diff --git a/schemascii/components_render.py b/schemascii/components_render.py index 46d06b4..7142bf0 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -88,6 +88,9 @@ def sort_terminals( return sort_terminals +@component("R", "RV", "VR") +@n_terminal(2) +@no_ambiguous def resistor( box: Cbox, terminals: list[Terminal], @@ -106,16 +109,11 @@ def resistor( points.append(t1 - rect(i / 4, angle) + pow(-1, i) * rect(1, quad_angle) / 4) points.append(t2) - text_pt = make_text_point(t1, t2, **options) return (polylinegon(points, **options) + make_variable(mid, angle, "V" in box.type, **options) + id_text( box, bom_data, terminals, (("Ω", False), ("W", False)), - text_pt, **options)) - - -# Register it -component("R", "RV", "VR")(n_terminal(2)(no_ambiguous(resistor))) + make_text_point(t1, t2, **options), **options)) @component("C", "CV", "VC") @@ -138,13 +136,42 @@ def capacitor( (complex(.4, .25), complex(-.4, .25)), (complex(.4, -.25), complex(-.4, -.25)), ], mid, angle) - text_pt = make_text_point(t1, t2, **options) return (bunch_o_lines(lines, **options) + make_plus(terminals, mid, angle, **options) + make_variable(mid, angle, "V" in box.type, **options) + id_text( box, bom_data, terminals, (("F", True), ("V", False)), - text_pt, **options)) + make_text_point(t1, t2, **options), **options)) + + +@component("L", "VL", "LV") +@no_ambiguous +def inductor( + box: Cbox, + terminals: list[Terminal], + bom_data: BOMData, + **options): + """Draw an inductor (coil, choke, etc) + bom:henries""" + t1, t2 = terminals[0].pt, terminals[1].pt + vec = t1 - t2 + mid = (t1 + t2) / 2 + length = abs(vec) + angle = phase(vec) + scale = options["scale"] + data = f"M{t1.real * scale} {t1.imag * scale}" + dxdy = rect(scale, angle) + for _ in range(int(length)): + data += f"a1 1 0 01{-dxdy.real} {dxdy.imag}" + return (XML.path( + d=data, + stroke=options["stroke"], + fill="transparent", + stroke__width=options["stroke_width"]) + + make_variable(mid, angle, "V" in box.type, **options) + + id_text( + box, bom_data, terminals, (("H", False),), + make_text_point(t1, t2, **options), **options)) @component("B", "BT", "BAT") @@ -169,10 +196,9 @@ def battery( (complex(.5, -.16), complex(-.5, -.16)), (complex(.25, -.5), complex(-.25, -.5)), ], mid, angle) - text_pt = make_text_point(t1, t2, **options) return (id_text( box, bom_data, terminals, (("V", False), ("Ah", False)), - text_pt, **options) + make_text_point(t1, t2, **options), **options) + bunch_o_lines(lines, **options)) @@ -195,12 +221,13 @@ def diode( (t1, mid + rect(-.3, angle)), deep_transform((-.3-.3j, .3-.3j), mid, angle)] triangle = deep_transform((-.3j, .3+.3j, -.3+.3j), mid, angle) - text_pt = make_text_point(t1, t2, **options) - light_emitting = "LED", "IR" + light_emitting = box.type in ("LED", "IR") + fill_override = {"stroke": bom_data.data} if box.type == "LED" else {} return ((light_arrows(mid, angle, True, **options) - if box.type in light_emitting else "") - + id_text(box, bom_data, terminals, None, text_pt, **options) - + bunch_o_lines(lines, **options) + if light_emitting else "") + + id_text(box, bom_data, terminals, None, + make_text_point(t1, t2, **options), **options) + + bunch_o_lines(lines, **(options | fill_override)) + polylinegon(triangle, True, **options)) @@ -337,7 +364,7 @@ def transistor( # x = (m^2 x1 - m y1 + m y2 + x2)/(m^2 + 1) slope = diff.imag / diff.real mid_x = (slope ** 2 * ap.real - slope * ap.imag + slope * - ctl.pt.imag + ctl.pt.real) / (slope ** 2 + 1) + ctl.pt.imag + ctl.pt.real) / (slope ** 2 + 1) mid = complex(mid_x, slope * (mid_x - ap.real) + ap.imag) theta = phase(ap - sp) backwards = 1 if is_clockwise([ae, se, ctl]) else -1 @@ -371,8 +398,8 @@ def transistor( mid - rect(1, theta) + rect(1, thetaquarter)), ]) out_lines.append((mid + rect(1, thetaquarter), ctl.pt)) - text_pt = make_text_point(ap, sp, **options) - return (id_text(box, bom_data, [ae, se], None, text_pt, **options) + return (id_text(box, bom_data, [ae, se], None, + make_text_point(ap, sp, **options), **options) + bunch_o_lines(out_lines, **options)) # code for drawing stuff @@ -390,10 +417,6 @@ def transistor( 'F': 'M0-.9A.1.1 0 000-1.1.1.1 0 000-.9ZM0-1Q.5-.5 0 0T0 1Q-.5.5 0 0T0-1ZM0 1.1A.1.1 0 000 .9.1.1 0 000 1.1Z', # jumper pads 'JP': 'M0-1Q-1-1-1-.25H1Q1-1 0-1ZM0 1Q-1 1-1 .25H1Q1 1 0 1', - # inductor style 1 (humps) - 'L': 'M0-1A.1.1 0 010-.6.1.1 0 010-.2.1.1 0 010 .2.1.1 0 010 .6.1.1 0 010 1 .1.1 0 000 .6.1.1 0 000 .2.1.1 0 000-.2.1.1 0 000-.6.1.1 0 000-1Z', - # inductor style 2 (coil) - # 'L': 'M0-1C1-1 1-.2 0-.2S-1-.8 0-.8 1 0 0 0-1-.6 0-.6 1 .2 0 .2-1-.4 0-.4 1 .4 0 .4-1-.2 0-.2 1 .6 0 .6-1 0 0 0 1 .8 0 .8-1 .2 0 .2 1 1 0 1C1 1 1 .2 0 .2S-1 .8 0 .8 1 0 0 0-1 .6 0 .6 1-.2 0-.2-1 .4 0 .4 1-.4 0-.4-1 .2 0 .2 1-.6 0-.6-1 0 0 0 1-.8 0-.8-1-.2 0-.2 1-1 0-1Z', # loudspeaker 'LS': 'M0-1V-.5H-.25V.5H.25V-.5H0M0 1V.5ZM1-1 .25-.5V.5L1 1Z', # electret mic diff --git a/supported-components.md b/supported-components.md index f4f3ccb..46270e0 100644 --- a/supported-components.md +++ b/supported-components.md @@ -10,6 +10,7 @@ Instead, edit schemascii/components_render.py and run scripts/cdoc.py to re-gene |:--:|:--|:--:|:--| | `R`, `RV`, `VR` | Resistor, Variable resistor, etc. | `ohms[,watts]` | | | `C`, `CV`, `VC` | Draw a capacitor, variable capacitor, etc. | `farads[,volts]` | `+` = positive | +| `L`, `VL`, `LV` | Draw an inductor (coil, choke, etc) | `henries` | | | `B`, `BT`, `BAT` | Draw a battery cell. | `volts[,amp-hours]` | `+` = positive | | `D`, `LED`, `CR`, `IR` | Draw a diode or LED. | `part-number` | `+` = positive | | `U`, `IC` | Draw an IC. | `part-number[,pin1-label[,pin2-label[,...]]]` | | diff --git a/test_data/test1.txt b/test_data/test1.txt index 328345e..8c9080e 100644 --- a/test_data/test1.txt +++ b/test_data/test1.txt @@ -1,49 +1,6 @@ --------sMOSFET1d----- - g MOSFET1:nfet:2N7000 - *-------- +!padding=30! +----------L1------ --------eQ1c----- - b Q1:pnp:TIP102 - *------ - --------dMOSFET2s----- - g MOSFET2:pfet:2N7001 - *-------- - --------cQ2e----- - b Q2:npn:TIP103 - *------ - --------dMOSFET3s----- - g MOSFET3:nfet:2N7000 - *-------- - --------cQ3e----- - b Q3:pnp:TIP102 - *------ - --------sMOSFET4d----- - g MOSFET4:pfet:2N7001 - *-------- - --------eQ4c----- - b Q4:npn:TIP103 - *------ - ---------* - e - .~~~~~. - : : --------b: Q9 : Q9:pnp:7476 - : : - : : - : : - .~~~~~. - c - | - | - - - - -!padding=30! \ No newline at end of file +------L2###########------- +L1:220u +L2:330u \ No newline at end of file From 74e6d760bc6bff6a8325c4cfceafd64faf209dc9 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Mon, 20 Mar 2023 17:14:10 -0400 Subject: [PATCH 07/52] fix bug with dropping leading zeros on flags --- .vscode/settings.json | 5 ++++- schemascii/components_render.py | 2 +- schemascii/utils.py | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 883f778..e18146e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,5 +8,8 @@ "rendec", "schemascii", "tspan" - ] + ], + "python.linting.pylintEnabled": false, + "python.linting.flake8Enabled": true, + "python.linting.enabled": true } \ No newline at end of file diff --git a/schemascii/components_render.py b/schemascii/components_render.py index 7142bf0..bef8d5b 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -162,7 +162,7 @@ def inductor( data = f"M{t1.real * scale} {t1.imag * scale}" dxdy = rect(scale, angle) for _ in range(int(length)): - data += f"a1 1 0 01{-dxdy.real} {dxdy.imag}" + data += f"a1 1 0 01 {-dxdy.real} {dxdy.imag}" return (XML.path( d=data, stroke=options["stroke"], diff --git a/schemascii/utils.py b/schemascii/utils.py index 60dd48b..610c3c8 100644 --- a/schemascii/utils.py +++ b/schemascii/utils.py @@ -98,11 +98,11 @@ def deep_transform(data, origin: complex, theta: float): def fix_number(n: float) -> str: - """If n is an integer, remove the trailing ".0". + """If n is an integer, remove the trailing ".0". Otherwise round it to 2 digits.""" if n.is_integer(): return str(int(n)) - return str(round(n, 4)) + return str(round(n, 2)) class XMLClass: From 1b24080b93d8a72e479caa97faf02aed534ec223 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Thu, 23 Mar 2023 16:11:56 -0400 Subject: [PATCH 08/52] Update and rename cdoc.py to documentation.py --- scripts/{cdoc.py => documentation.py} | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) rename scripts/{cdoc.py => documentation.py} (80%) diff --git a/scripts/cdoc.py b/scripts/documentation.py similarity index 80% rename from scripts/cdoc.py rename to scripts/documentation.py index 0be1791..4975038 100755 --- a/scripts/cdoc.py +++ b/scripts/documentation.py @@ -4,13 +4,15 @@ from schemascii.components_render import RENDERERS # pylint: disable=unspecified-encoding,missing-function-docstring,invalid-name,not-an-iterable -# cSpell:ignore siht etareneg redner iicsa stpircs -# cSpell:ignore mehcs daetsn detareneg yllacitamotua codc stnenopmoc +# cSpell:ignore siht etareneg redner iicsa stpircs nettirwrevo ylpmis segnahc +# cSpell:ignore mehcs daetsn detareneg yllacitamotua codc stnenopmoc lliw ruo TOP = ("# Supported Schemascii Components\n\n\n\n| Reference Designators | Description | BOM Syntax | Supported Flags |" "\n|:--:|:--|:--:|:--|\n") From e06fad255b5d89db66bf0a1a19ee81fec536b638 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 24 Mar 2023 14:24:35 +0000 Subject: [PATCH 09/52] change docs.py --- scripts/{documentation.py => docs.py} | 21 +++++++++++++-------- supported-components.md | 4 +++- 2 files changed, 16 insertions(+), 9 deletions(-) rename scripts/{documentation.py => docs.py} (72%) diff --git a/scripts/documentation.py b/scripts/docs.py similarity index 72% rename from scripts/documentation.py rename to scripts/docs.py index 4975038..631d7ca 100755 --- a/scripts/documentation.py +++ b/scripts/docs.py @@ -1,21 +1,26 @@ #! /usr/bin/env python3 import re +import os from itertools import groupby from schemascii.components_render import RENDERERS -# pylint: disable=unspecified-encoding,missing-function-docstring,invalid-name,not-an-iterable +# pylint: disable=unspecified-encoding,missing-function-docstring,invalid-name +# pylint: disable=not-an-iterable # cSpell:ignore siht etareneg redner iicsa stpircs nettirwrevo ylpmis segnahc # cSpell:ignore mehcs daetsn detareneg yllacitamotua codc stnenopmoc lliw ruo +# cSpell:ignore sgnirtscod TOP = ("# Supported Schemascii Components\n\n\n\n| Reference Designators | Description | BOM Syntax | Supported Flags |" - "\n|:--:|:--|:--:|:--|\n") + + "\n-->\n\n| Reference Designators | Description | " + + "BOM Syntax | Supported Flags |" + + "\n|:--:|:--|:--:|:--|\n") def group_components_by_func(): diff --git a/supported-components.md b/supported-components.md index 46270e0..cd01f0a 100644 --- a/supported-components.md +++ b/supported-components.md @@ -3,7 +3,9 @@ | Reference Designators | Description | BOM Syntax | Supported Flags | From 44df3c9840c769448c7cd5c63440e610077a8899 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 24 Mar 2023 15:15:24 +0000 Subject: [PATCH 10/52] allow component 0 implicit, alt glyphs for jack --- schemascii/components.py | 7 ++-- schemascii/components_render.py | 59 ++++++++++++++++++++------------- supported-components.md | 2 +- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/schemascii/components.py b/schemascii/components.py index 542bcbd..d7a1c37 100644 --- a/schemascii/components.py +++ b/schemascii/components.py @@ -4,7 +4,7 @@ from .errors import DiagramSyntaxError, BOMError -SMALL_COMPONENT_OR_BOM = re.compile(r'#*([A-Z]+)(\d+|\.\w+)(:[^\s]+)?#*') +SMALL_COMPONENT_OR_BOM = re.compile(r'#*([A-Z]+)(\d*|\.\w+)(:[^\s]+)?#*') def find_small(grid: Grid) -> tuple[list[Cbox], list[BOMData]]: @@ -14,13 +14,14 @@ def find_small(grid: Grid) -> tuple[list[Cbox], list[BOMData]]: boms: list[BOMData] = [] for i, line in enumerate(grid.lines): for m in SMALL_COMPONENT_OR_BOM.finditer(line): + ident = m.group(2) or '0' if m.group(3): boms.append(BOMData(m.group(1), - m.group(2), m.group(3)[1:])) + ident, m.group(3)[1:])) else: components.append(Cbox(complex(m.start(), i), complex(m.end() - 1, i), - m.group(1), m.group(2))) + m.group(1), ident)) for z in range(*m.span(0)): grid.setmask(complex(z, i)) return components, boms diff --git a/schemascii/components_render.py b/schemascii/components_render.py index bef8d5b..c2974e0 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -5,7 +5,8 @@ from .utils import (Cbox, Terminal, BOMData, XML, Side, arrow_points, polylinegon, id_text, make_text_point, bunch_o_lines, deep_transform, make_plus, make_variable, - sort_counterclockwise, light_arrows, sort_for_flags, is_clockwise) + sort_counterclockwise, light_arrows, sort_for_flags, + is_clockwise) from .errors import TerminalsError, BOMError, UnsupportedComponentError # pylint: disable=unbalanced-tuple-unpacking @@ -309,26 +310,35 @@ def jack( bom_data: BOMData, **options): """Draw a jack connector or plug. - bom:label""" + bom:label[,{circle/input/output}]""" scale = options["scale"] - sc_t1 = terminals[0].pt * scale - sc_t2 = sc_t1 + rect(scale, SIDE_TO_ANGLE_MAP[terminals[0].side]) - sc_text_pt = sc_t2 + rect(scale * 2, SIDE_TO_ANGLE_MAP[terminals[0].side]) + t1 = terminals[0].pt + t2 = t1 + rect(1, SIDE_TO_ANGLE_MAP[terminals[0].side]) + sc_t2 = t2 * scale + sc_text_pt = sc_t2 + rect(scale, SIDE_TO_ANGLE_MAP[terminals[0].side]) + style = "input" if terminals[0].side in ( + Side.LEFT, Side.TOP) else "output" + if any(bom_data.data.endswith(x) + for x in (",circle", ",input", ",output")): + style = bom_data.data.split(",")[-1] + bom_data = BOMData(bom_data.type, bom_data.id, + bom_data.data.rstrip("cirlenputo") + .removesuffix(",")) + if style == "circle": + return ( + bunch_o_lines([(t1, t2)], **options) + + XML.circle( + cx=sc_t2.real, + cy=sc_t2.imag, + r=scale / 4, + stroke__width=options["stroke_width"], + stroke=options["stroke"], + fill="transparent") + + id_text(box, bom_data, terminals, None, sc_text_pt, **options)) + if style == "output": + t1, t2 = t2, t1 return ( - XML.line( - x1=sc_t1.real, - x2=sc_t2.real, - y1=sc_t1.imag, - y2=sc_t2.imag, - stroke__width=options["stroke_width"], - stroke=options["stroke"]) - + XML.circle( - cx=sc_t2.real, - cy=sc_t2.imag, - r=scale / 4, - stroke__width=options["stroke_width"], - stroke=options["stroke"], - fill="transparent") + bunch_o_lines(arrow_points(t1, t2), **options) + id_text(box, bom_data, terminals, None, sc_text_pt, **options)) @@ -343,7 +353,8 @@ def transistor( """Draw a bipolar transistor (PNP/NPN) or FET (NFET/PFET). bom:{npn/pnp/nfet/pfet}:part-number flags:s=source,d=drain,g=gate,e=emitter,c=collector,b=base""" - if not any(bom_data.data.lower().startswith(x) for x in ("pnp:", "npn:", "nfet:", "pfet:")): + if not any(bom_data.data.lower().startswith(x) for x in ( + "pnp:", "npn:", "nfet:", "pfet:")): raise BOMError( f"Need type of transistor for {box.type}{box.id}") silicon_type, part_num = bom_data.data.split(":") @@ -380,7 +391,8 @@ def transistor( arr = arr[1], arr[0] out_lines.extend([ *arrow_points(*arr), - (mid - rect(.8, theta), mid - rect(.8, theta) + rect(.7, thetaquarter)), + (mid - rect(.8, theta), mid - rect(.8, theta) + + rect(.7, thetaquarter)), (mid + rect(1, theta) + rect(.7, thetaquarter), mid - rect(1, theta) + rect(.7, thetaquarter)), (mid + rect(.5, theta) + rect(1, thetaquarter), @@ -393,7 +405,8 @@ def transistor( arr = arr[1], arr[0] out_lines.extend([ *arrow_points(*arr), - (mid - rect(.8, theta), mid - rect(.4, theta) + rect(1, thetaquarter)), + (mid - rect(.8, theta), mid - rect(.4, theta) + + rect(1, thetaquarter)), (mid + rect(1, theta) + rect(1, thetaquarter), mid - rect(1, theta) + rect(1, thetaquarter)), ]) @@ -412,7 +425,7 @@ def transistor( # + is on the top unless otherwise noted # terminals will be connected at (0, -1) and (0, 1) relative to the paths here # if they aren't the path will be transformed -twoterminals = { +{ # fuse 'F': 'M0-.9A.1.1 0 000-1.1.1.1 0 000-.9ZM0-1Q.5-.5 0 0T0 1Q-.5.5 0 0T0-1ZM0 1.1A.1.1 0 000 .9.1.1 0 000 1.1Z', # jumper pads diff --git a/supported-components.md b/supported-components.md index cd01f0a..e76a3ab 100644 --- a/supported-components.md +++ b/supported-components.md @@ -16,5 +16,5 @@ and run scripts/docs.py to re-generate this file. | `B`, `BT`, `BAT` | Draw a battery cell. | `volts[,amp-hours]` | `+` = positive | | `D`, `LED`, `CR`, `IR` | Draw a diode or LED. | `part-number` | `+` = positive | | `U`, `IC` | Draw an IC. | `part-number[,pin1-label[,pin2-label[,...]]]` | | -| `J`, `P` | Draw a jack connector or plug. | `label` | | +| `J`, `P` | Draw a jack connector or plug. | `label[,{circle/input/output}]` | | | `Q`, `MOSFET`, `MOS`, `FET` | Draw a bipolar transistor (PNP/NPN) or FET (NFET/PFET). | `{npn/pnp/nfet/pfet}:part-number` | `s` = source
`d` = drain
`g` = gate
`e` = emitter
`c` = collector
`b` = base | From 3aec23e6c1be188f4c3ec22d34230801ac5c34d8 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 24 Mar 2023 16:44:20 +0000 Subject: [PATCH 11/52] some better jack renderind --- schemascii/components_render.py | 2 +- schemascii/edgemarks.py | 9 +---- schemascii/utils.py | 16 ++++++-- scripts/release.py | 2 +- test_data/all_gates_3t.txt | 67 +++++++++++++++++++++++++++++++++ 5 files changed, 83 insertions(+), 13 deletions(-) create mode 100644 test_data/all_gates_3t.txt diff --git a/schemascii/components_render.py b/schemascii/components_render.py index c2974e0..50290b6 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -315,7 +315,7 @@ def jack( t1 = terminals[0].pt t2 = t1 + rect(1, SIDE_TO_ANGLE_MAP[terminals[0].side]) sc_t2 = t2 * scale - sc_text_pt = sc_t2 + rect(scale, SIDE_TO_ANGLE_MAP[terminals[0].side]) + sc_text_pt = sc_t2 + rect(scale / 2, SIDE_TO_ANGLE_MAP[terminals[0].side]) style = "input" if terminals[0].side in ( Side.LEFT, Side.TOP) else "output" if any(bom_data.data.endswith(x) diff --git a/schemascii/edgemarks.py b/schemascii/edgemarks.py index aea494e..3bdbf4f 100644 --- a/schemascii/edgemarks.py +++ b/schemascii/edgemarks.py @@ -37,13 +37,8 @@ def flags(p: complex, s: Side) -> Flag | None: c = grid.get(p) if c in ' -|()*': return None - if s in (Side.TOP, Side.BOTTOM): - grid.setmask(p, '|') - return Flag(p, c, s) - if s in (Side.LEFT, Side.RIGHT): - grid.setmask(p, '-') - return Flag(p, c, s) - return None + grid.setmask(p, '*') + return Flag(p, c, s) return flags diff --git a/schemascii/utils.py b/schemascii/utils.py index 610c3c8..c96b486 100644 --- a/schemascii/utils.py +++ b/schemascii/utils.py @@ -145,6 +145,9 @@ def find_dots(points: list[tuple[complex, complex]]) -> list[complex]: "Finds all the points where there are 4 or more connecting wires." seen = {} for p1, p2 in points: + if p1 == p2: + # Skip zero-length wires + continue if p1 not in seen: seen[p1] = 1 else: @@ -202,6 +205,14 @@ def id_text( for x, (y, six) in zip(text.split(","), unit)) classy = "cmp-value" data = XML.tspan(text, class_=classy) + if len(terminals) > 1: + textach = "start" if ( + any(Side.BOTTOM == t.side for t in terminals) + or any(Side.TOP == t.side for t in terminals) + ) else "middle" + else: + textach = "middle" if terminals[0].side in ( + Side.TOP, Side.BOTTOM) else "start" return XML.text( (XML.tspan(f"{box.type}{box.id}", class_="cmp-id") * bool("L" in label_style)), @@ -209,10 +220,7 @@ def id_text( data * bool("V" in label_style), x=point.real, y=point.imag, - text__anchor="start" if ( - any(Side.BOTTOM == t.side for t in terminals) - or any(Side.TOP == t.side for t in terminals) - ) else "middle", + text__anchor=textach, font__size=options["scale"], fill=options["stroke"]) diff --git a/scripts/release.py b/scripts/release.py index 9d67f5a..bfc6ab6 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -39,7 +39,7 @@ def writefile(file, text): re.sub(r'__version__ = "[\d.]+"', f'__version__ = "{args.version}"', init_text)) - +cmd("scripts/docs.py") cmd("python3 -m build --sdist") cmd("python3 -m build --wheel") diff --git a/test_data/all_gates_3t.txt b/test_data/all_gates_3t.txt new file mode 100644 index 0000000..054f985 --- /dev/null +++ b/test_data/all_gates_3t.txt @@ -0,0 +1,67 @@ +Q:nfet: R:1k !label=V!!padding=30! +J1:A J2:B J4:VCC,circle J5:gnd,circle +J1 J2 J4 J5 +| | | | +| | *-R-----*----------J1001 J1001:NAND +| | | | d +*----------------gQ +| | | | s +| | | | d +| *-------------gQ +| | | | s +| | | *--* +| | | | +| | *-R-----*---*------J1002 J1002:NOR +| | | | d d +*----------------gQ *gQ +| | | | s | s +| | | *--*-|-* +| *-----------|----* +| | | | +| | *-R---------*------J1003 J1003:XNOR +| | | | | +| | | | d-* +*----------------*-gQ | +| | | | | s | +| *--------------*-* | +| | | | || | +| | | | || d-* +| | | | |*gQ +| | | | | s +| | | | *--* +| | | | +| | *-R-------*--------J1004 J1004:AND +| | | | d +| | *-R-----*gQ +| | | | d s +*----------------gQ | +| | | | s | +| | | | d | +| *-------------gQ | +| | | | s | +| | | *--*-* +| | | | +| | *-R-----------*----J1005 J1005:OR +| | | | d +| | *-R-----*---*gQ +| | | | d d s +*----------------gQ *gQ | +| | | | s | s | +| | | *--*-|-*-* +| *-----------|----* +| | | | +| | *-R-----------*----J1006 J1006:XOR +| | | | | +| | *-R---------* | +| | | | | | +| | | | d-* | +*----------------*-gQ | | +| | | | | s | | +| *--------------*-* | | +| | | | || | d +| | | | || d-*gQ +| | | | |*gQ s +| | | | | s | +| | | | *--* | +| | | *--------* +| | | | From 18178a7ac07f513883337eb1c9ff3a470ddea6ef Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Tue, 28 Mar 2023 16:22:53 +0000 Subject: [PATCH 12/52] add ground --- schemascii/components_render.py | 36 +++++++++++++++++++++++++++++++++ test_data/test1.txt | 10 ++++++--- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/schemascii/components_render.py b/schemascii/components_render.py index 50290b6..2c88395 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -415,6 +415,42 @@ def transistor( make_text_point(ap, sp, **options), **options) + bunch_o_lines(out_lines, **options)) + +@component("G", "GND") +@n_terminal(1) +@no_ambiguous +def ground( + box: Cbox, + terminals: list[Terminal], + bom_data: BOMData, + **options): + """Draw a ground symbol. + bom:[{earth/chassis/signal/common}]""" + icon_type = bom_data.data or "earth" + points = [(0, 1j), (-.5+1j, .5+1j)] + match icon_type: + case "earth": + points += [ + (-.33+1.25j, .33+1.25j), + (-.16+1.5j, .16+1.5j)] + case "chassis": + points += [ + (-.5+1j, -.25+1.5j), + (1j, .25+1.5j), + (.5+1j, .75+1.5j)] + case "signal": + points += [ + (-.5+1j, 1.5j), + (.5+1j, 1.5j)] + case "common": + pass + case _: + raise BOMError( + f"Unknown ground symbol type: {icon_type}") + points = deep_transform(points, terminals[0].pt, pi / 2) + return bunch_o_lines(points, **options) + + # code for drawing stuff # https://github.com/pfalstad/circuitjs1/tree/master/src/com/lushprojects/circuitjs1/client # https://github.com/KenKundert/svg_schematic/blob/0abb5dc/svg_schematic.py diff --git a/test_data/test1.txt b/test_data/test1.txt index 8c9080e..71f203b 100644 --- a/test_data/test1.txt +++ b/test_data/test1.txt @@ -1,6 +1,10 @@ !padding=30! -----------L1------ +G3----------L1------G4 -------L2###########------- +G2------L2###########-------G1 L1:220u -L2:330u \ No newline at end of file +L2:330u +G1:earth +G2:chassis +G3:signal +G4:common From 3bfd9257a1bf76a3b149e837d6f453745d6ca803 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Wed, 24 May 2023 11:55:48 +0000 Subject: [PATCH 13/52] formatter --- .vscode/settings.json | 2 +- schemascii/__init__.py | 48 ++-- schemascii/__main__.py | 26 +- schemascii/components.py | 56 ++-- schemascii/components_render.py | 446 +++++++++++++++++--------------- schemascii/configs.py | 44 ++-- schemascii/edgemarks.py | 38 ++- schemascii/grid.py | 31 ++- schemascii/inline_config.py | 10 +- schemascii/metric.py | 29 ++- schemascii/utils.py | 182 ++++++------- schemascii/wires.py | 43 +-- 12 files changed, 521 insertions(+), 434 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e18146e..2157f82 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,6 +10,6 @@ "tspan" ], "python.linting.pylintEnabled": false, - "python.linting.flake8Enabled": true, + "python.linting.flake8Enabled": false, "python.linting.enabled": true } \ No newline at end of file diff --git a/schemascii/__init__.py b/schemascii/__init__.py index 24a839f..29b2001 100644 --- a/schemascii/__init__.py +++ b/schemascii/__init__.py @@ -19,36 +19,44 @@ def render(filename: str, text: str = None, **options) -> str: # get everything grid = Grid(filename, text) # Passed-in options override diagram inline options - options = apply_config_defaults(options - | get_inline_configs(grid) - | options.get("override_options", {})) + options = apply_config_defaults( + options | get_inline_configs(grid) | options.get("override_options", {}) + ) components, bom_data = find_all(grid) terminals = {c: find_edge_marks(grid, c) for c in components} - fixed_bom_data = {c: [b for b in bom_data if - b.id == c.id and b.type == c.type] - for c in components} + fixed_bom_data = { + c: [b for b in bom_data if b.id == c.id and b.type == c.type] + for c in components + } # get some options - padding = options['padding'] - scale = options['scale'] + padding = options["padding"] + scale = options["scale"] wires = get_wires(grid, **options) - components_strs = (render_component( - c, terminals[c], fixed_bom_data[c], **options) - for c in components) + components_strs = ( + render_component(c, terminals[c], fixed_bom_data[c], **options) + for c in components + ) return XML.svg( - wires, *components_strs, + wires, + *components_strs, width=grid.width * scale + padding * 2, height=grid.height * scale + padding * 2, - viewBox=f'{-padding} {-padding} ' - f'{grid.width * scale + padding * 2} ' - f'{grid.height * scale + padding * 2}', + viewBox=f"{-padding} {-padding} " + f"{grid.width * scale + padding * 2} " + f"{grid.height * scale + padding * 2}", xmlns="http://www.w3.org/2000/svg", class_="schemascii", ) -if __name__ == '__main__': - print(render( - "test_data/test_resistors.txt", - scale=20, padding=20, stroke_width=2, - stroke="black")) +if __name__ == "__main__": + print( + render( + "test_data/test_resistors.txt", + scale=20, + padding=20, + stroke_width=2, + stroke="black", + ) + ) diff --git a/schemascii/__main__.py b/schemascii/__main__.py index 823199f..b987580 100644 --- a/schemascii/__main__.py +++ b/schemascii/__main__.py @@ -8,17 +8,19 @@ def cli_main(): ap = argparse.ArgumentParser( - prog="schemascii", - description="Render ASCII-art schematics into SVG.") - ap.add_argument("-V", "--version", - action="version", - version="%(prog)s " + __version__) - ap.add_argument("in_file", - help="File to process.") - ap.add_argument("-o", "--out", - default=None, - dest="out_file", - help="Output SVG file. (default input file plus .svg)") + prog="schemascii", description="Render ASCII-art schematics into SVG." + ) + ap.add_argument( + "-V", "--version", action="version", version="%(prog)s " + __version__ + ) + ap.add_argument("in_file", help="File to process.") + ap.add_argument( + "-o", + "--out", + default=None, + dest="out_file", + help="Output SVG file. (default input file plus .svg)", + ) add_config_arguments(ap) args = ap.parse_args() if args.out_file is None: @@ -43,5 +45,5 @@ def cli_main(): out.write(result_svg) -if __name__ == '__main__': +if __name__ == "__main__": cli_main() diff --git a/schemascii/components.py b/schemascii/components.py index d7a1c37..3bbeaa0 100644 --- a/schemascii/components.py +++ b/schemascii/components.py @@ -4,7 +4,7 @@ from .errors import DiagramSyntaxError, BOMError -SMALL_COMPONENT_OR_BOM = re.compile(r'#*([A-Z]+)(\d*|\.\w+)(:[^\s]+)?#*') +SMALL_COMPONENT_OR_BOM = re.compile(r"#*([A-Z]+)(\d*|\.\w+)(:[^\s]+)?#*") def find_small(grid: Grid) -> tuple[list[Cbox], list[BOMData]]: @@ -14,20 +14,24 @@ def find_small(grid: Grid) -> tuple[list[Cbox], list[BOMData]]: boms: list[BOMData] = [] for i, line in enumerate(grid.lines): for m in SMALL_COMPONENT_OR_BOM.finditer(line): - ident = m.group(2) or '0' + ident = m.group(2) or "0" if m.group(3): - boms.append(BOMData(m.group(1), - ident, m.group(3)[1:])) + boms.append(BOMData(m.group(1), ident, m.group(3)[1:])) else: - components.append(Cbox(complex(m.start(), i), - complex(m.end() - 1, i), - m.group(1), ident)) + components.append( + Cbox( + complex(m.start(), i), + complex(m.end() - 1, i), + m.group(1), + ident, + ) + ) for z in range(*m.span(0)): grid.setmask(complex(z, i)) return components, boms -TOP_OF_BOX = re.compile(r'\.~+\.') +TOP_OF_BOX = re.compile(r"\.~+\.") def find_big(grid: Grid) -> tuple[list[Cbox], list[BOMData]]: @@ -49,35 +53,37 @@ def find_big(grid: Grid) -> tuple[list[Cbox], list[BOMData]]: if cs == tb: y2 = j break - if not cs[0] == cs[-1] == ':': + if not cs[0] == cs[-1] == ":": raise DiagramSyntaxError( - f'{grid.filename}: Fragmented box ' - f'starting at line {y1 + 1}, col {x1 + 1}') + f"{grid.filename}: Fragmented box " + f"starting at line {y1 + 1}, col {x1 + 1}" + ) else: raise DiagramSyntaxError( - f'{grid.filename}: Unfinished box ' - f'starting at line {y1 + 1}, col {x1 + 1}') + f"{grid.filename}: Unfinished box " + f"starting at line {y1 + 1}, col {x1 + 1}" + ) inside = grid.clip(complex(x1, y1), complex(x2, y2)) results, resb = find_small(inside) if len(results) == 0 and len(resb) == 0: raise BOMError( - f'{grid.filename}: Box starting at ' - f'line {y1 + 1}, col {x1 + 1} is ' - f'missing reference designator') + f"{grid.filename}: Box starting at " + f"line {y1 + 1}, col {x1 + 1} is " + f"missing reference designator" + ) if len(results) != 1 and len(resb) != 1: raise BOMError( - f'{grid.filename}: Box starting at ' - f'line {y1 + 1}, col {x1 + 1} has ' - f'multiple reference designators') + f"{grid.filename}: Box starting at " + f"line {y1 + 1}, col {x1 + 1} has " + f"multiple reference designators" + ) if not results: merd = resb[0] else: merd = results[0] boxes.append( - Cbox(complex(x1, y1), - complex(x2 - 1, y2), - merd.type, - merd.id)) + Cbox(complex(x1, y1), complex(x2 - 1, y2), merd.type, merd.id) + ) boms.extend(resb) # mark everything for i in range(x1, x2): @@ -94,10 +100,10 @@ def find_all(grid: Grid) -> tuple[list[Cbox], list[BOMData]]: and masks off all of them, leaving only wires and extraneous text.""" b1, l1 = find_big(grid) b2, l2 = find_small(grid) - return b1+b2, l1+l2 + return b1 + b2, l1 + l2 -if __name__ == '__main__': +if __name__ == "__main__": test_grid = Grid("test_data/test_resistors.txt") bbb, _ = find_all(test_grid) all_pts = [] diff --git a/schemascii/components_render.py b/schemascii/components_render.py index 2c88395..4ee60b1 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -2,11 +2,25 @@ from cmath import phase, rect from math import pi from warnings import warn -from .utils import (Cbox, Terminal, BOMData, XML, Side, arrow_points, - polylinegon, id_text, make_text_point, - bunch_o_lines, deep_transform, make_plus, make_variable, - sort_counterclockwise, light_arrows, sort_for_flags, - is_clockwise) +from .utils import ( + Cbox, + Terminal, + BOMData, + XML, + Side, + arrow_points, + polylinegon, + id_text, + make_text_point, + bunch_o_lines, + deep_transform, + make_plus, + make_variable, + sort_counterclockwise, + light_arrows, + sort_for_flags, + is_clockwise, +) from .errors import TerminalsError, BOMError, UnsupportedComponentError # pylint: disable=unbalanced-tuple-unpacking @@ -16,52 +30,50 @@ def component(*rd_s: list[str]) -> Callable: "Registers the component under a set of reference designators." + def rendec(func: Callable[[Cbox, list[Terminal], list[BOMData]], str]): for r_d in rd_s: rdu = r_d.upper() if rdu in RENDERERS: - raise RuntimeError( - f"{rdu} reference designator already taken") + raise RuntimeError(f"{rdu} reference designator already taken") RENDERERS[rdu] = func return func + return rendec def n_terminal(n_terminals: int) -> Callable: "Ensures the component has N terminals." + def n_inner(func: Callable) -> Callable: def n_check( - box: Cbox, - terminals: list[Terminal], - bom_data: list[BOMData], - **options): + box: Cbox, terminals: list[Terminal], bom_data: list[BOMData], **options + ): if len(terminals) != n_terminals: raise TerminalsError( f"{box.type}{box.id} component can only " - f"have {n_terminals} terminals") + f"have {n_terminals} terminals" + ) return func(box, terminals, bom_data, **options) + n_check.__doc__ = func.__doc__ return n_check + return n_inner def no_ambiguous(func: Callable) -> Callable: "Ensures the component has exactly one BOM data marker, and unwraps it." + def de_ambiguous( - box: Cbox, - terminals: list[Terminal], - bom_data: list[BOMData], - **options): + box: Cbox, terminals: list[Terminal], bom_data: list[BOMData], **options + ): if len(bom_data) > 1: - raise BOMError( - f"Ambiguous BOM data for {box.type}{box.id}: {bom_data!r}") + raise BOMError(f"Ambiguous BOM data for {box.type}{box.id}: {bom_data!r}") if not bom_data: bom_data = [BOMData(box.type, box.id, "")] - return func( - box, - terminals, - bom_data[0], - **options) + return func(box, terminals, bom_data[0], **options) + de_ambiguous.__doc__ = func.__doc__ return de_ambiguous @@ -69,22 +81,18 @@ def de_ambiguous( def polarized(func: Callable) -> Callable: """Ensures the component has 2 terminals, and then sorts them so the + terminal is first.""" + def sort_terminals( - box: Cbox, - terminals: list[Terminal], - bom_data: list[BOMData], - **options): + box: Cbox, terminals: list[Terminal], bom_data: list[BOMData], **options + ): if len(terminals) != 2: raise TerminalsError( - f"{box.type}{box.id} component can only " - f"have 2 terminals") - if terminals[1].flag == '+': + f"{box.type}{box.id} component can only " f"have 2 terminals" + ) + if terminals[1].flag == "+": terminals[0], terminals[1] = terminals[1], terminals[0] - return func( - box, - terminals, - bom_data, - **options) + return func(box, terminals, bom_data, **options) + sort_terminals.__doc__ = func.__doc__ return sort_terminals @@ -92,11 +100,7 @@ def sort_terminals( @component("R", "RV", "VR") @n_terminal(2) @no_ambiguous -def resistor( - box: Cbox, - terminals: list[Terminal], - bom_data: BOMData, - **options): +def resistor(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): """Resistor, Variable resistor, etc. bom:ohms[,watts]""" t1, t2 = terminals[0].pt, terminals[1].pt @@ -107,24 +111,26 @@ def resistor( quad_angle = angle + pi / 2 points = [t1] for i in range(1, 4 * int(length)): - points.append(t1 - rect(i / 4, angle) + - pow(-1, i) * rect(1, quad_angle) / 4) + points.append(t1 - rect(i / 4, angle) + pow(-1, i) * rect(1, quad_angle) / 4) points.append(t2) - return (polylinegon(points, **options) - + make_variable(mid, angle, "V" in box.type, **options) - + id_text( - box, bom_data, terminals, (("Ω", False), ("W", False)), - make_text_point(t1, t2, **options), **options)) + return ( + polylinegon(points, **options) + + make_variable(mid, angle, "V" in box.type, **options) + + id_text( + box, + bom_data, + terminals, + (("Ω", False), ("W", False)), + make_text_point(t1, t2, **options), + **options, + ) + ) @component("C", "CV", "VC") @n_terminal(2) @no_ambiguous -def capacitor( - box: Cbox, - terminals: list[Terminal], - bom_data: BOMData, - **options): +def capacitor(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): """Draw a capacitor, variable capacitor, etc. bom:farads[,volts] flags:+=positive""" @@ -132,26 +138,34 @@ def capacitor( mid = (t1 + t2) / 2 angle = phase(t1 - t2) lines = [ - (t1, mid + rect(.25, angle)), - (t2, mid + rect(-.25, angle))] + deep_transform([ - (complex(.4, .25), complex(-.4, .25)), - (complex(.4, -.25), complex(-.4, -.25)), - ], mid, angle) - return (bunch_o_lines(lines, **options) - + make_plus(terminals, mid, angle, **options) - + make_variable(mid, angle, "V" in box.type, **options) - + id_text( - box, bom_data, terminals, (("F", True), ("V", False)), - make_text_point(t1, t2, **options), **options)) + (t1, mid + rect(0.25, angle)), + (t2, mid + rect(-0.25, angle)), + ] + deep_transform( + [ + (complex(0.4, 0.25), complex(-0.4, 0.25)), + (complex(0.4, -0.25), complex(-0.4, -0.25)), + ], + mid, + angle, + ) + return ( + bunch_o_lines(lines, **options) + + make_plus(terminals, mid, angle, **options) + + make_variable(mid, angle, "V" in box.type, **options) + + id_text( + box, + bom_data, + terminals, + (("F", True), ("V", False)), + make_text_point(t1, t2, **options), + **options, + ) + ) @component("L", "VL", "LV") @no_ambiguous -def inductor( - box: Cbox, - terminals: list[Terminal], - bom_data: BOMData, - **options): +def inductor(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): """Draw an inductor (coil, choke, etc) bom:henries""" t1, t2 = terminals[0].pt, terminals[1].pt @@ -164,25 +178,29 @@ def inductor( dxdy = rect(scale, angle) for _ in range(int(length)): data += f"a1 1 0 01 {-dxdy.real} {dxdy.imag}" - return (XML.path( - d=data, - stroke=options["stroke"], - fill="transparent", - stroke__width=options["stroke_width"]) + return ( + XML.path( + d=data, + stroke=options["stroke"], + fill="transparent", + stroke__width=options["stroke_width"], + ) + make_variable(mid, angle, "V" in box.type, **options) + id_text( - box, bom_data, terminals, (("H", False),), - make_text_point(t1, t2, **options), **options)) + box, + bom_data, + terminals, + (("H", False),), + make_text_point(t1, t2, **options), + **options, + ) + ) @component("B", "BT", "BAT") @polarized @no_ambiguous -def battery( - box: Cbox, - terminals: list[Terminal], - bom_data: BOMData, - **options): +def battery(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): """Draw a battery cell. bom:volts[,amp-hours] flags:+=positive""" @@ -190,27 +208,32 @@ def battery( mid = (t1 + t2) / 2 angle = phase(t1 - t2) lines = [ - (t1, mid + rect(.5, angle)), - (t2, mid + rect(-.5, angle))] + deep_transform([ - (complex(.5, .5), complex(-.5, .5)), - (complex(.25, .16), complex(-.25, .16)), - (complex(.5, -.16), complex(-.5, -.16)), - (complex(.25, -.5), complex(-.25, -.5)), - ], mid, angle) - return (id_text( - box, bom_data, terminals, (("V", False), ("Ah", False)), - make_text_point(t1, t2, **options), **options) - + bunch_o_lines(lines, **options)) + (t1, mid + rect(0.5, angle)), + (t2, mid + rect(-0.5, angle)), + ] + deep_transform( + [ + (complex(0.5, 0.5), complex(-0.5, 0.5)), + (complex(0.25, 0.16), complex(-0.25, 0.16)), + (complex(0.5, -0.16), complex(-0.5, -0.16)), + (complex(0.25, -0.5), complex(-0.25, -0.5)), + ], + mid, + angle, + ) + return id_text( + box, + bom_data, + terminals, + (("V", False), ("Ah", False)), + make_text_point(t1, t2, **options), + **options, + ) + bunch_o_lines(lines, **options) @component("D", "LED", "CR", "IR") @polarized @no_ambiguous -def diode( - box: Cbox, - terminals: list[Terminal], - bom_data: BOMData, - **options): +def diode(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): """Draw a diode or LED. bom:part-number flags:+=positive""" @@ -218,23 +241,31 @@ def diode( mid = (t1 + t2) / 2 angle = phase(t1 - t2) lines = [ - (t2, mid + rect(.3, angle)), - (t1, mid + rect(-.3, angle)), - deep_transform((-.3-.3j, .3-.3j), mid, angle)] - triangle = deep_transform((-.3j, .3+.3j, -.3+.3j), mid, angle) + (t2, mid + rect(0.3, angle)), + (t1, mid + rect(-0.3, angle)), + deep_transform((-0.3 - 0.3j, 0.3 - 0.3j), mid, angle), + ] + triangle = deep_transform((-0.3j, 0.3 + 0.3j, -0.3 + 0.3j), mid, angle) light_emitting = box.type in ("LED", "IR") fill_override = {"stroke": bom_data.data} if box.type == "LED" else {} - return ((light_arrows(mid, angle, True, **options) - if light_emitting else "") - + id_text(box, bom_data, terminals, None, - make_text_point(t1, t2, **options), **options) - + bunch_o_lines(lines, **(options | fill_override)) - + polylinegon(triangle, True, **options)) + return ( + (light_arrows(mid, angle, True, **options) if light_emitting else "") + + id_text( + box, + bom_data, + terminals, + None, + make_text_point(t1, t2, **options), + **options, + ) + + bunch_o_lines(lines, **(options | fill_override)) + + polylinegon(triangle, True, **options) + ) SIDE_TO_ANGLE_MAP = { Side.RIGHT: pi, - Side.TOP: pi / 2, + Side.TOP: pi / 2, Side.LEFT: 0, Side.BOTTOM: 3 * pi / 2, } @@ -243,10 +274,8 @@ def diode( @component("U", "IC") @no_ambiguous def integrated_circuit( - box: Cbox, - terminals: list[Terminal], - bom_data: BOMData, - **options): + box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options +): """Draw an IC. bom:part-number[,pin1-label[,pin2-label[,...]]]""" label_style = options["label"] @@ -261,12 +290,12 @@ def integrated_circuit( height=sz.imag, stroke__width=options["stroke_width"], stroke=options["stroke"], - fill="transparent") + fill="transparent", + ) for term in terminals: - out += bunch_o_lines([( - term.pt, - term.pt + rect(1, SIDE_TO_ANGLE_MAP[term.side]) - )], **options) + out += bunch_o_lines( + [(term.pt, term.pt + rect(1, SIDE_TO_ANGLE_MAP[term.side]))], **options + ) if "V" in label_style and part_num: out += XML.text( XML.tspan(part_num, class_="part-num"), @@ -274,7 +303,8 @@ def integrated_circuit( y=mid.imag, text__anchor="middle", font__size=options["scale"], - fill=options["stroke"]) + fill=options["stroke"], + ) mid -= 1j * scale if "L" in label_style and not options["nolabels"]: out += XML.text( @@ -283,7 +313,8 @@ def integrated_circuit( y=mid.imag, text__anchor="middle", font__size=options["scale"], - fill=options["stroke"]) + fill=options["stroke"], + ) s_terminals = sort_counterclockwise(terminals) for terminal, label in zip(s_terminals, pin_labels): sc_text_pt = terminal.pt * scale @@ -291,24 +322,24 @@ def integrated_circuit( label, x=sc_text_pt.real, y=sc_text_pt.imag, - text__anchor=("start" if (terminal.side in (Side.TOP, Side.BOTTOM)) - else "middle"), + text__anchor=( + "start" if (terminal.side in (Side.TOP, Side.BOTTOM)) else "middle" + ), font__size=options["scale"], fill=options["stroke"], - class_="pin-label") - warn("ICs are not fully implemented yet. " - "Pin labels may have not been rendered correctly.") + class_="pin-label", + ) + warn( + "ICs are not fully implemented yet. " + "Pin labels may have not been rendered correctly." + ) return out @component("J", "P") @n_terminal(1) @no_ambiguous -def jack( - box: Cbox, - terminals: list[Terminal], - bom_data: BOMData, - **options): +def jack(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): """Draw a jack connector or plug. bom:label[,{circle/input/output}]""" scale = options["scale"] @@ -316,14 +347,14 @@ def jack( t2 = t1 + rect(1, SIDE_TO_ANGLE_MAP[terminals[0].side]) sc_t2 = t2 * scale sc_text_pt = sc_t2 + rect(scale / 2, SIDE_TO_ANGLE_MAP[terminals[0].side]) - style = "input" if terminals[0].side in ( - Side.LEFT, Side.TOP) else "output" - if any(bom_data.data.endswith(x) - for x in (",circle", ",input", ",output")): + style = "input" if terminals[0].side in (Side.LEFT, Side.TOP) else "output" + if any(bom_data.data.endswith(x) for x in (",circle", ",input", ",output")): style = bom_data.data.split(",")[-1] - bom_data = BOMData(bom_data.type, bom_data.id, - bom_data.data.rstrip("cirlenputo") - .removesuffix(",")) + bom_data = BOMData( + bom_data.type, + bom_data.id, + bom_data.data.rstrip("cirlenputo").removesuffix(","), + ) if style == "circle": return ( bunch_o_lines([(t1, t2)], **options) @@ -333,34 +364,32 @@ def jack( r=scale / 4, stroke__width=options["stroke_width"], stroke=options["stroke"], - fill="transparent") - + id_text(box, bom_data, terminals, None, sc_text_pt, **options)) + fill="transparent", + ) + + id_text(box, bom_data, terminals, None, sc_text_pt, **options) + ) if style == "output": t1, t2 = t2, t1 - return ( - bunch_o_lines(arrow_points(t1, t2), **options) - + id_text(box, bom_data, terminals, None, sc_text_pt, **options)) + return bunch_o_lines(arrow_points(t1, t2), **options) + id_text( + box, bom_data, terminals, None, sc_text_pt, **options + ) @component("Q", "MOSFET", "MOS", "FET") @n_terminal(3) @no_ambiguous -def transistor( - box: Cbox, - terminals: list[Terminal], - bom_data: BOMData, - **options): +def transistor(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): """Draw a bipolar transistor (PNP/NPN) or FET (NFET/PFET). bom:{npn/pnp/nfet/pfet}:part-number flags:s=source,d=drain,g=gate,e=emitter,c=collector,b=base""" - if not any(bom_data.data.lower().startswith(x) for x in ( - "pnp:", "npn:", "nfet:", "pfet:")): - raise BOMError( - f"Need type of transistor for {box.type}{box.id}") + if not any( + bom_data.data.lower().startswith(x) for x in ("pnp:", "npn:", "nfet:", "pfet:") + ): + raise BOMError(f"Need type of transistor for {box.type}{box.id}") silicon_type, part_num = bom_data.data.split(":") silicon_type = silicon_type.lower() bom_data = BOMData(bom_data.type, bom_data.id, part_num) - if 'fet' in silicon_type: + if "fet" in silicon_type: ae, se, ctl = sort_for_flags(terminals, box, "s", "d", "g") else: ae, se, ctl = sort_for_flags(terminals, box, "e", "c", "b") @@ -374,79 +403,84 @@ def transistor( # From wolfram alpha "solve m*(x-x1)+y1=(-1/m)*(x-x2)+y2 for x" # x = (m^2 x1 - m y1 + m y2 + x2)/(m^2 + 1) slope = diff.imag / diff.real - mid_x = (slope ** 2 * ap.real - slope * ap.imag + slope * - ctl.pt.imag + ctl.pt.real) / (slope ** 2 + 1) + mid_x = ( + slope**2 * ap.real - slope * ap.imag + slope * ctl.pt.imag + ctl.pt.real + ) / (slope**2 + 1) mid = complex(mid_x, slope * (mid_x - ap.real) + ap.imag) theta = phase(ap - sp) backwards = 1 if is_clockwise([ae, se, ctl]) else -1 thetaquarter = theta + (backwards * pi / 2) out_lines = [ - (ap, mid + rect(.8, theta)), # Lead in - (sp, mid - rect(.8, theta)), # Lead out + (ap, mid + rect(0.8, theta)), # Lead in + (sp, mid - rect(0.8, theta)), # Lead out ] - if 'fet' in silicon_type: - arr = mid + rect(.8, theta), mid + rect(.8, theta) + \ - rect(.7, thetaquarter) - if 'nfet' == silicon_type: + if "fet" in silicon_type: + arr = mid + rect(0.8, theta), mid + rect(0.8, theta) + rect(0.7, thetaquarter) + if "nfet" == silicon_type: arr = arr[1], arr[0] - out_lines.extend([ - *arrow_points(*arr), - (mid - rect(.8, theta), mid - rect(.8, theta) - + rect(.7, thetaquarter)), - (mid + rect(1, theta) + rect(.7, thetaquarter), - mid - rect(1, theta) + rect(.7, thetaquarter)), - (mid + rect(.5, theta) + rect(1, thetaquarter), - mid - rect(.5, theta) + rect(1, thetaquarter)), - ]) + out_lines.extend( + [ + *arrow_points(*arr), + ( + mid - rect(0.8, theta), + mid - rect(0.8, theta) + rect(0.7, thetaquarter), + ), + ( + mid + rect(1, theta) + rect(0.7, thetaquarter), + mid - rect(1, theta) + rect(0.7, thetaquarter), + ), + ( + mid + rect(0.5, theta) + rect(1, thetaquarter), + mid - rect(0.5, theta) + rect(1, thetaquarter), + ), + ] + ) else: - arr = mid + rect(.8, theta), mid + rect(.4, theta) + \ - rect(1, thetaquarter) - if 'npn' == silicon_type: + arr = mid + rect(0.8, theta), mid + rect(0.4, theta) + rect(1, thetaquarter) + if "npn" == silicon_type: arr = arr[1], arr[0] - out_lines.extend([ - *arrow_points(*arr), - (mid - rect(.8, theta), mid - rect(.4, theta) - + rect(1, thetaquarter)), - (mid + rect(1, theta) + rect(1, thetaquarter), - mid - rect(1, theta) + rect(1, thetaquarter)), - ]) + out_lines.extend( + [ + *arrow_points(*arr), + ( + mid - rect(0.8, theta), + mid - rect(0.4, theta) + rect(1, thetaquarter), + ), + ( + mid + rect(1, theta) + rect(1, thetaquarter), + mid - rect(1, theta) + rect(1, thetaquarter), + ), + ] + ) out_lines.append((mid + rect(1, thetaquarter), ctl.pt)) - return (id_text(box, bom_data, [ae, se], None, - make_text_point(ap, sp, **options), **options) - + bunch_o_lines(out_lines, **options)) + return id_text( + box, bom_data, [ae, se], None, make_text_point(ap, sp, **options), **options + ) + bunch_o_lines(out_lines, **options) @component("G", "GND") @n_terminal(1) @no_ambiguous -def ground( - box: Cbox, - terminals: list[Terminal], - bom_data: BOMData, - **options): +def ground(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): """Draw a ground symbol. bom:[{earth/chassis/signal/common}]""" icon_type = bom_data.data or "earth" - points = [(0, 1j), (-.5+1j, .5+1j)] + points = [(0, 1j), (-0.5 + 1j, 0.5 + 1j)] match icon_type: case "earth": - points += [ - (-.33+1.25j, .33+1.25j), - (-.16+1.5j, .16+1.5j)] + points += [(-0.33 + 1.25j, 0.33 + 1.25j), (-0.16 + 1.5j, 0.16 + 1.5j)] case "chassis": points += [ - (-.5+1j, -.25+1.5j), - (1j, .25+1.5j), - (.5+1j, .75+1.5j)] + (-0.5 + 1j, -0.25 + 1.5j), + (1j, 0.25 + 1.5j), + (0.5 + 1j, 0.75 + 1.5j), + ] case "signal": - points += [ - (-.5+1j, 1.5j), - (.5+1j, 1.5j)] + points += [(-0.5 + 1j, 1.5j), (0.5 + 1j, 1.5j)] case "common": pass case _: - raise BOMError( - f"Unknown ground symbol type: {icon_type}") + raise BOMError(f"Unknown ground symbol type: {icon_type}") points = deep_transform(points, terminals[0].pt, pi / 2) return bunch_o_lines(points, **options) @@ -463,28 +497,26 @@ def ground( # if they aren't the path will be transformed { # fuse - 'F': 'M0-.9A.1.1 0 000-1.1.1.1 0 000-.9ZM0-1Q.5-.5 0 0T0 1Q-.5.5 0 0T0-1ZM0 1.1A.1.1 0 000 .9.1.1 0 000 1.1Z', + "F": "M0-.9A.1.1 0 000-1.1.1.1 0 000-.9ZM0-1Q.5-.5 0 0T0 1Q-.5.5 0 0T0-1ZM0 1.1A.1.1 0 000 .9.1.1 0 000 1.1Z", # jumper pads - 'JP': 'M0-1Q-1-1-1-.25H1Q1-1 0-1ZM0 1Q-1 1-1 .25H1Q1 1 0 1', + "JP": "M0-1Q-1-1-1-.25H1Q1-1 0-1ZM0 1Q-1 1-1 .25H1Q1 1 0 1", # loudspeaker - 'LS': 'M0-1V-.5H-.25V.5H.25V-.5H0M0 1V.5ZM1-1 .25-.5V.5L1 1Z', + "LS": "M0-1V-.5H-.25V.5H.25V-.5H0M0 1V.5ZM1-1 .25-.5V.5L1 1Z", # electret mic - 'MIC': 'M1 0A1 1 0 00-1 0 1 1 0 001 0V-1 1Z', + "MIC": "M1 0A1 1 0 00-1 0 1 1 0 001 0V-1 1Z", } def render_component( - box: Cbox, - terminals: list[Terminal], - bom_data: list[BOMData], - **options): + box: Cbox, terminals: list[Terminal], bom_data: list[BOMData], **options +): "Render the component into an SVG string." if box.type not in RENDERERS: raise UnsupportedComponentError(box.type) return XML.g( RENDERERS[box.type](box, terminals, bom_data, **options), - class_=f"component {box.type}" + class_=f"component {box.type}", ) -__all__ = ['render_component'] +__all__ = ["render_component"] diff --git a/schemascii/configs.py b/schemascii/configs.py index 97a400c..d2376d7 100644 --- a/schemascii/configs.py +++ b/schemascii/configs.py @@ -12,16 +12,24 @@ class ConfigConfig: OPTIONS = [ - ConfigConfig("padding", float, 10, - "Amount of padding to add on the edges."), - ConfigConfig("scale", float, 15, - "Scale at which to enlarge the entire diagram by."), + ConfigConfig("padding", float, 10, "Amount of padding to add on the edges."), + ConfigConfig( + "scale", float, 15, "Scale at which to enlarge the entire diagram by." + ), ConfigConfig("stroke_width", float, 2, "Width of the lines"), ConfigConfig("stroke", str, "black", "Color of the lines."), - ConfigConfig("label", ["L", "V", "VL"], "VL", - "Component label style (L=include label, V=include value, VL=both)"), - ConfigConfig("nolabels", bool, False, - "Turns off labels on all components, except for part numbers on ICs."), + ConfigConfig( + "label", + ["L", "V", "VL"], + "VL", + "Component label style (L=include label, V=include value, VL=both)", + ), + ConfigConfig( + "nolabels", + bool, + False, + "Turns off labels on all components, except for part numbers on ICs.", + ), ] @@ -33,18 +41,21 @@ def add_config_arguments(a: argparse.ArgumentParser): "--" + opt.name, help=opt.description, choices=opt.clazz, - default=opt.default) + default=opt.default, + ) elif opt.clazz is bool: a.add_argument( "--" + opt.name, help=opt.description, - action="store_false" if opt.default else "store_true") + action="store_false" if opt.default else "store_true", + ) else: a.add_argument( "--" + opt.name, help=opt.description, type=opt.clazz, - default=opt.default) + default=opt.default, + ) def apply_config_defaults(options: dict) -> dict: @@ -58,12 +69,15 @@ def apply_config_defaults(options: dict) -> dict: raise ArgumentError( f"config option {opt.name}: " f"invalid choice: {options[opt.name]} " - f"(valid options are {', '.join(map(repr, opt.clazz))})") + f"(valid options are {', '.join(map(repr, opt.clazz))})" + ) continue try: options[opt.name] = opt.clazz(options[opt.name]) except ValueError as err: - raise ArgumentError(f"config option {opt.name}: " - f"invalid {opt.clazz.__name__} value: " - f"{options[opt.name]}") from err + raise ArgumentError( + f"config option {opt.name}: " + f"invalid {opt.clazz.__name__} value: " + f"{options[opt.name]}" + ) from err return options diff --git a/schemascii/edgemarks.py b/schemascii/edgemarks.py index 3bdbf4f..d9bd19c 100644 --- a/schemascii/edgemarks.py +++ b/schemascii/edgemarks.py @@ -6,39 +6,51 @@ def over_edges(box: Cbox) -> list: "Decorator - Runs around the edges of the box on the grid." + def inner_over_edges(func: FunctionType): out = [] for p, s in chain( # Top side - ((complex(xx, int(box.p1.imag) - 1), Side.TOP) - for xx in range(int(box.p1.real), int(box.p2.real) + 1)), + ( + (complex(xx, int(box.p1.imag) - 1), Side.TOP) + for xx in range(int(box.p1.real), int(box.p2.real) + 1) + ), # Right side - ((complex(int(box.p2.real) + 1, yy), Side.RIGHT) - for yy in range(int(box.p1.imag), int(box.p2.imag) + 1)), + ( + (complex(int(box.p2.real) + 1, yy), Side.RIGHT) + for yy in range(int(box.p1.imag), int(box.p2.imag) + 1) + ), # Bottom side - ((complex(xx, int(box.p2.imag) + 1), Side.BOTTOM) - for xx in range(int(box.p1.real), int(box.p2.real) + 1)), + ( + (complex(xx, int(box.p2.imag) + 1), Side.BOTTOM) + for xx in range(int(box.p1.real), int(box.p2.real) + 1) + ), # Left side - ((complex(int(box.p1.real) - 1, yy), Side.LEFT) - for yy in range(int(box.p1.imag), int(box.p2.imag) + 1)), + ( + (complex(int(box.p1.real) - 1, yy), Side.LEFT) + for yy in range(int(box.p1.imag), int(box.p2.imag) + 1) + ), ): result = func(p, s) if result is not None: out.append(result) return out + return inner_over_edges def take_flags(grid: Grid, box: Cbox) -> list[Flag]: """Runs around the edges of the component box, collects the flags, and masks them off to wires.""" + @over_edges(box) def flags(p: complex, s: Side) -> Flag | None: c = grid.get(p) - if c in ' -|()*': + if c in " -|()*": return None - grid.setmask(p, '*') + grid.setmask(p, "*") return Flag(p, c, s) + return flags @@ -49,11 +61,13 @@ def find_edge_marks(grid: Grid, box: Cbox) -> list[Terminal]: @over_edges(box) def terminals(p: complex, s: Side) -> Terminal | None: c = grid.get(p) - if ((c in "*|()" and s in (Side.TOP, Side.BOTTOM)) - or (c in "*-" and s in (Side.LEFT, Side.RIGHT))): + if (c in "*|()" and s in (Side.TOP, Side.BOTTOM)) or ( + c in "*-" and s in (Side.LEFT, Side.RIGHT) + ): maybe_flag = [f for f in flags if f.pt == p] if maybe_flag: return Terminal(p, maybe_flag[0].char, s) return Terminal(p, None, s) return None + return terminals diff --git a/schemascii/grid.py b/schemascii/grid.py index 9463ac8..85e39d4 100644 --- a/schemascii/grid.py +++ b/schemascii/grid.py @@ -8,12 +8,12 @@ def __init__(self, filename: str, data: str = None): data = f.read() self.filename: str = filename self.raw: str = data - lines: list[str] = data.split('\n') + lines: list[str] = data.split("\n") maxlen: int = max(len(line) for line in lines) - self.data: list[list[str]] = [ - list(line.ljust(maxlen, ' ')) for line in lines] + self.data: list[list[str]] = [list(line.ljust(maxlen, " ")) for line in lines] self.masks: list[list[bool | str]] = [ - [False for x in range(maxlen)] for y in range(len(lines))] + [False for x in range(maxlen)] for y in range(len(lines)) + ] self.width = maxlen self.height = len(self.data) @@ -27,14 +27,16 @@ def get(self, p: complex) -> str: the mask character if it was set, otherwise the original character.""" if not self.validbounds(p): - return ' ' + return " " return self.getmask(p) or self.data[int(p.imag)][int(p.real)] @property def lines(self): "The current contents, with masks applied." - return [''.join(self.get(complex(x, y)) for x in range(self.width)) - for y in range(self.height)] + return [ + "".join(self.get(complex(x, y)) for x in range(self.width)) + for y in range(self.height) + ] def getmask(self, p: complex) -> str | bool: """Sees the mask applied to the specified point; @@ -43,7 +45,7 @@ def getmask(self, p: complex) -> str | bool: return False return self.masks[int(p.imag)][int(p.real)] - def setmask(self, p: complex, mask: str | bool = ' '): + def setmask(self, p: complex, mask: str | bool = " "): "Sets or clears the mask at the point." if not self.validbounds(p): return @@ -55,19 +57,19 @@ def clrmask(self, p: complex): def clrall(self): "Clears all the masks at once." - self.masks = [[False for x in range(self.width)] - for y in range(self.height)] + self.masks = [[False for x in range(self.width)] for y in range(self.height)] def clip(self, p1: complex, p2: complex): """Returns a sub-grid with the contents bounded by the p1 and p2 box. Masks are not copied.""" ls = slice(int(p1.real), int(p2.real)) cs = slice(int(p1.imag), int(p2.imag) + 1) - d = '\n'.join(''.join(ln[ls]) for ln in self.data[cs]) + d = "\n".join("".join(ln[ls]) for ln in self.data[cs]) return Grid(self.filename, d) def __repr__(self): return f"Grid({self.filename!r}, '''\n{chr(10).join(self.lines)}''')" + __str__ = __repr__ def spark(self, *points): @@ -82,6 +84,7 @@ def spark(self, *points): print(char, end="") print() -if __name__ == '__main__': - x = Grid('', ' \n \n ') - x.spark(0, 1, 2, 1j, 2j, 1+2j, 2+2j, 2+1j) + +if __name__ == "__main__": + x = Grid("", " \n \n ") + x.spark(0, 1, 2, 1j, 2j, 1 + 2j, 2 + 2j, 2 + 1j) diff --git a/schemascii/inline_config.py b/schemascii/inline_config.py index f72acbe..a37d629 100644 --- a/schemascii/inline_config.py +++ b/schemascii/inline_config.py @@ -22,12 +22,14 @@ def get_inline_configs(grid: Grid) -> dict: return out -if __name__ == '__main__': - g = Grid("null", - """ +if __name__ == "__main__": + g = Grid( + "null", + """ foobar -------C1------- !padding=30!!label=! !foobar=bar! -""") +""", + ) print(get_inline_configs(g)) print(g) diff --git a/schemascii/metric.py b/schemascii/metric.py index ef8182f..031b86c 100644 --- a/schemascii/metric.py +++ b/schemascii/metric.py @@ -23,17 +23,17 @@ def prefix_to_exponent(prefix: int) -> str: E.g. "k" --> 3 (kilo) E.g. " " --> 0 (no prefix) E.g. "u" --> -6 (micro)""" - if prefix in (' ', ''): + if prefix in (" ", ""): return 0 if prefix == "µ": - prefix = "u" # allow unicode - if prefix == 'K': + prefix = "u" # allow unicode + if prefix == "K": prefix = prefix.lower() # special case (preferred is lowercase) i = "pnum kMG".index(prefix) return (i - 4) * 3 -def format_metric_unit(num: str, unit: str = '', six: bool = False) -> str: +def format_metric_unit(num: str, unit: str = "", six: bool = False) -> str: "Normalizes the Metric unit on the number." num = num.strip() match = METRIC_NUMBER.match(num) @@ -41,30 +41,31 @@ def format_metric_unit(num: str, unit: str = '', six: bool = False) -> str: return num digits_str, prefix = match.group(1), match.group(2) digits_decimal = Decimal(digits_str) - digits_decimal *= Decimal('10') ** Decimal(prefix_to_exponent(prefix)) + digits_decimal *= Decimal("10") ** Decimal(prefix_to_exponent(prefix)) res = ENG_NUMBER.match(digits_decimal.to_eng_string()) if not res: raise RuntimeError - digits, exp = Decimal(res.group(1)), int(res.group(2) or '0') - assert exp % 3 == 0, 'failed to make engineering notation' + digits, exp = Decimal(res.group(1)), int(res.group(2) or "0") + assert exp % 3 == 0, "failed to make engineering notation" possibilities = [] for d_e in range(-6, 9, 3): if (exp + d_e) % 6 == 0 or not six: new_exp = exp - d_e - new_digits = str(digits * (Decimal('10') ** Decimal(d_e))) - if 'e' in new_digits.lower(): + new_digits = str(digits * (Decimal("10") ** Decimal(d_e))) + if "e" in new_digits.lower(): continue - if '.' in new_digits: - new_digits = new_digits.rstrip('0').removesuffix('.') + if "." in new_digits: + new_digits = new_digits.rstrip("0").removesuffix(".") possibilities.append((new_exp, new_digits)) # heuristic: shorter is better, prefer no decimal point - exp, digits = sorted(possibilities, key=lambda x: len( - x[1]) + (0.5 * ('.' in x[1])))[0] + exp, digits = sorted( + possibilities, key=lambda x: len(x[1]) + (0.5 * ("." in x[1])) + )[0] out = digits + " " + exponent_to_prefix(exp) + unit return out.replace(" u", " µ") -if __name__ == '__main__': +if __name__ == "__main__": print(">>", format_metric_unit("2.5", "V")) print(">>", format_metric_unit("50n", "F", True)) print(">>", format_metric_unit("1234", "Ω")) diff --git a/schemascii/utils.py b/schemascii/utils.py index c96b486..39e7f7a 100644 --- a/schemascii/utils.py +++ b/schemascii/utils.py @@ -8,10 +8,10 @@ from .metric import format_metric_unit from .errors import TerminalsError -Cbox = namedtuple('Cbox', 'p1 p2 type id') -BOMData = namedtuple('BOMData', 'type id data') -Flag = namedtuple('Flag', 'pt char side') -Terminal = namedtuple('Terminal', 'pt flag side') +Cbox = namedtuple("Cbox", "p1 p2 type id") +BOMData = namedtuple("BOMData", "type id data") +Flag = namedtuple("Flag", "pt char side") +Terminal = namedtuple("Terminal", "pt flag side") class Side(IntEnum): @@ -24,7 +24,7 @@ class Side(IntEnum): def colinear(points: list[complex]) -> bool: "Returns true if all the points are in the same line." - return len(set(phase(p-points[0]) for p in points[1:])) == 1 + return len(set(phase(p - points[0]) for p in points[1:])) == 1 def sharpness_score(points: list[complex]) -> float: @@ -50,7 +50,9 @@ def intersecting(a, b, p, q): # UNUSED as of yet -def merge_colinear(points: list[tuple[complex, complex]]) -> list[tuple[complex, complex]]: +def merge_colinear( + points: list[tuple[complex, complex]] +) -> list[tuple[complex, complex]]: "Merges line segments that are colinear." points = list(set(points)) out = [] @@ -70,7 +72,7 @@ def merge_colinear(points: list[tuple[complex, complex]]) -> list[tuple[complex, return out -def iterate_line(p1: complex, p2: complex, step: float = 1.): +def iterate_line(p1: complex, p2: complex, step: float = 1.0): "Yields complex points along a line." vec = p2 - p1 point = p1 @@ -87,14 +89,11 @@ def deep_transform(data, origin: complex, theta: float): if isinstance(data, list | tuple): return [deep_transform(d, origin, theta) for d in data] if isinstance(data, complex): - return (origin - + rect(data.real, theta + pi / 2) - + rect(data.imag, theta)) + return origin + rect(data.real, theta + pi / 2) + rect(data.imag, theta) try: return deep_transform(complex(data), origin, theta) except TypeError as err: - raise TypeError( - "bad type to deep_transform(): " + type(data).__name__) from err + raise TypeError("bad type to deep_transform(): " + type(data).__name__) from err def fix_number(n: float) -> str: @@ -107,19 +106,19 @@ def fix_number(n: float) -> str: class XMLClass: def __getattr__(self, tag) -> Callable: - def mk_tag(*contents, **attrs) -> str: - out = f'<{tag} ' + def mk_tag(*contents: str, **attrs: str) -> str: + out = f"<{tag} " for k, v in attrs.items(): if v is False: continue if isinstance(v, float): v = fix_number(v) elif isinstance(v, str): - v = re.sub(r"\d+(\.\d+)", - lambda m: fix_number(float(m.group())), v) + v = re.sub(r"\d+(\.\d+)", lambda m: fix_number(float(m.group())), v) out += f'{k.removesuffix("_").replace("__", "-")}="{v}" ' - out = out.rstrip() + '>' + ''.join(contents) - return out + f'' + out = out.rstrip() + ">" + "".join(contents) + return out + f"" + return mk_tag @@ -132,13 +131,10 @@ def polylinegon(points: list[complex], is_polygon: bool = False, **options): scale = options["scale"] w = options["stroke_width"] c = options["stroke"] - pts = ' '.join( - f'{x.real * scale},{x.imag * scale}' - for x in points) + pts = " ".join(f"{x.real * scale},{x.imag * scale}" for x in points) if is_polygon: return XML.polygon(points=pts, fill=c) - return XML.polyline( - points=pts, fill="transparent", stroke__width=w, stroke=c) + return XML.polyline(points=pts, fill="transparent", stroke__width=w, stroke=c) def find_dots(points: list[tuple[complex, complex]]) -> list[complex]: @@ -161,8 +157,8 @@ def find_dots(points: list[tuple[complex, complex]]) -> list[complex]: def bunch_o_lines(points: list[tuple[complex, complex]], **options): "Return a for each pair of points." - out = '' - scale = options['scale'] + out = "" + scale = options["scale"] w = options["stroke_width"] c = options["stroke"] for p1, p2 in points: @@ -174,17 +170,19 @@ def bunch_o_lines(points: list[tuple[complex, complex]], **options): f"{p2.real * scale}," f"{p2.imag * scale}", stroke=c, - stroke__width=w) + stroke__width=w, + ) return out def id_text( - box: Cbox, - bom_data: BOMData, - terminals: list[Terminal], - unit: str | list[str] | None, - point: complex | None = None, - **options): + box: Cbox, + bom_data: BOMData, + terminals: list[Terminal], + unit: str | list[str] | None, + point: complex | None = None, + **options, +): "Format the component ID and value around the point." if options["nolabels"]: return "" @@ -201,28 +199,33 @@ def id_text( text = format_metric_unit(text, unit) classy = "cmp-value" else: - text = " ".join(format_metric_unit(x, y, six) - for x, (y, six) in zip(text.split(","), unit)) + text = " ".join( + format_metric_unit(x, y, six) + for x, (y, six) in zip(text.split(","), unit) + ) classy = "cmp-value" data = XML.tspan(text, class_=classy) if len(terminals) > 1: - textach = "start" if ( - any(Side.BOTTOM == t.side for t in terminals) - or any(Side.TOP == t.side for t in terminals) - ) else "middle" + textach = ( + "start" + if ( + any(Side.BOTTOM == t.side for t in terminals) + or any(Side.TOP == t.side for t in terminals) + ) + else "middle" + ) else: - textach = "middle" if terminals[0].side in ( - Side.TOP, Side.BOTTOM) else "start" + textach = "middle" if terminals[0].side in (Side.TOP, Side.BOTTOM) else "start" return XML.text( - (XML.tspan(f"{box.type}{box.id}", class_="cmp-id") - * bool("L" in label_style)), + (XML.tspan(f"{box.type}{box.id}", class_="cmp-id") * bool("L" in label_style)), " " * (bool(data) and "L" in label_style), data * bool("V" in label_style), x=point.real, y=point.imag, text__anchor=textach, font__size=options["scale"], - fill=options["stroke"]) + fill=options["stroke"], + ) def make_text_point(t1: complex, t2: complex, **options) -> complex: @@ -236,18 +239,22 @@ def make_text_point(t1: complex, t2: complex, **options) -> complex: def make_plus( - terminals: list[Terminal], - center: complex, - theta: float, - **options) -> str: + terminals: list[Terminal], center: complex, theta: float, **options +) -> str: "Make a + sign if the terminals indicate the component is polarized." if all(t.flag != "+" for t in terminals): return "" return XML.g( - bunch_o_lines(deep_transform(deep_transform( - [(.125, -.125), (.125j, -.125j)], 0, theta), - center + deep_transform(.33+.75j, 0, theta), 0), **options), - class_="plus") + bunch_o_lines( + deep_transform( + deep_transform([(0.125, -0.125), (0.125j, -0.125j)], 0, theta), + center + deep_transform(0.33 + 0.75j, 0, theta), + 0, + ), + **options, + ), + class_="plus", + ) def arrow_points(p1: complex, p2: complex) -> list[tuple[complex, complex]]: @@ -256,59 +263,50 @@ def arrow_points(p1: complex, p2: complex) -> list[tuple[complex, complex]]: tick_len = min(0.5, abs(p2 - p1)) return [ (p2, p1), - (p2, p2 - rect(tick_len, angle + pi/5)), - (p2, p2 - rect(tick_len, angle - pi/5))] + (p2, p2 - rect(tick_len, angle + pi / 5)), + (p2, p2 - rect(tick_len, angle - pi / 5)), + ] def make_variable( - center: complex, - theta: float, - is_variable: bool = True, - **options) -> str: + center: complex, theta: float, is_variable: bool = True, **options +) -> str: "Draw a 'variable' arrow across the component." if not is_variable: return "" return bunch_o_lines( - deep_transform( - arrow_points(-1, 1), - center, - (theta % pi) + pi/4), - **options) - - -def light_arrows( - center: complex, - theta: float, - out: bool, - **options): + deep_transform(arrow_points(-1, 1), center, (theta % pi) + pi / 4), **options + ) + + +def light_arrows(center: complex, theta: float, out: bool, **options): """Draw arrows towards or away from the component (i.e. light-emitting or light-dependent).""" - a, b = 1j, .3+.3j + a, b = 1j, 0.3 + 0.3j if out: a, b = b, a return bunch_o_lines( - deep_transform( - arrow_points(a, b), - center, theta - pi/2), - **options) + bunch_o_lines( - deep_transform( - arrow_points(a - .5, b - .5), - center, theta - pi/2), - **options) + deep_transform(arrow_points(a, b), center, theta - pi / 2), **options + ) + bunch_o_lines( + deep_transform(arrow_points(a - 0.5, b - 0.5), center, theta - pi / 2), + **options, + ) def sort_counterclockwise(terminals: list[Terminal]) -> list[Terminal]: "Sort the terminals in counterclockwise order." partitioned = { side: list(filtered_terminals) - for side, filtered_terminals in groupby( - terminals, - lambda t: t.side)} - return list(chain( - sorted(partitioned.get(Side.LEFT, []), key=lambda t: t.pt.imag), - sorted(partitioned.get(Side.BOTTOM, []), key=lambda t: t.pt.real), - sorted(partitioned.get(Side.RIGHT, []), key=lambda t: -t.pt.imag), - sorted(partitioned.get(Side.TOP, []), key=lambda t: -t.pt.real))) + for side, filtered_terminals in groupby(terminals, lambda t: t.side) + } + return list( + chain( + sorted(partitioned.get(Side.LEFT, []), key=lambda t: t.pt.imag), + sorted(partitioned.get(Side.BOTTOM, []), key=lambda t: t.pt.real), + sorted(partitioned.get(Side.RIGHT, []), key=lambda t: -t.pt.imag), + sorted(partitioned.get(Side.TOP, []), key=lambda t: -t.pt.real), + ) + ) def is_clockwise(terminals: list[Terminal]) -> bool: @@ -321,7 +319,9 @@ def is_clockwise(terminals: list[Terminal]) -> bool: return False -def sort_for_flags(terminals: list[Terminal], box: Cbox, *flags: list[str]) -> list[Terminal]: +def sort_for_flags( + terminals: list[Terminal], box: Cbox, *flags: list[str] +) -> list[Terminal]: """Sorts out the terminals in the specified order using the flags. Raises and error if the flags are absent.""" out = () @@ -330,12 +330,14 @@ def sort_for_flags(terminals: list[Terminal], box: Cbox, *flags: list[str]) -> l if len(matching_terminals) > 1: raise TerminalsError( f"Multiple terminals with the same flag {flag} " - f"on component {box.type}{box.id}") + f"on component {box.type}{box.id}" + ) if len(matching_terminals) == 0: raise TerminalsError( f"Need a terminal with the flag {flag} " - f"on component {box.type}{box.id}") - terminal, = matching_terminals + f"on component {box.type}{box.id}" + ) + (terminal,) = matching_terminals out = *out, terminal terminals.remove(terminal) return out diff --git a/schemascii/wires.py b/schemascii/wires.py index e6fe999..ecc1130 100644 --- a/schemascii/wires.py +++ b/schemascii/wires.py @@ -9,33 +9,32 @@ def next_in_dir( - grid: Grid, - point: complex, - dydx: complex) -> tuple[complex, complex] | None: + grid: Grid, point: complex, dydx: complex +) -> tuple[complex, complex] | None: """Follows the wire starting at the point in the specified direction, until some interesting change (a corner, junction, or end). Returns the tuple (new, old).""" old_point = point match grid.get(point): - case '|' | '(' | ')': + case "|" | "(" | ")": # extend up or down if dydx in (1j, -1j): - while grid.get(point) in '-|()': + while grid.get(point) in "-|()": point += dydx - if grid.get(point) != '*': + if grid.get(point) != "*": point -= dydx else: return None # The vertical wires do not connect horizontally - case '-': + case "-": # extend sideways if dydx in (1, -1): - while grid.get(point) in '-|()': + while grid.get(point) in "-|()": point += dydx - if grid.get(point) != '*': + if grid.get(point) != "*": point -= dydx else: return None # The horizontal wires do not connect vertically - case '*': + case "*": # can extend any direction if grid.get(point + dydx) in "|()-*": point += dydx @@ -88,8 +87,7 @@ def blank_wire(grid: Grid, p1: complex, p2: complex): keep = ["|()", "-"][way] swap = "|-"[way] if old not in keep: - if (grid.get(px + side) in keep and - grid.get(px - side) in keep): + if grid.get(px + side) in keep and grid.get(px - side) in keep: grid.setmask(px, swap) else: grid.setmask(px) @@ -103,7 +101,7 @@ def next_wire(grid: Grid, **options) -> str | None: color = options["stroke"] # Find the first wire or return None for i, line in enumerate(grid.lines): - indexes = [line.index(c) for c in '-|()*' if c in line] + indexes = [line.index(c) for c in "-|()*" if c in line] if len(indexes) > 0: line_pieces = search_wire(grid, complex(min(indexes), i)) if line_pieces: @@ -124,17 +122,22 @@ def next_wire(grid: Grid, **options) -> str | None: x2=p2.real * scale, y2=p2.imag * scale, stroke__width=stroke_width, - stroke=color) - for p1, p2 in line_pieces), + stroke=color, + ) + for p1, p2 in line_pieces + ), *( XML.circle( cx=pt.real * scale, cy=pt.imag * scale, r=2 * stroke_width, stroke="none", - fill=color) - for pt in dots), - class_="wire") + fill=color, + ) + for pt in dots + ), + class_="wire" + ) def get_wires(grid: Grid, **options) -> str: @@ -147,7 +150,7 @@ def get_wires(grid: Grid, **options) -> str: return out -if __name__ == '__main__': - xg = Grid('test_data/test_resistors.txt') +if __name__ == "__main__": + xg = Grid("test_data/test_resistors.txt") print(get_wires(xg, scale=20)) print(xg) From d0d3f2d3ea81d045e16102ffe80817039b6399b1 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Wed, 24 May 2023 15:10:14 +0000 Subject: [PATCH 14/52] add switches -> 0.2.3 --- dist/schemascii-0.2.3-py3-none-any.whl | Bin 0 -> 46680 bytes dist/schemascii-0.2.3.tar.gz | Bin 0 -> 57008 bytes index.html | 96 +++++++++++++++++++++++++ pyproject.toml | 2 +- schemascii/__init__.py | 2 +- schemascii/components_render.py | 73 +++++++++++++++++-- schemascii/utils.py | 4 +- schemascii_example.css | 9 ++- supported-components.md | 2 + test_data/test_charge_pump.txt.svg | 2 +- test_data/test_switches.txt | 6 ++ 11 files changed, 184 insertions(+), 12 deletions(-) create mode 100644 dist/schemascii-0.2.3-py3-none-any.whl create mode 100644 dist/schemascii-0.2.3.tar.gz create mode 100644 index.html create mode 100644 test_data/test_switches.txt diff --git a/dist/schemascii-0.2.3-py3-none-any.whl b/dist/schemascii-0.2.3-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..798c11442f169812864081c50732f8f7bec2e66f GIT binary patch literal 46680 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 +S-^ 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

  • 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 literal 0 HcmV?d00001 diff --git a/index.html b/index.html new file mode 100644 index 0000000..47835d9 --- /dev/null +++ b/index.html @@ -0,0 +1,96 @@ + + + + + Schemascii + + + + + + +

    Schemascii Playground

    +
    +
    +
    +

    Schemascii Source

    + +
    +
    +
    +

    CSS

    +
    +
    +
    +
    
    +        
    + + + + \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 39cf0ee..7524d87 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "schemascii" -version = "0.2.2" +version = "0.2.3" description = "Render ASCII-art schematics to SVG" readme = "README.md" authors = [{ name = "dragoncoder047", email = "101021094+dragoncoder047@users.noreply.github.com" }] diff --git a/schemascii/__init__.py b/schemascii/__init__.py index 29b2001..c3fd015 100644 --- a/schemascii/__init__.py +++ b/schemascii/__init__.py @@ -8,7 +8,7 @@ from .utils import XML from .errors import * -__version__ = "0.2.2" +__version__ = "0.2.3" def render(filename: str, text: str = None, **options) -> str: diff --git a/schemascii/components_render.py b/schemascii/components_render.py index 4ee60b1..81c9955 100644 --- a/schemascii/components_render.py +++ b/schemascii/components_render.py @@ -69,7 +69,8 @@ def de_ambiguous( box: Cbox, terminals: list[Terminal], bom_data: list[BOMData], **options ): if len(bom_data) > 1: - raise BOMError(f"Ambiguous BOM data for {box.type}{box.id}: {bom_data!r}") + raise BOMError( + f"Ambiguous BOM data for {box.type}{box.id}: {bom_data!r}") if not bom_data: bom_data = [BOMData(box.type, box.id, "")] return func(box, terminals, bom_data[0], **options) @@ -111,7 +112,8 @@ def resistor(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options) quad_angle = angle + pi / 2 points = [t1] for i in range(1, 4 * int(length)): - points.append(t1 - rect(i / 4, angle) + pow(-1, i) * rect(1, quad_angle) / 4) + points.append(t1 - rect(i / 4, angle) + pow(-1, i) + * rect(1, quad_angle) / 4) points.append(t2) return ( polylinegon(points, **options) @@ -323,7 +325,8 @@ def integrated_circuit( x=sc_text_pt.real, y=sc_text_pt.imag, text__anchor=( - "start" if (terminal.side in (Side.TOP, Side.BOTTOM)) else "middle" + "start" if (terminal.side in ( + Side.TOP, Side.BOTTOM)) else "middle" ), font__size=options["scale"], fill=options["stroke"], @@ -415,7 +418,8 @@ def transistor(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **option (sp, mid - rect(0.8, theta)), # Lead out ] if "fet" in silicon_type: - arr = mid + rect(0.8, theta), mid + rect(0.8, theta) + rect(0.7, thetaquarter) + arr = mid + rect(0.8, theta), mid + \ + rect(0.8, theta) + rect(0.7, thetaquarter) if "nfet" == silicon_type: arr = arr[1], arr[0] out_lines.extend( @@ -436,7 +440,8 @@ def transistor(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **option ] ) else: - arr = mid + rect(0.8, theta), mid + rect(0.4, theta) + rect(1, thetaquarter) + arr = mid + rect(0.8, theta), mid + \ + rect(0.4, theta) + rect(1, thetaquarter) if "npn" == silicon_type: arr = arr[1], arr[0] out_lines.extend( @@ -468,7 +473,8 @@ def ground(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): points = [(0, 1j), (-0.5 + 1j, 0.5 + 1j)] match icon_type: case "earth": - points += [(-0.33 + 1.25j, 0.33 + 1.25j), (-0.16 + 1.5j, 0.16 + 1.5j)] + points += [(-0.33 + 1.25j, 0.33 + 1.25j), + (-0.16 + 1.5j, 0.16 + 1.5j)] case "chassis": points += [ (-0.5 + 1j, -0.25 + 1.5j), @@ -485,6 +491,61 @@ def ground(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): return bunch_o_lines(points, **options) +@component("S", "SW", "PB") +@n_terminal(2) +@no_ambiguous +def switch(box: Cbox, terminals: list[Terminal], bom_data: BOMData, **options): + """Draw a mechanical switch symbol. + bom:{nc/no}[m][:label]""" + icon_type = bom_data.data or "no" + if ":" in icon_type: + icon_type, *b = icon_type.split(":") + bom_data = BOMData(bom_data.type, bom_data.id, ":".join(b)) + else: + bom_data = BOMData(bom_data.type, bom_data.id, "") + t1, t2 = terminals[0].pt, terminals[1].pt + mid = (t1 + t2) / 2 + angle = phase(t1 - t2) + quad_angle = angle + pi / 2 + scale = options["scale"] + out = (XML.circle( + cx=(rect(-scale, angle) + mid * scale).real, + cy=(rect(-scale, angle) + mid * scale).imag, + r=scale / 4, + stroke="transparent", + fill=options["stroke"], + class_="filled", + ) + XML.circle( + cx=(rect(scale, angle) + mid * scale).real, + cy=(rect(scale, angle) + mid * scale).imag, + r=scale / 4, + stroke="transparent", + fill=options["stroke"], + class_="filled", + ) + bunch_o_lines([(t1, mid + rect(1, angle)), (t2, mid + rect(-1, angle))], **options)) + sc = 1 + match icon_type: + case "nc": + points = [(-1j, -.3+1j)] + case "no": + points = [(-1j, -.8+1j)] + sc = 1.9 + case "ncm": + points = [(.3-1j, .3+1j)] + out += polylinegon(deep_transform([-.5+.6j, -.5-.6j, .3-.6j, .3+.6j], mid, angle), True, **options) + sc = 1.3 + case "nom": + points = [(-.5-1j, -.5+1j)] + out += polylinegon(deep_transform([-1+.6j, -1-.6j, -.5-.6j, -.5+.6j], mid, angle), True, **options) + sc = 2.5 + case _: + raise BOMError(f"Unknown switch symbol type: {icon_type}") + points = deep_transform(points, mid, angle) + return bunch_o_lines(points, **options) + out + id_text( + box, bom_data, terminals, None, make_text_point( + t1, t2, **(options | {"offset_scaler": sc})), **options) + + # code for drawing stuff # https://github.com/pfalstad/circuitjs1/tree/master/src/com/lushprojects/circuitjs1/client # https://github.com/KenKundert/svg_schematic/blob/0abb5dc/svg_schematic.py diff --git a/schemascii/utils.py b/schemascii/utils.py index 39e7f7a..bc0bd08 100644 --- a/schemascii/utils.py +++ b/schemascii/utils.py @@ -133,7 +133,7 @@ def polylinegon(points: list[complex], is_polygon: bool = False, **options): c = options["stroke"] pts = " ".join(f"{x.real * scale},{x.imag * scale}" for x in points) if is_polygon: - return XML.polygon(points=pts, fill=c) + return XML.polygon(points=pts, fill=c, class_="filled") return XML.polyline(points=pts, fill="transparent", stroke__width=w, stroke=c) @@ -233,7 +233,7 @@ def make_text_point(t1: complex, t2: complex, **options) -> complex: quad_angle = phase(t1 - t2) + pi / 2 scale = options["scale"] text_pt = (t1 + t2) * scale / 2 - offset = rect(scale / 2, quad_angle) + offset = rect(scale / 2 * options.get("offset_scaler", 1), quad_angle) text_pt += complex(abs(offset.real), -abs(offset.imag)) return text_pt diff --git a/schemascii_example.css b/schemascii_example.css index 0d2f62b..22754ad 100644 --- a/schemascii_example.css +++ b/schemascii_example.css @@ -18,7 +18,7 @@ svg.schemascii :is(.wire, .component):hover { --sch-color: lime; } -svg.schemascii .component :is(polyline, path, line, polygon, rect, circle) { +svg.schemascii .component :is(polyline, path, line, polygon, rect, circle):not(.filled) { stroke: var(--sch-color, red); stroke-width: 2; stroke-linecap: round; @@ -26,6 +26,13 @@ svg.schemascii .component :is(polyline, path, line, polygon, rect, circle) { fill: transparent; } +svg.schemascii .component :is(polyline, path, line, polygon, rect, circle).filled { + fill: var(--sch-color, red); + stroke: none; + transition-duration: 0.2s; +} + + svg.schemascii .component .plus :is(polyline, path, line) { stroke-width: 1; } diff --git a/supported-components.md b/supported-components.md index e76a3ab..7138a45 100644 --- a/supported-components.md +++ b/supported-components.md @@ -18,3 +18,5 @@ and run scripts/docs.py to re-generate this file. | `U`, `IC` | Draw an IC. | `part-number[,pin1-label[,pin2-label[,...]]]` | | | `J`, `P` | Draw a jack connector or plug. | `label[,{circle/input/output}]` | | | `Q`, `MOSFET`, `MOS`, `FET` | Draw a bipolar transistor (PNP/NPN) or FET (NFET/PFET). | `{npn/pnp/nfet/pfet}:part-number` | `s` = source
    `d` = drain
    `g` = gate
    `e` = emitter
    `c` = collector
    `b` = base | +| `G`, `GND` | Draw a ground symbol. | `[{earth/chassis/signal/common}]` | | +| `S`, `SW`, `PB` | Draw a mechanical switch symbol. | `{nc/no}[m][:label]` | | diff --git a/test_data/test_charge_pump.txt.svg b/test_data/test_charge_pump.txt.svg index 5d945b7..115782c 100644 --- a/test_data/test_charge_pump.txt.svg +++ b/test_data/test_charge_pump.txt.svg @@ -1 +1 @@ -NE555U176215348BAT1 5 VR1 10 kΩC2 10 µFD2 1N4001J1 -5VR2 100 kΩC1 0.01 µFC3 100 µFC4 10 pFD1 1N4001J2 GND \ No newline at end of file +NE555U176215348BAT1 5 VR1 10 kΩC2 10 µFD2 1N4001J1 -5VR2 100 kΩC1 0.01 µFC3 100 µFC4 10 pFD1 1N4001J2 GND \ No newline at end of file diff --git a/test_data/test_switches.txt b/test_data/test_switches.txt new file mode 100644 index 0000000..03a1ecd --- /dev/null +++ b/test_data/test_switches.txt @@ -0,0 +1,6 @@ +!padding=30! +*------S1-------S2--------S3-----S4-- +| S1:nc S2:no S3:ncm S4:nom +S5 S5:nc:LIMIT +| +| \ No newline at end of file From e159cadd13b140651877b02ad5d873be92438f30 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Wed, 24 May 2023 15:15:06 +0000 Subject: [PATCH 15/52] show error handler on playground --- index.html | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/index.html b/index.html index 47835d9..46fa8d0 100644 --- a/index.html +++ b/index.html @@ -56,18 +56,23 @@

    Schemascii Playground

    var render_button = document.getElementById("render"); var schemascii; async function main() { - info("Loading Python... "); - pyodide = await loadPyodide({ stdout: info, stderr: error }); - info("done\n"); - info("Fetching current Schemascii version... "); - var pyproject_toml = await fetch("pyproject.toml").then(x => x.text()); - var ver = /version = "([\d.]+)"/.exec(pyproject_toml)[1]; - info(ver + "\n"); - info(`Installing schemascii-${ver}... `); - await pyodide.runPythonAsync(`import micropip\nawait micropip.install("https://dragoncoder047.github.io/schemascii/dist/schemascii-${ver}-py3-none-any.whl")`); - schemascii = pyodide.pyimport("schemascii"); - setup(); - console.textContent = "ready\n"; + try { + info("Loading Python... "); + pyodide = await loadPyodide({ stdout: info, stderr: error }); + info("done\n"); + info("Fetching current Schemascii version... "); + var pyproject_toml = await fetch("pyproject.toml").then(x => x.text()); + var ver = /version = "([\d.]+)"/.exec(pyproject_toml)[1]; + info(ver + "\n"); + info(`Installing schemascii-${ver}... `); + await pyodide.runPythonAsync(`import micropip\nawait micropip.install("https://dragoncoder047.github.io/schemascii/dist/schemascii-${ver}-py3-none-any.whl")`); + schemascii = pyodide.pyimport("schemascii"); + setup(); + console.textContent = "ready\n"; + } catch (e) { + error(`\nJS Error:\n${e.stack}\n`); + throw e; + } } function info(line) { console.textContent += line; From 40c189967f97069023623bb3ef93c1c1124a70a2 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Wed, 24 May 2023 15:17:15 +0000 Subject: [PATCH 16/52] expand it all + fetch default css --- index.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 46fa8d0..58d962a 100644 --- a/index.html +++ b/index.html @@ -30,7 +30,7 @@

    Schemascii Playground

    -
    +

    Schemascii Source

    @@ -67,7 +67,7 @@

    Schemascii Playground

    info(`Installing schemascii-${ver}... `); await pyodide.runPythonAsync(`import micropip\nawait micropip.install("https://dragoncoder047.github.io/schemascii/dist/schemascii-${ver}-py3-none-any.whl")`); schemascii = pyodide.pyimport("schemascii"); - setup(); + await setup(); console.textContent = "ready\n"; } catch (e) { error(`\nJS Error:\n${e.stack}\n`); @@ -80,7 +80,8 @@

    Schemascii Playground

    function error(text) { errors.textContent += text; } - function setup() { + async function setup() { + css.value = await fetch("schemascii_example.css").then(x => x.text()); css.addEventListener("input", () => { style_elem.innerHTML = css.value; }); From 3c1df60aba208609daba65cdeff856db70a14d69 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Wed, 24 May 2023 15:22:21 +0000 Subject: [PATCH 17/52] wait for micropip to load --- index.html | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/index.html b/index.html index 58d962a..a6f38bb 100644 --- a/index.html +++ b/index.html @@ -43,7 +43,7 @@

    Schemascii Playground

    
    -        
    +
    
         
         
     
    -
    \ No newline at end of file
    +
    
    From bb539979e811e1c02ca7bd53283f9ac59ab1bdf5 Mon Sep 17 00:00:00 2001
    From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com>
    Date: Wed, 24 May 2023 12:31:59 -0400
    Subject: [PATCH 26/52] implement debounce properly
    
    ---
     index.html | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/index.html b/index.html
    index ffaccb5..65d4062 100644
    --- a/index.html
    +++ b/index.html
    @@ -100,7 +100,7 @@ 

    Errors

    var timeout = null; source.addEventListener("input", () => { if (timeout) clearTimeout(timeout); - setTimeout(async () => { + timeout = setTimeout(async () => { console.textContent = ""; errors.textContent = ""; try { @@ -110,7 +110,7 @@

    Errors

    output.innerHTML = ""; throw e; } - }, 500); + }, 100); }); } main(); From 2895d00c54a0a6159412ccfa39f53b5a1d02dd76 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Wed, 24 May 2023 12:34:45 -0400 Subject: [PATCH 27/52] prevent senseless input if there is an error --- index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 65d4062..7ba4351 100644 --- a/index.html +++ b/index.html @@ -42,10 +42,10 @@

    Schemascii Playground

    -

    Schemascii Source

    +

    Schemascii Source

    -

    CSS

    +

    CSS

    Result

    @@ -112,6 +112,8 @@

    Errors

    } }, 100); }); + source.removeAttribute("disabled"); + css.removeAttribute("disabled"); } main(); From 27e2317788de41d1118f0ac4c6527f1389d396ab Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Wed, 24 May 2023 12:37:10 -0400 Subject: [PATCH 28/52] Update index.html --- index.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index 7ba4351..1389912 100644 --- a/index.html +++ b/index.html @@ -42,10 +42,10 @@

    Schemascii Playground

    -

    Schemascii Source

    +

    Schemascii Source

    -

    CSS

    +

    CSS

    Result

    @@ -54,6 +54,8 @@

    Messages

    
             

    Errors

    
    +        

    More Information

    +

    https://github.com/dragoncoder047/schemascii/

    - + \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index e14990c..91486a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "schemascii" -version = "0.3.1" +version = "0.3.2" description = "Render ASCII-art schematics to SVG" readme = "README.md" authors = [{ name = "dragoncoder047", email = "101021094+dragoncoder047@users.noreply.github.com" }] diff --git a/schemascii/__init__.py b/schemascii/__init__.py index ee060e4..96d7308 100644 --- a/schemascii/__init__.py +++ b/schemascii/__init__.py @@ -8,7 +8,7 @@ from .utils import XML from .errors import * -__version__ = "0.3.1" +__version__ = "0.3.2" def render(filename: str, text: str = None, **options) -> str: diff --git a/scripts/web_startup.py b/scripts/web_startup.py new file mode 100644 index 0000000..9e24293 --- /dev/null +++ b/scripts/web_startup.py @@ -0,0 +1,99 @@ +from pyodide.http import pyfetch as fetch, open_url as get +from pyodide.ffi import create_proxy as event_handler +import asyncio +import functools +import sys +import re +import js +import json +from operator import itemgetter +import warnings +import micropip + + +def debounced(fun): + timeout = None + + @functools.wraps(fun) + def inner(): + nonlocal timeout + if timeout: + js.clearTimeout(timeout) + timeout = js.setTimeout(fun, 100) + + return inner + + +def syncify(fun): + @functools.wraps(fun) + def inner(e): + return asyncio.ensure_future(fun(e)) + return inner + + +@event_handler +@debounced +def sync_css(): + style_elem.innerHTML = css_box.value + + +@event_handler +@debounced +def render_catch_warnings(*args, **kwargs): + import schemascii + console.textContent = "" + errors.textContent = "" + with warnings.catch_warnings(record=True) as captured_warnings: + out = schemascii.render(*args, **kwargs) + for warn in captured_warnings: + print("warning:", warn.message) + return out + + +@event_handler +@syncify +async def switch_version(): + if "schemascii" in sys.modules: + del sys.modules["schemascii"] # Invalidate cache + version = ver_switcher.value + await micropip.install(versions_to_wheel_map[version]) + +output = js.document.getElementById("output") +css_box = js.document.getElementById("css") +console = js.document.getElementById("console") +source = js.document.getElementById("schemascii") +style_elem = js.document.getElementById("custom-css") +errors = js.document.getElementById("errors") +ver_switcher = js.document.getElementById("version") + + +print("Loading all versions... ", end="") +versions_all = json.load( + get("https://api.github.com/repos/dragoncoder047/schemascii/contents/dist")) +versions_to_wheel_map = dict( + zip(map(itemgetter("name"), versions_all), map(itemgetter("path"), versions_all))) +all_versions = list(versions_to_wheel_map.keys()) +all_versions.append("DEV") +latest_version = re.search( + r'''version = "([\d.]+)"''', get("pyproject.toml").read()).group(1) +print(all_versions, "latest =", latest_version) + +for ver in all_versions: + opt = js.document.createElement("option") + opt.value = opt.textContent = ver + ver_switcher.append(opt) + +ver_switcher.value = latest_version +await micropip.install(versions_to_wheel_map[latest_version]) + + +css_source = get("schemascii_example.css").read() +style_elem.textContent = css_source +css_box.value = css_source + +css_box.addEventListener("input", sync_css) +source.addEventListener("input", render_catch_warnings) + +source.removeAttribute("disabled") +css_box.removeAttribute("disabled") +console.textContent = "ready\n" diff --git a/test_data/test_charge_pump.txt.svg b/test_data/test_charge_pump.txt.svg index e72f24f..128baf2 100644 --- a/test_data/test_charge_pump.txt.svg +++ b/test_data/test_charge_pump.txt.svg @@ -1 +1 @@ -NE555U176215348BAT1 5 VR1 10 kΩC2 10 µFD2 1N4001J1 -5VR2 100 kΩC1 0.01 µFC3 100 µFC4 10 pFD1 1N4001J2 GND \ No newline at end of file +NE555U176215348BAT1 5 VR1 10 kΩC2 10 µFD2 1N4001J1 -5VR2 100 kΩC1 0.01 µFC3 100 µFC4 10 pFD1 1N4001J2 GND \ No newline at end of file From 6757c2e882e22db54534430abe97f805d7b7b950 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 18:35:20 +0000 Subject: [PATCH 40/52] fix version finding bug --- scripts/web_startup.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/web_startup.py b/scripts/web_startup.py index 9e24293..1977a97 100644 --- a/scripts/web_startup.py +++ b/scripts/web_startup.py @@ -6,7 +6,6 @@ import re import js import json -from operator import itemgetter import warnings import micropip @@ -68,12 +67,13 @@ async def switch_version(): print("Loading all versions... ", end="") -versions_all = json.load( +foo = json.load( get("https://api.github.com/repos/dragoncoder047/schemascii/contents/dist")) +foo = filter(lambda x: x["name"].endswith(".whl"), foo) +foo = map(lambda x: x["path"], foo) versions_to_wheel_map = dict( - zip(map(itemgetter("name"), versions_all), map(itemgetter("path"), versions_all))) + zip(map(lambda x: re.search(r"""/schemascii-([\d.]+)-""", x).group(1), foo), foo)) all_versions = list(versions_to_wheel_map.keys()) -all_versions.append("DEV") latest_version = re.search( r'''version = "([\d.]+)"''', get("pyproject.toml").read()).group(1) print(all_versions, "latest =", latest_version) From c625572397b7a8ac17b574389175bd3e84e04c9b Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 18:41:39 +0000 Subject: [PATCH 41/52] mixed up lazy iteration --- scripts/web_startup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/web_startup.py b/scripts/web_startup.py index 1977a97..b4b8ac0 100644 --- a/scripts/web_startup.py +++ b/scripts/web_startup.py @@ -70,7 +70,7 @@ async def switch_version(): foo = json.load( get("https://api.github.com/repos/dragoncoder047/schemascii/contents/dist")) foo = filter(lambda x: x["name"].endswith(".whl"), foo) -foo = map(lambda x: x["path"], foo) +foo = list(map(lambda x: x["path"], foo)) versions_to_wheel_map = dict( zip(map(lambda x: re.search(r"""/schemascii-([\d.]+)-""", x).group(1), foo), foo)) all_versions = list(versions_to_wheel_map.keys()) From f44028cff791a95d228164ee60523895e4f0372d Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 18:55:18 +0000 Subject: [PATCH 42/52] add download button --- index.html | 2 +- scripts/web_startup.py | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index 098f57c..eafbbbb 100644 --- a/index.html +++ b/index.html @@ -61,7 +61,7 @@

    Schemascii Source

    CSS

    -

    Result

    +

    Result

    Messages

    
    diff --git a/scripts/web_startup.py b/scripts/web_startup.py
    index b4b8ac0..8a3b93a 100644
    --- a/scripts/web_startup.py
    +++ b/scripts/web_startup.py
    @@ -1,5 +1,3 @@
    -from pyodide.http import pyfetch as fetch, open_url as get
    -from pyodide.ffi import create_proxy as event_handler
     import asyncio
     import functools
     import sys
    @@ -7,6 +5,8 @@
     import js
     import json
     import warnings
    +from pyodide.http import pyfetch as fetch, open_url as get
    +from pyodide.ffi import create_proxy as event_handler
     import micropip
     
     
    @@ -57,6 +57,13 @@ async def switch_version():
         version = ver_switcher.value
         await micropip.install(versions_to_wheel_map[version])
     
    +@event_handler
    +def download_svg():
    +    a = js.document.createElement("a")
    +    a.setAttribute("href", js.URL.createObjectURL(js.Blob.new([output.innerHTML], {"type": "application/svg+xml"})))
    +    a.setAttribute("download", f"schemascii_playground_{js.Date.new.toISOString()}_no_css.svg")
    +    a.click()
    +
     output = js.document.getElementById("output")
     css_box = js.document.getElementById("css")
     console = js.document.getElementById("console")
    @@ -64,6 +71,7 @@ async def switch_version():
     style_elem = js.document.getElementById("custom-css")
     errors = js.document.getElementById("errors")
     ver_switcher = js.document.getElementById("version")
    +download_button = js.document.getElementById("download")
     
     
     print("Loading all versions... ", end="")
    @@ -93,6 +101,7 @@ async def switch_version():
     
     css_box.addEventListener("input", sync_css)
     source.addEventListener("input", render_catch_warnings)
    +download_button.addEventListener("click", download_svg)
     
     source.removeAttribute("disabled")
     css_box.removeAttribute("disabled")
    
    From b323c9a295ad9a3d4d8e071d928b2e89ef7ec598 Mon Sep 17 00:00:00 2001
    From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com>
    Date: Fri, 11 Aug 2023 19:29:51 +0000
    Subject: [PATCH 43/52] kludges on event handlers
    
    ---
     index.html             | 20 +++++++++++++++-
     scripts/web_startup.py | 52 ++++++++----------------------------------
     2 files changed, 29 insertions(+), 43 deletions(-)
    
    diff --git a/index.html b/index.html
    index eafbbbb..7847b02 100644
    --- a/index.html
    +++ b/index.html
    @@ -75,7 +75,11 @@ 

    More Information

    // cSpell:ignore pyodide pyproject var pyodide; var console = document.getElementById("console"); - var errors = document.getElementById("errors") + var errors = document.getElementById("errors"); + var css_box = document.getElementById("css"); + var source = document.getElementById("schemascii"); + var download_button = document.getElementById("download"); + var ver_switcher = document.getElementById("version"); async function main() { try { @@ -85,6 +89,13 @@

    More Information

    await pyodide.loadPackage("micropip", { errorCallback: error, messageCallback: () => { } }); info("done\n"); await pyodide.runPythonAsync(await fetch("scripts/web_startup.py").then(r => r.text())); + css_box.addEventListener("input", debounce(pyodide.globals.get("sync_css"))); + source.addEventListener("input", debounce(pyodide.globals.get("render_catch_warnings"))); + download_button.addEventListener("click", pyodide.globals.get("download_svg")); + ver_switcher.addEventListener("change", pyodide.globals.get("switch_version")); + source.removeAttribute("disabled"); + css_box.removeAttribute("disabled"); + console.textContent = "Ready"; } catch (e) { error(`\nFATAL ERROR:\n${e.stack}\n`); throw e; @@ -96,6 +107,13 @@

    More Information

    function error(text) { errors.textContent += text; } + function debounce(fun) { + var timeout; + return function() { + if (timeout) clearTimeout(timeout); + timeout = setTimeout(fun, 100); + } + } main(); diff --git a/scripts/web_startup.py b/scripts/web_startup.py index 8a3b93a..360902b 100644 --- a/scripts/web_startup.py +++ b/scripts/web_startup.py @@ -1,43 +1,17 @@ -import asyncio import functools import sys import re import js import json import warnings -from pyodide.http import pyfetch as fetch, open_url as get -from pyodide.ffi import create_proxy as event_handler +from pyodide.http import open_url as get import micropip -def debounced(fun): - timeout = None - - @functools.wraps(fun) - def inner(): - nonlocal timeout - if timeout: - js.clearTimeout(timeout) - timeout = js.setTimeout(fun, 100) - - return inner - - -def syncify(fun): - @functools.wraps(fun) - def inner(e): - return asyncio.ensure_future(fun(e)) - return inner - - -@event_handler -@debounced def sync_css(): style_elem.innerHTML = css_box.value -@event_handler -@debounced def render_catch_warnings(*args, **kwargs): import schemascii console.textContent = "" @@ -49,21 +23,23 @@ def render_catch_warnings(*args, **kwargs): return out -@event_handler -@syncify -async def switch_version(): +def switch_version(): if "schemascii" in sys.modules: del sys.modules["schemascii"] # Invalidate cache version = ver_switcher.value - await micropip.install(versions_to_wheel_map[version]) + js.eval( + f'''(async () => await pyodide.globals.get("micropip").install({versions_to_wheel_map[version]!r}))();''') + -@event_handler def download_svg(): a = js.document.createElement("a") - a.setAttribute("href", js.URL.createObjectURL(js.Blob.new([output.innerHTML], {"type": "application/svg+xml"}))) - a.setAttribute("download", f"schemascii_playground_{js.Date.new.toISOString()}_no_css.svg") + a.setAttribute("href", js.URL.createObjectURL(js.Blob.new( + [output.innerHTML], {"type": "application/svg+xml"}))) + a.setAttribute( + "download", f"schemascii_playground_{js.Date.new.toISOString()}_no_css.svg") a.click() + output = js.document.getElementById("output") css_box = js.document.getElementById("css") console = js.document.getElementById("console") @@ -98,11 +74,3 @@ def download_svg(): css_source = get("schemascii_example.css").read() style_elem.textContent = css_source css_box.value = css_source - -css_box.addEventListener("input", sync_css) -source.addEventListener("input", render_catch_warnings) -download_button.addEventListener("click", download_svg) - -source.removeAttribute("disabled") -css_box.removeAttribute("disabled") -console.textContent = "ready\n" From cf32b6cf08dd10ff6cbf320f6a22e3de897cb41d Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 20:46:36 +0000 Subject: [PATCH 44/52] move to js because pyodide is being annoying --- index.html | 46 +---------------- scripts/monkeypatch.py | 17 +++++++ scripts/web_startup.js | 110 +++++++++++++++++++++++++++++++++++++++++ scripts/web_startup.py | 76 ---------------------------- 4 files changed, 128 insertions(+), 121 deletions(-) create mode 100644 scripts/monkeypatch.py create mode 100644 scripts/web_startup.js delete mode 100644 scripts/web_startup.py diff --git a/index.html b/index.html index 7847b02..6f750b2 100644 --- a/index.html +++ b/index.html @@ -71,50 +71,6 @@

    More Information

    https://github.com/dragoncoder047/schemascii/

    - + \ No newline at end of file diff --git a/scripts/monkeypatch.py b/scripts/monkeypatch.py new file mode 100644 index 0000000..affc0fd --- /dev/null +++ b/scripts/monkeypatch.py @@ -0,0 +1,17 @@ +import sys +if "schemascii" in sys.modules: + del sys.modules["schemascii"] + +import warnings +import schemascii + +print("monkeypatching... ", end="") + +def patched(src): + with warnings.catch_warnings(record=True) as captured_warnings: + out = schemascii.render("", src) + for warn in captured_warnings: + print("warning:", warn.message) + return out + +schemascii.patched_render = patched diff --git a/scripts/web_startup.js b/scripts/web_startup.js new file mode 100644 index 0000000..d2b1a0b --- /dev/null +++ b/scripts/web_startup.js @@ -0,0 +1,110 @@ +// cSpell:ignore pyodide pyproject +var pyodide; +var console = document.getElementById("console"); +var errors = document.getElementById("errors"); +var css_box = document.getElementById("css"); +var source = document.getElementById("schemascii"); +var download_button = document.getElementById("download"); +var ver_switcher = document.getElementById("version"); + +var schemascii; +var monkeysrc; + +var ver_map; + +async function main() { + try { + info("Loading Python... "); + pyodide = await loadPyodide({ stdout: info, stderr: error }); + info("done\nInstalling micropip..."); + await pyodide.loadPackage("micropip", { errorCallback: error, messageCallback: () => { } }); + info("done\nFetching versions... "); + monkeysrc = await fetch("scripts/monkeypatch.py").then(r => r.text()); + var foo = await fetch("https://api.github.com/repos/dragoncoder047/schemascii/contents/dist").then(r => r.json()); + foo = foo.filter(x => x.name.endsWith(".whl")).map(x => x.path); + ver_map = Object.fromEntries(foo.map(x => [/\/schemascii-([\d.]+)-/.exec(x)[1], x])) + var all_versions = Object.keys(ver_map); + //all_versions.push("DEV"); + for (var v of all_versions) { + var o = document.createElement("option"); + o.textContent = o.value = v; + ver_switcher.append(o); + } + var latest_version = await fetch("pyproject.toml").then(r => r.text()).then(r => /version = "([\d.]+)"/.exec(r)[0]); + ver_switcher.value = latest_version; + info(`["${all_versions.join('", "')}"]\nlatest=${latest_version}\n`); + await switch_version(); + css_box.addEventListener("input", debounce(sync_css)); + source.addEventListener("input", debounce(catched(render))); + download_button.addEventListener("click", download); + ver_switcher.addEventListener("change", acatched(switch_version)); + + source.removeAttribute("disabled"); + css_box.removeAttribute("disabled"); + console.textContent = "Ready"; + } catch (e) { + error(`\nFATAL ERROR:\n${e.stack}\n`); + throw e; + } +} +function monkeypatch() { + pyodide.runPython(monkeysrc); +} +function info(line) { + console.textContent += line; +} +function error(text) { + errors.textContent += text; +} +function debounce(fun) { + var timeout; + return function () { + if (timeout) clearTimeout(timeout); + timeout = setTimeout(fun.bind(this, arguments), 100); + }; +} +function catched(fun) { + return function () { + try { + fun.call(this, arguments); + } catch (e) { + error(e.stack); + } + }; +} +async function acatched(fun) { + return async function() { + try { + await fun.call(this, arguments); + } catch (e) { + error(e.stack); + } + }; +} +function sync_css() { + style_elem.innerHTML = css_box.value; +} +function render() { + console.textContent = ""; + errors.textContent = ""; + output.textContent = schemascii.patched_render(source.value); +} + +async function switch_version() { + info("Installing Schemascii version " + ver_switcher.value + "... ") + await pyodide.pyimport("micropip").install(ver_map[ver_switcher.value]); + monkeypatch(); + schemascii = pyodide.runPython("import schemascii; schemascii"); + info("done\n"); +} + +function download() { + var a = document.createElement("a"); + a.setAttribute("href", URL.createObjectURL(new Blob([output.innerHTML], {"type": "application/svg+xml"}))); + a.setAttribute("download", `schemascii_playground_${new Date().toISOString()}_no_css.svg`); + a.click(); +} + +main(); + +// fetch("https://github.com/dragoncoder047/schemascii/zipball/main/").then(r => r.arrayBuffer()).then(b => pyodide.unpackArchive(b, "zip")); diff --git a/scripts/web_startup.py b/scripts/web_startup.py deleted file mode 100644 index 360902b..0000000 --- a/scripts/web_startup.py +++ /dev/null @@ -1,76 +0,0 @@ -import functools -import sys -import re -import js -import json -import warnings -from pyodide.http import open_url as get -import micropip - - -def sync_css(): - style_elem.innerHTML = css_box.value - - -def render_catch_warnings(*args, **kwargs): - import schemascii - console.textContent = "" - errors.textContent = "" - with warnings.catch_warnings(record=True) as captured_warnings: - out = schemascii.render(*args, **kwargs) - for warn in captured_warnings: - print("warning:", warn.message) - return out - - -def switch_version(): - if "schemascii" in sys.modules: - del sys.modules["schemascii"] # Invalidate cache - version = ver_switcher.value - js.eval( - f'''(async () => await pyodide.globals.get("micropip").install({versions_to_wheel_map[version]!r}))();''') - - -def download_svg(): - a = js.document.createElement("a") - a.setAttribute("href", js.URL.createObjectURL(js.Blob.new( - [output.innerHTML], {"type": "application/svg+xml"}))) - a.setAttribute( - "download", f"schemascii_playground_{js.Date.new.toISOString()}_no_css.svg") - a.click() - - -output = js.document.getElementById("output") -css_box = js.document.getElementById("css") -console = js.document.getElementById("console") -source = js.document.getElementById("schemascii") -style_elem = js.document.getElementById("custom-css") -errors = js.document.getElementById("errors") -ver_switcher = js.document.getElementById("version") -download_button = js.document.getElementById("download") - - -print("Loading all versions... ", end="") -foo = json.load( - get("https://api.github.com/repos/dragoncoder047/schemascii/contents/dist")) -foo = filter(lambda x: x["name"].endswith(".whl"), foo) -foo = list(map(lambda x: x["path"], foo)) -versions_to_wheel_map = dict( - zip(map(lambda x: re.search(r"""/schemascii-([\d.]+)-""", x).group(1), foo), foo)) -all_versions = list(versions_to_wheel_map.keys()) -latest_version = re.search( - r'''version = "([\d.]+)"''', get("pyproject.toml").read()).group(1) -print(all_versions, "latest =", latest_version) - -for ver in all_versions: - opt = js.document.createElement("option") - opt.value = opt.textContent = ver - ver_switcher.append(opt) - -ver_switcher.value = latest_version -await micropip.install(versions_to_wheel_map[latest_version]) - - -css_source = get("schemascii_example.css").read() -style_elem.textContent = css_source -css_box.value = css_source From 6b9bf5145f1a6afa6787482bc1fb48d977173801 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 16:49:03 -0400 Subject: [PATCH 45/52] typo --- scripts/web_startup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/web_startup.js b/scripts/web_startup.js index d2b1a0b..9547219 100644 --- a/scripts/web_startup.js +++ b/scripts/web_startup.js @@ -30,7 +30,7 @@ async function main() { o.textContent = o.value = v; ver_switcher.append(o); } - var latest_version = await fetch("pyproject.toml").then(r => r.text()).then(r => /version = "([\d.]+)"/.exec(r)[0]); + var latest_version = await fetch("pyproject.toml").then(r => r.text()).then(r => /version = "([\d.]+)"/.exec(r)[1]); ver_switcher.value = latest_version; info(`["${all_versions.join('", "')}"]\nlatest=${latest_version}\n`); await switch_version(); From 510aba8eb3bce4a6bff6218f199402ae24fbabb4 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 16:52:07 -0400 Subject: [PATCH 46/52] another typo --- scripts/web_startup.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/web_startup.js b/scripts/web_startup.js index 9547219..729c156 100644 --- a/scripts/web_startup.js +++ b/scripts/web_startup.js @@ -87,7 +87,7 @@ function sync_css() { function render() { console.textContent = ""; errors.textContent = ""; - output.textContent = schemascii.patched_render(source.value); + output.innerHTML = schemascii.patched_render(source.value); } async function switch_version() { From dbbee0dfd2c63b6d9b95eba2448b573382af8215 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 16:54:59 -0400 Subject: [PATCH 47/52] forgot to fetch css --- scripts/web_startup.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/web_startup.js b/scripts/web_startup.js index 729c156..a905ab9 100644 --- a/scripts/web_startup.js +++ b/scripts/web_startup.js @@ -39,6 +39,7 @@ async function main() { download_button.addEventListener("click", download); ver_switcher.addEventListener("change", acatched(switch_version)); + css_box.value = await fetch("schemascii_example.css").then(r => r.text()); source.removeAttribute("disabled"); css_box.removeAttribute("disabled"); console.textContent = "Ready"; From 43d70fffa7d6b230242fcf6370b0ace9e4a9a60a Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 17:01:16 -0400 Subject: [PATCH 48/52] missing objects --- scripts/web_startup.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/web_startup.js b/scripts/web_startup.js index a905ab9..12b455e 100644 --- a/scripts/web_startup.js +++ b/scripts/web_startup.js @@ -6,6 +6,8 @@ var css_box = document.getElementById("css"); var source = document.getElementById("schemascii"); var download_button = document.getElementById("download"); var ver_switcher = document.getElementById("version"); +var style_elem = document.getElementById("custom-css"); +var output = document.getElementById("output"); var schemascii; var monkeysrc; @@ -34,6 +36,7 @@ async function main() { ver_switcher.value = latest_version; info(`["${all_versions.join('", "')}"]\nlatest=${latest_version}\n`); await switch_version(); + css_box.addEventListener("input", debounce(sync_css)); source.addEventListener("input", debounce(catched(render))); download_button.addEventListener("click", download); @@ -95,11 +98,13 @@ async function switch_version() { info("Installing Schemascii version " + ver_switcher.value + "... ") await pyodide.pyimport("micropip").install(ver_map[ver_switcher.value]); monkeypatch(); - schemascii = pyodide.runPython("import schemascii; schemascii"); + schemascii = pyodide.runPython("import schemascii\nschemascii"); info("done\n"); + output.innerHTML = ""; } function download() { + if (!output.innerHTML) return; var a = document.createElement("a"); a.setAttribute("href", URL.createObjectURL(new Blob([output.innerHTML], {"type": "application/svg+xml"}))); a.setAttribute("download", `schemascii_playground_${new Date().toISOString()}_no_css.svg`); From 52bb36d4eae0274c20bbfea5b01508c3e2d44c0d Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 17:03:59 -0400 Subject: [PATCH 49/52] guards around installing new version --- scripts/web_startup.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/web_startup.js b/scripts/web_startup.js index 12b455e..00a45e9 100644 --- a/scripts/web_startup.js +++ b/scripts/web_startup.js @@ -95,12 +95,14 @@ function render() { } async function switch_version() { + source.setAttribute("disabled", true); info("Installing Schemascii version " + ver_switcher.value + "... ") await pyodide.pyimport("micropip").install(ver_map[ver_switcher.value]); monkeypatch(); schemascii = pyodide.runPython("import schemascii\nschemascii"); info("done\n"); output.innerHTML = ""; + source.removeAttribute("disabled"); } function download() { From a76158b6dfa26384f8e2fc8bdce52b5efca728bd Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 11 Aug 2023 17:04:48 -0400 Subject: [PATCH 50/52] sync css to start --- scripts/web_startup.js | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/web_startup.js b/scripts/web_startup.js index 00a45e9..db6ac5e 100644 --- a/scripts/web_startup.js +++ b/scripts/web_startup.js @@ -43,6 +43,7 @@ async function main() { ver_switcher.addEventListener("change", acatched(switch_version)); css_box.value = await fetch("schemascii_example.css").then(r => r.text()); + sync_css(); source.removeAttribute("disabled"); css_box.removeAttribute("disabled"); console.textContent = "Ready"; From 4889bbad2ffe686034acf2287a912955c5ef03e5 Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Mon, 16 Sep 2024 20:51:55 -0400 Subject: [PATCH 51/52] Use nested CSS --- schemascii_example.css | 108 +++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 59 deletions(-) diff --git a/schemascii_example.css b/schemascii_example.css index 617c61d..379ae3e 100644 --- a/schemascii_example.css +++ b/schemascii_example.css @@ -1,69 +1,59 @@ svg.schemascii { background: black; -} - -svg.schemascii .wire polyline { - stroke: var(--sch-color, blue); - stroke-width: 2; - stroke-linecap: round; - stroke-linejoin: round; - transition-duration: 0.2s; - fill: transparent; -} - -svg.schemascii .wire circle { - fill: var(--sch-color, blue); - transition-duration: 0.2s; -} - -svg.schemascii :is(.wire, .component):hover { - --sch-color: lime; -} - -svg.schemascii .component :is(polyline, path, line, polygon, rect, circle):not(.filled) { - stroke: var(--sch-color, red); - stroke-width: 2; - stroke-linecap: round; - transition-duration: 0.2s; - fill: transparent; -} - -svg.schemascii .component :is(polyline, path, line, polygon, rect, circle).filled { - fill: var(--sch-color, red); - stroke: none; - transition-duration: 0.2s; -} - - -svg.schemascii .component .plus :is(polyline, path, line) { - stroke-width: 1; -} - -svg.schemascii .component polygon { - fill: var(--sch-color, red); -} - -svg.schemascii .component text { - fill: white; - transition-duration: 0.2s; -} - -svg.schemascii .component:hover text { - font-weight: bold; -} -svg.schemascii .component tspan:is(.cmp-value, .part-num) { - opacity: 50%; + & .wire polyline { + stroke: var(--sch-color, blue); + stroke-width: 2; + stroke-linecap: round; + stroke-linejoin: round; + transition-duration: 0.2s; + fill: transparent; + } + & .wire circle { + fill: var(--sch-color, blue); + transition-duration: 0.2s; + } + & :is(.wire, .component):hover { + --sch-color: lime; + } + & .component :is(polyline, path, line, polygon, rect, circle):not(.filled) { + stroke: var(--sch-color, red); + stroke-width: 2; + stroke-linecap: round; + transition-duration: 0.2s; + fill: transparent; + } + & .component :is(polyline, path, line, polygon, rect, circle).filled { + fill: var(--sch-color, red); + stroke: none; + transition-duration: 0.2s; + } + & .component .plus :is(polyline, path, line) { + stroke-width: 1; + } + & .component polygon { + fill: var(--sch-color, red); + } + & .component text { + fill: white; + transition-duration: 0.2s; + } + & .component:hover text { + font-weight: bold; + } + & .component tspan:is(.cmp-value, .part-num) { + opacity: 50%; + } } @media all and (prefers-color-scheme: light) { svg.schemascii { background: white; - } - svg.schemascii .component text { - fill: black; - } - svg.schemascii :is(.wire, .component):hover { - --sch-color: lime; + & .component text { + fill: black; + } + & :is(.wire, .component):hover { + --sch-color: lime; + } } } From a4e968395668a7d8ba82633ba8bb881eb6d7e16f Mon Sep 17 00:00:00 2001 From: dragoncoder047 <101021094+dragoncoder047@users.noreply.github.com> Date: Fri, 16 May 2025 13:55:02 -0400 Subject: [PATCH 52/52] force monospaced font on textareas closes #10 --- index.html | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 6f750b2..7d2e0e7 100644 --- a/index.html +++ b/index.html @@ -24,6 +24,11 @@ resize: vertical; } + textarea, + pre { + font-family: "Fira Code", monospace; + } + #errors { color: red; } @@ -73,4 +78,4 @@

    More Information

    - \ No newline at end of file + pFad - Phonifier reborn

    Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

    Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


    Alternative Proxies:

    Alternative Proxy

    pFad Proxy

    pFad v3 Proxy

    pFad v4 Proxy