Zesstra | 7ea4a03 | 2019-11-26 20:11:40 +0100 | [diff] [blame] | 1 | PRELIMINARY |
| 2 | CONCEPT |
| 3 | python |
| 4 | |
| 5 | DESCRIPTION |
| 6 | Python can be used to extend the LDMud driver. At the startup |
| 7 | of LDMud a python script will be called that can register |
| 8 | additional efuns. The python script can either be given |
| 9 | on the command line using the --python-script option, |
| 10 | or at compile time with the --with-python-script configuration |
| 11 | option. |
| 12 | |
| 13 | The python script can import the builtin ldmud module. |
| 14 | This module provides the following functions: |
| 15 | |
| 16 | - register_efun(name, function) -> None |
| 17 | Registers a new efun name. This is not allowed during |
| 18 | compilation of an LPC object. |
| 19 | |
| 20 | If the Python function has type annotations for its |
| 21 | arguments and return value, the type is checked |
| 22 | at compile and runtime. Union types can be specified |
| 23 | as tuples of types. |
| 24 | |
| 25 | - unregister_efun(name) -> None |
| 26 | Removes a python efun from registration. This is not |
| 27 | allowed during compilation of an LPC object. The |
| 28 | removal will only affect newly compiled code, |
| 29 | already compiled code will produce errors when |
| 30 | calling this efun. |
| 31 | |
| 32 | - register_socket(fd, function [,eventmask]) -> None |
| 33 | Registers a socket <fd> to watch for events (like |
| 34 | poll/select). The socket must be either given as |
| 35 | an integer or an object with a fileno() method |
| 36 | returning an integer. The function must be a callable |
| 37 | accepting one argument, the actual event mask. |
| 38 | <eventmask> may be an combination of select.POLLIN, |
| 39 | select.POLLOUT and select.POLLPRI or a callable |
| 40 | returning such a combination. |
| 41 | |
| 42 | - unregister_socket(fd) -> None |
| 43 | Removes a previously registered socket from the |
| 44 | watch list. |
| 45 | |
| 46 | - register_hook(hook, function) -> None |
| 47 | Register a hook. The python function will be called |
| 48 | whenever <hook> happens. <hook> can be one of the |
| 49 | following: |
| 50 | |
| 51 | ON_HEARTBEAT |
| 52 | Called without arguments for every backend loop |
| 53 | |
| 54 | ON_OBJECT_CREATED |
| 55 | Called whenever an object was created, with the |
| 56 | object as its first and only argument. This call |
| 57 | happens before any LPC code of the object ran. |
| 58 | |
| 59 | ON_OBJECT_DESTRUCTED |
| 60 | Called just before an object will be destructed, |
| 61 | with the object as its first and only argument. |
| 62 | |
Zesstra | 5481d49 | 2021-04-08 20:07:06 +0200 | [diff] [blame] | 63 | ON_CHILD_PROCESS_TERMINATED |
| 64 | Called without any arguments whenever a SIGCHLD signal |
| 65 | was received. This could also happen for processes |
| 66 | spawned by the driver itself (eg. erq). |
| 67 | |
Zesstra | 7ea4a03 | 2019-11-26 20:11:40 +0100 | [diff] [blame] | 68 | - unregister_hook(hook, function) -> None |
| 69 | Removes a hook function. |
| 70 | |
| 71 | - get_master() - > Object |
| 72 | Returns the current master object. |
| 73 | Returns None, if there is no master object (yet). |
| 74 | |
| 75 | - get_simul_efun() - > Object |
| 76 | Returns the current simul-efun object |
| 77 | (or None if there is none). |
| 78 | |
| 79 | |
| 80 | This module provides the following types: |
| 81 | |
| 82 | - Object(filename) |
| 83 | Corresponds to the LPC object type. |
| 84 | On instantiation a filename for an object |
| 85 | to search or load is required. |
| 86 | |
Zesstra | 5481d49 | 2021-04-08 20:07:06 +0200 | [diff] [blame] | 87 | Has the following members: |
| 88 | |
| 89 | name |
| 90 | The object name |
| 91 | |
| 92 | functions |
| 93 | Contains all the visible functions (private functions |
| 94 | are excluded) as attributes. They support the call |
| 95 | operator and contain the following attributes: |
| 96 | |
| 97 | name |
| 98 | The name of the function |
| 99 | |
| 100 | file_name |
| 101 | The file that contains the function's definition |
| 102 | |
| 103 | line_number |
| 104 | The starting line number of the function's definition |
| 105 | |
| 106 | arguments |
| 107 | A list of all arguments with their type, flags |
| 108 | (combination of LA_* constants) and position. |
| 109 | |
| 110 | return_type |
| 111 | The return type as Python object (maybe missing if |
| 112 | unknown or mixed). |
| 113 | |
| 114 | flags |
| 115 | A combination of the following flags: |
| 116 | LF_STATIC, LF_NOMASK, LF_VARARGS, LF_VIRTUAL and |
| 117 | LF_DEPRECATED |
| 118 | |
| 119 | visibility: |
| 120 | One of the following: |
| 121 | VIS_PRIVATE, VIS_PROTECTED, VIS_VISIBLE, VIS_PUBLIC |
| 122 | |
| 123 | variables |
| 124 | Contains all variables as attributes. They contain the |
| 125 | following attributes: |
| 126 | |
| 127 | name |
| 128 | The name of the variable |
| 129 | |
| 130 | value |
| 131 | The value of the variable. This attribute is writable |
| 132 | to assign a new value. |
| 133 | |
| 134 | type |
| 135 | The type as a Python object (maybe missing if |
| 136 | unknown or mixed). |
| 137 | |
| 138 | flags |
| 139 | A combination of the following flags: |
| 140 | VF_NOSAVE, VF_NOMASK, VF_VIRTUAL and VF_DEPRECATED |
| 141 | |
| 142 | visibility: |
| 143 | One of the following: |
| 144 | VIS_PRIVATE, VIS_PROTECTED, VIS_VISIBLE, VIS_PUBLIC |
| 145 | |
| 146 | - LWObject(filename) |
| 147 | Corresponds to the LPC lwobject type. |
| 148 | On instantiation a filename of a blueprint to create |
| 149 | a lightweight object from is required. |
| 150 | |
| 151 | Has the following members: |
| 152 | |
| 153 | program_name |
| 154 | The program name (file name it was created from) |
| 155 | |
| 156 | functions |
| 157 | Contains all the visible functions (private functions |
| 158 | are excluded) as attributes. They are similar to the |
| 159 | same member of the Object type. |
| 160 | |
| 161 | variables |
| 162 | Contains all variables as attributes. They are similar |
| 163 | to the same member of the Object type. |
| 164 | |
Zesstra | 7ea4a03 | 2019-11-26 20:11:40 +0100 | [diff] [blame] | 165 | - Array([values | size]) |
| 166 | Corresponds to an LPC array. |
| 167 | Can either be initialized with a list of values |
| 168 | or to a given size. |
| 169 | |
| 170 | Supports element access with [], len() and __contains__. |
| 171 | |
| 172 | - Mapping([values | width]) |
| 173 | Corresponds to an LPC mapping. |
| 174 | Can either be initialized with a dict, a list of tuples |
| 175 | or as an empty mapping with a given width. |
| 176 | |
| 177 | Supports element access with [], len(), __contains__ |
| 178 | and has a width member. |
| 179 | |
| 180 | - Struct(object, name [, values]) |
Zesstra | 5481d49 | 2021-04-08 20:07:06 +0200 | [diff] [blame] | 181 | Corresponds to an LPC struct. |
| 182 | On initialization the name of the struct definition and |
| 183 | the correspopnding object is required. It can be initialized |
| 184 | with a list of values or dict. |
Zesstra | 7ea4a03 | 2019-11-26 20:11:40 +0100 | [diff] [blame] | 185 | |
Zesstra | 5481d49 | 2021-04-08 20:07:06 +0200 | [diff] [blame] | 186 | Has the following members: |
| 187 | |
| 188 | name |
| 189 | The name of the struct |
| 190 | |
| 191 | program_name |
| 192 | The name of the program that defined the struct. |
| 193 | |
| 194 | members |
| 195 | Contains all members as attributes. They contain the |
| 196 | following attributes: |
| 197 | |
| 198 | name |
| 199 | The name of the member |
| 200 | |
| 201 | value |
| 202 | The value of the member. This attribute is writable |
| 203 | to assign a new value. |
| 204 | |
| 205 | type |
| 206 | The type as a Python object (maybe missing if |
| 207 | unknown or mixed). |
Zesstra | 7ea4a03 | 2019-11-26 20:11:40 +0100 | [diff] [blame] | 208 | |
| 209 | - Closure(object [,name [, lfun_object]]) |
| 210 | Corresponds to an LPC closure. |
| 211 | On initialization a closure bound to <object> will be created, |
| 212 | like a call to symbol_function(<name> [, <lfun_object>]). |
| 213 | |
| 214 | Supports function calls. |
| 215 | |
| 216 | - Symbol(name [, quotes]) |
| 217 | Corresponds to an LPC symbol. |
| 218 | On initialization the name of the symbol is required. |
| 219 | Optionally the number of quotes (at least 1) can be specified. |
| 220 | |
| 221 | Has two members: name and quotes. |
| 222 | |
| 223 | - QuotedArray(array [, quotes]) |
| 224 | Corresponds to an LPC quoted array. |
| 225 | On initialization an array is required. |
| 226 | Optionally the number of quotes (at least 1) can be specified. |
| 227 | |
| 228 | Has two members: array and quotes. |
| 229 | |
Zesstra | 5481d49 | 2021-04-08 20:07:06 +0200 | [diff] [blame] | 230 | - Lvalue(value) |
| 231 | Creates an lvalue reference for the given value. |
| 232 | |
| 233 | Has two member: value and members. |
| 234 | |
| 235 | If the value is an array, mapping or string, then lvalues |
| 236 | to its elements can be created with []. |
| 237 | |
| 238 | If the value is a struct, then lvalues to its members can |
| 239 | be created with the members attribute. It contains all |
| 240 | the struct members as attributes and will return an Lvalue |
| 241 | object to the struct member. |
Zesstra | 7ea4a03 | 2019-11-26 20:11:40 +0100 | [diff] [blame] | 242 | |
| 243 | This module contains the following sub-namespaces: |
| 244 | |
| 245 | - efuns |
| 246 | This namespace contains all original efuns (without any |
| 247 | registered python efuns or simul-efuns). These can be called |
| 248 | as a regular function. |
| 249 | |
| 250 | |
Zesstra | 5481d49 | 2021-04-08 20:07:06 +0200 | [diff] [blame] | 251 | There is mapping of LPC values to Python values for the following types: |
| 252 | int <-> int(, bool) |
| 253 | float <-> float |
| 254 | string <-> str |
| 255 | bytes <-> bytes |
| 256 | |
| 257 | Type definitions are translated in a similar fashion, additionally the |
| 258 | following mappings are done: |
| 259 | void <-> None |
| 260 | union <-> tuple of types |
| 261 | |
Zesstra | 7ea4a03 | 2019-11-26 20:11:40 +0100 | [diff] [blame] | 262 | EXAMPLE |
| 263 | import ldmud |
| 264 | |
| 265 | def hello_world(name: str) -> int: |
| 266 | print("Hello, world, %s!\n" % (name,)) |
| 267 | return 1 |
| 268 | |
| 269 | ldmud.register_efun("hello", hello_world) |
| 270 | |
| 271 | NOTES |
| 272 | Just like simul-efuns python efuns can shadow real efuns. The |
| 273 | original efun is then inaccessible for LPC code (except for code |
| 274 | that was compiled before the efun was registered). Python efuns are |
| 275 | nearly indistinguishable from real efuns, they also use the efun:: |
| 276 | prefix. However they can be detected with |
| 277 | CLOSURE_IS_PYTHON_EFUN(get_type_info(#'efun,1)) |
| 278 | |
| 279 | Without the prefix the order of name resolution for function calls is: |
| 280 | 1. lfuns |
| 281 | 2. simul-efuns |
| 282 | 3. python efuns |
| 283 | 4. real efuns |
| 284 | |
| 285 | Also just like simul-efuns python-registered efuns are called |
| 286 | from LPC code that was compiled after the registration. LPC code |
| 287 | that was compiled before the registration will still call the |
| 288 | original efuns (or throw a compile error if that efun doesn't exist). |
| 289 | Therefore such efuns should be registered in the python startup |
| 290 | script. |
| 291 | |
| 292 | When a python efun is unregistered, code that was compiled while the |
| 293 | registration was in effect will throw a runtime error. (Regardless |
| 294 | of whether a driver efun with the same name exists or not.) |
| 295 | |
| 296 | There is a limit of 2048 python efuns. Not only registered, but also |
| 297 | formerly registered - but now unregistered - efuns count toward that |
| 298 | limit. Re-registering the same efun name again won't count a second |
| 299 | time. (LPC code that was compiled during the previous registration |
| 300 | will also call the new efun after the re-registration.) |
| 301 | |
| 302 | As LDMud is single-threaded, the python code will run in the same |
| 303 | thread as the LPC machine. So any long-running python function will |
| 304 | halt the MUD for all players. Hence python functions should return |
| 305 | promptly and source out any lengthy tasks to another process. If |
| 306 | other threads are spawned from python, then these threads are not |
| 307 | allowed to access any LDMud functions or objects. |
| 308 | |
| 309 | Finally a note of caution: Don't change the meaning of base efuns |
| 310 | fundamentally as it furthers confusion and hinders exchange of LPC |
| 311 | code and knowledge between mudlibs. |
| 312 | |
| 313 | HISTORY |
| 314 | LDMud 3.5 implemented the python functionality. |
| 315 | LDMud 3.6 added type checks. |
| 316 | |
| 317 | SEE ALSO |
| 318 | simul_efun(C) |