Results for: "OptionParser"

No documentation available
No documentation available

The Specification class contains the information for a gem. Typically defined in a .gemspec file or a Rakefile, and looks like this:

Gem::Specification.new do |s|
  s.name        = 'example'
  s.version     = '0.1.0'
  s.licenses    = ['MIT']
  s.summary     = "This is an example!"
  s.description = "Much longer explanation of the example!"
  s.authors     = ["Ruby Coder"]
  s.email       = 'rubycoder@example.com'
  s.files       = ["lib/example.rb"]
  s.homepage    = 'https://rubygems.org/gems/example'
  s.metadata    = { "source_code_uri" => "https://github.com/example/example" }
end

Starting in RubyGems 2.0, a Specification can hold arbitrary metadata. See metadata for restrictions on the format and size of metadata items you may add to a specification.

No documentation available

Gem::StubSpecification reads the stub: line from the gemspec. This prevents us having to eval the entire gemspec in order to find out certain information.

There are three main phases in the algorithm:

  1. Sanitize/format input source

  2. Search for invalid blocks

  3. Format invalid blocks into something meaningful

The Code frontier is a critical part of the second step

## Knowing where we’ve been

Once a code block is generated it is added onto the frontier. Then it will be sorted by indentation and frontier can be filtered. Large blocks that fully enclose a smaller block will cause the smaller block to be evicted.

CodeFrontier#<<(block) # Adds block to frontier
CodeFrontier#pop # Removes block from frontier

## Knowing where we can go

Internally the frontier keeps track of “unvisited” lines which are exposed via ‘next_indent_line` when called, this method returns, a line of code with the highest indentation.

The returned line of code can be used to build a CodeBlock and then that code block is added back to the frontier. Then, the lines are removed from the “unvisited” so we don’t double-create the same block.

CodeFrontier#next_indent_line # Shows next line
CodeFrontier#register_indent_block(block) # Removes lines from unvisited

## Knowing when to stop

The frontier knows how to check the entire document for a syntax error. When blocks are added onto the frontier, they’re removed from the document. When all code containing syntax errors has been added to the frontier, the document will be parsable without a syntax error and the search can stop.

CodeFrontier#holds_all_syntax_errors? # Returns true when frontier holds all syntax errors

## Filtering false positives

Once the search is completed, the frontier may have multiple blocks that do not contain the syntax error. To limit the result to the smallest subset of “invalid blocks” call:

CodeFrontier#detect_invalid_blocks

Capture parse errors from Ripper

Prism returns the errors with their messages, but Ripper does not. To get them we must make a custom subclass.

Example:

puts RipperErrors.new(" def foo").call.errors
# => ["syntax error, unexpected end-of-input, expecting ';' or '\\n'"]

Encoding conversion class.

Mixin module that provides the following:

  1. Access to the CGI environment variables as methods. See documentation to the CGI class for a list of these variables. The methods are exposed by removing the leading HTTP_ (if it exists) and downcasing the name. For example, auth_type will return the environment variable AUTH_TYPE, and accept will return the value for HTTP_ACCEPT.

  2. Access to cookies, including the cookies attribute.

  3. Access to parameters, including the params attribute, and overloading [] to perform parameter value lookup by key.

  4. The initialize_query method, for initializing the above mechanisms, handling multipart forms, and allowing the class to be used in “offline” mode.

No documentation available

Flags for parameter nodes.

Flags for regular expression and match last line nodes.

The Reflection module provides the ability to reflect on the structure of the syntax tree itself, as opposed to looking at a single syntax tree. This is useful in metaprogramming contexts.

Prism parses deterministically for the same input. This provides a nice property that is exposed through the node_id API on nodes. Effectively this means that for the same input, these values will remain consistent every time the source is parsed. This means we can reparse the source same with a node_id value and find the exact same node again.

The Relocation module provides an API around this property. It allows you to “save” nodes and locations using a minimal amount of memory (just the node_id and a field identifier) and then reify them later.

This module is responsible for converting the prism syntax tree into other syntax trees.

Utility methods for using the RubyGems API.

The WebauthnListener class retrieves an OTP after a user successfully WebAuthns with the Gem host. An instance opens a socket using the TCPServer instance given and listens for a request from the Gem host. The request should be a GET request to the root path and contains the OTP code in the form of a query parameter ‘code`. The listener will return the code which will be used as the OTP for API requests.

Types of responses sent by the listener after receiving a request:

- 200 OK: OTP code was successfully retrieved
- 204 No Content: If the request was an OPTIONS request
- 400 Bad Request: If the request did not contain a query parameter `code`
- 404 Not Found: The request was not to the root path
- 405 Method Not Allowed: OTP code was not retrieved because the request was not a GET/OPTIONS request

Example usage:

thread = Gem::WebauthnListener.listener_thread("https://rubygems.example", server)
thread.join
otp = thread[:otp]
error = thread[:error]

The WebauthnListener Response class is used by the WebauthnListener to create responses to be sent to the Gem host. It creates a Gem::Net::HTTPResponse instance when initialized and can be converted to the appropriate format to be sent by a socket using ‘to_s`. Gem::Net::HTTPResponse instances cannot be directly sent over a socket.

Types of response classes:

- OkResponse
- NoContentResponse
- BadRequestResponse
- NotFoundResponse
- MethodNotAllowedResponse

Example usage:

server = TCPServer.new(0)
socket = server.accept

response = OkResponse.for("https://rubygems.example")
socket.print response.to_s
socket.close

The WebauthnPoller class retrieves an OTP after a user successfully WebAuthns. An instance polls the Gem host for the OTP code. The polling request (api/v1/webauthn_verification/<webauthn_token>/status.json) is sent to the Gem host every 5 seconds and will timeout after 5 minutes. If the status field in the json response is “success”, the code field will contain the OTP code.

Example usage:

thread = Gem::WebauthnPoller.poll_thread(
  {},
  "RubyGems.org",
  "https://rubygems.org/api/v1/webauthn_verification/odow34b93t6aPCdY",
  { email: "email@example.com", password: "password" }
)
thread.join
otp = thread[:otp]
error = thread[:error]

Helper methods for both Gem::Installer and Gem::Uninstaller

Mixin methods for Gem::Command to promote available RubyGems update

A stub yaml serializer that can handle only hashes and strings (as of now).

An Array object is an ordered, integer-indexed collection of objects, called elements; the object represents an array data structure.

An element may be any object (even another array); elements may be any mixture of objects of different types.

Important data structures that use arrays include:

There are also array-like data structures:

Array Indexes

Array indexing starts at 0, as in C or Java.

A non-negative index is an offset from the first element:

A negative index is an offset, backwards, from the end of the array:

In-Range and Out-of-Range Indexes

A non-negative index is in range if and only if it is smaller than the size of the array. For a 3-element array:

A negative index is in range if and only if its absolute value is not larger than the size of the array. For a 3-element array:

Effective Index

Although the effective index into an array is always an integer, some methods (both within class Array and elsewhere) accept one or more non-integer arguments that are integer-convertible objects.

Creating Arrays

You can create an Array object explicitly with:

A number of Ruby methods, both in the core and in the standard library, provide instance method to_a, which converts an object to an array.

Example Usage

In addition to the methods it mixes in through the Enumerable module, the Array class has proprietary methods for accessing, searching and otherwise manipulating arrays.

Some of the more common ones are illustrated below.

Accessing Elements

Elements in an array can be retrieved using the Array#[] method. It can take a single integer argument (a numeric index), a pair of arguments (start and length) or a range. Negative indices start counting from the end, with -1 being the last element.

arr = [1, 2, 3, 4, 5, 6]
arr[2]    #=> 3
arr[100]  #=> nil
arr[-3]   #=> 4
arr[2, 3] #=> [3, 4, 5]
arr[1..4] #=> [2, 3, 4, 5]
arr[1..-3] #=> [2, 3, 4]

Another way to access a particular array element is by using the at method

arr.at(0) #=> 1

The slice method works in an identical manner to Array#[].

To raise an error for indices outside of the array bounds or else to provide a default value when that happens, you can use fetch.

arr = ['a', 'b', 'c', 'd', 'e', 'f']
arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6
arr.fetch(100, "oops") #=> "oops"

The special methods first and last will return the first and last elements of an array, respectively.

arr.first #=> 1
arr.last  #=> 6

To return the first n elements of an array, use take

arr.take(3) #=> [1, 2, 3]

drop does the opposite of take, by returning the elements after n elements have been dropped:

arr.drop(3) #=> [4, 5, 6]

Obtaining Information about an Array

Arrays keep track of their own length at all times. To query an array about the number of elements it contains, use length, count or size.

browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
browsers.length #=> 5
browsers.count #=> 5

To check whether an array contains any elements at all

browsers.empty? #=> false

To check whether a particular item is included in the array

browsers.include?('Konqueror') #=> false

Adding Items to Arrays

Items can be added to the end of an array by using either push or <<

arr = [1, 2, 3, 4]
arr.push(5) #=> [1, 2, 3, 4, 5]
arr << 6    #=> [1, 2, 3, 4, 5, 6]

unshift will add a new item to the beginning of an array.

arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]

With insert you can add a new element to an array at any position.

arr.insert(3, 'apple')  #=> [0, 1, 2, 'apple', 3, 4, 5, 6]

Using the insert method, you can also insert multiple values at once:

arr.insert(3, 'orange', 'pear', 'grapefruit')
#=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]

Removing Items from an Array

The method pop removes the last element in an array and returns it:

arr =  [1, 2, 3, 4, 5, 6]
arr.pop #=> 6
arr #=> [1, 2, 3, 4, 5]

To retrieve and at the same time remove the first item, use shift:

arr.shift #=> 1
arr #=> [2, 3, 4, 5]

To delete an element at a particular index:

arr.delete_at(2) #=> 4
arr #=> [2, 3, 5]

To delete a particular element anywhere in an array, use delete:

arr = [1, 2, 2, 3]
arr.delete(2) #=> 2
arr #=> [1,3]

A useful method if you need to remove nil values from an array is compact:

arr = ['foo', 0, nil, 'bar', 7, 'baz', nil]
arr.compact  #=> ['foo', 0, 'bar', 7, 'baz']
arr          #=> ['foo', 0, nil, 'bar', 7, 'baz', nil]
arr.compact! #=> ['foo', 0, 'bar', 7, 'baz']
arr          #=> ['foo', 0, 'bar', 7, 'baz']

Another common need is to remove duplicate elements from an array.

It has the non-destructive uniq, and destructive method uniq!

arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]

Iterating over Arrays

Like all classes that include the Enumerable module, Array has an each method, which defines what elements should be iterated over and how. In case of Array’s each, all elements in the Array instance are yielded to the supplied block in sequence.

Note that this operation leaves the array unchanged.

arr = [1, 2, 3, 4, 5]
arr.each {|a| print a -= 10, " "}
# prints: -9 -8 -7 -6 -5
#=> [1, 2, 3, 4, 5]

Another sometimes useful iterator is reverse_each which will iterate over the elements in the array in reverse order.

words = %w[first second third fourth fifth sixth]
str = ""
words.reverse_each {|word| str += "#{word} "}
p str #=> "sixth fifth fourth third second first "

The map method can be used to create a new array based on the original array, but with the values modified by the supplied block:

arr.map {|a| 2*a}     #=> [2, 4, 6, 8, 10]
arr                   #=> [1, 2, 3, 4, 5]
arr.map! {|a| a**2}   #=> [1, 4, 9, 16, 25]
arr                   #=> [1, 4, 9, 16, 25]

Selecting Items from an Array

Elements can be selected from an array according to criteria defined in a block. The selection can happen in a destructive or a non-destructive manner. While the destructive operations will modify the array they were called on, the non-destructive methods usually return a new array with the selected elements, but leave the original array unchanged.

Non-destructive Selection

arr = [1, 2, 3, 4, 5, 6]
arr.select {|a| a > 3}       #=> [4, 5, 6]
arr.reject {|a| a < 3}       #=> [3, 4, 5, 6]
arr.drop_while {|a| a < 4}   #=> [4, 5, 6]
arr                          #=> [1, 2, 3, 4, 5, 6]

Destructive Selection

select! and reject! are the corresponding destructive methods to select and reject

Similar to select vs. reject, delete_if and keep_if have the exact opposite result when supplied with the same block:

arr.delete_if {|a| a < 4}   #=> [4, 5, 6]
arr                         #=> [4, 5, 6]

arr = [1, 2, 3, 4, 5, 6]
arr.keep_if {|a| a < 4}   #=> [1, 2, 3]
arr                       #=> [1, 2, 3]

What’s Here

First, what’s elsewhere. Class Array:

Here, class Array provides methods that are useful for:

Methods for Creating an Array

See also Creating Arrays.

Methods for Querying

Methods for Comparing

Methods for Fetching

These methods do not modify self.

Methods for Assigning

These methods add, replace, or reorder elements in self.

Methods for Deleting

Each of these methods removes elements from self:

Methods for Combining

Methods for Iterating

Methods for Converting

Other Methods

An Integer object represents an integer value.

You can create an Integer object explicitly with:

You can convert certain objects to Integers with:

An attempt to add a singleton method to an instance of this class causes an exception to be raised.

What’s Here

First, what’s elsewhere. Class Integer:

Here, class Integer provides methods for:

Querying

Comparing

Converting

Other

Numeric is the class from which all higher-level numeric classes should inherit.

Numeric allows instantiation of heap-allocated objects. Other core numeric classes such as Integer are implemented as immediates, which means that each Integer is a single immutable object which is always passed by value.

a = 1
1.object_id == a.object_id   #=> true

There can only ever be one instance of the integer 1, for example. Ruby ensures this by preventing instantiation. If duplication is attempted, the same instance is returned.

Integer.new(1)                   #=> NoMethodError: undefined method `new' for Integer:Class
1.dup                            #=> 1
1.object_id == 1.dup.object_id   #=> true

