Module: Rubyx

Defined in:
lib/rubyx.rb,
lib/rubyx/uv.rb,
lib/rubyx/error.rb,
lib/rubyx/rails.rb,
lib/rubyx/context.rb,
lib/rubyx/railtie.rb,
lib/rubyx/version.rb,
lib/generators/rubyx/install_generator.rb

Defined Under Namespace

Modules: Generators, Rails, Uv Classes: AttributeError, Context, Error, ImportError, IndexError, InvalidModuleNameError, KeyError, PythonError, Railtie, TypeError, ValueError

Constant Summary collapse

VALID_MODULE_NAME_PATTERN =
/\A[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*\z/
VERSION =
"0.2.1".freeze

Class Method Summary collapse

Class Method Details

.async_await(code_or_coroutine, **globals) ⇒ Rubyx::Future

Run a Python coroutine on a background thread (non-blocking). Accepts either a RubyxObject (coroutine) or a code string with globals.

Examples:

future = Rubyx.async_await("fetch(url)", url: "https://example.com")
future.value

Parameters:

  • code_or_coroutine (String, RubyxObject)

    Python code or coroutine object

  • globals (Hash)

    Ruby values to inject as Python globals (only with code string)

Returns:

  • (Rubyx::Future)

    A future that resolves to the result



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/rubyx.rb', line 111

def self.async_await(code_or_coroutine, **globals)
  if code_or_coroutine.is_a?(String)
    if globals.empty?
      _async_await_with_globals(code_or_coroutine, {})
    else
      _async_await_with_globals(code_or_coroutine, globals)
    end
  else
    raise ArgumentError, "cannot pass globals with a coroutine object" unless globals.empty?
    _async_await(code_or_coroutine)
  end
end

.await(code_or_coroutine, **globals) ⇒ RubyxObject

Run a Python coroutine with asyncio.run() (blocking). Accepts either a RubyxObject (coroutine) or a code string with globals.

Examples:

Rubyx.await("fetch(url)", url: "https://example.com")

Parameters:

  • code_or_coroutine (String, RubyxObject)

    Python code or coroutine object

  • globals (Hash)

    Ruby values to inject as Python globals (only with code string)

Returns:

  • (RubyxObject)

    The awaited result



89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/rubyx.rb', line 89

def self.await(code_or_coroutine, **globals)
  if code_or_coroutine.is_a?(String)
    if globals.empty?
      _await_with_globals(code_or_coroutine, {})
    else
      _await_with_globals(code_or_coroutine, globals)
    end
  else
    raise ArgumentError, "cannot pass globals with a coroutine object" unless globals.empty?
    _await(code_or_coroutine)
  end
end

.import(module_name) ⇒ RubyxObject

Import a Python module by name.

Parameters:

  • module_name (String)

    Python module name (e.g., “os”, “numpy”, “my_module.sub”)

Returns:

  • (RubyxObject)

    Wrapped Python module

Raises:



54
55
56
57
58
59
60
61
62
# File 'lib/rubyx.rb', line 54

def self.import(module_name)
  name = module_name.to_s
  unless name.match?(VALID_MODULE_NAME_PATTERN)
    raise InvalidModuleNameError,
          "Invalid Python module name: '#{name}'. " \
            "Module names must contain only alphanumeric characters, underscores, and dots."
  end
  _import(name)
end

.uv_init(pyproject_toml, **options) ⇒ Hash

Convenience method: setup Python environment via uv and initialize.

Parameters:

  • pyproject_toml (String)

    Content of pyproject.toml

  • options (Hash)

    Options passed to Uv.setup and Uv.init

Returns:

  • (Hash)

    Resolved paths from Uv.init



129
130
131
132
133
134
135
# File 'lib/rubyx.rb', line 129

def self.uv_init(pyproject_toml, **options)
  setup_keys = %i[force uv_version project_dir uv_args uv_path]
  init_keys = %i[uv_version project_dir]

  Uv.setup(pyproject_toml, **options.slice(*setup_keys))
  Uv.init(pyproject_toml, **options.slice(*init_keys))
end