Skip to main content

No project description provided

Project description

UnityPython

Key points:

  1. Run a Python-like programming language on ALL platforms such as iOS, Android, etc.
  2. Good IDE support via Pylance, type checked! (see unitypython-typeshed)
  3. Dynamic and fast code loading in Unity. Edit code and see how UI changes immediately (Unity Editor is painful to me)!
  4. An extensible coroutine implementation. async and await are not as restricted as that in CPython and can be used as fast/fine-grained controlled event loops in game development.

UnityPython is based on CPython 3.10, but not fully compatible to CPython. For instance, StopIteration is not used for loop constructs (exceptions are heavy and not used for control flow); type is the only metaclass, etc.

import UnityEngine

class MyComponent(UnityEngine.MonoBehaviour):
    def Start(self):
        async def coro():
            while not cond_satisfied:
                await Task.Yield
            do_something()
        def coro2():
            while not cond_satisfied:
                yield
            do_something()
        self.StartCoroutine(coro())
        self.StartCoroutine(coro2())

Contributing

See 0.1 roadmap

Basic development workflow:

  1. cd UnityPython.FrontEnd && pip install -e . && cd ..; requires Python 3.8+ (Python 3.10 is better)
  2. cd UnityPython.BackEnd
  3. dotnet restore
  4. bash build-code.sh && bash runtests.sh

UnityPython.BackEnd/tests/test_*.py will be executed.

Besides, we badly need more tests! Help us and refer test_semantics.

How to add a method to datatypes? (concise way)

[PyBind] can be used to bind Python methods. You can bind a Python staticmethod or instance method through the following the steps:

  1. implement an instacne/static method/instance property

    [PyBind]
    public TrObject append(TrObject elt)
    {
        container.Add(elt);
        return MK.None();
    }
    
  2. build an DLL for UnityPython.BackEnd

    dotnet public -c Release

  3. codegen using UnityPython.BackEnd.CodeGen

    dotnet run --project ../UnityPython.BackEnd.CodeGen/UnityPython.BackEnd.CodeGen.csproj

Then append is bound.

[PyBind] works for static methods and properties as well. Default arguments work.

NOTE: functions annotated by [PyBind] must take a return value!!!

How to add a method to datatypes? (verbose way)

For example, if we want to implement append for list,

  • we firstly get to UnityPython.BackEnd/src/Traffy.Objects/List.cs

  • then we find the method annotated with [Mark(Initialization.TokenClassInit)]

  • see the code

      public static TrObject append(TrObject self, TrObject value)
      {
          ((TrList)self).container.Add(value);
          return RTS.object_none; // RTS = runtime support
      }
    
     [Mark(Initialization.TokenClassInit)]
      static void _Init()
      {
          CLASS = TrClass.FromPrototype<TrList>();
          CLASS.Name = "list";
          CLASS.InitInlineCacheForMagicMethods();
          CLASS[CLASS.ic__new] = TrStaticMethod.Bind("list.__new__", TrList.datanew);
    
          // 1. 'TrSharpFunc.FromFunc' converts a CSharp function to UnityPython 'builtin_function'
          // 2. 'CLASS["somemethod".ToIntern()] = python-object' is equal to something like
          //      class list:
          //         somemethod = expr
          CLASS["append".ToIntern()] = TrSharpFunc.FromFunc("list.append", TrList.append);
          ...
      }
    

    PS:

    • TrSharpFunc.FromFunc creates a method
    • TrStaticMethod.Bind creates a staticmethod
    • TrClassMethod.Bind creates a classmethod
    • TrProperty.Create(getter=null, setter=null) creates a property

How to add a builtin-function

Basically, you just need to call Initialization.Prelude(string name, TrObject o).

For maintainability, please collect all builtin callables (other than datatypes) at UnityPython.BackEnd/src/Builtins.cs

namespace Traffy
{
    public static class Builtins
    {
        static IEnumerator<TrObject> mkrange(int start, int end, int step)
        {
            for (int i = start; i < end; i += step)
                yield return MK.Int(i);
        }

        // BLists, or double-ended lists, are designed for fast method call (requires adding a 'self' to the left end)
        static TrObject range(BList<TrObject> args, Dictionary<TrObject, TrObject> kwargs)
        {
            var narg = args.Count;
            switch(narg)
            {
                case 1:
                    return MK.Iter(mkrange(0, args[0].AsInt(), 1));
                case 2:
                    return MK.Iter(mkrange(args[0].AsInt(),  args[1].AsInt(), 1));
                case 3:
                    return MK.Iter(mkrange(args[0].AsInt(),  args[1].AsInt(), args[2].AsInt()));
                default:
                    throw new TypeError($"range() takes 1 to 3 positional argument(s) but {narg} were given");
            }
        }

        [Mark(Initialization.TokenBuiltinInit)]
        public static void InitRuntime()
        {
            Initialization.Prelude(TrSharpFunc.FromFunc("range", range));
        }

    }
}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

unitypython-0.2.1-py3-none-any.whl (21.5 kB view hashes)

Uploaded py3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page