
Security News
Astral Launches pyx: A Python-Native Package Registry
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
[!IMPORTANT] This is a fork of the Steep gem. This fork exists primarily to support a legacy system that needs more permissive (relaxed) version constraints for selected runtime dependencies.
Install via RubyGems.
$ gem install steep
Steep requires Ruby 2.6 or later.
Steep does not infer types from Ruby programs, but requires declaring types and writing annotations. You have to go on the following three steps.
steep init
Run steep init
to generate a configuration file.
$ steep init # Generates Steepfile
Edit the Steepfile
:
target :app do
check "lib"
signature "sig"
library "pathname"
end
Declare types in .rbs
files in sig
directory.
class Person
@name: String
@contacts: Array[Email | Phone]
def initialize: (name: String) -> untyped
def name: -> String
def contacts: -> Array[Email | Phone]
def guess_country: -> (String | nil)
end
class Email
@address: String
def initialize: (address: String) -> untyped
def address: -> String
end
class Phone
@country: String
@number: String
def initialize: (country: String, number: String) -> untyped
def country: -> String
def number: -> String
def self.countries: -> Hash[String, String]
end
Hash[String, String]
.Email | Phone
.self.countries
.nil
type to represent nullable types.Write Ruby code with annotations.
class Person
# `@dynamic` annotation is to tell steep that
# the `name` and `contacts` methods are defined without def syntax.
# (Steep can skip checking if the methods are implemented.)
# @dynamic name, contacts
attr_reader :name
attr_reader :contacts
def initialize(name:)
@name = name
@contacts = []
end
def guess_country()
contacts.map do |contact|
# With case expression, simple type-case is implemented.
# `contact` has type of `Phone | Email` but in the `when` clause, contact has type of `Phone`.
case contact
when Phone
contact.country
end
end.compact.first
end
end
class Email
# @dynamic address
attr_reader :address
def initialize(address:)
@address = address
end
def ==(other)
# `other` has type of `untyped`, which means type checking is skipped.
# No type errors can be detected in this method.
other.is_a?(self.class) && other.address == address
end
def hash
[self.class, address].hash
end
end
class Phone
# @dynamic country, number
attr_reader :country, :number
def initialize(country:, number:)
@country = country
@number = number
end
def ==(other)
# You cannot use `case` for type case because `other` has type of `untyped`, not a union type.
# You have to explicitly declare the type of `other` in `if` expression.
if other.is_a?(Phone)
# @type var other: Phone
other.country == country && other.number == number
end
end
def hash
[self.class, country, number].hash
end
end
Run steep check
command to type check. 💡
$ steep check
lib/phone.rb:46:0: MethodDefinitionMissing: module=::Phone, method=self.countries (class Phone)
You now find Phone.countries
method is not implemented yet. 🙃
You can use rbs prototype
command to generate a signature declaration.
$ rbs prototype rb lib/person.rb lib/email.rb lib/phone.rb
class Person
@name: untyped
@contacts: Array[untyped]
def initialize: (name: untyped) -> Array[untyped]
def guess_country: () -> untyped
end
class Email
@address: untyped
def initialize: (address: untyped) -> untyped
def ==: (untyped) -> untyped
def hash: () -> untyped
end
class Phone
@country: untyped
@number: untyped
def initialize: (country: untyped, number: untyped) -> untyped
def ==: (untyped) -> void
def hash: () -> untyped
end
It prints all methods, classes, instance variables, and constants. It can be a good starting point to writing signatures.
Because it just prints all def
s, you may find some odd points:
initialize
in Person
looks strange.attr_reader
methods extracted.Generally, these are by our design.
rbs prototype
offers options: rbi
to generate prototype from Sorbet RBI and runtime
to generate from runtime API.
There are some documents in the manul
and guide
directories.
The doc
directory contains a few internal design docs.
You can find examples in smoke
directory.
Steep implements some of the Language Server Protocol features.
let g:ale_ruby_steep_executable = 'bundle'
to use your bundled steep
version.Other LSP supporting tools may work with Steep where it starts the server as steep langserver
.
Steep comes with a set of configurable Rake tasks.
# Rakefile
require "steep/rake_task"
Steep::RakeTask.new do |t|
t.check.severity_level = :error
t.watch.verbose
end
task default: [:steep]
Use bundle exec rake -T
to see all available tasks.
After checking out the repo, run bin/setup
to install dependencies. Then, run rake test
to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/soutaro/steep.
FAQs
Unknown package
We found that steep-relaxed demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Astral unveils pyx, a Python-native package registry in beta, designed to speed installs, enhance security, and integrate deeply with uv.
Security News
The Latio podcast explores how static and runtime reachability help teams prioritize exploitable vulnerabilities and streamline AppSec workflows.
Security News
The latest Opengrep releases add Apex scanning, precision rule tuning, and performance gains for open source static code analysis.