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);
}
}
}
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits