dandy 1.0.3 → 2.0.0.pre.alpha

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
  SHA256:
3
- metadata.gz: 10c1d06be946e67fdc9c9e2dd27e37015aa5c315006f153364f6a729eecadc8c
4
- data.tar.gz: eb3055e8a23b44e78661f7ae89896bb96748fb71bb2dbd9122f5f9f6a4271a94
3
+ metadata.gz: f0a2a55e97bb758be7b7fd22226adc5757a7ad94fc48596448d0b10447e85abe
4
+ data.tar.gz: 232468091c7e5dca9f15a28b54dedc298003f24a0acc116f85ea79f64f83db09
5
5
  SHA512:
6
- metadata.gz: 40389e9152244e5949e539d18caa4fd35604286721d327543bc2e20765d078e4888f2da0225bd052f54ec0e817e4cef7b50b5cf1092afdd09e5aed9364da66e3
7
- data.tar.gz: d6966b353e974d10a755677b84a1a5943a59cf2335eeec2a396203df118a03161fec03bd7f72b63a83467595d92ab019aac30c1d82412a9b5017e553bd8e43ae
6
+ metadata.gz: a090b89c227d4acd9b2d4fcd2527a649acd147d60b23aee1ebef93c3eec4659311a1204487e304e04a02a7c2abd489b5800c7c6a0522ba63cbd893ccdac24bdd
7
+ data.tar.gz: dca5768ae6c078c5f1cc5f529489ac43d856b169b49617dfacab1df649779a60a2f8a36d4eaeff20ff862443124e204d7d0d12e5fd49328a211d2c29140e93f1
data/lib/dandy.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'dandy/version'
2
2
  require 'dandy/app'
3
+ require 'dandy/consumer'
3
4
  require 'dandy/base/handle_errors'
4
5
 
5
6
  module Dandy
data/lib/dandy/app.rb CHANGED
@@ -11,7 +11,8 @@ require 'dandy/view_builder_registry'
11
11
  require 'dandy/view_factory'
12
12
  require 'dandy/view_builders/json'
13
13
  require 'dandy/routing/routing'
14
- require 'dandy/safe_executor'
14
+ require 'dandy/route_executor'
15
+ require 'dandy/handler_executor'
15
16
 
16
17
  module Dandy
17
18
  class App
@@ -22,12 +23,12 @@ module Dandy
22
23
 
23
24
  register_dependencies
24
25
  load_basic_dependencies
25
- parse_routes
26
+ parse_entrypoints
26
27
  add_view_builders
27
28
  end
28
29
 
29
30
  def call(env)
30
- request = Request.new(@route_matcher, @container, @safe_executor)
31
+ request = Request.new(@route_matcher, @container, @route_executor)
31
32
  request.handle(env)
32
33
  end
33
34
 
@@ -37,6 +38,10 @@ module Dandy
37
38
  @view_builder_registry.add(view_builder, format)
38
39
  end
39
40
 
41
+ def add_consumer(consumer)
42
+ consumer.connect(@message_handlers, @handler_executor)
43
+ end
44
+
40
45
  private
41
46
 
42
47
  def add_view_builders
@@ -65,9 +70,11 @@ module Dandy
65
70
  file_reader: Routing::FileReader,
66
71
  syntax_parser: SyntaxParser,
67
72
  syntax_error_interpreter: Routing::SyntaxErrorInterpreter,
68
- routes_builder: Routing::Builder,
69
- route_parser: Routing::Parser,
70
- safe_executor: SafeExecutor
73
+ routes_builder: Routing::RoutesBuilder,
74
+ handlers_builder: Routing::HandlersBuilder,
75
+ dandy_parser: Routing::Parser,
76
+ route_executor: RouteExecutor,
77
+ handler_executor: HandlerExecutor
71
78
  }
72
79
 
73
80
  singletons.keys.each do |name|
@@ -81,14 +88,17 @@ module Dandy
81
88
  @view_factory = @container.resolve(:view_factory)
82
89
  @dependency_loader = @container.resolve(:dependency_loader)
83
90
  @view_builder_registry = @container.resolve(:view_builder_registry)
84
- @route_parser = @container.resolve(:route_parser)
85
- @safe_executor = @container.resolve(:safe_executor)
91
+ @dandy_parser = @container.resolve(:dandy_parser)
92
+ @route_executor = @container.resolve(:route_executor)
93
+ @handler_executor = @container.resolve(:handler_executor)
86
94
 
87
95
  @dependency_loader.load_components
88
96
  end
89
97
 
90
- def parse_routes
91
- @routes = @route_parser.parse
98
+ def parse_entrypoints
99
+ entrypoints = @dandy_parser.parse
100
+ @routes = entrypoints[:routes]
101
+ @message_handlers = entrypoints[:message_handlers]
92
102
  @route_matcher = Routing::Matcher.new(@routes)
93
103
  end
94
104
  end
data/lib/dandy/chain.rb CHANGED
@@ -7,7 +7,7 @@ module Dandy
7
7
  @async_timeout = dandy_config[:action][:async_timeout]
8
8
  end
9
9
 
10
- def run_commands(commands, last_command)
10
+ def run_commands(commands, last_command, scope)
11
11
  threads = []
12
12
  Thread.abort_on_exception = true
13
13
 
@@ -19,17 +19,17 @@ module Dandy
19
19
  threads = []
20
20
 
21
21
  if last_command && (command.name == last_command.name)
22
- result = run_command(command)
22
+ result = run_command(command, scope)
23
23
  else
24
- run_command(command)
24
+ run_command(command, scope)
25
25
  end
26
26
  else
27
27
  thread = Thread.new {
28
28
  Timeout::timeout(@async_timeout) {
29
29
  if last_command && (command.name == last_command.name)
30
- result = run_command(command)
30
+ result = run_command(command, scope)
31
31
  else
32
- run_command(command)
32
+ run_command(command, scope)
33
33
  end
34
34
  }
35
35
  }
@@ -47,7 +47,7 @@ module Dandy
47
47
 
48
48
  private
49
49
 
50
- def run_command(command)
50
+ def run_command(command, scope)
51
51
  if command.entity?
52
52
  entity = @container.resolve(command.entity_name.to_sym)
53
53
  method_name = command.entity_method.to_sym
@@ -65,7 +65,7 @@ module Dandy
65
65
  @container
66
66
  .register_instance(result, command.result_name.to_sym)
67
67
  .using_lifetime(:scope)
68
- .bound_to(:dandy_request)
68
+ .bound_to(scope)
69
69
 
70
70
  result
71
71
  end
@@ -0,0 +1,32 @@
1
+ require 'dandy/message'
2
+
3
+ module Dandy
4
+ class Consumer
5
+ def initialize(container)
6
+ @container = container
7
+ end
8
+
9
+ def connect(message_handlers, handler_executor)
10
+ @message_handlers = {}
11
+ @handler_executor = handler_executor
12
+
13
+ message_handlers.each do |handler|
14
+ @message_handlers[handler.name] = handler
15
+ end
16
+
17
+ subscribe
18
+ end
19
+
20
+ def subscribe
21
+ raise DandyError, 'Method subscribe is not implemented in your consumer'
22
+ end
23
+
24
+ def handle(message_name, payload)
25
+ if @message_handlers.key? message_name
26
+ handler = @message_handlers[message_name]
27
+ message = Message.new(@container, handler, @handler_executor)
28
+ message.handle(payload)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -2,7 +2,7 @@ path:
2
2
  dependencies:
3
3
  - app/actions
4
4
  views: app/views
5
- routes: app/app.routes
5
+ routes: app/app.dandy
6
6
  action:
7
7
  async_timeout: 10 # in seconds
8
8
  db:
@@ -0,0 +1,28 @@
1
+ module Dandy
2
+ class HandlerExecutor
3
+ def initialize(container, dandy_config)
4
+ @container = container
5
+ @dandy_config = dandy_config
6
+ end
7
+
8
+ def execute(message_handler)
9
+ chain = Chain.new(@container, @dandy_config)
10
+
11
+ begin
12
+ chain.run_commands(message_handler.commands, message_handler.last_command, :dandy_message)
13
+ rescue Exception => error
14
+ handle_error(message_handler, error)
15
+ end
16
+ end
17
+
18
+ def handle_error(message_handler, error)
19
+ @container
20
+ .register_instance(error, :dandy_error)
21
+ .using_lifetime(:scope)
22
+ .bound_to(:dandy_message)
23
+
24
+ command = @container.resolve(message_handler.catch.name.to_sym)
25
+ command.call
26
+ end
27
+ end
28
+ end
@@ -7,14 +7,16 @@ module Dandy
7
7
  @dandy_env = dandy_env
8
8
  end
9
9
 
10
- def load_components
10
+ def load_components(scope = :dandy_request)
11
11
  if @dandy_env == 'development'
12
12
  # every time reload types in development mode
13
13
  @types = @type_loader.load_types
14
14
  end
15
15
 
16
16
  @types.each do |type|
17
- @container.register(type[:class], type[:path].to_sym).using_lifetime(:scope).bound_to(:dandy_request)
17
+ @container.register(type[:class], type[:path].to_sym)
18
+ .using_lifetime(:scope)
19
+ .bound_to(scope)
18
20
  end
19
21
  end
20
22
  end
@@ -0,0 +1,50 @@
1
+ require 'json'
2
+ require 'awrence'
3
+ require 'plissken'
4
+ require 'rack/multipart'
5
+ require 'dandy/extensions/hash'
6
+ require 'dandy/view_factory'
7
+ require 'dandy/chain'
8
+
9
+ module Dandy
10
+ class Message
11
+ include Hypo::Scope
12
+
13
+ def initialize(container, handler, handler_executor)
14
+ @container = container
15
+ @handler = handler
16
+ @handler_executor = handler_executor
17
+ end
18
+
19
+ def handle(data)
20
+ create_scope
21
+ register_data(data)
22
+
23
+ begin
24
+ result = @handler_executor.execute(@handler)
25
+ release
26
+ rescue Exception => error
27
+ result = @handler_executor.handle_error(@handler, error)
28
+ end
29
+
30
+ result
31
+ end
32
+
33
+ private
34
+
35
+ def create_scope
36
+ @container
37
+ .register_instance(self, :dandy_message)
38
+ .using_lifetime(:scope)
39
+ .bound_to(self)
40
+ end
41
+
42
+ def register_data(data)
43
+ unless data.nil?
44
+ @container.register_instance(data, :dandy_data)
45
+ .using_lifetime(:scope)
46
+ .bound_to(:dandy_message)
47
+ end
48
+ end
49
+ end
50
+ end
data/lib/dandy/request.rb CHANGED
@@ -10,10 +10,10 @@ module Dandy
10
10
  class Request
11
11
  include Hypo::Scope
12
12
 
13
- def initialize(route_matcher, container, safe_executor)
13
+ def initialize(route_matcher, container, route_executor)
14
14
  @container = container
15
15
  @route_matcher = route_matcher
16
- @safe_executor = safe_executor
16
+ @route_executor = route_executor
17
17
  end
18
18
 
19
19
  def handle(rack_env)
@@ -49,12 +49,11 @@ module Dandy
49
49
  multipart = Rack::Multipart.parse_multipart(rack_env) || {}
50
50
  register_context(multipart.values, :dandy_files)
51
51
 
52
- body = @safe_executor.execute(match.route, headers)
53
-
54
52
  begin
53
+ body = @route_executor.execute(match.route, headers)
55
54
  release
56
55
  rescue Exception => error
57
- body = @safe_executor.handle_error(match.route, headers, error)
56
+ body = @route_executor.handle_error(match.route, headers, error)
58
57
  end
59
58
 
60
59
  status = @container.resolve(:dandy_status)
@@ -1,7 +1,7 @@
1
1
  require 'dandy/response'
2
2
 
3
3
  module Dandy
4
- class SafeExecutor
4
+ class RouteExecutor
5
5
  def initialize(container, dandy_config, view_factory)
6
6
  @container = container
7
7
  @dandy_config = dandy_config
@@ -12,7 +12,7 @@ module Dandy
12
12
  chain = Chain.new(@container, @dandy_config)
