doodle 0.0.10 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. data/CREDITS +22 -0
  2. data/{ChangeLog → History.txt} +22 -3
  3. data/License.txt +20 -0
  4. data/Manifest.txt +61 -0
  5. data/README.txt +166 -0
  6. data/Rakefile +4 -0
  7. data/config/hoe.rb +77 -0
  8. data/config/requirements.rb +15 -0
  9. data/examples/doodle-errors.rb +25 -0
  10. data/examples/event-location.rb +3 -7
  11. data/examples/example-01.rb +1 -1
  12. data/examples/example-01.rdoc +3 -3
  13. data/examples/example-02.rb +15 -4
  14. data/examples/example-02.rdoc +17 -5
  15. data/examples/mail-datatypes.rb +104 -0
  16. data/examples/mail.rb +85 -0
  17. data/examples/parent.rb +40 -0
  18. data/examples/profile-options.rb +67 -0
  19. data/examples/smtp_tls.rb +65 -0
  20. data/examples/test-datatypes.rb +55 -0
  21. data/examples/yaml-example.rb +40 -0
  22. data/examples/yaml-example2.rb +42 -0
  23. data/lib/doodle.rb +364 -301
  24. data/lib/doodle/datatypes.rb +148 -0
  25. data/lib/doodle/rfc822.rb +31 -0
  26. data/lib/doodle/utils.rb +13 -0
  27. data/lib/doodle/version.rb +9 -0
  28. data/log/debug.log +0 -0
  29. data/script/console +10 -0
  30. data/script/destroy +14 -0
  31. data/script/generate +14 -0
  32. data/script/txt2html +82 -0
  33. data/setup.rb +1585 -0
  34. data/spec/arg_order_spec.rb +5 -5
  35. data/spec/attributes_spec.rb +66 -24
  36. data/spec/bugs_spec.rb +109 -6
  37. data/spec/class_spec.rb +7 -4
  38. data/spec/class_validation_spec.rb +46 -0
  39. data/spec/class_var_spec.rb +76 -0
  40. data/spec/collector_spec.rb +16 -30
  41. data/spec/conversion_spec.rb +8 -3
  42. data/spec/defaults_spec.rb +4 -4
  43. data/spec/doodle_context_spec.rb +3 -4
  44. data/spec/doodle_spec.rb +25 -15
  45. data/spec/extra_args_spec.rb +1 -1
  46. data/spec/factory_spec.rb +3 -3
  47. data/spec/init_spec.rb +11 -11
  48. data/spec/new_doodle_spec.rb +19 -0
  49. data/spec/required_spec.rb +1 -1
  50. data/spec/serialization_spec.rb +3 -6
  51. data/spec/singleton_spec.rb +5 -5
  52. data/spec/spec.opts +1 -0
  53. data/spec/spec_helper.rb +44 -0
  54. data/spec/superclass_spec.rb +6 -5
  55. data/spec/validation2_spec.rb +248 -0
  56. data/spec/validation_spec.rb +26 -37
  57. data/tasks/deployment.rake +34 -0
  58. data/tasks/environment.rake +7 -0
  59. data/tasks/rspec.rake +21 -0
  60. data/tasks/website.rake +17 -0
  61. metadata +76 -20
  62. data/COPYING +0 -18
  63. data/README +0 -57
  64. data/examples/event.rb +0 -39
  65. data/examples/example-03.rb +0 -45
  66. data/examples/example-03.rdoc +0 -55
  67. data/lib/semantic.cache +0 -8
@@ -2,7 +2,7 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  require 'date'
3
3
  require 'doodle'
4
4
 
5
- class DateRange < Doodle::Base
5
+ class DateRange < Doodle
6
6
  has :start_date do
7
7
  default { Date.today }
8
8
  end
@@ -2,7 +2,7 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  require 'date'
3
3
  require 'doodle'
4
4
 
5
- class DateRange < Doodle::Base
5
+ class DateRange < Doodle
6
6
  has :start_date do
7
7
  default { Date.today }
8
8
  end
@@ -12,6 +12,6 @@ class DateRange < Doodle::Base
12
12
  end
13
13
 
14
14
  dr = DateRange.new
15
- dr.start_date # => #<Date: 4909137/2,0,2299161>
16
- dr.end_date # => #<Date: 4909137/2,0,2299161>
15
+ dr.start_date # => #<Date: 4909159/2,0,2299161>
16
+ dr.end_date # => #<Date: 4909159/2,0,2299161>
17
17
 
@@ -1,8 +1,9 @@
1
1
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  require 'date'
3
3
  require 'doodle'
4
+ require 'doodle/utils' # for try
4
5
 
5
- class DateRange < Doodle::Base
6
+ class DateRange < Doodle
6
7
  has :start_date, :kind => Date do
7
8
  default { Date.today }
8
9
  from String do |s|
@@ -25,6 +26,8 @@ class DateRange < Doodle::Base
25
26
  m = /(\d{4}-\d{2}-\d{2})\s*(?:to|-|\s)\s*(\d{4}-\d{2}-\d{2})/.match(s)
26
27
  if m
27
28
  self.new(*m.captures)
29
+ else
30
+ raise Exception, "Cannot parse date: '#{s}'"
28
31
  end
29
32
  end
30
33
  end
@@ -57,6 +60,14 @@ dr = DateRange.from '2007-01-01 2007-12-31'
57
60
  dr.start_date # =>
58
61
  dr.end_date # =>
59
62
 
60
- dr = DateRange '2008-01-01', '2007-12-31'
61
- dr.start_date # =>
62
- dr.end_date # =>
63
+ p try {
64
+ dr = DateRange.from 'Hello World'
65
+ dr.start_date # =>
66
+ dr.end_date # =>
67
+ }
68
+
69
+ p try {
70
+ dr = DateRange '2008-01-01', '2007-12-31'
71
+ dr.start_date # =>
72
+ dr.end_date # =>
73
+ }
@@ -1,8 +1,9 @@
1
1
  $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
2
  require 'date'
3
3
  require 'doodle'
4
+ require 'doodle/utils' # for try
4
5
 
5
- class DateRange < Doodle::Base
6
+ class DateRange < Doodle
6
7
  has :start_date, :kind => Date do
7
8
  default { Date.today }
8
9
  from String do |s|
@@ -25,6 +26,8 @@ class DateRange < Doodle::Base
25
26
  m = /(\d{4}-\d{2}-\d{2})\s*(?:to|-|\s)\s*(\d{4}-\d{2}-\d{2})/.match(s)
26
27
  if m
27
28
  self.new(*m.captures)
29
+ else
30
+ raise Exception, "Cannot parse date: '#{s}'"
28
31
  end
29
32
  end
30
33
  end
@@ -57,7 +60,16 @@ dr = DateRange.from '2007-01-01 2007-12-31'
57
60
  dr.start_date # => #<Date: 4908203/2,0,2299161>
58
61
  dr.end_date # => #<Date: 4908931/2,0,2299161>
59
62
 
60
- dr = DateRange '2008-01-01', '2007-12-31'
61
- dr.start_date # =>
62
- dr.end_date # =>
63
- # ~> -:60: #<DateRange:0xb7a52640 @end_date=#<Date: 4908931/2,0,2299161>, @start_date=#<Date: 4908933/2,0,2299161>> must have end_date >= start_date (Doodle::ValidationError)
63
+ p try {
64
+ dr = DateRange.from 'Hello World'
65
+ dr.start_date # =>
66
+ dr.end_date # =>
67
+ }
68
+
69
+ p try {
70
+ dr = DateRange '2008-01-01', '2007-12-31'
71
+ dr.start_date # =>
72
+ dr.end_date # =>
73
+ }
74
+ # >> #<Doodle::ConversionError: Cannot parse date: 'Hello World'>
75
+ # >> #<Doodle::ValidationError: DateRange must have end_date >= start_date>
@@ -0,0 +1,104 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $:.unshift(File.join(File.dirname(__FILE__), '.'))
3
+
4
+ require 'doodle'
5
+ require 'doodle/datatypes'
6
+ require 'net/smtp'
7
+ require 'time'
8
+ require 'datatypes'
9
+ require 'smtp_tls'
10
+
11
+ # note: translated from Florian Frank's example in dslkit [http://dslkit.rubyforge.org/]
12
+
13
+ class Mail < Doodle
14
+ doodle do
15
+ string :mail_server, :default => ENV['MAILSERVER'] || 'mail'
16
+ string :body
17
+ email :from do
18
+ default do
19
+ if ENV['USER']
20
+ ENV['USER'] + '@' + mail_server
21
+ else
22
+ 'from@example.com'
23
+ end
24
+ end
25
+ end
26
+ email :to
27
+ string :subject, :default => 'Test Email'
28
+ date :date do
29
+ default { Time.now.rfc2822 }
30
+ end
31
+ string :message_id do
32
+ default do
33
+ key = [ ENV['HOSTNAME'] || 'localhost', $$ , Time.now ].join
34
+ (::Digest::MD5.new << key).to_s
35
+ end
36
+ end
37
+ string :msg do
38
+ default do
39
+ [
40
+ "From: #{from}",
41
+ "To: #{to}",
42
+ "Subject: #{subject}",
43
+ "Date: #{date}",
44
+ "Message-Id: <#{message_id}@#{mail_server}>",
45
+ '',
46
+ body
47
+ ] * "\n"
48
+ end
49
+ end
50
+ end
51
+
52
+ def send_message
53
+ if true
54
+ puts msg
55
+ else
56
+ ::Net::SMTP.start(mail_server, 25) do |smtp|
57
+ smtp.send_message msg, from, to
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ require 'highline/import'
64
+ def prompt_for_password
65
+ ask("Enter your password: ") { |q| q.echo = '*' }
66
+ end
67
+
68
+ class GMail < Mail
69
+ has :mail_server, :default => 'smtp.gmail.com'
70
+ has :port, :default => 587
71
+ has :username, :default => 'sean.ohalpin@gmail.com'
72
+ has :password, :default => 'sesame'
73
+ # has :password do
74
+ # init do
75
+ # prompt_for_password
76
+ # end
77
+ # end
78
+ has :host, :default => 'localhost.localdomain'
79
+ has :message_format, :default => 'plain'
80
+
81
+ def send_message
82
+ puts msg
83
+ return
84
+ ::Net::SMTP.start(mail_server,
85
+ port,
86
+ host,
87
+ username,
88
+ password,
89
+ message_format) do |smtp|
90
+ smtp.send_message(msg, from, to)
91
+ end
92
+ end
93
+ end
94
+
95
+ GMail do
96
+ subject subject + ': Hi!'
97
+ to 'sean.ohalpin@gmail.com'
98
+ body <<BODY
99
+ Hi,
100
+
101
+ this is a test email from Ruby.
102
+
103
+ BODY
104
+ end.send_message
@@ -0,0 +1,85 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $:.unshift(File.join(File.dirname(__FILE__), '.'))
3
+ require 'doodle'
4
+ require 'doodle/rfc822'
5
+ require 'net/smtp'
6
+ require 'time'
7
+
8
+ # note: translated from Florian Frank's example in dslkit [http://dslkit.rubyforge.org/]
9
+
10
+ class Mail < Doodle
11
+ has :mail_server, :default => ENV['MAILSERVER'] || 'mail'
12
+ has :body, :kind => String
13
+
14
+ has :from, :kind => String do
15
+ default do
16
+ if ENV['USER']
17
+ ENV['USER'] + '@' + mail_server
18
+ else
19
+ 'from@example.com'
20
+ end
21
+ end
22
+ must 'be valid email address' do |s|
23
+ s =~ RFC822::EmailAddress
24
+ end
25
+ end
26
+
27
+ has :to, :kind => String do
28
+ must 'be valid email address' do |s|
29
+ s =~ RFC822::EmailAddress
30
+ end
31
+ end
32
+ has :subject, :default => 'Test Email'
33
+ has :date do
34
+ default { Time.now.rfc2822 }
35
+ end
36
+ has :message_id do
37
+ default do
38
+ key = [ ENV['HOSTNAME'] || 'localhost', $$ , Time.now ].join
39
+ (::Digest::MD5.new << key).to_s
40
+ end
41
+ end
42
+ has :msg, :kind => String do
43
+ default do
44
+ [
45
+ "From: #{from}",
46
+ "To: #{to}",
47
+ "Subject: #{subject}",
48
+ "Date: #{date}",
49
+ "Message-Id: <#{message_id}@#{mail_server}>",
50
+ '',
51
+ body
52
+ ] * "\n"
53
+ end
54
+ end
55
+
56
+ def send
57
+ if true
58
+ puts msg
59
+ else
60
+ ::Net::SMTP.start(mail_server, 25) do |smtp|
61
+ smtp.send_message msg, from, to
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ def mail(&block)
68
+ Mail.new(&block)
69
+ end
70
+
71
+ def prompt
72
+ return 'someone@example.com'
73
+ STDOUT.print "Send to? "
74
+ STDOUT.flush
75
+ STDIN.gets.strip
76
+ end
77
+
78
+ m = Mail do
79
+ subject subject + ': Hi!'
80
+ if rcpt = prompt
81
+ to rcpt
82
+ end
83
+ body "Hello, world!\n"
84
+ end
85
+ m.send
@@ -0,0 +1,40 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'doodle'
3
+ require 'yaml'
4
+
5
+ class Child < Doodle
6
+ has :name
7
+ has :dad do
8
+ # I'm treating block arguments and Proc object (proc/lambda) arguments
9
+ # to :init differently:
10
+ # - a proc/lamba is treated as a literal argument, i.e. the
11
+ # - value is set to a Proc
12
+ # - a block argument, on the other hand, is instance
13
+ # - evaluated during initialization
14
+ # - consequences
15
+ # - can only be done in init block
16
+ # - somewhat subtle difference (from programmer's point of
17
+ # - view) between a proc and a block
18
+
19
+ # Also note re: Doodle.parent - its value is only valid
20
+ # during initialization - this is a way to capture that
21
+ # value for ues later
22
+
23
+ init do
24
+ parent
25
+ end
26
+ end
27
+ end
28
+
29
+ class Parent < Child
30
+ has :children, :collect => Child
31
+ end
32
+
33
+ parent = Parent 'Conn' do
34
+ child 'Sean'
35
+ end
36
+
37
+ puts parent.to_yaml
38
+
39
+
40
+
@@ -0,0 +1,67 @@
1
+ require 'lib/doodle'
2
+
3
+ module CommandLine
4
+ class Base < Doodle::Base
5
+ has :name
6
+ singleton_class do
7
+ has :doc
8
+ end
9
+ def to_s
10
+ name
11
+ end
12
+ end
13
+ class Command < Base
14
+ end
15
+ class KeyValue < Base
16
+ # specify order (should I need to do this?)
17
+ has :name
18
+ has :value
19
+ def to_s
20
+ %[--#{name}="#{value}"]
21
+ end
22
+ end
23
+ class Flag < Base
24
+ def to_s
25
+ %[--#{name}]
26
+ end
27
+ end
28
+ end
29
+
30
+ module Zenity
31
+ include CommandLine
32
+ class Entry < Flag
33
+ # specifying name here has effect of re-ordering positional args
34
+ doc "Display text entry dialogue"
35
+ has :name, :default => :entry
36
+ end
37
+ class Text < KeyValue
38
+ doc "Set the dialogue text"
39
+ has :name, :default => :text
40
+ end
41
+ class EntryText < KeyValue
42
+ doc "Set the entry text"
43
+ has :name, :default => 'entry-text'
44
+ end
45
+ class HideText < KeyValue
46
+ doc "Hide the entry text"
47
+ has :name, :default => 'hide-text'
48
+ end
49
+ end
50
+
51
+ include Zenity
52
+
53
+ 1.upto(100) do
54
+ cmd = [
55
+ Command.new("zenity"),
56
+ Entry.new(),
57
+ # KeyValue.new("text", "Enter name:"),
58
+ # KeyValue.new(:name => "text", :value => "Enter name:"),
59
+ # Text.new(:value => "Enter name:"),
60
+ Text.new(:value => "Enter name:"),
61
+ EntryText.new(:value => "Enter text"),
62
+ ].join(' ')
63
+ #puts cmd
64
+ end
65
+ #result = `#{cmd}`
66
+ #puts "result=#{result}"
67
+
@@ -0,0 +1,65 @@
1
+ require "openssl"
2
+ require "net/smtp"
3
+
4
+ Net::SMTP.class_eval do
5
+ private
6
+ def do_start(helodomain, user, secret, authtype)
7
+ raise IOError, 'SMTP session already started' if @started
8
+ check_auth_args user, secret, authtype if user or secret
9
+
10
+ sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
11
+ @socket = Net::InternetMessageIO.new(sock)
12
+ @socket.read_timeout = 60 #@read_timeout
13
+
14
+ check_response(critical { recv_response() })
15
+ do_helo(helodomain)
16
+
17
+ if starttls
18
+ raise 'openssl library not installed' unless defined?(OpenSSL)
19
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
20
+ ssl.sync_close = true
21
+ ssl.connect
22
+ @socket = Net::InternetMessageIO.new(ssl)
23
+ @socket.read_timeout = 60 #@read_timeout
24
+ do_helo(helodomain)
25
+ end
26
+
27
+ authenticate user, secret, authtype if user
28
+ @started = true
29
+ ensure
30
+ unless @started
31
+ # authentication failed, cancel connection.
32
+ @socket.close if not @started and @socket and not @socket.closed?
33
+ @socket = nil
34
+ end
35
+ end
36
+
37
+ def do_helo(helodomain)
38
+ begin
39
+ if @esmtp
40
+ ehlo helodomain
41
+ else
42
+ helo helodomain
43
+ end
44
+ rescue Net::ProtocolError
45
+ if @esmtp
46
+ @esmtp = false
47
+ @error_occured = false
48
+ retry
49
+ end
50
+ raise
51
+ end
52
+ end
53
+
54
+ def starttls
55
+ getok('STARTTLS') rescue return false
56
+ return true
57
+ end
58
+
59
+ def quit
60
+ begin
61
+ getok('QUIT')
62
+ rescue EOFError
63
+ end
64
+ end
65
+ end