bdist_nsi-0.1.5/0000755000000000000000000000000013077170004012170 5ustar rootrootbdist_nsi-0.1.5/bdist_nsi/0000755000000000000000000000000013077170004014146 5ustar rootrootbdist_nsi-0.1.5/bdist_nsi/__init__.py0000755000000000000000000000000012042736306016254 0ustar rootrootbdist_nsi-0.1.5/bdist_nsi/python-uninstall.ico0000755000000000000000000007644612042736306020222 0ustar rootroot hF  00 %V@@ (B:(  IIIB山]]]h梥VVVh+μR^㛛SSSh+^fLX[++^rsͻu6a.++ ggkLqSk ;++ppmw>++(0"' )))-PQ/'._s99mmm:::{{{RR j0Gd㍍888???mmmvvyPazLYtO쿿qqq~ 444giiios YoO JQ-tt큁X3jjdASUUBBBB!A'C2.{r ??( @ ,,,hxxx㺺튊@@@YYY񽽽ꅅ>>>///hꁁ;;;aaa|||999GUONzzz999GɾҷPůROKRuuu777Gh}vnTv6wROVYĽ¹GGGH8iFv6ZfOMu|GGOT\MZcv6t6XKHDgGG3-nWWzzv6t6s7W84zGGһ3$M>vvrrwk\i5r6q6p7r=;GGнhhbb|ueR;a1 u=9GGLL^^=<C6_=9GG JJNnoUWyySSYv1nGGRR,ggqqqpppGG! |zzzFFF G"~$3EE]]]L覦eee&=tb ff,,,,,,ccc *3d25뒒aaalllꦦzzzeee(~(C)S6AZbaa萐瀀''',,,PPPAA&F HDP5zJ%'쮮JJJ)))zzzVV 6slmpe,=Gnη6!!!KKKttt闗su)oZE < o ӶPPP&&&WWW99K)-}O>I n#^^^,'56]H;D ///h)[3uJ*UVLLLF3 IBI!L111iik%%%h I(`e`[8N_~fiX}:,@(0` ,@VVVooo000<)CCCݷlll///< ~~~jjj---<)HHHhhh---<"""fff---< LLLddd,,,<mĻXQNLqaaa+++<mźȿǯSQNLIJ___)))<mCv6y=DzSQNLI`û]]]))) my,/4w6v6u6ζSQNLIX_ļmmZ2Mvp?+>{JW\(Rbxmm\\Qb G|Gee{||SSSUUUmm<<oQ>VUUsssNNNKKKm}D+!aaa;;;(mᱱACA= MxMOOO/mIZIA,7k!!!v}}}LLLRgR3sbmnnWWW/###ᢢLLLYkY"B,,r{r"""/```nnnBBB荍▖y}yV,-0Tg)쁁ꁁVVV/$$$̙CCCyyy } ,ZR,=:Loo{{{ooo/]]]홙^^^JJJq1bsC?;.kNhN==헗555 www+++```*p*#QrT|K S092sLOIӵ/: nqqq>m>;3Z$ 4d@@V 폏<<<v2 ;;;dddTmTad:  B ?cvvvۛ/<AAAmmm𜜜`d"Rxb???<AAQ 36"![/Hfn`g XJJJ$ΑpSo 6 #UU~~~"""gr+1m<9Wcf rrAAA)B} H2p7}GAi_crrmmm͚F=3wFF&rRRu``ww777)$$7~HHGY;&&&XXX$!K(_(fdF.()-[Ti`:i +$V)q-*t/????????????????!#(@ KcJJJ```(((`I777𬬬^^^(((`mmm]]]'''`I:::𵵵[[['''`rrrZZZ'''`I===𾾾XXX%%%`wwwWWW%%%`8@@@ooVVV$$$`]QPNLWUUU###`ûSQPNLJHfSSS###`µǾƤzQǨSQPNLJHGMRRR###`ǻūw6v6u6v7SQPNLJHw[ƽPPP###>]ekux}VVZơuw6v6u6u6˹SQPNLJHenü rx}.BUw6v6u6u6ʸSQPNLvqGifFĽſ[3Es7SrV;!8Mw6v6u6u6ηcQPNLR|FAºO7VS\3-?@Ww6v6u6u6_QPNLJHJ|O4~op4Go&Ko]]ơtw6v6u6u6t6ƷbPNLJHGECgɴJhDDgoo3:lllռw6v6u6u6t6w=rNLJHGEC@?WdFv )9XkM4YV||ffvy8v6u6u6t6s6u:ŬuJHGE@ )]<<^r3$k7TDBllRRrͯv6u6u6t6s6r6q6v?KEL^<:rX;)A-oOOfyySSBBB^^^NNNiu6u6t6s6r6q6p6o6p9sKz;<::Xn@rmMM|yyQQbYYYGC=nP,n3s6r6q6p6o6n6m6sQ]3><:8ѷ}}kkHHwIIIUUT?6,fG"k3p6o6n6_H _?><:8faSKKjvvhhyQPP;1%cE"d95%\><:8I99\\ZZ==Ae>uF><:8@<<:8G=={{\\}qq|zxGHH#?I&78bSV)GQM t ~ f>d>BBqwyADE =HY^^0`0%%rrrAAA???))7d^4_4AAkkk<<<===𐐐B*6 ;vvvfff:::`䴴$-5OwI03[[[222G'A'\m,! HeHEEEQ䠠<<<+S+ ci &Rvvv򸸸hhh'Z'$ig/Jn9Z9MMMQooo􎎎:::'Z')'bse))cc򟟟<<'ZMGFmF)))QPPPJJJ///~~~ v ?% M$H*6z=&YKG $j$װQkkk%%%rrr[\q_pBj4t</lJ9k}000gooo*X*ZL2Pok2(9B@6eמQY9222ZZZ9V9,}I2@1 2cuuuװ111 `555aaaXdgek)-}ggg򫫫Q`:::hhh,,J Co\e333`$$y-ds7 L Q6H vOC===A0#UI,C8rrr 2'27,B'{ wU 888Iͩ/+c6y=B.CM{fff~555x$Q?EJG&Uo 333I_:=8:&XHNOOP `55 \\\{ <A::QSG*tQZZZ...IW*M;DIHGu,LLL`#Q(Z::6YGIB6fi0r/BP]m}v`E-! 1*??????0p?bdist_nsi-0.1.5/bdist_nsi/python-install.ico0000755000000000000000000007644612042736306017657 0ustar rootroot hF  00 %V@@ (B:(  IIIB山]]]h梥VVVh+μR^㛛SSSh+^fLX[++ʽtsͻu6aJ++͵uukLtA;++t~}>++ss ##)))-PP99mmm:::{{{RRj0Gd㍍888???mmmvvLYtO쿿qqq~ 444giiic$큁3jjd^ĉBBBB!A'C2.{r ??( @ ,,,hxxx㺺튊@@@YYY񽽽ꅅ>>>///hꁁ;;;aaa|||999GUONzzz999GɾҷPůROKRuuu777Gh}vnTv6wROVYĽ¹GGGH8iFv6ZfOMu|GGPT\MZcv6t6XKHDgGGarnWVzzv6t6s7WD@=zGGһy>Ljvvrrwk\i5r6q6p7kA=;GGƱŬbb|ueR;b0m6p==9GGyy^^tj_\J3=9GGddNnoUWyyYv1nGGagavggqqqpppGG/g/((zzzFFF G""iEE]]]L覦eee ff,,,,,,cccd25뒒aaalllꦦzzzeee(~(S6AZbaa萐瀀''',,,PPPAADP5zJ%'쮮JJJ)))zzzVVe,=Gnη6!!!KKKttt闗tto ӶPPP&&&WWW}}}}m|^^^),6]H;5m5///h)[3uJ*_f_槧LLL IBI!L111jjj%%%h I(`e`[8N_~fiX}:,(0` ,@VVVooo000<)CCCݷlll///< ~~~jjj---<)HHHhhh---<"""fff---< LLLddd,,,<mĻXQNLqaaa+++<mźȿǯSQNLIJ___)))<mCv6y=DzSQNLI`û]]]))) my,/4w6v6u6ζSQNLIX_ļmmZ2Mvp?+m> 4d@@V 폏<<<v2 ;;;dddTmT ?cvvvۛ/<AAAmmm𜜜b???<GGGuuuw[/<MXJJJ$0opSo -R-~~~"""+1m<9W{AAA) H2p7}GAiO񙙙mmmF=3wFF&rccc777)$7~HHGY;&&&XXX$!K(_(fdF.()-[Ti`:i +$V)q-*t/????????????????!#(@ KcJJJ```(((`I777𬬬^^^(((`mmm]]]'''`I:::𵵵[[['''`rrrZZZ'''`I===𾾾XXX%%%`wwwWWW%%%`8@@@ooVVV$$$`]QPNLWUUU###`ûSQPNLJHfSSS###`µǾƤzQǨSQPNLJHGMRRR###`ǻūw6v6u6v7SQPNLJHw[ƽPPP###>]ekux}VVZơuw6v6u6u6˹SQPNLJHenü rx}.BUw6v6u6u6ʸSQPNLvqGifFĽſ[3Es7SrV;!8Mw6v6u6u6ηcQPNLR|FAºO7VS\3-?@Ww6v6u6u6_QPNLJHJ|O4~op4Go&Ko]]ơtw6v6u6u6t6ƷbPNLJHGECgɴOhDDgoo3:lllռw6v6u6u6t6w=rNLJHGECA?Ww8UkM4YV||ffvy8v6u6u6t6s6u:ŬuJHGECA?><^ȥzu6u8r7o6l6TDBllRRrͯv6u6u6t6s6r6q6v?KECA?><:rXu6s6v=Yl6oOOfyySSBBB^^^NNNiu6u6t6s6r6q6p6o6p9sDA?><::Xu6Ugp7q=MM|yyQQbYYYGC=nP,n3s6r6q6p6o6n6m6m6jD?><:8ѷɭӼ|I˿}}kkHHwIIIUUT?6,fG"k3p6o6n6m6m6l6|N?><:8fũKKjvvhhyQPP;1%cE"h3m6m6l6k6\><:8I\\ZZ==AMLK8/$aD"f3k6uF><:8@DD\~~AAg}JHG6-#]B"><:8GBB}{{\\}|zxGHH#?I&78boooPP]X[)GQM t ~ f>d>qwyADE =HY555(;(_0`0rrrAAA???侾&5& d^4_4kkk<<<===𐐐S*6}OlOfff:::`䴴'1']$d$[[[222G'A'wK HeHEEEQ䠠<<<+S+pRvvv򸸸hhh'Z'n9Z9MMMQooo􎎎:::'Z'e))cc򟟟<<'ZMGFmF)))QPPPJJJ///~~~ v H*6z=&YKG $j$װQkkk%%%rrr[j4t</lJ9k}000gooo*X*2(9B@6eמQY9222ZZZ9V91 2cuuuװ111 `555aaa_l_}ggg򫫫Q`:::hhh } e333`===nnnZ L Q`0C===A v/G/rrr '27,B'{ ]888I+c6y=B.CKfff55x$Q?EJG&)=)333I=8:&XHNOOV嘘\\\ <A::QSG*tQZZZ...IM;DIHGu,LLL`#Q(Z::6YGIB6fi0r/BP]m}v`E-! 1*???????bdist_nsi-0.1.5/bdist_nsi/python-install-164x314.bmp0000755000000000000000000045565612042736306020617 0ustar rootrootBM[6(:x[  ؿ줤LXL(6(   /F Y kL  '[Ԅ+9+  P +6A6aia(g # ALAS]S  {  V_Vele  yex}x  m $ W_W_  c第mrm8E8lql   # X`XW`W  Lxtqxq * a`h`  t  CMC H  ! ZbZg!,!k `uzu  }5?5"," ! [c[*4* M J MVMe ^   <   ! \d\LUL 2 ] zz www  `n  wwwwyw| " OWO:D: 3 gntn*4* www ~wwww  u   |  6}wy}wwww|  Q $+5+ A W &1&wwww} - ?J?uzu  $hhm4 }w} )(5(S\S  b 4UU\"")*4*   M rxr‹*6*(DOD  22:0o,*7*LWLS]S*  Com  BBffkDDL/:/B )  % U   /'}}YdY' > `xx&MMT66kNNV  g  HSH՜S\S    F 7@7  $0$MMUYY]],,3ZZNNVG hnhHSH)  $ qwq(  33X22W66a^^MMWlqlz y&1& H    "e{{ssBBK\\__MMW%1% ~{#,#zz ywy   , QQXSSJJEEK~~ff@@I   * wwww  ! !xx~~088euu""*C-7- Q wwwwy  i{{33[yy||y|yu R gng ( wwwx   &119UU*\d\%||   E &tt瀀66aYbY0!+! ` zz  .8.ntyt**FZZLLTV`V =H=T]T 2   !  !TTYAAz}}R]RJ    $ 5 ((/WW55^OZO  $/$ V  AJAww퀀jj$LXLkrk %    5C588f//PIUIKWKy  $$*eeɀgg$$*\e\ipiAKA4    ##7--J \ >L># U   FFMTTcc''.2*t  #||))B   X`X" hhmGGcc '%2% OYO  W  d !uu退FFMMS]e] X 񚛚+8+#r #fmf99h++J Z  2>2sys#A ] xm: * %jjԀww%    Ÿw{wHTH$1$   4C4!!5~~oo-||@L@  W ZZ`EEyy%%@%))7B7   ,6,A .;.!ff[[(<]W &1& %  2 > >D>n=G= L  } o<>,HRHmuY  R 6=bzS\Sz!66||  D >SHey s`h`@K@N<1Uc  !JV)E lkrk  z =E'  3v{czzK!p M F7 W M ty} M iX M M ;F#Lv?C C 6lz:!\q!.!W "L*a'V V 6 xn<BFJJ#CM -:-&2&o 6y=A?IMP.z # KWKoh?9=A/nHLPK ix|xmwo ,b8~<@$QDKOS"1#/# U qz3q7};?'Z0oJNR6Y  <|/i7{:>0oEJMQ;K a"m *]6y:=?=IMQ>>>K>  e65w9=A'[HLP3w/**8*v 4t8~<@6{GKO-bkbxmwu@57};?BGJ>   T {{"G:>BFAI{>/cxpxog=!K'Y#>x~MM  kgZo>$0$te,-ZcZ|dN  V}R /yV{  Zk)CPCk`W7E7Znd/'oX$/$q-7@7 : J [s @3q9;:&Mu$O5u7}:=@C7 nojoj43r1o8~<?BEG8! dcJ&),)[5v8~%T>@CFIL `  4s7{94wFBEHKN3wG he S }} 5x8;>$S&VGJLO>4mp2q:=@CC<KNQE(l O npq"E<>ADF'[LPS5{Oge :@CFIJ@QT +~Y  $?EHJMOS1q" Xc ! z|$3uILON0k   zo & 7:A  4 6gin ) J ] , {{#3^ALA  ai  fmf℆==<;:Use=˪v|X.~Z/jEkF˾|X.Ʒx|X.{ƷggjDʼϡg`9|[a8´ɽȹ}Z0Ĵ~[0|X.yƱ\3|X.ȯy:v6u6u6u6u6t6{BSRQQPONMLKJJIHGFEEDCBA@?>==<;:9DƪwtQe>sPĴͿ{Ze=lGƘ{Yԡh˾曀_vToKpõga8~[0şgnJ{YƷʺtQc==<;:98r|X.v6v6v6u6u6u6u6t6{BSRQQPONMLKJJIHGFEEDCBA@?>==<;:987±|X.\v6v6v6u6u6u6u6t6{BSRQQPONMLKJJIHGFEEDCBA@?>==<;:987±|X.x6v6v6v6u6u6u6u6t6t6SRQQPONMLKJJIHGFEEDCBA@?>==<;:987Hƶ|X.лx6v6v6v6u6u6u6u6t6t6SRQQPONMLKJJIHGFEEDCBA@?>==<;:9876ɺ|X.Եx6v6v6v6u6u6u6u6t6t6βsRQQPONMLKJJIHGFEEDCBA@?>==<;:9876轫ŝnx6v6v6v6u6u6u6u6t6t6y>^QQPONMLKJJIHGFEEDCBA@?>==<;:9876]x6v6v6v6u6u6u6u6t6t6t6[|QPONMLKJJIHGFEEDCBA@?>==<;:9876y|||dddnnnOx6v6v6v6u6u6u6u6t6t6t6r6XrEBA@?>==<;:9876jdddvvv򿿿{{{dddzzzHx6v6v6v6u6u6u6u6t6t6t6r6r6t9ģ|Ѿ|A@?>==<;:9876pdddvvvhhhiiiVx6v6v6v6u6u6u6u6t6t6t6r6r6q6q6q6q6q6p6p6n6n6m6m6m6m6m6l6l6m8f@?>==<;:9876dddvvvdddÙhx6v6v6v6u6u6u6u6t6t6t6r6r6q6q6q6q6q6p6p6n6n6m6m6m6m6m6l6l6l6j6j6Ʈ?>==<;:9876dddvvvddd}}}άx6v6v6v6u6u6u6u6t6t6t6r6r6q6q6q6q6q6p6p6n6n6m6m6m6m6m6l6l6l6j6j6j6űM>==<;:9876dddvvvdddmmmǫx6v6v6v6u6u6u6u6t6t6t6r6r6q6q6q6q6q6p6p6n6n6m6m6m6m6m6l6l6l6j6j6j6xI>==<;:9876dddvvv٩鶶iiiddd󽽽ɧԭx6v6v6v6u6u6u6u6t6t6t6r6r6q6q6q6q6q6p6p6n6n6m6m6m6m6m6l6l6l6j6j6j6j6>==<;:987==<;:987pdddeeeyyydddddddddՇdddddd|||ddddddddddddqqqeeedddddddddϰv6v6v6u6u6u6u6t6t6t6r6r6q6q6q6q6q6p6p6n6n6m6m6m6m6m6l6l6l6j6j6j6j6¬>==<;:987dddvvvdddddddddddddddeeedddddddddddddddddddddddd~Bv6v6u6u6u6u6t6t6t6r6r6q6q6q6q6q6p6p6n6n6n6m6m6m6m6l6l6l6j6j6j6j6¬>==<;:98Ddddvvv{{{dddddddddddddddddddddddddddfffdddddd|||ddddddz;v6u6u6u6u6t6t6t6r6r6q6q6q6q6q6p6p6n6n6n6m6m6m6m6l6l6l6j6j6j6j6¬>==<;:98dddvvvddd}}}dddddddddddddddddddddddddddiiiddddddddddddͶPu6u6u6u6t6t6t6r6r6q6q6q6q6q6p6p6n6n6n6m6m6m6m6l6l6l6j6j6j6j6¬>==<;:9dddvvvdddqqqdddddddddddddddddddddddddddwwwddddddddddddм˫i^^^^^^^^^^^^^^^Ym6m6m6m6l6l6l6j6j6j6j6¬eddckdddvvvdddsssddddddddddddddddddddddddddd}}}ddddddddddddm6m6m6m6l6l6l6j6j6j6j6¬dddvvvddddddddddddddddddddddddddddddpppdddddddddddd¨llllllllllem6m6m6m6l6l6l6j6j6j6j6¬dddvvvddddddddddddddddddddddddddddddddddddkkkddddddʭr6q6q6q6q6q6p6p6n6n6n6m6m6m6m6l6l6l6j6j6j6j6¬dddvvveeeddddddddddddddddddddddddpppddd~~~ddddddddddddʭr6q6q6q6q6q6p6p6n6n6n6m6m6m6m6l6l6l6j6j6j6j6¬fffkkkddddddddddddddddddddddddeeedddhhhfffmmmdddrrrdddddddddʭr6q6x>īѸq7p6n6n6n6m6m6m6m6l6l6l6j6j6j6j6¬uuudddzzz}}}dddsssddddddddddddddddddddduuuddduuuiiidddeeeiiieeezzzdddttthhhpppddddddʭr6q6Ի¢~p6n6n6n6m6m6m6m6l6l6l6j6j6j6j6Űʟzzz⩩Өddddddddddddѭ騨zzz|||дr6q6ҿҺp6n6n6n6m6m6m6m6l6l6l6j6j6j6j6dddddddddddd©r6q6¡{]p6n6n6n6m6m6m6m6l6l6l6j6j6j6p?ddddddddddddt8q6q6f̰Xp6p6n6n6n6m6m6m6m6l6l6l6j6j6j6ʵddddddddddddѷq6q6q6q6q6p6p6n6n6n6m6m6m6m6l6l6l6j6j6yƐddddddκVq6q6q6p6p6n6n6n6m6m6m6m6l6l6l6sBнddddddĬǫmVxCt=n6m6wCzG]uƮ̻ddddddkkkbdist_nsi-0.1.5/bdist_nsi/python-install-150x57.bmp0000755000000000000000000006233212042736306020517 0ustar rootrootBMd6(9d  쾬{k[cm~õ}Y.qONMLKJJIHGFFvõ}Y.̾bQPONMLKJJIHGFEEDbɻ}Y.õSQQPONMLKJJIHGFHWDCM}Y.õ[RQQPONMLKJJIHGhJBc}Y.ôĵtչxƶ˸y²±{̽ʹ~SRQQPONMLKJJIHGBA}Y.`9rNya7e=ŵ~Z0sʻ]3pK~Z0y}Y.˽}Y.d±rNh}Y.҅b:iBkh@Ǹ~Z/gɺlG^SRQQPONMLKJJIHGBA}Y.Ԁ[1qL~Z/~}Y.}Y.}Y.̽e=}Y.}ɻ}Y.}Y.kFjC~[0ce~[0SRQQPONMLKJJIHGmLBA}Y.ɻp}Y.t}Y.h@qL±}Y.fl}Y.gg@d]3}Y.ŷ}Y.ŵ}Y.ʽx}Y.SRQQPONMLKJJIHGFMaFCBA}Y.ɻ²}Y.ójCa7k}Y.|\a9܁_4}Y.ԇg@b;qM}Y.}Y.l}Y.y}Y.SRQQPONMLKJJIHGFEEDCBA}Y.ŵ}Y.~Z/lG}Y.~Z0srN˽nHlG~[1qL}Y.}Y.{X}Y.}Y.SRQQPONMLKJJIHGFEEDCBA}Y.±ʻ}Y.b;g?~}Y.̽}Y.õ}Y.˽vSpK\2zWzWzWzWb:g?}Y.ij}Y.qLzWzWzWpL}Y.ɻm}Y.}Y.SRQQPONMLK\}Y.±}Y.f}Y.|[~Z0m[1ʇg@}Y.]3o^4cwT}Y.}Y.̾Ƹ}Y.}Y.ƶ}Y.ɯ־־սSRQQPONMLKU}Y.sO]3}Y.~Z/o_4eb;c==<;:Tse=˪v}Y.~Z/jEkF̾}Y.Ǹx}Y.zǸffjCʻΡf`9|[a7´ʽȸ~Z0Ĵ~Z/}Y.yű\2}Y.ȯy9w6v6v6u6u6t6{BSRQQPONMLKJJIHGFEEDCBA@?>==<;:9DŪwuQe>sOĴ{Ze=lGŘ{Xԡg̾曀^vTpKoõfa7~Z/ğfoJ{YǸʻuQc==<;:98q}Y.w6w6w6v6v6u6u6t6{BSRQQPONMLKJJIHGFEEDCBA@?>==<;:987±}Y.[w6w6w6v6v6u6u6t6{BSRQQPONMLKJJIHGFEEDCBA@?>==<;:987±}Y.x6w6w6w6v6v6u6u6t6t6SRQQPONMLKJJIHGFEEDCBA@?>==<;:987Gƶ}Y.ѻx6w6w6w6v6v6u6u6t6t6SRQQPONMLKJJIHGFEEDCBA@?>==<;:9876ɻ}Y.Եx6w6w6w6v6v6u6u6t6t6βrRQQPONMLKJJIHGFEEDCBA@?>==<;:9876羬ŝnx6w6w6w6v6v6u6u6t6t6y=]QQPONMLKJJIHGFEEDCBA@?>==<;:9876\x6w6w6w6v6v6u6u6t6t6t6[|QPONMLKJJIHGFEEDCBA@?>==<;:9876x|||dddmmmOx6w6w6w6v6v6u6u6t6t6t6s6XqDBA@?>==<;:9876jdddvvv񾾾{{{dddyyyGx6w6w6w6v6v6u6u6t6t6t6s6s6s8Ģ{Ѿ{A@?>==<;:9876odddvvvgggiiiVx6w6w6w6v6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6n6n6n6m6m6l6l6l7e@?>==<;:9876dddvvvdddÙhx6w6w6w6v6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6n6n6n6m6m6l6l6l6k6k6Ʈ?>==<;:9876dddvvvddd}}}άx6w6w6w6v6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6n6n6n6m6m6l6l6l6k6k6j6ŰL>==<;:9876dddvvvdddlllǫx6w6w6w6v6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6n6n6n6m6m6l6l6l6k6k6j6wH>==<;:9876dddvvvب赵iiiddd򽽽ɧԮx6w6w6w6v6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6n6n6n6m6m6l6l6l6k6k6j6j6>==<;:987;dddllldddqqqsssddddddgggdddeeeuuugggdddgggdddkkkeeedddddddddxxxddd{{{rrrdddddddddCw6w6w6v6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6n6n6n6m6m6l6l6l6k6k6j6j6ȶ>==<;:987odddeeexxxdddddddddՆdddddd|||ddddddddddddqqqeeedddddddddϰw6w6w6v6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6n6n6n6m6m6l6l6l6k6k6j6j6¬>==<;:987dddvvvdddddddddddddddeeedddddddddddddddddddddddd~Bw6w6v6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6o6n6n6m6m6l6l6l6k6k6j6j6¬>==<;:98Ddddvvv{{{dddddddddddddddddddddddddddeeedddddd|||ddddddy:w6v6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6o6n6n6m6m6l6l6l6k6k6j6j6¬>==<;:98dddvvvddd}}}dddddddddddddddddddddddddddiiidddddddddddd̷Ov6v6u6u6t6t6t6s6s6r6r6q6q6q6p6p6o6o6o6n6n6m6m6l6l6l6k6k6j6j6¬>==<;:9dddvvvdddqqqdddddddddddddddddddddddddddwwwddddddddddddѼ˫i]]]]]]]]]]]]]]]Yn6n6m6m6l6l6l6k6k6j6j6¬eddckdddvvvdddrrrddddddddddddddddddddddddddd}}}ddddddddddddn6n6m6m6l6l6l6k6k6j6j6¬dddvvvddddddddddddddddddddddddddddddpppdddddddddddd¨kkkkkkkkkkdn6n6m6m6l6l6l6k6k6j6j6¬dddvvvddddddddddddddddddddddddddddddddddddkkkddddddʭs6r6r6r6q6q6p6p6o6o6o6n6n6m6m6l6l6l6k6k6j6j6¬dddvvveeeddddddddddddddddddddddddpppddd}}}ddddddddddddʭs6r6r6r6q6q6p6p6o6o6o6n6n6m6m6l6l6l6k6k6j6j6¬eeekkkddddddddddddddddddddddddeeedddgggeeellldddqqqdddddddddʭs6r6x>īѸq7p6o6o6o6n6n6m6m6l6l6l6k6k6j6j6¬uuudddyyy}}}dddrrrddddddddddddddddddddduuuddduuuiiidddeeeiiieeeyyydddsssgggpppddddddʭs6r6Լã~p6o6o6o6n6n6m6m6l6l6l6k6k6j6j6ůʞyyyᨨӨddddddddddddЬ訨yyy|||ϴs6r6ҿҺp6o6o6o6n6n6m6m6l6l6l6k6k6j6j6dddddddddddd©s6r6â{]p6o6o6o6n6n6m6m6l6l6l6k6k6j6p>ddddddddddddt8r6r6f̰Xp6p6o6o6o6n6n6m6m6l6l6l6k6k6j6ʵddddddddddddѷr6r6r6q6q6p6p6o6o6o6n6n6m6m6l6l6l6k6k6xƐddddddκVr6q6q6p6p6o6o6o6n6n6m6m6l6l6l6sBнddddddĬǪmVxCt>> RegKey(view=32, root="HKLM", key=r"Software\BlenderFoundation", ... name="Install_Dir") RegKey(view=32, root='HKLM', key='Software\\BlenderFoundation', name='Install_Dir') """ return( "RegKey(view=%s, root=%s, key=%s, name=%s)" % (repr(self.view), repr(self.root), repr(self.key), repr(self.name))) class AppInfo: """Information of an application which integrates Python.""" name = None """Name of the application.""" version = None """The version of the application.""" label = None """A label which uniquely identifies the application.""" regkeys = None # list of registry keys """List of registry keys which are checked to determine whether the application is installed or not, and to get its installation path. """ py_version = None # 2.4, 2.5, ... """A string of the form 'x.x' which determines the Python version for this application. """ VERSIONS = [] """List of (version, py_version, bits) tuples.""" def __init__(self, name=None, label=None, regkeys=None, py_version=None): """Initialize application information.""" self.name = name self.label = label self.regkeys = regkeys self.py_version = py_version def __repr__(self): r"""Return string representation. >>> regkey = RegKey(view=32, root="HKLM", ... key=r"Software\BlenderFoundation", ... name="Install_Dir") >>> AppInfo(name="Test", label="test", regkeys=[regkey], ... py_version="3.2") AppInfo(name='Test', label='test', regkeys=[RegKey(view=32, root='HKLM', key='Software\\BlenderFoundation', name='Install_Dir')], py_version='3.2') """ return ( "AppInfo(name=%s, label=%s, regkeys=%s, py_version=%s)" % (repr(self.name), repr(self.label), repr(self.regkeys), repr(self.py_version))) @property def bits(self): """32 or 64. >>> PythonAppInfo(version="2.7", bits=64).bits 64 >>> PythonAppInfo(version="3.1", bits=32).bits 32 >>> MayaAppInfo(version="2009", py_version="2.5", bits=64).bits 64 >>> MayaAppInfo(version="2009", py_version="2.5", bits=32).bits 32 >>> BlenderAppInfo(version="2.4x", py_version="2.6", bits=64).bits 64 >>> BlenderAppInfo(version="2.4x", py_version="2.6", bits=32).bits 32 """ return max(regkey.view for regkey in self.regkeys) def macro_get_registry_keys(self): r"""Returns NSIS script which defines a macro which jumps to if_found if the registry key is found in any of the listed registry keys, storing the result in $PATH_${label}. >>> regkey1 = RegKey(view=32, root="HKLM", ... key=r"Software\BlenderFoundation", ... name="Install_Dir") >>> regkey2 = RegKey(view=64, root="HKCU", ... key=r"SOFTWARE\Autodesk\Maya\2008\Setup\InstallPath", ... name="MAYA_INSTALL_LOCATION") >>> regkey3 = RegKey(view=32, root="HKCR", ... key="NSIS.Header", ... name="DefaultIcon") >>> app = AppInfo(name="Test", label="test", ... regkeys=[regkey1, regkey2, regkey3], ... py_version='3.2') >>> print("\n".join(app.macro_get_registry_keys())) !macro GET_REGISTRY_KEYS_test if_found !insertmacro GET_REGISTRY_KEY $PATH_test 32 HKLM "Software\BlenderFoundation" "Install_Dir" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_test 64 HKCU "SOFTWARE\Autodesk\Maya\2008\Setup\InstallPath" "MAYA_INSTALL_LOCATION" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_test 32 HKCR "NSIS.Header" "DefaultIcon" ${if_found} !macroend """ yield "!macro GET_REGISTRY_KEYS_%s if_found" % self.label for regkey in self.regkeys: yield ( ' !insertmacro GET_REGISTRY_KEY $PATH_%s %s %s "%s" "%s"' ' ${if_found}' % (self.label, regkey.view, regkey.root, regkey.key, regkey.name)) yield "!macroend" def macro_get_path_extra_check(self): """Returns NSIS script which validates a given path.""" # default: do nothing return def insertmacro_variables(self): """Define variables.""" yield "var PATH_%s" % self.label def macro_section_extra(self): """Define section install variables $0 to $5 (see the implementation of PythonAppInfo.macro_section_extra for an example). """ raise NotImplementedError @staticmethod def make_version_bits_tuples(versions, bits=None): """Convert string versions into tuple versions. >>> list(AppInfo.make_version_bits_tuples(["2.5", "3.1"])) [('2.5', 32), ('2.5', 64), ('3.1', 32), ('3.1', 64)] >>> list(AppInfo.make_version_bits_tuples(["2.5", "3.1"], bits=64)) [('2.5', 64), ('3.1', 64)] """ for version in versions: if bits is None: for bits_ in [32, 64]: yield version, bits_ else: yield version, bits @classmethod def make_apps(cls, versions, bits=None): """Get all applications of maya that match given python versions, which is a list of the form ["2.3", "2.4"] etc. >>> MayaAppInfo.make_apps(["2.6"]) [MayaAppInfo(version='2010', py_version='2.6', bits=32), MayaAppInfo(version='2010', py_version='2.6', bits=64)] >>> BlenderAppInfo.make_apps(["2.6"]) [BlenderAppInfo(version='2.4x', py_version='2.6', bits=32)] """ version_bits = list( cls.make_version_bits_tuples(versions, bits)) return [ cls(*args) for args in cls.VERSIONS if tuple(args[-2:]) in version_bits] class PythonAppInfo(AppInfo): r"""Python application info. >>> print("\n".join(PythonAppInfo(version="2.5", bits=32).macro_get_registry_keys())) !macro GET_REGISTRY_KEYS_python_2_5_32 if_found !insertmacro GET_REGISTRY_KEY $PATH_python_2_5_32 32 HKLM "SOFTWARE\Python\PythonCore\2.5\InstallPath" "" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_python_2_5_32 32 HKCU "SOFTWARE\Python\PythonCore\2.5\InstallPath" "" ${if_found} !macroend """ def __init__(self, version=None, bits=None): r"""Constructor. >>> print(AppInfo.__repr__(PythonAppInfo(version="2.7", bits=64))) AppInfo(name='Python 2.7 (64 bit)', label='python_2_7_64', regkeys=[RegKey(view=64, root='HKLM', key='SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath', name=''), RegKey(view=64, root='HKCU', key='SOFTWARE\\Python\\PythonCore\\2.7\\InstallPath', name='')], py_version='2.7') >>> PythonAppInfo(version="2.7", bits=64).py_version '2.7' """ self.py_version = version self.name = "Python %s (%i bit)" % (self.py_version, bits) self.label = "python_%s_%i" % (self.py_version.replace(".", "_"), bits) key = r"SOFTWARE\Python\PythonCore\%s\InstallPath" % self.py_version self.regkeys = [ RegKey(view=bits, root="HKLM", key=key, name=""), RegKey(view=bits, root="HKCU", key=key, name=""), ] def __repr__(self): """String representation. >>> PythonAppInfo(version="2.7", bits=64) PythonAppInfo(version='2.7', bits=64) """ return ("PythonAppInfo(version=%s, bits=%i)" % (repr(self.py_version), self.bits)) @classmethod def make_apps(cls, versions=None, bits=None): """Get all applications of python that match versions, which is a list of the form ["2.3", "2.4"] etc. >>> PythonAppInfo.make_apps(["2.1", "2.2"]) [PythonAppInfo(version='2.1', bits=32), PythonAppInfo(version='2.1', bits=64), PythonAppInfo(version='2.2', bits=32), PythonAppInfo(version='2.2', bits=64)] >>> PythonAppInfo.make_apps(["2.3", "3.0"], bits=32) [PythonAppInfo(version='2.3', bits=32), PythonAppInfo(version='3.0', bits=32)] """ version_bits = cls.make_version_bits_tuples(versions, bits) return [PythonAppInfo(version=version, bits=bits) for version, bits in version_bits] def macro_get_path_extra_check(self): """Returns NSIS script which validates the python path.""" yield '!macro GET_PATH_EXTRA_CHECK_%s' % self.label yield ' !insertmacro GET_PATH_EXTRA_CHECK_PYTHON %s' % self.label yield '!macroend' def macro_section_extra(self): """Returns NSIS script which sets up the installation variables in the section definition. """ yield '!macro SECTION_EXTRA_%s' % self.label yield (' !insertmacro SECTION_EXTRA_PYTHON %s %s' % (self.label, self.py_version)) yield '!macroend' class MayaAppInfo(AppInfo): r"""Maya application info. >>> print("\n".join(MayaAppInfo(version=2008, py_version="2.5", bits=32).macro_get_registry_keys())) !macro GET_REGISTRY_KEYS_maya_2008_32 if_found !insertmacro GET_REGISTRY_KEY $PATH_maya_2008_32 32 HKLM "SOFTWARE\Autodesk\Maya\2008\Setup\InstallPath" "MAYA_INSTALL_LOCATION" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_maya_2008_32 32 HKCU "SOFTWARE\Autodesk\Maya\2008\Setup\InstallPath" "MAYA_INSTALL_LOCATION" ${if_found} !macroend >>> print("\n".join(MayaAppInfo(version=2008, py_version="2.5", bits=64).macro_get_registry_keys())) !macro GET_REGISTRY_KEYS_maya_2008_64 if_found !insertmacro GET_REGISTRY_KEY $PATH_maya_2008_64 32 HKLM "SOFTWARE\Autodesk\Maya\2008-x64\Setup\InstallPath" "MAYA_INSTALL_LOCATION" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_maya_2008_64 32 HKCU "SOFTWARE\Autodesk\Maya\2008-x64\Setup\InstallPath" "MAYA_INSTALL_LOCATION" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_maya_2008_64 64 HKLM "SOFTWARE\Autodesk\Maya\2008-x64\Setup\InstallPath" "MAYA_INSTALL_LOCATION" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_maya_2008_64 64 HKCU "SOFTWARE\Autodesk\Maya\2008-x64\Setup\InstallPath" "MAYA_INSTALL_LOCATION" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_maya_2008_64 64 HKLM "SOFTWARE\Autodesk\Maya\2008\Setup\InstallPath" "MAYA_INSTALL_LOCATION" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_maya_2008_64 64 HKCU "SOFTWARE\Autodesk\Maya\2008\Setup\InstallPath" "MAYA_INSTALL_LOCATION" ${if_found} !macroend """ VERSIONS = [ ("2008", "2.5", 32), ("2008", "2.5", 64), ("2009", "2.5", 32), ("2009", "2.5", 64), ("2010", "2.6", 32), ("2010", "2.6", 64), ("2011", "2.6", 32), ("2011", "2.6", 64), ] """All versions of maya, as (version, py_version, bits).""" def __init__(self, version=None, py_version=None, bits=None): self.version = version self.py_version = py_version self.name = "Maya %s (%i bit)" % (version, bits) self.label = "maya_%s_%i" % (version, bits) key = ( r"SOFTWARE\Autodesk\Maya\%s\Setup\InstallPath" % version) key_x64 = ( r"SOFTWARE\Autodesk\Maya\%s-x64\Setup\InstallPath" % version) name = "MAYA_INSTALL_LOCATION" if bits == 32: self.regkeys = [ RegKey(view=bits, root="HKLM", key=key, name=name), RegKey(view=bits, root="HKCU", key=key, name=name), ] else: self.regkeys = [ RegKey(view=32, root="HKLM", key=key_x64, name=name), RegKey(view=32, root="HKCU", key=key_x64, name=name), RegKey(view=64, root="HKLM", key=key_x64, name=name), RegKey(view=64, root="HKCU", key=key_x64, name=name), RegKey(view=64, root="HKLM", key=key, name=name), RegKey(view=64, root="HKCU", key=key, name=name), ] def __repr__(self): """String representation. >>> MayaAppInfo(version="2009", py_version="2.5", bits=64) MayaAppInfo(version='2009', py_version='2.5', bits=64) """ return ("MayaAppInfo(version=%s, py_version=%s, bits=%i)" % (repr(self.version), repr(self.py_version), self.bits)) def macro_get_path_extra_check(self): """Returns NSIS script which validates the python path.""" yield '!macro GET_PATH_EXTRA_CHECK_%s' % self.label yield ' !insertmacro GET_PATH_EXTRA_CHECK_MAYA %s' % self.label yield '!macroend' def macro_section_extra(self): """Returns NSIS script which sets up the installation variables in the section definition. """ yield '!macro SECTION_EXTRA_%s' % self.label yield (' !insertmacro SECTION_EXTRA_MAYA %s %s' % (self.label, self.py_version)) yield '!macroend' class BlenderAppInfo(AppInfo): r"""Blender application info. >>> print("\n".join(BlenderAppInfo(version="2.4x", py_version="2.6", bits=32).macro_get_registry_keys())) !macro GET_REGISTRY_KEYS_blender_2_4x_2_6_32 if_found !insertmacro GET_REGISTRY_KEY $PATH_blender_2_4x_2_6_32 32 HKLM "SOFTWARE\BlenderFoundation" "Install_Dir" ${if_found} !insertmacro GET_REGISTRY_KEY $PATH_blender_2_4x_2_6_32 32 HKCU "SOFTWARE\BlenderFoundation" "Install_Dir" ${if_found} !macroend """ VERSIONS = [ ("2.4x", "2.3", 32), ("2.4x", "2.4", 32), ("2.4x", "2.5", 32), ("2.4x", "2.6", 32), ] """All versions of blender, as (version, py_version, bits).""" def __init__(self, version=None, py_version=None, bits=None): self.version = version self.name = ("Blender %s (Python %s, %i bit)" % (version, py_version, bits)) self.label = (("blender_%s_%s_%i" % (version, py_version, bits)) .replace(".", "_")) self.py_version = py_version key = r"SOFTWARE\BlenderFoundation" name = r"Install_Dir" self.regkeys = [ RegKey(view=bits, root="HKLM", key=key, name=name), RegKey(view=bits, root="HKCU", key=key, name=name), ] def __repr__(self): """String representation. >>> BlenderAppInfo(version="2.4x", py_version="2.6", bits=64) BlenderAppInfo(version='2.4x', py_version='2.6', bits=64) """ return ("%s(version=%s, py_version=%s, bits=%s)" % (self.__class__.__name__, repr(self.version), repr(self.py_version), repr(self.bits))) def insertmacro_variables(self): """Define variables.""" yield "var PATH_%s" % self.label yield "var SCRIPTS_%s" % self.label def macro_get_path_extra_check(self): """Returns NSIS script which validates the python path.""" yield '!macro GET_PATH_EXTRA_CHECK_%s' % self.label yield (' !insertmacro GET_PATH_EXTRA_CHECK_BLENDER %s %s' % (self.label, self.py_version)) yield '!macroend' def macro_section_extra(self): """Returns NSIS script which sets up the installation variables in the section definition. """ yield '!macro SECTION_EXTRA_%s' % self.label yield (' !insertmacro SECTION_EXTRA_BLENDER %s %s' % (self.label, self.py_version)) yield '!macroend' @staticmethod def insertmacro_push_blender_python_version(target_versions): """Push the python version, for use in the CHECK_BLENDER_PYTHON_VERSION macro. """ if not target_versions: raise ValueError( "target_versions must contain at least one element") yield ' ; note: if user installs a newer version of Blender over' yield ' ; an older version then two python dll files could co-exist;' yield ' ; therefore, check the higher version numbers first' versions = sorted(target_versions, reverse=True) yield (' ${If} ${FileExists} "$PATH_${label}\python%s.dll"' % versions[0].replace(".", "")) yield ' Push "%s"' % versions[0] for version in versions[1:]: yield (' ${ElseIf} ${FileExists} "$PATH_${label}\python%s.dll"' % version.replace(".", "")) yield ' Push "%s"' % version yield ' ${Else}' yield ' Push ""' yield ' ${EndIf}' # blender versions from 25x onwards embed python class Blender25xAppInfo(BlenderAppInfo): VERSIONS = [ ("2.59", "3.2", 32), ("2.59", "3.2", 64), ("2.60", "3.2", 32), ("2.60", "3.2", 64), ("2.61", "3.2", 32), ("2.61", "3.2", 64), ("2.62", "3.2", 32), ("2.62", "3.2", 64), ("2.63", "3.2", 32), ("2.63", "3.2", 64), ("2.64", "3.2", 32), ("2.64", "3.2", 64), ] """All versions of blender, as (version, py_version, bits).""" def insertmacro_variables(self): """Define variables.""" return AppInfo.insertmacro_variables(self) # only PATH_${label} def macro_get_path_extra_check(self): """Returns NSIS script which validates the python path.""" yield '!macro GET_PATH_EXTRA_CHECK_%s' % self.label yield (' !insertmacro GET_PATH_EXTRA_CHECK_BLENDER_25X %s %s %s' % (self.label, self.py_version, self.version)) yield '!macroend' def macro_section_extra(self): """Returns NSIS script which sets up the installation variables in the section definition. """ yield '!macro SECTION_EXTRA_%s' % self.label yield (' !insertmacro SECTION_EXTRA_BLENDER_25X %s %s %s' % (self.label, self.py_version, self.version)) yield '!macroend' class bdist_nsi(Command): description = "create an executable installer for MS Windows, using NSIS" user_options = [('bdist-dir=', None, "temporary directory for creating the distribution"), ('plat-name=', 'p', "platform name to embed in generated filenames " "(default: %s)" % get_platform()), ('keep-temp', 'k', "keep the pseudo-installation tree around after " + "creating the distribution archive"), ('target-version=', None, "require a specific python version" + " on the target system"), ('no-target-compile', 'c', "do not compile .py to .pyc on the target system"), ('no-target-optimize', 'o', "do not compile .py to .pyo (optimized)" "on the target system"), ('dist-dir=', 'd', "directory to put final built distributions in"), ('nsis-dir=', 'n', "directory of nsis compiler"), ('bitmap=', 'b', "bitmap (size 164x314) to use for the " + "installer instead of python-powered logo"), ('headerbitmap=', None, "header bitmap (size 150x57) to use for the " + "installer instead of python-powered logo"), ('title=', 't', "title to display on the installer background instead of default"), ('skip-build', None, "skip rebuilding everything (for testing/debugging)"), ('run2to3', None, "run 2to3 on 3.x installs"), ('msvc2005', None, "check if msvc 2005 redistributable package is installed"), ('msvc2005sp1', None, "check if msvc 2005 sp1 redistributable package is installed"), ('msvc2008', None, "check if msvc 2008 redistributable package is installed"), ('msvc2008sp1', None, "check if msvc 2008 sp1 redistributable package is installed"), ('nshextra=', None, "additional nsis header file to include at the start of the file, and which must define the following macros (they can be empty if not used): InstallFilesExtra, UninstallFilesExtra, PostExtra, and UnPostExtra"), ('target-versions=', None, "comma separated list of python versions (only for pure packages)"), ('maya', None, "include (compatible) Maya targets in installer"), ('blender', None, "include (compatible) Blender targets in installer"), ('debug', None, "debug mode (only use if you know what you are doing)"), ('productkey=', None, "product key" " used for install registry key" " and install folder; useful for allowing" " different versions" " of the same package installed simultaneously"), ] boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize', 'skip-build', 'run2to3', 'msvc2005', 'msvc2005sp1', 'msvc2008', 'msvc2008sp1', 'maya', 'blender', 'debug'] def initialize_options (self): self.bdist_dir = None self.plat_name = None self.keep_temp = 0 self.no_target_compile = 0 self.no_target_optimize = 0 self.target_version = None self.dist_dir = None self.nsis_dir = None self.bitmap = None self.headerbitmap = None self.title = None self.skip_build = 0 self.run2to3 = 0 self.msvc2005 = 0 self.msvc2005sp1 = 0 self.msvc2008 = 0 self.msvc2008sp1 = 0 self.nshextra = None self.target_versions = None self.maya = 0 self.blender = 0 self.debug = 0 self.productkey = None # initialize_options() def finalize_options (self): if self.bdist_dir is None: if self.skip_build and self.plat_name: # If build is skipped and plat_name is overridden, bdist will # not see the correct 'plat_name' - so set that up manually. bdist = self.distribution.get_command_obj('bdist') bdist.plat_name = self.plat_name # next the command will be initialized using that name bdist_base = self.get_finalized_command('bdist').bdist_base self.bdist_dir = os.path.join(bdist_base, 'nsi') if not self.target_version: self.target_version = "" if not self.skip_build and self.distribution.has_ext_modules(): short_version = get_python_version() if self.target_version and self.target_version != short_version: raise DistutilsOptionError("target version can only be %s, or the '--skip_build'" \ " option must be specified" % (short_version,)) self.target_version = short_version # find makensis executable if self.nsis_dir is None: pathlist = os.environ.get('PATH', os.defpath).split(os.pathsep) # common locations pathlist.extend([ ".", "C:\\Program Files\\NSIS", "C:\\Program Files (x86)\\NSIS"]) else: pathlist = [self.nsis_dir] for path in pathlist: # windows executable? makensis = os.path.join(path, "makensis.exe") if os.access(makensis, os.X_OK): self.nsis_dir = makensis break # linux executable? (for instance on Fedora 11) makensis = os.path.join(path, "makensis") if os.access(makensis, os.X_OK): self.nsis_dir = makensis break else: print( "Error: makensis executable not found, " "add NSIS directory to the path or specify it " "with --nsis-dir") self.nsis_dir = None if not self.headerbitmap: self.headerbitmap = os.path.join(os.path.dirname(__file__), "python-install-150x57.bmp").replace("/", "\\") else: self.headerbitmap = self.abspath(self.headerbitmap) if not self.bitmap: self.bitmap = os.path.join(os.path.dirname(__file__), "python-install-164x314.bmp").replace("/", "\\") else: self.bitmap = self.abspath(self.bitmap) if self.nshextra: self.nshextra = self.abspath(self.nshextra) self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'), ('plat_name', 'plat_name'), ('nsis_dir', 'nsis_dir'), ) # finalize_options() def abspath(self, filename): # absolute path with windows separator return os.path.abspath(filename).replace('/', '\\') def run (self): if (sys.platform != "win32" and (self.distribution.has_ext_modules() or self.distribution.has_c_libraries())): raise DistutilsPlatformError \ ("distribution contains extensions and/or C libraries; " "must be compiled on a Windows 32 platform") if not self.skip_build: self.run_command('build') install = self.reinitialize_command('install', reinit_subcommands=1) install.root = self.bdist_dir install.skip_build = self.skip_build install.warn_dir = 0 install.plat_name = self.plat_name install_lib = self.reinitialize_command('install_lib') # we do not want to include pyc or pyo files install_lib.compile = 0 install_lib.optimize = 0 if self.distribution.has_ext_modules(): # If we are building an installer for a Python version other # than the one we are currently running, then we need to ensure # our build_lib reflects the other Python version rather than ours. # Note that for target_version!=sys.version, we must have skipped the # build step, so there is no issue with enforcing the build of this # version. target_version = self.target_version if not target_version: assert self.skip_build, "Should have already checked this" target_version = sys.version[0:3] plat_specifier = ".%s-%s" % (self.plat_name, target_version) build = self.get_finalized_command('build') build.build_lib = os.path.join(build.build_base, 'lib' + plat_specifier) # use windows installation scheme for key in WINDOWS_SCHEME.keys(): value = WINDOWS_SCHEME[key].replace("$base", "_python") setattr(install, 'install_' + key, value) log.info("installing to %s", self.bdist_dir) install.ensure_finalized() install.run() self.build_nsi() if not self.keep_temp: remove_tree(self.bdist_dir, dry_run=self.dry_run) # run() def build_nsi(self): if self.target_version.upper() not in ["","ANY"]: nsiscript = get_nsi(target_versions=[self.target_version]) elif self.target_versions: nsiscript = get_nsi(target_versions=self.target_versions.split(",")) elif sys.version_info[0] < 3: # python 2.x target_versions = ["2.3", "2.4", "2.5", "2.6", "2.7"] if self.run2to3: target_versions.extend(["3.0", "3.1", "3.2"]) nsiscript = get_nsi(target_versions=target_versions) else: # python 3.x target_versions = ["3.0", "3.1", "3.2"] # disable 2to3 self.run2to3 = 0 nsiscript = get_nsi(target_versions=target_versions) metadata = self.distribution.metadata def get_full_author(key): # full author and maintainer info? author = key author_email = "%s_email" % author if (getattr(metadata, author, "") and getattr(metadata, author_email, "")): return '@%s@ <@%s@>' % (author, author_email) elif getattr(metadata, author, ""): return '@%s@' % author elif getattr(metadata, author_email, ""): return '@%s@' % author_email else: return '' annotated_author = get_full_author("author") if annotated_author: nsiscript = nsiscript.replace( "@annotated_author@", "Author: %s$\\r$\\n" % annotated_author) annotated_maintainer = get_full_author("maintainer") if annotated_maintainer: nsiscript = nsiscript.replace( "@annotated_maintainer@", "Maintainer: %s$\\r$\\n" % annotated_maintainer) for name in ["author", "author_email", "maintainer", "maintainer_email", "description", "name", "url", "version", "license"]: data = getattr(metadata, name, "") if data: nsiscript = nsiscript.replace('@has'+name+'@', "") nsiscript = nsiscript.replace('@'+name+'@',data) nsiscript = nsiscript.replace( '@annotated_'+name+'@', "%s: %s$\\r$\\n" % (name.replace("_", " ").capitalize(), data)) else: nsiscript = nsiscript.replace( '@annotated_'+name+'@', '') nsiscript = nsiscript.replace('@has'+name+'@', ";") # XXX todo: use the moduleinfo file in the installer? for licensefile in ['license', 'license.txt', 'license.rst', 'LICENSE', 'LICENSE.txt', 'LICENSE.rst', 'LICENSE.TXT', 'LICENSE.RST']: if os.path.exists(licensefile): nsiscript=nsiscript.replace('@haslicensefile@', "") nsiscript=nsiscript.replace('@licensefile@', self.abspath(licensefile)) break else: nsiscript=nsiscript.replace('@haslicensefile@', ";") if self.target_version: installer_path = os.path.join(self.dist_dir, "%s.win32-py%s.exe" % (self.distribution.get_fullname(), self.target_version)) else: installer_path = os.path.join(self.dist_dir, "%s.win32.exe" % self.distribution.get_fullname()) installer_path = self.abspath(installer_path) nsiscript=nsiscript.replace('@installer_path@',installer_path) haspythonversion=";" if self.target_version.upper() not in ["","ANY"]: nsiscript=nsiscript.replace('@pythonversion@',self.target_version) haspythonversion="" nsiscript=nsiscript.replace('@haspythonversion@',haspythonversion) files=[] for dirpath, dirnames, filenames in os.walk(self.bdist_dir+os.sep+'_python'): self.visit(files, dirpath, filenames) # install folders and files (as nsis commands) _f_packages=[] _f_scripts=[] _f_include=[] # delete files (as nsis commands) _d_packages=[] _d_scripts=[] _d_include=[] # folders for recursive delete (as strings, for compiling and cleaning) _r_packages=[] _r_scripts=[] _r_include=[] lastdir="" for each in files: # skip egg info files if each[1].endswith(".egg-info"): continue if each[1].lower().startswith("lib\\site-packages\\"): outpath = "$3\\%s" % each[0][18:] outfile = "$3\\%s" % each[1][18:] _f = _f_packages _d = _d_packages _r = _r_packages elif each[1].lower().startswith("scripts\\"): outpath = "$4\\%s" % each[0][8:] outfile = "$4\\%s" % each[1][8:] _f = _f_scripts _d = _d_scripts _r = _r_scripts elif each[1].lower().startswith("include\\"): outpath = "$5\\%s" % each[0][8:] outfile = "$5\\%s" % each[1][8:] _f = _f_include _d = _d_include _r = _r_include else: log.warn("warning: ignoring %s" % each[1]) continue # find root directories and root files components = outfile.split("\\") # components[1] can be empty in case of e.g. "$4\\" if len(components) >= 2 and components[1]: root = "\\".join(components[:2]) if len(components) >= 3: root = root + "\\" # folder! if root not in _r: _r.append(root) if lastdir != each[0]: lastdir=each[0] _f.append(' SetOutPath "%s"\n' % outpath) _f.append(' File "_python\\'+each[1]+'\"\n') _d.append(' Delete "%s"\n' % outfile) if outfile.lower().endswith(".py"): _d.append(' Delete "%so"\n' % outfile) _d.append(' Delete "%sc"\n' % outfile) # remove folders for _d, _r, tag in zip([_d_packages, _d_scripts, _d_include], [_r_packages, _r_scripts, _r_include], ['packages', 'scripts', 'include']): _d.append(' ; cleaning folders\n') for root in _r: if root.endswith("\\"): _d.append(' RmDir /r "%s"\n' % root) # 2to3, compile, optimize for _f, _r, tag in zip([_f_packages, _f_scripts], [_r_packages, _r_scripts], ['packages', 'scripts']): if not _r: continue # 2to3 _f.append(' !ifdef MISC_2TO3\n') _f.append(' Push $9\n') _f.append(' StrCmp $0 "" end_2to3_%s 0 ; only run if we have a full python install\n' % tag) _f.append(' StrCmp $1 "" end_2to3_%s 0 ; only run if we have an executable\n' % tag) _f.append(' StrCpy $9 "$2" 1\n') _f.append(' StrCmp $9 "3" 0 end_2to3_%s\n' % tag) _f.append(' SetOutPath "$0"\n') for root in _r: _f.append(""" nsExec::ExecToLog "$1 $\\"$0\\Tools\\Scripts\\2to3.py$\\" -w -n $\\"%s$\\""\n""" % root.rstrip("\\")) _f.append('end_2to3_%s:\n' % tag) _f.append(' Pop $9\n') _f.append(' !endif\n') # compile modules _f.append(' !ifdef MISC_COMPILE\n') _f.append(' StrCmp $0 "" end_compile_%s 0 ; only run if we have a full python install\n' % tag) _f.append(' StrCmp $1 "" end_compile_%s 0 ; only run if we have an executable\n' % tag) _f.append(' SetOutPath "$0"\n') for root in _r: if root.endswith("\\"): _f.append(""" nsExec::ExecToLog "$1 -c $\\"import compileall; compileall.compile_dir('%s')$\\""\n""" % root.replace("\\", "\\\\")) else: _f.append(""" nsExec::ExecToLog "$1 -c $\\"import py_compile; py_compile.compile('%s')$\\""\n""" % root.replace("\\", "\\\\")) _f.append('end_compile_%s:\n' % tag) _f.append(' !endif\n') _f.append(' !ifdef MISC_OPTIMIZE\n') _f.append(' StrCmp $0 "" end_optimize_%s 0 ; only run if we have a full python install\n' % tag) _f.append(' StrCmp $1 "" end_optimize_%s 0 ; only run if we have an executable\n' % tag) _f.append(' SetOutPath "$0"\n') for root in _r: if root.endswith("\\"): _f.append(""" nsExec::ExecToLog "$1 -OO -c $\\"import compileall; compileall.compile_dir('%s')$\\""\n""" % root.replace("\\", "\\\\")) else: _f.append(""" nsExec::ExecToLog "$1 -OO -c $\\"import py_compile; py_compile.compile('%s')$\\""\n""" % root.replace("\\", "\\\\")) _f.append('end_optimize_%s:\n' % tag) _f.append(' !endif\n') _f = [] _f.append(' ; packages\n') _f.append(' StrCmp $3 "" end_packages 0\n') _f += _f_packages _f.append('end_packages:\n\n') _f.append(' ; scripts\n') _f.append(' StrCmp $4 "" end_scripts 0\n') _f += _f_scripts _f.append('end_scripts:\n\n') _f.append(' ; headers\n') _f.append(' StrCmp $5 "" end_include 0\n') _f += _f_include _f.append('end_include:\n\n') _d = [] _d.append(' ; packages\n') _d.append(' StrCmp $3 "" end_clean_packages 0\n') _d += _d_packages _d.append(' Delete "$3\\${PRODUCT_NAME}*.egg-info"\n') _d.append('end_clean_packages:\n\n') _d.append(' ; scripts\n') _d.append(' StrCmp $4 "" end_clean_scripts 0\n') _d += _d_scripts _d.append('end_clean_scripts:\n\n') _d.append(' ; headers\n') _d.append(' StrCmp $5 "" end_clean_include 0\n') _d += _d_include _d.append('end_clean_include:\n\n') _d.append(' ; remove clutter\n') _d.append(' StrCmp $0 "" end_clean_clutter 0\n') _d.append(' Delete "$0\\Remove${PRODUCT_NAME}.*"\n') _d.append(' Delete "$0\\${PRODUCT_NAME}-wininst.log"\n') _d.append('end_clean_clutter:\n\n') nsiscript=nsiscript.replace('@_files@',''.join(_f)) nsiscript=nsiscript.replace('@_deletefiles@',''.join(_d)) abs_py_dir = os.path.abspath(self.bdist_dir+os.sep+'_python') if not self.no_target_compile: nsiscript=nsiscript.replace('@compile@','') print(sys.executable + ' -c "import compileall; compileall.compile_dir(\'%s\')"' % (abs_py_dir.replace('\\', '\\\\'))) # compile folder - for size calculation below subprocess.call([sys.executable, '-c', 'import compileall; compileall.compile_dir(\'%s\')' % (abs_py_dir.replace('\\', '\\\\'))]) else: nsiscript=nsiscript.replace('@compile@',';') if not self.no_target_optimize: nsiscript=nsiscript.replace('@optimize@','') # compile folder - for size calculation below subprocess.call([sys.executable, '-OO', '-c', 'import compileall; compileall.compile_dir(\'%s\')' % (abs_py_dir.replace('\\', '\\\\'))]) else: nsiscript=nsiscript.replace('@optimize@',';') # get total size def round4k(x): """Round number up to closest 4k boundary (disk space is allocated in chunks of 4k so this 'fixes' the file size). """ return (1 + (x // 4096)) * 4096 pysize = sum( sum(round4k(os.path.getsize(os.path.join(dirpath, filename))) for filename in filenames) for dirpath, dirnames, filenames in os.walk(self.bdist_dir+os.sep+'_python')) nsiscript=nsiscript.replace('@pysizekb@', str(1 + (pysize // 1000))) if self.run2to3: nsiscript=nsiscript.replace('@2to3@','') else: nsiscript=nsiscript.replace('@2to3@',';') if self.msvc2005: nsiscript=nsiscript.replace('@msvc2005@','') else: nsiscript=nsiscript.replace('@msvc2005@',';') if self.msvc2005sp1: nsiscript=nsiscript.replace('@msvc2005sp1@','') else: nsiscript=nsiscript.replace('@msvc2005sp1@',';') if self.msvc2008: nsiscript=nsiscript.replace('@msvc2008@','') else: nsiscript=nsiscript.replace('@msvc2008@',';') if self.msvc2008sp1: nsiscript=nsiscript.replace('@msvc2008sp1@','') else: nsiscript=nsiscript.replace('@msvc2008sp1@',';') if self.nshextra: nsiscript=nsiscript.replace('@hasnshextra@','') nsiscript=nsiscript.replace('@nshextra@', self.nshextra) else: nsiscript=nsiscript.replace('@hasnshextra@',';') if self.maya: nsiscript=nsiscript.replace('@maya@','') else: nsiscript=nsiscript.replace('@maya@',';') if self.blender: nsiscript=nsiscript.replace('@blender@','') else: nsiscript=nsiscript.replace('@blender@',';') if self.debug: nsiscript=nsiscript.replace('@debug@','') else: nsiscript=nsiscript.replace('@debug@',';') nsiscript = nsiscript.replace("@srcdir@", self.abspath(os.getcwd())) if not self.productkey: nsiscript = nsiscript.replace('@key@', '') else: nsiscript = nsiscript.replace('@key@', '-' + self.productkey) # icon files # XXX todo: make icons configurable nsiscript = nsiscript.replace( "@ico_install@", self.abspath(os.path.join(os.path.dirname(__file__), "python-install.ico"))) nsiscript = nsiscript.replace( "@ico_uninstall@", self.abspath(os.path.join(os.path.dirname(__file__), "python-uninstall.ico"))) nsiscript = nsiscript.replace("@header_bitmap@", self.headerbitmap) nsiscript = nsiscript.replace("@welcome_bitmap@", self.bitmap) nsifile=open(os.path.join(self.bdist_dir,'setup.nsi'),'wt') nsifile.write(nsiscript) nsifile.close() self.compile() def visit(self,arg,dir,fil): for each in fil: if not os.path.isdir(dir+os.sep+each): f=str(dir+os.sep+each)[len(self.bdist_dir+os.sep+'_python'+os.sep):] # replace / by \\ so it works on linux too arg.append([os.path.dirname(f).replace("/", "\\"), f.replace("/", "\\")]) def compile(self): if self.nsis_dir is not None: # create destination directory # (nsis complains if it does not yet exist) self.mkpath(self.dist_dir) try: spawn([os.path.join(self.nsis_dir), os.path.join(self.bdist_dir, 'setup.nsi')]) except: print("Warning: possible error during NSIS compilation.") # class bdist_nsi def get_nsi(target_versions=None, bits=None): # list all applications python_apps = PythonAppInfo.make_apps(target_versions, bits) maya_apps = MayaAppInfo.make_apps(target_versions, bits) blender_apps = ( BlenderAppInfo.make_apps(target_versions, bits) + Blender25xAppInfo.make_apps(target_versions, bits) ) NSI_HEADER = r"""\ ; @name@ self-installer for Windows ; (@name@ - @url@) ; (NSIS - http://nsis.sourceforge.net) ; Define Application Specific Constants ; ===================================== !define PRODUCT_NAME "@name@" !define PRODUCT_KEY "@key@" !define PRODUCT_VERSION "@version@" !define PRODUCT_PUBLISHER "@author@ <@author_email@>" !define PRODUCT_WEB_SITE "@url@" !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}${PRODUCT_KEY}" !define PRODUCT_UNINST_ROOT_KEY "HKLM" !define PRODUCT_UNINST_REG_VIEW 32 !define MISC_SRCDIR "@srcdir@" !define MISC_PYSIZEKB "@pysizekb@" @compile@!define MISC_COMPILE "1" @optimize@!define MISC_OPTIMIZE "1" @2to3@!define MISC_2TO3 "1" @msvc2005@!define MISC_MSVC2005 "1" @msvc2005sp1@!define MISC_MSVC2005SP1 "1" @msvc2008@!define MISC_MSVC2008 "1" @msvc2008sp1@!define MISC_MSVC2008SP1 "1" @maya@!define MISC_MAYA "1" @blender@!define MISC_BLENDER "1" @hasurl@BrandingText "@url@" @hasnshextra@!define MISC_NSHEXTRA "1" @debug@!define MISC_DEBUG "1" !ifdef MISC_BLENDER | MISC_MSVC2005 | MISC_MSVC2005SP1 | MISC_MSVC2008 | MISC_MSVC2008SP1 !define REQUIREOPENLINKNEWWINDOW "1" !endif ; Various Settings ; ================ ; solid lzma gives best compression in virtually all cases SetCompressor /SOLID lzma Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" OutFile "@installer_path@" InstallDir "$PROGRAMFILES\${PRODUCT_NAME}${PRODUCT_KEY}" ShowInstDetails show ShowUnInstDetails show ; Includes ; ======== !include "MUI2.nsh" !include "LogicLib.nsh" !include "x64.nsh" ; MUI Settings ; ============ !define MUI_ABORTWARNING !define MUI_FINISHPAGE_NOAUTOCLOSE !define MUI_UNFINISHPAGE_NOAUTOCLOSE !define MUI_ICON "@ico_install@" !define MUI_UNICON "@ico_uninstall@" !define MUI_HEADERIMAGE !define MUI_HEADERIMAGE_BITMAP "@header_bitmap@" !define MUI_HEADERIMAGE_UNBITMAP "@header_bitmap@" !define MUI_WELCOMEFINISHPAGE_BITMAP "@welcome_bitmap@" !define MUI_UNWELCOMEFINISHPAGE_BITMAP "@welcome_bitmap@" !insertmacro MUI_PAGE_WELCOME @haslicensefile@!insertmacro MUI_PAGE_LICENSE "@licensefile@" !insertmacro MUI_PAGE_COMPONENTS !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_PAGE_FINISH !insertmacro MUI_UNPAGE_WELCOME !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_FINISH !define MUI_COMPONENTSPAGE_NODESC ; Languages ; ========= !insertmacro MUI_LANGUAGE "English" ;first language is the default language !insertmacro MUI_LANGUAGE "French" !insertmacro MUI_LANGUAGE "German" !insertmacro MUI_LANGUAGE "Spanish" !insertmacro MUI_LANGUAGE "SpanishInternational" !insertmacro MUI_LANGUAGE "SimpChinese" !insertmacro MUI_LANGUAGE "TradChinese" !insertmacro MUI_LANGUAGE "Japanese" !insertmacro MUI_LANGUAGE "Korean" !insertmacro MUI_LANGUAGE "Italian" !insertmacro MUI_LANGUAGE "Dutch" !insertmacro MUI_LANGUAGE "Danish" !insertmacro MUI_LANGUAGE "Swedish" !insertmacro MUI_LANGUAGE "Norwegian" !insertmacro MUI_LANGUAGE "NorwegianNynorsk" !insertmacro MUI_LANGUAGE "Finnish" !insertmacro MUI_LANGUAGE "Greek" !insertmacro MUI_LANGUAGE "Russian" !insertmacro MUI_LANGUAGE "Portuguese" !insertmacro MUI_LANGUAGE "PortugueseBR" !insertmacro MUI_LANGUAGE "Polish" !insertmacro MUI_LANGUAGE "Ukrainian" !insertmacro MUI_LANGUAGE "Czech" !insertmacro MUI_LANGUAGE "Slovak" !insertmacro MUI_LANGUAGE "Croatian" !insertmacro MUI_LANGUAGE "Bulgarian" !insertmacro MUI_LANGUAGE "Hungarian" !insertmacro MUI_LANGUAGE "Thai" !insertmacro MUI_LANGUAGE "Romanian" !insertmacro MUI_LANGUAGE "Latvian" !insertmacro MUI_LANGUAGE "Macedonian" !insertmacro MUI_LANGUAGE "Estonian" !insertmacro MUI_LANGUAGE "Turkish" !insertmacro MUI_LANGUAGE "Lithuanian" !insertmacro MUI_LANGUAGE "Slovenian" !insertmacro MUI_LANGUAGE "Serbian" !insertmacro MUI_LANGUAGE "SerbianLatin" !insertmacro MUI_LANGUAGE "Arabic" !insertmacro MUI_LANGUAGE "Farsi" !insertmacro MUI_LANGUAGE "Hebrew" !insertmacro MUI_LANGUAGE "Indonesian" !insertmacro MUI_LANGUAGE "Mongolian" !insertmacro MUI_LANGUAGE "Luxembourgish" !insertmacro MUI_LANGUAGE "Albanian" !insertmacro MUI_LANGUAGE "Breton" !insertmacro MUI_LANGUAGE "Belarusian" !insertmacro MUI_LANGUAGE "Icelandic" !insertmacro MUI_LANGUAGE "Malay" !insertmacro MUI_LANGUAGE "Bosnian" !insertmacro MUI_LANGUAGE "Kurdish" !insertmacro MUI_LANGUAGE "Irish" !insertmacro MUI_LANGUAGE "Uzbek" !insertmacro MUI_LANGUAGE "Galician" !insertmacro MUI_LANGUAGE "Afrikaans" !insertmacro MUI_LANGUAGE "Catalan" !insertmacro MUI_LANGUAGE "Esperanto" ; If you are using solid compression, files that are required before ; the actual installation should be stored first in the data block, ; because this will make your installer start faster. !insertmacro MUI_RESERVEFILE_LANGDLL ; Extra header ; ============ !ifdef MISC_NSHEXTRA !include "@nshextra@" !endif ; Install and uninstall functions ; =============================== ; $0 = full path to python directory (typically, C:\PythonXX) ; $1 = full path to python executable (typically, C:\PythonXX\python.exe; if empty then compile/optimize/2to3 will be disabled) ; $2 = python version (e.g. "2.6") ; $3 = full path to python package directory (typically, C:\PythonXX\Lib\site-packages) ; $4 = full path to python scripts directory (if empty, not installed) ; $5 = full path to python include directory (if empty, not installed) Function InstallFiles ; first remove any stray files leftover from a previous installation @_deletefiles@ !ifdef MISC_NSHEXTRA !insertmacro UninstallFilesExtra !endif ; now install all files @_files@ !ifdef MISC_NSHEXTRA !insertmacro InstallFilesExtra !endif FunctionEnd Function un.InstallFiles @_deletefiles@ !ifdef MISC_NSHEXTRA !insertmacro UninstallFilesExtra !endif FunctionEnd ; Variables ; ========= """ + "\n".join( "\n".join(app.insertmacro_variables()) for app in python_apps) + r""" !ifdef MISC_MAYA """ + "\n".join( "\n".join(app.insertmacro_variables()) for app in maya_apps) + r""" !endif !ifdef MISC_BLENDER """ + "\n".join( "\n".join(app.insertmacro_variables()) for app in blender_apps) + r""" !endif ; Macros ; ====== !macro DEBUG_MSG text !ifdef MISC_DEBUG MessageBox MB_OK "${text}" !endif !macroend ; jumps to registry_key_found if the registry key is found !macro GET_REGISTRY_KEY variable reg_view reg_root reg_key reg_name if_found !insertmacro DEBUG_MSG "looking for ${reg_root}\${reg_key}\${reg_name} in ${reg_view} bit registry" !if "${reg_view}" == "64" ; only check 64 bit registry keys on 64 bit systems ${If} ${RunningX64} !endif SetRegView ${reg_view} ReadRegStr ${variable} ${reg_root} ${reg_key} "${reg_name}" IfErrors 0 ${if_found} !if "${reg_view}" == "64" ${EndIf} !endif !macroend """ + "\n".join( "\n".join(app.macro_get_registry_keys()) for app in python_apps) + r""" !ifdef MISC_MAYA """ + "\n".join( "\n".join(app.macro_get_registry_keys()) for app in maya_apps) + r""" !endif !ifdef MISC_BLENDER """ + "\n".join( "\n".join(app.macro_get_registry_keys()) for app in blender_apps) + r""" !endif ; get path !macro GET_PATH label ; check registry ClearErrors !insertmacro GET_REGISTRY_KEYS_${label} registry_key_found_${label} StrCpy $PATH_${label} "" !insertmacro DEBUG_MSG "not found in registry" Goto get_path_end_${label} registry_key_found_${label}: ; remove trailing backslash using the $EXEDIR trick Push $PATH_${label} Exch $EXEDIR Exch $EXEDIR Pop $PATH_${label} !insertmacro DEBUG_MSG "found at $PATH_${label}" !insertmacro GET_PATH_EXTRA_CHECK_${label} get_path_end_${label}: !macroend ; validates python path !macro GET_PATH_EXTRA_CHECK_PYTHON label IfFileExists "$PATH_${label}\python.exe" 0 python_exe_not_found_${label} !insertmacro DEBUG_MSG "found python executable at $PATH_${label}\python.exe" GoTo get_path_end_${label} python_exe_not_found_${label}: !insertmacro DEBUG_MSG "python executable not found" StrCpy $PATH_${label} "" !macroend """ + "\n".join( "\n".join(app.macro_get_path_extra_check()) for app in python_apps) + r""" !ifdef MISC_MAYA """ + "\n".join( "\n".join(app.macro_get_path_extra_check()) for app in maya_apps) + r""" !endif !ifdef MISC_BLENDER """ + "\n".join( "\n".join(app.macro_get_path_extra_check()) for app in blender_apps) + r""" !endif !macro SECTION un name label !ifndef HAVE_SECTION_${label} !define HAVE_SECTION_${label} !endif Section "${un}${name}" ${un}section_${label} SetShellVarContext all StrCmp $PATH_${label} "" section_end_${label} !insertmacro SECTION_EXTRA_${label} Call ${un}InstallFiles section_end_${label}: SectionEnd !macroend ; setup install vars for python !macro SECTION_EXTRA_PYTHON label py_version StrCpy $0 "$PATH_${label}" StrCpy $1 "$PATH_${label}\python.exe" StrCpy $2 "${py_version}" StrCpy $3 "$PATH_${label}\Lib\site-packages" StrCpy $4 "$PATH_${label}\Scripts" StrCpy $5 "$PATH_${label}\Include" !macroend """ + "\n\n".join( "\n".join(app.macro_section_extra()) for app in python_apps) + r""" !ifdef MISC_MAYA """ + "\n\n".join( "\n".join(app.macro_section_extra()) for app in maya_apps) + r""" !endif !ifdef MISC_BLENDER """ + "\n\n".join( "\n".join(app.macro_section_extra()) for app in blender_apps) + r""" !endif !macro SECTION_SET_PROPERTIES label SectionSetSize ${section_${label}} ${MISC_PYSIZEKB} !insertmacro GET_PATH ${label} StrCmp $PATH_${label} "" 0 +2 SectionSetFlags ${section_${label}} ${SF_RO} !macroend !ifdef MISC_MAYA ; validates python path for maya !macro GET_PATH_EXTRA_CHECK_MAYA label IfFileExists $PATH_${label}\bin\mayapy.exe 0 mayapy_exe_not_found_${label} !insertmacro DEBUG_MSG "found python executable at $PATH_${label}\bin\mayapy.exe" GoTo get_path_end_${label} mayapy_exe_not_found_${label}: !insertmacro DEBUG_MSG "python executable not found" StrCpy $PATH_${label} "" !macroend ; setup install vars for maya !macro SECTION_EXTRA_MAYA label py_version StrCpy $0 "$PATH_${label}\Python" StrCpy $1 "$PATH_${label}\bin\mayapy.exe" StrCpy $2 "${py_version}" StrCpy $3 "$PATH_${label}\Python\Lib\site-packages" StrCpy $4 "" ; no scripts StrCpy $5 "" ; no headers !macroend !endif ;MISC_MAYA !ifdef MISC_BLENDER ; Blender 24x !macro CLEAN_STRAY_BLENDER_USER_DATA_FILES path !insertmacro DEBUG_MSG "checking for stray Blender user data files in ${path}" IfFileExists "${path}" 0 +3 MessageBox MB_YESNO|MB_ICONQUESTION "Clean stray Blender user data files in ${path} (highly recommended)?" IDNO +2 RmDir /r "${path}" !macroend !macro CLEAN_ALL_STRAY_BLENDER_USER_DATA_FILES SetShellVarContext current !insertmacro CLEAN_STRAY_BLENDER_USER_DATA_FILES "$APPDATA\Blender Foundation" SetShellVarContext all !insertmacro CLEAN_STRAY_BLENDER_USER_DATA_FILES "$APPDATA\Blender Foundation" ReadEnvStr $0 "HOME" !insertmacro CLEAN_STRAY_BLENDER_USER_DATA_FILES "$0\.blender" !macroend !macro FILE_EXISTS_BLENDER_SCRIPTS label path if_found if_not_found !insertmacro DEBUG_MSG "checking for blender scripts ${path}" StrCpy $SCRIPTS_${label} "${path}" IfFileExists "$SCRIPTS_${label}\*.*" ${if_found} ${if_not_found} !macroend !macro CHECK_BLENDER_PYTHON_VERSION label py_version if_right if_wrong ; dll check for python version """ + "\n".join( BlenderAppInfo.insertmacro_push_blender_python_version( target_versions)) + r""" Pop $0 StrCmp $0 ${py_version} ${if_right} ${if_wrong} !macroend ; validates path for blender !macro GET_PATH_EXTRA_CHECK_BLENDER label py_version ; check if blender.exe exists IfFileExists "$PATH_${label}\blender.exe" 0 blender_exe_not_found_${label} !insertmacro DEBUG_MSG "found blender executable at $PATH_${label}\blender.exe" !insertmacro CHECK_BLENDER_PYTHON_VERSION ${label} ${py_version} 0 wrong_python_version_${label} ; clear variable StrCpy $SCRIPTS_${label} "" ; get Blender scripts dir !insertmacro FILE_EXISTS_BLENDER_SCRIPTS ${label} "$PATH_${label}\.blender\scripts" blender_scripts_found_in_install_dir_${label} 0 ; extra sanity check during install: scripts not in default location, so warn, clean, and reinstall blender !ifndef __UNINSTALL__ MessageBox MB_YESNO|MB_ICONEXCLAMATION "Blender's user data files (such as scripts) do not reside in Blender's installation directory. Blender will sometimes only find its scripts if Blender's user data files reside in Blender's installation directory.$\r$\n$\r$\nDo you wish to abort installation, and first reinstall Blender?" IDNO blender_scripts_notininstallfolder_${label} MessageBox MB_YESNO|MB_ICONQUESTION "Please reinstall Blender, and select 'Use the installation directory' when asked where to install Blender's user data files. When you are done, rerun this installer.$\r$\n$\r$\nVisit the Blender download page?" IDNO blender_scripts_skip_blender_download_page_${label} StrCpy $0 "http://www.blender.org/download/get-blender/" Call openLinkNewWindow blender_scripts_skip_blender_download_page_${label}: Abort ; causes installer to quit blender_scripts_notininstallfolder_${label}: !endif SetShellVarContext current !insertmacro FILE_EXISTS_BLENDER_SCRIPTS ${label} "$APPDATA\Blender Foundation\Blender\.blender\scripts" blender_scripts_found_${label} 0 SetShellVarContext all !insertmacro FILE_EXISTS_BLENDER_SCRIPTS ${label} "$APPDATA\Blender Foundation\Blender\.blender\scripts" blender_scripts_found_${label} 0 ReadEnvStr $0 "HOME" !insertmacro FILE_EXISTS_BLENDER_SCRIPTS ${label} "$0\.blender\scripts" blender_scripts_found_${label} blender_scripts_not_found_${label} blender_scripts_found_in_install_dir_${label}: ; extra cleaning if installing in default directory (only during install) !ifndef __UNINSTALL__ !insertmacro CLEAN_ALL_STRAY_BLENDER_USER_DATA_FILES !endif blender_scripts_found_${label}: !insertmacro DEBUG_MSG "found blender scripts in $SCRIPTS_${label}" ; remove trailing backslash using the $EXEDIR trick Push $SCRIPTS_${label} Exch $EXEDIR Exch $EXEDIR Pop $SCRIPTS_${label} GoTo blender_scripts_done_${label} blender_exe_not_found_${label}: wrong_python_version_${label}: blender_scripts_not_found_${label}: !insertmacro DEBUG_MSG "blender scripts not found" StrCpy $SCRIPTS_${label} "" StrCpy $PATH_${label} "" blender_scripts_done_${label}: !macroend !macro SECTION_EXTRA_BLENDER label py_version StrCpy $0 "" ; XXX todo: set python path StrCpy $1 "" ; XXX todo: set python executable StrCpy $2 "${py_version}" StrCpy $3 "$SCRIPTS_${label}\bpymodules" StrCpy $4 "" ; no scripts StrCpy $5 "" ; no headers !macroend ; Blender 25x+ !macro GET_PATH_EXTRA_CHECK_BLENDER_25X label py_version version IfFileExists $PATH_${label}\${version}\python\lib\*.* 0 python_lib_not_found_${label} !insertmacro DEBUG_MSG "found python libraries at $PATH_${label}\${version}\python\lib" GoTo get_path_end_${label} python_lib_not_found_${label}: !insertmacro DEBUG_MSG "python libraries not found" StrCpy $PATH_${label} "" !macroend !macro SECTION_EXTRA_BLENDER_25X label py_version version StrCpy $0 "$PATH_${label}\${version}\python" StrCpy $1 "" ; no interpreter StrCpy $2 "${py_version}" # Blender does not have site-packages on its sys.path #StrCpy $3 "$PATH_${label}\${version}\python\lib\site-packages" # instead, we use scripts\addons\modules StrCpy $3 "$PATH_${label}\${version}\scripts\addons\modules" StrCpy $4 "" ; no scripts StrCpy $5 "" ; no headers !macroend !endif ;MISC_BLENDER !include "FileFunc.nsh" !include "WordFunc.nsh" !insertmacro Locate !insertmacro VersionCompare !macro SearchDLL DLLLABEL DLLDESC DLLFILE DLLVERSION DLLLINK Var DLLFound${DLLLABEL} Function Download${DLLLABEL} Push ${DLLLINK} MessageBox MB_OK "You will need to download ${DLLDESC}. Pressing OK will take you to the download page, please follow the instructions on the page that appears." StrCpy $0 ${DLLLINK} Call openLinkNewWindow FunctionEnd Function LocateCallback${DLLLABEL} MoreInfo::GetProductVersion "$R9" Pop $0 ${VersionCompare} "$0" "${DLLVERSION}" $R1 ; $R1 contains the result of the comparison ; 0 = versions are equal ; 1 = first version is newer than second version ; 2 = first version is older than second version StrCmp $R1 2 0 found ; version $0 is older than ${DLLVERSION} ;DEBUG;MessageBox MB_OK "${DLLFILE} ($0) is too old." Push "$0" GoTo notfound found: ; version $0 is equal or newer than ${DLLVERSION} ;DEBUG;MessageBox MB_OK "${DLLFILE} ($0) located!" StrCpy "$0" StopLocate StrCpy $DLLFound${DLLLABEL} "true" Push "$0" notfound: FunctionEnd Function Find${DLLLABEL} Push $0 Push $1 DetailPrint "Locating ${DLLDESC}: ${DLLFILE} (${DLLVERSION})." StrCpy $1 $WINDIR StrCpy $DLLFound${DLLLABEL} "false" ${Locate} "$1" "/L=F /M=${DLLFILE} /S=0B" "LocateCallback${DLLLABEL}" StrCmp $DLLFound${DLLLABEL} "false" 0 +2 Call Download${DLLLABEL} Pop $1 Pop $0 FunctionEnd !macroend !ifdef MISC_MSVC2005 !insertmacro SearchDLL "MSVC2005" "Microsoft Visual C++ 2005 Redistributable Package" "MSVCR80.DLL" "8.0.50727.42" "http://www.microsoft.com/en-us/download/details.aspx?id=3387" !endif !ifdef MISC_MSVC2005SP1 !insertmacro SearchDLL "MSVC2005SP1" "Microsoft Visual C++ 2005 SP1 Redistributable Package" "MSVCR80.DLL" "8.0.50727.762" "http://www.microsoft.com/en-us/download/details.aspx?id=5638" !endif !ifdef MISC_MSVC2008 !insertmacro SearchDLL "MSVC2008" "Microsoft Visual C++ 2008 Redistributable Package" "MSVCR90.DLL" "9.0.21022.8" "http://www.microsoft.com/en-us/download/details.aspx?id=29" !endif !ifdef MISC_MSVC2008SP1 !insertmacro SearchDLL "MSVC2008SP1" "Microsoft Visual C++ 2008 SP1 Redistributable Package" "MSVCR90.DLL" "9.0.30729.1" "http://www.microsoft.com/en-us/download/details.aspx?id=5582" !endif """ NSI_FOOTER = r""" ; Functions ; ========= !ifdef REQUIREOPENLINKNEWWINDOW ; taken from http://nsis.sourceforge.net/Open_link_in_new_browser_window # uses $0 Function openLinkNewWindow Push $3 Push $2 Push $1 Push $0 ReadRegStr $0 HKCR "http\shell\open\command" "" # Get browser path DetailPrint $0 StrCpy $2 '"' StrCpy $1 $0 1 StrCmp $1 $2 +2 # if path is not enclosed in " look for space as final char StrCpy $2 ' ' StrCpy $3 1 loop: StrCpy $1 $0 1 $3 DetailPrint $1 StrCmp $1 $2 found StrCmp $1 "" found IntOp $3 $3 + 1 Goto loop found: StrCpy $1 $0 $3 StrCmp $2 " " +2 StrCpy $1 '$1"' Pop $0 Exec '$1 $0' Pop $1 Pop $2 Pop $3 FunctionEnd !endif Function .onInit ; Check if user is admin. ; Call userInfo plugin to get user info. ; The plugin puts the result in the stack. userInfo::getAccountType ; pop the result from the stack into $0 pop $0 ; Compare the result with the string "Admin" to see if the user is admin. ; If match, jump 3 lines down. strCmp $0 "Admin" +3 ; if there is not a match, print message and return messageBox MB_OK|MB_ICONEXCLAMATION "You require administrator privileges to install ${PRODUCT_NAME} successfully." Abort ; quit installer ; Language selection. !insertmacro MUI_LANGDLL_DISPLAY !ifdef MISC_DEBUG ${If} ${RunningX64} MessageBox MB_OK "running on x64" ${EndIf} !endif ; check python versions """ + "\n".join( " !insertmacro SECTION_SET_PROPERTIES %s" % app.label for app in python_apps) + r""" !ifdef MISC_MAYA """ + "\n".join( " !insertmacro SECTION_SET_PROPERTIES %s" % app.label for app in maya_apps) + r""" !endif ;MISC_MAYA !ifdef MISC_BLENDER """ + "\n".join( " !insertmacro SECTION_SET_PROPERTIES %s" % app.label for app in blender_apps) + r""" !endif ;MISC_BLENDER FunctionEnd Function un.onInit """ + "\n".join( ' !insertmacro GET_PATH %s' % app.label for app in python_apps) + r""" !ifdef MISC_MAYA """ + "\n".join( ' !insertmacro GET_PATH %s' % app.label for app in maya_apps) + r""" !endif ;MISC_MAYA !ifdef MISC_BLENDER """ + "\n".join( ' !insertmacro GET_PATH %s' % app.label for app in blender_apps) + r""" !endif ;MISC_BLENDER FunctionEnd Section -Post SetOutPath "$INSTDIR" WriteUninstaller "$INSTDIR\${PRODUCT_NAME}_uninstall.exe" SetRegView ${PRODUCT_UNINST_REG_VIEW} WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\${PRODUCT_NAME}_uninstall.exe" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" !ifdef MISC_NSHEXTRA !insertmacro UnPostExtra !insertmacro PostExtra !endif !ifdef MISC_MSVC2005 Call FindMSVC2005 !endif !ifdef MISC_MSVC2005SP1 Call FindMSVC2005SP1 !endif !ifdef MISC_MSVC2008 Call FindMSVC2008 !endif !ifdef MISC_MSVC2008SP1 Call FindMSVC2008SP1 !endif SectionEnd Section un.Post !ifdef MISC_NSHEXTRA !insertmacro UnPostExtra !endif Delete "$INSTDIR\${PRODUCT_NAME}_uninstall.exe" RmDir "$INSTDIR" SetRegView ${PRODUCT_UNINST_REG_VIEW} DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" SectionEnd """ return (NSI_HEADER + "\nSectionGroup /e Python\n" + "\n".join( '!insertmacro SECTION "" "%s" %s' % (app.name, app.label) for app in python_apps) + "\nSectionGroupEnd\n\n" + "\nSectionGroup /e un.Python\n" + "\n".join( '!insertmacro SECTION "un." "%s" %s' % (app.name, app.label) for app in python_apps) + "\nSectionGroupEnd\n\n\n" + "!ifdef MISC_MAYA\n" + "\nSectionGroup /e Maya\n" + "\n".join( '!insertmacro SECTION "" "%s" %s' % (app.name, app.label) for app in maya_apps) + "\nSectionGroupEnd\n\n" + "\nSectionGroup /e un.Maya\n" + "\n".join( '!insertmacro SECTION "un." "%s" %s' % (app.name, app.label) for app in maya_apps) + "\nSectionGroupEnd\n\n" + "!endif ;MISC_MAYA\n\n\n" + "!ifdef MISC_BLENDER\n" + "\nSectionGroup /e Blender\n" + "\n".join( '!insertmacro SECTION "" "%s" %s' % (app.name, app.label) for app in blender_apps) + "\nSectionGroupEnd\n\n" + "\nSectionGroup /e un.Blender\n" + "\n".join( '!insertmacro SECTION "un." "%s" %s' % (app.name, app.label) for app in blender_apps) + "\nSectionGroupEnd\n\n\n" + "!endif ;MISC_BLENDER\n\n\n" + NSI_FOOTER) if __name__=='__main__': import doctest doctest.testmod() bdist_nsi-0.1.5/setup.py0000755000000000000000000000224612042740054013710 0ustar rootroot#!/usr/bin/env python """Setup script for bdist_nsi.""" classifiers = """Development Status :: 5 - Production/Stable Intended Audience :: Developers License :: OSI Approved :: BSD License Natural Language :: English Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: 2 Programming Language :: Python :: 3 Topic :: System :: Software Distribution Topic :: Software Development :: Code Generators""" from distutils.core import setup import os long_description = open("README.rst").read() setup( name = 'bdist_nsi', packages = ['bdist_nsi'], package_data = {'': ['*.ico', '*.bmp']}, # include ico and bmp files version = '0.1.5', description = 'Create NSIS windows installers for Python modules.', # note: author of the original http://bdist-nsi.sourceforge.net/ package # (which formed the original basis of bdist_nsi) is j-cg author = 'Amorilia', author_email = 'amorilia@users.sourceforge.net', url = 'http://bdist-nsi.sourceforge.net/', license = 'BSD', platforms = ["any"], classifiers = [_f for _f in classifiers.split("\n") if _f], long_description = long_description ) bdist_nsi-0.1.5/README.rst0000755000000000000000000000342112042736306013666 0ustar rootrootbdist_nsi ========= The bdist_nsi module extends Python's distutils module with a bdist_nsi setup command to create binary Windows installers for Python modules, based on NSIS. Thereby, bdist_nsi brings all the features of NSIS to Windows installers for Python modules, such as silent install, modern user interface, and internationalization. In action --------- Take a look at the `screenshots `_. What you need ------------- Besides Python and the bdist_nsi module, you will need `NSIS `_. It can be run under windows and linux (see NSIS forum for instructions). Installation ------------ The latest version can always be downloaded from https://sourceforge.net/projects/bdist-nsi/files. To install from source, simply run:: python setup.py install Usage ----- Add ``bdist_nsi`` option to your setup.py file. In your projects setup.py:: try: import bdist_nsi except ImportError: pass nsis_options = {} # your nsis options setup( name='your application name', version='0.0.x', author='your name', author_email='your email', url='http://yourdomain.com/', options={'bdist_nsi': nsis_options, }, license='your license',) # your setup options You can create installer ``python setup.py bdist_nsi`` command. If the makensis executable is not installed in one of the usual locations (``/usr/bin``, ``C:\Program Files\NSIS``, or ``C:\Program Files (x86)\NSIS``), then you can specify the NSIS folder with the *--nsis-dir* option, or just add *-k* to have a look at the temporary generated files. Development ----------- Development happens at github, http://github.com/amorilia/bdist_nsi/. Fork at will! bdist_nsi-0.1.5/PKG-INFO0000755000000000000000000000576112042740230013274 0ustar rootrootMetadata-Version: 1.1 Name: bdist_nsi Version: 0.1.5 Summary: Create NSIS windows installers for Python modules. Home-page: http://bdist-nsi.sourceforge.net/ Author: Amorilia Author-email: amorilia@users.sourceforge.net License: BSD Description: bdist_nsi ========= The bdist_nsi module extends Python's distutils module with a bdist_nsi setup command to create binary Windows installers for Python modules, based on NSIS. Thereby, bdist_nsi brings all the features of NSIS to Windows installers for Python modules, such as silent install, modern user interface, and internationalization. In action --------- Take a look at the `screenshots `_. What you need ------------- Besides Python and the bdist_nsi module, you will need `NSIS `_. It can be run under windows and linux (see NSIS forum for instructions). Installation ------------ The latest version can always be downloaded from https://sourceforge.net/projects/bdist-nsi/files. To install from source, simply run:: python setup.py install Usage ----- Add ``bdist_nsi`` option to your setup.py file. In your projects setup.py:: try: import bdist_nsi except ImportError: pass nsis_options = {} # your nsis options setup( name='your application name', version='0.0.x', author='your name', author_email='your email', url='http://yourdomain.com/', options={'bdist_nsi': nsis_options, }, license='your license',) # your setup options You can create installer ``python setup.py bdist_nsi`` command. If the makensis executable is not installed in one of the usual locations (``/usr/bin``, ``C:\Program Files\NSIS``, or ``C:\Program Files (x86)\NSIS``), then you can specify the NSIS folder with the *--nsis-dir* option, or just add *-k* to have a look at the temporary generated files. Development ----------- Development happens at github, http://github.com/amorilia/bdist_nsi/. Fork at will! Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Natural Language :: English Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: System :: Software Distribution Classifier: Topic :: Software Development :: Code Generators bdist_nsi-0.1.5/LICENSE.rst0000755000000000000000000000277012042736306014021 0ustar rootrootCopyright © 2009, bdist_nsi contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the bdist_nsi project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.