| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
parent directory.. | ||||
While our monorepo is predominantly geared toward Ruby on Rails, we have the ability to run Python code from Rails. This is enabled by pycall.rb, and allows us to take advantage of Python's great package ecosystem. More information is available in the initial pycall PR.
For package management and virtual env we use uv, see section on using uv below.
While we hope to fix this in the future, PyCall is not thread-safe, and cannot be invoked from Rails web requests. Invoking PyCall from a Rails controller request will cause an instant SEGV crash of the Rails process.
This means, at present, PyCall should be used from ActiveJob workers.
uv uses pyproject.toml to create a python virtualenv, and install and manage its dependencies. Its similar to bundle from the Ruby world, or yarn/npm from the Node world, and includes many of the same features.
Common commands:
Importing a python module and calling it:
pyimport 'math'
puts "Python says the square root of 25 is: #{math.sqrt(25)}"
pyfrom 'math', import: :sqrt
puts "Python says the square root of 100 is: #{sqrt(100)}"
pyimport 'math', as: :numberstuff
puts "Python says the square root of 9 is: #{numberstuff.sqrt(9)}
# or to use a lower-level method, you could do:
yo = PyCall.import_module 'math'
puts "Python says the square root of 16 is: #{yo.sqrt(16)}
Importing /python/pycdo/pycdo/test_module/test_func.py in ruby:
pyfrom 'pycdo.test_module`, import: :test_func puts test_func() # => "Ruby can call Python1"
Accessing python's builtin methods like dir() and help():
pyfrom :builtins, import: [:dir, :help] help(math) dir(math)
You have two basic options:
Once you've added your python code either of these two ways, you can call it from Ruby tests, or from Rails models and controller methods.
Adding a new file or module to the pycdo package is a great way to support smaller features that will only be one or a few files of python.
def testmefunc():
print("testme() called")
return "testme"
pyfrom 'pycdo', import: :myfeature myfeature.testmefunc()
We showed adding a single-file module, but you can of course also create a new sub-directory like /python/pycdo/myfeature/__init__.py.
Creating a new python package under /python is a great way to add larger features. This will permit you to specify your own dependencies, and have your own test setup. You'll be able to test and run your package in its own virtualenv, as well as in the repo-wide virtualenv.
Create a new sub-dir under /python for your package, e.g. /python/myfeature
Create a /python/newfeature/pyproject.toml for your package
Create a module sub-directory inside your package: /python/myfeature/myfeature
def testmefunc():
print("testme() called")
return "testme"
Try out your module from inside it's directory (e.g. from /python/myfeature) run:
Modify the toplevel /pyproject.toml's dependencies section to point to your new package:
dependencies = [
"myfeature",
...
[tool.uv.sources]
myfeature = { workspace = true }
...
[tool.uv.workspace]
members = [
'python/myfeature',
Now try out your package from the project repo directory (i.e. from code-dot-org/) run:
uv sync
uv run python3 -c 'import myfeature; print(myfeature.testmefunc)'
Now you're ready to try our code from Ruby:
bin/dashboard-console:
pyimport 'myfeature' myfeature.testmefunc()
NOTE: when adding python dependencies, please prefer '>=' version matches to '==' matches. The lockfile will ensure that version numbers are kept constant, and using '>=' will make it much easier to do package version upgrades repo-wide.
Python packages should be testable by running uv run pytest from the package's main directory.
Most likely you want to configure your project to use pytest on the tests/ sub-dir by configuring pyproject.toml like:
[tool.pytest.ini_options] testpaths = ['tests']
Our CI system will automatically run uv run pytest against every directory that contains a pyproject.toml.
All .py files in python/ will be automatically linted using Ruff, both at commit and in CI.
| Back | FazBrowse Home | New Git URL |