extlibs

package
v0.0.0-...-4fb4123 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 15, 2026 License: MIT Imports: 32 Imported by: 0

Documentation

Overview

Package extlibs provides external libraries that need explicit registration

Package extlibs provides external libraries that need explicit registration

Index

Constants

View Source
const (
	RequestsLibraryName   = "requests"
	SysLibraryName        = "sys"
	SecretsLibraryName    = "secrets"
	SubprocessLibraryName = "subprocess"
	HTMLParserLibraryName = "html.parser"
	OSLibraryName         = "os"
	OSPathLibraryName     = "os.path"
	PathlibLibraryName    = "pathlib"
	GlobLibraryName       = "glob"
	ThreadsLibraryName    = "sl.threads"
	LoggingLibraryName    = "logging"
	WaitForLibraryName    = "wait_for"
	AILibraryName         = "sl.ai"
	MCPLibraryName        = "sl.mcp"
	ToonLibraryName       = "sl.toon"
	ConsoleLibraryName    = "sl.console"
)

Library names as constants for easy reference

Variables

View Source
var ApplyFunctionFunc func(ctx context.Context, fn object.Object, args []object.Object, kwargs map[string]object.Object, env *object.Environment) object.Object

ApplyFunctionFunc is set by the evaluator to allow calling user functions This avoids import cycles

View Source
var ApplyMethodFunc func(ctx context.Context, instance *object.Instance, method *object.Function, args []object.Object) object.Object

ApplyMethodFunc is a function type that the evaluator can set to allow calling user methods

View Source
var CompletedProcessClass = &object.Class{
	Name: "CompletedProcess",
	Methods: map[string]object.Object{
		"check_returncode": &object.Builtin{
			Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
				if err := errors.ExactArgs(args, 1); err != nil {
					return err
				}
				if instance, ok := args[0].(*object.Instance); ok {
					if returncode, ok := instance.Fields["returncode"].(*object.Integer); ok {
						if returncode.Value != 0 {
							return errors.NewError("Command returned non-zero exit status %d", returncode.Value)
						}
						return args[0]
					}
				}
				return errors.NewError("Invalid CompletedProcess instance")
			},
			HelpText: `check_returncode() - Check if the process returned successfully

Raises an exception if returncode is non-zero.`,
		},
	},
}

CompletedProcessClass defines the CompletedProcess class

View Source
var HTMLParserLibrary = object.NewLibrary(nil, map[string]object.Object{
	"HTMLParser": &object.Class{
		Name:    "HTMLParser",
		Methods: htmlParserMethods,
	},
}, "HTML parser library compatible with Python's html.parser module")

HTMLParserLibrary provides Python-compatible html.parser functionality

View Source
var RequestsLibrary = object.NewLibrary(map[string]*object.Builtin{

	"exceptions": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			return exceptionsNamespace
		},
	},
	"get": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			url, _, options, err := extractRequestArgs(kwargs, args, false)
			if err != nil {
				return err
			}
			timeout, headers, user, pass := parseRequestOptions(options)
			return httpRequestWithContext(ctx, "GET", url, "", timeout, headers, user, pass)
		},
		HelpText: `get(url, **kwargs) - Send a GET request

Sends an HTTP GET request to the specified URL.

Parameters:
  url (string): The URL to send the request to
  **kwargs: Optional arguments
    - timeout (int): Request timeout in seconds (default: 5)
    - headers (dict): HTTP headers as key-value pairs
    - auth (tuple/list): Basic authentication as (username, password)

Returns:
  Response object with status_code, text, headers, body, url, and json() method`,
	},
	"post": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			url, data, options, err := extractRequestArgs(kwargs, args, true)
			if err != nil {
				return err
			}
			timeout, headers, user, pass := parseRequestOptions(options)
			return httpRequestWithContext(ctx, "POST", url, data, timeout, headers, user, pass)
		},
		HelpText: `post(url, data=None, **kwargs) - Send a POST request

Sends an HTTP POST request to the specified URL with the given data.

Parameters:
  url (string): The URL to send the request to
  data (string, optional): The request body data
  **kwargs: Optional arguments
    - timeout (int): Request timeout in seconds (default: 5)
    - headers (dict): HTTP headers as key-value pairs
    - auth (tuple/list): Basic authentication as (username, password)

Returns:
  Response object with status_code, text, headers, body, url, and json() method`,
	},
	"put": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			url, data, options, err := extractRequestArgs(kwargs, args, true)
			if err != nil {
				return err
			}
			timeout, headers, user, pass := parseRequestOptions(options)
			return httpRequestWithContext(ctx, "PUT", url, data, timeout, headers, user, pass)
		},
		HelpText: `put(url, data=None, **kwargs) - Send a PUT request

Sends an HTTP PUT request to the specified URL with the given data.

Parameters:
  url (string): The URL to send the request to
  data (string, optional): The request body data
  **kwargs: Optional arguments
    - timeout (int): Request timeout in seconds (default: 5)
    - headers (dict): HTTP headers as key-value pairs
    - auth (tuple/list): Basic authentication as (username, password)

Returns:
  Response object with status_code, text, headers, body, url, and json() method`,
	},
	"delete": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			url, _, options, err := extractRequestArgs(kwargs, args, false)
			if err != nil {
				return err
			}
			timeout, headers, user, pass := parseRequestOptions(options)
			return httpRequestWithContext(ctx, "DELETE", url, "", timeout, headers, user, pass)
		},
		HelpText: `delete(url, **kwargs) - Send a DELETE request

Sends an HTTP DELETE request to the specified URL.

Parameters:
  url (string): The URL to send the request to
  **kwargs: Optional arguments
    - timeout (int): Request timeout in seconds (default: 5)
    - headers (dict): HTTP headers as key-value pairs
    - auth (tuple/list): Basic authentication as (username, password)

Returns:
  Response object with status_code, text, headers, body, url, and json() method`,
	},
	"patch": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			url, data, options, err := extractRequestArgs(kwargs, args, true)
			if err != nil {
				return err
			}
			timeout, headers, user, pass := parseRequestOptions(options)
			return httpRequestWithContext(ctx, "PATCH", url, data, timeout, headers, user, pass)
		},
		HelpText: `patch(url, data=None, **kwargs) - Send a PATCH request

Sends an HTTP PATCH request to the specified URL with the given data.

Parameters:
  url (string): The URL to send the request to
  data (string, optional): The request body data
  **kwargs: Optional arguments
    - timeout (int): Request timeout in seconds (default: 5)
    - headers (dict): HTTP headers as key-value pairs
    - auth (tuple/list): Basic authentication as (username, password)

Returns:
  Response object with status_code, text, headers, body, url, and json() method`,
	},
}, map[string]object.Object{

	"RequestException": requestExceptionType,
	"HTTPError":        httpErrorType,
	"Response":         ResponseClass,
}, "HTTP requests library")
View Source
var ResponseClass = &object.Class{
	Name: "Response",
	Methods: map[string]object.Object{
		"json": &object.Builtin{
			Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
				if err := errors.ExactArgs(args, 1); err != nil {
					return err
				}
				if instance, ok := args[0].(*object.Instance); ok {
					if body, err := instance.Fields["body"].AsString(); err == nil {
						var result interface{}
						if err := json.Unmarshal([]byte(body), &result); err != nil {
							return errors.NewError("JSONDecodeError: %s", err.Error())
						}
						return convertJSONToObject(result)
					}
				}
				return errors.NewError("json() called on non-Response object")
			},
			HelpText: `json() - Parses the response body as JSON and returns the parsed object`,
		},
		"raise_for_status": &object.Builtin{
			Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
				if err := errors.ExactArgs(args, 1); err != nil {
					return err
				}
				if instance, ok := args[0].(*object.Instance); ok {
					if statusCode, err := instance.Fields["status_code"].AsInt(); err == nil {
						if statusCode >= 400 {
							if statusCode >= 500 {
								return errors.NewError("HTTPError: %d Server Error", statusCode)
							} else {
								return errors.NewError("HTTPError: %d Client Error", statusCode)
							}
						}
						return &object.Null{}
					}
				}
				return errors.NewError("raise_for_status() called on non-Response object")
			},
			HelpText: `raise_for_status() - Raises an exception if the status code indicates an error`,
		},
	},
}

ResponseClass defines the Response class with its methods

View Source
var SecretsLibrary = object.NewLibrary(map[string]*object.Builtin{
	"token_bytes": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			nbytes := 32
			if len(args) > 0 {
				if intVal, ok := args[0].(*object.Integer); ok {
					nbytes = int(intVal.Value)
				}
			}

			if nbytes < 1 {
				return errors.NewError("token_bytes requires a positive number of bytes")
			}

			bytes := make([]byte, nbytes)
			_, err := rand.Read(bytes)
			if err != nil {
				return errors.NewError("failed to generate random bytes: %s", err.Error())
			}

			elements := make([]object.Object, nbytes)
			for i, b := range bytes {
				elements[i] = object.NewInteger(int64(b))
			}
			return &object.List{Elements: elements}
		},
		HelpText: `token_bytes([nbytes]) - Generate nbytes random bytes

Parameters:
  nbytes - Number of bytes to generate (default 32)

Returns: List of integers representing bytes

Example:
  import secrets
  bytes = secrets.token_bytes(16)`,
	},

	"token_hex": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			nbytes := 32
			if len(args) > 0 {
				if intVal, ok := args[0].(*object.Integer); ok {
					nbytes = int(intVal.Value)
				}
			}

			if nbytes < 1 {
				return errors.NewError("token_hex requires a positive number of bytes")
			}

			bytes := make([]byte, nbytes)
			_, err := rand.Read(bytes)
			if err != nil {
				return errors.NewError("failed to generate random bytes: %s", err.Error())
			}

			return &object.String{Value: hex.EncodeToString(bytes)}
		},
		HelpText: `token_hex([nbytes]) - Generate random text in hexadecimal

Parameters:
  nbytes - Number of random bytes (string will be 2x this length) (default 32)

Returns: Hex string

Example:
  import secrets
  token = secrets.token_hex(16)  # 32 character hex string`,
	},

	"token_urlsafe": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			nbytes := 32
			if len(args) > 0 {
				if intVal, ok := args[0].(*object.Integer); ok {
					nbytes = int(intVal.Value)
				}
			}

			if nbytes < 1 {
				return errors.NewError("token_urlsafe requires a positive number of bytes")
			}

			bytes := make([]byte, nbytes)
			_, err := rand.Read(bytes)
			if err != nil {
				return errors.NewError("failed to generate random bytes: %s", err.Error())
			}

			encoded := base64.URLEncoding.EncodeToString(bytes)

			encoded = strings.TrimRight(encoded, "=")
			return &object.String{Value: encoded}
		},
		HelpText: `token_urlsafe([nbytes]) - Generate URL-safe random text

Parameters:
  nbytes - Number of random bytes (default 32)

Returns: URL-safe base64 encoded string

Example:
  import secrets
  token = secrets.token_urlsafe(16)`,
	},

	"randbelow": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			if len(args) != 1 {
				return errors.NewError("randbelow() requires exactly 1 argument")
			}

			n, ok := args[0].(*object.Integer)
			if !ok {
				return errors.NewTypeError("INTEGER", args[0].Type().String())
			}

			if n.Value <= 0 {
				return errors.NewError("randbelow requires a positive upper bound")
			}

			result, err := rand.Int(rand.Reader, big.NewInt(n.Value))
			if err != nil {
				return errors.NewError("failed to generate random number: %s", err.Error())
			}

			return object.NewInteger(result.Int64())
		},
		HelpText: `randbelow(n) - Generate a random integer in range [0, n)

Parameters:
  n - Exclusive upper bound (must be positive)

Returns: Random integer from 0 to n-1

Example:
  import secrets
  dice = secrets.randbelow(6) + 1  # 1-6`,
	},

	"randbits": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			if len(args) != 1 {
				return errors.NewError("randbits() requires exactly 1 argument")
			}

			k, ok := args[0].(*object.Integer)
			if !ok {
				return errors.NewTypeError("INTEGER", args[0].Type().String())
			}

			if k.Value < 1 {
				return errors.NewError("randbits requires a positive number of bits")
			}

			result, err := rand.Int(rand.Reader, big.NewInt(0).Lsh(big.NewInt(1), uint(k.Value)))
			if err != nil {
				return errors.NewError("failed to generate random bits: %s", err.Error())
			}

			return object.NewInteger(result.Int64())
		},
		HelpText: `randbits(k) - Generate a random integer with k random bits

Parameters:
  k - Number of random bits (must be positive)

Returns: Random integer with k bits

Example:
  import secrets
  random_int = secrets.randbits(8)  # 0-255`,
	},

	"choice": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			if len(args) != 1 {
				return errors.NewError("choice() requires exactly 1 argument")
			}

			if str, ok := args[0].(*object.String); ok {
				if len(str.Value) == 0 {
					return errors.NewError("cannot choose from empty sequence")
				}
				idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(str.Value))))
				if err != nil {
					return errors.NewError("failed to generate random index: %s", err.Error())
				}
				return &object.String{Value: string(str.Value[idx.Int64()])}
			}

			list, ok := args[0].(*object.List)
			if !ok {
				return errors.NewTypeError("LIST or STRING", args[0].Type().String())
			}

			if len(list.Elements) == 0 {
				return errors.NewError("cannot choose from empty sequence")
			}

			idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(list.Elements))))
			if err != nil {
				return errors.NewError("failed to generate random index: %s", err.Error())
			}

			return list.Elements[idx.Int64()]
		},
		HelpText: `choice(sequence) - Return a random element from sequence

Parameters:
  sequence - Non-empty list or string to choose from

Returns: Random element from the sequence

Example:
  import secrets
  item = secrets.choice(["apple", "banana", "cherry"])
  char = secrets.choice("abcdef")`,
	},

	"compare_digest": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			if len(args) != 2 {
				return errors.NewError("compare_digest() requires exactly 2 arguments")
			}

			a, okA := args[0].(*object.String)
			b, okB := args[1].(*object.String)
			if !okA || !okB {
				return errors.NewError("compare_digest() requires two string arguments")
			}

			if subtle.ConstantTimeCompare([]byte(a.Value), []byte(b.Value)) == 1 {
				return &object.Boolean{Value: true}
			}
			return &object.Boolean{Value: false}
		},
		HelpText: `compare_digest(a, b) - Compare two strings using constant-time comparison

This function is designed to prevent timing attacks when comparing secret values.

Parameters:
  a - First string
  b - Second string

Returns: True if strings are equal, False otherwise

Example:
  import secrets
  secrets.compare_digest(user_token, stored_token)`,
	},
}, nil, "Cryptographically strong random number generation (extended library)")

