mirror of
https://github.com/Relintai/gdnative_python.git
synced 2024-11-12 10:25:08 +01:00
Mass replace godot to pandemonium pt3.
This commit is contained in:
parent
9b4c18e994
commit
e8bff7346e
2
.github/workflows_off/build.yml
vendored
2
.github/workflows_off/build.yml
vendored
@ -149,7 +149,7 @@ jobs:
|
||||
else
|
||||
curl https://downloads.fdossena.com/Projects/Mesa3D/Builds/MesaForWindows-20.0.7.7z -o mesa.7z
|
||||
fi
|
||||
# opengl32.dll must be extracted in the same directory than Godot binary
|
||||
# opengl32.dll must be extracted in the same directory than Pandemonium binary
|
||||
7z.exe x mesa.7z
|
||||
ls -lh opengl32.dll # Sanity check
|
||||
popd
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -14,11 +14,11 @@ pandemonium_headers/
|
||||
# mac os thumbs files
|
||||
.DS_Store
|
||||
|
||||
# Godot import folders
|
||||
# Pandemonium import folders
|
||||
.import
|
||||
.cache
|
||||
|
||||
# Godot runtime logs
|
||||
# Pandemonium runtime logs
|
||||
logs
|
||||
|
||||
# Scons build artefact
|
||||
|
12
README.rst
12
README.rst
@ -28,11 +28,11 @@ example:
|
||||
@exposed
|
||||
class Player(Node2D):
|
||||
"""
|
||||
This is the file's main class which will be made available to Godot. This
|
||||
This is the file's main class which will be made available to Pandemonium. This
|
||||
class must inherit from `godot.Node` or any of its children (e.g.
|
||||
`godot.KinematicBody`).
|
||||
|
||||
Because Godot scripts only accept file paths, you can't have two `exposed` classes in the same file.
|
||||
Because Pandemonium scripts only accept file paths, you can't have two `exposed` classes in the same file.
|
||||
"""
|
||||
# Exposed class can define some attributes as export(<type>) to achieve
|
||||
# similar goal than GDSscript's `export` keyword
|
||||
@ -48,12 +48,12 @@ example:
|
||||
def age(self, value):
|
||||
self._age = value
|
||||
|
||||
# All methods are exposed to Godot
|
||||
# All methods are exposed to Pandemonium
|
||||
def talk(self, msg):
|
||||
print(f"I'm saying {msg}")
|
||||
|
||||
def _ready(self):
|
||||
# Don't confuse `__init__` with Godot's `_ready`!
|
||||
# Don't confuse `__init__` with Pandemonium's `_ready`!
|
||||
self.weapon = WEAPON_RES.instance()
|
||||
self._age = 42
|
||||
# Of course you can access property & methods defined in the parent
|
||||
@ -80,10 +80,10 @@ Building
|
||||
To build the project from source, first checkout the repo or download the
|
||||
latest tarball.
|
||||
|
||||
Godot-Python requires Python >= 3.7 and a C compiler.
|
||||
GDNative Python requires Python >= 3.7 and a C compiler.
|
||||
|
||||
|
||||
Godot GDNative header
|
||||
Pandemonium GDNative header
|
||||
---------------------
|
||||
|
||||
TODO (need to be copied from the gdnative module)
|
||||
|
@ -21,7 +21,7 @@ def pandemonium_binary_converter(val, env):
|
||||
file = File(val)
|
||||
if file.exists():
|
||||
# Note here `env["pandemonium_binary_download_version"]` is not defined, this is ok given
|
||||
# this variable shouldn't be needed if Godot doesn't have to be downloaded
|
||||
# this variable shouldn't be needed if Pandemonium doesn't have to be downloaded
|
||||
return file
|
||||
# Provided value is version information with format <major>.<minor>.<patch>[-<extra>]
|
||||
match = re.match(r"^([0-9]+)\.([0-9]+)\.([0-9]+)(?:-(\w+))?$", val)
|
||||
@ -29,7 +29,7 @@ def pandemonium_binary_converter(val, env):
|
||||
major, minor, patch, extra = match.groups()
|
||||
else:
|
||||
raise UserError(
|
||||
f"`{val}` is neither an existing file nor a valid <major>.<minor>.<patch>[-<extra>] Godot version format"
|
||||
f"`{val}` is neither an existing file nor a valid <major>.<minor>.<patch>[-<extra>] Pandemonium version format"
|
||||
)
|
||||
env["pandemonium_binary_download_version"] = (major, minor, patch, extra or "stable")
|
||||
# `pandemonium_binary` is set to None to indicate it should be downloaded
|
||||
@ -52,11 +52,11 @@ vars.Add(
|
||||
vars.Add("release_suffix", "Suffix to add to the release archive", extract_version())
|
||||
vars.Add(
|
||||
"pandemonium_binary",
|
||||
"Path to Godot binary or version of Godot to use",
|
||||
"Path to Pandemonium binary or version of Pandemonium to use",
|
||||
default="3.2.2",
|
||||
converter=pandemonium_binary_converter,
|
||||
)
|
||||
vars.Add("pandemonium_headers", "Path to Godot GDnative headers", "")
|
||||
vars.Add("pandemonium_headers", "Path to Pandemonium GDnative headers", "")
|
||||
vars.Add("debugger", "Run test with a debugger", "")
|
||||
vars.Add(BoolVariable("debug", "Compile with debug symbols", False))
|
||||
vars.Add(BoolVariable("headless", "Run tests in headless mode", False))
|
||||
|
@ -5,7 +5,7 @@ from collections import deque
|
||||
from threading import Thread, Lock, Event
|
||||
from queue import SimpleQueue
|
||||
|
||||
from _pandemonium import StdoutStderrCaptureToGodot, StdinCapture
|
||||
from _pandemonium import StdoutStderrCaptureToPandemonium, StdinCapture
|
||||
from pandemonium import exposed, export, ResourceLoader, VBoxContainer
|
||||
|
||||
from .plugin import BASE_RES
|
||||
@ -14,7 +14,7 @@ from .plugin import BASE_RES
|
||||
FONT = ResourceLoader.load(f"{BASE_RES}/hack_regular.tres")
|
||||
|
||||
|
||||
class StdoutStderrCaptureToBufferAndPassthrough(StdoutStderrCaptureToGodot):
|
||||
class StdoutStderrCaptureToBufferAndPassthrough(StdoutStderrCaptureToPandemonium):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self._buffer = ""
|
||||
|
@ -12,9 +12,9 @@ outside the interpretor) through numerous ways:
|
||||
- ...
|
||||
|
||||
However those functions are no longer relevant when python is embedded
|
||||
into Godot. They can even be dangerous when opening a Godot application to
|
||||
into Pandemonium. They can even be dangerous when opening a Pandemonium application to
|
||||
modding given a 3rd party python code has suddently full access to the computer !
|
||||
|
||||
Hence, those functions needs to be adapted to Godot:
|
||||
Hence, those functions needs to be adapted to Pandemonium:
|
||||
- ``ctype``, ``ffi`` and ``open`` disabled
|
||||
- ``stdout``, ``stderr`` and ``stdin`` redirected to Godot editor's console
|
||||
- ``stdout``, ``stderr`` and ``stdin`` redirected to Pandemonium editor's console
|
||||
|
@ -5,7 +5,7 @@ Object conversion model
|
||||
Base object types
|
||||
-----------------
|
||||
|
||||
Godot Variant
|
||||
Pandemonium Variant
|
||||
- standalone: bool, int, real
|
||||
- pointer to builtin type (e.g. ``Matrix32``, ``AABB``, etc.)
|
||||
- pointer to generic ``Object``
|
||||
@ -19,11 +19,11 @@ Python mp_obj_t
|
||||
needed on themselves.
|
||||
|
||||
Naming conventions:
|
||||
- GST: Godot STandalone
|
||||
- GPB: Godot Pointer Builtin
|
||||
- GPO: Godot Pointer Object
|
||||
- GST: Pandemonium STandalone
|
||||
- GPB: Pandemonium Pointer Builtin
|
||||
- GPO: Pandemonium Pointer Object
|
||||
- PST: Python STandalone
|
||||
- PPB: Python Pointer Binding (proxy to Godot data)
|
||||
- PPB: Python Pointer Binding (proxy to Pandemonium data)
|
||||
- PPE: Python Pointer Exposed (defined with `@exposed` decorator)
|
||||
- PPI: Python Pointer Internal
|
||||
|
||||
@ -51,24 +51,24 @@ Standalone doesn't need garbage collection and doesn't hold reference on
|
||||
other objects. Hence conversion is trivial.
|
||||
|
||||
|
||||
Conversion Godot -> Python
|
||||
Conversion Pandemonium -> Python
|
||||
--------------------------
|
||||
|
||||
Each GPB has a corresponding PPB, acting like a proxy from within the
|
||||
Python interpreter.
|
||||
|
||||
GPO binding is done dynamically with the ``DynamicBinder`` using Godot
|
||||
GPO binding is done dynamically with the ``DynamicBinder`` using Pandemonium
|
||||
introspection (i.e. ``ObjectTypeDB``).
|
||||
|
||||
It is possible in the future that to create static proxy for core GPO and rely
|
||||
on dynamic method as a fall-back for unknown classes (i.g. added by 3rd party).
|
||||
|
||||
|
||||
Conversion Python -> Godot
|
||||
Conversion Python -> Pandemonium
|
||||
--------------------------
|
||||
|
||||
PPB -> GPB described earlier.
|
||||
|
||||
PPI objects cannot be converted back to Godot.
|
||||
PPI objects cannot be converted back to Pandemonium.
|
||||
|
||||
PPE instance are exposed as ``PyInstance`` (class exposed as ``PyScript``).
|
||||
|
@ -9,7 +9,7 @@ from pandemonium.builtins cimport *
|
||||
from enum import IntFlag
|
||||
|
||||
|
||||
__ERR_MSG_BINDING_NOT_AVAILABLE = "No Godot binding available"
|
||||
__ERR_MSG_BINDING_NOT_AVAILABLE = "No Pandemonium binding available"
|
||||
|
||||
|
||||
class Error(IntFlag):
|
||||
@ -138,11 +138,11 @@ class VariantOperator(IntFlag):
|
||||
|
||||
### Class&singletons needed for Pythonscript bootstrap ###
|
||||
|
||||
# Godot classes&singletons are not all available when loading Pythonscript.
|
||||
# Pandemonium classes&singletons are not all available when loading Pythonscript.
|
||||
# Hence greedy loading is done only for items needed for Pythonscript
|
||||
# bootstrap.
|
||||
# The remaining loading will be achieved when loading the first python script
|
||||
# (where at this point Godot should have finished it initialization).
|
||||
# (where at this point Pandemonium should have finished it initialization).
|
||||
|
||||
{% set early_needed_bindings = ["_OS", "_ProjectSettings"] %}
|
||||
cdef pandemonium_object *_ptr
|
||||
|
@ -40,7 +40,7 @@ cdef class {{ cls.name }}({{ cls.base_class }}):
|
||||
|
||||
def __init__(self):
|
||||
raise RuntimeError(
|
||||
f"Use `new()` method to instantiate non-refcounted Godot object (and don't forget to free it !)"
|
||||
f"Use `new()` method to instantiate non-refcounted Pandemonium object (and don't forget to free it !)"
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
@ -101,7 +101,7 @@ cdef class {{ cls.name }}({{ cls.base_class }}):
|
||||
# return partial(self.call, gdname)
|
||||
|
||||
elif any(x for x in self.get_property_list() if x[gdnamefield] == gdname):
|
||||
# TODO: Godot currently lacks a `has_property` method
|
||||
# TODO: Pandemonium currently lacks a `has_property` method
|
||||
return self.get(gdname)
|
||||
|
||||
raise AttributeError(
|
||||
@ -116,11 +116,11 @@ cdef class {{ cls.name }}({{ cls.base_class }}):
|
||||
PyObject_GenericSetAttr(self, name, value)
|
||||
return
|
||||
|
||||
# Could retrieve the item inside the Godot class, try to look into
|
||||
# Could retrieve the item inside the Pandemonium class, try to look into
|
||||
# the attached script if it has one
|
||||
else:
|
||||
if any(x for x in self.get_property_list() if x[gdnamefield] == gdname):
|
||||
# TODO: Godot currently lacks a `has_property` method
|
||||
# TODO: Pandemonium currently lacks a `has_property` method
|
||||
self.set(name, value)
|
||||
return
|
||||
|
||||
@ -169,7 +169,7 @@ cdef class {{ cls.name }}({{ cls.base_class }}):
|
||||
{% if cls.name == "Reference" %}
|
||||
@classmethod
|
||||
def new(cls):
|
||||
raise RuntimeError(f"Refcounted Godot object must be created with `{ cls.__name__ }()`")
|
||||
raise RuntimeError(f"Refcounted Pandemonium object must be created with `{ cls.__name__ }()`")
|
||||
|
||||
def __dealloc__(self):
|
||||
cdef pandemonium_bool __ret
|
||||
|
@ -108,7 +108,7 @@ with nogil:
|
||||
{% set retval_as_arg = "NULL" %}
|
||||
{% elif method.return_type.is_object %}
|
||||
# It's important to initialize this pointer to null given
|
||||
# in case of Reference, Godot will try to decrease the
|
||||
# in case of Reference, Pandemonium will try to decrease the
|
||||
# refcount if the pointer is valid !
|
||||
# (see https://github.com/pandemoniumengine/pandemonium/issues/35609)
|
||||
cdef pandemonium_object *{{ retval }} = NULL
|
||||
|
@ -79,7 +79,7 @@ cdef class Dictionary:
|
||||
{{ force_mark_rendered("pandemonium_dictionary_operator_index") }}
|
||||
cdef pandemonium_variant var_key
|
||||
if not pyobj_to_pandemonium_variant(key, &var_key):
|
||||
raise TypeError(f"Cannot convert `{key!r}` to Godot Variant")
|
||||
raise TypeError(f"Cannot convert `{key!r}` to Pandemonium Variant")
|
||||
cdef pandemonium_variant *p_var_ret = gdapi10.pandemonium_dictionary_operator_index(&self._gd_data, &var_key)
|
||||
gdapi10.pandemonium_variant_destroy(&var_key)
|
||||
if p_var_ret == NULL:
|
||||
@ -93,7 +93,7 @@ cdef class Dictionary:
|
||||
{{ force_mark_rendered("pandemonium_dictionary_erase_with_return") }}
|
||||
cdef pandemonium_variant var_key
|
||||
if not pyobj_to_pandemonium_variant(key, &var_key):
|
||||
raise TypeError(f"Cannot convert `{key!r}` to Godot Variant")
|
||||
raise TypeError(f"Cannot convert `{key!r}` to Pandemonium Variant")
|
||||
cdef pandemonium_bool ret = gdapi11.pandemonium_dictionary_erase_with_return(&self._gd_data, &var_key)
|
||||
gdapi10.pandemonium_variant_destroy(&var_key)
|
||||
if not ret:
|
||||
|
@ -8,7 +8,7 @@ from libc.stdint cimport int8_t
|
||||
{{ force_mark_rendered("pandemonium_char_string_destroy") }}
|
||||
{{ force_mark_rendered("pandemonium_char_string_get_data") }}
|
||||
{{ force_mark_rendered("pandemonium_char_string_length") }}
|
||||
{# Those methods are present in gdnative_api.json but not in the Godot documentation... #}
|
||||
{# Those methods are present in gdnative_api.json but not in the Pandemonium documentation... #}
|
||||
{{ force_mark_rendered("pandemonium_string_ascii") }}
|
||||
{{ force_mark_rendered("pandemonium_string_ascii_extended") }}
|
||||
{{ force_mark_rendered("pandemonium_string_begins_with_char_array") }}
|
||||
|
@ -27,7 +27,7 @@ def {{ py_name or spec.py_name }}({{ spec.klass.cy_type }} self{%- if args_witho
|
||||
gdapi10.pandemonium_variant_destroy(&__var_{{ initialized_arg.name }})
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
raise TypeError(f"Cannot convert `{ {{ arg.name}} !r}` to Godot Variant")
|
||||
raise TypeError(f"Cannot convert `{ {{ arg.name}} !r}` to Pandemonium Variant")
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if spec.return_type.is_variant %}
|
||||
|
@ -592,7 +592,7 @@ if __name__ == "__main__":
|
||||
required=True,
|
||||
metavar="API_PATH",
|
||||
type=argparse.FileType("r", encoding="utf8"),
|
||||
help="Path to Godot api.json file",
|
||||
help="Path to Pandemonium api.json file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output",
|
||||
|
@ -380,7 +380,7 @@ if __name__ == "__main__":
|
||||
required=True,
|
||||
metavar="GDNATIVE_API_PATH",
|
||||
type=argparse.FileType("r", encoding="utf8"),
|
||||
help="Path to Godot gdnative_api.json file",
|
||||
help="Path to Pandemonium gdnative_api.json file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output",
|
||||
|
@ -1,23 +1,23 @@
|
||||
# Describe all base types (i.e. scalar such as int and Godot builtins)
|
||||
# Describe all base types (i.e. scalar such as int and Pandemonium builtins)
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class TypeSpec:
|
||||
# Type used within Godot api.json
|
||||
# Type used within Pandemonium api.json
|
||||
gdapi_type: str
|
||||
# Type used when calling C api functions
|
||||
c_type: str
|
||||
# Type used in Cython, basically similar to c_type for scalars&enums
|
||||
# and to py_type for Godot objects&builtins
|
||||
# and to py_type for Pandemonium objects&builtins
|
||||
cy_type: str
|
||||
# TODO: typing should be divided between argument and return (e.g. `Union[str, NodePath]` vs `NodePath`)
|
||||
# Type used for PEP 484 Python typing
|
||||
py_type: str = ""
|
||||
# Type is a Godot object (i.e. defined in api.json)
|
||||
# Type is a Pandemonium object (i.e. defined in api.json)
|
||||
is_object: bool = False
|
||||
# Type is a Godot builtin (e.g. Vector2)
|
||||
# Type is a Pandemonium builtin (e.g. Vector2)
|
||||
is_builtin: bool = False
|
||||
# Type is a scalar (e.g. int, float) or void
|
||||
is_base_type: bool = False
|
||||
|
@ -2,7 +2,9 @@
|
||||
| Godot Python |
|
||||
+---------------------------------------------------------------------------+
|
||||
|
||||
Copyright (c) 2016 by Emmanuel Leblond.
|
||||
Copyright (c) 2023-present Péter Magyar.
|
||||
Copyright (c) 2016-2023 by Emmanuel Leblond.
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
@ -23,11 +25,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Godot Python Logo (C) Pinswell
|
||||
Distributed under the terms of the Creative Commons Attribution License
|
||||
version 3.0 (CC-BY 3.0)
|
||||
https://creativecommons.org/licenses/by/3.0/legalcode.
|
||||
|
||||
|
||||
+---------------------------------------------------------------------------+
|
||||
| CPython |
|
||||
|
@ -10,7 +10,7 @@
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This is a beta version of the Python module for Godot.
|
||||
This is a beta version of the Python module for Pandemonium.
|
||||
|
||||
You are likely to encounter bugs and catastrophic crashes, if so please
|
||||
report them to https://github.com/Relintai/gdnative_python.
|
||||
@ -19,7 +19,7 @@ report them to https://github.com/Relintai/gdnative_python.
|
||||
Working features
|
||||
----------------
|
||||
|
||||
Every Godot core features are expected to work fine:
|
||||
Every Pandemonium core features are expected to work fine:
|
||||
- builtins (e.g. Vector2)
|
||||
- Objects classes (e.g. Node)
|
||||
- signals
|
||||
|
@ -13,15 +13,15 @@ Import("env")
|
||||
def resolve_pandemonium_download_url(major, minor, patch, extra, platform):
|
||||
#version = f"{major}.{minor}.{patch}" if patch != 0 else f"{major}.{minor}"
|
||||
#if extra == "stable":
|
||||
# return f"https://downloads.tuxfamily.org/godotengine/{version}/Godot_v{version}-{extra}_{platform}.zip"
|
||||
# return f"https://downloads.tuxfamily.org/godotengine/{version}/Pandemonium_v{version}-{extra}_{platform}.zip"
|
||||
#else:
|
||||
# return f"https://downloads.tuxfamily.org/godotengine/{version}/{extra}/Godot_v{version}-{extra}_{platform}.zip"
|
||||
# return f"https://downloads.tuxfamily.org/godotengine/{version}/{extra}/Pandemonium_v{version}-{extra}_{platform}.zip"
|
||||
returnf ""
|
||||
|
||||
|
||||
def resolve_pandemonium_binary_name(major, minor, patch, extra, platform):
|
||||
version = f"{major}.{minor}.{patch}" if patch != 0 else f"{major}.{minor}"
|
||||
return f"Godot_v{version}-{extra}_{platform}"
|
||||
return f"Pandemonium_v{version}-{extra}_{platform}"
|
||||
|
||||
|
||||
SConscript([f"{env['platform']}/SConscript"])
|
||||
@ -74,7 +74,7 @@ env.AddMethod(install, "Install")
|
||||
env.AddMethod(install_as, "InstallAs")
|
||||
|
||||
|
||||
### Godot binary (to run tests) ###
|
||||
### Pandemonium binary (to run tests) ###
|
||||
|
||||
|
||||
if not env["pandemonium_binary"]:
|
||||
|
@ -14,7 +14,7 @@ cpython_build = Dir("cpython_build")
|
||||
|
||||
env["bits"] = "64"
|
||||
env["pandemonium_binary_download_platform"] = "osx.64"
|
||||
env["pandemonium_binary_download_zip_path"] = "Godot.app/Contents/MacOS/Godot"
|
||||
env["pandemonium_binary_download_zip_path"] = "Pandemonium.app/Contents/MacOS/Pandemonium"
|
||||
env["cpython_build"] = cpython_build
|
||||
env["cpython_build_dir"] = cpython_build
|
||||
env["DIST_SITE_PACKAGES"] = Dir(f"{env['DIST_PLATFORM']}/lib/python3.8/site-packages")
|
||||
|
@ -1,5 +1,5 @@
|
||||
# `_pandemoniummonium` module contains all the callbacks needed by Godot's Pluginscript
|
||||
# system to expose Python as a language to Godot (see pythonscript.c for
|
||||
# `_pandemoniummonium` module contains all the callbacks needed by Pandemonium's Pluginscript
|
||||
# system to expose Python as a language to Pandemonium (see pythonscript.c for
|
||||
# more on this).
|
||||
# Hence there is no point of importing this module from Python given it
|
||||
# only expose C functions.
|
||||
@ -45,10 +45,10 @@ cdef api pandemonium_pluginscript_language_data *pythonscript_init() with gil:
|
||||
p = ProjectSettings.globalize_path(GDString(p))
|
||||
sys.path.insert(0, str(p))
|
||||
|
||||
# Redirect stdout/stderr to have it in the Godot editor console
|
||||
# Redirect stdout/stderr to have it in the Pandemonium editor console
|
||||
if _setup_config_entry("python_script/io_streams_capture", True):
|
||||
# Note we don't have to remove the stream capture in `pythonscript_finish` given
|
||||
# Godot print API is available until after the Python interpreter is teardown
|
||||
# Pandemonium print API is available until after the Python interpreter is teardown
|
||||
install_io_streams_capture()
|
||||
|
||||
# Enable verbose output from pythonscript framework
|
||||
|
@ -149,7 +149,7 @@ cdef api void pythonscript_add_global_constant(
|
||||
const pandemonium_string *p_variable,
|
||||
const pandemonium_variant *p_value
|
||||
) with gil:
|
||||
# However, Godot add global constants very early (first as an empty variant
|
||||
# However, Pandemonium add global constants very early (first as an empty variant
|
||||
# placeholder before any script is loaded, then as a proper loaded script).
|
||||
# So it's possible this function get called before `pythonscript_script_init`
|
||||
# (which is supposed to do the lazy `_initialize_bindings`).
|
||||
|
@ -51,7 +51,7 @@ cdef api pandemonium_bool pythonscript_instance_set_prop(
|
||||
cdef str key = pandemonium_string_to_pyobj(p_name)
|
||||
|
||||
# Should look among properties added by the script and it parents,
|
||||
# not Godot native properties that are handled by the caller
|
||||
# not Pandemonium native properties that are handled by the caller
|
||||
try:
|
||||
field = instance.__exported[key]
|
||||
except KeyError:
|
||||
@ -78,7 +78,7 @@ cdef api pandemonium_bool pythonscript_instance_get_prop(
|
||||
cdef str key = pandemonium_string_to_pyobj(p_name)
|
||||
|
||||
# Should look among properties added by the script and it parents,
|
||||
# not Godot native properties that are handled by the caller
|
||||
# not Pandemonium native properties that are handled by the caller
|
||||
try:
|
||||
field = instance.__exported[key]
|
||||
except KeyError:
|
||||
@ -155,7 +155,7 @@ cdef api void pythonscript_instance_notification(
|
||||
int p_notification
|
||||
) with gil:
|
||||
cdef object instance = <object>p_data
|
||||
# Godot's notification should call all parent `_notification`
|
||||
# Pandemonium's notification should call all parent `_notification`
|
||||
# methods (better not use `super()._notification` in those methods...)
|
||||
# TODO: cache the methods to call ?
|
||||
for parentcls in instance.__class__.__mro__:
|
||||
|
@ -88,7 +88,7 @@ class StdoutStderrCapture(TextIOBase):
|
||||
self._enabled = False
|
||||
|
||||
|
||||
class StdoutStderrCaptureToGodot(StdoutStderrCapture):
|
||||
class StdoutStderrCaptureToPandemonium(StdoutStderrCapture):
|
||||
|
||||
def __init__(self):
|
||||
self.buffer = ""
|
||||
@ -125,5 +125,5 @@ cdef _capture_io_streams = None
|
||||
cdef install_io_streams_capture():
|
||||
global _capture_io_streams
|
||||
assert _capture_io_streams is None
|
||||
_capture_io_streams = StdoutStderrCaptureToGodot()
|
||||
_capture_io_streams = StdoutStderrCaptureToPandemonium()
|
||||
_capture_io_streams.install()
|
||||
|
@ -115,7 +115,7 @@ cdef pandemonium_pluginscript_script_manifest _build_script_manifest(object cls)
|
||||
gdapi10.pandemonium_dictionary_new(&manifest.member_lines)
|
||||
|
||||
if cls.__bases__:
|
||||
# Only one Godot parent class (checked at class definition time)
|
||||
# Only one Pandemonium parent class (checked at class definition time)
|
||||
pandemonium_parent_class = next(
|
||||
(b for b in cls.__bases__ if issubclass(b, Object))
|
||||
)
|
||||
@ -150,7 +150,7 @@ cdef api pandemonium_pluginscript_script_manifest pythonscript_script_init(
|
||||
const pandemonium_string *p_source,
|
||||
pandemonium_error *r_error
|
||||
) with gil:
|
||||
# Godot class&singleton are not all available at Pythonscript bootstrap.
|
||||
# Pandemonium class&singleton are not all available at Pythonscript bootstrap.
|
||||
# Hence we wait until the Pythonscript start being actually used (i.e. until
|
||||
# the first Python script is loaded) before initializing the bindings.
|
||||
_initialize_bindings()
|
||||
@ -182,7 +182,7 @@ cdef api pandemonium_pluginscript_script_manifest pythonscript_script_init(
|
||||
cls = get_exposed_class(modname)
|
||||
|
||||
# If the module has no exported class, it has no real connection with
|
||||
# Godot and doesn't need to be reloaded
|
||||
# Pandemonium and doesn't need to be reloaded
|
||||
if cls:
|
||||
if get_pythonscript_verbose():
|
||||
print(f"Reloading python script from {path} ({modname})")
|
||||
@ -205,13 +205,13 @@ cdef api pandemonium_pluginscript_script_manifest pythonscript_script_init(
|
||||
|
||||
if cls is None:
|
||||
print(
|
||||
f"Cannot load {path} ({modname}) because it doesn't expose any class to Godot"
|
||||
f"Cannot load {path} ({modname}) because it doesn't expose any class to Pandemonium"
|
||||
)
|
||||
r_error[0] = GODOT_ERR_PARSE_ERROR
|
||||
return _build_empty_script_manifest()
|
||||
|
||||
if is_reload:
|
||||
# During reloading, Godot calls the new class init before the old class finish (so
|
||||
# During reloading, Pandemonium calls the new class init before the old class finish (so
|
||||
# `pythonscript_script_finish` is going to be called after this function returns).
|
||||
# Hence we must manually increase the refcount to prevent finish to remove
|
||||
# the class.
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Start with a sanity check to ensure the loading is done from Godot-Python
|
||||
# Start with a sanity check to ensure the loading is done from Pandemonium-Python
|
||||
# (and not from a regular Python interpreter which would lead to a segfault).
|
||||
# The idea is we should have the following loading order:
|
||||
# pandemonium binary -> pythonscript.so -> _pandemonium.so -> pandemonium/__init__.py
|
||||
@ -6,10 +6,10 @@ import sys
|
||||
|
||||
if "_pandemonium" not in sys.modules:
|
||||
raise ImportError(
|
||||
"Cannot initialize pandemonium module given Godot GDNative API not available.\n"
|
||||
"Cannot initialize pandemonium module given Pandemonium GDNative API not available.\n"
|
||||
"This is most likely because you are running code from a regular Python interpreter"
|
||||
" (i.e. doing something like `python my_script.py`) while pandemonium module is only available"
|
||||
" to Python code loaded from Godot through Godot-Python plugin."
|
||||
" to Python code loaded from Pandemonium through Pandemonium-Python plugin."
|
||||
)
|
||||
del sys
|
||||
|
||||
|
@ -13,7 +13,7 @@ from pandemonium._hazmat.gdnative_api_struct cimport (
|
||||
from pandemonium.builtins cimport GDString, NodePath
|
||||
|
||||
|
||||
# Godot string are basically a vector of wchar_t, each wchar_t representing
|
||||
# Pandemonium string are basically a vector of wchar_t, each wchar_t representing
|
||||
# a single unicode character (i.e. there is no surrogates support).
|
||||
# The sad part is wchar_t is not portable: it is 16bits long on Windows and
|
||||
# 32bits long on Linux and MacOS...
|
||||
|
@ -92,7 +92,7 @@ cdef bint is_pytype_compatible_with_pandemonium_variant(object pytype):
|
||||
cdef object pandemonium_type_to_pytype(pandemonium_variant_type gdtype):
|
||||
cdef pytype = next((py for gd, py in GD_PY_TYPES if gd == gdtype), None)
|
||||
if pytype is None:
|
||||
warn(f"No Python equivalent for Godot type `{gdtype}`")
|
||||
warn(f"No Python equivalent for Pandemonium type `{gdtype}`")
|
||||
return None
|
||||
|
||||
return pytype
|
||||
@ -104,7 +104,7 @@ cdef pandemonium_variant_type pytype_to_pandemonium_type(object pytype):
|
||||
if issubclass(pytype, Object):
|
||||
return pandemonium_variant_type.GODOT_VARIANT_TYPE_OBJECT
|
||||
else:
|
||||
warn(f"No Godot equivalent for Python type `{pytype}`")
|
||||
warn(f"No Pandemonium equivalent for Python type `{pytype}`")
|
||||
return pandemonium_variant_type.GODOT_VARIANT_TYPE_NIL
|
||||
|
||||
return gdtype
|
||||
@ -396,7 +396,7 @@ cdef bint pyobj_to_pandemonium_variant(object pyobj, pandemonium_variant *p_var)
|
||||
elif isinstance(pyobj, Object):
|
||||
gdapi10.pandemonium_variant_new_object(p_var, (<Object>pyobj)._gd_ptr)
|
||||
else:
|
||||
warn(f"Cannot convert `{type(pyobj)}` to Godot's Variant")
|
||||
warn(f"Cannot convert `{type(pyobj)}` to Pandemonium's Variant")
|
||||
gdapi10.pandemonium_variant_new_nil(p_var)
|
||||
return False
|
||||
return True
|
||||
|
@ -16,7 +16,7 @@ cdef class ModExposedClass:
|
||||
|
||||
|
||||
# /!\ Those containers are strictly private /!\
|
||||
# They contain class objects that are referenced from Godot without refcounting,
|
||||
# They contain class objects that are referenced from Pandemonium without refcounting,
|
||||
# so droping an item from there will likely cause a segfault !
|
||||
cdef dict __modules_with_exposed_class = {}
|
||||
cdef list __all_exposed_classes = []
|
||||
@ -40,25 +40,25 @@ cdef void set_exposed_class(object cls):
|
||||
|
||||
# We must keep track of reference counts for the module when reloading a script,
|
||||
# pandemonium calls pythonscript_script_init BEFORE pythonscript_script_finish
|
||||
# this happens because Godot can make multiple PluginScript instances for the same resource.
|
||||
# this happens because Pandemonium can make multiple PluginScript instances for the same resource.
|
||||
|
||||
# Godot calls
|
||||
# Pandemonium calls
|
||||
try:
|
||||
mod = __modules_with_exposed_class[modname]
|
||||
except KeyError:
|
||||
__modules_with_exposed_class[modname] = ModExposedClass(cls)
|
||||
else:
|
||||
# When reloading a script, Godot calls `pythonscript_script_init` BEFORE
|
||||
# When reloading a script, Pandemonium calls `pythonscript_script_init` BEFORE
|
||||
# `pythonscript_script_finish`. Hence we drop replace the old class
|
||||
# here but have to increase the refcount so
|
||||
mod.kls = cls
|
||||
mod.refcount += 1
|
||||
|
||||
# Sometimes Godot fails to reload a script, and when this happens we end
|
||||
# Sometimes Pandemonium fails to reload a script, and when this happens we end
|
||||
# up with a stale PyObject* for the class, which is then garbage collected by Python
|
||||
# so next time a script is instantiated from Godot we end up with a sefault :(
|
||||
# so next time a script is instantiated from Pandemonium we end up with a sefault :(
|
||||
# To avoid this we keep reference forever to all the classes.
|
||||
# TODO: This may be troublesome when running the Godot editor given the classes are
|
||||
# TODO: This may be troublesome when running the Pandemonium editor given the classes are
|
||||
# reloaded each time they are modified, hence leading to a small memory leak...
|
||||
__all_exposed_classes.append(cls)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Public low-level APIs are exposed here
|
||||
|
||||
from pandemoniummonium._hazmat cimport gdnative_api_struct
|
||||
# Re-expose Godot API with better names
|
||||
# Re-expose Pandemonium API with better names
|
||||
from pandemoniummonium._hazmat.gdapi cimport (
|
||||
pythonscript_gdapi10 as gdapi10,
|
||||
pythonscript_gdapi11 as gdapi11,
|
||||
|
@ -19,7 +19,7 @@ from pandemonium.builtins cimport Array, Dictionary, GDString
|
||||
from pandemonium.bindings cimport Object, Resource
|
||||
|
||||
|
||||
# Make Godot enums accesible from Python at runtime
|
||||
# Make Pandemonium enums accesible from Python at runtime
|
||||
|
||||
|
||||
class MethodRPCMode(enum.IntEnum):
|
||||
@ -162,14 +162,14 @@ class ExportedField:
|
||||
type = Dictionary if type == dict else type
|
||||
|
||||
if not is_pytype_compatible_with_pandemonium_variant(type):
|
||||
raise ValueError(f"{type!r} type value not compatible with Godot")
|
||||
raise ValueError(f"{type!r} type value not compatible with Pandemonium")
|
||||
|
||||
cdef pandemonium_variant gd_default
|
||||
if default is not None:
|
||||
# Convert `default` to a Godot-compatible value (e.g. str -> GDString)
|
||||
# Convert `default` to a Pandemonium-compatible value (e.g. str -> GDString)
|
||||
if not pyobj_to_pandemonium_variant(default, &gd_default):
|
||||
gdapi10.pandemonium_variant_destroy(&gd_default)
|
||||
raise ValueError(f"{default!r} default value not compatible with Godot")
|
||||
raise ValueError(f"{default!r} default value not compatible with Pandemonium")
|
||||
default = pandemonium_variant_to_pyobj(&gd_default)
|
||||
gdapi10.pandemonium_variant_destroy(&gd_default)
|
||||
|
||||
@ -245,8 +245,8 @@ def export(
|
||||
rpc: MethodRPCMode=MethodRPCMode.DISABLED
|
||||
):
|
||||
"""
|
||||
Decorator used to mark a class attribute as beeing exported to Godot
|
||||
(hence making it readable/writable from Godot)
|
||||
Decorator used to mark a class attribute as beeing exported to Pandemonium
|
||||
(hence making it readable/writable from Pandemonium)
|
||||
|
||||
usage::
|
||||
@exposed
|
||||
@ -276,9 +276,9 @@ def export(
|
||||
|
||||
def exposed(cls=None, tool=False):
|
||||
"""
|
||||
Decorator used to mark a class as beeing exposed to Godot (hence making
|
||||
it available from other Godot languages and the Godot IDE).
|
||||
Due to how Godot identifiest classes by their file pathes, only a single
|
||||
Decorator used to mark a class as beeing exposed to Pandemonium (hence making
|
||||
it available from other Pandemonium languages and the Pandemonium IDE).
|
||||
Due to how Pandemonium identifiest classes by their file pathes, only a single
|
||||
class can be marked with this decorator per file.
|
||||
|
||||
usage::
|
||||
@ -290,7 +290,7 @@ def exposed(cls=None, tool=False):
|
||||
def wrapper(cls):
|
||||
if not issubclass(cls, Object):
|
||||
raise ValueError(
|
||||
f"{cls!r} must inherit from a Godot (e.g. `pandemonium.bindings.Node`) "
|
||||
f"{cls!r} must inherit from a Pandemonium (e.g. `pandemonium.bindings.Node`) "
|
||||
"class to be marked as @exposed"
|
||||
)
|
||||
|
||||
@ -333,15 +333,15 @@ def exposed(cls=None, tool=False):
|
||||
elif callable(v):
|
||||
cls.__exported[k] = v
|
||||
|
||||
# Overwrite parent __init__ to avoid creating a Godot object given
|
||||
# exported script are always initialized with an existing Godot object
|
||||
# Overwrite parent __init__ to avoid creating a Pandemonium object given
|
||||
# exported script are always initialized with an existing Pandemonium object
|
||||
# On top of that, we must initialize the attributes defined in the class
|
||||
# and it parents
|
||||
g = {}
|
||||
exec(init_func_code, g)
|
||||
cls.__init__ = g["__init__"]
|
||||
# Also overwrite parent new otherwise we would return an instance
|
||||
# of a Godot class without our script attached to it...
|
||||
# of a Pandemonium class without our script attached to it...
|
||||
@classmethod
|
||||
def new(cls):
|
||||
raise NotImplementedError("Instantiating Python script from Python is not implemented yet :'(")
|
||||
@ -350,7 +350,7 @@ def exposed(cls=None, tool=False):
|
||||
# except AttributeError:
|
||||
# # It's also possible we try to instantiate a singleton, but a better
|
||||
# # message will be provided anyway if the user try the provided hint
|
||||
# raise RuntimeError(f"Refcounted Godot object must be created with `{ cls.__name__ }()`")
|
||||
# raise RuntimeError(f"Refcounted Pandemonium object must be created with `{ cls.__name__ }()`")
|
||||
# instance = cls._from_ptr(ptr)
|
||||
# # TODO: We should generate a Resource instance containing the script
|
||||
# # and attach it to the main class here.
|
||||
|
@ -1,11 +1,11 @@
|
||||
/*
|
||||
* This file gets compiled as a shared library that act as the entry point
|
||||
* to the pythonscript plugin.
|
||||
* It should be loaded by Godot's GDNative system (see the `pythonscript.gdnlib`
|
||||
* It should be loaded by Pandemonium's GDNative system (see the `pythonscript.gdnlib`
|
||||
* file in the example/test projects).
|
||||
* As part of the loading, GDNative will call the `pandemonium_gdnative_init`
|
||||
* function which will in turn initialize the CPython interpreter then register
|
||||
* Python as a new language using Godot's Pluginscript system.
|
||||
* Python as a new language using Pandemonium's Pluginscript system.
|
||||
*/
|
||||
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
@ -65,7 +65,7 @@ static PyThreadState *gilstate = NULL;
|
||||
|
||||
|
||||
/*
|
||||
* Global variables exposing Godot API to the pandemonium.hazmat cython module.
|
||||
* Global variables exposing Pandemonium API to the pandemonium.hazmat cython module.
|
||||
* Hence we must initialized them before loading `_pandemonium`/`pandemonium` modules
|
||||
* (which both depend on `pandemonium.hazmat`).
|
||||
*/
|
||||
@ -135,7 +135,7 @@ GDN_EXPORT void pandemonium_gdnative_init(pandemonium_gdnative_init_options *opt
|
||||
// Check for mandatory plugins
|
||||
|
||||
if (!pythonscript_gdapi10 || !pythonscript_gdapi11 || !pythonscript_gdapi12) {
|
||||
GD_ERROR_PRINT("Godot-Python requires GDNative API >= v1.2");
|
||||
GD_ERROR_PRINT("Pandemonium-Python requires GDNative API >= v1.2");
|
||||
return;
|
||||
}
|
||||
if (!pythonscript_gdapi_ext_pluginscript) {
|
||||
|
@ -182,7 +182,7 @@ def test_access_property(generate_obj):
|
||||
def test_new_on_overloaded_class(generate_obj):
|
||||
node = generate_obj(virtualtestbedcls)
|
||||
# Make sure doing MyClass.new() doesn't return an instance of the
|
||||
# Godot class we inherit from
|
||||
# Pandemonium class we inherit from
|
||||
assert isinstance(node, virtualtestbedcls)
|
||||
|
||||
|
||||
|
@ -69,7 +69,7 @@ def test_getitem():
|
||||
assert v[0.5] == Vector2()
|
||||
# Missing items are stored as None
|
||||
assert v["dummy"] is None
|
||||
# Cannot store non Godot types
|
||||
# Cannot store non Pandemonium types
|
||||
with pytest.raises(TypeError):
|
||||
v[object()]
|
||||
|
||||
@ -82,7 +82,7 @@ def test_setitem():
|
||||
v["a"] = 4
|
||||
assert len(v) == 4
|
||||
assert v["a"] == 4
|
||||
# Cannot store non Godot types
|
||||
# Cannot store non Pandemonium types
|
||||
with pytest.raises(TypeError):
|
||||
v[object()] = 4
|
||||
with pytest.raises(TypeError):
|
||||
@ -99,7 +99,7 @@ def test_delitem():
|
||||
# Delete on missing items should raise error
|
||||
with pytest.raises(KeyError):
|
||||
del v["missing"]
|
||||
# Cannot store non Godot types
|
||||
# Cannot store non Pandemonium types
|
||||
with pytest.raises(TypeError):
|
||||
del v[object()]
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
# assert isinstance(KEY_ESCAPE, int)
|
||||
|
||||
# def test_objects_unicity(self):
|
||||
# # Main loop object is a Godot Object, calling `get_main_loop` from
|
||||
# # Main loop object is a Pandemonium Object, calling `get_main_loop` from
|
||||
# # python returns a different python wrapper on the same object each time.
|
||||
# # However those wrappers should feel like they are the same object.
|
||||
# ml = Engine.get_main_loop()
|
||||
@ -40,7 +40,7 @@
|
||||
# assert ml != None # noqa
|
||||
# assert ml != ""
|
||||
# assert ml != 42
|
||||
# # Don't forget to free the Godot Object
|
||||
# # Don't forget to free the Pandemonium Object
|
||||
# obj.free()
|
||||
|
||||
# def test_class(self):
|
||||
|
@ -8,7 +8,7 @@ def environment_factory():
|
||||
# Environment objects are stubbed on headless server, hence
|
||||
# their corresponding RID is always the same default value
|
||||
if OS.has_feature("Server"):
|
||||
pytest.skip("Not available on headless Godot")
|
||||
pytest.skip("Not available on headless Pandemonium")
|
||||
|
||||
def _factory():
|
||||
return Environment()
|
||||
|
@ -29,7 +29,7 @@ def test_base():
|
||||
|
||||
@pytest.mark.parametrize("char", ["e", "é", "€", "蛇", "🐍"])
|
||||
def test_unicode(char):
|
||||
# Godot supports UCS2 on Windows and UCS4 on other platforms
|
||||
# Pandemonium supports UCS2 on Windows and UCS4 on other platforms
|
||||
if len(char.encode("utf8")) > 2 and sys.platform == "win32":
|
||||
pytest.skip("Windows only supports UCS2")
|
||||
|
||||
|
@ -76,7 +76,7 @@ test_factory(
|
||||
try:
|
||||
import pandemonium
|
||||
except ImportError as exc:
|
||||
assert "Cannot initialize pandemonium module given Godot GDNative API not available." in str(exc)
|
||||
assert "Cannot initialize pandemonium module given Pandemonium GDNative API not available." in str(exc)
|
||||
""",
|
||||
],
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user