seqdiag-0.9.3/0000755000076600000240000000000012355212722013742 5ustar tkomiyastaff00000000000000seqdiag-0.9.3/bootstrap.py0000644000076600000240000001306112217202626016331 0ustar tkomiyastaff00000000000000############################################################################## # # Copyright (c) 2006 Zope Foundation and Contributors. # All Rights Reserved. # # This software is subject to the provisions of the Zope Public License, # Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS # FOR A PARTICULAR PURPOSE. # ############################################################################## """Bootstrap a buildout-based project Simply run this script in a directory containing a buildout.cfg. The script accepts buildout command-line options, so you can use the -c option to specify an alternate configuration file. """ import os import shutil import sys import tempfile from optparse import OptionParser tmpeggs = tempfile.mkdtemp() usage = '''\ [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] Bootstraps a buildout-based project. Simply run this script in a directory containing a buildout.cfg, using the Python that you want bin/buildout to use. Note that by using --find-links to point to local resources, you can keep this script from going over the network. ''' parser = OptionParser(usage=usage) parser.add_option("-v", "--version", help="use a specific zc.buildout version") parser.add_option("-t", "--accept-buildout-test-releases", dest='accept_buildout_test_releases', action="store_true", default=False, help=("Normally, if you do not specify a --version, the " "bootstrap script and buildout gets the newest " "*final* versions of zc.buildout and its recipes and " "extensions for you. If you use this flag, " "bootstrap and buildout will get the newest releases " "even if they are alphas or betas.")) parser.add_option("-c", "--config-file", help=("Specify the path to the buildout configuration " "file to be used.")) parser.add_option("-f", "--find-links", help=("Specify a URL to search for buildout releases")) options, args = parser.parse_args() ###################################################################### # load/install setuptools to_reload = False try: import pkg_resources import setuptools except ImportError: ez = {} try: from urllib.request import urlopen except ImportError: from urllib2 import urlopen # XXX use a more permanent ez_setup.py URL when available. exec(urlopen('http://bitbucket.org/pypa/setuptools/raw/0.7.2/ez_setup.py' ).read(), ez) setup_args = dict(to_dir=tmpeggs, download_delay=0) ez['use_setuptools'](**setup_args) if to_reload: reload(pkg_resources) import pkg_resources # This does not (always?) update the default working set. We will # do it. for path in sys.path: if path not in pkg_resources.working_set.entries: pkg_resources.working_set.add_entry(path) ###################################################################### # Install buildout ws = pkg_resources.working_set cmd = [sys.executable, '-c', 'from setuptools.command.easy_install import main; main()', '-mZqNxd', tmpeggs] find_links = os.environ.get( 'bootstrap-testing-find-links', options.find_links or ('http://downloads.buildout.org/' if options.accept_buildout_test_releases else None) ) if find_links: cmd.extend(['-f', find_links]) setuptools_path = ws.find( pkg_resources.Requirement.parse('setuptools')).location requirement = 'zc.buildout' version = options.version if version is None and not options.accept_buildout_test_releases: # Figure out the most recent final version of zc.buildout. import setuptools.package_index _final_parts = '*final-', '*final' def _final_version(parsed_version): for part in parsed_version: if (part[:1] == '*') and (part not in _final_parts): return False return True index = setuptools.package_index.PackageIndex( search_path=[setuptools_path]) if find_links: index.add_find_links((find_links,)) req = pkg_resources.Requirement.parse(requirement) if index.obtain(req) is not None: best = [] bestv = None for dist in index[req.project_name]: distv = dist.parsed_version if _final_version(distv): if bestv is None or distv > bestv: best = [dist] bestv = distv elif distv == bestv: best.append(dist) if best: best.sort() version = best[-1].version if version: requirement = '=='.join((requirement, version)) cmd.append(requirement) import subprocess if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0: raise Exception( "Failed to execute command:\n%s", repr(cmd)[1:-1]) ###################################################################### # Import and run buildout ws.add_entry(tmpeggs) ws.require(requirement) import zc.buildout.buildout if not [a for a in args if '=' not in a]: args.append('bootstrap') # if -c was provided, we push it back into args for buildout' main function if options.config_file is not None: args[0:0] = ['-c', options.config_file] zc.buildout.buildout.main(args) shutil.rmtree(tmpeggs) seqdiag-0.9.3/buildout.cfg0000644000076600000240000000061612354721644016264 0ustar tkomiyastaff00000000000000[buildout] parts = seqdiag test tox static_analysis develop = . [seqdiag] recipe = zc.recipe.egg eggs = seqdiag interpreter = py [test] recipe = pbp.recipe.noserunner eggs = seqdiag[rst] seqdiag[testing] coverage unittest-xml-reporting [tox] recipe = zc.recipe.egg eggs = tox detox [static_analysis] recipe = zc.recipe.egg eggs = coverage flake8 pylint seqdiag-0.9.3/examples/0000755000076600000240000000000012355212722015560 5ustar tkomiyastaff00000000000000seqdiag-0.9.3/examples/edge_attributes.diag0000644000076600000240000000030311650005514021550 0ustar tkomiyastaff00000000000000{ // edge label A -> B [label = "call"]; A <- B [label = "return"]; // diagonal edge A -> B [diagonal, label = "diagonal edge"]; A <- B [diagonal, label = "return diagonal edge"]; } seqdiag-0.9.3/examples/edge_attributes.png0000644000076600000240000002300111655736155021451 0ustar tkomiyastaff00000000000000PNG  IHDRڠ8%IDATxMs#ǝ|*t*֨r~Veso=yz~s9>eC~13ҶZdと=JV$@P'UfVtQ+1^DD""@H @$ DD""@H @$wX'xE?~-'iN"@HG98Ĝf9cs9!z@H @bN)<cDD:9!Dpls΃DZ99!z@H @Q1'vLs?1.D""r!6Br9A#T"!+7 ~ w{EDnc5{?I/:|m_qJ?ƀRr_)ne1ӧY:]Bk}ScjDN\+RJM&p]\\Z먵u\1$R?nȣVu]Ƙh1qcA#X9Q8Ɇz ՙֶ9AiN}+:RQԭ_B^l6{o~csRJc'V~CH\*u(O˲\B0J]1nL+?ύ>{e[mѿݻwO&d2u]gR* ZS)}\ @u?>߿>;;h+sεiNcq +__^^Z,/Vդm[ct!XOOOC/> 1&h[\Sr:^Zkt0`G"0mh1&Xk;\ouQWEQ\mRZۆlьeϕe82<~x'c:\S2}{8Zkm7l/s0 Euv{*⪪EUUi r5m}01tzyex7Yp5LWU5j7+kmc`ƳLP뚕.bYU|:^{_u]u] |C/skm7eUU(zC#0c$Pw]wI1&Zk;}Sr2.Ұ6MS@)5իWo ϡ_qo}]Ub:^'?ywvvv1LeY.M? 㩯zԿ_GT&i<Ak&ɼiu?+hd~;2[ZyOoVd7uSIQQ?'.aT,]uV땿,E]דiʶm? O A~k9Ld6N/`7aL[9?4Zh ι6Xݻ]"~|ui7?pρe/9w?NAGsE=byc7!خ\۶iii!t+&M@ W&  w6O3}9NcƘ.W]ld+(w"ߎno:;FWSGEHTt[{D @`g|`J<Jp#*u}cw˻O}ݻwC/ܜ"o]6ߑP?N\n) 5Q)!Ϲ{zY+XCԿJ>3ƺ98!b#IieOF˪L6}\c/iύ&Dj+%<s>!])޿R߻R߿nJ* IucPw^!!"!CqMr H~ҙF9ʐa#hdQD""yGm}F1Ȝ;m|~O.z@H @di<-|^O\"@H:xtP<i5K ù!/Q(}~$I|$~rmcs` <ž@sm[nw]džvr?Ĝ!DAs91TcC &w4۶5ym8Vs'.4q΅iL4&_C/#j9Eњ1J)彧d5|~ >nFliLpx@̉жTkc:u_:u[1Z7IclY6YV/1Ƙ(Tj 1J.֯ٶX,s+{t2xݢt8&wHcP7[}޳c,Yj4\Hf>pK l!cEP>>b&}qqduWzB~.%c"H?6m[1֮+ccc] =Uga9W!cisˢ(f{Bo0 cGc#pC@[5ֺ/l.5=}p܅4TomX,μ˺i?Lhpdl! myVi߶ΆL4 k2~ x3a+~5kPXW֮LM+hp lDʱn%^+[z @*ڶƄZDNl C2@lɨ#"@H @$ DD""@H @$ DD""@H @$ DD""@H @$ DD""Bk Rßcng\ȯ76+ZoM t6 m<{1MӘ(A6ZO)£C/Coo"eS* {ns1&cBuM;@^~C/oZ_zQg gˡxmi??q@?})˒qf4Y;o Ƙ` wꫯp_V+7?cbOs1OA7w۷//|m[kKk1]:X?"Fp׿C/@Q]acLvι{(TYҥ,UQ>tpDbko޼eUU?裷^.i!]þ1EQ\)t:+LuZNyUU(z)֚ъGbgljiise҇0VEQ,'L)/sm ggg'ɬ(~5 Ao@o@3 r@cj1s(ֺկ~|Qkqέs˾4Z6#@AnOӷ!ckmm11Ißƃ0Zi8T];2 *TY1F03^_T#ǁ0zD0:OjĪ뚯 !P'u4 "@H89OyE  y:@hDDbyy9cL!  ;x(=@H @$  V6P0>|H @$XZpe@H @$ !8ȿ_|ʲ9(9xq0n T]NFz!P}PJmo=Z{w"cLPÓkCѤ^ٺ߯ΰGp@|X,ֺj0>4Mc9RZkCu7 !PI!M}<|6/O++e=] M{}M5,7islx:sv6}px *OCOeS=>S#l6M;g]/:``ڭ7kOsww amkm,>{9AAN0+7A9 ԏ;(ua??dnp -N+.pź+&VbH 89O9o9@=@H s>>|HN7oltLetW_}W^˗/_jHNRQ޼y˪{Ƙ&!nnjģV[goI7  <ƦS2Ǐu*u?34<ŜදAP.nL H~">H=as741 D etnjXkkkmm1RJ8 D#ǯmpXrέsK9gRuv8>jfEYi.0Ƙx0x^_фj...a2̺J]{c\`%ws@ + nm[1֮+cccݦcN!PBjUcܲ(އlKAO0>V8^j[˦iʮR8 >4{j7!sř~Yu4M1 a:?@,8r㣥aЭ/ժhƷm뺮!?? b@D[}p3z~&{ p$@`d[vL[Iƒq]^~7{\F<3C5nKCO8n $A@ؚaT Ǎ7ca`?c c`l΀+boA"[}B «+"a0d*(b{_8,t:m 8^ Ѣ0 `tLH[} d"F])(8 xjfa6jDD""@H @$ DD""@H @$ DD""@H @$ DD""@H @$ DD""@H @$ DD""@H @$8aZ=vYG^0^ D@1Fg`0=R {[z_@MϿky=fzw-67cq΅=E<;@kRk5w-CJQ.1&nnϱֆmRAض1*}h(uu]AP065)5w¼]ܻcκ] ]um' oqsm.ß+xm!sAf2>u`J)@!m_ H@`Gá"wyu>?-w6 !M;t]g"R6Mc+y@}szϻѶw5vƘ.~#A8z@>Eu=1Z9Z}ReYj۶s5eYyp"Gp46mx}g~IC`{ ƘZx(Rj:ΕR:gm鼪EQWZd=֚eNm:h:0z>*b9LfJ)u~~~kSVU5?;;{?LfEQ,a|@؛MAlZ4*r>N/Rŋo˲\1+r1N/eYsUia <ڶAw}3ƴι{})ԋ/m1Zu罿L&~~霫1ֺ;W[a?@[;K*Ƙϥ!Z޻M|m[jCrQ,vhz}CO`M'xeyWks;:??:cZhms+ܲ-1ֺpЫ{A`iB!ckmm11Ißƃ{ЭCu/SJ)c̭!1ٜa_!8 02> p$[h6>D0C NA'xP#ǏAw:@`0 Aqx0&Cr:M FbT:"q8c8z0Tvιж-u$a!<6LRJVZ6B雺pp;;??_l8ڠV`x^~ue6.k5D}E^}ٿje4 p?^wꫯpe}`˗_zY s3d/=@l͛7|ݫC/Tҡ7;fb ˥a"ܡ6ցSDD""@H @$ @,  :zp8 @$UGƌĝAcED"=?cGZ_zQ`o@9ⶁKegػK;` Ƙu2\^^~ݻ}o߾?ms/3t}ބ"0 T6PC0csε(,UuWmvι,UQ>П50 H!cڡ%`gmuQWUU-+LuZNyUU(z)֚e,#ׇ0VEQ,':??xŻt9??8;;{?LfEQ,a|*=Kß1 ,R)^x,ec,b:^e9_e@p@^[gis~YUSJ/^|4McZ{5LfUUPU{9WcZuV31 GHkb\m+k1˗/_g۶EhC,geY/>o@3 2>ZcL3J)Rۮ|Qkqέs˾4Z6N(@CKàM_HMh1ƘӤOz|ƀ4{RJcnDR,ˋIv}/uN(Dv>.^ 1V)s ThQ]o]cG 0)&*:u1j2Ƭ SG &¸\.~CƆsF 3 4?xc`l@9R#m=G"P8BTLD""1: enD"" blockdiag { // edge label A -> B [label = "call"]; A <- B [label = "return"]; // diagonal edge A -> B [diagonal, label = "diagonal edge"]; A <- B [diagonal, label = "return diagonal edge"]; } A B call return diagonal edge return diagonal edge seqdiag-0.9.3/examples/edge_type.diag0000644000076600000240000000074511650005514020355 0ustar tkomiyastaff00000000000000{ // normal edge A -> B [label = "normal edge"]; // dotted edge B --> C [label = "dotted edge"]; // asynchronus edge A ->> B [label = "asynchronus edge"]; B -->> C [label = "asynchronus dotted edge"]; // return edge B <- C [label = "return edge"]; A <-- B [label = "return dotted edge"]; B <<- C [label = "return asynchronus edge"]; A <<-- B [label = "return asynchronus dotted edge"]; // self referenced edge A -> A [label = "self referenced edge"]; } seqdiag-0.9.3/examples/edge_type.png0000644000076600000240000004235011655736155020254 0ustar tkomiyastaff00000000000000PNG  IHDRFDIDATx͎#Ib'xs~dtjӭ)Zػ=ԩ`4=}` TRqN>:;"$Gy0I ~?Ac{u]HF^1$FHɘ^kR1$FHEv?nzڜ?=Tr c gN }Yt$!6?tt]ʗ?=_OYJ?8n7?!sR!$}ٻ?5!-,w,!PoWtJ.!0LS{(˲.˲v۶!&T7%CƀdYecbM1|B)K%7M$l>|(zcЄ6+PgRI*p_ֶm~pz_eYe,ruݲ(:bMs\—_gOR !m !5n׷mǁYu]5WRIYjQ^_qZ]a޽d2L&M!0fYC8A?QI%$nIw|jUBMQ~LH1뺮/&T7%m/_E]UռEYmŜ.BgH'e/o%m߿W!|Fx<7Mmf}9_?ۨ,MpxΧh@!\__/eY.'ru]5MS6Mw]9mQI٥} pY?mN]No>r9zx ?)Kߓ`Ф\Vź?/K3P_,p,koAq믿];?)KI1].D۶o0|j6],jUv]Wm{buQ?O]i1YGt: 6 T_Ww }ϲ1y7EQʲ˲\VU5jZB|նmu]/h4 /aݼ(ꪪnϺ,eYuQ<ϛ_@OW˧*wtYy7yeY.x< !(jU7zpQ}éw 6dx<dz`yy3 T7-}pm˗YUx1.,z4N&7o޼˲\i]U!\૯ex /,x;*˲y'z >qM.8h+b4M!|Fru=ZV3w2q ؟dr3L`OIHoeYnO]-buݲ??En/_? F[Yˢ(m?e?LWCPSZȫԛM뺻[۶Y۶y4j*뺮mu]\/WЛ NS,_Xٻx?KMñ1Ʀ?h&/ENE?x}'\od_~ܩRJ*>"hh6o6h s jcKnns~PSl&6v5Ju] {Ss/g޽'pw`p{T dt!v?\%ʲO]ml ~/e#JW$[7%Cܶ!X?їԏIٮ/%~y?1)$`oׇ;+K|?RwQ?}^OG?PJ{iR~!x!?HO"oKR^qi!.{=DJ$!R7(:{磔@=ue .`Mڇڏ N<#$FL\Y2?m1И;o>;o>K@scYx^?ϋyK @b@ɺ{u;uE F'e 1 @b] dLO۫<`%2')~C)')~CWyw6@lR>/]#$39)eYuݣ7(Sv^18vl> yBN 1+׮o\.rϫ%/sk:tvZUU.F1 \201ۮuݶ=]uݽ"b4m ?Gَ/ls=Oʲ !tt-?{7}3~ Z:>9oB۶BeY{ss3ʲ] nG;D.c|Z 1U<1E1ﺮY|J|YXmۃ@}᫶mc.ⶪ,˶muG kl!^.v_dY*r6?u=jt{ >TYv6)v\뺮6w~ٲ;B^`?IC vX,F岪\VE4y۶q|B ![z%ᎯourNIÿ|G﬚}Gr5;A΁m;;g,#|.?'CwpIR|iΏ#RJd';?RLH 1 @b@Hk͇ 1 $ȵ&$FH 1 @b@#@\ 8m>| A6 1 @b@)N]HYuI6Y 1 @bW5MO=И 1 $(sN1O0rb?,k{=uy^c{=l^@QZ[H!|ɏ,BnZvmc!Bl˲lvͷo~ZΓpl6+,kTUU>VZbQj}Xm4wcm۶1˲{ݴwk2?t!.Hf]^ac?x2ϱ.|GlZ.}A MҶmݮv>ZCe·p ukݽiZO!p|Pkަ`7|,ǎ[.~-`c·/8@$r/˗ 1 ,Ǟj(.lq3VUU1}!<Ϲ]1K bqpޮ']>.h4auݶu]w/ Go箯mf/!tӲm֏tBFb;˶:L㛛*˲.pw˲.0 CoNs<8>sz^^4{?tZ/cnc g_*m; !YBmA!2pAujfY,V[eY! < xru]bE|2Ƹ1!Ї@A3m֭8;*bQmYEQB1vDA3pl___,h4Cc?~L3E_.İu]ld2n co Z%r@P}Ç?_VBq"Eqc̻k#e.mۃ~᫶mc.ⶪ,˶mu_ |@@]/,[e95M^n -uw!egٛ,o帮j3g˺u%ew_,rYu]Vim۸^pu W/!^.aiطoy eaˆc  BO]>3#AH|BKe{'$FH 1 @b@#$FH 1 @b@#$FH 1 @b@S{,;QIK 1 @b@pB 1 @b@,S9\񺮻w8 1 2Ndr5,6(Bo(˲vWKٶi1wz=ׂ5z? EQQq|^ L]hQi=|ܷ6[mkvcvLa+߶Kvs׺}njK0ʫ"`,Ή]|n= 8<Z!pgA8Z]ױ뺻#s6o]\}vmvQ9oSc2!ta>y׿7wGhBn8k {}W__|˲6[D˷9v) Ѩ kڶ-?i׿ ]וmۖmm|g!$u]u6MSmʮ늮V؅:W΍>->mQ mZMַqQm1ƺ뺦6!8[y"!r7eY6M@t]Z9٪뺿vg{|VU5+bOx\VU4𜀙n_{,r꺮lٞ: u]u]ժh&^ $tm`"Ziumݾ1h6]OΊǰo8g .p!$ ?#$FH 1 @b@#$FH 1 @b@#$FH 1 @b@S!uݽY$O @b@18 cNG @b@Lep.S_{7NGU ^|> Mz2 +UUUUeY!EцBwCYжi1m}S=9rH`|2R8 \]]fYy{{0\.ﶱu]m&6Mcwۮbuq[`zhڶY>9lO|o,?6,coZOp}}=7M<8fvMR]S?d]94\]]Ͷ=\.cUUm(jR>ay2s}]O) D}2~뺎ؿciWK)Zݱ/fsi;Zh:}_oֿmU;ltom;dÇʳٲ8|ر^ww׺*Ù8zl]׹zc,kvڶism-Qlm |B8o8`zTyN1c8CB酓.TjxXЮJ>}]e GotDw-3 à`x^guݑv[u^\y@/as7熗ۼpm40y4C.3֏m'8qvB0 p| ]O]g4U۶캮n]s%$r߶Vd}E1jvckkqgK3ԏ)^zpdž囪ޔey4͢aum sR y|VU5+bY,r9ZVe4sf}ϓlX,F岪ֳe{N?+%[u]u]Vi|x5ӵ9C jʛ/mwf7تmlx[wn>! V־aֿ'[9r ^B$$FH 1 @b@#$FH 1 @b@#$FH 1 @b@#$FH 1 @b@#$FHHH^eBIX},Ǜo]Z~_yclc[-˲l˲\y)˲뺸~uq#ضm{wLj!| *v]ʲl뺎!| RGQah]cDŽ}c,XU@ ױ=vjX Iv2s rkBi<#% zϳ9Bn6:i8<-L뺎WUqEbmf=}ؿ;RMOcH &IBk.Je.WWWS>7!_.|nY J8Ÿٟ?.,˺-9O Lfo޼N,y/,v gHB!yv4L&xa<XMQ1eqBh?CB!EQ̫Fxxk <ZZ$B< @b> -@c " |=$FHc0&t$FHcW 1 @b@#$FH 1 @b@#$FH Ȳ=E ^Kcl5ai,k7o>/tmγm}5϶iZ{Hclc[/˲l˲RTpI,kw]}MUC_{1m.yZbj]ׅ,ۺcr@6v>\=: 6] xrp - SkݾC_-3:[t8==}ac*>.]c6?Gܷipʶ=Z]˷mw4Mu]a8@ Lugܾ{k?4챯=uÃ@Bܷ0Wi{۩]Ά 1yd҆bCe٩@vuu5;u %9/q2K˲L.ȃ=uT,놷B?87 {}7EyycE8z}wO]x EQeY6UU5UUʲ\eYEZ&˲vz)gI`{S>u[Fz4-GѢeYˢ(|c A/p@ U1.<Eq} +&y/c8qkW.:Ƹr$ t !op@u#|7M/p@ y]cpꘝo E8 (Nk 938ũ p&>@Z>H΁c>#-k 1 @b@ ^-#$@2&8-#$@WĘ@%hH 1 @b@#$FH 1 @b@#p,kO]E^7 1.D/˲vpWm>z}u]~h=oCB16Ƹu(,˶,KaG.Hemuqx؇~Zܵ]lgǬcߺmcֳϾu۶mc۶q3yޮVZb!˲l뺎u]Ǫ@&\] oLJyu ׾eoǾ<>m~r)r94}9\1e|Ͼ{1v.W?|lyyȮE}dž簭̛mC_T]w낞pvl>~ZuLm۾rok&O Ӈ0UUj 8t,Ck c=,3'!ݻʲ=uyHݡ.˲n6\Dot8W{1#C x@ۿCDz,ocueMe6wO}>ݻw~jUEQo<ϛcwa0C/_>mQW pcySŪ,:FѢijjGѢeY خ`"^} ,noo̫Է"wu]cl<˲\VU5!tzBMyx7o8L-r j[BQ0uc[8zœ.A!]ɲ. !"lt/e 2 ]!-|+]- .s^.%yP'^>%+[.2@| gL7.Te{2p: @b@g9?.-#$@x>8=cӥ 1 $i a>|qy-k'LHcN9xtiH 1 @b@d#$FeYZ #$FH 1 @b@xs;}KY΍gU nt8ȣL:]@qh?\ϰ'؆S}(lns}釼ξogvh-rH`5_ R8|M&v>>rCS:u˲lWc;(eYvxxh<]>lYǾu?fڰ,Ǽmд1k{~mpֹ0Lvkcه!aycCCs.9t7 A;C[bH]ݏݍMrʍ徖.!]Ͻa.ǔ U b n8>ow}k&>W|̀nDŽc7m_>o}ClY6Np81zm]l֓m5C`?Gfs7˲꺎ǫiv\zCֿyɡ9f=cyC~]=?<$?(<̯ecyHawwsP4v;yበ` _ ?4\-9ʗ_~Cɲ9uyeY֭(AOoCݻw_ey{C]emÍK^|_?\__Oã:pڳ5}x:mcxX,;O[6'6fYn{ocJ^9ۿC|,]yMM~wǯkn5﷿~޽7?nnnޮV(z}[yu A._wo~?/?1pF116(UYFxc2eqc_-~%wM!ﺄCa4.p0fYcns'op=ߦn? O?Lt]bx0N\BBeYu]BE.6{o}N. wnKtt ~%dlh`n8Q 4AH\u!p@ i"} 8{O H @b@@꺶 $YN6ccHdEў p*Y c }1) 1 @b^g "-#j6dpڌN8<%$FZLO 1 @b@#$FH$˵PI6>@b@@\ i#Yey ((6G̲oW+N]ҲZbe^Qkt G] !? iEQÿMcl۶~j_x<~治ۜk<1o < 2㪪revVU_o3u]6CmN{7=f΄GZߦBնyvC;=:cyx ]z:NwCܱofSsylVfY֌vXBX.1A6=vcf؝u=vy<7|? -2_Yc[w;vc;dǎ;v')S&rw}UmβN[y@M suGxO]~3`!v$Lv&@`C #$FH(ۮ;ovuu5fmǎ"3#$)9MHd/-py@J˦{i/~<}ݻN]i@v}}=fO R@6G @b@#$FHHk2?m>|d*)S&$Fd,N]3K#$Fd+-p@>eY{@eYq.}2/8u> l׿ڻ@mͲ{ 0 wyoÇxݿ~pssvZEQ*&ج] µPI60 ]cySŪ,˺h4Z4M3_VMQh4ZTU,rY@8sl`y]岪xc2eqc_-~p wM!ﺄCa4.p0fYcn| \Ϸ>j[BQ0uc[8z%&`㠐.dYv]Bq6`{WևNkMo{~p[wW|K `b6]?>y!&N`uEL鉧./KH. +8@c 2x,-#$3a\$FHc_)cE @b@10x)Z#$FH 1 @b@#$FH%dIENDB`seqdiag-0.9.3/examples/edge_type.svg0000644000076600000240000001546412230473410020253 0ustar tkomiyastaff00000000000000 blockdiag { // normal edge A -> B [label = "normal edge"]; // dotted edge B --> C [label = "dotted edge"]; // asynchronus edge A ->> B [label = "asynchronus edge"]; B -->> C [label = "asynchronus dotted edge"]; // return edge B <- C [label = "return edge"]; A <-- B [label = "return dotted edge"]; B <<- C [label = "return asynchronus edge"]; A <<-- B [label = "return asynchronus dotted edge"]; // self referenced edge A -> A [label = "self referenced edge"]; } A B C normal edge dotted edge asynchronus edge asynchronus dotted edge return edge return dotted edge return asynchronus edge return asynchronus dotted ed ge self referenced e dge seqdiag-0.9.3/examples/seqdiagrc0000644000076600000240000000010611650005514017436 0ustar tkomiyastaff00000000000000[seqdiag] fontpath = /usr/share/fonts/truetype/kochi/kochi-mincho.ttf seqdiag-0.9.3/examples/simple.diag0000644000076600000240000000042211650005514017671 0ustar tkomiyastaff00000000000000diagram { browser -> webserver [label = "GET /index.html"]; browser <-- webserver; browser -> webserver [label = "POST /blog/comment"]; webserver -> database [label = "INSERT comment"]; webserver <-- database; browser <-- webserver; } seqdiag-0.9.3/examples/simple.png0000644000076600000240000003036711655736155017605 0ustar tkomiyastaff00000000000000PNG  IHDRćn10IDATx͎XzIRpf]rW^ͪ7]%8Wmc;蛘fYAo} ؞M2ͬ T"R!Esf<*CR(> *|xSJZ@ s"C @ 0@a!C @ 0@aܡg`ҡgxVZmP_ω@a91C g!١  @ 0'1p1!85O9ǩ!ٱ@ 0@aNr cBplscCCc7D 0@aŒb cB܎iFCc@ 0~ jscPȨH&E,ܬ.| 4i{o#"bk, }PȨ_2I/:M1~) W?Iu {J;oܕ KZ&ƴ"ţQD_Rj2CZ'uӺV?H&@~ Z-112X=n,d?/M~vuuZuε (V+S ɤ:R7tz~px/uJikRROcdH\Tj0R?/r]\(u=0XkRJaL ?>I᯼z{m~O&d2 !XZ:A?BC1]-@Am?ç/^8o+68<&SJi `SJ\G" ^ۘCh~Z zfpxWWW/jܰc1@C2aפ+n/mۺ@p QLZI]Rj_,vBp 5|+?$X+`8|Hmoa0s@C2a:cwyO[Uo%0g=PLh+d@+u{4χPLj+%<}x`I 1}a=e}E`dv io-klz. <.5oom{ߺk~X&OMu{eeYp'Jkn!쟲M &q/muӞY&o\s88NtC @ 0@a!C l;:0v?$X/i?vCC2Tˆ\Z뤔JZԭ ROFp?$ZJ)ܡgR7ӽ͌1ֱ+=GLX 1*%{u_|}w?>x=_u=i֧\qb877:|SoZ9הeN6_z+8@CS?/WD9z((ڶJ)emc6dƲe9?<:|/%osw@_W1Fcԃfю(+cRA@WO<En+_"qӵN)x8G}4q#WۣQ?T}` &nERss7g{+ XVm?O"@~2׭G}<FM |&O #Dlӗ+"؋./A_}oB߾Cj+%<I҇$vJHJ?ٕE]Yw1Ϻ?$}]HI&$v\\?t3Ef]4iivF?>!C{=Pmc8N;m|O.Z!C$2fi<-|_OizZ?@ 0@atJ= á! 5@a3p.HEC2_<1'>On: z C?]!qJym܍_mk6Mݟhc7&oCԯ9FV?ǀ{AnoZ+km !ަ5, d}-Zؿ?} y۞ۿx}hn_m[viU?fR2!\;.1b=$DeޯV4~<뇰MA.1^?~c/ >M[=q|NixjFF i㽏Ígw8ZjfCXG1cry+A֏ʇYg[vHuZT0]0)`ャC(`C06vѕcǚ+DzqMJZQ7 A F#sSƌ(LcomRJF "NEYk ٰb_WUu?/// uRJtxumZa k鸾XoTTJEu,ֱ;jCDCwh:G?={a ")M]]m;ZcLZ%hh]/?!\D.ϩ1.Kc(T c40le# е~]7sv- QJ)cLJ[dq(6;}߳c,YhP)x1|;Gp_ySJwb2B^n/cL vcR7A8*?܍(@uxqqq۶eJIcZkmm11ƦB =n#Vc;xc4Ƙ9(b1F۵~ `8v?AANlJkzUU]4MStGG*R-.ϝ/rY5MS 7~toG8 lﻮr\Mm]M 2d3!7|^ N Ae{oB&xޚ㬱)` 6bk6zz =@ܒv`cBC g)kd?#CV@2X?HF3 0@a! /@ 0@\!C @ 0@asƗ @ q.`!Ckh= 7@؀`ܡgk2D Nvvv6?<D#bg~z}Zг;}xy)ip??q՛7o~cʲq:iV{[ ![koM;U==Ƹ>ڶZ_17ûnFcLZA19 zo u]M+Mlu6. czJTY4=ly5o'߿Żw~_/˶ms.6cBWaP0ZH7\|W_}__z>J:FcL\oR,˺|)˲.bصV-ٷ~WUU}裏z^mrrֻh {,J)RʄNUU͋/M%0"N6ͦƘf:6`. _]b2̔R9XU/>L&YQ }= ?[,[G w^*r:^(˗/ߕe1ZcL(r>NϧEY^]t8i@ֵcL[zUU}1:zwMT)%d2Ǫ>xι1Zu\SC0*ZkR]޻_z_m)%]He9+~aίO+8SD0v n1f3J)J)uvv]:Yk\[t cRk~ '`Ժ t|{:11Xkڥ1fiir/-~ƀ`rwn J)eYu ?O)ٔ7f0t~y_P]!cAe#|CSJڨ]R-7.cG0j$TNR:_:[#ޙAA0M&X,욧%al8l@b tӻm|, h=S:!1#@"C.`'1ݸt@aju в@'q{89=ha 1' -!@G91DC Vu \@8<x^sB2_6 0@a!C8^c"xC d X6|a۸}bCXZ΅ 8l@a0vvv6] nmoLv1fcWĦ_<]k=)~6|O<} |p x|Akʲ(TQQ)Y$\Q: cbpƘ!Sbib'J]:ֶSMkܼ1y.߿]󇯱Gij !km|/07`SJf[?f4n{M=~7}3lLtAio- 4ۂC{]H\Cir޾21"Ac#`c1P?c }ÆOn+@{}!wn5Ow;aUIXgF r4EQ~X!)[vi vYӚvؿ]_16]6 6ͦۦժm-l 7۞n\.KHw״{cpLfS0oe]h[XOq+8 ll cMhbS1]ƌbLயAPpF#@NYk`?)uI/n@!1!b7oo߰v׿gꇿ~bR*jWTT H8u@wCW-mNmw Z렺`4ꔒ5~eiKk44J)C r/vk\[x9RƘe 8u@'+wc.f{eYrhcSJyL|`Tݿy_JwZߝd2RݾƘ<n? vj`rm˔2ƴZ[cjcM)Niuc;xc4Ƙ9(b1F۵ Nh w ֺϫh !hףI#{**r\mHio۶QJ)k30RΐRZ{`=N)1x`rsE\̭.z1dݷfc\1bAGEq9U۶59 >u\j]?|m,i\ MӘ7fhƘ'[ !p֟ymMk [;]G.~ .~`zl!k:Y1@m<}/d" mkcy~ \Od<-Hؓᯀ-Dֵɇԅ]c5k<@A{f|VH̷׍w >5omz]_{8Ș @8AGFSG]fS0]G v} "09uSඐG? #R |)%5Lbk^"n@`7o?<Ng{F-><<v tZ48xf@͛71eYMӬz!tk)t5ӅM1nm`L?qo|/@ ޾}ۻB`]fSJ4)uMwzJTY4=ly5o'߿Żw~_/˶ms.6cBWaPF__}~}(1ZsQJ,몪,˺(cZIZ`~_UUᣏ>zwyɭʩkZ1&Xk(+NJ)Bpv:^VU5/{6֚8 l6ctz^m6 uQd2SJs\`UU/^0LfEQ,0ƁX,@MxUt:PJ/_+rcƘP|:OӋ,/W #յcL[zUU}1i*d{5LfUUXU94ƴZ8M@FBkRJy {RJ)eml۶H)uB,YY kmUp~}ZOJ]pk1KQJ)upmB>Z8jܢk[cZK`Zr7p1__?-hs4cLc]ZkƘ1ݿ0(1f%ReYL1kcZ@`z ZL)J)圛+.u 4BR*hcJI+1Vһz #;3H?&2Ƅ5OK  tӻm|,ƉP=S:'9 \.C0'n\<-住@ 00@X3 l@Ęi9` 6LRJu͎'{;;;z}O?=iSw}Y!N?zGJ:u\O{Gx6@l͛,o $nf5&{kqa5Z{kzT)3}c[mۭ5z+~3km4Duc#boX׵Ժ4iJ]m:P)1=y*,lw6zwyɭʩkZ1&Xk(+NJ)Bpv:^VU5/{6֚8Y@l6ctz^m6 uQd29>rε9VUuŋdV{_C ce#{ݿʲN1FoeY.bʲOtzQs0Nuv:EUUbNksu4UJjj2̪sniiցg QZR|^nޥRJW?o۶-RJFk8/rVZ[wp_Vp*uX. K]pk1KQJ)uPJB>Z8jܢk[cZK`8i@ֵn঻/]h ƘZ.1KcLi0@u+`PJ)c̪KX)ʲZ8jܢk[cZK`pt-tt:}c9c1.Kc_Z8m0(1f%ReYL1kcZxJ'jD@!z ZL)J)圛+[[ o\=' PBR*hcJI+1VһztRJcš%0@aj |;΅ ɨ8Rz pZa<t] @ 0 blockdiag diagram { browser -> webserver [label = "GET /index.html"]; browser <-- webserver; browser -> webserver [label = "POST /blog/comment"]; webserver -> database [label = "INSERT comment"]; webserver <-- database; browser <-- webserver; } browser webserver database GET /index.html POST /blog/comment INSERT comment seqdiag-0.9.3/LICENSE0000644000076600000240000002613611650005514014753 0ustar tkomiyastaff00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. seqdiag-0.9.3/MANIFEST.in0000644000076600000240000000042412352166267015511 0ustar tkomiyastaff00000000000000include buildout.cfg include bootstrap.py include MANIFEST.in include README.rst include LICENSE include seqdiag.1 include tox.ini recursive-include examples seqdiagrc *.diag *.png *.svg recursive-include src *.py *.diag *.gif exclude .drone.io.sh exclude examples/update.sh seqdiag-0.9.3/PKG-INFO0000644000076600000240000002246712355212722015052 0ustar tkomiyastaff00000000000000Metadata-Version: 1.1 Name: seqdiag Version: 0.9.3 Summary: seqdiag generates sequence-diagram image from text Home-page: http://blockdiag.com/ Author: Takeshi Komiya Author-email: i.tkomiya at gmail.com License: Apache License 2.0 Download-URL: http://pypi.python.org/pypi/seqdiag Description: `seqdiag` generate sequence-diagram image file from spec-text file. .. image:: https://drone.io/bitbucket.org/blockdiag/seqdiag/status.png :target: https://drone.io/bitbucket.org/blockdiag/seqdiag :alt: drone.io CI build status .. image:: https://pypip.in/v/seqdiag/badge.png :target: https://pypi.python.org/pypi/seqdiag/ :alt: Latest PyPI version .. image:: https://pypip.in/d/seqdiag/badge.png :target: https://pypi.python.org/pypi/seqdiag/ :alt: Number of PyPI downloads Features ======== * Generate sequence-diagram from dot like text (basic feature). * Multilingualization for node-label (utf-8 only). You can get some examples and generated images on `blockdiag.com`_ . Setup ===== Use easy_install or pip:: $ sudo easy_install seqdiag Or $ sudo pip seqdiag Copy and modify ini file. example:: $ cp /blockdiag/examples/simple.diag . $ vi simple.diag Please refer to `spec-text setting sample`_ section for the format of the `simpla.diag` configuration file. spec-text setting sample ======================== Few examples are available. You can get more examples at `blockdiag.com `_ . simple.diag ------------ simple.diag is simply define nodes and transitions by dot-like text format:: diagram { browser -> webserver [label = "GET /index.html"]; browser <-- webserver; browser -> webserver [label = "POST /blog/comment"]; webserver -> database [label = "INSERT comment"]; webserver <-- database; browser <-- webserver; } Usage ===== Execute seqdiag command:: $ seqdiag simple.diag $ ls simple.png simple.png Requirements ============ * Python 2.6, 2.7, 3.2, 3.3, 3.4 * Pillow 2.2.1 or later * funcparserlib 0.3.6 or later * reportlab (optional) * wand and imagemagick (optional) * setuptools License ======= Apache License 2.0 History ======= 0.9.3 (2014-07-03) ------------------ * Fix bugs 0.9.2 (2014-07-02) ------------------ * Change interface of docutils node (for sphinxcontrib module) 0.9.1 (2014-06-23) ------------------ * Add options to blockdiag directive (docutils extension) - :width: - :height: - :scale: - :align: - :name: - :class: - :figwidth: - :figclass: 0.9.0 (2013-10-05) ------------------ * Support python 3.2 and 3.3 (thanks to @masayuko) * Drop supports for python 2.4 and 2.5 * Replace dependency: PIL -> Pillow 0.8.2 (2013-02-09) ------------------ * Fix bugs 0.8.1 (2012-11-12) ------------------ * Add altblock feature (experimental) * Fix bugs 0.8.0 (2012-10-22) ------------------ * Optimize algorithm for rendering shadow * Add options to docutils directive * Fix bugs 0.7.5 (2012-09-29) ------------------ * Fix bugs 0.7.4 (2012-09-20) ------------------ * Support blockdiag-1.1.7 interface * Fix bugs 0.7.3 (2012-03-16) ------------------ * Allow to insert separators in subedge-group * Fix bugs 0.7.2 (2011-12-12) ------------------ * Fix bugs 0.7.1 (2011-11-30) ------------------ * Fix bugs 0.7.0 (2011-11-19) ------------------ * Add fontfamily attribute for switching fontface * Fix bugs 0.6.3 (2011-11-06) ------------------ * Add docutils extention * Fix bugs 0.6.2 (2011-11-01) ------------------ * Add class feature (experimental) 0.6.1 (2011-11-01) ------------------ * Follow blockdiag-0.9.7 interface 0.6.0 (2011-10-28) ------------------ * Add edge attributes: note, rightnote, leftnote, notecolor * Add diagram atteribute: default_note_color 0.5.2 (2011-10-27) ------------------ * Implement auto edge height adjusting * Fix bugs 0.5.1 (2011-10-24) ------------------ * Fix bugs 0.5.0 (2011-10-21) ------------------ * Add diagram attributes: activation, autonumber * Add edge attribute: failed * Add separator syntax 0.4.3 (2011-10-19) ------------------ * Follow blockdiag-0.9.5 interface 0.4.2 (2011-10-11) ------------------ * Fix bugs 0.4.1 (2011-09-30) ------------------ * Add diagram attribute: default_text_color * Add node attribte: textcolor * Fix bugs 0.4.0 (2011-09-26) ------------------ * Add diagram attributes: default_node_color, default_group_color and default_line_color 0.3.8 (2011-08-02) ------------------ * Allow dot characters in node_id * Fix bugs 0.3.7 (2011-07-05) ------------------ * Fix bugs 0.3.6 (2011-07-03) ------------------ * Support input from stdin 0.3.5 (2011-06-02) ------------------ * Fix bugs 0.3.4 (2011-05-18) ------------------ * Fix bugs 0.3.3 (2011-05-16) ------------------ * Add --version option * Add sphinxhelper module 0.3.2 (2011-05-14) ------------------ * Render group label * Support blockdiag 0.8.1 core interface 0.3.1 (2011-04-22) ------------------ * Render group label * Fix sphinxcontrib_seqdiag does not work with seqdiag 0.3.0 0.3.0 (2011-04-22) ------------------ * Add group syntax 0.2.7 (2011-04-15) ------------------ * Adjust start coordinates of edges 0.2.6 (2011-04-14) ------------------ * Fix bugs * Allow unquoted utf8 characters 0.2.5 (2011-03-26) ------------------ * Fix seqdiag could not run under blockdiag 0.7.6 0.2.4 (2011-03-20) ------------------ * Fix bugs 0.2.3 (2011-03-09) ------------------ * Fix bugs 0.2.2 (2011-03-07) ------------------ * Fix could not run under python 2.4 * Support edge colors 0.2.1 (2011-02-28) ------------------ * Add default_shape attribute to diagram 0.2.0 (2011-02-27) ------------------ * Add metrix parameters for edge label: edge_height, edge_length * Fix bugs 0.1.7 (2011-01-21) ------------------ * Fix TeX exporting in Sphinx extension 0.1.6 (2011-01-15) ------------------ * Support blockdiag-0.6.3 * Fix bugs 0.1.5 (2011-01-15) ------------------ * Draw activity on lifelines * Support both direction edge with '=>' operator 0.1.4 (2011-01-13) ------------------ * Change synxtax around edges 0.1.3 (2011-01-12) ------------------ * Support diagonal edge * Fix bugs 0.1.2 (2011-01-11) ------------------ * Support nested edges * Add edge attributes; return, dir * Add sphinx extention module(sphinxcontrib_seqdiag) * Fix bugs 0.1.1 (2011-01-11) ------------------ * Fix bugs about layouting 0.1.0 (2011-01-08) ------------------ * first release Keywords: diagram,generator Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Documentation Classifier: Topic :: Text Processing :: Markup seqdiag-0.9.3/README.rst0000644000076600000240000001412012355211416015426 0ustar tkomiyastaff00000000000000`seqdiag` generate sequence-diagram image file from spec-text file. .. image:: https://drone.io/bitbucket.org/blockdiag/seqdiag/status.png :target: https://drone.io/bitbucket.org/blockdiag/seqdiag :alt: drone.io CI build status .. image:: https://pypip.in/v/seqdiag/badge.png :target: https://pypi.python.org/pypi/seqdiag/ :alt: Latest PyPI version .. image:: https://pypip.in/d/seqdiag/badge.png :target: https://pypi.python.org/pypi/seqdiag/ :alt: Number of PyPI downloads Features ======== * Generate sequence-diagram from dot like text (basic feature). * Multilingualization for node-label (utf-8 only). You can get some examples and generated images on `blockdiag.com`_ . Setup ===== Use easy_install or pip:: $ sudo easy_install seqdiag Or $ sudo pip seqdiag Copy and modify ini file. example:: $ cp /blockdiag/examples/simple.diag . $ vi simple.diag Please refer to `spec-text setting sample`_ section for the format of the `simpla.diag` configuration file. spec-text setting sample ======================== Few examples are available. You can get more examples at `blockdiag.com `_ . simple.diag ------------ simple.diag is simply define nodes and transitions by dot-like text format:: diagram { browser -> webserver [label = "GET /index.html"]; browser <-- webserver; browser -> webserver [label = "POST /blog/comment"]; webserver -> database [label = "INSERT comment"]; webserver <-- database; browser <-- webserver; } Usage ===== Execute seqdiag command:: $ seqdiag simple.diag $ ls simple.png simple.png Requirements ============ * Python 2.6, 2.7, 3.2, 3.3, 3.4 * Pillow 2.2.1 or later * funcparserlib 0.3.6 or later * reportlab (optional) * wand and imagemagick (optional) * setuptools License ======= Apache License 2.0 History ======= 0.9.3 (2014-07-03) ------------------ * Fix bugs 0.9.2 (2014-07-02) ------------------ * Change interface of docutils node (for sphinxcontrib module) 0.9.1 (2014-06-23) ------------------ * Add options to blockdiag directive (docutils extension) - :width: - :height: - :scale: - :align: - :name: - :class: - :figwidth: - :figclass: 0.9.0 (2013-10-05) ------------------ * Support python 3.2 and 3.3 (thanks to @masayuko) * Drop supports for python 2.4 and 2.5 * Replace dependency: PIL -> Pillow 0.8.2 (2013-02-09) ------------------ * Fix bugs 0.8.1 (2012-11-12) ------------------ * Add altblock feature (experimental) * Fix bugs 0.8.0 (2012-10-22) ------------------ * Optimize algorithm for rendering shadow * Add options to docutils directive * Fix bugs 0.7.5 (2012-09-29) ------------------ * Fix bugs 0.7.4 (2012-09-20) ------------------ * Support blockdiag-1.1.7 interface * Fix bugs 0.7.3 (2012-03-16) ------------------ * Allow to insert separators in subedge-group * Fix bugs 0.7.2 (2011-12-12) ------------------ * Fix bugs 0.7.1 (2011-11-30) ------------------ * Fix bugs 0.7.0 (2011-11-19) ------------------ * Add fontfamily attribute for switching fontface * Fix bugs 0.6.3 (2011-11-06) ------------------ * Add docutils extention * Fix bugs 0.6.2 (2011-11-01) ------------------ * Add class feature (experimental) 0.6.1 (2011-11-01) ------------------ * Follow blockdiag-0.9.7 interface 0.6.0 (2011-10-28) ------------------ * Add edge attributes: note, rightnote, leftnote, notecolor * Add diagram atteribute: default_note_color 0.5.2 (2011-10-27) ------------------ * Implement auto edge height adjusting * Fix bugs 0.5.1 (2011-10-24) ------------------ * Fix bugs 0.5.0 (2011-10-21) ------------------ * Add diagram attributes: activation, autonumber * Add edge attribute: failed * Add separator syntax 0.4.3 (2011-10-19) ------------------ * Follow blockdiag-0.9.5 interface 0.4.2 (2011-10-11) ------------------ * Fix bugs 0.4.1 (2011-09-30) ------------------ * Add diagram attribute: default_text_color * Add node attribte: textcolor * Fix bugs 0.4.0 (2011-09-26) ------------------ * Add diagram attributes: default_node_color, default_group_color and default_line_color 0.3.8 (2011-08-02) ------------------ * Allow dot characters in node_id * Fix bugs 0.3.7 (2011-07-05) ------------------ * Fix bugs 0.3.6 (2011-07-03) ------------------ * Support input from stdin 0.3.5 (2011-06-02) ------------------ * Fix bugs 0.3.4 (2011-05-18) ------------------ * Fix bugs 0.3.3 (2011-05-16) ------------------ * Add --version option * Add sphinxhelper module 0.3.2 (2011-05-14) ------------------ * Render group label * Support blockdiag 0.8.1 core interface 0.3.1 (2011-04-22) ------------------ * Render group label * Fix sphinxcontrib_seqdiag does not work with seqdiag 0.3.0 0.3.0 (2011-04-22) ------------------ * Add group syntax 0.2.7 (2011-04-15) ------------------ * Adjust start coordinates of edges 0.2.6 (2011-04-14) ------------------ * Fix bugs * Allow unquoted utf8 characters 0.2.5 (2011-03-26) ------------------ * Fix seqdiag could not run under blockdiag 0.7.6 0.2.4 (2011-03-20) ------------------ * Fix bugs 0.2.3 (2011-03-09) ------------------ * Fix bugs 0.2.2 (2011-03-07) ------------------ * Fix could not run under python 2.4 * Support edge colors 0.2.1 (2011-02-28) ------------------ * Add default_shape attribute to diagram 0.2.0 (2011-02-27) ------------------ * Add metrix parameters for edge label: edge_height, edge_length * Fix bugs 0.1.7 (2011-01-21) ------------------ * Fix TeX exporting in Sphinx extension 0.1.6 (2011-01-15) ------------------ * Support blockdiag-0.6.3 * Fix bugs 0.1.5 (2011-01-15) ------------------ * Draw activity on lifelines * Support both direction edge with '=>' operator 0.1.4 (2011-01-13) ------------------ * Change synxtax around edges 0.1.3 (2011-01-12) ------------------ * Support diagonal edge * Fix bugs 0.1.2 (2011-01-11) ------------------ * Support nested edges * Add edge attributes; return, dir * Add sphinx extention module(sphinxcontrib_seqdiag) * Fix bugs 0.1.1 (2011-01-11) ------------------ * Fix bugs about layouting 0.1.0 (2011-01-08) ------------------ * first release seqdiag-0.9.3/seqdiag.10000644000076600000240000000376511650005514015450 0ustar tkomiyastaff00000000000000.\" Hey, EMACS: -*- nroff -*- .\" First parameter, NAME, should be all caps .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" other parameters are allowed: see man(7), man(1) .TH SEQDIAG 1 "May 21, 2011" .\" Please adjust this date whenever revising the manpage. .\" .\" Some roff macros, for reference: .\" .nh disable hyphenation .\" .hy enable hyphenation .\" .ad l left justify .\" .ad b justify to both left and right margins .\" .nf disable filling .\" .fi enable filling .\" .br insert line break .\" .sp insert n+1 empty lines .\" for manpage-specific macros, see man(7) .SH NAME seqdiag \- generate sequence-diagram image file from spec-text file. .SH SYNOPSIS .B seqdiag .RI [ options ] " file" .br .SH DESCRIPTION This manual page documents briefly the .B seqdiag commands. .PP .\" TeX users may be more comfortable with the \fB\fP and .\" \fI\fP escape sequences to invode bold face and italics, .\" respectively. \fBseqdiag\fP is generate sequence-diagram image file from spec-text file. .SH OPTIONS These programs follow the usual GNU command line syntax, with long options starting with two dashes (`-'). A summary of options is included below. For a complete description, see the Info files. .TP .B \-\-version show program's version number and exit .TP .B \-h, \-\-help show this help message and exit .TP .B \-a, \-\-antialias Pass diagram image to anti-alias filter .TP .B \-c FILE, \-\-config=FILE read configurations from FILE .TP .B \-o FILE write diagram to FILE .TP .B \-f FONT, \-\-font=FONT use FONT to draw diagram .TP .B \-T TYPE Output diagram as TYPE format .SH SEE ALSO .BR .br The programs are documented fully by .br .IR http://tk0miya.bitbucket.org/seqdiag/build/html/index.html .SH AUTHOR seqdiag was written by Takeshi Komiya .PP This manual page was written by Kouhei Maeda , for the Debian project (and may be used by others). seqdiag-0.9.3/setup.cfg0000644000076600000240000000041112355212722015557 0ustar tkomiyastaff00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [build] build-base = _build [sdist] formats = gztar [wheel] universal = 1 [aliases] release = check -r -s register sdist bdist_wheel upload [check] strict = 1 restructuredtext = 1 [flake8] ignore = _ seqdiag-0.9.3/setup.py0000644000076600000240000000325112354723131015455 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- import sys from setuptools import setup, find_packages sys.path.insert(0, 'src') import seqdiag classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: System Administrators", "License :: OSI Approved :: Apache Software License", "Programming Language :: Python", "Topic :: Software Development", "Topic :: Software Development :: Documentation", "Topic :: Text Processing :: Markup", ] test_requires = ['nose', 'pep8>=1.3', 'reportlab', 'docutils'] # only for Python2.6 if sys.version_info > (2, 6) and sys.version_info < (2, 7): test_requires.append('unittest2') setup( name='seqdiag', version=seqdiag.__version__, description='seqdiag generates sequence-diagram image from text', long_description=open("README.rst").read(), classifiers=classifiers, keywords=['diagram', 'generator'], author='Takeshi Komiya', author_email='i.tkomiya at gmail.com', url='http://blockdiag.com/', download_url='http://pypi.python.org/pypi/seqdiag', license='Apache License 2.0', py_modules=['seqdiag_sphinxhelper'], packages=find_packages('src'), package_dir={'': 'src'}, package_data={'': ['buildout.cfg']}, include_package_data=True, install_requires=[ 'setuptools', 'blockdiag>=1.4.1', # -*- Extra requirements: -*- ], extras_require=dict( testing=test_requires, rst=[ 'docutils', ], ), test_suite='nose.collector', tests_require=test_requires, entry_points=""" [console_scripts] seqdiag = seqdiag.command:main """, ) seqdiag-0.9.3/src/0000755000076600000240000000000012355212722014531 5ustar tkomiyastaff00000000000000seqdiag-0.9.3/src/seqdiag/0000755000076600000240000000000012355212722016146 5ustar tkomiyastaff00000000000000seqdiag-0.9.3/src/seqdiag/__init__.py0000644000076600000240000000117312355211313020254 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __version__ = '0.9.3' seqdiag-0.9.3/src/seqdiag/builder.py0000644000076600000240000002014312346552765020164 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from seqdiag import parser from seqdiag.elements import (Diagram, DiagramNode, NodeGroup, DiagramEdge, EdgeSeparator, AltBlock) from blockdiag.utils import unquote, XY from blockdiag.utils.compat import u class DiagramTreeBuilder(object): def build(self, tree): self.diagram = Diagram() self.diagram = self.instantiate(self.diagram, None, tree) self.update_node_order() self.update_edge_order() self.update_altblock_ylevel() self.diagram.colwidth = len(self.diagram.nodes) self.diagram.colheight = len(self.diagram.edges) + 1 for sep in self.diagram.separators: self.diagram.edges.remove(sep) if self.diagram.activation != 'none': self.create_activities() if self.diagram.autonumber: self.update_label_numbered() return self.diagram def update_edge_order(self): for i, edge in enumerate(self.diagram.edges): edge.order = i height = len(self.diagram.edges) + 1 for group in self.diagram.groups: group.colheight = height def update_altblock_ylevel(self): altblocks = self.diagram.altblocks for i in range(len(self.diagram.edges) + 1): blocks = [b for b in altblocks if b.edges[0].order == i] for j, altblock in enumerate(reversed(blocks)): altblock.ylevel_top = j + 1 blocks = [b for b in altblocks if b.edges[-1].order == i] for j, altblock in enumerate(reversed(blocks)): altblock.ylevel_bottom = j + 1 def update_label_numbered(self): for i, edge in enumerate(self.diagram.edges): edge.label = u("%d. %s") % (i + 1, edge.label or "") def create_activities(self): if len(self.diagram.edges) == 0: return first_node = self.diagram.edges[0].node1 active_nodes = {first_node: 1} for node in self.diagram.nodes: if node.activated: active_nodes[node] = 1 edge_count = len(self.diagram.edges) + len(self.diagram.separators) for i in range(edge_count): match = [e for e in self.diagram.edges if e.order == i] if match: edge = match[0] if edge.node1 == edge.node2: pass elif edge.activate is False: pass elif edge.dir == 'forward': if edge.node2 in active_nodes: active_nodes[edge.node2] += 1 else: active_nodes[edge.node2] = 1 elif edge.dir == 'back': if edge.node2 in active_nodes: active_nodes[edge.node2] -= 1 else: active_nodes[edge.node2] = 0 for node in active_nodes: if active_nodes[node] > 0: for index in range(active_nodes[node]): node.activate(i, index) for node in self.diagram.nodes: node.deactivate() def update_node_order(self): x = 0 uniq = [] for node in self.diagram.nodes: if node not in uniq: node.xy = XY(x, 0) uniq.append(node) x += 1 if node.group: for subnode in node.group.nodes: if subnode not in uniq: subnode.xy = XY(x, 0) uniq.append(subnode) x += 1 for group in self.diagram.groups: x = min(node.xy.x for node in group.nodes) group.xy = XY(x, 0) group.colwidth = len(group.nodes) def append_node(self, node, group): if node not in self.diagram.nodes: self.diagram.nodes.append(node) if isinstance(group, NodeGroup) and node not in group.nodes: if node.group: msg = "DiagramNode could not belong to two groups" raise RuntimeError(msg) group.nodes.append(node) node.group = group def instantiate(self, group, block, tree): for stmt in tree.stmts: if isinstance(stmt, parser.Node): node = DiagramNode.get(stmt.id) node.set_attributes(stmt.attrs) self.append_node(node, group) elif isinstance(stmt, parser.Edge): self.instantiate_edge(group, block, stmt) elif isinstance(stmt, parser.Group): node = NodeGroup.get(None) self.instantiate(node, block, stmt) self.diagram.groups.append(node) elif isinstance(stmt, parser.Attr): if block: block.set_attribute(stmt) else: group.set_attribute(stmt) elif isinstance(stmt, parser.Separator): sep = EdgeSeparator(stmt.type, unquote(stmt.value)) sep.group = group self.diagram.separators.append(sep) group.edges.append(sep) elif isinstance(stmt, parser.Fragment): subblock = AltBlock(stmt.type, stmt.id) if block: subblock.xlevel = block.xlevel + 1 self.diagram.altblocks.append(subblock) self.instantiate(group, subblock, stmt) if block: for edge in subblock.edges: block.edges.append(edge) elif isinstance(stmt, parser.Extension): if stmt.type == 'class': name = unquote(stmt.name) Diagram.classes[name] = stmt elif stmt.type == 'plugin': self.diagram.set_plugin(stmt.name, stmt.attrs) return group def instantiate_edge(self, group, block, stmt): from_node = DiagramNode.get(stmt.from_node) self.append_node(from_node, group) to_node = DiagramNode.get(stmt.to_node) self.append_node(to_node, group) edge = DiagramEdge(from_node, to_node) edge.set_dir(stmt.edge_type) edge.set_attributes(stmt.attrs) if edge.dir in ('forward', 'both'): forward = edge.duplicate() forward.dir = 'forward' group.edges.append(forward) if block: block.edges.append(forward) if stmt.followers: followers = list(stmt.followers) next_edge_type, next_to_node = followers.pop(0) nested = parser.Edge(stmt.to_node, next_edge_type, next_to_node, followers, stmt.attrs, stmt.edge_block) self.instantiate_edge(group, block, nested) elif stmt.edge_block: self.instantiate(group, block, stmt.edge_block) if edge.dir in ('back', 'both') and edge.node1 != edge.node2: reverse = edge.duplicate() reverse.dir = 'back' if edge.dir == 'both': reverse.style = 'dashed' reverse.label = edge.return_label reverse.leftnote = None reverse.rightnote = None group.edges.append(reverse) if block: block.edges.append(reverse) class ScreenNodeBuilder(object): @classmethod def build(cls, tree): DiagramNode.clear() DiagramEdge.clear() NodeGroup.clear() return DiagramTreeBuilder().build(tree) seqdiag-0.9.3/src/seqdiag/command.py0000644000076600000240000000155312355207776020157 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import sys import seqdiag import seqdiag.builder import seqdiag.drawer import seqdiag.parser from blockdiag.utils.bootstrap import Application class SeqdiagApp(Application): module = seqdiag def main(args=sys.argv[1:]): return SeqdiagApp().run(args) seqdiag-0.9.3/src/seqdiag/drawer.py0000644000076600000240000001477212217202626020016 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import blockdiag.drawer from seqdiag.metrics import DiagramMetrics from blockdiag.utils import XY class DiagramDraw(blockdiag.drawer.DiagramDraw): def create_metrics(self, *args, **kwargs): return DiagramMetrics(*args, **kwargs) def _draw_background(self): for node in self.nodes: node.activities.sort(key=lambda x: x['level']) if self.diagram.shadow_style != 'none': for node in self.nodes: for activity in node.activities: self.node_activity_shadow(node, activity) if self.diagram.shadow_style != 'none': for edge in self.edges: self.edge_shadow(edge) super(DiagramDraw, self)._draw_background() def _draw_elements(self, **kwargs): for block in self.diagram.altblocks: self.altblock(block) for node in self.nodes: self.lifelines(node) super(DiagramDraw, self)._draw_elements(**kwargs) for sep in self.diagram.separators: self.separator(sep) for group in self.diagram.groups: self.group_label(group, **kwargs) def node_activity_shadow(self, node, activity): box = self.metrics.activity_shadow(node, activity) if self.diagram.shadow_style == 'solid': self.drawer.rectangle(box, fill=self.shadow) else: self.drawer.rectangle(box, fill=self.shadow, filter='transp-blur') def node_activity(self, node, activity): box = self.metrics.activity_box(node, activity) self.drawer.rectangle(box, width=1, outline=self.diagram.linecolor, fill='moccasin') def lifelines(self, node): for line, style in self.metrics.lifeline(node): self.drawer.line(line, fill=self.diagram.linecolor, style=style) for activity in node.activities: self.node_activity(node, activity) def edge_shadow(self, edge): m = self.metrics dx, dy = m.shadow_offset if edge.leftnote: polygon = m.edge(edge).leftnoteshape shadow = [XY(pt.x + dx, pt.y + dy) for pt in polygon] if self.diagram.shadow_style == 'solid': self.drawer.polygon(shadow, fill=self.shadow, outline=self.shadow) else: self.drawer.polygon(shadow, fill=self.shadow, outline=self.shadow, filter='transp-blur') if edge.rightnote: polygon = m.edge(edge).rightnoteshape shadow = [XY(pt.x + dx, pt.y + dy) for pt in polygon] if self.diagram.shadow_style == 'solid': self.drawer.polygon(shadow, fill=self.shadow, outline=self.shadow) else: self.drawer.polygon(shadow, fill=self.shadow, outline=self.shadow, filter='transp-blur') def edge(self, edge): # render shaft of edges m = self.metrics.edge(edge) shaft = m.shaft self.drawer.line(shaft, fill=edge.color, style=edge.style) # render head of edges head = m.head if edge.async: self.drawer.line((head[0], head[1]), fill=edge.color) self.drawer.line((head[1], head[2]), fill=edge.color) else: self.drawer.polygon(head, outline=edge.color, fill=edge.color) if edge.failed: for line in m.failedmark: self.drawer.line(line, fill=edge.color) if edge.leftnote: polygon = m.leftnoteshape self.drawer.polygon(polygon, fill=edge.notecolor, outline=self.fill) folded = [polygon[1], XY(polygon[1].x, polygon[2].y), polygon[2]] self.drawer.line(folded, fill=self.fill) self.drawer.textarea(m.leftnotebox, edge.leftnote, self.metrics.font_for(edge), fill=edge.color, halign='left') if edge.rightnote: polygon = m.rightnoteshape self.drawer.polygon(polygon, fill=edge.notecolor, outline=self.fill) folded = [polygon[1], XY(polygon[1].x, polygon[2].y), polygon[2]] self.drawer.line(folded, fill=self.fill) self.drawer.textarea(m.rightnotebox, edge.rightnote, self.metrics.font_for(edge), fill=edge.color, halign='left') def edge_label(self, edge): m = self.metrics.edge(edge) if edge.label: if edge.direction in ('right', 'self'): halign = 'left' else: halign = 'right' self.drawer.textarea(m.textbox, edge.label, self.metrics.font_for(edge), fill=edge.color, halign=halign) def separator(self, sep): m = self.metrics.separator(sep) for line in m.lines: self.drawer.line(line, fill=self.fill, style=sep.style) if sep.type == 'delay': self.drawer.rectangle(m.labelbox, fill='white', outline='white') elif sep.type == 'divider': self.drawer.rectangle(m.labelbox, fill=sep.color, outline=sep.linecolor) self.drawer.textarea(m.labelbox, sep.label, self.metrics.font_for(sep), fill=sep.textcolor) def altblock(self, block): m = self.metrics.cell(block) self.drawer.rectangle(m, outline=block.linecolor) box = m.textbox line = [XY(box.x1, box.y2), XY(box.x2, box.y2), XY(box.x2 + self.metrics.cellsize * 2, box.y1)] self.drawer.line(line, fill=block.linecolor) self.drawer.textarea(box, block.type, fill=block.textcolor, font=self.metrics.font_for(block)) seqdiag-0.9.3/src/seqdiag/elements.py0000644000076600000240000001751412352027065020345 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import re import blockdiag.elements from blockdiag.utils import images, Size, XY from blockdiag.utils.logging import warning class NodeGroup(blockdiag.elements.NodeGroup): pass class DiagramNode(blockdiag.elements.DiagramNode): def __init__(self, _id): super(DiagramNode, self).__init__(_id) self.activated = False self.activity = [] self.activities = [] def set_activated(self, value): self.activated = True def activate(self, height, index): if len(self.activity) <= index: self.activity.insert(index, []) if (len(self.activity[index]) > 0 and (self.activity[index][-1] != height - 1)): self.deactivate(index) self.activity[index].append(height) def deactivate(self, index=None): if index is None: for i in range(len(self.activity)): self.deactivate(i) return if self.activity[index]: attr = {'lifetime': self.activity[index], 'level': index} self.activities.append(attr) self.activity[index] = [] class EdgeSeparator(blockdiag.elements.Base): basecolor = (208, 208, 208) linecolor = (0, 0, 0) @classmethod def clear(cls): super(EdgeSeparator, cls).clear() cls.basecolor = (208, 208, 208) cls.linecolor = (0, 0, 0) def __init__(self, _type, label): super(EdgeSeparator, self).__init__() self.label = label self.group = None self.style = None self.color = self.basecolor self.order = 0 if _type == '===': self.type = 'divider' elif _type == '...': self.type = 'delay' class DiagramEdge(blockdiag.elements.DiagramEdge): notecolor = (255, 182, 193) # LightPink @classmethod def clear(cls): super(DiagramEdge, cls).clear() cls.notecolor = (255, 182, 193) @classmethod def set_default_note_color(cls, color): color = images.color_to_rgb(color) cls.notecolor = color def __init__(self, node1, node2): super(DiagramEdge, self).__init__(node1, node2) self.leftnote = None self.leftnotesize = Size(0, 0) self.rightnote = None self.rightnotesize = Size(0, 0) self.textwidth = 0 self.textheight = 0 self.order = 0 self.activate = True self.async = False self.diagonal = False self.failed = False self.return_label = '' @property def left_node(self): if self.node1.xy.x <= self.node2.xy.x: return self.node1 else: return self.node2 @property def right_node(self): if self.node1.xy.x > self.node2.xy.x: return self.node1 else: return self.node2 @property def direction(self): if self.node1.xy.x == self.node2.xy.x: direction = 'self' elif self.node1.xy.x < self.node2.xy.x: # n1 .. n2 if self.dir == 'forward': direction = 'right' else: direction = 'left' else: # n2 .. n1 if self.dir == 'forward': direction = 'left' else: direction = 'right' return direction def set_note(self, value): self.rightnote = value def set_diagonal(self, value): self.diagonal = True def set_async(self, value): self.dir = 'forward' def set_return(self, value): self.return_label = value def set_failed(self, value): self.failed = True self.activate = False def set_activate(self, value): self.activate = True def set_noactivate(self, value): self.activate = False def set_dir(self, value): _dir = value.lower() if _dir in ('back', 'both', 'forward'): self.dir = _dir elif _dir == '=>': self.dir = 'both' elif _dir in ('->', '->>', '-->', '-->>'): self.dir = 'forward' if re.search('--', _dir): self.style = 'dashed' else: self.style = None if re.search('>>', _dir): self.async = True else: self.async = False elif _dir in ('<-', '<<-', '<--', '<<--'): self.dir = 'back' if re.search('--', _dir): self.style = 'dashed' else: self.style = None if re.search('<<', _dir): self.async = True else: self.async = False else: warning("unknown edge dir: %s", _dir) class AltBlock(blockdiag.elements.Base): basecolor = (0, 0, 0) linecolor = (0, 0, 0) width = None height = None @classmethod def clear(cls): super(EdgeSeparator, cls).clear() cls.basecolor = (0, 0, 0) cls.linecolor = (0, 0, 0) @classmethod def set_default_linecolor(cls, color): color = images.color_to_rgb(color) cls.linecolor = color def __init__(self, _type, _id): self.type = _type self.id = _id self.xlevel = 1 self.ylevel_top = 1 self.ylevel_bottom = 1 self.edges = [] self.color = self.basecolor @property def xy(self): if len(self.edges) == 0: return XY(0, 0) else: x = min(e.left_node.xy.x for e in self.edges) y = min(e.order for e in self.edges) + 1 return XY(x, y) @property def colwidth(self): if len(self.edges) == 0: return 1 else: x2 = max(e.right_node.xy.x for e in self.edges) return x2 - self.xy.x + 1 @property def colheight(self): if len(self.edges) == 0: return 1 else: y2 = max(e.order for e in self.edges) + 1 return y2 - self.xy.y + 1 class Diagram(blockdiag.elements.Diagram): _DiagramNode = DiagramNode _DiagramEdge = DiagramEdge def __init__(self): super(Diagram, self).__init__() self.int_attrs.append('edge_length') self.activation = True self.autonumber = False self.edge_length = None self.groups = [] self.separators = [] self.altblocks = [] def traverse_groups(self, preorder=False): return self.groups def set_default_linecolor(self, color): super(Diagram, self).set_default_linecolor(color) color = images.color_to_rgb(color) AltBlock.set_default_linecolor(color) def set_default_note_color(self, color): color = images.color_to_rgb(color) self._DiagramEdge.set_default_note_color(color) def set_activation(self, value): value = value.lower() if value == 'none': self.activation = value else: warning("unknown activation style: %s", value) def set_autonumber(self, value): if value.lower() == 'false': self.autonumber = False else: self.autonumber = True def set_edge_height(self, value): warning("edge_height is obsoleted; use span_height") self.span_height = int(value) seqdiag-0.9.3/src/seqdiag/metrics.py0000644000076600000240000004471312355210762020201 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import division from collections import namedtuple, defaultdict from seqdiag import elements import blockdiag.metrics from blockdiag.utils import Box, XY from blockdiag.utils.logging import warning class DiagramMetrics(blockdiag.metrics.DiagramMetrics): edge_height = 10 def __init__(self, diagram, **kwargs): super(DiagramMetrics, self).__init__(diagram, **kwargs) self.node_count = len(diagram.nodes) self.edges = diagram.edges self.separators = diagram.separators self.page_padding = [0, 0, self.cellsize * 3, 0] if diagram.edge_length: span_width = diagram.edge_length - self.node_width if span_width < 0: warning("edge_length is too short: %d", diagram.edge_length) span_width = 0 self.spreadsheet.set_span_width(0, self.span_width) self.spreadsheet.set_span_width(self.node_count, self.span_width) self.span_width = span_width for edge in diagram.edges: edge.textwidth, edge.textheight = self.edge_textsize(edge) height = self.edge_height + edge.textheight if edge.diagonal: height += self.node_height * 3 // 4 elif edge.direction == 'self': height += self.cellsize * 2 font = self.font_for(edge) if edge.leftnote: edge.leftnotesize = self.textsize(edge.leftnote, font=font) if height < edge.leftnotesize.height: height = edge.leftnotesize.height if edge.rightnote: edge.rightnotesize = self.textsize(edge.rightnote, font=font) if height < edge.rightnotesize.height: height = edge.rightnotesize.height self.spreadsheet.set_node_height(edge.order + 1, height) self.expand_pagesize_for_note(edge) span_width = defaultdict(int) span_height = defaultdict(int) for block in diagram.altblocks: x1, y1 = block.xy x2 = x1 + block.colwidth y2 = y1 + block.colheight for y in range(y1, y2): span_width[(x1, y)] += 1 span_width[(x2, y)] += 1 for x in range(x1, x2): if block.type != 'else': span_height[(x, y1)] += 1 span_height[(x, y2)] += 1 for x in range(self.node_count + 1): widths = [span_width[xy] for xy in span_width if xy[0] == x] if widths: width = self.span_width + max(widths) * self.cellsize self.spreadsheet.set_span_width(x, width) for y in range(0, len(self.edges) + 1): blocks = [b for b in diagram.altblocks if b.edges[0].order == y] span_height = self.spreadsheet.span_height[y] span_height = 0 if blocks: max_ylevel_top = max(b.ylevel_top for b in blocks) span_height = (self.spreadsheet.span_height[y + 1] + self.cellsize * 5 // 2 * (max_ylevel_top - 1) + self.cellsize) self.spreadsheet.set_span_height(y + 1, span_height) blocks = [b for b in diagram.altblocks if b.edges[-1].order == y] if blocks: max_ylevel_bottom = max(b.ylevel_bottom for b in blocks) span_height = (self.spreadsheet.span_height[y + 2] + self.cellsize // 2 * (max_ylevel_bottom - 1)) self.spreadsheet.set_span_height(y + 2, span_height) def pagesize(self, width=None, height=None): width = self.node_count height = len(self.edges) + len(self.separators) + 1 return super(DiagramMetrics, self).pagesize(width, height) @property def bottomheight(self): height = len(self.edges) + len(self.separators) dummy = elements.DiagramNode(None) dummy.xy = XY(1, height) _, y = self.spreadsheet._node_bottomright(dummy, use_padding=False) y += self.spreadsheet.span_height[len(self.edges) + 1] // 2 return y @property def edge_length(self): return self.node_width + self.span_width def lifeline(self, node): delayed = [] for sep in self.separators: if sep.type == 'delay': delayed.append(sep) lines = [] d = self.cellsize pt = self.node(node).bottom for sep in delayed: m = self.cell(sep) y1 = m.top.y y2 = m.bottom.y lines.append(((pt, XY(pt.x, y1)), '8,4')) lines.append(((XY(pt.x, y1 + d), XY(pt.x, y2 - d)), '2,8')) pt = XY(pt.x, y2) y = self.bottomheight + self.cellsize * 4 lines.append(((pt, XY(pt.x, y)), '8,4')) return lines def activity_box(self, node, activity): edges = dict([e.order, e] for e in self.edges + self.separators) # y coodinates for top of activity box starts = activity['lifetime'][0] edge = edges[starts] y1 = self.edge(edge).baseheight if isinstance(edge, elements.DiagramEdge): if edge.diagonal and edge.node2 == node: y1 += self.edge_height * 3 // 4 # y coodinates for bottom of activity box ends = activity['lifetime'][-1] + 1 if ends < len(edges): y2 = self.edge(edges[ends]).baseheight else: y2 = self.bottomheight + self.cellsize * 2 index = activity['level'] base_x = self.cell(node).bottom.x box = Box(base_x + (index - 1) * self.cellsize // 2, y1, base_x + (index + 1) * self.cellsize // 2, y2) return box def activity_shadow(self, node, activity): box = self.activity_box(node, activity) return Box(box[0] + self.shadow_offset.x, box[1] + self.shadow_offset.y, box[2] + self.shadow_offset.x, box[3] + self.shadow_offset.y) def edge_textsize(self, edge): width = 0 height = 0 if edge.label: if edge.direction == 'self': cell = self.cell(edge.node1) width = self.edge(edge).right - cell.center.x else: width = (self.cell(edge.right_node).center.x - self.cell(edge.left_node).center.x - self.cellsize * 4) # 4: width of activity and padding width, height = self.textsize(edge.label, width=width, font=self.font_for(edge)) return XY(width, height) def expand_pagesize_for_note(self, edge): if edge.leftnote: cell = self.cell(edge.left_node) width = cell.center.x - self.cellsize * 6 if width < edge.leftnotesize.width: span_width = edge.leftnotesize.width - width self.spreadsheet.span_width[0] += span_width if edge.rightnote: cell = self.cell(edge.right_node) if edge.direction == 'self': right = self.edge(edge).right width = self.pagesize().width - right - self.cellsize * 3 else: width = (self.pagesize().width - cell.center.x - self.cellsize * 3) if edge.right_node.xy.x + 1 == self.node_count: width -= self.cellsize * 2 if width < edge.rightnotesize.width: span_width = edge.rightnotesize.width - width self.spreadsheet.span_width[self.node_count] += span_width def cell(self, obj, use_padding=True): if isinstance(obj, (elements.DiagramEdge, elements.EdgeSeparator)): klass = namedtuple('_', 'xy width height colwidth colheight') edge = klass(XY(1, obj.order + 1), None, None, 1, 1) return super(DiagramMetrics, self).cell(edge, use_padding=False) elif isinstance(obj, elements.AltBlock): box = super(DiagramMetrics, self).cell(obj, use_padding=False) return AltBlockMetrics(self, obj, box) else: return super(DiagramMetrics, self).cell(obj, use_padding) def edge(self, edge): if isinstance(edge, elements.EdgeSeparator): return self.separator(edge) else: return EdgeMetrics(edge, self) def separator(self, separator): return SeparatorMetrics(separator, self) class AltBlockMetrics(blockdiag.metrics.NodeMetrics): def __init__(self, metrics, block, node): self.block = block sheet = metrics.spreadsheet cellsize = metrics.cellsize box = node.box box[0] -= (sheet.span_width[block.xy.x + 1] // 2 - cellsize * (block.xlevel - 1)) box[1] -= cellsize * 5 // 2 * (block.ylevel_top - 1) + cellsize * 3 box[2] += (sheet.span_width[block.xy.x + block.colwidth + 2] // 2 - cellsize * (block.xlevel - 1)) box[3] += cellsize * (block.ylevel_bottom - 1) + cellsize super(AltBlockMetrics, self).__init__(metrics, *box) @property def textbox(self): size = self.metrics.textsize(self.block.type, font=self.metrics.font_for(self.block)) return Box(self.x1, self.y1, self.x1 + size.width, self.y1 + size.height) class EdgeMetrics(object): def __init__(self, edge, metrics): self.metrics = metrics self.edge = edge @property def baseheight(self): cell = self.metrics.cell(self.edge) if (cell.height == self.edge.leftnotesize.height or (cell.height == self.edge.rightnotesize.height)): return cell.center.y else: return cell.top.y + self.edge.textheight @property def right(self): m = self.metrics cell = m.cell(self.edge.right_node) if self.edge.direction == 'self': if self.edge.node1.xy.x + 1 == m.node_count: width = cell.width // 2 + m.cellsize * 3 else: span_width = m.spreadsheet.span_width[self.edge.node1.xy.x] width = cell.width // 2 + span_width // 2 x = cell.bottom.x + width else: x = cell.bottom.x - m.cellsize if self.edge.failed: x -= self.metrics.edge_length // 2 return x @property def shaft(self): m = self.metrics baseheight = self.baseheight if self.edge.direction == 'self': cell = m.cell(self.edge.node1) fold_height = m.cellsize * 2 # adjust textbox to right on activity-lines base_x = cell.bottom.x x1 = base_x + self.activity_line_width(self.edge.node1) x2 = self.right line = [XY(x1 + m.cellsize, baseheight), XY(x2, baseheight), XY(x2, baseheight + fold_height), XY(x1 + m.cellsize, baseheight + fold_height)] else: x1 = (self.metrics.node(self.edge.left_node).bottom.x + self.activity_line_width(self.edge.left_node)) x2 = self.metrics.node(self.edge.right_node).bottom.x margin = m.cellsize if self.edge.diagonal: height = m.node_height * 3 // 4 if self.edge.direction == 'right': line = [XY(x1 + margin, baseheight), XY(x2 - margin, baseheight + height)] else: line = [XY(x1 + margin, baseheight + height), XY(x2 - margin, baseheight)] else: line = [XY(x1 + margin, baseheight), XY(x2 - margin, baseheight)] if self.edge.failed: edge_length = self.metrics.edge_length pt1, pt2 = line if self.edge.direction == 'right': pt2 = XY(pt2.x - edge_length // 2, (pt1.y + pt2.y) // 2) else: pt1 = XY(pt1.x + edge_length // 2, (pt1.y + pt2.y) // 2) line = [pt1, pt2] return line @property def failedmark(self): lines = [] if self.edge.failed: r = self.metrics.cellsize if self.edge.direction == 'right': pt = self.shaft[-1] lines.append((XY(pt.x + r, pt.y - r), XY(pt.x + r * 3, pt.y + r))) lines.append((XY(pt.x + r, pt.y + r), XY(pt.x + r * 3, pt.y - r))) else: pt = self.shaft[0] lines.append((XY(pt.x - r * 3, pt.y - r), XY(pt.x - r, pt.y + r))) lines.append((XY(pt.x - r * 3, pt.y + r), XY(pt.x - r, pt.y - r))) return lines @property def head(self): cell = self.metrics.cellsize head = [] if self.edge.direction == 'right': xy = self.shaft[-1] head.append(XY(xy.x - cell, xy.y - cell // 2)) head.append(xy) head.append(XY(xy.x - cell, xy.y + cell // 2)) elif self.edge.direction == 'left': xy = self.shaft[0] head.append(XY(xy.x + cell, xy.y - cell // 2)) head.append(xy) head.append(XY(xy.x + cell, xy.y + cell // 2)) else: # self xy = self.shaft[-1] head.append(XY(xy.x + cell, xy.y - cell // 2)) head.append(xy) head.append(XY(xy.x + cell, xy.y + cell // 2)) return head @property def textbox(self): m = self.metrics if self.edge.direction == 'self': x = m.node(self.edge.node1).bottom.x + \ self.activity_line_width(self.edge.node1) elif self.edge.direction == 'right': x = m.node(self.edge.left_node).bottom.x + \ self.activity_line_width(self.edge.left_node) + \ self.metrics.cellsize // 2 else: # left x = m.node(self.edge.right_node).bottom.x - self.edge.textwidth y1 = self.baseheight - self.edge.textheight return Box(x, y1, x + self.edge.textwidth, y1 + self.edge.textheight) def activity_line_width(self, node): m = self.metrics index = self.edge.order activities = [a for a in node.activities if index in a['lifetime']] if activities: level = max(a['level'] for a in activities) else: level = 0 return m.cellsize // 2 * level @property def leftnotebox(self): if not self.edge.leftnote: return Box(0, 0, 0, 0) m = self.metrics cell = m.cell(self.edge.left_node) notesize = self.edge.leftnotesize x = cell.center.x - m.cellsize * 3 - notesize.width y = self.baseheight - notesize.height // 2 if self.edge.failed and self.edge.direction == 'left': x += self.metrics.edge_length // 2 - m.cellsize return Box(x, y, x + notesize.width, y + notesize.height) @property def leftnoteshape(self): if not self.edge.leftnote: return [] r = self.metrics.cellsize box = self.leftnotebox return [XY(box[0], box[1]), XY(box[2], box[1]), XY(box[2] + r, box[1] + r), XY(box[2] + r, box[3]), XY(box[0], box[3]), XY(box[0], box[1])] @property def rightnotebox(self): if not self.edge.rightnote: return Box(0, 0, 0, 0) m = self.metrics cell = m.cell(self.edge.right_node) if self.edge.direction == 'self': x = self.right + m.cellsize * 2 elif self.edge.failed and self.edge.direction == 'right': x = self.right + m.cellsize * 4 else: x = cell.center.x + m.cellsize * 2 notesize = self.edge.rightnotesize y = self.baseheight - notesize.height // 2 return Box(x, y, x + notesize.width, y + notesize.height) @property def rightnoteshape(self): if not self.edge.rightnote: return [] r = self.metrics.cellsize box = self.rightnotebox return [XY(box[0], box[1]), XY(box[2], box[1]), XY(box[2] + r, box[1] + r), XY(box[2] + r, box[3]), XY(box[0], box[3]), XY(box[0], box[1])] class SeparatorMetrics(object): def __init__(self, separator, metrics): self.metrics = metrics self.separator = separator x1, x2 = self.baseline y1 = self.baseheight y2 = y1 + self.metrics.node_height d = self.metrics.cellsize // 4 font = metrics.font_for(self) size = metrics.textsize(separator.label, font, x2 - x1) dx = (x2 - x1 - size.width) // 2 dy = (y2 - y1 - size.height) // 2 self.labelbox = Box(x1 + dx - d, y1 + dy - d, x1 + dx + size.width + d, y1 + dy + size.height + d) @property def baseheight(self): return self.metrics.cell(self.separator).top.y @property def baseline(self): dummy = elements.DiagramNode(None) dummy.xy = XY(0, 1) dummy.colwidth = self.metrics.node_count m = self.metrics.cell(dummy) r = self.metrics.cellsize * 3 return (m.x1 - r, m.x2 + r) @property def lines(self): lines = [] if self.separator.type == 'divider': y = (self.labelbox[1] + self.labelbox[3]) // 2 x1, x2 = self.baseline d = self.metrics.cellsize // 4 lines.append((XY(x1, y - d), XY(self.labelbox[0], y - d))) lines.append((XY(x1, y + d), XY(self.labelbox[0], y + d))) lines.append((XY(self.labelbox[2], y - d), XY(x2, y - d))) lines.append((XY(self.labelbox[2], y + d), XY(x2, y + d))) return lines seqdiag-0.9.3/src/seqdiag/parser.py0000644000076600000240000002001212346552765020025 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- # Copyright (c) 2008/2009 Andrey Vlasovskikh # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. r'''A DOT language parser using funcparserlib. The parser is based on [the DOT grammar][1]. It is pretty complete with a few not supported things: * Ports and compass points * XML identifiers At the moment, the parser builds only a parse tree, not an abstract syntax tree (AST) or an API for dealing with DOT. [1]: http://www.graphviz.org/doc/info/lang.html ''' import io from re import MULTILINE, DOTALL from collections import namedtuple from funcparserlib.lexer import make_tokenizer, Token, LexerError from funcparserlib.parser import (some, a, maybe, many, finished, skip, forward_decl) from blockdiag.parser import create_mapper, flatten, oneplus_to_list from blockdiag.utils.compat import u Diagram = namedtuple('Diagram', 'id stmts') Group = namedtuple('Group', 'stmts') Node = namedtuple('Node', 'id attrs') Attr = namedtuple('Attr', 'name value') Edge = namedtuple('Edge', ('from_node edge_type to_node ' 'followers attrs edge_block')) Statements = namedtuple('Statements', 'stmts') Separator = namedtuple('Separator', 'type value') Extension = namedtuple('Extension', 'type name attrs') Fragment = namedtuple('Fragment', 'type id stmts') class ParseException(Exception): pass def tokenize(string): """str -> Sequence(Token)""" # flake8: NOQA specs = [ # NOQA ('Comment', (r'/\*(.|[\r\n])*?\*/', MULTILINE)), # NOQA ('Comment', (r'(//|#).*',)), # NOQA ('NL', (r'[\r\n]+',)), # NOQA ('Space', (r'[ \t\r\n]+',)), # NOQA ('Separator', (r'(?P===|\.\.\.)[^\r\n]+(?P=sep)',)), # NOQA ('Name', (u('[A-Za-z_0-9\u0080-\uffff]') + # NOQA u('[A-Za-z_\\-.0-9\u0080-\uffff]*'),)), # NOQA ('Op', (r'(=>)|[{};,=\[\]]|(<>?)',)), # NOQA ('Number', (r'-?(\.[0-9]+)|([0-9]+(\.[0-9]*)?)',)), # NOQA ('String', (r'(?P"|\').*?(? object""" tokval = lambda x: x.value op = lambda s: a(Token('Op', s)) >> tokval op_ = lambda s: skip(op(s)) _id = some(lambda t: t.type in ['Name', 'Number', 'String']) >> tokval keyword = lambda s: a(Token('Name', s)) >> tokval separator = some(lambda t: t.type == 'Separator') >> tokval def make_separator(sep): return Separator(sep[0:3], sep[3:-3].strip()) # # parts of syntax # option_stmt = ( _id + maybe(op_('=') + _id) >> create_mapper(Attr) ) option_list = ( maybe(op_('[') + option_stmt + many(op_(',') + option_stmt) + op_(']')) >> create_mapper(oneplus_to_list, default_value=[]) ) # attributes statement:: # default_shape = box; # default_fontsize = 16; # attribute_stmt = ( _id + op_('=') + _id >> create_mapper(Attr) ) # node statement:: # A; # B [attr = value, attr = value]; # node_stmt = ( _id + option_list >> create_mapper(Node) ) # separator statement:: # === message === # ... message ... # separator_stmt = ( separator >> make_separator ) # edge statement:: # A -> B; # C -> D { # D -> E; # } # edge_block = forward_decl() edge_relation = ( op('<<--') | op('<--') | op('<<-') | op('<-') | op('->') | op('->>') | op('-->') | op('-->>') | op('=>') ) edge_stmt = ( _id + edge_relation + _id + many(edge_relation + _id) + option_list + maybe(edge_block) >> create_mapper(Edge) ) edge_block_inline_stmt_list = ( many(edge_stmt + skip(maybe(op(';'))) | separator_stmt) ) edge_block.define( op_('{') + edge_block_inline_stmt_list + op_('}') >> Statements ) # group statement:: # group { # A; # } # group_inline_stmt_list = ( many((attribute_stmt | node_stmt) + skip(maybe(op(';')))) ) group_stmt = ( skip(keyword('group')) + skip(maybe(_id)) + op_('{') + group_inline_stmt_list + op_('}') >> Group ) # combined fragment (alt, loop) statement:: # loop { # A -> B; # } # alt { # D -> E; # } # fragment_stmt = forward_decl() fragment_inline_stmt = ( attribute_stmt | fragment_stmt | edge_stmt | node_stmt ) fragment_inline_stmt_list = ( many(fragment_inline_stmt + skip(maybe(op(';')))) ) fragment_types = ( keyword('alt') | keyword('loop') ) fragment_stmt.define( fragment_types + maybe(_id) + op_('{') + fragment_inline_stmt_list + op_('}') >> create_mapper(Fragment) ) # extension statement (class, plugin):: # class red [color = red]; # plugin attributes [name = Name]; # extension_stmt = ( (keyword('class') | keyword('plugin')) + _id + option_list >> create_mapper(Extension) ) # diagram statement:: # seqdiag { # A -> B; # } # diagram_id = ( (keyword('diagram') | keyword('seqdiag')) + maybe(_id) >> list ) diagram_inline_stmt = ( extension_stmt | attribute_stmt | fragment_stmt | group_stmt | edge_stmt | separator_stmt | node_stmt ) diagram_inline_stmt_list = ( many(diagram_inline_stmt + skip(maybe(op(';')))) ) diagram = ( maybe(diagram_id) + op_('{') + diagram_inline_stmt_list + op_('}') >> create_mapper(Diagram) ) dotfile = diagram + skip(finished) return dotfile.parse(seq) def sort_tree(tree): def weight(node): if isinstance(node, (Attr, Extension)): return 1 else: return 2 if hasattr(tree, 'stmts'): tree.stmts.sort(key=lambda x: weight(x)) for stmt in tree.stmts: sort_tree(stmt) return tree def parse_string(string): try: tree = parse(tokenize(string)) return sort_tree(tree) except LexerError as e: message = "Got unexpected token at line %d column %d" % e.place raise ParseException(message) except Exception as e: raise ParseException(str(e)) def parse_file(path): code = io.open(path, 'r', encoding='utf-8-sig').read() return parse_string(code) seqdiag-0.9.3/src/seqdiag/tests/0000755000076600000240000000000012355212722017310 5ustar tkomiyastaff00000000000000seqdiag-0.9.3/src/seqdiag/tests/diagrams/0000755000076600000240000000000012355212722021077 5ustar tkomiyastaff00000000000000seqdiag-0.9.3/src/seqdiag/tests/diagrams/alt_block.diag0000644000076600000240000000020012050072561023644 0ustar tkomiyastaff00000000000000{ alt { color = red; A => B; loop { A -> C [note = hello]; } A [width = 200, label = "hoge"]; } } seqdiag-0.9.3/src/seqdiag/tests/diagrams/altblock.diag0000644000076600000240000000003412235166124023516 0ustar tkomiyastaff00000000000000{ alt { A -> B; } } seqdiag-0.9.3/src/seqdiag/tests/diagrams/diagram_class.diag0000644000076600000240000000012311672674553024531 0ustar tkomiyastaff00000000000000{ class emphasis [color = pink, style = dashed]; A => B [class = emphasis]; } seqdiag-0.9.3/src/seqdiag/tests/diagrams/diagram_edge_length.diag0000644000076600000240000000027511672674553025701 0ustar tkomiyastaff00000000000000{ edge_length = 200; A => B [label = "hello\nworld"]; A -> B -> A [diagonal, label = "very long long long long long long long long word"]; A -> C [label = "good-bye"]; A -> A; } seqdiag-0.9.3/src/seqdiag/tests/diagrams/nested_altblock.diag0000644000076600000240000000040611736532432025067 0ustar tkomiyastaff00000000000000{ alt { A -> B [label = label, note = note]; alt { A -> B [label = label, note = note]; } } alt { alt { alt { A -> B [label = label, note = note]; } } } alt { A -> B [label = label, note = note]; } } seqdiag-0.9.3/src/seqdiag/tests/diagrams/node_activated.diag0000644000076600000240000000005712045667174024713 0ustar tkomiyastaff00000000000000{ A => B C [activated]; D [activated]; } seqdiag-0.9.3/src/seqdiag/tests/diagrams/node_fontsize.diag0000644000076600000240000000015211672674553024610 0ustar tkomiyastaff00000000000000{ A [fontsize = 20]; A -> B; A -> C [fontsize = 20, label = "hello world", note = "hello world"]; } seqdiag-0.9.3/src/seqdiag/tests/diagrams/node_notes.diag0000644000076600000240000000047111672674553024103 0ustar tkomiyastaff00000000000000{ A -> B [label = "multi\nline\nlabel", leftnote = "hello", rightnote= "world"]; A -> C [note = "hello world"]; A -> D [label = "short label", note = "goodbye\nworld"]; A -> B [note = "very very very very long long long long text"]; A -> B [leftnote = "very very very very long long long long text"]; } seqdiag-0.9.3/src/seqdiag/tests/diagrams/plugin_autoclass.diag0000644000076600000240000000012511672674553025316 0ustar tkomiyastaff00000000000000{ plugin autoclass; class emphasis [color = red]; A_emphasis => B_emphasis; } seqdiag-0.9.3/src/seqdiag/tests/diagrams/separators.diag0000644000076600000240000000026111672674553024126 0ustar tkomiyastaff00000000000000{ A -> B [failed]; A <- B [failed, color= red]; === separator === A -> C; ... separator ... A -> C; === "quoted separator" === A -> C; === separator(1) === } seqdiag-0.9.3/src/seqdiag/tests/diagrams/separators_in_subedge.diag0000644000076600000240000000014611701022675026275 0ustar tkomiyastaff00000000000000{ A -> B; === separator === A -> B { B -> C; === separator === B -> D; } } seqdiag-0.9.3/src/seqdiag/tests/test_generate_diagram.py0000644000076600000240000000063312355210015024172 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- import os import seqdiag.command from blockdiag.tests.test_generate_diagram import ( get_diagram_files, testcase_generator ) def test_generate(): mainfunc = seqdiag.command.main basepath = os.path.dirname(__file__) files = get_diagram_files(basepath) options = [] for testcase in testcase_generator(basepath, mainfunc, files, options): yield testcase seqdiag-0.9.3/src/seqdiag/tests/test_pep8.py0000644000076600000240000000324712346552765021621 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- from __future__ import print_function import os import sys import pep8 CURRENT_DIR = os.path.dirname(os.path.abspath(__file__)) BASE_DIR = os.path.dirname(CURRENT_DIR) def test_pep8(): arglist = [['statistics', True], ['show-source', True], ['repeat', True], ['paths', [BASE_DIR]]] pep8style = pep8.StyleGuide(arglist, parse_argv=False, config_file=True) options = pep8style.options if options.doctest: import doctest fail_d, done_d = doctest.testmod(report=False, verbose=options.verbose) fail_s, done_s = pep8.selftest(options) count_failed = fail_s + fail_d if not options.quiet: count_passed = done_d + done_s - count_failed print("%d passed and %d failed." % (count_passed, count_failed)) if count_failed: print("Test failed.") else: print("Test passed.") if count_failed: sys.exit(1) if options.testsuite: pep8.init_tests(pep8style) report = pep8style.check_files() if options.statistics: report.print_statistics() if options.benchmark: report.print_benchmark() if options.testsuite and not options.quiet: report.print_results() if report.total_errors: if options.count: sys.stderr.write(str(report.total_errors) + '\n') # sys.exit(1) # reporting errors (additional summary) errors = report.get_count('E') warnings = report.get_count('W') message = 'pep8: %d errors / %d warnings' % (errors, warnings) print(message) assert report.total_errors == 0, message seqdiag-0.9.3/src/seqdiag/tests/test_rst_directives.py0000644000076600000240000007712412354723122023765 0ustar tkomiyastaff00000000000000# -*- coding: utf-8 -*- import sys if sys.version_info < (2, 7): import unittest2 as unittest else: import unittest import os from blockdiag.tests.utils import capture_stderr, with_pil, TemporaryDirectory from docutils import nodes from docutils.core import publish_doctree from docutils.parsers.rst import directives as docutils from seqdiag.utils.rst import directives from blockdiag.utils.compat import u class TestRstDirectives(unittest.TestCase): def setUp(self): self._tmpdir = TemporaryDirectory() def tearDown(self): if 'seqdiag' in docutils._directives: del docutils._directives['seqdiag'] self._tmpdir.clean() @property def tmpdir(self): return self._tmpdir.name def test_setup(self): directives.setup() options = directives.directive_options self.assertIn('seqdiag', docutils._directives) self.assertEqual(directives.SeqdiagDirective, docutils._directives['seqdiag']) self.assertEqual('PNG', options['format']) self.assertEqual(False, options['antialias']) self.assertEqual(None, options['fontpath']) self.assertEqual(False, options['nodoctype']) self.assertEqual(False, options['noviewbox']) self.assertEqual(False, options['inline_svg']) def test_setup_with_args(self): directives.setup(format='SVG', antialias=True, fontpath='/dev/null', nodoctype=True, noviewbox=True, inline_svg=True) options = directives.directive_options self.assertIn('seqdiag', docutils._directives) self.assertEqual(directives.SeqdiagDirective, docutils._directives['seqdiag']) self.assertEqual('SVG', options['format']) self.assertEqual(True, options['antialias']) self.assertEqual('/dev/null', options['fontpath']) self.assertEqual(True, options['nodoctype']) self.assertEqual(True, options['noviewbox']) self.assertEqual(True, options['inline_svg']) def test_setup_fontpath1(self): with self.assertRaises(RuntimeError): directives.setup(format='SVG', fontpath=['dummy.ttf'], outputdir=self.tmpdir) text = (".. seqdiag::\n" "\n" " A -> B") publish_doctree(text) def test_setup_fontpath2(self): with self.assertRaises(RuntimeError): directives.setup(format='SVG', fontpath='dummy.ttf', outputdir=self.tmpdir) text = (".. seqdiag::\n" "\n" " A -> B") publish_doctree(text) def test_setup_nodoctype_is_true(self): directives.setup(format='SVG', outputdir=self.tmpdir, nodoctype=True) text = (".. seqdiag::\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[-1])) svg = open(doctree[0]['uri']).read() self.assertEqual(" B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) svg = open(doctree[0]['uri']).read() self.assertEqual("\n" " B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) svg = open(doctree[0]['uri']).read() self.assertRegexpMatches(svg, ' B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) svg = open(doctree[0]['uri']).read() self.assertRegexpMatches(svg, ' B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.raw, type(doctree[0])) self.assertEqual('html', doctree[0]['format']) self.assertEqual(nodes.Text, type(doctree[0][0])) self.assertEqual("\n" " B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(1, len(os.listdir(self.tmpdir))) @with_pil def test_setup_inline_svg_is_true_but_format_isnt_svg(self): directives.setup(format='PNG', outputdir=self.tmpdir, inline_svg=True) text = (".. seqdiag::\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) def test_setup_inline_svg_is_true_with_multibytes(self): directives.setup(format='SVG', outputdir=self.tmpdir, inline_svg=True) text = u(".. seqdiag::\n" "\n" " あ -> い") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.raw, type(doctree[0])) def test_setup_inline_svg_is_true_and_width_option1(self): directives.setup(format='SVG', outputdir=self.tmpdir, nodoctype=True, noviewbox=True, inline_svg=True) text = (".. seqdiag::\n" " :width: 100\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.raw, type(doctree[0])) self.assertEqual(nodes.Text, type(doctree[0][0])) self.assertRegexpMatches(doctree[0][0], ' B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.raw, type(doctree[0])) self.assertEqual(nodes.Text, type(doctree[0][0])) self.assertRegexpMatches(doctree[0][0], ' B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.raw, type(doctree[0])) self.assertEqual(nodes.Text, type(doctree[0][0])) self.assertRegexpMatches(doctree[0][0], ' B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.raw, type(doctree[0])) self.assertEqual(nodes.Text, type(doctree[0][0])) self.assertRegexpMatches(doctree[0][0], ' B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.raw, type(doctree[0])) self.assertEqual(nodes.Text, type(doctree[0][0])) self.assertRegexpMatches(doctree[0][0], ' B" " }") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_call_without_braces(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_alt_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :alt: hello world\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual('hello world', doctree[0]['alt']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_align_option1(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :align: left\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual('left', doctree[0]['align']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_align_option2(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :align: center\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual('center', doctree[0]['align']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_align_option3(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :align: right\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual('right', doctree[0]['align']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) @capture_stderr def test_align_option4(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :align: unknown\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.system_message, type(doctree[0])) # clear stderr outputs (ignore ERROR) from io import StringIO sys.stderr = StringIO() def test_caption_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :caption: hello world\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.figure, type(doctree[0])) self.assertEqual(2, len(doctree[0])) self.assertEqual(nodes.image, type(doctree[0][0])) self.assertEqual(nodes.caption, type(doctree[0][1])) self.assertEqual(1, len(doctree[0][1])) self.assertEqual(nodes.Text, type(doctree[0][1][0])) self.assertEqual('hello world', doctree[0][1][0]) def test_caption_option_and_align_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :align: left\n" " :caption: hello world\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.figure, type(doctree[0])) self.assertEqual('left', doctree[0]['align']) self.assertEqual(2, len(doctree[0])) self.assertEqual(nodes.image, type(doctree[0][0])) self.assertNotIn('align', doctree[0][0]) self.assertEqual(nodes.caption, type(doctree[0][1])) self.assertEqual(1, len(doctree[0][1])) self.assertEqual(nodes.Text, type(doctree[0][1][0])) self.assertEqual('hello world', doctree[0][1][0]) @capture_stderr def test_maxwidth_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :maxwidth: 100\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) self.assertEqual('100', doctree[0]['width']) self.assertEqual(nodes.system_message, type(doctree[1])) def test_width_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :width: 100\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual('100', doctree[0]['width']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_height_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :height: 100\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual('100', doctree[0]['height']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_scale_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :scale: 50%\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(50, doctree[0]['scale']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_name_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :name: foo%\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(['foo%'], doctree[0]['names']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_class_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :class: bar%\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(['bar'], doctree[0]['classes']) self.assertEqual(0, doctree[0]['uri'].index(self.tmpdir)) def test_figwidth_option1(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :caption: hello world\n" " :figwidth: 100\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.figure, type(doctree[0])) self.assertEqual('100px', doctree[0]['width']) def test_figwidth_option2(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :caption: hello world\n" " :figwidth: image\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.figure, type(doctree[0])) self.assertEqual('448px', doctree[0]['width']) def test_figclass_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :caption: hello world\n" " :figclass: baz\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.figure, type(doctree[0])) self.assertEqual(['baz'], doctree[0]['classes']) def test_desctable_option(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :desctable:\n" "\n" " A [description = foo]" " B [description = bar]") doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) # tgroup self.assertEqual(4, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.thead, type(doctree[1][0][2])) self.assertEqual(nodes.tbody, type(doctree[1][0][3])) # colspec self.assertEqual(50, doctree[1][0][0]['colwidth']) self.assertEqual(50, doctree[1][0][1]['colwidth']) # thead thead = doctree[1][0][2] self.assertEqual(2, len(thead[0])) self.assertEqual('Name', thead[0][0][0][0]) self.assertEqual('Description', thead[0][1][0][0]) # tbody tbody = doctree[1][0][3] self.assertEqual(2, len(tbody)) self.assertEqual('A', tbody[0][0][0][0]) self.assertEqual('foo', tbody[0][1][0][0]) self.assertEqual('B', tbody[1][0][0][0]) self.assertEqual('bar', tbody[1][1][0][0]) def test_desctable_option_without_description(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :desctable:\n" "\n" " A -> B") doctree = publish_doctree(text) self.assertEqual(1, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) def test_desctable_option_using_node_group(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :desctable:\n" "\n" " A [description = foo]" " B [description = bar]" " group { A }" " A -> B") doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) self.assertEqual(1, len(doctree[1])) self.assertEqual(nodes.tgroup, type(doctree[1][0])) # tgroup self.assertEqual(4, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.thead, type(doctree[1][0][2])) self.assertEqual(nodes.tbody, type(doctree[1][0][3])) # colspec self.assertEqual(0, len(doctree[1][0][0])) self.assertEqual(50, doctree[1][0][0]['colwidth']) self.assertEqual(0, len(doctree[1][0][1])) self.assertEqual(50, doctree[1][0][1]['colwidth']) # thead thead = doctree[1][0][2] self.assertEqual(1, len(thead)) self.assertEqual(2, len(thead[0])) self.assertEqual(1, len(thead[0][0])) self.assertEqual(1, len(thead[0][0][0])) self.assertEqual('Name', thead[0][0][0][0]) self.assertEqual(1, len(thead[0][1])) self.assertEqual(1, len(thead[0][1][0])) self.assertEqual('Description', thead[0][1][0][0]) # tbody tbody = doctree[1][0][3] self.assertEqual(2, len(tbody)) self.assertEqual(2, len(tbody[0])) self.assertEqual(1, len(tbody[0][0])) self.assertEqual(1, len(tbody[0][0][0])) self.assertEqual('A', tbody[0][0][0][0]) self.assertEqual(1, len(tbody[0][1])) self.assertEqual('foo', tbody[0][1][0][0]) self.assertEqual(2, len(tbody[1])) self.assertEqual(1, len(tbody[1][0])) self.assertEqual(1, len(tbody[1][0][0])) self.assertEqual('B', tbody[1][0][0][0]) self.assertEqual(1, len(tbody[1][1])) self.assertEqual('bar', tbody[1][1][0][0]) def test_desctable_option_with_rest_markups(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :desctable:\n" "\n" " A [description = \"foo *bar* **baz**\"]" " B [description = \"**foo** *bar* baz\"]") doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) # tgroup self.assertEqual(4, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.thead, type(doctree[1][0][2])) self.assertEqual(nodes.tbody, type(doctree[1][0][3])) # colspec self.assertEqual(50, doctree[1][0][0]['colwidth']) self.assertEqual(50, doctree[1][0][1]['colwidth']) # thead thead = doctree[1][0][2] self.assertEqual(2, len(thead[0])) self.assertEqual('Name', thead[0][0][0][0]) self.assertEqual('Description', thead[0][1][0][0]) # tbody tbody = doctree[1][0][3] self.assertEqual(2, len(tbody)) self.assertEqual('A', tbody[0][0][0][0]) self.assertEqual(4, len(tbody[0][1][0])) self.assertEqual(nodes.Text, type(tbody[0][1][0][0])) self.assertEqual('foo ', str(tbody[0][1][0][0])) self.assertEqual(nodes.emphasis, type(tbody[0][1][0][1])) self.assertEqual(nodes.Text, type(tbody[0][1][0][1][0])) self.assertEqual('bar', tbody[0][1][0][1][0]) self.assertEqual(nodes.Text, type(tbody[0][1][0][2])) self.assertEqual(' ', str(tbody[0][1][0][2])) self.assertEqual(nodes.strong, type(tbody[0][1][0][3])) self.assertEqual(nodes.Text, type(tbody[0][1][0][3][0])) self.assertEqual('baz', str(tbody[0][1][0][3][0])) self.assertEqual('B', tbody[1][0][0][0]) self.assertEqual(4, len(tbody[1][1][0])) self.assertEqual(nodes.strong, type(tbody[1][1][0][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][0][0])) self.assertEqual('foo', str(tbody[1][1][0][0][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][1])) self.assertEqual(' ', str(tbody[1][1][0][1])) self.assertEqual(nodes.emphasis, type(tbody[1][1][0][2])) self.assertEqual(nodes.Text, type(tbody[1][1][0][2][0])) self.assertEqual('bar', str(tbody[1][1][0][2][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][3])) self.assertEqual(' baz', str(tbody[1][1][0][3])) def test_desctable_option_with_numbered(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :desctable:\n" "\n" " A [numbered = 2]" " B [numbered = 1]") doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) # tgroup self.assertEqual(4, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.thead, type(doctree[1][0][2])) self.assertEqual(nodes.tbody, type(doctree[1][0][3])) # colspec self.assertEqual(25, doctree[1][0][0]['colwidth']) self.assertEqual(50, doctree[1][0][1]['colwidth']) # thead thead = doctree[1][0][2] self.assertEqual(2, len(thead[0])) self.assertEqual('No', thead[0][0][0][0]) self.assertEqual('Name', thead[0][1][0][0]) # tbody tbody = doctree[1][0][3] self.assertEqual(2, len(tbody)) self.assertEqual('1', tbody[0][0][0][0]) self.assertEqual('B', tbody[0][1][0][0]) self.assertEqual('2', tbody[1][0][0][0]) self.assertEqual('A', tbody[1][1][0][0]) def test_desctable_option_with_numbered_and_description(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :desctable:\n" "\n" " A [description = foo, numbered = 2]" " B [description = bar, numbered = 1]") doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) # tgroup self.assertEqual(5, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.colspec, type(doctree[1][0][2])) self.assertEqual(nodes.thead, type(doctree[1][0][3])) self.assertEqual(nodes.tbody, type(doctree[1][0][4])) # colspec self.assertEqual(25, doctree[1][0][0]['colwidth']) self.assertEqual(50, doctree[1][0][1]['colwidth']) self.assertEqual(50, doctree[1][0][2]['colwidth']) # thead thead = doctree[1][0][3] self.assertEqual(3, len(thead[0])) self.assertEqual('No', thead[0][0][0][0]) self.assertEqual('Name', thead[0][1][0][0]) self.assertEqual('Description', thead[0][2][0][0]) # tbody tbody = doctree[1][0][4] self.assertEqual(2, len(tbody)) self.assertEqual('1', tbody[0][0][0][0]) self.assertEqual('B', tbody[0][1][0][0]) self.assertEqual(1, len(tbody[0][2])) self.assertEqual('bar', tbody[0][2][0][0]) self.assertEqual('2', tbody[1][0][0][0]) self.assertEqual('A', tbody[1][1][0][0]) self.assertEqual('foo', tbody[1][2][0][0]) def test_desctable_option_for_edges(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :desctable:\n" "\n" " A -> B [description = \"foo\"]" " C -> D [description = \"bar\"]" " C [label = \"label_C\"]" " D [label = \"label_D\"]") doctree = publish_doctree(text) self.assertEqual(2, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) # tgroup self.assertEqual(4, len(doctree[1][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][0])) self.assertEqual(nodes.colspec, type(doctree[1][0][1])) self.assertEqual(nodes.thead, type(doctree[1][0][2])) self.assertEqual(nodes.tbody, type(doctree[1][0][3])) # colspec self.assertEqual(25, doctree[1][0][0]['colwidth']) self.assertEqual(50, doctree[1][0][1]['colwidth']) # thead thead = doctree[1][0][2] self.assertEqual(2, len(thead[0])) self.assertEqual('Name', thead[0][0][0][0]) self.assertEqual('Description', thead[0][1][0][0]) # tbody tbody = doctree[1][0][3] self.assertEqual(2, len(tbody)) self.assertEqual('A -> B', tbody[0][0][0][0]) self.assertEqual(1, len(tbody[0][1][0])) self.assertEqual(nodes.Text, type(tbody[0][1][0][0])) self.assertEqual('foo', str(tbody[0][1][0][0])) self.assertEqual('label_C -> label_D', tbody[1][0][0][0]) self.assertEqual(1, len(tbody[1][1][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][0])) self.assertEqual('bar', str(tbody[1][1][0][0])) def test_desctable_option_for_nodes_and_edges(self): directives.setup(format='SVG', outputdir=self.tmpdir) text = (".. seqdiag::\n" " :desctable:\n" "\n" " A -> B [description = \"foo\"]" " C -> D [description = \"bar\"]" " C [label = \"label_C\", description = foo]" " D [label = \"label_D\"]") doctree = publish_doctree(text) self.assertEqual(3, len(doctree)) self.assertEqual(nodes.image, type(doctree[0])) self.assertEqual(nodes.table, type(doctree[1])) self.assertEqual(nodes.table, type(doctree[2])) # tgroup self.assertEqual(4, len(doctree[2][0])) self.assertEqual(nodes.colspec, type(doctree[2][0][0])) self.assertEqual(nodes.colspec, type(doctree[2][0][1])) self.assertEqual(nodes.thead, type(doctree[2][0][2])) self.assertEqual(nodes.tbody, type(doctree[2][0][3])) # colspec self.assertEqual(25, doctree[2][0][0]['colwidth']) self.assertEqual(50, doctree[2][0][1]['colwidth']) # thead thead = doctree[2][0][2] self.assertEqual(2, len(thead[0])) self.assertEqual('Name', thead[0][0][0][0]) self.assertEqual('Description', thead[0][1][0][0]) # tbody tbody = doctree[2][0][3] self.assertEqual(2, len(tbody)) self.assertEqual('A -> B', tbody[0][0][0][0]) self.assertEqual(1, len(tbody[0][1][0])) self.assertEqual(nodes.Text, type(tbody[0][1][0][0])) self.assertEqual('foo', str(tbody[0][1][0][0])) self.assertEqual('label_C -> label_D', tbody[1][0][0][0]) self.assertEqual(1, len(tbody[1][1][0])) self.assertEqual(nodes.Text, type(tbody[1][1][0][0])) self.assertEqual('bar', str(tbody[1][1][0][0])) ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag/utils/��������������������������������������������������������������������0000755�0000766�0000024�00000000000�12355212722�017306� 5����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag/utils/__init__.py���������������������������������������������������������0000644�0000766�0000024�00000001144�11655736155�021434� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag/utils/rst/����������������������������������������������������������������0000755�0000766�0000024�00000000000�12355212722�020116� 5����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag/utils/rst/__init__.py�����������������������������������������������������0000644�0000766�0000024�00000001144�11655736155�022244� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag/utils/rst/directives.py���������������������������������������������������0000644�0000766�0000024�00000002745�12354723131�022641� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from docutils.parsers import rst from seqdiag.utils.rst.nodes import seqdiag as seqdiag_node from blockdiag.utils.rst import directives directive_options_default = dict(format='PNG', antialias=False, fontpath=None, outputdir=None, nodoctype=False, noviewbox=False, inline_svg=False) directive_options = {} class SeqdiagDirective(directives.BlockdiagDirective): name = "seqdiag" node_class = seqdiag_node @property def global_options(self): return directive_options def setup(**kwargs): for key, value in directive_options_default.items(): directive_options[key] = kwargs.get(key, value) rst.directives.register_directive("seqdiag", SeqdiagDirective) ���������������������������seqdiag-0.9.3/src/seqdiag/utils/rst/nodes.py��������������������������������������������������������0000644�0000766�0000024�00000001435�12354723131�021603� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import seqdiag.parser import seqdiag.builder import seqdiag.drawer from blockdiag.utils.rst import nodes class seqdiag(nodes.blockdiag): name = 'seqdiag' processor = seqdiag �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag.egg-info/�����������������������������������������������������������������0000755�0000766�0000024�00000000000�12355212722�017640� 5����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag.egg-info/dependency_links.txt���������������������������������������������0000644�0000766�0000024�00000000001�12355212714�023707� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag.egg-info/entry_points.txt�������������������������������������������������0000644�0000766�0000024�00000000104�12355212714�023132� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������ [console_scripts] seqdiag = seqdiag.command:main ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag.egg-info/PKG-INFO���������������������������������������������������������0000644�0000766�0000024�00000022467�12355212714�020751� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������Metadata-Version: 1.1 Name: seqdiag Version: 0.9.3 Summary: seqdiag generates sequence-diagram image from text Home-page: http://blockdiag.com/ Author: Takeshi Komiya Author-email: i.tkomiya at gmail.com License: Apache License 2.0 Download-URL: http://pypi.python.org/pypi/seqdiag Description: `seqdiag` generate sequence-diagram image file from spec-text file. .. image:: https://drone.io/bitbucket.org/blockdiag/seqdiag/status.png :target: https://drone.io/bitbucket.org/blockdiag/seqdiag :alt: drone.io CI build status .. image:: https://pypip.in/v/seqdiag/badge.png :target: https://pypi.python.org/pypi/seqdiag/ :alt: Latest PyPI version .. image:: https://pypip.in/d/seqdiag/badge.png :target: https://pypi.python.org/pypi/seqdiag/ :alt: Number of PyPI downloads Features ======== * Generate sequence-diagram from dot like text (basic feature). * Multilingualization for node-label (utf-8 only). You can get some examples and generated images on `blockdiag.com`_ . Setup ===== Use easy_install or pip:: $ sudo easy_install seqdiag Or $ sudo pip seqdiag Copy and modify ini file. example:: $ cp /blockdiag/examples/simple.diag . $ vi simple.diag Please refer to `spec-text setting sample`_ section for the format of the `simpla.diag` configuration file. spec-text setting sample ======================== Few examples are available. You can get more examples at `blockdiag.com `_ . simple.diag ------------ simple.diag is simply define nodes and transitions by dot-like text format:: diagram { browser -> webserver [label = "GET /index.html"]; browser <-- webserver; browser -> webserver [label = "POST /blog/comment"]; webserver -> database [label = "INSERT comment"]; webserver <-- database; browser <-- webserver; } Usage ===== Execute seqdiag command:: $ seqdiag simple.diag $ ls simple.png simple.png Requirements ============ * Python 2.6, 2.7, 3.2, 3.3, 3.4 * Pillow 2.2.1 or later * funcparserlib 0.3.6 or later * reportlab (optional) * wand and imagemagick (optional) * setuptools License ======= Apache License 2.0 History ======= 0.9.3 (2014-07-03) ------------------ * Fix bugs 0.9.2 (2014-07-02) ------------------ * Change interface of docutils node (for sphinxcontrib module) 0.9.1 (2014-06-23) ------------------ * Add options to blockdiag directive (docutils extension) - :width: - :height: - :scale: - :align: - :name: - :class: - :figwidth: - :figclass: 0.9.0 (2013-10-05) ------------------ * Support python 3.2 and 3.3 (thanks to @masayuko) * Drop supports for python 2.4 and 2.5 * Replace dependency: PIL -> Pillow 0.8.2 (2013-02-09) ------------------ * Fix bugs 0.8.1 (2012-11-12) ------------------ * Add altblock feature (experimental) * Fix bugs 0.8.0 (2012-10-22) ------------------ * Optimize algorithm for rendering shadow * Add options to docutils directive * Fix bugs 0.7.5 (2012-09-29) ------------------ * Fix bugs 0.7.4 (2012-09-20) ------------------ * Support blockdiag-1.1.7 interface * Fix bugs 0.7.3 (2012-03-16) ------------------ * Allow to insert separators in subedge-group * Fix bugs 0.7.2 (2011-12-12) ------------------ * Fix bugs 0.7.1 (2011-11-30) ------------------ * Fix bugs 0.7.0 (2011-11-19) ------------------ * Add fontfamily attribute for switching fontface * Fix bugs 0.6.3 (2011-11-06) ------------------ * Add docutils extention * Fix bugs 0.6.2 (2011-11-01) ------------------ * Add class feature (experimental) 0.6.1 (2011-11-01) ------------------ * Follow blockdiag-0.9.7 interface 0.6.0 (2011-10-28) ------------------ * Add edge attributes: note, rightnote, leftnote, notecolor * Add diagram atteribute: default_note_color 0.5.2 (2011-10-27) ------------------ * Implement auto edge height adjusting * Fix bugs 0.5.1 (2011-10-24) ------------------ * Fix bugs 0.5.0 (2011-10-21) ------------------ * Add diagram attributes: activation, autonumber * Add edge attribute: failed * Add separator syntax 0.4.3 (2011-10-19) ------------------ * Follow blockdiag-0.9.5 interface 0.4.2 (2011-10-11) ------------------ * Fix bugs 0.4.1 (2011-09-30) ------------------ * Add diagram attribute: default_text_color * Add node attribte: textcolor * Fix bugs 0.4.0 (2011-09-26) ------------------ * Add diagram attributes: default_node_color, default_group_color and default_line_color 0.3.8 (2011-08-02) ------------------ * Allow dot characters in node_id * Fix bugs 0.3.7 (2011-07-05) ------------------ * Fix bugs 0.3.6 (2011-07-03) ------------------ * Support input from stdin 0.3.5 (2011-06-02) ------------------ * Fix bugs 0.3.4 (2011-05-18) ------------------ * Fix bugs 0.3.3 (2011-05-16) ------------------ * Add --version option * Add sphinxhelper module 0.3.2 (2011-05-14) ------------------ * Render group label * Support blockdiag 0.8.1 core interface 0.3.1 (2011-04-22) ------------------ * Render group label * Fix sphinxcontrib_seqdiag does not work with seqdiag 0.3.0 0.3.0 (2011-04-22) ------------------ * Add group syntax 0.2.7 (2011-04-15) ------------------ * Adjust start coordinates of edges 0.2.6 (2011-04-14) ------------------ * Fix bugs * Allow unquoted utf8 characters 0.2.5 (2011-03-26) ------------------ * Fix seqdiag could not run under blockdiag 0.7.6 0.2.4 (2011-03-20) ------------------ * Fix bugs 0.2.3 (2011-03-09) ------------------ * Fix bugs 0.2.2 (2011-03-07) ------------------ * Fix could not run under python 2.4 * Support edge colors 0.2.1 (2011-02-28) ------------------ * Add default_shape attribute to diagram 0.2.0 (2011-02-27) ------------------ * Add metrix parameters for edge label: edge_height, edge_length * Fix bugs 0.1.7 (2011-01-21) ------------------ * Fix TeX exporting in Sphinx extension 0.1.6 (2011-01-15) ------------------ * Support blockdiag-0.6.3 * Fix bugs 0.1.5 (2011-01-15) ------------------ * Draw activity on lifelines * Support both direction edge with '=>' operator 0.1.4 (2011-01-13) ------------------ * Change synxtax around edges 0.1.3 (2011-01-12) ------------------ * Support diagonal edge * Fix bugs 0.1.2 (2011-01-11) ------------------ * Support nested edges * Add edge attributes; return, dir * Add sphinx extention module(sphinxcontrib_seqdiag) * Fix bugs 0.1.1 (2011-01-11) ------------------ * Fix bugs about layouting 0.1.0 (2011-01-08) ------------------ * first release Keywords: diagram,generator Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: System Administrators Classifier: License :: OSI Approved :: Apache Software License Classifier: Programming Language :: Python Classifier: Topic :: Software Development Classifier: Topic :: Software Development :: Documentation Classifier: Topic :: Text Processing :: Markup ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag.egg-info/requires.txt�����������������������������������������������������0000644�0000766�0000024�00000000131�12355212714�022234� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������setuptools blockdiag>=1.4.1 [rst] docutils [testing] nose pep8>=1.3 reportlab docutils ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag.egg-info/SOURCES.txt������������������������������������������������������0000644�0000766�0000024�00000002721�12355212716�021531� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������LICENSE MANIFEST.in README.rst bootstrap.py buildout.cfg seqdiag.1 setup.cfg setup.py tox.ini examples/edge_attributes.diag examples/edge_attributes.png examples/edge_attributes.svg examples/edge_type.diag examples/edge_type.png examples/edge_type.svg examples/seqdiagrc examples/simple.diag examples/simple.png examples/simple.svg src/seqdiag_sphinxhelper.py src/seqdiag/__init__.py src/seqdiag/builder.py src/seqdiag/command.py src/seqdiag/drawer.py src/seqdiag/elements.py src/seqdiag/metrics.py src/seqdiag/parser.py src/seqdiag.egg-info/PKG-INFO src/seqdiag.egg-info/SOURCES.txt src/seqdiag.egg-info/dependency_links.txt src/seqdiag.egg-info/entry_points.txt src/seqdiag.egg-info/requires.txt src/seqdiag.egg-info/top_level.txt src/seqdiag/tests/test_generate_diagram.py src/seqdiag/tests/test_pep8.py src/seqdiag/tests/test_rst_directives.py src/seqdiag/tests/diagrams/alt_block.diag src/seqdiag/tests/diagrams/altblock.diag src/seqdiag/tests/diagrams/diagram_class.diag src/seqdiag/tests/diagrams/diagram_edge_length.diag src/seqdiag/tests/diagrams/nested_altblock.diag src/seqdiag/tests/diagrams/node_activated.diag src/seqdiag/tests/diagrams/node_fontsize.diag src/seqdiag/tests/diagrams/node_notes.diag src/seqdiag/tests/diagrams/plugin_autoclass.diag src/seqdiag/tests/diagrams/separators.diag src/seqdiag/tests/diagrams/separators_in_subedge.diag src/seqdiag/utils/__init__.py src/seqdiag/utils/rst/__init__.py src/seqdiag/utils/rst/directives.py src/seqdiag/utils/rst/nodes.py�����������������������������������������������seqdiag-0.9.3/src/seqdiag.egg-info/top_level.txt����������������������������������������������������0000644�0000766�0000024�00000000035�12355212714�022371� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag_sphinxhelper seqdiag ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/src/seqdiag_sphinxhelper.py�����������������������������������������������������������0000644�0000766�0000024�00000002036�12224140114�021300� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������# -*- coding: utf-8 -*- # Copyright 2011 Takeshi KOMIYA # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. __all__ = [ 'core', 'utils' ] import seqdiag import seqdiag.parser import seqdiag.builder import seqdiag.drawer core = seqdiag import seqdiag.utils.rst.nodes import seqdiag.utils.rst.directives utils = seqdiag.utils import blockdiag.utils.bootstrap utils.bootstrap = blockdiag.utils.bootstrap import blockdiag.utils.fontmap utils.fontmap = blockdiag.utils.fontmap import blockdiag.utils.compat utils.compat = blockdiag.utils.compat ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������seqdiag-0.9.3/tox.ini�������������������������������������������������������������������������������0000644�0000766�0000024�00000000342�12346552765�015272� 0����������������������������������������������������������������������������������������������������ustar �tkomiya�������������������������staff���������������������������0000000�0000000������������������������������������������������������������������������������������������������������������������������������������������������������������������������[tox] envlist=py26,py27,py32,py33,py34 [testenv] deps= nose flake8 docutils reportlab commands= nosetests flake8 src [testenv:py26] deps= nose flake8 docutils reportlab unittest2 ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������