Flask-Script-0.6.7/0000755000076500000240000000000012300146140014615 5ustar smlynchstaff00000000000000Flask-Script-0.6.7/docs/0000755000076500000240000000000012300146140015545 5ustar smlynchstaff00000000000000Flask-Script-0.6.7/docs/.DS_Store0000644000076500000240000001400412023135547017242 0ustar smlynchstaff00000000000000Bud1ticbwspbl_staticbwspblobbplist00 \WindowBounds[ShowSidebar]ShowStatusBar[ShowPathbar[ShowToolbar\SidebarWidth_{{573, 140}, {770, 668}} "._B:v d= `j$A {r8NXA2LrN*RSV}$8@2 Vua]B\ [uT*$KS(d2Y'ńk&!BA!`0 V)ڀbwUm f}5qHN&q2``0LZfqBǩfY'8\Iu2vjC*A2jڈ, `0LF;AuL$=B\k x `71u%QV$F#"tf0  BP&w#SQH& Zw6\.yJRlY `0 BȢs~:"'Q*琦?`0 DmR 3<T AΆnPFD@>L a BJp?@?N;\!&0` cH  w:&Q@B PI3q w0s|ex|x5c|NqO X|HsLr٩T*)[K?#K"p a< LI90(<=  l6;B;%<!9Rnp4K!1Bj$p!8G ݮN%xX_@Y!c(&NʟT$L(A 4h}جǓ8ÒdF.g"{Hb0AܩIô8 I ~ ~UT*B.8R(mPk BMca1%Ej f,# Hȃ[/M BG mxvlb`0&ء˗/ @oo/4:,%KlDlϙ3[luڵkiӦ׭Vصk֬Y믿3f,^?; 5:aӞ(u\T}h7S`0Ў~|S@;{.Z!|jeF5 A #_ 5G`j*x"<AC`H=6 z,t$Oh @v}gJBd2zEլNd2ِH&Y>NLF)D/2ߥqc2#܋hTkD.V7Mc DrmHLɰ3~J`x+WbpK.Žދ.ի/~Dt: K.Ar;w.6l؀۽+gYyj5r98͛7cڵ>iu"ϟOCKΈvZW5qST=V52"9!ņ>r\?HS6 Fd D - pck47n3=.p<^!3"PTiA2 2-TUX,:R)Jus0eH𽹰o*ۇko&5$1+/fY\.78#fT*Փ56D0Ah9A5G[B82c4p2k| ov_.FS.gC( NZt2L HlK( p-&,9 :tt0BuOro@ZYP+3AL6aLA-!\͑#!+f;(D"|>\.n̟/d?KRL&M6aΝXp!N;4p pfBOOO܅ bX`jժyT ƍz*/6Y:<< F`1Dh4wUA9P}h7O&JL P%ASeQژjv5+<î( =GC֣ۤA8 F ,ǻ􋶾ѪH$9 ("A=WuFbF 3(t&)SAa&_gW[@c\QQ])!Dŵ\{&jb<Q n/op%^=q49L|@;|U+@c@D Nw BȅL&SPNFD$ J5q5A)(G$oݜB'k5( 0,w\]!$ &{n&I7>x>sw9eR?SĽ|h>=j8 ;ĵJ>}K|Ʊ B~U@>rn:# ӂJ&l@ D0ȴ Z0A8= l8p\h!V{r3GRp=3-'@yGLMOE8!JzuL#Q3Oj&4k u>>+}}R=%I]/*@eES^k{P]ղM 9x&|I/9qrzpE>j-USeF 3$S< tM RKPs<K ~42%Ęh$>mdL9,>}1;[3͡ihϐ$zsu85Sާu/8a^f+,=c [ɵ2MnFt|Y9<|dQ{0_N@ԾIPiv*ԕp5U3Ah%%99X|wq>c@~llkL; mAi]܀}lCt ʏl" 6?h{Ůߏ< L tx9 bfIDqOdžgΥrKChcfl6&xR2uOTs!:BaD#U QV;1Z]q- ;}v;ci>n! p{r,F!:ǃ>NjA Q4udK~gYm<اAx{]Y'%Y6u\~m1lY!w@D;1IjL/{,N (YɤPTl6@2t~-&'?4<myTx2$iԶb3 C8b,a§uDt:{ȱ\#UWYz:? s&C3%WT '}ڬf1ŰvʟC8nGu>m?chw':Q~N)ɤS,*6H; xD Qq-A&>"[:.'B% ;'ПXf J:JU<>-_0Dϰ:!yN!&gM~'niϋm7h]*^jFIUK3>#^Xƒ-̐~Ӷ<&z"dҩT*ad&PGRINT\"%LJSW‘q-A4BMzV/">A ?pL;\lPWɡG~Tc[7޸*|~D Y * (+4g8 zI r,] ՆMg ׺>@_٤k;:݆6[I"2e?T5L|IR yPVDNfGlCuz4d߳./Hr!y<bRa=k@L 4fPv÷ܥ%Fa=,xFa ipʟ7Gp ^TtE? P&*u r@qNFw"$J J 'QlIR qH?1=:q)Ջ擭4Avr ϥKp&Z̈{? s28JzbW#n>j~[<7[cvݩL$PCU A*k"\AD1&q-AO V>TV(>Hҏa{ xzNq]?ia ףiu| }ٚlR7ȣ)qVl_N"Ԛ Jn9*%wLƩVN&i(h9AX 0WIjsD<9OCjș)bEE d$-x߳1R΁]D#7 Z{aΠh Lv&_m:SLNW&-#ĵu DDcر(Fy}SYP> @*@_@T^4u8IXPn-|Q?lΉ̰x/mD?o`_A e EFBh*F)TNc K Bp!mO4johB0}Aן*4hG`_\l =C]zeS%-($)37h"ڟ y\rtC(#hbBVbS5qoA 9B2); 9Nb>cxѓҜ1dǍlcI^>{DTk7-ܔ[~ο7#W{!Eݭ9w;eZ1f ŠBޠ9R-7!51CkbXRKpp"MYK cx~Ftm؍b vől4 y/g1Api ȩP |C1%*DT2h ЊrASGXmP;'a֑;"$'&$ t6]M/#׼+kB)W~-B{y[6 5 #Jh p|\KPs-1 R#8J_K^RwoEDi;MjvL$a(57.ϬKs0{Rp\=JZ /C{x>m3ֱ48,Ap7GJc@.,ۏ ka[ ص| nG]yT>7 !35.$1K5z0wDB$lzn95D?0\m5C *q>SS|މ 1?%e2m{wv I+0;~&_cv;=1\*؍u>~WwA֘9bzb}S?OcݱO1dB|Hm]<S;z>xB$#4b"hwgA#MmKb7 ؄\AtdְT@c~PnlrKCRfs&aX>潕8B{a~OXguh}(94<| މNCő2񟚶6y`"ASZ%^!/# “f^R2$w-L7(wWȏ E4^X!R@g4u AutIDATK|v]| HA޶j[JB˧M°qFwdJE4TCɧ0UL<9Յ'r>je5DSQ؍YO<Vi9Da 6a ~`FC1"umr~Hť0GXyOҴŜm(WB%3=:Q)}+KsD ^j땚qLީMLմsxJi H,w[/!XDRU ,vȎ!'+NY-rB 8\ t]wB+~lh{^7ęWyjk|:9!2kя),E8t!%Ynx?ΔDyk)wP(R[1 閻4r/&߳Aץ=G3ѽH*g/NVABmMObcl| ީwZl5iwH#١,esX s~_nkf"+-b#w/ DAmaaU? q5>s3  sO.f7O>|ucT4#g`H8y>/~;Nri3LB.1oak-_ Y7."!^pF$ZIK$>eƌx饗H$P,l20FD"2[ IVExZvɃi%)U/pÞHeK\_ IliMBد sn߁f%~uˏM_+l 9~ȏ"LUm.כ,?WZtO>Y9 ϽH>C?</ʋg_Y3d= "Q _ xW1Dr>)Ǥ^qDQӷZȉAZ NjҌre{y%_t|~w h0DQ0삈8&;5DSc oҴV;L> R8AcG#p4^~`F{TSm0ZK&CܭLXj1"l>{DԌ kA8ƺsո 08H4h̎IBI!TQh1Vcl3)R6fEUp&doI6NDgßsUj^ك3.IZQj:Ar٬S,y;74猧s-8=` `)ȤI*A8 LKٱcˢE0 #Nl O'r0@̟?.`0ıS4J) %rP`GA`0p+ۄ ;wb2}jBaѹeO9 r0AMxUWa֭7o.^L #.}g0vrdZ`0 (D7'Nn0 c1L&K`0qx:LfD*徾>0 c4Ko,D" 6Wfr`0 AKܡTB(Wh/FRB`01 b͚5V6m? `0 `0 `0 uo368IENDB`Flask-Script-0.6.7/docs/_static/index.html0000644000076500000240000000104012023244177021176 0ustar smlynchstaff00000000000000 Flask-Script documentation has moved... Flask-Script documentation is now maintained at Read the Docs. If your browser does not automatically redirect you, please click here. Flask-Script-0.6.7/docs/_static/index.zip0000644000076500000240000000066312022535104021036 0ustar smlynchstaff00000000000000PKպ'A index.htmlUX JPJPR=O0 &30Cڅ tK\]ҔĽS=nZĀ K'}XQǛ[h(LQ j;?y·ͳI#[b mQJx@,B?zw,E:an^wt%e=)IHd\.OV,SL6#= $.~+fTh.COcĵhA(ljJ1!%uU,5 OO16zK/3ӄ%5f PK z PKպ'A z  @index.htmlUXJPJPPKDYFlask-Script-0.6.7/docs/_themes/0000755000076500000240000000000012300146140017171 5ustar smlynchstaff00000000000000Flask-Script-0.6.7/docs/_themes/flask/0000755000076500000240000000000012300146140020271 5ustar smlynchstaff00000000000000Flask-Script-0.6.7/docs/_themes/flask/static/0000755000076500000240000000000012300146140021560 5ustar smlynchstaff00000000000000Flask-Script-0.6.7/docs/_themes/flask/static/flasky.css_t0000644000076500000240000001245311765767607024152 0ustar smlynchstaff00000000000000/* * flasky.css_t * ~~~~~~~~~~~~ * * Sphinx stylesheet -- flasky theme based on nature theme. * * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: 'Georgia', serif; font-size: 17px; background-color: #ddd; color: #000; margin: 0; padding: 0; } div.document { background: #fafafa; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 230px; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #ffffff; color: #3E4349; padding: 0 30px 30px 30px; min-height: 34em; } img.floatingflask { padding: 0 0 10px 10px; float: right; } div.footer { position: absolute; right: 0; margin-top: -70px; text-align: right; color: #888; padding: 10px; font-size: 14px; } div.footer a { color: #888; text-decoration: underline; } div.related { line-height: 32px; color: #888; } div.related ul { padding: 0 0 0 10px; } div.related a { color: #444; } div.sphinxsidebar { font-size: 14px; line-height: 1.5; } div.sphinxsidebarwrapper { padding: 0 20px; } div.sphinxsidebarwrapper p.logo { padding: 20px 0 10px 0; margin: 0; text-align: center; } div.sphinxsidebar h3, div.sphinxsidebar h4 { font-family: 'Garamond', 'Georgia', serif; color: #222; font-size: 24px; font-weight: normal; margin: 20px 0 5px 0; padding: 0; } div.sphinxsidebar h4 { font-size: 20px; } div.sphinxsidebar h3 a { color: #444; } div.sphinxsidebar p { color: #555; margin: 10px 0; } div.sphinxsidebar ul { margin: 10px 0; padding: 0; color: #000; } div.sphinxsidebar a { color: #444; text-decoration: none; } div.sphinxsidebar a:hover { text-decoration: underline; } div.sphinxsidebar input { border: 1px solid #ccc; font-family: 'Georgia', serif; font-size: 1em; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body { padding-bottom: 40px; /* saved for footer */ } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } div.body h1 { margin-top: 0; padding-top: 20px; font-size: 240%; } div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: white; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #eaeaea; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { background: #fafafa; margin: 20px -30px; padding: 10px 30px; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } div.admonition p.admonition-title { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } div.highlight{ background-color: white; } dt:target, .highlight { background: #FAF3E8; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.9em; } img.screenshot { } tt.descname, tt.descclassname { font-size: 0.95em; } tt.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #eee; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.footnote td { padding: 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } pre { background: #eee; padding: 7px 30px; margin: 15px -30px; line-height: 1.3em; } dl pre { margin-left: -60px; padding-left: 60px; } dl dl pre { margin-left: -90px; padding-left: 90px; } tt { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, a tt { background-color: #FBFBFB; text-decoration: none!important; } a:hover tt { background: #EEE; } Flask-Script-0.6.7/docs/_themes/flask/theme.conf0000644000076500000240000000014111765767607022275 0ustar smlynchstaff00000000000000[theme] inherit = basic stylesheet = flasky.css pygments_style = flask_theme_support.FlaskyStyle Flask-Script-0.6.7/docs/_themes/flask_small/0000755000076500000240000000000012300146140021461 5ustar smlynchstaff00000000000000Flask-Script-0.6.7/docs/_themes/flask_small/layout.html0000644000076500000240000000125311765767607023724 0ustar smlynchstaff00000000000000{% extends "basic/layout.html" %} {% block header %} {{ super() }} {% if pagename == 'index' %}
{% endif %} {% endblock %} {% block footer %} {% if pagename == 'index' %}
{% endif %} {% endblock %} {# do not display relbars #} {% block relbar1 %}{% endblock %} {% block relbar2 %} {% if theme_github_fork %} Fork me on GitHub {% endif %} {% endblock %} {% block sidebar1 %}{% endblock %} {% block sidebar2 %}{% endblock %} Flask-Script-0.6.7/docs/_themes/flask_small/static/0000755000076500000240000000000012300146140022750 5ustar smlynchstaff00000000000000Flask-Script-0.6.7/docs/_themes/flask_small/static/flasky.css_t0000644000076500000240000001100111765767607025326 0ustar smlynchstaff00000000000000/* * flasky.css_t * ~~~~~~~~~~~~ * * Sphinx stylesheet -- flasky theme based on nature theme. * * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: 'Georgia', serif; font-size: 17px; color: #000; background: white; margin: 0; padding: 0; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 40px auto 0 auto; width: 700px; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #ffffff; color: #3E4349; padding: 0 30px 30px 30px; } img.floatingflask { padding: 0 0 10px 10px; float: right; } div.footer { text-align: right; color: #888; padding: 10px; font-size: 14px; width: 650px; margin: 0 auto 40px auto; } div.footer a { color: #888; text-decoration: underline; } div.related { line-height: 32px; color: #888; } div.related ul { padding: 0 0 0 10px; } div.related a { color: #444; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body { padding-bottom: 40px; /* saved for footer */ } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } {% if theme_index_logo %} div.indexwrapper h1 { text-indent: -999999px; background: url({{ theme_index_logo }}) no-repeat center center; height: {{ theme_index_logo_height }}; } {% endif %} div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: white; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #eaeaea; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { background: #fafafa; margin: 20px -30px; padding: 10px 30px; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } div.admonition p.admonition-title { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } div.highlight{ background-color: white; } dt:target, .highlight { background: #FAF3E8; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.85em; } img.screenshot { } tt.descname, tt.descclassname { font-size: 0.95em; } tt.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #eee; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.footnote td { padding: 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } pre { padding: 0; margin: 15px -30px; padding: 8px; line-height: 1.3em; padding: 7px 30px; background: #eee; border-radius: 2px; -moz-border-radius: 2px; -webkit-border-radius: 2px; } dl pre { margin-left: -60px; padding-left: 60px; } tt { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, a tt { background-color: #FBFBFB; } a:hover tt { background: #EEE; } Flask-Script-0.6.7/docs/_themes/flask_small/theme.conf0000644000076500000240000000027011765767607023470 0ustar smlynchstaff00000000000000[theme] inherit = basic stylesheet = flasky.css nosidebar = true pygments_style = flask_theme_support.FlaskyStyle [options] index_logo = '' index_logo_height = 120px github_fork = '' Flask-Script-0.6.7/docs/_themes/flask_theme_support.py0000644000076500000240000001141311765767607023660 0ustar smlynchstaff00000000000000# flasky extensions. flasky pygments style based on tango style from pygments.style import Style from pygments.token import Keyword, Name, Comment, String, Error, \ Number, Operator, Generic, Whitespace, Punctuation, Other, Literal class FlaskyStyle(Style): background_color = "#f8f8f8" default_style = "" styles = { # No corresponding class for the following: #Text: "", # class: '' Whitespace: "underline #f8f8f8", # class: 'w' Error: "#a40000 border:#ef2929", # class: 'err' Other: "#000000", # class 'x' Comment: "italic #8f5902", # class: 'c' Comment.Preproc: "noitalic", # class: 'cp' Keyword: "bold #004461", # class: 'k' Keyword.Constant: "bold #004461", # class: 'kc' Keyword.Declaration: "bold #004461", # class: 'kd' Keyword.Namespace: "bold #004461", # class: 'kn' Keyword.Pseudo: "bold #004461", # class: 'kp' Keyword.Reserved: "bold #004461", # class: 'kr' Keyword.Type: "bold #004461", # class: 'kt' Operator: "#582800", # class: 'o' Operator.Word: "bold #004461", # class: 'ow' - like keywords Punctuation: "bold #000000", # class: 'p' # because special names such as Name.Class, Name.Function, etc. # are not recognized as such later in the parsing, we choose them # to look the same as ordinary variables. Name: "#000000", # class: 'n' Name.Attribute: "#c4a000", # class: 'na' - to be revised Name.Builtin: "#004461", # class: 'nb' Name.Builtin.Pseudo: "#3465a4", # class: 'bp' Name.Class: "#000000", # class: 'nc' - to be revised Name.Constant: "#000000", # class: 'no' - to be revised Name.Decorator: "#888", # class: 'nd' - to be revised Name.Entity: "#ce5c00", # class: 'ni' Name.Exception: "bold #cc0000", # class: 'ne' Name.Function: "#000000", # class: 'nf' Name.Property: "#000000", # class: 'py' Name.Label: "#f57900", # class: 'nl' Name.Namespace: "#000000", # class: 'nn' - to be revised Name.Other: "#000000", # class: 'nx' Name.Tag: "bold #004461", # class: 'nt' - like a keyword Name.Variable: "#000000", # class: 'nv' - to be revised Name.Variable.Class: "#000000", # class: 'vc' - to be revised Name.Variable.Global: "#000000", # class: 'vg' - to be revised Name.Variable.Instance: "#000000", # class: 'vi' - to be revised Number: "#990000", # class: 'm' Literal: "#000000", # class: 'l' Literal.Date: "#000000", # class: 'ld' String: "#4e9a06", # class: 's' String.Backtick: "#4e9a06", # class: 'sb' String.Char: "#4e9a06", # class: 'sc' String.Doc: "italic #8f5902", # class: 'sd' - like a comment String.Double: "#4e9a06", # class: 's2' String.Escape: "#4e9a06", # class: 'se' String.Heredoc: "#4e9a06", # class: 'sh' String.Interpol: "#4e9a06", # class: 'si' String.Other: "#4e9a06", # class: 'sx' String.Regex: "#4e9a06", # class: 'sr' String.Single: "#4e9a06", # class: 's1' String.Symbol: "#4e9a06", # class: 'ss' Generic: "#000000", # class: 'g' Generic.Deleted: "#a40000", # class: 'gd' Generic.Emph: "italic #000000", # class: 'ge' Generic.Error: "#ef2929", # class: 'gr' Generic.Heading: "bold #000080", # class: 'gh' Generic.Inserted: "#00A000", # class: 'gi' Generic.Output: "#888", # class: 'go' Generic.Prompt: "#745334", # class: 'gp' Generic.Strong: "bold #000000", # class: 'gs' Generic.Subheading: "bold #800080", # class: 'gu' Generic.Traceback: "bold #a40000", # class: 'gt' } Flask-Script-0.6.7/docs/_themes/README0000644000076500000240000000210511765767607020106 0ustar smlynchstaff00000000000000Flask Sphinx Styles =================== This repository contains sphinx styles for Flask and Flask related projects. To use this style in your Sphinx documentation, follow this guide: 1. put this folder as _themes into your docs folder. Alternatively you can also use git submodules to check out the contents there. 2. add this to your conf.py: sys.path.append(os.path.abspath('_themes')) html_theme_path = ['_themes'] html_theme = 'flask' The following themes exist: - 'flask' - the standard flask documentation theme for large projects - 'flask_small' - small one-page theme. Intended to be used by very small addon libraries for flask. The following options exist for the flask_small theme: [options] index_logo = '' filename of a picture in _static to be used as replacement for the h1 in the index.rst file. index_logo_height = 120px height of the index logo github_fork = '' repository name on github for the "fork me" badge Flask-Script-0.6.7/docs/conf.py0000644000076500000240000001606612064665645017104 0ustar smlynchstaff00000000000000# -*- coding: utf-8 -*- # # flask-script documentation build configuration file, created by # sphinx-quickstart on Wed Jun 23 08:26:41 2010. # # This file is execfile()d with the current directory set to its containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. sys.path.insert(0, os.path.abspath('..')) sys.path.append(os.path.abspath('_themes')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. #needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Flask-Script' copyright = u'2010, Dan Jacob' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '0.4' # The full version, including alpha/beta/rc tags. release = '0.4.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents. #default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. #pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'flask_small' html_theme_options = { 'index_logo': 'flask-script.png', 'github_fork': 'techniq/flask-script' } # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. html_theme_path = ['_themes'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. #html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. #html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. #html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. #html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'flask-scriptdoc' # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ ('index', 'flask-script.tex', u'Flask-Script Documentation', u'Dan Jacob', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. #latex_use_parts = False # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False # Additional stuff for the LaTeX preamble. #latex_preamble = '' # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'flask-script', u'Flask-Script Documentation', [u'Dan Jacob'], 1) ] Flask-Script-0.6.7/docs/index.rst0000644000076500000240000004111412236707534017431 0ustar smlynchstaff00000000000000Flask-Script ====================================== .. module:: Flask-Script The **Flask-Script** extension provides support for writing external scripts in Flask. This includes running a development server, a customised Python shell, scripts to set up your database, cronjobs, and other command-line tasks that belong outside the web application itself. **Flask-Script** works in a similar way to Flask itself. You define and add commands that can be called from the command line to a ``Manager`` instance:: # manage.py from flask.ext.script import Manager from myapp import app manager = Manager(app) @manager.command def hello(): print "hello" if __name__ == "__main__": manager.run() Once you define your script commands, you can then run them on the command line:: python manage.py hello > hello Source code and issue tracking at `GitHub`_. Installing Flask-Script ------------------------ Install with **pip** and **easy_install**:: pip install Flask-Script or download the latest version from version control:: git clone https://github.com/techniq/flask-script.git cd flask-script python setup.py develop If you are using **virtualenv**, it is assumed that you are installing **Flask-Script** in the same virtualenv as your Flask application(s). Creating and running commands ----------------------------- The first step is to create a Python module to run your script commands in. You can call it anything you like, for our examples we'll call it **manage.py**. You don't have to place all your commands in the same file; for example, in a larger project with lots of commands you might want to split them into a number of files with related commands. In your **manage.py** file you have to create a ``Manager`` instance. The ``Manager`` class keeps track of all the commands and handles how they are called from the command line:: from flask.ext.script import Manager app = Flask(__name__) # configure your app manager = Manager(app) if __name__ == "__main__": manager.run() Calling ``manager.run()`` prepares your ``Manager`` instance to receive input from the command line. The ``Manager`` requires a single argument, a **Flask** instance. This may also be a function or other callable that returns a **Flask** instance instead, if you want to use a factory pattern. The next step is to create and add your commands. There are three methods for creating commands: * subclassing the ``Command`` class * using the ``@command`` decorator * using the ``@option`` decorator To take a very simple example, we want to create a **Hello** command that just prints out "hello world". It doesn't take any arguments so is very straightforward:: from flask.ext.script import Command class Hello(Command): "prints hello world" def run(self): print "hello world" Now the command needs to be added to our ``Manager`` instance, like the one created above:: manager.add_command('hello', Hello()) This of course needs to be called before ``manager.run``. Now in our command line:: python manage.py hello > hello world You can also pass the ``Command`` instance in a dict to ``manager.run()``:: manager.run({'hello' : Hello()}) The ``Command`` class must define a ``run`` method. The positional and optional arguments depend on the command-line arguments you pass to the ``Command`` (see below). To get a list of available commands and their descriptions, just run with no command:: python manage.py To get help text for a particular command:: python manage.py runserver -h This will print usage plus the docstring of the ``Command``. This first method is probably the most flexible, but it's also the most verbose. For simpler commands you can use the ``@command`` decorator, which belongs to the ``Manager`` instance:: @manager.command def hello(): "Just say hello" print "hello" Commands created this way are run in exactly the same way as those created with the ``Command`` class:: python manage.py hello > hello As with the ``Command`` class, the docstring you use for the function will appear when you run with the **-h** option:: python manage.py -h > Just say hello Finally, the ``@option`` decorator, again belonging to ``Manager`` can be used when you want more sophisticated control over your commands:: @manager.option('-n', '--name', help='Your name') def hello(name): print "hello", name The ``@option`` decorator is explained in more detail below. Adding arguments to commands ---------------------------- Most commands take a number of named or positional arguments that you pass in the command line. Taking the above examples, rather than just print "hello world" we would like to be able to print some arbitrary name, like this:: python manage.py hello --name=Joe hello Joe or alternatively:: python manage.py hello -n Joe To facilitate this you use the ``option_list`` attribute of the ``Command`` class:: from flask.ext.script import Command, Manager, Option class Hello(Command): option_list = ( Option('--name', '-n', dest='name'), ) def run(self, name): print "hello %s" % name Positional and optional arguments are stored as ``Option`` instances - see the :ref:`api` below for details. Alternatively, you can define a ``get_options`` method for your ``Command`` class. This is useful if you want to be able to return options at runtime based on for example per-instance attributes:: class Hello(Command): def __init__(self, default_name='Joe'): self.default_name=default_name def get_options(self): return [ Option('-n', '--name', dest='name', default=self.default_name), ] def run(self, name): print "hello", name If you are using the ``@command`` decorator, it's much easier - the options are extracted automatically from your function arguments. This is an example of a positional argument:: @manager.command def hello(name): print "hello", name You then invoke this on the command line like so:: > python manage.py hello Joe hello Joe Or you can do optional arguments:: @manager.command def hello(name="Fred") print hello, name These can be called like so:: > python manage.py hello --name=Joe hello Joe alternatively:: > python manage.py hello -n Joe hello Joe There are a couple of important points to note here. The short-form **-n** is formed from the first letter of the argument, so "name" > "-n". Therefore it's a good idea that your optional argument variable names begin with different letters. The second issue is that the **-h** switch always runs the help text for that command, so avoid arguments starting with the letter "h". Note also that if your optional argument is a boolean, for example:: @manage.command def verify(verified=False): """ Checks if verified """ print "VERIFIED?", "YES" if verified else "NO" You can just call it like this:: > python manage.py verify VERIFIED? NO > python manage.py verify -v VERIFIED? YES > python manage.py verify --verified VERIFIED? YES The ``@command`` decorator is fine for simple operations, but often you need the flexibility. For more sophisticated options it's better to use the ``@option`` decorator:: @manager.option('-n', '--name', dest='name', default='joe') def hello(name): print "hello", name You can add as many options as you want:: @manager.option('-n', '--name', dest='name', default='joe') @manager.option('-u', '--url', dest='url', default=None) def hello(name, url): if url is None: print "hello", name else: print "hello", name, "from", url This can be called like so:: > python manage.py hello -n Joe -u reddit.com hello Joe from reddit.com or alternatively:: > python manage.py hello --name=Joe --url=reddit.com hello Joe from reddit.com Adding options to the manager ----------------------------- Options can also be passed to the ``Manager`` instance. This is allows you to set up options that are passed to the application rather than a single command. For example, you might want to have a flag to set the configuration file for your application. Suppose you create your application with a factory function:: def create_app(config=None): app = Flask(__name__) if config is not None: app.config.from_pyfile(config) # configure your app... return app You want to be able to define the ``config`` argument on the command line - for example, if you have a command to set up your database, you most certainly want to use different configuration files for production and development. In order to pass that ``config`` argument, use the ``add_option()`` method of your ``Manager`` instance. It takes the same arguments as ``Option``:: manager.add_option('-c', '--config', dest='config', required=False) As with any other **Flask-Script** configuration you can call this anywhere in your script module, but it must be called before your ``manager.run()`` call. Suppose you have this command:: @manager.command def hello(name): uppercase = app.config.get('USE_UPPERCASE', False) if uppercase: name = name.upper() print hello, name You can now run the following:: > python manage.py hello joe -c dev.cfg hello JOE Assuming the ``USE_UPPERCASE`` setting is **True** in your dev.cfg file. Notice also that the "config" option is **not** passed to the command. In order for manager options to work you must pass a factory function, rather than a Flask instance, to your ``Manager`` constructor. A simple but complete example is available in `this gist `_. Getting user input ------------------ **Flask-Script** comes with a set of helper functions for grabbing user input from the command line. For example:: from flask.ext.script import Manager, prompt_bool from myapp import app from myapp.models import db manager = Manager(app) @manager.command def dropdb(): if prompt_bool( "Are you sure you want to lose all your data"): db.drop_all() It then runs like this:: python manage.py dropdb > Are you sure you want to lose all your data ? [N] See the :ref:`api` below for details on the various prompt functions. Default commands ---------------- **Flask-Script** has a couple of ready commands you can add and customise: ``Server`` and ``Shell``. The ``Server`` command runs the **Flask** development server. It takes an optional ``port`` argument (default **5000**):: from flask.ext.script import Server, Manager from myapp import create_app manager = Manager(create_app) manager.add_command("runserver", Server()) if __name__ == "__main__": manager.run() and then run the command:: python manage.py runserver The ``Server`` command has a number of command-line arguments - run ``python manage.py runserver -h`` for details on these. You can redefine the defaults in the constructor:: server = Server(host="0.0.0.0", port=9000) Needless to say the development server is not intended for production use. The ``Shell`` command starts a Python shell. You can pass in a ``make_context`` argument, which must be a ``callable`` returning a ``dict``. By default, this is just a dict returning the your Flask application instance:: from flask.ext.script import Shell, Manager from myapp import app from myapp import models from myapp.models import db def _make_context(): return dict(app=app, db=db, models=models) manager = Manager(create_app) manager.add_command("shell", Shell(make_context=_make_context)) This is handy if you want to include a bunch of defaults in your shell to save typing lots of ``import`` statements. The ``Shell`` command will use `IPython `_ if it is installed, otherwise it defaults to the standard Python shell. You can disable this behaviour in two ways: by passing the ``use_ipython`` argument to the ``Shell`` constructor, or passing the flag ``--no-ipython`` in the command line:: shell = Shell(use_ipython=False) There is also a ``shell`` decorator which you can use with a context function:: @manager.shell def make_shell_context(): return dict(app=app, db=db, models=models) This enables a **shell** command with the defaults enabled:: > python manage.py shell The default commands **shell** and **runserver** are included by default, with the default options for these commands. If you wish to replace them with different commands simply override with ``add_command()`` or the decorators. If you pass ``with_default_commands=False`` to the ``Manager`` constructor these commands will not be loaded:: manager = Manager(app, with_default_commands=False) Sub-Managers ------------ A Sub-Manager is an instance of ``Manager`` added as a command to another Manager To create a submanager:: sub_manager = Manager() manager = Manager(self.app) manager.add_command("sub_manager", sub_manager) Restrictions - A sub-manager does not provide an app instance/factory when created, it defers the calls to it's parent Manager's - A sub-manager inhert's the parent Manager's app options (used for the app instance/factory) - A sub-manager does not get default commands added to itself (by default) - A sub-manager must be added the primary/root ``Manager`` instance via ``add_command(sub_manager)`` - A sub-manager can be added to another sub-manager as long as the parent sub-manager is added to the primary/root Manager *New in version 0.5.0.* Note to extension developers ---------------------------- Extension developers can easily create convenient sub-manager instance within their extensions to make it easy for a user to consume all the available commands of an extension. Here is an example how a database extension could provide (ex. database.py):: manager = Manager(usage="Perform database operations") @manager.command def drop(): "Drops database tables" if prompt_bool("Are you sure you want to lose all your data"): db.drop_all() @manager.command def create(default_data=True, sample_data=False): "Creates database tables from sqlalchemy models" db.create_all() populate(default_data, sample_data) @manager.command def recreate(default_data=True, sample_data=False): "Recreates database tables (same as issuing 'drop' and then 'create')" drop() create(default_data, sample_data) @manager.command def populate(default_data=False, sample_data=False): "Populate database with default data" from fixtures import dbfixture if default_data: from fixtures.default_data import all default_data = dbfixture.data(*all) default_data.setup() if sample_data: from fixtures.sample_data import all sample_data = dbfixture.data(*all) sample_data.setup() Then the user can register the sub-manager to their primary Manager (within manage.py):: manager = Manager(app) from flask.ext.database import manager as database_manager manager.add_command("database", database_manager) The commands will then be available:: > python manage.py database Please provide a command: Perform database operations create Creates database tables from sqlalchemy models drop Drops database tables populate Populate database with default data recreate Recreates database tables (same as issuing 'drop' and then 'create') Accessing local proxies ----------------------- The ``Manager`` runs the command inside a `Flask test context `_. This means that you can access request-local proxies where appropriate, such as ``current_app``, which may be used by extensions. .. _api: API --- .. module:: flask_script .. autoclass:: Manager :members: run, add_option, add_command, command, option, shell, get_usage, print_usage .. autoclass:: Command :members: run, get_options .. autoclass:: Shell .. autoclass:: Server .. autoclass:: Option .. autoclass:: Group .. autofunction:: prompt .. autofunction:: prompt_bool .. autofunction:: prompt_pass .. autofunction:: prompt_choices .. _Flask: http://flask.pocoo.org .. _GitHub: http://github.com/techniq/flask-script .. _argparse: http://pypi.python.org/pypi/argparse Flask-Script-0.6.7/docs/make.bat0000644000076500000240000001003211765767607017205 0ustar smlynchstaff00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. singlehtml to make a single large HTML file echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml echo. echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\flask-unittest.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\flask-unittest.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp echo. echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub echo. echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text echo. echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man echo. echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end Flask-Script-0.6.7/docs/Makefile0000644000076500000240000001101611765767607017243 0ustar smlynchstaff00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " singlehtml to make a single large HTML file" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " text to make text files" @echo " man to make manual pages" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/flask-unittest.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/flask-unittest.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/flask-unittest" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/flask-unittest" @echo "# devhelp" epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make' in that directory to run these through (pdf)latex" \ "(use \`make latexpdf' here to do that automatically)." latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." make -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." Flask-Script-0.6.7/flask_script/0000755000076500000240000000000012300146140017301 5ustar smlynchstaff00000000000000Flask-Script-0.6.7/flask_script/__init__.py0000644000076500000240000003221112275721160021425 0ustar smlynchstaff00000000000000# -*- coding: utf-8 -*- from __future__ import absolute_import import os import re import sys import types import inspect import warnings import argparse from flask import Flask from ._compat import text_type, iteritems, izip from .commands import Group, Option, Command, Server, Shell from .cli import prompt, prompt_pass, prompt_bool, prompt_choices __all__ = ["Command", "Shell", "Server", "Manager", "Group", "Option", "prompt", "prompt_pass", "prompt_bool", "prompt_choices"] safe_actions = (argparse._StoreAction, argparse._StoreConstAction, argparse._StoreTrueAction, argparse._StoreFalseAction, argparse._AppendAction, argparse._AppendConstAction, argparse._CountAction) try: import argcomplete ARGCOMPLETE_IMPORTED = True except ImportError: ARGCOMPLETE_IMPORTED = False class Manager(object): """ Controller class for handling a set of commands. Typical usage:: class Print(Command): def run(self): print "hello" app = Flask(__name__) manager = Manager(app) manager.add_command("print", Print()) if __name__ == "__main__": manager.run() On command line:: python manage.py print > hello :param app: Flask instance or callable returning a Flask instance. :param with_default_commands: load commands **runserver** and **shell** by default. :param disable_argcomplete: disable automatic loading of argcomplete. """ def __init__(self, app=None, with_default_commands=None, usage=None, help=None, description=None, disable_argcomplete=False): self.app = app self._commands = dict() self._options = list() # Primary/root Manager instance adds default commands by default, # Sub-Managers do not if with_default_commands or (app and with_default_commands is None): self.add_default_commands() self.usage = usage self.help = help if help is not None else usage self.description = description if description is not None else usage self.disable_argcomplete = disable_argcomplete self.parent = None def add_default_commands(self): """ Adds the shell and runserver default commands. To override these simply add your own equivalents using add_command or decorators. """ self.add_command("shell", Shell()) self.add_command("runserver", Server()) def add_option(self, *args, **kwargs): """ Adds an application-wide option. This is useful if you want to set variables applying to the application setup, rather than individual commands. For this to work, the manager must be initialized with a factory function rather than an instance. Otherwise any options you set will be ignored. The arguments are then passed to your function, e.g.:: def create_app(config=None): app = Flask(__name__) if config: app.config.from_pyfile(config) return app manager = Manager(create_app) manager.add_option("-c", "--config", dest="config", required=False) and are evoked like this:: > python manage.py -c dev.cfg mycommand Any manager options passed in the command line will not be passed to the command. Arguments for this function are the same as for the Option class. """ self._options.append(Option(*args, **kwargs)) def create_app(self, **kwargs): if self.parent: # Sub-manager, defer to parent Manager return self.parent.create_app(**kwargs) if isinstance(self.app, Flask): return self.app return self.app(**kwargs) def create_parser(self, prog, parents=None): """ Creates an ArgumentParser instance from options returned by get_options(), and a subparser for the given command. """ prog = os.path.basename(prog) options_parser = argparse.ArgumentParser(add_help=False) for option in self.get_options(): options_parser.add_argument(*option.args, **option.kwargs) # parser_parents = parents if parents else [option_parser] # parser_parents = [options_parser] parser = argparse.ArgumentParser(prog=prog, usage=self.usage, description=self.description, parents=[options_parser]) self._patch_argparser(parser) subparsers = parser.add_subparsers() for name, command in self._commands.items(): usage = getattr(command, 'usage', None) help = getattr(command, 'help', command.__doc__) description = getattr(command, 'description', command.__doc__) # Only pass `parents` argument for commands that support it try: command_parser = command.create_parser(name, parents=[options_parser]) except TypeError: warnings.warn("create_parser for {0} command should accept a `parents` argument".format(name), DeprecationWarning) command_parser = command.create_parser(name) subparser = subparsers.add_parser(name, usage=usage, help=help, description=description, parents=[command_parser], add_help=False) if isinstance(command, Manager): self._patch_argparser(subparser) ## enable autocomplete only for parent parser when argcomplete is ## imported and it is NOT disabled in constructor if parents is None and ARGCOMPLETE_IMPORTED \ and not self.disable_argcomplete: argcomplete.autocomplete(parser, always_complete_options=True) return parser # def foo(self, app, *args, **kwargs): # print(args) def _patch_argparser(self, parser): """ Patches the parser to print the full help if no arguments are supplied """ def _parse_known_args(self, arg_strings, *args, **kw): if not arg_strings: self.print_help() self.exit(2) return self._parse_known_args2(arg_strings, *args, **kw) parser._parse_known_args2 = parser._parse_known_args parser._parse_known_args = types.MethodType(_parse_known_args, parser) def get_options(self): if self.parent: return self.parent._options return self._options def add_command(self, *args, **kwargs): """ Adds command to registry. :param command: Command instance :param name: Name of the command (optional) :param namespace: Namespace of the command (optional; pass as kwarg) """ if len(args) == 1: command = args[0] name = None else: name, command = args if name is None: if hasattr(command, 'name'): name = command.name else: name = type(command).__name__.lower() name = re.sub(r'command$', '', name) if isinstance(command, Manager): command.parent = self if isinstance(command, type): command = command() namespace = kwargs.get('namespace') if not namespace: namespace = getattr(command, 'namespace', None) if namespace: if namespace not in self._commands: self.add_command(namespace, Manager()) self._commands[namespace]._commands[name] = command else: self._commands[name] = command def command(self, func): """ Decorator to add a command function to the registry. :param func: command function.Arguments depend on the options. """ args, varargs, keywords, defaults = inspect.getargspec(func) options = [] # first arg is always "app" : ignore defaults = defaults or [] kwargs = dict(izip(*[reversed(l) for l in (args, defaults)])) for arg in args: if arg in kwargs: default = kwargs[arg] if isinstance(default, bool): options.append(Option('-%s' % arg[0], '--%s' % arg, action="store_true", dest=arg, required=False, default=default)) else: options.append(Option('-%s' % arg[0], '--%s' % arg, dest=arg, type=text_type, required=False, default=default)) else: options.append(Option(arg, type=text_type)) command = Command() command.run = func command.__doc__ = func.__doc__ command.option_list = options self.add_command(func.__name__, command) return func def option(self, *args, **kwargs): """ Decorator to add an option to a function. Automatically registers the function - do not use together with ``@command``. You can add as many ``@option`` calls as you like, for example:: @option('-n', '--name', dest='name') @option('-u', '--url', dest='url') def hello(name, url): print "hello", name, url Takes the same arguments as the ``Option`` constructor. """ option = Option(*args, **kwargs) def decorate(func): name = func.__name__ if name not in self._commands: command = Command() command.run = func command.__doc__ = func.__doc__ command.option_list = [] self.add_command(name, command) self._commands[name].option_list.append(option) return func return decorate def shell(self, func): """ Decorator that wraps function in shell command. This is equivalent to:: def _make_context(app): return dict(app=app) manager.add_command("shell", Shell(make_context=_make_context)) The decorated function should take a single "app" argument, and return a dict. For more sophisticated usage use the Shell class. """ self.add_command('shell', Shell(make_context=func)) return func def handle(self, prog, args=None): app_parser = self.create_parser(prog) args = list(args or []) app_namespace, remaining_args = app_parser.parse_known_args(args) # get the handle function and remove it from parsed options kwargs = app_namespace.__dict__ handle = kwargs.pop('func_handle', None) if not handle: app_parser.error('too few arguments') # get only safe config options app_config_keys = [action.dest for action in app_parser._actions if action.__class__ in safe_actions] # pass only safe app config keys app_config = dict((k, v) for k, v in iteritems(kwargs) if k in app_config_keys) # remove application config keys from handle kwargs kwargs = dict((k, v) for k, v in iteritems(kwargs) if k not in app_config_keys) # get command from bound handle function (py2.7+) command = handle.__self__ if getattr(command, 'capture_all_args', False): positional_args = [remaining_args] else: if len(remaining_args): # raise correct exception # FIXME maybe change capture_all_args flag app_parser.parse_args(args) # sys.exit(2) pass positional_args = [] app = self.create_app(**app_config) # for convience usage in a command self.app = app return handle(app, *positional_args, **kwargs) def run(self, commands=None, default_command=None): """ Prepares manager to receive command line input. Usually run inside "if __name__ == "__main__" block in a Python script. :param commands: optional dict of commands. Appended to any commands added using add_command(). :param default_command: name of default command to run if no arguments passed. """ if commands: self._commands.update(commands) if default_command is not None and len(sys.argv) == 1: sys.argv.append(default_command) try: result = self.handle(sys.argv[0], sys.argv[1:]) except SystemExit as e: result = e.code sys.exit(result or 0) Flask-Script-0.6.7/flask_script/_compat.py0000644000076500000240000000624612200426160021307 0ustar smlynchstaff00000000000000# -*- coding: utf-8 -*- """ flask_script._compat ~~~~~~~~~~~~~~~~~~~~ Some py2/py3 compatibility support based on a stripped down version of six so we don't have to depend on a specific version of it. :copyright: (c) 2013 by Armin Ronacher. :license: BSD, see LICENSE for more details. """ import sys PY2 = sys.version_info[0] == 2 PYPY = hasattr(sys, 'pypy_translation_info') _identity = lambda x: x if not PY2: unichr = chr range_type = range text_type = str string_types = (str, ) integer_types = (int, ) iterkeys = lambda d: iter(d.keys()) itervalues = lambda d: iter(d.values()) iteritems = lambda d: iter(d.items()) import pickle from io import BytesIO, StringIO NativeStringIO = StringIO def reraise(tp, value, tb=None): if value.__traceback__ is not tb: raise value.with_traceback(tb) raise value ifilter = filter imap = map izip = zip intern = sys.intern implements_iterator = _identity implements_to_string = _identity encode_filename = _identity get_next = lambda x: x.__next__ input = input from string import ascii_lowercase else: unichr = unichr text_type = unicode range_type = xrange string_types = (str, unicode) integer_types = (int, long) iterkeys = lambda d: d.iterkeys() itervalues = lambda d: d.itervalues() iteritems = lambda d: d.iteritems() import cPickle as pickle from cStringIO import StringIO as BytesIO, StringIO NativeStringIO = BytesIO exec('def reraise(tp, value, tb=None):\n raise tp, value, tb') from itertools import imap, izip, ifilter intern = intern def implements_iterator(cls): cls.next = cls.__next__ del cls.__next__ return cls def implements_to_string(cls): cls.__unicode__ = cls.__str__ cls.__str__ = lambda x: x.__unicode__().encode('utf-8') return cls get_next = lambda x: x.next def encode_filename(filename): if isinstance(filename, unicode): return filename.encode('utf-8') return filename input = raw_input from string import lower as ascii_lowercase def with_metaclass(meta, *bases): # This requires a bit of explanation: the basic idea is to make a # dummy metaclass for one level of class instantiation that replaces # itself with the actual metaclass. Because of internal type checks # we also need to make sure that we downgrade the custom metaclass # for one level to something closer to type (that's why __call__ and # __init__ comes back from type etc.). # # This has the advantage over six.with_metaclass in that it does not # introduce dummy classes into the final MRO. class metaclass(meta): __call__ = type.__call__ __init__ = type.__init__ def __new__(cls, name, this_bases, d): if this_bases is None: return type.__new__(cls, name, (), d) return meta(name, bases, d) return metaclass('temporary_class', None, {}) try: from urllib.parse import quote_from_bytes as url_quote except ImportError: from urllib import quote as url_quote Flask-Script-0.6.7/flask_script/cli.py0000644000076500000240000000533412200426160020431 0ustar smlynchstaff00000000000000# -*- coding: utf-8 -*- import getpass from ._compat import string_types, ascii_lowercase, input def prompt(name, default=None): """ Grab user input from command line. :param name: prompt text :param default: default value if no input provided. """ prompt = name + (default and ' [%s]' % default or '') prompt += name.endswith('?') and ' ' or ': ' while True: rv = input(prompt) if rv: return rv if default is not None: return default def prompt_pass(name, default=None): """ Grabs hidden (password) input from command line. :param name: prompt text :param default: default value if no input provided. """ prompt = name + (default and ' [%s]' % default or '') prompt += name.endswith('?') and ' ' or ': ' while True: rv = getpass.getpass(prompt) if rv: return rv if default is not None: return default def prompt_bool(name, default=False, yes_choices=None, no_choices=None): """ Grabs user input from command line and converts to boolean value. :param name: prompt text :param default: default value if no input provided. :param yes_choices: default 'y', 'yes', '1', 'on', 'true', 't' :param no_choices: default 'n', 'no', '0', 'off', 'false', 'f' """ yes_choices = yes_choices or ('y', 'yes', '1', 'on', 'true', 't') no_choices = no_choices or ('n', 'no', '0', 'off', 'false', 'f') while True: rv = prompt(name, default and yes_choices[0] or no_choices[0]) if not rv: return default if rv.lower() in yes_choices: return True elif rv.lower() in no_choices: return False def prompt_choices(name, choices, default=None, resolve=ascii_lowercase, no_choice=('none',)): """ Grabs user input from command line from set of provided choices. :param name: prompt text :param choices: list or tuple of available choices. Choices may be single strings or (key, value) tuples. :param default: default value if no input provided. :param no_choice: acceptable list of strings for "null choice" """ _choices = [] options = [] for choice in choices: if isinstance(choice, string_types): options.append(choice) else: options.append("%s [%s]" % (choice[1], choice[0])) choice = choice[0] _choices.append(choice) while True: rv = prompt(name + ' - (%s)' % ', '.join(options), default) if not rv: return default rv = resolve(rv) if rv in no_choice: return None if rv in _choices: return rv Flask-Script-0.6.7/flask_script/commands.py0000644000076500000240000003716312275721646021513 0ustar smlynchstaff00000000000000# -*- coding: utf-8 -*- from __future__ import absolute_import import os import code import warnings import string import argparse from flask import _request_ctx_stack from .cli import prompt, prompt_pass, prompt_bool, prompt_choices class InvalidCommand(Exception): pass class Group(object): """ Stores argument groups and mutually exclusive groups for `ArgumentParser.add_argument_group ` or `ArgumentParser.add_mutually_exclusive_group `. Note: The title and description params cannot be used with the exclusive or required params. :param options: A list of Option classes to add to this group :param title: A string to use as the title of the argument group :param description: A string to use as the description of the argument group :param exclusive: A boolean indicating if this is an argument group or a mutually exclusive group :param required: A boolean indicating if this mutually exclusive group must have an option selected """ def __init__(self, *options, **kwargs): self.option_list = options self.title = kwargs.pop("title", None) self.description = kwargs.pop("description", None) self.exclusive = kwargs.pop("exclusive", None) self.required = kwargs.pop("required", None) if ((self.title or self.description) and (self.required or self.exclusive)): raise TypeError("title and/or description cannot be used with " "required and/or exclusive.") super(Group, self).__init__(**kwargs) def get_options(self): """ By default, returns self.option_list. Override if you need to do instance-specific configuration. """ return self.option_list class Option(object): """ Stores positional and optional arguments for `ArgumentParser.add_argument `_. :param name_or_flags: Either a name or a list of option strings, e.g. foo or -f, --foo :param action: The basic type of action to be taken when this argument is encountered at the command-line. :param nargs: The number of command-line arguments that should be consumed. :param const: A constant value required by some action and nargs selections. :param default: The value produced if the argument is absent from the command-line. :param type: The type to which the command-line arg should be converted. :param choices: A container of the allowable values for the argument. :param required: Whether or not the command-line option may be omitted (optionals only). :param help: A brief description of what the argument does. :param metavar: A name for the argument in usage messages. :param dest: The name of the attribute to be added to the object returned by parse_args(). """ def __init__(self, *args, **kwargs): self.args = args self.kwargs = kwargs class Command(object): """ Base class for creating commands. """ option_list = [] @property def description(self): description = self.__doc__ or '' return description.strip() def add_option(self, option): """ Adds Option to option list. """ self.option_list.append(option) def get_options(self): """ By default, returns self.option_list. Override if you need to do instance-specific configuration. """ return self.option_list def create_parser(self, *args, **kwargs): parser = argparse.ArgumentParser(*args, **kwargs) for option in self.get_options(): if isinstance(option, Group): if option.exclusive: group = parser.add_mutually_exclusive_group( required=option.required, ) else: group = parser.add_argument_group( title=option.title, description=option.description, ) for opt in option.get_options(): group.add_argument(*opt.args, **opt.kwargs) else: parser.add_argument(*option.args, **option.kwargs) parser.set_defaults(func_handle=self.handle) return parser def handle(self, app, *args, **kwargs): """ Handles the command with given app. Default behaviour is to call within a test request context. """ with app.test_request_context(): return self.run(*args, **kwargs) def run(self): """ Runs a command. This must be implemented by the subclass. Should take arguments as configured by the Command options. """ raise NotImplementedError def prompt(self, name, default=None): warnings.warn_explicit( "Command.prompt is deprecated, use prompt() function instead") prompt(name, default) def prompt_pass(self, name, default=None): warnings.warn_explicit( "Command.prompt_pass is deprecated, use prompt_pass() function " "instead") prompt_pass(name, default) def prompt_bool(self, name, default=False): warnings.warn_explicit( "Command.prompt_bool is deprecated, use prompt_bool() function " "instead") prompt_bool(name, default) def prompt_choices(self, name, choices, default=None): warnings.warn_explicit( "Command.choices is deprecated, use prompt_choices() function " "instead") prompt_choices(name, choices, default) class Shell(Command): """ Runs a Python shell inside Flask application context. :param banner: banner appearing at top of shell when started :param make_context: a callable returning a dict of variables used in the shell namespace. By default returns a dict consisting of just the app. :param use_bpython: use BPython shell if available, ignore if not. The BPython shell can be turned off in command line by passing the **--no-bpython** flag. :param use_ipython: use IPython shell if available, ignore if not. The IPython shell can be turned off in command line by passing the **--no-ipython** flag. """ banner = '' help = description = 'Runs a Python shell inside Flask application context.' def __init__(self, banner=None, make_context=None, use_ipython=True, use_bpython=True): self.banner = banner or self.banner self.use_ipython = use_ipython self.use_bpython = use_bpython if make_context is None: make_context = lambda: dict(app=_request_ctx_stack.top.app) self.make_context = make_context def get_options(self): return ( Option('--no-ipython', action="store_true", dest='no_ipython', default=not(self.use_ipython)), Option('--no-bpython', action="store_true", dest='no_bpython', default=not(self.use_bpython)) ) def get_context(self): """ Returns a dict of context variables added to the shell namespace. """ return self.make_context() def run(self, no_ipython, no_bpython): """ Runs the shell. If no_bpython is False or use_bpython is True, then a BPython shell is run (if installed). Else, if no_ipython is False or use_python is True then a IPython shell is run (if installed). """ context = self.get_context() if not no_bpython: # Try BPython try: from bpython import embed embed(banner=self.banner, locals_=context) return except ImportError: pass if not no_ipython: # Try IPython try: try: # 0.10.x from IPython.Shell import IPShellEmbed ipshell = IPShellEmbed(banner=self.banner) ipshell(global_ns=dict(), local_ns=context) except ImportError: # 0.12+ from IPython import embed embed(banner1=self.banner, user_ns=context) return except ImportError: pass # Use basic python shell code.interact(self.banner, local=context) class Server(Command): """ Runs the Flask development server i.e. app.run() :param host: server host :param port: server port :param use_debugger: if False, will no longer use Werkzeug debugger. This can be overriden in the command line by passing the **-d** flag. :param use_reloader: if False, will no longer use auto-reloader. This can be overriden in the command line by passing the **-r** flag. :param threaded: should the process handle each request in a separate thread? :param processes: number of processes to spawn :param passthrough_errors: disable the error catching. This means that the server will die on errors but it can be useful to hook debuggers in (pdb etc.) :param options: :func:`werkzeug.run_simple` options. """ help = description = 'Runs the Flask development server i.e. app.run()' def __init__(self, host='127.0.0.1', port=5000, use_debugger=True, use_reloader=True, threaded=False, processes=1, passthrough_errors=False, **options): self.port = port self.host = host self.use_debugger = use_debugger self.use_reloader = use_reloader self.server_options = options self.threaded = threaded self.processes = processes self.passthrough_errors = passthrough_errors def get_options(self): options = ( Option('-t', '--host', dest='host', default=self.host), Option('-p', '--port', dest='port', type=int, default=self.port), Option('--threaded', dest='threaded', action='store_true', default=self.threaded), Option('--processes', dest='processes', type=int, default=self.processes), Option('--passthrough-errors', action='store_true', dest='passthrough_errors', default=self.passthrough_errors), ) if self.use_debugger: options += (Option('-d', '--no-debug', action='store_false', dest='use_debugger', default=self.use_debugger),) else: options += (Option('-d', '--debug', action='store_true', dest='use_debugger', default=self.use_debugger),) if self.use_reloader: options += (Option('-r', '--no-reload', action='store_false', dest='use_reloader', default=self.use_reloader),) else: options += (Option('-r', '--reload', action='store_true', dest='use_reloader', default=self.use_reloader),) return options def handle(self, app, host, port, use_debugger, use_reloader, threaded, processes, passthrough_errors): # we don't need to run the server in request context # so just run it directly app.run(host=host, port=port, debug=use_debugger, use_debugger=use_debugger, use_reloader=use_reloader, threaded=threaded, processes=processes, passthrough_errors=passthrough_errors, **self.server_options) class Clean(Command): "Remove *.pyc and *.pyo files recursively starting at current directory" def run(self): for dirpath, dirnames, filenames in os.walk('.'): for filename in filenames: if filename.endswith('.pyc') or filename.endswith('.pyo'): full_pathname = os.path.join(dirpath, filename) print('Removing %s' % full_pathname) os.remove(full_pathname) class ShowUrls(Command): """ Displays all of the url matching routes for the project """ def __init__(self, order='rule'): self.order = order def get_options(self): return ( Option('url', nargs='?', help='Url to test (ex. /static/image.png)'), Option('--order', dest='order', default=self.order, help='Property on Rule to order by (default: %s)' % self.order) ) return options def run(self, url, order): from flask import current_app from werkzeug.exceptions import NotFound, MethodNotAllowed rows = [] column_length = 0 column_headers = ('Rule', 'Endpoint', 'Arguments') if url: try: rule, arguments = current_app.url_map \ .bind('localhost') \ .match(url, return_rule=True) rows.append((rule.rule, rule.endpoint, arguments)) column_length = 3 except (NotFound, MethodNotAllowed) as e: rows.append(("<%s>" % e, None, None)) column_length = 1 else: rules = sorted(current_app.url_map.iter_rules(), key=lambda rule: getattr(rule, order)) for rule in rules: rows.append((rule.rule, rule.endpoint, None)) column_length = 2 str_template = '' table_width = 0 if column_length >= 1: max_rule_length = max(len(r[0]) for r in rows) max_rule_length = max_rule_length if max_rule_length > 4 else 4 str_template += '%-' + str(max_rule_length) + 's' table_width += max_rule_length if column_length >= 2: max_endpoint_length = max(len(str(r[1])) for r in rows) # max_endpoint_length = max(rows, key=len) max_endpoint_length = max_endpoint_length if max_endpoint_length > 8 else 8 str_template += ' %-' + str(max_endpoint_length) + 's' table_width += 2 + max_endpoint_length if column_length >= 3: max_arguments_length = max(len(str(r[2])) for r in rows) max_arguments_length = max_arguments_length if max_arguments_length > 9 else 9 str_template += ' %-' + str(max_arguments_length) + 's' table_width += 2 + max_arguments_length print(str_template % (column_headers[:column_length])) print('-' * table_width) for row in rows: print(str_template % row[:column_length]) Flask-Script-0.6.7/Flask_Script.egg-info/0000755000076500000240000000000012300146140020673 5ustar smlynchstaff00000000000000Flask-Script-0.6.7/Flask_Script.egg-info/dependency_links.txt0000644000076500000240000000000112300146137024747 0ustar smlynchstaff00000000000000 Flask-Script-0.6.7/Flask_Script.egg-info/not-zip-safe0000644000076500000240000000000111765773514023152 0ustar smlynchstaff00000000000000 Flask-Script-0.6.7/Flask_Script.egg-info/PKG-INFO0000644000076500000240000000215312300146137021777 0ustar smlynchstaff00000000000000Metadata-Version: 1.1 Name: Flask-Script Version: 0.6.7 Summary: Scripting support for Flask Home-page: http://github.com/techniq/flask-script Author: Sean Lynch Author-email: techniq35@gmail.com License: BSD Description: Flask-Script -------------- Flask support for writing external scripts. Links ````` * `documentation `_ Platform: any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Flask-Script-0.6.7/Flask_Script.egg-info/requires.txt0000644000076500000240000000000512300146137023274 0ustar smlynchstaff00000000000000FlaskFlask-Script-0.6.7/Flask_Script.egg-info/SOURCES.txt0000644000076500000240000000136512300146140022564 0ustar smlynchstaff00000000000000LICENSE MANIFEST.in README.rst setup.cfg setup.py tests.py Flask_Script.egg-info/PKG-INFO Flask_Script.egg-info/SOURCES.txt Flask_Script.egg-info/dependency_links.txt Flask_Script.egg-info/not-zip-safe Flask_Script.egg-info/requires.txt Flask_Script.egg-info/top_level.txt docs/.DS_Store docs/Makefile docs/conf.py docs/index.rst docs/make.bat docs/_static/flask-script.png docs/_static/index.html docs/_static/index.zip docs/_themes/README docs/_themes/flask_theme_support.py docs/_themes/flask/theme.conf docs/_themes/flask/static/flasky.css_t docs/_themes/flask_small/layout.html docs/_themes/flask_small/theme.conf docs/_themes/flask_small/static/flasky.css_t flask_script/__init__.py flask_script/_compat.py flask_script/cli.py flask_script/commands.pyFlask-Script-0.6.7/Flask_Script.egg-info/top_level.txt0000644000076500000240000000001512300146137023427 0ustar smlynchstaff00000000000000flask_script Flask-Script-0.6.7/LICENSE0000644000076500000240000000265411765767607015670 0ustar smlynchstaff00000000000000Copyright (c) 2010 by Dan Jacob. Some 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. * The names of the contributors may not 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. Flask-Script-0.6.7/MANIFEST.in0000644000076500000240000000022611765767607016412 0ustar smlynchstaff00000000000000include LICENSE tests.py recursive-include docs * recursive-exclude docs *.pyc recursive-exclude docs *.pyo prune docs/_build prune docs/_themes/.git Flask-Script-0.6.7/PKG-INFO0000644000076500000240000000215312300146140015713 0ustar smlynchstaff00000000000000Metadata-Version: 1.1 Name: Flask-Script Version: 0.6.7 Summary: Scripting support for Flask Home-page: http://github.com/techniq/flask-script Author: Sean Lynch Author-email: techniq35@gmail.com License: BSD Description: Flask-Script -------------- Flask support for writing external scripts. Links ````` * `documentation `_ Platform: any Classifier: Development Status :: 4 - Beta Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.3 Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules Flask-Script-0.6.7/README.rst0000644000076500000240000000102412126641330016310 0ustar smlynchstaff00000000000000Flask-Script ============== .. image:: https://travis-ci.org/techniq/flask-script.png?branch=master :target: https://travis-ci.org/techniq/flask-script A set of utilities for use with the Flask framework, which provide decorators, classes and helpers for writing your own script commands. Useful for creating command-line scripts, cronjobs etc outside your web application. Resources --------- - `Documentation `_ - `Issue Tracker `_ Flask-Script-0.6.7/setup.cfg0000644000076500000240000000026312300146140016437 0ustar smlynchstaff00000000000000[build_sphinx] source-dir = docs/ build-dir = docs/_build all_files = 1 [upload_sphinx] upload-dir = docs/_build/html [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 Flask-Script-0.6.7/setup.py0000644000076500000240000000334512300145733016343 0ustar smlynchstaff00000000000000""" Flask-Script -------------- Flask support for writing external scripts. Links ````` * `documentation `_ """ import sys from setuptools import setup # Hack to prevent stupid TypeError: 'NoneType' object is not callable error on # exit of python setup.py test # in multiprocessing/util.py _exit_function when # running python setup.py test (see # https://github.com/pypa/virtualenv/pull/259) try: import multiprocessing except ImportError: pass install_requires = ['Flask'] if sys.version_info < (2, 7): install_requires += ['argparse'] setup( name='Flask-Script', version='0.6.7', url='http://github.com/techniq/flask-script', license='BSD', author='Dan Jacob', author_email='danjac354@gmail.com', maintainer='Sean Lynch', maintainer_email='techniq35@gmail.com', description='Scripting support for Flask', long_description=__doc__, packages=[ 'flask_script' ], zip_safe=False, install_requires=install_requires, tests_require=[ 'pytest', ], platforms='any', classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.3', 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 'Topic :: Software Development :: Libraries :: Python Modules' ] ) Flask-Script-0.6.7/tests.py0000644000076500000240000005234612275721160016357 0ustar smlynchstaff00000000000000# -*- coding: utf-8 -*- import re import sys import unittest from flask import Flask from flask.ext.script._compat import StringIO, text_type from flask.ext.script import Command, Manager, Option, prompt, prompt_bool from pytest import raises class Catcher(object): """Helper decorator to test raw_input.""" ## see: http://stackoverflow.com/questions/13480632/python-stringio-selectively-place-data-into-stdin def __init__(self, handler): self.handler = handler self.inputs = [] def __enter__(self): self.__stdin = sys.stdin self.__stdout = sys.stdout sys.stdin = self sys.stdout = self def __exit__(self, type, value, traceback): sys.stdin = self.__stdin sys.stdout = self.__stdout def write(self, value): self.__stdout.write(value) result = self.handler(value) if result is not None: self.inputs.append(result) def readline(self): return self.inputs.pop() def getvalue(self): return self.__stdout.getvalue() def truncate(self, pos): return self.__stdout.truncate(pos) def run(command_line, manager_run): ''' Returns tuple of standard output and exit code ''' sys.argv = command_line.split() exit_code = None try: manager_run() except SystemExit as e: exit_code = e.code return exit_code class SimpleCommand(Command): 'simple command' def run(self): print('OK') class NamedCommand(Command): 'named command' def run(self): print('OK') class ExplicitNamedCommand(Command): 'named command' name = 'named' def run(self): print('OK') class NamespacedCommand(Command): 'namespaced command' namespace = 'ns' def run(self): print('OK') class CommandWithArgs(Command): 'command with args' option_list = ( Option('name'), ) def run(self, name): print(name) class CommandWithOptions(Command): 'command with options' option_list = ( Option('-n', '--name', help='name to pass in', dest='name'), ) def run(self, name): print(name) class CommandWithDynamicOptions(Command): 'command with options' def __init__(self, default_name='Joe'): self.default_name = default_name def get_options(self): return ( Option('-n', '--name', help='name to pass in', dest='name', default=self.default_name), ) def run(self, name): print(name) class CommandWithCatchAll(Command): 'command with catch all args' capture_all_args = True def get_options(self): return (Option('--foo', dest='foo', action='store_true'),) def run(self, remaining_args, foo): print(remaining_args) class TestCommands(unittest.TestCase): TESTING = True def setup(self): self.app = Flask(__name__) self.app.config.from_object(self) class TestManager: TESTING = True def setup(self): self.app = Flask(__name__) self.app.config.from_object(self) def test_with_default_commands(self): manager = Manager(self.app) assert 'runserver' in manager._commands assert 'shell' in manager._commands def test_without_default_commands(self): manager = Manager(self.app, with_default_commands=False) assert 'runserver' not in manager._commands assert 'shell' not in manager._commands def test_add_command(self): manager = Manager(self.app) manager.add_command('simple', SimpleCommand()) assert isinstance(manager._commands['simple'], SimpleCommand) def test_add_named_command(self): manager = Manager(self.app) manager.add_command(NamedCommand()) assert 'named' in manager._commands assert isinstance(manager._commands['named'], NamedCommand) def test_add_explicit_named_command(self): manager = Manager(self.app) manager.add_command(ExplicitNamedCommand()) name = ExplicitNamedCommand.name assert name in manager._commands assert isinstance(manager._commands[name], ExplicitNamedCommand) def test_add_namespaced_command(self): manager = Manager(self.app) manager.add_command('one', NamespacedCommand()) manager.add_command('two', NamespacedCommand()) assert 'ns' in manager._commands assert isinstance(manager._commands['ns'], Manager) ns = manager._commands['ns'] assert isinstance(ns._commands['one'], NamespacedCommand) assert isinstance(ns._commands['two'], NamespacedCommand) def test_add_namespaced_simple_command(self): manager = Manager(self.app) manager.add_command('hello', SimpleCommand(), namespace='ns') manager.add_command('world', SimpleCommand(), namespace='ns') assert 'ns' in manager._commands assert isinstance(manager._commands['ns'], Manager) ns = manager._commands['ns'] assert isinstance(ns._commands['hello'], SimpleCommand) assert isinstance(ns._commands['world'], SimpleCommand) def test_add_command_class(self): manager = Manager(self.app) manager.add_command('simple', SimpleCommand) assert isinstance(manager._commands['simple'], SimpleCommand) def test_simple_command_decorator(self, capsys): manager = Manager(self.app) @manager.command def hello(): print('hello') assert 'hello' in manager._commands code = run('manage.py hello', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello' in out def test_simple_command_decorator_with_pos_arg(self, capsys): manager = Manager(self.app) @manager.command def hello(name): print('hello ' + name) assert 'hello' in manager._commands code = run('manage.py hello joe', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello joe' in out def test_command_decorator_with_options(self, capsys): manager = Manager(self.app) @manager.command def hello(name='fred'): 'Prints your name' print('hello ' + name) assert 'hello' in manager._commands code = run('manage.py hello --name=joe', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello joe' in out code = run('manage.py hello -n joe', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello joe' in out code = run('manage.py hello -h', lambda: manager.run()) out, err = capsys.readouterr() assert 'Prints your name' in out code = run('manage.py hello --help', lambda: manager.run()) out, err = capsys.readouterr() assert 'Prints your name' in out def test_command_decorator_with_boolean_options(self, capsys): manager = Manager(self.app) @manager.command def verify(verified=False): 'Checks if verified' print('VERIFIED ? ' + 'YES' if verified else 'NO') assert 'verify' in manager._commands code = run('manage.py verify --verified', lambda: manager.run()) out, err = capsys.readouterr() assert 'YES' in out code = run('manage.py verify -v', lambda: manager.run()) out, err = capsys.readouterr() assert 'YES' in out code = run('manage.py verify', lambda: manager.run()) out, err = capsys.readouterr() assert 'NO' in out code = run('manage.py verify -h', lambda: manager.run()) out, err = capsys.readouterr() assert 'Checks if verified' in out def test_simple_command_decorator_with_pos_arg_and_options(self, capsys): manager = Manager(self.app) @manager.command def hello(name, url=None): if url: assert type(url) is text_type print('hello ' + name + ' from ' + url) else: assert type(name) is text_type print('hello ' + name) assert 'hello' in manager._commands code = run('manage.py hello joe', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello joe' in out code = run('manage.py hello joe --url=reddit.com', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello joe from reddit.com' in out def test_command_decorator_with_additional_options(self, capsys): manager = Manager(self.app) @manager.option('-n', '--name', dest='name', help='Your name') def hello(name): print('hello ' + name) assert 'hello' in manager._commands code = run('manage.py hello --name=joe', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello joe' in out code = run('manage.py hello -h', lambda: manager.run()) out, err = capsys.readouterr() assert 'Your name' in out @manager.option('-n', '--name', dest='name', help='Your name') @manager.option('-u', '--url', dest='url', help='Your URL') def hello_again(name, url=None): if url: print('hello ' + name + ' from ' + url) else: print('hello ' + name) assert 'hello_again' in manager._commands code = run('manage.py hello_again --name=joe', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello joe' in out code = run('manage.py hello_again --name=joe --url=reddit.com', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello joe from reddit.com' in out def test_global_option_provided_before_and_after_command(self, capsys): manager = Manager(self.app) manager.add_option('-c', '--config', dest='config_name', required=False, default='Development') manager.add_command('simple', SimpleCommand()) assert isinstance(manager._commands['simple'], SimpleCommand) code = run('manage.py -c Development simple', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'OK' in out code = run('manage.py simple -c Development', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'OK' in out def test_global_option_value(self, capsys): def create_app(config_name='Empty'): print(config_name) return self.app manager = Manager(create_app) manager.add_option('-c', '--config', dest='config_name', required=False, default='Development') manager.add_command('simple', SimpleCommand()) assert isinstance(manager._commands['simple'], SimpleCommand) code = run('manage.py simple', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'Empty' not in out # config_name is overwritten by default option value assert 'Development' in out assert 'OK' in out def test_get_usage(self): manager = Manager(self.app) manager.add_command('simple', SimpleCommand()) usage = manager.create_parser('manage.py').format_help() assert 'simple command' in usage def test_get_usage_with_specified_usage(self): manager = Manager(self.app, usage='hello') manager.add_command('simple', SimpleCommand()) usage = manager.create_parser('manage.py').format_help() assert 'simple command' in usage assert 'hello' in usage def test_run_existing_command(self, capsys): manager = Manager(self.app) manager.add_command('simple', SimpleCommand()) code = run('manage.py simple', lambda: manager.run()) out, err = capsys.readouterr() assert 'OK' in out def test_run_non_existant_command(self, capsys): manager = Manager(self.app) run('manage.py simple', lambda: manager.run()) out, err = capsys.readouterr() assert 'invalid choice' in err def test_run_existing(self, capsys): manager = Manager(self.app) manager.add_command('simple', SimpleCommand()) code = run('manage.py simple', lambda: manager.run()) out, err = capsys.readouterr() assert 0 == code assert 'OK' in out def test_run_existing_bind_later(self, capsys): manager = Manager(self.app) code = run('manage.py simple', lambda: manager.run({'simple': SimpleCommand()})) out, err = capsys.readouterr() assert code == 0 assert 'OK' in out def test_run_not_existing(self, capsys): manager = Manager(self.app) code = run('manage.py simple', lambda: manager.run()) out, err = capsys.readouterr() assert code == 2 assert 'OK' not in out def test_run_no_name(self, capsys): manager = Manager(self.app) manager.add_command('simple', SimpleCommand()) code = run('manage.py', lambda: manager.run()) out, err = capsys.readouterr() assert code == 2 assert 'simple command' in out def test_run_good_options(self, capsys): manager = Manager(self.app) manager.add_command('simple', CommandWithOptions()) code = run('manage.py simple --name=Joe', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'Joe' in out def test_run_dynamic_options(self, capsys): manager = Manager(self.app) manager.add_command('simple', CommandWithDynamicOptions('Fred')) code = run('manage.py simple', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'Fred' in out def test_run_catch_all(self, capsys): manager = Manager(self.app) manager.add_command('catch', CommandWithCatchAll()) code = run('manage.py catch pos1 --foo pos2 --bar', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert "['pos1', 'pos2', '--bar']" in out def test_run_bad_options(self, capsys): manager = Manager(self.app) manager.add_command('simple', CommandWithOptions()) code = run('manage.py simple --foo=bar', lambda: manager.run()) assert code == 2 def test_init_with_flask_instance(self): manager = Manager(self.app) assert callable(manager.app) def test_init_with_callable(self): manager = Manager(lambda: self.app) assert callable(manager.app) def test_raise_index_error(self): manager = Manager(self.app) @manager.command def error(): raise IndexError() with raises(IndexError): run('manage.py error', lambda: manager.run()) def test_run_with_default_command(self, capsys): manager = Manager(self.app) manager.add_command('simple', SimpleCommand()) code = run('manage.py', lambda: manager.run(default_command='simple')) out, err = capsys.readouterr() assert code == 0 assert 'OK' in out def test_command_with_prompt(self, capsys): manager = Manager(self.app) @manager.command def hello(): print(prompt(name='hello')) @Catcher def hello_john(msg): if re.search("hello", msg): return 'john' with hello_john: code = run('manage.py hello', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello: john' in out def test_command_with_default_prompt(self, capsys): manager = Manager(self.app) @manager.command def hello(): print(prompt(name='hello', default='romeo')) @Catcher def hello(msg): if re.search("hello", msg): return '\n' # just hit enter with hello: code = run('manage.py hello', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello [romeo]: romeo' in out @Catcher def hello_juliette(msg): if re.search("hello", msg): return 'juliette' with hello_juliette: code = run('manage.py hello', lambda: manager.run()) out, err = capsys.readouterr() assert 'hello [romeo]: juliette' in out def test_command_with_prompt_bool(self, capsys): manager = Manager(self.app) @manager.command def hello(): print(prompt_bool(name='correct', default=True, yes_choices=['y'], no_choices=['n']) and 'yes' or 'no') @Catcher def correct_default(msg): if re.search("correct", msg): return '\n' # just hit enter @Catcher def correct_y(msg): if re.search("correct", msg): return 'y' @Catcher def correct_n(msg): if re.search("correct", msg): return 'n' with correct_default: code = run('manage.py hello', lambda: manager.run()) out, err = capsys.readouterr() assert 'correct [y]: yes' in out with correct_y: code = run('manage.py hello', lambda: manager.run()) out, err = capsys.readouterr() assert 'correct [y]: yes' in out with correct_n: code = run('manage.py hello', lambda: manager.run()) out, err = capsys.readouterr() assert 'correct [y]: no' in out class TestSubManager: TESTING = True def setup(self): self.app = Flask(__name__) self.app.config.from_object(self) def test_add_submanager(self): sub_manager = Manager() manager = Manager(self.app) manager.add_command('sub_manager', sub_manager) assert isinstance(manager._commands['sub_manager'], Manager) assert sub_manager.parent == manager assert sub_manager.get_options() == manager.get_options() def test_run_submanager_command(self, capsys): sub_manager = Manager() sub_manager.add_command('simple', SimpleCommand()) manager = Manager(self.app) manager.add_command('sub_manager', sub_manager) code = run('manage.py sub_manager simple', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'OK' in out def test_submanager_has_options(self, capsys): sub_manager = Manager() sub_manager.add_command('simple', SimpleCommand()) manager = Manager(self.app) manager.add_command('sub_manager', sub_manager) manager.add_option('-c', '--config', dest='config', required=False) code = run('manage.py sub_manager simple', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'OK' in out code = run('manage.py -c Development sub_manager simple', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'OK' in out def test_manager_usage_with_submanager(self, capsys): sub_manager = Manager(usage='Example sub-manager') manager = Manager(self.app) manager.add_command('sub_manager', sub_manager) code = run('manage.py -h', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'Example sub-manager' in out def test_submanager_usage_and_help_and_description(self, capsys): sub_manager = Manager(usage='sub_manager [--foo]', help='shorter desc for submanager', description='longer desc for submanager') sub_manager.add_command('simple', SimpleCommand()) manager = Manager(self.app) manager.add_command('sub_manager', sub_manager) code = run('manage.py -h', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'sub_manager [--foo]' not in out assert 'shorter desc for submanager' in out assert 'longer desc for submanager' not in out code = run('manage.py sub_manager', lambda: manager.run()) out, err = capsys.readouterr() assert code == 2 assert 'sub_manager [--foo]' in out assert 'shorter desc for submanager' not in out assert 'longer desc for submanager' in out assert 'simple command' in out code = run('manage.py sub_manager -h', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'sub_manager [--foo]' in out assert 'shorter desc for submanager' not in out assert 'longer desc for submanager' in out assert 'simple command' in out code = run('manage.py sub_manager simple -h', lambda: manager.run()) out, err = capsys.readouterr() assert code == 0 assert 'sub_manager [--foo] simple [-h]' in out assert 'simple command' in out def test_submanager_has_no_default_commands(self): sub_manager = Manager() manager = Manager() manager.add_command('sub_manager', sub_manager) assert 'runserver' not in sub_manager._commands assert 'shell' not in sub_manager._commands