SecretsLibrary provides cryptographically strong random number generation NOTE: This is an extended library and not enabled by default

View Source
var SubprocessLibrary = object.NewLibrary(map[string]*object.Builtin{
	"run": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			if err := errors.MinArgs(args, 1); err != nil {
				return err
			}

			// Parse args - can be string or list
			var cmdArgs []string
			var cmdStr string
			if args[0].Type() == object.STRING_OBJ {
				cmdStr, _ = args[0].AsString()

				shell := false
				if sh, exists := kwargs.Kwargs["shell"]; exists {
					if b, ok := sh.(*object.Boolean); ok {
						shell = b.Value
					}
				}
				if shell {

					cmdArgs = []string{cmdStr}
				} else {

					cmdArgs = strings.Fields(cmdStr)
				}
			} else if args[0].Type() == object.LIST_OBJ {
				list, _ := args[0].AsList()
				cmdArgs = make([]string, len(list))
				for i, arg := range list {
					if str, err := arg.AsString(); err == nil {
						cmdArgs[i] = str
					} else {
						return errors.NewTypeError("STRING", arg.Type().String())
					}
				}
			} else {
				return errors.NewTypeError("STRING or LIST", args[0].Type().String())
			}

			captureOutput := false
			shell := false
			cwd := ""
			timeout := 0.0
			check := false
			text := false
			encoding := "utf-8"
			inputData := ""
			env := make(map[string]string)

			if capture, exists := kwargs.Kwargs["capture_output"]; exists {
				if b, ok := capture.(*object.Boolean); ok {
					captureOutput = b.Value
				}
			}
			if sh, exists := kwargs.Kwargs["shell"]; exists {
				if b, ok := sh.(*object.Boolean); ok {
					shell = b.Value
				}
			}
			if wd, exists := kwargs.Kwargs["cwd"]; exists {
				if s, ok := wd.(*object.String); ok {
					cwd = s.Value
				}
			}
			if to, exists := kwargs.Kwargs["timeout"]; exists {
				if f, ok := to.(*object.Float); ok {
					timeout = f.Value
				} else if i, ok := to.(*object.Integer); ok {
					timeout = float64(i.Value)
				}
			}
			if ch, exists := kwargs.Kwargs["check"]; exists {
				if b, ok := ch.(*object.Boolean); ok {
					check = b.Value
				}
			}
			if txt, exists := kwargs.Kwargs["text"]; exists {
				if b, ok := txt.(*object.Boolean); ok {
					text = b.Value
				}
			}
			if enc, exists := kwargs.Kwargs["encoding"]; exists {
				if s, ok := enc.(*object.String); ok {
					encoding = s.Value
				}
			}
			if inp, exists := kwargs.Kwargs["input"]; exists {
				if s, ok := inp.(*object.String); ok {
					inputData = s.Value
				}
			}
			if envDict, exists := kwargs.Kwargs["env"]; exists {
				if d, ok := envDict.(*object.Dict); ok {
					for _, pair := range d.Pairs {
						if keyStr, ok := pair.Key.(*object.String); ok {
							if valStr, ok := pair.Value.(*object.String); ok {
								env[keyStr.Value] = valStr.Value
							}
						}
					}
				}
			}

			if shell && args[0].Type() == object.STRING_OBJ {
				cmdArgs = []string{"sh", "-c", cmdStr}
			}

			// Execute command
			var cmd *exec.Cmd
			if shell && args[0].Type() == object.STRING_OBJ {
				cmd = exec.Command(cmdArgs[0], cmdArgs[1:]...)
			} else {
				cmd = exec.Command(cmdArgs[0], cmdArgs[1:]...)
			}

			if cwd != "" {
				cmd.Dir = cwd
			}

			if len(env) > 0 {
				cmd.Env = make([]string, 0, len(env))
				for k, v := range env {
					cmd.Env = append(cmd.Env, k+"="+v)
				}
			}

			if inputData != "" {
				cmd.Stdin = strings.NewReader(inputData)
			}

			if timeout > 0 {
				ctx, cancel := context.WithTimeout(ctx, time.Duration(timeout*float64(time.Second)))
				defer cancel()
				cmd = exec.CommandContext(ctx, cmd.Path, cmd.Args[1:]...)
				cmd.Dir = cwd
				if len(env) > 0 {
					cmd.Env = make([]string, 0, len(env))
					for k, v := range env {
						cmd.Env = append(cmd.Env, k+"="+v)
					}
				}
				if inputData != "" {
					cmd.Stdin = strings.NewReader(inputData)
				}
			}

			var stdout, stderr []byte
			var err error

			if captureOutput {
				stdout, err = cmd.Output()
				if exitErr, ok := err.(*exec.ExitError); ok {
					stderr = exitErr.Stderr
				}
			} else {
				err = cmd.Run()
			}

			returncode := 0
			if err != nil {
				if exitErr, ok := err.(*exec.ExitError); ok {
					returncode = exitErr.ExitCode()
				} else {
					return errors.NewError("Command execution failed: %v", err)
				}
			}

			// Convert output based on text/encoding settings
			var stdoutStr, stderrStr string
			if text {

				_ = encoding
				stdoutStr = string(stdout)
				stderrStr = string(stderr)
			} else {

				stdoutStr = string(stdout)
				stderrStr = string(stderr)
			}
			instance := &object.Instance{
				Class: CompletedProcessClass,
				Fields: map[string]object.Object{
					"args":       &object.List{Elements: make([]object.Object, len(cmdArgs))},
					"returncode": &object.Integer{Value: int64(returncode)},
					"stdout":     &object.String{Value: stdoutStr},
					"stderr":     &object.String{Value: stderrStr},
				},
			}
			for i, arg := range cmdArgs {
				instance.Fields["args"].(*object.List).Elements[i] = &object.String{Value: arg}
			}

			if check && returncode != 0 {
				return errors.NewError("Command returned non-zero exit status %d", returncode)
			}

			return instance
		},
		HelpText: `run(args, options={}) - Run a command

Runs a command and returns a CompletedProcess instance.

Parameters:
  args (string or list): Command to run. If string, split on spaces. If list, each element is an argument.
  options (dict, optional): Options
    - capture_output (bool): Capture stdout and stderr (default: false)
    - shell (bool): Run command through shell (default: false)
    - cwd (string): Working directory for command
    - timeout (int): Timeout in seconds
    - check (bool): Raise exception if returncode is non-zero

Returns:
  CompletedProcess instance with args, returncode, stdout, stderr`,
	},
}, map[string]object.Object{}, "Subprocess library for running external commands")
View Source
var SysExitCallback func(code int)

