toys 0.12.2 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +2 -0
  3. data/CHANGELOG.md +35 -0
  4. data/LICENSE.md +1 -1
  5. data/README.md +7 -4
  6. data/builtins/system/git-cache.rb +238 -0
  7. data/builtins/system/test.rb +37 -2
  8. data/core-docs/toys/acceptor.rb +432 -0
  9. data/core-docs/toys/arg_parser.rb +397 -0
  10. data/core-docs/toys/cli.rb +493 -0
  11. data/core-docs/toys/compat.rb +2 -0
  12. data/core-docs/toys/completion.rb +329 -0
  13. data/core-docs/toys/context.rb +321 -0
  14. data/core-docs/toys/core.rb +14 -0
  15. data/core-docs/toys/dsl/base.rb +56 -0
  16. data/core-docs/toys/dsl/flag.rb +261 -0
  17. data/core-docs/toys/dsl/flag_group.rb +259 -0
  18. data/core-docs/toys/dsl/internal.rb +4 -0
  19. data/core-docs/toys/dsl/positional_arg.rb +139 -0
  20. data/core-docs/toys/dsl/tool.rb +1530 -0
  21. data/core-docs/toys/errors.rb +93 -0
  22. data/core-docs/toys/flag.rb +549 -0
  23. data/core-docs/toys/flag_group.rb +186 -0
  24. data/core-docs/toys/input_file.rb +8 -0
  25. data/core-docs/toys/loader.rb +222 -0
  26. data/core-docs/toys/middleware.rb +295 -0
  27. data/core-docs/toys/mixin.rb +142 -0
  28. data/core-docs/toys/module_lookup.rb +75 -0
  29. data/core-docs/toys/positional_arg.rb +145 -0
  30. data/core-docs/toys/settings.rb +507 -0
  31. data/core-docs/toys/source_info.rb +127 -0
  32. data/core-docs/toys/standard_middleware/add_verbosity_flags.rb +49 -0
  33. data/core-docs/toys/standard_middleware/apply_config.rb +24 -0
  34. data/core-docs/toys/standard_middleware/handle_usage_errors.rb +33 -0
  35. data/core-docs/toys/standard_middleware/set_default_descriptions.rb +222 -0
  36. data/core-docs/toys/standard_middleware/show_help.rb +190 -0
  37. data/core-docs/toys/standard_middleware/show_root_version.rb +45 -0
  38. data/core-docs/toys/standard_mixins/bundler.rb +83 -0
  39. data/core-docs/toys/standard_mixins/exec.rb +645 -0
  40. data/core-docs/toys/standard_mixins/fileutils.rb +18 -0
  41. data/core-docs/toys/standard_mixins/gems.rb +48 -0
  42. data/core-docs/toys/standard_mixins/git_cache.rb +41 -0
  43. data/core-docs/toys/standard_mixins/highline.rb +133 -0
  44. data/core-docs/toys/standard_mixins/terminal.rb +135 -0
  45. data/core-docs/toys/standard_mixins/xdg.rb +49 -0
  46. data/core-docs/toys/template.rb +112 -0
  47. data/core-docs/toys/tool_definition.rb +926 -0
  48. data/core-docs/toys/utils/completion_engine.rb +49 -0
  49. data/core-docs/toys/utils/exec.rb +721 -0
  50. data/core-docs/toys/utils/gems.rb +185 -0
  51. data/core-docs/toys/utils/git_cache.rb +353 -0
  52. data/core-docs/toys/utils/help_text.rb +134 -0
  53. data/core-docs/toys/utils/terminal.rb +310 -0
  54. data/core-docs/toys/utils/xdg.rb +253 -0
  55. data/core-docs/toys/wrappable_string.rb +120 -0
  56. data/core-docs/toys-core.rb +63 -0
  57. data/docs/guide.md +497 -156
  58. data/lib/toys/standard_cli.rb +50 -36
  59. data/lib/toys/templates/clean.rb +18 -0
  60. data/lib/toys/templates/gem_build.rb +24 -0
  61. data/lib/toys/templates/minitest.rb +21 -0
  62. data/lib/toys/templates/rake.rb +23 -3
  63. data/lib/toys/templates/rdoc.rb +29 -0
  64. data/lib/toys/templates/rspec.rb +32 -4
  65. data/lib/toys/templates/rubocop.rb +14 -1
  66. data/lib/toys/templates/yardoc.rb +55 -0
  67. data/lib/toys/testing.rb +186 -109
  68. data/lib/toys/version.rb +1 -1
  69. data/lib/toys.rb +4 -2
  70. metadata +56 -6