For this reason, Numeric should be used when defining other numeric classes.

Classes which inherit from Numeric must implement coerce, which returns a two-member Array containing an object that has been coerced into an instance of the new class and self (see coerce).

Inheriting classes should also implement arithmetic operator methods (+, -, * and /) and the <=> operator (see Comparable). These methods may rely on coerce to ensure interoperability with instances of other numeric classes.

class Tally < Numeric
  def initialize(string)
    @string = string
  end

  def to_s
    @string
  end

  def to_i
    @string.size
  end

  def coerce(other)
    [self.class.new('|' * other.to_i), self]
  end

  def <=>(other)
    to_i <=> other.to_i
  end

  def +(other)
    self.class.new('|' * (to_i + other.to_i))
  end

  def -(other)
    self.class.new('|' * (to_i - other.to_i))
  end

  def *(other)
    self.class.new('|' * (to_i * other.to_i))
  end

  def /(other)
    self.class.new('|' * (to_i / other.to_i))
  end
end

tally = Tally.new('||')
puts tally * 2            #=> "||||"
puts tally > 1            #=> true

What’s Here

First, what’s elsewhere. Class Numeric:

Here, class Numeric provides methods for:

Querying

Comparing

Converting

Other

Fibers are primitives for implementing light weight cooperative concurrency in Ruby. Basically they are a means of creating code blocks that can be paused and resumed, much like threads. The main difference is that they are never preempted and that the scheduling must be done by the programmer and not the VM.

As opposed to other stackless light weight concurrency models, each fiber comes with a stack. This enables the fiber to be paused from deeply nested function calls within the fiber block. See the ruby(1) manpage to configure the size of the fiber stack(s).

When a fiber is created it will not run automatically. Rather it must be explicitly asked to run using the Fiber#resume method. The code running inside the fiber can give up control by calling Fiber.yield in which case it yields control back to caller (the caller of the Fiber#resume).

Upon yielding or termination the Fiber returns the value of the last executed expression

For instance:

fiber = Fiber.new do
  Fiber.yield 1
  2
end

puts fiber.resume
puts fiber.resume
puts fiber.resume

produces

1
2
FiberError: dead fiber called

The Fiber#resume method accepts an arbitrary number of parameters, if it is the first call to resume then they will be passed as block arguments. Otherwise they will be the return value of the call to Fiber.yield

Example:

fiber = Fiber.new do |first|
  second = Fiber.yield first + 2
end

puts fiber.resume 10
puts fiber.resume 1_000_000
puts fiber.resume "The fiber will be dead before I can cause trouble"

produces

12
1000000
FiberError: dead fiber called

Non-blocking Fibers

The concept of non-blocking fiber was introduced in Ruby 3.0. A non-blocking fiber, when reaching a operation that would normally block the fiber (like sleep, or wait for another process or I/O) will yield control to other fibers and allow the scheduler to handle blocking and waking up (resuming) this fiber when it can proceed.

For a Fiber to behave as non-blocking, it need to be created in Fiber.new with blocking: false (which is the default), and Fiber.scheduler should be set with Fiber.set_scheduler. If Fiber.scheduler is not set in the current thread, blocking and non-blocking fibers’ behavior is identical.

Ruby doesn’t provide a scheduler class: it is expected to be implemented by the user and correspond to Fiber::Scheduler.

There is also Fiber.schedule method, which is expected to immediately perform the given block in a non-blocking manner. Its actual implementation is up to the scheduler.

A class which allows both internal and external iteration.

An Enumerator can be created by the following methods.

Most methods have two forms: a block form where the contents are evaluated for each item in the enumeration, and a non-block form which returns a new Enumerator wrapping the iteration.

enumerator = %w(one two three).each
puts enumerator.class # => Enumerator

enumerator.each_with_object("foo") do |item, obj|
  puts "#{obj}: #{item}"
end

# foo: one
# foo: two
# foo: three

enum_with_obj = enumerator.each_with_object("foo")
puts enum_with_obj.class # => Enumerator

enum_with_obj.each do |item, obj|
  puts "#{obj}: #{item}"
end

# foo: one
# foo: two
# foo: three

This allows you to chain Enumerators together. For example, you can map a list’s elements to strings containing the index and the element as a string via:

puts %w[foo bar baz].map.with_index { |w, i| "#{i}:#{w}" }
# => ["0:foo", "1:bar", "2:baz"]

External Iteration

An Enumerator can also be used as an external iterator. For example, Enumerator#next returns the next value of the iterator or raises StopIteration if the Enumerator is at the end.

e = [1,2,3].each   # returns an enumerator object.
puts e.next   # => 1
puts e.next   # => 2
puts e.next   # => 3
puts e.next   # raises StopIteration

next, next_values, peek, and peek_values are the only methods which use external iteration (and Array#zip(Enumerable-not-Array) which uses next internally).

These methods do not affect other internal enumeration methods, unless the underlying iteration method itself has side-effect, e.g. IO#each_line.

FrozenError will be raised if these methods are called against a frozen enumerator. Since rewind and feed also change state for external iteration, these methods may raise FrozenError too.

External iteration differs significantly from internal iteration due to using a Fiber:

Concretely:

Thread.current[:fiber_local] = 1
Fiber[:storage_var] = 1
e = Enumerator.new do |y|
  p Thread.current[:fiber_local] # for external iteration: nil, for internal iteration: 1
  p Fiber[:storage_var] # => 1, inherited
  Fiber[:storage_var] += 1
  y << 42
end

p e.next # => 42
p Fiber[:storage_var] # => 1 (it ran in a different Fiber)

e.each { p _1 }
p Fiber[:storage_var] # => 2 (it ran in the same Fiber/"stack" as the current Fiber)

Convert External Iteration to Internal Iteration

You can use an external iterator to implement an internal iterator as follows:

def ext_each(e)
  while true
    begin
      vs = e.next_values
    rescue StopIteration
      return $!.result
    end
    y = yield(*vs)
    e.feed y
  end
end

o = Object.new

def o.each
  puts yield
  puts yield(1)
  puts yield(1, 2)
  3
end

# use o.each as an internal iterator directly.
puts o.each {|*x| puts x; [:b, *x] }
# => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3

# convert o.each to an external iterator for
# implementing an internal iterator.
puts ext_each(o.to_enum) {|*x| puts x; [:b, *x] }
# => [], [:b], [1], [:b, 1], [1, 2], [:b, 1, 2], 3

Raised when encountering an object that is not of the expected type.

[1, 2, 3].first("two")

raises the exception:

TypeError: no implicit conversion of String into Integer
Search took: 22ms  ·  Total Results: 6041