SysExitCallback can be set to customize sys.exit() behavior

View Source
var ThreadsLibrary = object.NewLibrary(map[string]*object.Builtin{
	"run": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			if err := errors.MinArgs(args, 1); err != nil {
				return err
			}

			fn := args[0]
			fnArgs := args[1:]

			env := getEnvFromContext(ctx)
			if env == nil {
				return errors.NewError("async.run: no environment in context")
			}

			clonedEnv := cloneEnvironment(env)
			promise := newPromise()

			go func() {
				var result object.Object
				if ApplyFunctionFunc != nil {
					result = ApplyFunctionFunc(ctx, fn, fnArgs, kwargs.Kwargs, clonedEnv)
				} else {
					result = errors.NewError("async library not properly initialized")
				}

				if err, ok := result.(*object.Error); ok {
					promise.set(nil, fmt.Errorf("%s", err.Message))
				} else {
					promise.set(result, nil)
				}
			}()

			return &object.Builtin{
				Attributes: map[string]object.Object{
					"get": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							result, err := promise.get()
							if err != nil {
								return errors.NewError("async error: %v", err)
							}
							return result
						},
						HelpText: "get() - Wait for and return the result",
					},
					"wait": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							_, err := promise.get()
							if err != nil {
								return errors.NewError("async error: %v", err)
							}
							return &object.Null{}
						},
						HelpText: "wait() - Wait for completion and discard the result",
					},
				},
				HelpText: "Promise object - call .get() to retrieve result or .wait() to wait without result",
			}
		},
		HelpText: `run(func, *args, **kwargs) - Run function asynchronously

Executes function in a separate goroutine with isolated environment.
Returns a Promise object. Call .get() to retrieve the result or .wait() to wait without result.
Supports both positional and keyword arguments.

Example:
    def worker(x, y=10):
        return x + y

    promise = async.run(worker, 5, y=3)
    result = promise.get()  # Returns 8
    # Or just wait for completion:
    promise.wait()  # Waits but discards result`,
	},

	"Atomic": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			initial := int64(0)
			if len(args) > 0 {
				if i, err := args[0].AsInt(); err == nil {
					initial = i
				} else {
					return errors.NewTypeError("INTEGER", args[0].Type().String())
				}
			}

			atomic := newAtomicInt64(initial)

			return &object.Builtin{
				Attributes: map[string]object.Object{
					"add": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							delta := int64(1)
							if len(args) > 0 {
								if d, err := args[0].AsInt(); err == nil {
									delta = d
								} else {
									return errors.NewTypeError("INTEGER", args[0].Type().String())
								}
							}
							newVal := atomic.add(delta)
							return object.NewInteger(newVal)
						},
						HelpText: "add(delta=1) - Atomically add delta and return new value",
					},
					"get": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							return object.NewInteger(atomic.get())
						},
						HelpText: "get() - Atomically read the value",
					},
					"set": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							if err := errors.ExactArgs(args, 1); err != nil {
								return err
							}
							if val, err := args[0].AsInt(); err == nil {
								atomic.set(val)
								return &object.Null{}
							}
							return errors.NewTypeError("INTEGER", args[0].Type().String())
						},
						HelpText: "set(value) - Atomically set the value",
					},
				},
				HelpText: "Atomic integer - lock-free operations",
			}
		},
		HelpText: `Atomic(initial=0) - Create an atomic integer counter

Lock-free atomic operations for high-performance counters.

Example:
    counter = async.Atomic(0)
    counter.add(1)      # Atomic increment
    counter.add(-5)     # Atomic add
    counter.set(100)    # Atomic set
    value = counter.get()  # Atomic read`,
	},

	"Shared": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			var initial object.Object = &object.Null{}
			if len(args) > 0 {
				initial = args[0]
			}

			shared := newSharedValue(initial)

			return &object.Builtin{
				Attributes: map[string]object.Object{
					"get": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							return shared.get()
						},
						HelpText: "get() - Get the current value (thread-safe)",
					},
					"set": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							if err := errors.ExactArgs(args, 1); err != nil {
								return err
							}
							shared.set(args[0])
							return &object.Null{}
						},
						HelpText: "set(value) - Set the value (thread-safe)",
					},
				},
				HelpText: "Shared variable - thread-safe access with get()/set()",
			}
		},
		HelpText: `Shared(initial_value) - Create a thread-safe shared variable

For complex types that need mutex protection.

Example:
    shared_list = async.Shared([])

    def append_item(item):
        current = shared_list.get()
        current.append(item)
        shared_list.set(current)

    promises = [async.run(append_item, i) for i in range(100)]
    for p in promises:
        p.get()`,
	},

	"WaitGroup": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			wg := newWaitGroup()

			return &object.Builtin{
				Attributes: map[string]object.Object{
					"add": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							delta := int64(1)
							if len(args) > 0 {
								if d, err := args[0].AsInt(); err == nil {
									delta = d
								}
							}
							wg.wg.Add(int(delta))
							return &object.Null{}
						},
						HelpText: "add(delta=1) - Add to the wait group counter",
					},
					"done": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							wg.wg.Done()
							return &object.Null{}
						},
						HelpText: "done() - Decrement the wait group counter",
					},
					"wait": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							wg.wg.Wait()
							return &object.Null{}
						},
						HelpText: "wait() - Block until counter reaches zero",
					},
				},
				HelpText: "WaitGroup - Go-style synchronization primitive",
			}
		},
		HelpText: `WaitGroup() - Create a wait group for synchronizing goroutines

Example:
    wg = async.WaitGroup()

    def worker(id):
        print(f"Worker {id}")
        wg.done()

    for i in range(10):
        wg.add(1)
        async.run(worker, i)

    wg.wait()`,
	},

	"Queue": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			maxsize := 0
			if len(args) > 0 {
				if m, err := args[0].AsInt(); err == nil {
					maxsize = int(m)
				}
			}
			if m, ok := kwargs.Kwargs["maxsize"]; ok {
				if mInt, err := m.AsInt(); err == nil {
					maxsize = int(mInt)
				}
			}

			queue := newQueue(maxsize)

			return &object.Builtin{
				Attributes: map[string]object.Object{
					"put": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							if err := errors.ExactArgs(args, 1); err != nil {
								return err
							}
							if err := queue.put(args[0]); err != nil {
								return errors.NewError("queue error: %v", err)
							}
							return &object.Null{}
						},
						HelpText: "put(item) - Add item to queue (blocks if full)",
					},
					"get": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							item, err := queue.get()
							if err != nil {
								return errors.NewError("queue error: %v", err)
							}
							return item
						},
						HelpText: "get() - Remove and return item from queue (blocks if empty)",
					},
					"size": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							return object.NewInteger(int64(queue.size()))
						},
						HelpText: "size() - Return number of items in queue",
					},
					"close": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							queue.close()
							return &object.Null{}
						},
						HelpText: "close() - Close the queue",
					},
				},
				HelpText: "Queue - Thread-safe queue for producer-consumer patterns",
			}
		},
		HelpText: `Queue(maxsize=0) - Create a thread-safe queue

maxsize=0 creates unbounded queue, maxsize>0 creates bounded queue.

Example:
    queue = async.Queue(maxsize=100)

    def producer():
        for i in range(10):
            queue.put(i)

    def consumer():
        for i in range(10):
            item = queue.get()
            print(item)

    async.run(producer)
    async.run(consumer)`,
	},

	"Pool": {
		Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
			if err := errors.MinArgs(args, 1); err != nil {
				return err
			}

			worker := args[0]
			workers := 4
			queueDepth := 0

			if len(args) > 1 {
				if w, err := args[1].AsInt(); err == nil {
					workers = int(w)
				}
			}
			if w, ok := kwargs.Kwargs["workers"]; ok {
				if wInt, err := w.AsInt(); err == nil {
					workers = int(wInt)
				}
			}
			if q, ok := kwargs.Kwargs["queue_depth"]; ok {
				if qInt, err := q.AsInt(); err == nil {
					queueDepth = int(qInt)
				}
			}

			env := getEnvFromContext(ctx)
			if env == nil {
				return errors.NewError("async.Pool: no environment in context")
			}

			pool := newPool(ctx, worker, env, workers, queueDepth)

			return &object.Builtin{
				Attributes: map[string]object.Object{
					"submit": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							if err := errors.ExactArgs(args, 1); err != nil {
								return err
							}
							if err := pool.submit(args[0]); err != nil {
								return errors.NewError("pool submit error: %v", err)
							}
							return &object.Null{}
						},
						HelpText: "submit(data) - Submit data to pool for processing",
					},
					"close": &object.Builtin{
						Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
							pool.close()
							return &object.Null{}
						},
						HelpText: "close() - Stop accepting work and wait for completion",
					},
				},
				HelpText: "Pool - Worker pool for processing data",
			}
		},
		HelpText: `Pool(worker_func, workers=4, queue_depth=workers*2) - Create a worker pool

worker_func is called with each submitted data item.

Example:
    def process_data(item):
        print(f"Processing {item}")

    pool = async.Pool(process_data, workers=4, queue_depth=1000)
    for i in range(100):
        pool.submit(i)
    pool.close()`,
	},
}, nil, "Asynchronous execution with isolated environments")

