On Saturday 16 July 2005 23:47, Amit Aronovitch wrote:
> הי,
>
> 1) קודם כל רציתי להעיר שלפעמים יותר פשוט (וגם יותר מדמה את המצב האמיתי
> שאתה בודק) פשוט לדרוך על המשתנים הרלוונטיים במודול הקיים. במקרה שלך
> למשל, היה מספיק לעשות:
>
> import cgi
> cgi.FieldStorage = get_params
>
> (כאשר אתה עושה import mytestcgi המודול cgi לא יאותחל מחדש, כי הוא כבר ב-
> sys.modules).
>

כן, אבל אז אני מעלה את המודול האמיתי, שיגרום להרבה תוצרי-לוואי, וכן יגרום 
לתוכנית הבדיקה להיכשל משום שהיא טוענת את "cgi" מבלי שתורץ מתוך שרת וו'ב.

> 2) טעינת מודול (import) לא אמורה להריץ קוד ביצועי, אלא לבצע פעולות
> איתחול בלבד. במודולים שרוצים שיהיה אפשר להשתמש בהם גם בתור סקריפט, נהוג
> לכתוב משהו כמו:
> if __name__ == "__main__": run_main()
> (כאשר הקוד הביצועי נמצע בפונקציה run_main).

אוקיי.

> ולמה אני אומר את זה? כי בדוגמה שלך נראה כאילו פעולת import mytestcgi
> אמורה להדפיס את פלט ה- cgi.

זה נכון. כך תכננתי את המודול. במקרה שלי "mytestcgi" הוא:

<<<<<<<<<<<<<<<
import cgi

form = cgi.FieldStorage()

print "Content-Type: text/html\n\n"

print form["hello"].value;
>>>>>>>>>>>>>>>

(אני מודע שיש כאן בעיית XSS קטנה, אבל כתבתי את הקוד כדי לבדוק את עקרון 
ה-mocking.)

>
> אילו mytestcgi היה כתוב לפי הנוהג שציינתי לעיל אז החישובים וההדפסות
> נעשים לא בזמן ה- import, אלא כאשר קוראים ל- run_main. במקרה כזה אפשר
> לבצע את הדריכה על המשתנים שבסע' 1 בצורה קצת יותר ממוקדת, או אפילו להחליף
> את cgi באוביקט משלך מבלי להתעסק עם sys.modules בכלל:
>
> ‪import mytestcgi # I assume mytestcgi does "import cgi"
> mytestcgi.cgi = my_cgi_object # see comment below
> mytestcgi.run_main()
> ‬
> (הערה: אם mytestcgi עושה ‪"from cgi import ..."‬ ולא import cgi, אז צריך
> לדרוך נקודתית על שמות הפונקציות שנטענו במקום על השם cgi)
>

נראה שזה עובד:

<<<<<<<<<<<<<<<<
#!/usr/bin/python

import cgi

def run_main():
    form = cgi.FieldStorage()

    print "Content-Type: text/html\n\n"

    print form["hello"].value;

if __name__ == "__main__": run_main()
>>>>>>>>>>>>>>>>

וכן:

<<<<<<<<<<<<<
import sys
import new
from StringIO import StringIO

class cgi_param:
    def __init__(self, value):
        self.value = value
    def value(self):
        return self.value
    
def get_params():
    return {"hello":cgi_param("ShlomifTest")}

cgi_mod = new.module("cgi");
cgi_mod.FieldStorage = get_params

save_stdout = sys.stdout
sys.stdout = StringIO()
import mytestcgi

mytestcgi.cgi = cgi_mod
mytestcgi.run_main()
buffer = sys.stdout.getvalue()

sys.stdout = save_stdout

if (buffer == "Content-Type: text/html\n\n\nShlomifTest\n"):
    print "ok"
else:
    print "not ok: buffer == " + buffer
>>>>>>>>>>>>>

ככל הנראה "import cgi" לא מבצע פעילות כלשהי כשלעצמו שתגרום לו להתנהג מוזר כאשר 
הוא לא רץ כתסריט CGI. אבל אם פעולת ה-import הייתה עושה משהו כזה, אז לא ניתן 
היה להשתמש בטריק הזה.

>
> 3) סתם rant לגבי דריכות על מודולים : יש חבילות - למשל Pmw, שמחליפות (ב-
> sys.modules) מודולים באוביקט משלהן, שאמור להתנהג כמו מודול.
> מכיוון שהחיקוי אינו מלא זה גורם לצרות צרורות, וכל מיני דברים מפסיקים
> לעבוד. נניח כאשר מנסים לעבור גרסת פיתון או להשתמש ב- import hooks.
> בקיצור: לקוד פנימי, בדיקות ודיבג הכל טוב ויפה, אבל כאשר רוצים להפיץ
> חבילת תוכנה למשתמשים כדאי לנסות לעבוד בצורה פשוטה ולהמנע מהתחכמויות
> מיותרות.

כמובן.

בכבוד רב,

        שלומי פיש

---------------------------------------------------------------------
Shlomi Fish      [EMAIL PROTECTED]
Homepage:        http://www.shlomifish.org/

Tcl is LISP on drugs. Using strings instead of S-expressions for closures
is Evil with one of those gigantic E's you can find at the beginning of 
paragraphs.

לענות