mail[Wesnoth-commits] r27612 - in /trunk: changelog data/ais/parse.py data/ais/safe.py src/ai_python.cpp


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by greg on June 30, 2008 - 16:07:
Author: oracle
Date: Mon Jun 30 15:44:59 2008
New Revision: 27612

URL: http://svn.gna.org/viewcvs/wesnoth?rev=27612&view=rev
Log:
get_variable now allows a default value to be passed to the call. If the
key is not found, the default value is returned. set_variable exception
handling has been fixed to return an exception in the current call frame.
Many wesnoth module functions now release the python GIL when it is both
safe to do so and the function call takes long enough where it also
makes sense. A new global boolean variable, 'restricted' is now set
before the user AI script is invoked. This variable indicates if it is
running inside of a restricted python environment or not. A new class
of unrestricted scripts are now listed. Previously only scripts which have
'#!WPY' at the top are allowed. If only allow safe python scripts is disabled,
scripts which start with #!UNSAFE_WPY are also shown to users. This allows
AI authors to specifically target either a restricted or unrestricted
environment. New "system" class attributes are exposed in the restricted
environment. These include; '__call__', '__copy__', '__deepcopy__',
'__doc__', '__name__', '__repr__' and '__str__', in addition to the
old __init__ method.


Modified:
    trunk/changelog
    trunk/data/ais/parse.py
    trunk/data/ais/safe.py
    trunk/src/ai_python.cpp

Modified: trunk/changelog
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/changelog?rev=27612&r1=27611&r2=27612&view=diff
==============================================================================
--- trunk/changelog (original)
+++ trunk/changelog Mon Jun 30 15:44:59 2008
@@ -29,7 +29,27 @@
    * Removed persistance from team configuration (bug: #10916)
    * Made automaticaly generated macro reference easier to naviagate and 
link to
         (patch: #1076)
-
+ * Python AI
+   * get_variable now allows a default value to be passed to the call. If the
+       key is not found, the default value is returned.
+   * set_variable exception handling has been fixed to return an exception in
+       the current call frame.
+   * Many wesnoth module functions now release the python GIL when it is both
+       safe to do so and the function call takes long enough where it also
+       makes sense. More changes coming.
+   * A new global boolean variable, 'restricted' is now set before the user 
AI
+       script is invoked. This variable indicates if it is running inside of
+       a restricted python environment or not.
+   * A new class of unrestricted scripts are now listed. Previously only 
scripts which have
+       #!WPY at the top are allowed. If only allow safe python scripts is 
disabled,
+       scripts which start with #!UNSAFE_WPY are also shown to users. This 
allows
+       AI authors to specifically target either a restricted or unrestricted 
environment.
+   * New "system" class attributes are exposed in the restricted 
environment. These
+       include; '__call__', '__copy__', '__deepcopy__', '__doc__', 
'__name__',
+       '__repr__' and '__str__', in addition to the old __init__ method.
+   * ValueError can now be caught.
+       
+       
 Version 1.5.1:
  * campaigns:
    * Descent into Darkness:
@@ -88,7 +108,7 @@
    * Try/Except clauses are now allowed. A subset of builtin exceptions are 
available.
        ArithmeticError, AssertionError, AttributeError, BaseException,
        StopIteration, IndexError, KeyError, NameError, RuntimeError,
-       RuntimeWarning, ZeroDivisionError
+       RuntimeWarning, and ZeroDivisionError
    * Exceptions can now be raised by user code.
  * terrains:
    * Fixed city village not being alias of the village terrain type; this was

Modified: trunk/data/ais/parse.py
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/data/ais/parse.py?rev=27612&r1=27611&r2=27612&view=diff
==============================================================================
--- trunk/data/ais/parse.py (original)
+++ trunk/data/ais/parse.py Mon Jun 30 15:44:59 2008
@@ -23,7 +23,7 @@
             except IOError:
                 pass
         else:
-            raise safe.SafeException("Could not include %s." % name)
+            raise safe.SafeException("Could not import '%s'." % name)
 
         r += code
 

Modified: trunk/data/ais/safe.py
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/data/ais/safe.py?rev=27612&r1=27611&r2=27612&view=diff
==============================================================================
--- trunk/data/ais/safe.py (original)
+++ trunk/data/ais/safe.py Mon Jun 30 15:44:59 2008
@@ -45,7 +45,8 @@
 # Expanded to allow repr, str, call, and doc. These are commonly overloaded
 # to provided fundamental functionality. Without __call__ support, most
 # categories of decorators are simply impossible.
-_STR_OK = [ '__call__', '__doc__', '__init__', '__name__', '__repr__', 
'__str__' ]
+_STR_OK = [ '__call__', '__copy__', '__deepcopy__', '__doc__',
+            '__init__', '__name__', '__repr__', '__str__' ]
 
 # If we put '__' in _STR_NOT_CONTAIN, then we can't have defacto private data
 _STR_NOT_CONTAIN = []
@@ -79,15 +80,15 @@
 
 _BUILTIN_OK = [
     '__debug__','quit','exit',
-    'Warning',
+    'Warning', 'restricted',
     'None','True','False',
     'abs', 'bool', 'callable', 'chr', 'cmp', 'complex', 'dict', 'divmod', 
'filter',
     'float', 'frozenset', 'hash', 'hex', 'int', 'isinstance', 'issubclass', 
'len',
     'list', 'long', 'map', 'max', 'min', 'object', 'oct', 'ord', 'pow', 
'range',
     'repr', 'round', 'set', 'slice', 'str', 'sum', 'super', 'tuple',  
'xrange', 'zip',
-    'ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 
'StopIteration',
-    'IndexError', 'KeyError', 'NameError', 'RuntimeError', 'RuntimeWarning',
-    'ZeroDivisionError'
+    'ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 
'Exception',
+    'IndexError', 'KeyError', 'NameError', 'RuntimeError', 'RuntimeWarning', 
'StopIteration',
+    'ValueError', 'ZeroDivisionError'
     ]
 
 _BUILTIN_STR = [
@@ -100,6 +101,7 @@
     return fnc
 _builtin_globals = None
 _builtin_globals_r = None
+
 def _builtin_init():
     global _builtin_globals, _builtin_globals_r
     if _builtin_globals != None: return
@@ -107,14 +109,22 @@
     r = _builtin_globals = {}
     for k in __builtin__.__dict__.keys():
         v = None
-        if k in _BUILTIN_OK: v = __builtin__.__dict__[k]
-        elif k in _BUILTIN_STR: v = ''
-        else: v = _builtin_fnc(k)
+        if k in _BUILTIN_OK:
+            v = __builtin__.__dict__[k]
+
+        elif k in _BUILTIN_STR:
+            v = ''
+
+        else:
+            v = _builtin_fnc(k)
+
         r[k] = v
+
 def _builtin_destroy():
     _builtin_init()
     for k,v in _builtin_globals.items():
         __builtin__.__dict__[k] = v
+
 def _builtin_restore():
     for k,v in _builtin_globals_r.items():
         __builtin__.__dict__[k] = v
@@ -147,8 +157,8 @@
 # Wrapper allowing safe_exec to be dynamically controlled
 # from wesnoth binary.
 def safe_exec( code, context=None, runSafe=True ):
-    # Allow the AI to know if it is restricted or not
-    context["restricted"] = runSafe
+    context[ 'restricted' ] = runSafe
+
     if runSafe:
         safe_exec_op( code, context )
 

Modified: trunk/src/ai_python.cpp
URL: 
http://svn.gna.org/viewcvs/wesnoth/trunk/src/ai_python.cpp?rev=27612&r1=27611&r2=27612&view=diff
==============================================================================
--- trunk/src/ai_python.cpp (original)
+++ trunk/src/ai_python.cpp Mon Jun 30 15:44:59 2008
@@ -1006,6 +1006,7 @@
 
        // Find side number of team
        int side = 0;
+       Py_BEGIN_ALLOW_THREADS
        for (size_t t = 0; t < running_instance->get_teams().size(); t++) {
                if (team->team_ == &running_instance->get_teams()[t]) {
                        side = 1 + t;
@@ -1014,6 +1015,8 @@
        }
 
        result = running_instance->current_team().is_enemy(side) == true ? 1 
: 0;
+       Py_END_ALLOW_THREADS
+
        return Py_BuildValue(INTVALUE, result);
 }
 
@@ -1705,8 +1708,13 @@
 PyObject* python_ai::wrapper_get_variable(PyObject* /*self*/, PyObject* args)
 {
        char const *variable;
-       if (!PyArg_ParseTuple(args, STRINGVALUE, &variable))
-               return NULL;
+       PyObject *default_value = Py_BuildValue( STRINGVALUE, "" ) ;
+
+       // If a default value was not provided, see if we were called with
+       // just the value to find.
+       if (!PyArg_ParseTuple(args, CC("s|O"), &variable, &default_value))
+               return NULL;
+
        config const &memory = running_instance->current_team().ai_memory();
        char const *s = memory[variable].c_str();
        if (s && s[0])
@@ -1725,10 +1733,14 @@
            }
         PyObject *ret = PyMarshal_ReadObjectFromString(data, len / 2);
         delete[] data;
-        return ret;
-    }
+        return ret ;
+       } else if( default_value ) {
+         // Value did not exist - do return default value
+         return default_value ;
+       }
+
     Py_INCREF(Py_None);
-       return Py_None;
+    return Py_None;
 }
 
 PyObject* python_ai::wrapper_get_version(PyObject* /*self*/, PyObject* args)