ThreadsLibrary provides async execution primitives

View Source
var WaitForLibrary = object.NewLibrary(
	map[string]*object.Builtin{
		"file": {
			Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
				if err := errors.MinArgs(args, 1); err != nil {
					return err
				}

				path, err := args[0].AsString()
				if err != nil {
					return err
				}

				timeout, pollRate, err := parseWaitOptions(args, kwargs.Kwargs)
				if err != nil {
					return err
				}

				deadline := time.Now().Add(time.Duration(timeout) * time.Second)
				pollInterval := time.Duration(pollRate * float64(time.Second))

				for time.Now().Before(deadline) {
					if _, err := os.Stat(path); err == nil {
						return &object.Boolean{Value: true}
					}

					select {
					case <-ctx.Done():
						return &object.Boolean{Value: false}
					case <-time.After(pollInterval):

					}
				}

				if _, err := os.Stat(path); err == nil {
					return &object.Boolean{Value: true}
				}
				return &object.Boolean{Value: false}
			},
			HelpText: `file(path, timeout=30, poll_rate=1) - Wait for a file to exist

Waits for the specified file to become available.

Parameters:
  path (string): Path to the file to wait for
  timeout (int): Maximum time to wait in seconds (default: 30)
  poll_rate (float): Time between checks in seconds (default: 1)

Returns:
  bool: True if file exists, False if timeout exceeded`,
		},
		"dir": {
			Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
				if err := errors.MinArgs(args, 1); err != nil {
					return err
				}

				path, err := args[0].AsString()
				if err != nil {
					return err
				}

				timeout, pollRate, err := parseWaitOptions(args, kwargs.Kwargs)
				if err != nil {
					return err
				}

				deadline := time.Now().Add(time.Duration(timeout) * time.Second)
				pollInterval := time.Duration(pollRate * float64(time.Second))

				for time.Now().Before(deadline) {
					if info, err := os.Stat(path); err == nil {
						if info.IsDir() {
							return &object.Boolean{Value: true}
						}
					}

					select {
					case <-ctx.Done():
						return &object.Boolean{Value: false}
					case <-time.After(pollInterval):

					}
				}

				if info, err := os.Stat(path); err == nil {
					if info.IsDir() {
						return &object.Boolean{Value: true}
					}
				}
				return &object.Boolean{Value: false}
			},
			HelpText: `dir(path, timeout=30, poll_rate=1) - Wait for a directory to exist

Waits for the specified directory to become available.

Parameters:
  path (string): Path to the directory to wait for
  timeout (int): Maximum time to wait in seconds (default: 30)
  poll_rate (float): Time between checks in seconds (default: 1)

Returns:
  bool: True if directory exists, False if timeout exceeded`,
		},
		"port": {
			Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
				if err := errors.MinArgs(args, 2); err != nil {
					return err
				}

				host, err := args[0].AsString()
				if err != nil {
					return err
				}

				var port int
				switch v := args[1].(type) {
				case *object.Integer:
					port = int(v.Value)
				case *object.String:
					p, err := strconv.Atoi(v.Value)
					if err != nil {
						return errors.NewError("invalid port number: %s", v.Value)
					}
					port = p
				default:
					return errors.NewTypeError("INT|STRING", args[1].Type().String())
				}

				timeout, pollRate, err := parseWaitOptionsKwargsOnly(30, 1.0, kwargs.Kwargs)
				if err != nil {
					return err
				}

				deadline := time.Now().Add(time.Duration(timeout) * time.Second)
				pollInterval := time.Duration(pollRate * float64(time.Second))
				address := fmt.Sprintf("%s:%d", host, port)

				for time.Now().Before(deadline) {
					conn, err := net.DialTimeout("tcp", address, time.Second)
					if err == nil {
						conn.Close()
						return &object.Boolean{Value: true}
					}

					select {
					case <-ctx.Done():
						return &object.Boolean{Value: false}
					case <-time.After(pollInterval):

					}
				}

				if conn, err := net.DialTimeout("tcp", address, time.Second); err == nil {
					conn.Close()
					return &object.Boolean{Value: true}
				}
				return &object.Boolean{Value: false}
			},
			HelpText: `port(host, port, timeout=30, poll_rate=1) - Wait for a TCP port to be open

Waits for the specified TCP port to accept connections.

Parameters:
  host (string): Hostname or IP address
  port (int|string): Port number
  timeout (int): Maximum time to wait in seconds (default: 30)
  poll_rate (float): Time between checks in seconds (default: 1)

Returns:
  bool: True if port is open, False if timeout exceeded`,
		},
		"http": {
			Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
				if err := errors.MinArgs(args, 1); err != nil {
					return err
				}

				url, err := args[0].AsString()
				if err != nil {
					return err
				}

				timeout := 30
				pollRate := 1.0
				expectedStatus := int64(200)

				if len(args) > 1 {
					if t, err := args[1].AsInt(); err == nil {
						timeout = int(t)
					} else {
						return err
					}
				}

				for k, v := range kwargs.Kwargs {
					switch k {
					case "timeout":
						if t, err := v.AsInt(); err == nil {
							timeout = int(t)
						} else {
							return err
						}
					case "poll_rate":
						if f, err := v.AsFloat(); err == nil {
							pollRate = f
						} else if i, err := v.AsInt(); err == nil {
							pollRate = float64(i)
						} else {
							return errors.NewTypeError("FLOAT", v.Type().String())
						}
					case "status_code":
						if s, err := v.AsInt(); err == nil {
							expectedStatus = s
						} else {
							return err
						}
					}
				}

				deadline := time.Now().Add(time.Duration(timeout) * time.Second)
				pollInterval := time.Duration(pollRate * float64(time.Second))

				client := pool.GetHTTPClient()

				for time.Now().Before(deadline) {
					req, httpErr := http.NewRequestWithContext(ctx, "GET", url, nil)
					if httpErr != nil {
						return errors.NewError("http request error: %s", httpErr.Error())
					}

					resp, httpErr := client.Do(req)
					if httpErr == nil {
						statusMatch := int64(resp.StatusCode) == expectedStatus
						resp.Body.Close()
						if statusMatch {
							return &object.Boolean{Value: true}
						}
					}

					select {
					case <-ctx.Done():
						return &object.Boolean{Value: false}
					case <-time.After(pollInterval):

					}
				}

				req, httpErr := http.NewRequestWithContext(ctx, "GET", url, nil)
				if httpErr != nil {
					return &object.Boolean{Value: false}
				}
				if resp, httpErr := client.Do(req); httpErr == nil {
					statusMatch := int64(resp.StatusCode) == expectedStatus
					resp.Body.Close()
					if statusMatch {
						return &object.Boolean{Value: true}
					}
				}
				return &object.Boolean{Value: false}
			},
			HelpText: `http(url, timeout=30, poll_rate=1, status_code=200) - Wait for HTTP endpoint

Waits for the specified HTTP endpoint to respond with the expected status code.

Parameters:
  url (string): URL to check
  timeout (int): Maximum time to wait in seconds (default: 30)
  poll_rate (float): Time between checks in seconds (default: 1)
  status_code (int): Expected HTTP status code (default: 200)

Returns:
  bool: True if endpoint responds with expected status, False if timeout exceeded`,
		},
		"file_content": {
			Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
				if err := errors.MinArgs(args, 2); err != nil {
					return err
				}

				path, err := args[0].AsString()
				if err != nil {
					return err
				}

				content, err := args[1].AsString()
				if err != nil {
					return err
				}

				timeout, pollRate, err := parseWaitOptionsKwargsOnly(30, 1.0, kwargs.Kwargs)
				if err != nil {
					return err
				}

				deadline := time.Now().Add(time.Duration(timeout) * time.Second)
				pollInterval := time.Duration(pollRate * float64(time.Second))

				for time.Now().Before(deadline) {
					if data, err := os.ReadFile(path); err == nil {
						if strings.Contains(string(data), content) {
							return &object.Boolean{Value: true}
						}
					}

					select {
					case <-ctx.Done():
						return &object.Boolean{Value: false}
					case <-time.After(pollInterval):

					}
				}

				if data, err := os.ReadFile(path); err == nil {
					if strings.Contains(string(data), content) {
						return &object.Boolean{Value: true}
					}
				}
				return &object.Boolean{Value: false}
			},
			HelpText: `file_content(path, content, timeout=30, poll_rate=1) - Wait for file to contain content

Waits for the specified file to exist and contain the given content.

Parameters:
  path (string): Path to the file to check
  content (string): Content to search for in the file
  timeout (int): Maximum time to wait in seconds (default: 30)
  poll_rate (float): Time between checks in seconds (default: 1)

Returns:
  bool: True if file contains the content, False if timeout exceeded`,
		},
		"process_name": {
			Fn: func(ctx context.Context, kwargs object.Kwargs, args ...object.Object) object.Object {
				if err := errors.MinArgs(args, 1); err != nil {
					return err
				}

				processName, err := args[0].AsString()
				if err != nil {
					return err
				}

				timeout, pollRate, err := parseWaitOptions(args, kwargs.Kwargs)
				if err != nil {
					return err
				}

				deadline := time.Now().Add(time.Duration(timeout) * time.Second)
				pollInterval := time.Duration(pollRate * float64(time.Second))

				for time.Now().Before(deadline) {
					if processRunning(processName) {
						return &object.Boolean{Value: true}
					}

					select {
					case <-ctx.Done():
						return &object.Boolean{Value: false}
					case <-time.After(pollInterval):

					}
				}

				if processRunning(processName) {
					return &object.Boolean{Value: true}
				}
				return &object.Boolean{Value: false}
			},
			HelpText: `process_name(name, timeout=30, poll_rate=1) - Wait for a process to be running

Waits for a process with the specified name to be running.

Parameters:
  name (string): Process name to search for
  timeout (int): Maximum time to wait in seconds (default: 30)
  poll_rate (float): Time between checks in seconds (default: 1)

Returns:
  bool: True if process is running, False if timeout exceeded`,
		},
	},
	nil,
	"Wait for resources to become available",
)