13
13
 
14
14
  begin
15
- result = chain.run_commands(route.commands, route.last_command)
15
+ result = chain.run_commands(route.commands, route.last_command, :dandy_request)
16
16
  if route.view
17
17
  result = @view_factory.create(route.view, headers['Accept'], {keys_format: headers['Keys-Format'] || 'snake'})
18
18
  end
@@ -0,0 +1,25 @@
1
+ require 'dandy/routing/message_handler'
2
+
3
+ module Dandy
4
+ module Routing
5
+ class HandlersBuilder
6
+ def initialize
7
+ @parsed_items = []
8
+ @route_params = []
9
+ @current_parent = nil
10
+ @prev_route = nil
11
+ end
12
+
13
+ def build(section)
14
+ section.messages.map do |message|
15
+ MessageHandler.new({
16
+ name: message.name,
17
+ catch: section.catch.command,
18
+ last_command: message.command_list.last,
19
+ commands: section.before_commands + message.command_list + section.after_commands
20
+ })
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,15 @@
1
+ module Dandy
2
+ module Routing
3
+ class MessageHandler
4
+ attr_reader :name, :params, :catch,
5
+ :commands, :last_command
6
+
7
+ def initialize(hash)
8
+ @name = hash[:name]
9
+ @commands = hash[:commands]
10
+ @last_command = hash[:last_command]
11
+ @catch = hash[:catch]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,10 +1,11 @@
1
1
  module Dandy
2
2
  module Routing
3
3
  class Parser
4
- def initialize(file_reader, routes_builder,
4
+ def initialize(file_reader, routes_builder, handlers_builder,
5
5
  syntax_parser, syntax_error_interpreter)
6
6
  @file_reader = file_reader
7
7
  @routes_builder = routes_builder
8
+ @handlers_builder = handlers_builder
8
9
  @syntax_parser = syntax_parser
9
10
  @syntax_error_interpreter = syntax_error_interpreter
10
11
  end
@@ -18,7 +19,18 @@ module Dandy
18
19
  raise Dandy::SyntaxError, error_message
19
20
  end
20
21
 
21
- @routes_builder.build(tree.parse)
22
+ dandy = tree.parse
23
+
24
+ result = {}
25
+ if dandy.requests
26
+ result[:routes] = @routes_builder.build(dandy.requests)
27
+ end
28
+
29
+ if dandy.messages
30
+ result[:message_handlers] = @handlers_builder.build(dandy.messages)
31
+ end
32
+
33
+ result
22
34
  end
23
35
  end
24
36
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Dandy
4
4
  module Routing
5
- class Builder
5
+ class RoutesBuilder
6
6
  def initialize
7
7
  @parsed_items = []
8
8
  @route_params = []
@@ -10,10 +10,10 @@ module Dandy
10
10
  @prev_route = nil
11
11
  end
12
12
 
13
- def build(sections)
13
+ def build(requests)
14
14
  result = []
15
15
 
16
- node = sections.node
16
+ node = requests.node
17
17
  restore_hierarchy(node, nil, node.to_hash)
18
18
 
19
19
  @route_params.each do |route|
@@ -25,7 +25,7 @@ module Dandy
25
25
  http_verb: action[:http_verb],
26
26
  view: action[:view],
27
27
  http_status: action[:http_status],
28
- catch: sections.catch.command,
28
+ catch: requests.catch.command,
29
29
  last_command: action[:commands].last,
30
30
  commands: restore_callbacks(route, :before) + action[:commands] + restore_callbacks(route, :after)
31
31
  })
@@ -1,5 +1,6 @@
1
1
  require 'treetop'
2
- require 'dandy/routing/builder'
2
+ require 'dandy/routing/routes_builder'
3
+ require 'dandy/routing/handlers_builder'
3
4
  require 'dandy/routing/parser'
4
5
  require 'dandy/routing/matcher'
5
6
  require 'dandy/routing/file_reader'
@@ -20,11 +20,17 @@ require_relative 'syntax/route'
20
20
  require_relative 'syntax/respond'
21
21
 
22
22
 
23
- require_relative 'syntax/sections'
23
+ require_relative 'syntax/requests'
24
24
  require_relative 'syntax/before_section'
25
25
  require_relative 'syntax/tree_section'
26
26
  require_relative 'syntax/after_section'
27
27
  require_relative 'syntax/catch_section'
28
28
 
29
+ require_relative 'syntax/message_name'
30
+ require_relative 'syntax/message'
31
+ require_relative 'syntax/messages'
32
+
33
+ require_relative 'syntax/dandy'
34
+
29
35
  module Syntax
30
36
  end
@@ -0,0 +1,20 @@
1
+ module Syntax
2
+ class Dandy < Treetop::Runtime::SyntaxNode
3
+ attr_reader :requests, :messages
4
+
5
+ def parse
6
+ elements.each do |element|
7
+ element.elements.each do |nested|
8
+ if nested.is_a? Requests
9
+ @requests = nested.parse
10
+ end
11
+
12
+ if nested.is_a? Messages
13
+ @messages = nested.parse
14
+ end
15
+ end
16
+ end
17
+ self
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Syntax
2
+ class Message < Treetop::Runtime::SyntaxNode
3
+ attr_accessor :name, :command_list
4
+
5
+ def parse
6
+ elements.each do |element|
7
+ if element.is_a? MessageName
8
+ @name = element.parse
9
+ end
10
+
11
+ if element.is_a? Commands
12
+ @command_list = element.parse
13
+ end
14
+ end
15
+
16
+ self
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ module Syntax
2
+ class MessageName < Treetop::Runtime::SyntaxNode
3
+ def parse
4
+ text_value.gsub('"','')
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,35 @@
1
+ module Syntax
2
+ class Messages < Treetop::Runtime::SyntaxNode
3
+ attr_reader :messages, :catch, :before_commands, :after_commands
4
+
5
+ def parse
6
+ @messages ||= []
7
+ @before_commands = []
8
+ @after_commands = []
9
+
10
+ elements.each do |element|
11
+ if element.elements
12
+ element.elements.each do |nested|
13
+ if nested.is_a? Message
14
+ @messages << nested.parse
15
+ end
16
+ end
17
+ end
18
+
19
+ if element.is_a? BeforeSection
20
+ @before_commands = element.parse.commands
21
+ end
22
+
23
+ if element.is_a? AfterSection
24
+ @after_commands = element.parse.commands
25
+ end
26
+
27
+ if element.is_a? CatchSection
28
+ @catch = element.parse
29
+ end
30
+ end
31
+
32
+ self
33
+ end
34
+ end
35
+ end
@@ -1,5 +1,5 @@
1
1
  module Syntax
2
- class Sections < Treetop::Runtime::SyntaxNode
2
+ class Requests < Treetop::Runtime::SyntaxNode
3
3
  attr_reader :node, :catch
4
4
 
5
5
  def parse
@@ -1,6 +1,22 @@
1
1
  grammar Syntax
2
- rule sections
3
- ':receive' eol node catch <Sections>
2
+ rule dandy
3
+ (requests) 0..1 (messages) 0..1 <Dandy>
4
+ end
5
+
6
+ rule requests
7
+ ':request' eol node catch <Requests>
8
+ end
9
+
10
+ rule messages
11
+ ':message' eol before after message+ catch <Messages>
12
+ end
13
+
14
+ rule message
15
+ indent message_name commands eol <Message>
16
+ end
17
+
18
+ rule message_name
19
+ '"' [a-z0-9_\-.]+ '"' <MessageName>
4
20
  end
5
21
 
6
22
  rule before
data/lib/dandy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Dandy
2
- VERSION = '1.0.3'
2
+ VERSION = '2.0.0-alpha'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dandy
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 2.0.0.pre.alpha
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vladimir Kalinkin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-09-07 00:00:00.000000000 Z
11
+ date: 2021-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hypo
@@ -231,6 +231,7 @@ files:
231
231
  - lib/dandy/base/handle_errors.rb
232
232
  - lib/dandy/chain.rb
233
233
  - lib/dandy/config.rb
234
+ - lib/dandy/consumer.rb
234
235
  - lib/dandy/errors/dandy_error.rb
235
236
  - lib/dandy/errors/syntax_error.rb
236
237
  - lib/dandy/errors/view_engine_error.rb
@@ -252,17 +253,22 @@ files:
252
253
  - lib/dandy/generators/templates/dandy.yml
253
254
  - lib/dandy/generators/templates/db/mapping.rb
254
255
  - lib/dandy/generators/templates/views/show_welcome.json.jbuilder
256
+ - lib/dandy/handler_executor.rb
255
257
  - lib/dandy/loaders/dependency_loader.rb
256
258
  - lib/dandy/loaders/template_loader.rb
257
259
  - lib/dandy/loaders/type_loader.rb
260
+ - lib/dandy/message.rb
258
261
  - lib/dandy/request.rb
259
262
  - lib/dandy/response.rb
260
- - lib/dandy/routing/builder.rb
263
+ - lib/dandy/route_executor.rb
261
264
  - lib/dandy/routing/file_reader.rb
265
+ - lib/dandy/routing/handlers_builder.rb
262
266
  - lib/dandy/routing/match.rb
263
267
  - lib/dandy/routing/matcher.rb
268
+ - lib/dandy/routing/message_handler.rb
264
269
  - lib/dandy/routing/parser.rb
265
270
  - lib/dandy/routing/route.rb
271
+ - lib/dandy/routing/routes_builder.rb
266
272
  - lib/dandy/routing/routing.rb
267
273
  - lib/dandy/routing/syntax.rb
268
274
  - lib/dandy/routing/syntax/action.rb
@@ -272,6 +278,10 @@ files:
272
278
  - lib/dandy/routing/syntax/catch_section.rb
273
279
  - lib/dandy/routing/syntax/command.rb
274
280
  - lib/dandy/routing/syntax/commands.rb
281
+ - lib/dandy/routing/syntax/dandy.rb
282
+ - lib/dandy/routing/syntax/message.rb
283
+ - lib/dandy/routing/syntax/message_name.rb
284
+ - lib/dandy/routing/syntax/messages.rb
275
285
  - lib/dandy/routing/syntax/node.rb
276
286
  - lib/dandy/routing/syntax/nodes.rb
277
287
  - lib/dandy/routing/syntax/primitives/arrow.rb
@@ -284,14 +294,13 @@ files:
284
294
  - lib/dandy/routing/syntax/primitives/parameter.rb
285
295
  - lib/dandy/routing/syntax/primitives/path.rb
286
296
  - lib/dandy/routing/syntax/primitives/result_name.rb
297
+ - lib/dandy/routing/syntax/requests.rb
287
298
  - lib/dandy/routing/syntax/respond.rb
288
299
  - lib/dandy/routing/syntax/route.rb
289
- - lib/dandy/routing/syntax/sections.rb
290
300
  - lib/dandy/routing/syntax/tree_section.rb
291
301
  - lib/dandy/routing/syntax/view.rb
292
302
  - lib/dandy/routing/syntax_error_interpreter.rb
293
303
  - lib/dandy/routing/syntax_grammar.tt
294
- - lib/dandy/safe_executor.rb
295
304
  - lib/dandy/template_registry.rb
296
305
  - lib/dandy/version.rb
297
306
  - lib/dandy/view_builder.rb
@@ -303,7 +312,7 @@ licenses:
303
312
  - MIT
304
313
  metadata:
305
314
  allowed_push_host: https://rubygems.org
306
- post_install_message:
315
+ post_install_message:
307
316
  rdoc_options: []
308
317
  require_paths:
309
318
  - lib
@@ -314,12 +323,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
314
323
  version: '0'
315
324
  required_rubygems_version: !ruby/object:Gem::Requirement
316
325
  requirements:
317
- - - ">="
326
+ - - ">"
318
327
  - !ruby/object:Gem::Version
319
- version: '0'
328
+ version: 1.3.1
320
329
  requirements: []
321
- rubygems_version: 3.1.2
322
- signing_key:
330
+ rubygems_version: 3.2.15
331
+ signing_key:
323
332
  specification_version: 4
324
333
  summary: Dandy is a minimalistic web API framework.
325
334
  test_files: []