@@ -1882,10 +1894,12 @@
                "used to make the AI save strings (and other python values 
which can "
                "be marshalled) over multiple turns.")
     MDEF("get_variable", python_ai::wrapper_get_variable,
-               "Parameters: variable\n"
-               "Returns: value\n"
+               "Parameters: variable, default value\n"
+               "Returns: value or default value\n"
                "Retrieves a persistent variable 'variable' from the AI, 
which has "
-               "previously been set with set_variable - or None if it can't 
be found.")
+               "previously been set with set_variable - or None if it can't 
be found and\n"
+               "default value has not been set. If a default value is set 
and the value"
+               "can not be found, the default value is returned.")
     MDEF("get_version", python_ai::wrapper_get_version,
                "Returns a string containing current Wesnoth version")
     MDEF("raise_user_interact", python_ai::wrapper_raise_user_interact,
@@ -2054,6 +2068,7 @@
 // They have to end with .py, and have #!WPY as first line.
 std::vector<std::string> python_ai::get_available_scripts()
 {
+       int allow_unsafe = !preferences::run_safe_python() ;
        std::vector<std::string> scripts;
        const std::vector<std::string>& paths = get_binary_paths("data");
        for(std::vector<std::string>::const_iterator i = paths.begin(); i != 
paths.end(); ++i) {
@@ -2068,6 +2083,9 @@
                                if (mark == "#!WPY" &&
                                        std::find(scripts.begin(), 
scripts.end(), name) == scripts.end())
                                        scripts.push_back(name);
+                               else if (allow_unsafe && mark == 
"#!UNSAFE_WPY" &&
+                                        std::find(scripts.begin(), 
scripts.end(), name) == scripts.end())
+                                 scripts.push_back(name);
                        }
                }
        }




Related Messages


Powered by MHonArc, Updated Mon Jun 30 16:42:50 2008