Functions

func NewConsoleLibrary

func NewConsoleLibrary(reader io.Reader) *object.Library

NewConsoleLibrary creates a new console library instance with its own scanner. Each scriptling environment should have its own console library to maintain proper buffering state for the input reader.

func NewGlobLibrary

func NewGlobLibrary(config fssecurity.Config) *object.Library

NewGlobLibrary creates a new Glob library with the given configuration.

func NewOSLibrary

func NewOSLibrary(config fssecurity.Config) (*object.Library, *object.Library)

NewOSLibrary creates a new OS library with the given configuration. The returned libraries are for "os" and "os.path". Prefer using RegisterOSLibrary which handles registration automatically.

func NewPathlibLibrary

func NewPathlibLibrary(config fssecurity.Config) *object.Library

NewPathlibLibrary creates a new Pathlib library with the given configuration.

func NewSysLibrary

func NewSysLibrary(argv []string) *object.Library

NewSysLibrary creates a new sys library with the given argv

func RegisterConsoleLibrary

func RegisterConsoleLibrary(registrar interface{ RegisterLibrary(string, *object.Library) })

RegisterConsoleLibrary registers the console library with a scriptling instance

func RegisterGlobLibrary

func RegisterGlobLibrary(registrar object.LibraryRegistrar, allowedPaths []string)

RegisterGlobLibrary registers the glob library with a Scriptling instance. If allowedPaths is empty or nil, all paths are allowed (no restrictions). If allowedPaths contains paths, all glob operations are restricted to those directories.

SECURITY: When running untrusted scripts, ALWAYS provide allowedPaths to restrict file system access. The security checks prevent: - Reading files outside allowed directories - Path traversal attacks (../../../etc/passwd) - Symlink attacks (symlinks pointing outside allowed dirs)

Example:

No restrictions - full filesystem access (DANGEROUS for untrusted code)
extlibs.RegisterGlobLibrary(s, nil)

Restricted to specific directories (SECURE)
extlibs.RegisterGlobLibrary(s, []string{"/tmp/sandbox", "/home/user/data"})

func RegisterHTMLParserLibrary

func RegisterHTMLParserLibrary(registrar interface{ RegisterLibrary(string, *object.Library) })

func RegisterLoggingLibrary

func RegisterLoggingLibrary(registrar interface{ RegisterLibrary(string, *object.Library) }, loggerInstance logger.Logger)

RegisterLoggingLibrary registers the logging library with the given registrar and optional logger Each environment gets its own logger instance

func RegisterLoggingLibraryDefault

func RegisterLoggingLibraryDefault(registrar interface{ RegisterLibrary(string, *object.Library) })

RegisterLoggingLibraryDefault registers the logging library with default configuration

func RegisterOSLibrary

func RegisterOSLibrary(registrar object.LibraryRegistrar, allowedPaths []string)

RegisterOSLibrary registers the os and os.path libraries with a Scriptling instance. If allowedPaths is empty or nil, all paths are allowed (no restrictions). If allowedPaths contains paths, all file operations are restricted to those directories.

SECURITY: When running untrusted scripts, ALWAYS provide allowedPaths to restrict file system access. The security checks prevent: - Reading/writing files outside allowed directories - Path traversal attacks (../../../etc/passwd) - Symlink attacks (symlinks pointing outside allowed dirs)

Example:

No restrictions - full filesystem access (DANGEROUS for untrusted code)
extlibs.RegisterOSLibrary(s, nil)

Restricted to specific directories (SECURE)
extlibs.RegisterOSLibrary(s, []string{"/tmp/sandbox", "/home/user/data"})

func RegisterPathlibLibrary

func RegisterPathlibLibrary(registrar object.LibraryRegistrar, allowedPaths []string)

RegisterPathlibLibrary registers the pathlib library with a Scriptling instance.

func RegisterRequestsLibrary

func RegisterRequestsLibrary(registrar interface{ RegisterLibrary(string, *object.Library) })

func RegisterSecretsLibrary

func RegisterSecretsLibrary(registrar interface{ RegisterLibrary(string, *object.Library) })

func RegisterSubprocessLibrary

func RegisterSubprocessLibrary(registrar interface{ RegisterLibrary(string, *object.Library) })

func RegisterSysLibrary

func RegisterSysLibrary(registrar interface{ RegisterLibrary(string, *object.Library) }, argv []string)

func RegisterThreadsLibrary

func RegisterThreadsLibrary(registrar interface{ RegisterLibrary(string, *object.Library) })

RegisterThreadsLibrary registers the threads library with the given registrar

func RegisterWaitForLibrary

func RegisterWaitForLibrary(registrar interface{ RegisterLibrary(string, *object.Library) })

Types

type AtomicInt64

type AtomicInt64 struct {
	// contains filtered or unexported fields
}

AtomicInt64 wraps an atomic int64

type CompletedProcess

type CompletedProcess struct {
	Args       []string
	Returncode int
	Stdout     string
	Stderr     string
}

CompletedProcess represents the result of a subprocess.run call

func (*CompletedProcess) AsBool

func (cp *CompletedProcess) AsBool() (bool, object.Object)

func (*CompletedProcess) AsDict

func (cp *CompletedProcess) AsDict() (map[string]object.Object, object.Object)

func (*CompletedProcess) AsFloat

func (cp *CompletedProcess) AsFloat() (float64, object.Object)

func (*CompletedProcess) AsInt

func (cp *CompletedProcess) AsInt() (int64, object.Object)

func (*CompletedProcess) AsList

func (cp *CompletedProcess) AsList() ([]object.Object, object.Object)

func (*CompletedProcess) AsString

func (cp *CompletedProcess) AsString() (string, object.Object)

func (*CompletedProcess) Inspect

func (cp *CompletedProcess) Inspect() string

func (*CompletedProcess) Type

func (cp *CompletedProcess) Type() object.ObjectType

type GlobLibraryInstance

type GlobLibraryInstance struct {
	// contains filtered or unexported fields
}

GlobLibraryInstance holds the configured Glob library instance

type PathlibLibraryInstance

type PathlibLibraryInstance struct {
	PathClass *object.Class
	// contains filtered or unexported fields
}

PathlibLibraryInstance holds the configured Pathlib library instance

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool is a worker pool with a specific worker function

type Promise

type Promise struct {
	// contains filtered or unexported fields
}

Promise represents an async operation result

type Queue

type Queue struct {
	// contains filtered or unexported fields
}

Queue is a thread-safe queue

type SharedValue

type SharedValue struct {
	// contains filtered or unexported fields
}

SharedValue wraps a value with a mutex for thread-safe access

type SysExitCode

type SysExitCode struct {
	Code int
}

SysExitCode is used to communicate exit codes from sys.exit()

func (*SysExitCode) Error

func (s *SysExitCode) Error() string

type WaitGroup

type WaitGroup struct {
	// contains filtered or unexported fields
}

WaitGroup is a Go-style wait group

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL