taipo 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 80a49dd630a757254866642ae69f3fd46f8804ca
4
- data.tar.gz: ac833851465c9174ffecdb1cd0c42e2f149bed75
3
+ metadata.gz: 5583e28b7b31de0e646bbdf2f03f274417946935
4
+ data.tar.gz: 5b9d14b293cabde611addc66b7857c2a16a46929
5
5
  SHA512:
6
- metadata.gz: a89531bc4c8f93e77badf0b3c6ca411c5eaf6bc67dde11816f74de816d6eb394a031c27b3de0d3537ca3567afa4f8215d4ef38d05a1a84654defa38b347b0f7e
7
- data.tar.gz: a18955f94b5744fc33c7739dac871fac1b94424d22f11119f16ee895dd3d7191206e5276eb9cf80df1064fb0b572c8f1126092c7fbcdf329a64198e4ad43c0a3
6
+ metadata.gz: b9c8e5d7fc2d9a419fb91cb82d063e2c4e294ba5b43677546557a133b9e0dbae420c3984f499381ae4e4d54157eb254fa0106720e6e44c2b271bacb34a97e487
7
+ data.tar.gz: 84aee96a5489147d14e7d2ed37ae66dbbbf8f7a6d9e12a365c4fb901160e91d6a58f6bbd6e5d59d03bbe3183b07030215fb5f0c5f74b644f28b88dbcddc3c885
data/README.md CHANGED
@@ -1,7 +1,13 @@
1
+ [![Gem Version](https://badge.fury.io/rb/taipo.svg)](https://badge.fury.io/rb/taipo) [![Inline docs](http://inch-ci.org/github/pyrmont/taipo.svg?branch=master)](http://inch-ci.org/github/pyrmont/taipo)
2
+
1
3
  # Taipo
2
4
 
3
5
  Taipo is a simple library for checking the types of variables.
4
6
 
7
+ [Full documentation][rd] is available at RubyDoc.
8
+
9
+ [rd]: http://www.rubydoc.info/gems/taipo/index
10
+
5
11
  ## Overview
6
12
 
7
13
  When we deal with variables in our code, we have certain expectations about what those variables can and can’t do.
@@ -14,18 +20,18 @@ Run `gem install taipo` or add `gem 'taipo'` to your `Gemfile`.
14
20
 
15
21
  ## Usage
16
22
 
17
- Taipo provides two methods that we can mix into our classes: `#check` and `#review`.
23
+ Taipo provides two methods in the `Taipo::Check` module that we can mix into our classes: `#check` and `#review`.
18
24
 
19
25
  ### #check
20
26
 
21
- ```
27
+ ```ruby
22
28
  require ‘taipo’
23
29
 
24
30
  class Foo
25
31
  include Taipo::Check
26
-
32
+
27
33
  def double(val)
28
- check types, val: ‘Integer’
34
+ check types, val: ‘Integer’
29
35
  val * 2
30
36
  end
31
37
  end
@@ -37,14 +43,18 @@ foo.double ‘Oops’ #=> Taipo::TypeError
37
43
 
38
44
  The method `#check` will raise an exception as soon as one of its arguments doesn’t match its type definition.
39
45
 
46
+ [More information about `#check`][rdc] is available in the documentation.
47
+
48
+ [rdc]: http://www.rubydoc.info/gems/taipo/Taipo/Check#check-instance_method
49
+
40
50
  ### #review
41
51
 
42
- ```
52
+ ```ruby
43
53
  require ‘taipo’
44
54
 
45
55
  class Foo
46
56
  include Taipo::Check
47
-
57
+
48
58
  def add(x, y)
49
59
  errors = review types, x: ‘Integer’, y: ‘Integer’
50
60
  if errors.empty?
@@ -62,26 +72,56 @@ foo.add 2, ‘OK’ #=> ‘Oops’
62
72
 
63
73
  The method `#review` will put the invalid arguments into an array and return that to the user. If there are no errors, the array is empty.
64
74
 
75
+ [More information about `#review`][rdr] is available in the documentation.
76
+
77
+ [rdr]: http://www.rubydoc.info/gems/taipo/Taipo/Check#review-instance_method
78
+
65
79
  ## Syntax
66
80
 
67
- Type definitions are passed as Strings with a straightforward syntax.
81
+ Type definitions are written as Strings. Type definitions can consist of (1) names, (2) collections, (3) constraints and (4) sums.
82
+
83
+ The information in this README is only meant as an introduction. [More information about the type definition syntax][rdv] is available in the documentation.
68
84
 
69
- The simplest case is to write the name of a class. For example, `’String’`. Taipo supports more complex type definitions should you need them. Here are some more examples.
85
+ [rdv]: http://www.rubydoc.info/gems/taipo/Taipo/Parser/Validater
70
86
 
87
+ ### Names
88
+
89
+ The simplest case is to write the name of a class. For example, `’String’`. Inherited class names can also be used.
90
+
91
+ ```ruby
92
+ check types, a: 'String', b: 'Numeric'
71
93
  ```
72
- 'String'
73
- 'Array<String>'
74
- 'Hash<Symbol,String>'
75
- 'String|Float'
76
- 'Boolean|Array<String|Hash<Symbol,Point>|Array<String>>'
77
- 'Array(len: 5)'
78
- 'String(format: /woo/)'
79
- 'String(#size)'
80
- 'String(#size, #to_s)'
81
- 'Integer(min: 1, max: 10)'
82
- 'String(val: "This is a test.")'
83
- '#to_s'
84
- '#to_s|#to_i'
94
+
95
+ #### Duck Types
96
+
97
+ It's possible to specify a duck type by writing the instance method (or methods) to which the object should respond.
98
+
99
+ ```ruby
100
+ check types, a: '#to_s', b: '(#foo, #bar)'
101
+ ```
102
+
103
+ ### Collections
104
+
105
+ Taipo can also check whether a variable has a collection of elements of the specified child type. A child type can consist of the same components as any other type (ie. a name, collection, constraint, sum).
106
+
107
+ ```ruby
108
+ check types, a: 'Array<Integer>', b: 'Hash<Symbol, String>', c: 'Array<Array<Float>>'
109
+ ```
110
+
111
+ ### Constraints
112
+
113
+ Constraints can be added to a type definition. Constraints consist of a list of one or more identifier-value pairs. Instance method names can also be in included.
114
+
115
+ ```ruby
116
+ check types, a: 'Array(len: 5)', b: 'Integer(min: 0, max: 10)', c: 'String(format: /a{3}/)', d: 'String(val: "Hello world!")', e: 'Foo(#bar)'
117
+ ```
118
+
119
+ ### Sums
120
+
121
+ Type definitions can be combined to form sum types. Sum types consist of two or more type definitions.
122
+
123
+ ```ruby
124
+ check types, a: 'String|Float', b: 'Boolean|Array<String|Hash<Symbol,Point>|Array<String>>', c: 'Integer(max: 100)|Float(max: 100)'
85
125
  ```
86
126
 
87
127
  ## Requirements
@@ -90,21 +130,25 @@ Taipo has been tested with Ruby version 2.4.2.
90
130
 
91
131
  ## Bugs
92
132
 
93
- Found a bug? I’d love to know about it. The best way is to report them on GitHub.
133
+ Found a bug? I’d love to know about it. The best way is to report them in the [Issues section][ghi] on GitHub.
134
+
135
+ [ghi]: https://github.com/pyrmont/taipo/issues
94
136
 
95
- ## Contributions
137
+ ## Contributing
96
138
 
97
139
  If you’re interested in contributing to Taipo, feel free to fork and submit a pull request.
98
140
 
99
141
  ## Colophon
100
142
 
101
- Taipo began as an exercise to improve my programming skills. If you want something more comprehensive, consider some of the other options, such as [Contracts][1], [Rtype][2], [Rubype][3] or [Sig][4].
143
+ Taipo began as, and remains primarily, an exercise to improve my programming skills. If Taipo has piqued your interest in adding type checks to Ruby, consider some of the other options, such as [Contracts][cnt], [Rtype][rty], [Rubype][rub] or [Sig][sig].
144
+
145
+ [cnt]: https://github.com/egonSchiele/contracts.ruby
146
+ [rty]: https://github.com/sputnikgugja/rtype
147
+ [rub]: https://github.com/gogotanaka/Rubype
148
+ [sig]: https://github.com/janlelis/sig
102
149
 
103
- [1]: https://github.com/egonSchiele/contracts.ruby
104
- [2]: https://github.com/sputnikgugja/rtype
105
- [3]: https://github.com/gogotanaka/Rubype
106
- [4]: https://github.com/janlelis/sig
150
+ ## Licence
107
151
 
108
- # Licence
152
+ Taipo is released into the public domain. See [LICENSE.md][lc] for more details.
109
153
 
110
- Taipo is released into the public domain. See LICENSE.md for more details.
154
+ [lc]: https://github.com/pyrmont/taipo/blob/master/LICENSE.md
@@ -3,8 +3,95 @@ require 'taipo/parser/syntax_state'
3
3
 
4
4
  module Taipo
5
5
  module Parser
6
-
6
+
7
7
  # A validater of Taipo type definitions
8
+ #
9
+ # Taipo's type definition syntax has four components: (1) names; (2)
10
+ # collections; (3) constraints; and (4) sums.
11
+ #
12
+ # === Names
13
+ #
14
+ # 'String', 'Numeric'
15
+ #
16
+ # A name should be the name of a class or a module.
17
+ #
18
+ # The validater does not check whether the name represents a valid name in
19
+ # the current context nor does it check whether the name complies with
20
+ # Ruby's requirements for names. Either situation will cause an exception
21
+ # to be raised by {Taipo::Check#check} or {Taipo::Check#review}.
22
+ #
23
+ # One special case is where the name is left blank. The validater will
24
+ # accept this as valid. {Taipo::Parser} will implictly add the name
25
+ # 'Object' when parsing the type definition. This allows a clean syntax for
26
+ # duck types (which are really constraints on the class Object).
27
+ #
28
+ # === Collections
29
+ #
30
+ # 'Array<Integer>', 'Hash<Symbol, String>', 'Array<Array<Float>>'
31
+ #
32
+ # A collection should be the type definiton for elements returned by
33
+ # +Enumerator#each+ (the child type) called on the collecting object (the
34
+ # parent type).
35
+ #
36
+ # A collection is demarcated by the angle brackets +<+ and +>+. These come
37
+ # immediately after the name of the parent (ie. without a space). The type
38
+ # definition for the child comes immediately after the opening angle
39
+ # bracket.
40
+ #
41
+ # If +Enumerator#each+ returns multiple values (eg. such as with Hash), the
42
+ # type definition for each value is delimited by a comma. It is optional
43
+ # whether a space follows the comma.
44
+ #
45
+ # The type definition for a child element can contain all the components of
46
+ # a type definition (ie. name, collection, constraint, sum) allowing for
47
+ # collections that contain collections and so on.
48
+ #
49
+ # === Constraints
50
+ #
51
+ # 'Array(len: 5)', 'Integer(min: 0, max: 10)', 'String(format: /a{3}/)',
52
+ # 'String(val: "Hello world!")', 'Foo(#bar)'
53
+ #
54
+ # A constraint should be a list of identifiers and values.
55
+ #
56
+ # A constraint is demarcated by parentheses (ie. +(+ and +)+). These come
57
+ # immediately after the name or collection (ie. without a space). The first
58
+ # identifier comes immediately after the opening parenthesis.
59
+ #
60
+ # An identifier and a value are separated by a colon (and an optional
61
+ # space). Multiple identifier-value pairs are delimited by a comma. It is
62
+ # optional whether a space follows the comma.
63
+ #
64
+ # The permitted identifiers and their values are as follows:
65
+ # - +format+: takes a regular expression demarcated by +/+
66
+ # - +len+: takes an integer
67
+ # - +max+: takes an integer
68
+ # - +min+: takes an integer
69
+ # - +val+: takes a number or a string demarcated by +"+
70
+ #
71
+ # The validater does not check whether the identifiers and values are
72
+ # acceptable, merely that they conform to the grammar.
73
+ # {Taipo::Parser.parse} will raise an exception when it parses the
74
+ # definition if the values are not acceptable for the relevant identifier.
75
+ # Similarly, while the repetition of an identifier is technically invalid,
76
+ # the exception will not be raised until {Taipo::Parser.parse} is called.
77
+ #
78
+ # One special case is where the identifier begins with a +#+. For this
79
+ # identifier, no value is provided and the constraint instead results in
80
+ # {Taipo::Check#check} and {Taipo::Check#review} checking whether the
81
+ # given object returns true for +Object#respond_to?+ with the identifier as
82
+ # the symbol.
83
+ #
84
+ # === Sums
85
+ #
86
+ # 'String|Float',
87
+ # 'Boolean|Array<String|Hash<Symbol,Point>|Array<String>>',
88
+ # 'Integer(max: 100)|Float(max: 100)'
89
+ #
90
+ # A sum is a combination of two or more type definitions.
91
+ #
92
+ # The sum comprises two or more type definitions, each separated by a bar
93
+ # (ie. +|+).
94
+ #
8
95
  # @since 1.0.0
9
96
  module Validater
10
97
 
@@ -12,8 +99,10 @@ module Taipo
12
99
  #
13
100
  # @param str [String] a type definition
14
101
  #
102
+ # @return [NilClass]
103
+ #
15
104
  # @raise [::TypeError] if +str+ is not a String
16
- # @raise [Taipo::SyntaxError] if +str+ is not a valid type definition
105
+ # @raise [Taipo::SyntaxError] if +str+ is not a valid type definition
17
106
  #
18
107
  # @since 1.0.0
19
108
  def self.validate(str)
@@ -72,7 +72,7 @@ module Taipo
72
72
  end
73
73
  when 'min'
74
74
  if arg.is_a? Numeric
75
- arg <= @value
75
+ arg >= @value
76
76
  else
77
77
  arg.respond_to?('size') && arg.size >= @value
78
78
  end
data/lib/taipo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Taipo
2
- VERSION = "1.0.0"
2
+ VERSION = "1.0.1"
3
3
  end
data/lib/taipo.rb CHANGED
@@ -3,14 +3,30 @@ require 'taipo/check'
3
3
  require 'taipo/parser'
4
4
 
5
5
  # A library for checking the types of objects
6
- #
6
+ #
7
+ # Taipo is primarily intended as a replacement for cumbersome, error-prone
8
+ # guard statements a user can put in their code to ensure that the variables
9
+ # they are handling conform to expectations.
10
+ #
11
+ # By including the module {Taipo::Check}, a user can call the
12
+ # {Taipo::Check#check} or {Taipo::Check#review} methods in their classes
13
+ # whenever a guard statement is necessary. Expectations are written as type
14
+ # definitions that can specify the type of the variable (including sum types)
15
+ # and the types of any elements it contains, all subject to a given constraints
16
+ # (see {Taipo::Parser::Validater} for the full syntax).
17
+ #
18
+ # As syntactic sugar, the {Taipo::Check} module also aliases +Kernel#binding+
19
+ # with the keyword +types+. This allows the user to call {Taipo::Check#check}
20
+ # and {Taipo::Check#review} by writing +check types, ...+ and
21
+ # +review types, ...+ respectively.
22
+ #
7
23
  # @since 1.0.0
8
- # @see https://github.com/pyrmont/shakushi
24
+ # @see https://github.com/pyrmont/taipo
9
25
  module Taipo
10
26
 
11
27
  # Check if a string is the name of an instance method
12
28
  #
13
- # @note All this does is check whether the given string begins with a hash
29
+ # @note All this does is check whether the given string begins with a hash
14
30
  # symbol.
15
31
  #
16
32
  # @param str [String] the method name to check
data/taipo.gemspec CHANGED
@@ -12,9 +12,11 @@ Gem::Specification.new do |spec|
12
12
  spec.summary = %q{A simple library for checking the types of variables.}
13
13
  spec.description = %q{Taipo provides a simple way to check your variables are what you think they are. With an easy to use syntax you can call a single method and pass expressive type definitions.}
14
14
  spec.homepage = "https://github.com/pyrmont/taipo/"
15
+ spec.license = "Unlicense"
15
16
 
16
17
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
18
  spec.require_paths = ["lib"]
19
+ spec.required_ruby_version = '>= 2.4.0'
18
20
 
19
21
  spec.metadata['allowed_push_host'] = 'https://rubygems.org'
20
22
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taipo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Camilleri
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-18 00:00:00.000000000 Z
11
+ date: 2018-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -124,7 +124,8 @@ files:
124
124
  - lib/taipo/version.rb
125
125
  - taipo.gemspec
126
126
  homepage: https://github.com/pyrmont/taipo/
127
- licenses: []
127
+ licenses:
128
+ - Unlicense
128
129
  metadata:
129
130
  allowed_push_host: https://rubygems.org
130
131
  post_install_message:
@@ -135,7 +136,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
135
136
  requirements:
136
137
  - - ">="
137
138
  - !ruby/object:Gem::Version
138
- version: '0'
139
+ version: 2.4.0
139
140
  required_rubygems_version: !ruby/object:Gem::Requirement
140
141
  requirements:
141
142
  - - ">="