Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

python: ParamObject does not generate named arguments when used in with EmitMethod #3871

Open
joprice opened this issue Jul 22, 2024 · 3 comments
Labels

Comments

@joprice
Copy link
Contributor

joprice commented Jul 22, 2024

Description

When attempting to extend a type with a method that takes keyword args, the generated code ignores the keyword arguments if EmitMethod is present. This isn't required when defining the type directly, but it is when extending an existing type.

Repro code

open Fable.Core

[<Erase>]
type IExports =
  [<ParamObject(1)>]
  [<EmitMethod("makedirs")>]
  abstract makedirs: path: string * ?exist_ok:bool -> unit

  [<ParamObject(1)>]
  abstract makedirs2: path: string * ?exist_ok:bool -> unit

type IExports with 
  [<ParamObject(1)>]
  [<EmitMethod("makedirs")>]
  member _.makedirs3(path: string, ?exist_ok:bool): unit = nativeOnly

[<ImportAll("os")>]
let os: IExports = nativeOnly

os.makedirs ("data", exist_ok = true)
os.makedirs2 ("data", exist_ok = true)
os.makedirs3 ("data", exist_ok = true)
import os
os.makedirs("data")

os.makedirs2("data", exist_ok = True)

os.makedirs("data")

https://fable.io/repl/#?code=PYBwpgdgBAYghgIwDZgHQGFgCcwChcDaAPAKJZwDOYAfALq4AuAnuFAJIkAeI2DFUAXlxQoxAApxyAWwDyCAFZgAxgwAUARgCUdYaNJSAlgwCyYBgAtgAE1UAiKXADWYKwawVb2+iMQUG5FSgHZ1d3AC4oEDgLCL8sAwgAcygAKigAfjBOAz8KAH1gRzCEYGAkKABaaigAVwgjfBFxSThZBWU1LR0fBDi4QOCXNwoAJgiomKg4hOS0zOzcgqKSssrquobGFjB2Lh4sPigAdyNzKF1m6TlFFQ0vC-0jUwtrO0HQj3uRKTApBDAsFA8qh3sMAMyqCbmWL+GYAGgyWRyfCWxVKSE0EQ2DEEUAg0QMADcwDIIEgmPhiGwpPsGABBJBIOzAT46FA4lkRDjcXj8AR4gnE0nk-AskFOIbuKB2KzROC2BFIxaFXH+GpgTS4MWg9wjaW2WUMeWKhYolX8tUarUUcUhcH6w3GqBKs2OVVYdWaIA&html=Q&css=Q

Related information

  • Fable version: 4.19.3
  • Operating system: OSX
@MangelMaxime
Copy link
Member

Hello,

The code in the REPL link is different compared to your snippet.

So I am unsure what is the bug you want to report.

Is it "just" the fact that EmitMethod is ignored on type augmentation?

type IExports with 
  [<ParamObject(1)>]
  [<EmitMethod("makedirs")>]
  member _.makedirs3(path: string, ?exists_ok:bool): unit = nativeOnly

Should generate makedirs instead of makedirs3?

@joprice
Copy link
Contributor Author

joprice commented Jul 22, 2024

I updated the snippet. EmitMethod works to override the name of the method, but it does not include the argument exists_ok. Try switching to javascript and you will see

import * as os from "os";

os.makedirs("data", {
    exists_ok: true,
});

os.makedirs2("data", {
    exists_ok: true,
});

os.makedirs("data", {
    exists_ok: true,
});

compared to the python

import os
os.makedirs("data")

os.makedirs2("data", exists_ok = True)

os.makedirs("data")

This is trying to show that when you don't include EmitMethod, the keyword arguments are generated for Python.

@joprice
Copy link
Contributor Author

joprice commented Aug 15, 2024

Here's another example where ParamObject is ignored:

open Fable.Core

[<Erase>]
type Process =
  abstract member start: unit -> unit
  abstract member join: unit -> unit
  abstract member is_alive: unit -> bool
  abstract member name: string

[<Erase>]
type ProcessType =
  [<EmitConstructor; ParamObject>]
  abstract Create: target: ('a -> unit) * args: 'a * ?name: string -> Process

[<Import("Process", "multiprocessing")>]
let Process: ProcessType = nativeOnly

let fn a = ()
Process.Create(target = fn, args = 1, name = "worker") |> ignore

produces

from multiprocessing import Process
from typing import Any
from fable_library_js.util import ignore

def fn(a: Any | None=None) -> None:
    pass


def _arrow2(a: int) -> None:
    fn(a)


ignore(Process())

whereas the arguments are passed in js:

import { Process } from "multiprocessing";

export function fn(a) {
}

new Process({
    target: (a) => {
        fn(a);
    },
    args: 1,
    name: "worker",
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants