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.