@@ -0,0 +1,493 @@
1
+ module Toys
2
+ ##
3
+ # **_Defined in the toys-core gem_**
4
+ #
5
+ # A Toys-based CLI.
6
+ #
7
+ # This is the entry point for command line execution. It includes the set of
8
+ # tool definitions (and/or information on how to load them from the file
9
+ # system), configuration parameters such as logging and error handling, and a
10
+ # method to call to invoke a command.
11
+ #
12
+ # This is the class to instantiate to create a Toys-based command line
13
+ # executable. For example:
14
+ #
15
+ # #!/usr/bin/env ruby
16
+ # require "toys-core"
17
+ # cli = Toys::CLI.new
18
+ # cli.add_config_block do
19
+ # def run
20
+ # puts "Hello, world!"
21
+ # end
22
+ # end
23
+ # exit(cli.run(*ARGV))
24
+ #
25
+ # The currently running CLI is also available at runtime, and can be used by
26
+ # tools that want to invoke other tools. For example:
27
+ #
28
+ # # My .toys.rb
29
+ # tool "foo" do
30
+ # def run
31
+ # puts "in foo"
32
+ # end
33
+ # end
34
+ # tool "bar" do
35
+ # def run
36
+ # puts "in bar"
37
+ # cli.run "foo"
38
+ # end
39
+ # end
40
+ #
41
+ class CLI
42
+ ##
43
+ # Create a CLI.
44
+ #
45
+ # Most configuration parameters (besides tool definitions and tool lookup
46
+ # paths) are set as options passed to the constructor. These options fall
47
+ # roughly into four categories:
48
+ #
49
+ # * Options affecting output behavior:
50
+ # * `logger`: A global logger for all tools to use
51
+ # * `logger_factory`: A proc that returns a logger to use
52
+ # * `base_level`: The default log level
53
+ # * `error_handler`: Callback for handling exceptions
54
+ # * `executable_name`: The name of the executable
55
+ # * Options affecting tool specification
56
+ # * `extra_delimibers`: Tool name delimiters besides space
57
+ # * `completion`: Tab completion handler
58
+ # * Options affecting tool definition
59
+ # * `middleware_stack`: The middleware applied to all tools
60
+ # * `mixin_lookup`: Where to find well-known mixins
61
+ # * `middleware_lookup`: Where to find well-known middleware
62
+ # * `template_lookup`: Where to find well-known templates
63
+ # * Options affecting tool files and directories
64
+ # * `config_dir_name`: Directory name containing tool files
65
+ # * `config_file_name`: File name for tools
66
+ # * `index_file_name`: Name of index files in tool directories
67
+ # * `preload_file_name`: Name of preload files in tool directories
68
+ # * `preload_dir_name`: Name of preload directories in tool directories
69
+ # * `data_dir_name`: Name of data directories in tool directories
70
+ #
71
+ # @param logger [Logger] A global logger to use for all tools. This may be
72
+ # set if the CLI will call at most one tool at a time. However, it will
73
+ # behave incorrectly if CLI might run multiple tools at the same time
74
+ # with different verbosity settings (since the logger cannot have
75
+ # multiple level settings simultaneously). In that case, do not set a
76
+ # global logger, but use the `logger_factory` parameter instead.
77
+ # @param logger_factory [Proc] A proc that takes a {Toys::ToolDefinition}
78
+ # as an argument, and returns a `Logger` to use when running that tool.
79
+ # Optional. If not provided (and no global logger is set), CLI will use
80
+ # a default factory that writes generates loggers writing formatted
81
+ # output to `STDERR`, as defined by {Toys::CLI.default_logger_factory}.
82
+ # @param base_level [Integer] The logger level that should correspond
83
+ # to zero verbosity.
84
+ # Optional. If not provided, defaults to the current level of the
85
+ # logger (which is often `Logger::WARN`).
86
+ # @param error_handler [Proc,nil] A proc that is called when an error is
87
+ # caught. The proc should take a {Toys::ContextualError} argument and
88
+ # report the error. It should return an exit code (normally nonzero).
89
+ # Optional. If not provided, defaults to an instance of
90
+ # {Toys::CLI::DefaultErrorHandler}, which displays an error message to
91
+ # `STDERR`.
92
+ # @param executable_name [String] The executable name displayed in help
93
+ # text. Optional. Defaults to the ruby program name.
94
+ #
95
+ # @param extra_delimiters [String] A string containing characters that can
96
+ # function as delimiters in a tool name. Defaults to empty. Allowed
97
+ # characters are period, colon, and slash.
98
+ # @param completion [Toys::Completion::Base] A specifier for shell tab
99
+ # completion for the CLI as a whole.
100
+ # Optional. If not provided, defaults to an instance of
101
+ # {Toys::CLI::DefaultCompletion}, which delegates completion to the
102
+ # relevant tool.
103
+ #
104
+ # @param middleware_stack [Array<Toys::Middleware::Spec>] An array of
105
+ # middleware that will be used by default for all tools.
106
+ # Optional. If not provided, uses a default set of middleware defined
107
+ # in {Toys::CLI.default_middleware_stack}. To include no middleware,
108
+ # pass the empty array explicitly.
109
+ # @param mixin_lookup [Toys::ModuleLookup] A lookup for well-known mixin
110
+ # modules (i.e. with symbol names).
111
+ # Optional. If not provided, defaults to the set of standard mixins
112
+ # provided by toys-core, as defined by
113
+ # {Toys::CLI.default_mixin_lookup}. If you explicitly want no standard
114
+ # mixins, pass an empty instance of {Toys::ModuleLookup}.
115
+ # @param middleware_lookup [Toys::ModuleLookup] A lookup for well-known
116
+ # middleware classes.
117
+ # Optional. If not provided, defaults to the set of standard middleware
118
+ # classes provided by toys-core, as defined by
119
+ # {Toys::CLI.default_middleware_lookup}. If you explicitly want no
120
+ # standard middleware, pass an empty instance of
121
+ # {Toys::ModuleLookup}.
122
+ # @param template_lookup [Toys::ModuleLookup] A lookup for well-known
123
+ # template classes.
124
+ # Optional. If not provided, defaults to the set of standard template
125
+ # classes provided by toys core, as defined by
126
+ # {Toys::CLI.default_template_lookup}. If you explicitly want no
127
+ # standard tenokates, pass an empty instance of {Toys::ModuleLookup}.
128
+ #
129
+ # @param config_dir_name [String] A directory with this name that appears
130
+ # in the loader path, is treated as a configuration directory whose
131
+ # contents are loaded into the toys configuration.
132
+ # Optional. If not provided, toplevel configuration directories are
133
+ # disabled.
134
+ # Note: the standard toys executable sets this to `".toys"`.
135
+ # @param config_file_name [String] A file with this name that appears in
136
+ # the loader path, is treated as a toplevel configuration file whose
137
+ # contents are loaded into the toys configuration. This does not
138
+ # include "index" configuration files located within a configuration
139
+ # directory.
140
+ # Optional. If not provided, toplevel configuration files are disabled.
141
+ # Note: the standard toys executable sets this to `".toys.rb"`.
142
+ # @param index_file_name [String] A file with this name that appears in any
143
+ # configuration directory is loaded first as a standalone configuration
144
+ # file. This does not include "toplevel" configuration files outside
145
+ # configuration directories.
146
+ # Optional. If not provided, index configuration files are disabled.
147
+ # Note: the standard toys executable sets this to `".toys.rb"`.
148
+ # @param preload_file_name [String] A file with this name that appears
149
+ # in any configuration directory is preloaded using `require` before
150
+ # any tools in that configuration directory are defined. A preload file
151
+ # includes normal Ruby code, rather than Toys DSL definitions. The
152
+ # preload file is loaded before any files in a preload directory.
153
+ # Optional. If not provided, preload files are disabled.
154
+ # Note: the standard toys executable sets this to `".preload.rb"`.
155
+ # @param preload_dir_name [String] A directory with this name that appears
156
+ # in any configuration directory is searched for Ruby files, which are
157
+ # preloaded using `require` before any tools in that configuration
158
+ # directory are defined. Files in a preload directory include normal
159
+ # Ruby code, rather than Toys DSL definitions. Files in a preload
160
+ # directory are loaded after any standalone preload file.
161
+ # Optional. If not provided, preload directories are disabled.
162
+ # Note: the standard toys executable sets this to `".preload"`.
163
+ # @param data_dir_name [String] A directory with this name that appears in
164
+ # any configuration directory is added to the data directory search
165
+ # path for any tool file in that directory.
166
+ # Optional. If not provided, data directories are disabled.
167
+ # Note: the standard toys executable sets this to `".data"`.
168
+ # @param lib_dir_name [String] A directory with this name that appears in
169
+ # any configuration directory is added to the Ruby load path when
170
+ # executing any tool file in that directory.
171
+ # Optional. If not provided, lib directories are disabled.
172
+ # Note: the standard toys executable sets this to `".lib"`.
173
+ #
174
+ def initialize(executable_name: nil, # rubocop:disable Metrics/MethodLength
175
+ middleware_stack: nil,
176
+ extra_delimiters: "",
177
+ config_dir_name: nil,
178
+ config_file_name: nil,
179
+ index_file_name: nil,
180
+ preload_file_name: nil,
181
+ preload_dir_name: nil,
182
+ data_dir_name: nil,
183
+ lib_dir_name: nil,
184
+ mixin_lookup: nil,
185
+ middleware_lookup: nil,
186
+ template_lookup: nil,
187
+ logger_factory: nil,
188
+ logger: nil,
189
+ base_level: nil,
190
+ error_handler: nil,
191
+ completion: nil)
192
+ # Source available in the toys-core gem
193
+ end
194
+
195
+ ##
196
+ # Make a clone with the same settings but no no config blocks and no paths
197
+ # in the loader. This is sometimes useful for calling another tool that has
198
+ # to be loaded from a different configuration.
199
+ #
200
+ # @param opts [keywords] Any configuration arguments that should be
201
+ # modified from the original. See {#initialize} for a list of
202
+ # recognized keywords.
203
+ # @return [Toys::CLI]
204
+ # @yieldparam cli [Toys::CLI] If you pass a block, the new CLI is yielded
205
+ # to it so you can add paths and make other modifications.
206
+ #
207
+ def child(**opts)
208
+ # Source available in the toys-core gem
209
+ end
210
+
211
+ ##
212
+ # The current loader for this CLI.
213
+ # @return [Toys::Loader]
214
+ #
215
+ attr_reader :loader
216
+
217
+ ##
218
+ # The effective executable name used for usage text in this CLI.
219
+ # @return [String]
220
+ #
221
+ attr_reader :executable_name
222
+
223
+ ##
224
+ # The string of tool name delimiter characters (besides space).
225
+ # @return [String]
226
+ #
227
+ attr_reader :extra_delimiters
228
+
229
+ ##
230
+ # The global logger, if any.
231
+ # @return [Logger,nil]
232
+ #
233
+ attr_reader :logger
234
+
235
+ ##
236
+ # The logger factory.
237
+ # @return [Proc]
238
+ #
239
+ attr_reader :logger_factory
240
+
241
+ ##
242
+ # The initial logger level in this CLI, used as the level for verbosity 0.
243
+ # May be `nil`, indicating it will use the initial logger setting.
244
+ # @return [Integer,nil]
245
+ #
246
+ attr_reader :base_level
247
+
248
+ ##
249
+ # The overall completion strategy for this CLI.
250
+ # @return [Toys::Completion::Base,Proc]
251
+ #
252
+ attr_reader :completion
253
+
254
+ ##
255
+ # Add a specific configuration file or directory to the loader.
256
+ #
257
+ # This is generally used to load a static or "built-in" set of tools,
258
+ # either for a standalone command line executable based on Toys, or to
259
+ # provide a "default" set of tools for a dynamic executable. For example,
260
+ # the main Toys executable uses this to load the builtin tools from its
261
+ # "builtins" directory.
262
+ #
263
+ # @param path [String] A path to add. May reference a single Toys file or
264
+ # a Toys directory.
265
+ # @param high_priority [Boolean] Add the config at the head of the priority
266
+ # list rather than the tail.
267
+ # @param source_name [String] A custom name for the root source. Optional.
268
+ # @param context_directory [String,nil,:path,:parent] The context directory
269
+ # for tools loaded from this path. You can pass a directory path as a
270
+ # string, `:path` to denote the given path, `:parent` to denote the
271
+ # given path's parent directory, or `nil` to denote no context.
272
+ # Defaults to `:parent`.
273
+ # @return [self]
274
+ #
275
+ def add_config_path(path,
276
+ high_priority: false,
277
+ source_name: nil,
278
+ context_directory: :parent)
279
+ # Source available in the toys-core gem
280
+ end
281
+
282
+ ##
283
+ # Add a configuration block to the loader.
284
+ #
285
+ # This is used to create tools "inline", and is useful for simple command
286
+ # line executables based on Toys.
287
+ #
288
+ # @param high_priority [Boolean] Add the config at the head of the priority
289
+ # list rather than the tail.
290
+ # @param source_name [String] The source name that will be shown in
291
+ # documentation for tools defined in this block. If omitted, a default
292
+ # unique string will be generated.
293
+ # @param block [Proc] The block of configuration, executed in the context
294
+ # of the tool DSL {Toys::DSL::Tool}.
295
+ # @param context_directory [String,nil] The context directory for tools
296
+ # loaded from this block. You can pass a directory path as a string, or
297
+ # `nil` to denote no context. Defaults to `nil`.
298
+ # @return [self]
299
+ #
300
+ def add_config_block(high_priority: false,
301
+ source_name: nil,
302
+ context_directory: nil,
303
+ &block)
304
+ # Source available in the toys-core gem
305
+ end
306
+
307
+ ##
308
+ # Checks the given directory path. If it contains a config file and/or
309
+ # config directory, those are added to the loader.
310
+ #
311
+ # The main Toys executable uses this method to load tools from directories
312
+ # in the `TOYS_PATH`.
313
+ #
314
+ # @param search_path [String] A path to search for configs.
315
+ # @param high_priority [Boolean] Add the configs at the head of the
316
+ # priority list rather than the tail.
317
+ # @param context_directory [String,nil,:path,:parent] The context directory
318
+ # for tools loaded from this path. You can pass a directory path as a
319
+ # string, `:path` to denote the given path, `:parent` to denote the
320
+ # given path's parent directory, or `nil` to denote no context.
321
+ # Defaults to `:path`.
322
+ # @return [self]
323
+ #
324
+ def add_search_path(search_path,
325
+ high_priority: false,
326
+ context_directory: :path)
327
+ # Source available in the toys-core gem
328
+ end
329
+
330
+ ##
331
+ # Walk up the directory hierarchy from the given start location, and add to
332
+ # the loader any config files and directories found.
333
+ #
334
+ # The main Toys executable uses this method to load tools from the current
335
+ # directory and its ancestors.
336
+ #
337
+ # @param start [String] The first directory to add. Defaults to the current
338
+ # working directory.
339
+ # @param terminate [Array<String>] Optional list of directories that should
340
+ # terminate the search. If the walk up the directory tree encounters
341
+ # one of these directories, the search is halted without checking the
342
+ # terminating directory.
343
+ # @param high_priority [Boolean] Add the configs at the head of the
344
+ # priority list rather than the tail.
345
+ # @return [self]
346
+ #
347
+ def add_search_path_hierarchy(start: nil, terminate: [], high_priority: false)
348
+ # Source available in the toys-core gem
349
+ end
350
+
351
+ ##
352
+ # Run the CLI with the given command line arguments.
353
+ # Handles exceptions using the error handler.
354
+ #
355
+ # @param args [String...] Command line arguments specifying which tool to
356
+ # run and what arguments to pass to it. You may pass either a single
357
+ # array of strings, or a series of string arguments.
358
+ # @param verbosity [Integer] Initial verbosity. Default is 0.
359
+ # @param delegated_from [Toys::Context] The context from which this
360
+ # execution is delegated. Optional. Should be set only if this is a
361
+ # delegated execution.
362
+ #
363
+ # @return [Integer] The resulting process status code (i.e. 0 for success).
364
+ #
365
+ def run(*args, verbosity: 0, delegated_from: nil)
366
+ # Source available in the toys-core gem
367
+ end
368
+
369
+ ##
370
+ # Prepare a tool to be run, but just execute the given block rather than
371
+ # performing a full run of the tool. This is intended for testing tools.
372
+ # Unlike {#run}, this does not catch errors and perform error handling.
373
+ #
374
+ # @param args [String...] Command line arguments specifying which tool to
375
+ # run and what arguments to pass to it. You may pass either a single
376
+ # array of strings, or a series of string arguments.
377
+ # @yieldparam context [Toys::Context] Yields the tool context.
378
+ #
379
+ # @return [Object] The value returned from the block.
380
+ #
381
+ def load_tool(*args)
382
+ # Source available in the toys-core gem
383
+ end
384
+
385
+ ##
386
+ # **_Defined in the toys-core gem_**
387
+ #
388
+ # A basic error handler that prints out captured errors to a stream or
389
+ # a logger.
390
+ #
391
+ class DefaultErrorHandler
392
+ ##
393
+ # Create an error handler.
394
+ #
395
+ # @param output [IO,nil] Where to write errors. Default is `$stderr`.
396
+ #
397
+ def initialize(output: $stderr)
398
+ # Source available in the toys-core gem
399
+ end
400
+
401
+ ##
402
+ # The error handler routine. Prints out the error message and backtrace,
403
+ # and returns the correct result code.
404
+ #
405
+ # @param error [Exception] The error that occurred.
406
+ # @return [Integer] The result code for the execution.
407
+ #
408
+ def call(error)
409
+ # Source available in the toys-core gem
410
+ end
411
+ end
412
+
413
+ ##
414
+ # **_Defined in the toys-core gem_**
415
+ #
416
+ # A Completion that implements the default algorithm for a CLI. This
417
+ # algorithm simply determines the tool and uses its completion.
418
+ #
419
+ class DefaultCompletion < Completion::Base
420
+ ##
421
+ # Returns candidates for the current completion.
422
+ #
423
+ # @param context [Toys::Completion::Context] the current completion
424
+ # context including the string fragment.
425
+ # @return [Array<Toys::Completion::Candidate>] an array of candidates
426
+ #
427
+ def call(context)
428
+ # Source available in the toys-core gem
429
+ end
430
+ end
431
+
432
+ class << self
433
+ ##
434
+ # Returns a default set of middleware that may be used as a starting
435
+ # point for a typical CLI. This set includes the following in order:
436
+ #
437
+ # * {Toys::StandardMiddleware::SetDefaultDescriptions} providing
438
+ # defaults for description fields.
439
+ # * {Toys::StandardMiddleware::ShowHelp} adding the `--help` flag and
440
+ # providing default behavior for namespaces.
441
+ # * {Toys::StandardMiddleware::HandleUsageErrors}
442
+ # * {Toys::StandardMiddleware::AddVerbosityFlags} adding the `--verbose`
443
+ # and `--quiet` flags for managing the logger level.
444
+ #
445
+ # @return [Array<Toys::Middleware::Spec>]
446
+ #
447
+ def default_middleware_stack
448
+ # Source available in the toys-core gem
449
+ end
450
+
451
+ ##
452
+ # Returns a default ModuleLookup for mixins that points at the
453
+ # StandardMixins module.
454
+ #
455
+ # @return [Toys::ModuleLookup]
456
+ #
457
+ def default_mixin_lookup
458
+ # Source available in the toys-core gem
459
+ end
460
+
461
+ ##
462
+ # Returns a default ModuleLookup for middleware that points at the
463
+ # StandardMiddleware module.
464
+ #
465
+ # @return [Toys::ModuleLookup]
466
+ #
467
+ def default_middleware_lookup
468
+ # Source available in the toys-core gem
469
+ end
470
+
471
+ ##
472
+ # Returns a default empty ModuleLookup for templates.
473
+ #
474
+ # @return [Toys::ModuleLookup]
475
+ #
476
+ def default_template_lookup
477
+ # Source available in the toys-core gem
478
+ end
479
+
480
+ ##
481
+ # Returns a logger factory that generates loggers that write to stderr.
482
+ # All loggers generated by this factory share a single
483
+ # {Toys::Utils::Terminal}, so log entries may interleave but will not
484
+ # interrupt one another.
485
+ #
486
+ # @return [Proc]
487
+ #
488
+ def default_logger_factory
489
+ # Source available in the toys-core gem
490
+ end
491
+ end
492
+ end
493
+ end
@@ -0,0 +1,2 @@
1
+ module Toys
2
+ end