{"action":"created","issue":{"url":"https://api.github.com/repos/swig/swig/issues/310","labels_url":"https://api.github.com/repos/swig/swig/issues/310/labels{/name}","comments_url":"https://api.github.com/repos/swig/swig/issues/310/comments","events_url":"https://api.github.com/repos/swig/swig/issues/310/events","html_url":"https://github.com/swig/swig/issues/310","id":54590017,"number":310,"title":"Python kwargs not working in swig 3.0.4 and 3.0.3 with default arguments of class type.","user":{"login":"lballabio","id":170560,"avatar_url":"https://avatars.githubusercontent.com/u/170560?v=3","gravatar_id":"","url":"https://api.github.com/users/lballabio","html_url":"https://github.com/lballabio","followers_url":"https://api.github.com/users/lballabio/followers","following_url":"https://api.github.com/users/lballabio/following{/other_user}","gists_url":"https://api.github.com/users/lballabio/gists{/gist_id}","starred_url":"https://api.github.com/users/lballabio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lballabio/subscriptions","organizations_url":"https://api.github.com/users/lballabio/orgs","repos_url":"https://api.github.com/users/lballabio/repos","events_url":"https://api.github.com/users/lballabio/events{/privacy}","received_events_url":"https://api.github.com/users/lballabio/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-01-16T15:50:15Z","updated_at":"2015-01-19T09:19:09Z","closed_at":"2015-01-16T16:37:41Z","body":"Hello,\r\n    when using `%feature(\"kwargs\")` with a method or a constructor, swig 3.0.4 tries to generate corresponding keyword arguments in the generated Python code (as opposed to 3.0.3 and later, that just generated a `(self, *args, **kwargs)` signature).\r\n\r\nUnfortunately, swig seems to add the corresponding default arguments in the signature only if they are of a built-in type. Short example:\r\n\r\n    %module Test\r\n\r\n    class Foo {\r\n      public:\r\n        Foo();\r\n    };\r\n\r\n    class Bar {\r\n        %feature(\"kwargs\") m1;\r\n        %feature(\"kwargs\") m2;\r\n      public:\r\n        void m1(double x, double y=1.0);\r\n        void m2(double x, const Foo& f = Foo());\r\n    };\r\n\r\nWith options `-c++ -python`, the above generates in `Test.py`:\r\n\r\n    class Bar(object):\r\n        ...\r\n        def m1(self, x, y=1.0):\r\n            return _Test.Bar_m1(self, x, y)\r\n\r\n        def m2(self, x, f):\r\n            return _Test.Bar_m2(self, x, f)\r\n\r\nthat misses the default argument in `m2`. The bug is particularly nasty when a default argument of a class type follows one of a built-in type. If we replace the declaration of `Bar` in the interface file with:\r\n\r\n    class Bar {\r\n        %feature(\"kwargs\") m2;\r\n      public:\r\n        void m2(double x, double y=1.0, const Foo& f = Foo());\r\n    };\r\n\r\nthe generated Python class is:\r\n\r\n    class Bar(object):\r\n        ...\r\n        def m2(self, x, y=1.0, f):\r\n            return _Test.Bar_m2(self, x, y, f)\r\n\r\nwhich is not valid Python code.\r\n\r\nswig 3.0.3 gets the above method right because it generates the signature `m2(self, *args, **kwargs)`, but it fails when wrapping functions. The interface:\r\n\r\n    %feature(\"kwargs\") g; \r\n    void g(double x=1.0, const Foo& f = Foo());\r\n\r\ngenerates the invalid code:\r\n\r\n    def g(x=1.0, f):\r\n        return _Test.g(x, f)\r\n    g = _Test.g\r\n\r\nStrangely, the above also reassigns `g` after defining it. But the interpreter never gets there and stops at the incorrect declaration. If you don't give a default argument to `x`, you get\r\n\r\n    def g(x, f):\r\n        return _Test.g(x, f)\r\n    g = _Test.g\r\n\r\nwhich defines a function that misses the default argument, but then redefines it as the native `_Test.g` so the incorrect one is thrown away and the bug is hidden.\r\n"},"comment":{"url":"https://api.github.com/repos/swig/swig/issues/comments/70464612","html_url":"https://github.com/swig/swig/issues/310#issuecomment-70464612","issue_url":"https://api.github.com/repos/swig/swig/issues/310","id":70464612,"user":{"login":"lballabio","id":170560,"avatar_url":"https://avatars.githubusercontent.com/u/170560?v=3","gravatar_id":"","url":"https://api.github.com/users/lballabio","html_url":"https://github.com/lballabio","followers_url":"https://api.github.com/users/lballabio/followers","following_url":"https://api.github.com/users/lballabio/following{/other_user}","gists_url":"https://api.github.com/users/lballabio/gists{/gist_id}","starred_url":"https://api.github.com/users/lballabio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lballabio/subscriptions","organizations_url":"https://api.github.com/users/lballabio/orgs","repos_url":"https://api.github.com/users/lballabio/repos","events_url":"https://api.github.com/users/lballabio/events{/privacy}","received_events_url":"https://api.github.com/users/lballabio/received_events","type":"User","site_admin":false},"created_at":"2015-01-19T09:19:09Z","updated_at":"2015-01-19T09:19:09Z","body":"Yes, that last commit fixes it. There's still the strange construct\r\n\r\n    def g(*args, **kwargs):\r\n        return _Test.g(*args, **kwargs)\r\n    g = _Test.g\r\n\r\nin the generated Python code that defines a function and immediately overwrite it, but it does no harm."}}