tinkit 0.0.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 (51) hide show
  1. data/LICENSE +176 -0
  2. data/README +11 -0
  3. data/Rakefile +75 -0
  4. data/lib/glue_envs/couchrest/couchrest_attachment_handler.rb +260 -0
  5. data/lib/glue_envs/couchrest/couchrest_files_mgr.rb +198 -0
  6. data/lib/glue_envs/couchrest_glue_env.rb +536 -0
  7. data/lib/glue_envs/files_mgr_base.rb +51 -0
  8. data/lib/glue_envs/filesystem/filesystem_files_mgr.rb +187 -0
  9. data/lib/glue_envs/filesystem_glue_env.rb +395 -0
  10. data/lib/glue_envs/mysql/mysql_files_mgr.rb +175 -0
  11. data/lib/glue_envs/mysql_glue_env.rb +428 -0
  12. data/lib/glue_envs/sdb_s3/sdb_s3_files_mgr.rb +314 -0
  13. data/lib/glue_envs/sdb_s3_glue_env.rb +248 -0
  14. data/lib/helpers/camel.rb +21 -0
  15. data/lib/helpers/filesystem_helpers.rb +27 -0
  16. data/lib/helpers/hash_helpers.rb +74 -0
  17. data/lib/helpers/log_helper.rb +34 -0
  18. data/lib/helpers/mime_types_new.rb +126 -0
  19. data/lib/helpers/old_more_open_struct.rb +28 -0
  20. data/lib/helpers/require_helper.rb +45 -0
  21. data/lib/helpers/tk_escape.rb +17 -0
  22. data/lib/midas/bufs_data_structure.rb +84 -0
  23. data/lib/midas/node_element_operations.rb +264 -0
  24. data/lib/tinkit.rb +38 -0
  25. data/lib/tinkit_base_node.rb +733 -0
  26. data/lib/tinkit_node_factory.rb +47 -0
  27. data/spec/couchrest_files_mgr_spec.rb +551 -0
  28. data/spec/couchrest_glue_spec.rb +246 -0
  29. data/spec/filesystem_files_mgr_spec.rb +236 -0
  30. data/spec/filesystem_glue_spec.rb +243 -0
  31. data/spec/filesystem_helpers_spec.rb +42 -0
  32. data/spec/helpers/bufs_node_builder.rb +17 -0
  33. data/spec/helpers/bufs_sample_dataset.rb +160 -0
  34. data/spec/helpers/bufs_test_environments.rb +81 -0
  35. data/spec/helpers/tmp_view_cleaner.rb +15 -0
  36. data/spec/lib_helpers/tk_escape_spec.rb +45 -0
  37. data/spec/mysql_files_mgr_spec.rb +250 -0
  38. data/spec/mysql_glue_spec.rb +214 -0
  39. data/spec/node_element_operations_spec.rb +392 -0
  40. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec1.rb +82 -0
  41. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec2.rb +68 -0
  42. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec3.rb +80 -0
  43. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec4.rb +110 -0
  44. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec5.rb +84 -0
  45. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec6.rb +83 -0
  46. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec7.rb +101 -0
  47. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec8.rb +92 -0
  48. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec_all.rb +266 -0
  49. data/spec/sdb_s3_glue_spec.rb +230 -0
  50. data/spec/tinkit_node_factory_spec.rb +1108 -0
  51. metadata +114 -0
@@ -0,0 +1,21 @@
1
+ #copy of Rails camelize and underscore (almost)
2
+
3
+ module Camel
4
+ def self.ize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
5
+ if first_letter_in_uppercase
6
+ lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
7
+ else
8
+ lower_case_and_underscored_word.first + camelize(lower_case_and_underscored_word)[1..-1]
9
+ end
10
+ end
11
+
12
+ def self.score(camel_cased_word)
13
+ word = camel_cased_word.to_s.dup
14
+ word.gsub!(/::/, '_') #except I changed '/' to '_'
15
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
16
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
17
+ word.tr!("-", "_")
18
+ word.downcase!
19
+ word
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+
2
+ class DirFilter
3
+ def initialize(ignore_list)
4
+ @ignore_list = [ignore_list].flatten
5
+ @ignore_list << /^\./ #ignore dot files
6
+ end
7
+
8
+
9
+ def filter_entries(path)
10
+ wkg_entries = Dir.entries(path)
11
+ #remove dot files
12
+ wkg_entires = wkg_entries.delete_if{|entry| in_ignore_list?(entry) }
13
+ end
14
+
15
+ private
16
+ def in_ignore_list?(entry)
17
+ in_ignore = @ignore_list.map{|list| true if entry =~ list}
18
+ in_ignore.compact.first #nil if nothing in ignore
19
+ end
20
+ end
21
+
22
+ class FileNames
23
+ def flatten_problem_chars(filenames)
24
+ #via http://stackoverflow.com/questions/2270635/invalid-chars-filter-for-file-folder-name-ruby
25
+ file_names.map! { |f| f.gsub(/[\x00\/\\:\*\?\"<>\|]/, '_') }
26
+ end
27
+ end
@@ -0,0 +1,74 @@
1
+ require 'ostruct'
2
+
3
+ #from Facets via Hashery
4
+ class Hash
5
+
6
+
7
+
8
+ def rekey!(*args, &block)
9
+ # for backward comptability (TODO: DEPRECATE).
10
+ block = args.pop.to_sym.to_proc if args.size == 1
11
+ if args.empty?
12
+ block = lambda{|k| k.to_sym} unless block
13
+ keys.each do |k|
14
+ nk = block[k]
15
+ self[nk]=delete(k) if nk
16
+ end
17
+ else
18
+ raise ArgumentError, "3 for 2" if block
19
+ to, from = *args
20
+ self[to] = self.delete(from) if self.has_key?(from)
21
+ end
22
+ self
23
+ end
24
+
25
+ def rekey(*args, &block)
26
+ dup.rekey!(*args, &block)
27
+ end
28
+
29
+ public :rekey, :rekey!
30
+ end
31
+
32
+ module HashKeys
33
+ def self.str_to_sym(a_hash)
34
+ raise "#{a_hash.class.name} must respond to inject" unless a_hash.respond_to? :inject
35
+ a_hash.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
36
+ end
37
+
38
+ def self.sym_to_str(a_hash) #inverse of above
39
+ raise "#{a_hash.class.name} must respond to inject" unless a_hash.respond_to? :inject
40
+ a_hash.inject({}){|memo,(k,v)| memo["#{k}"] = v; memo}
41
+ end
42
+ end
43
+
44
+ module HashOps
45
+ def self.remove_hash(other_hash)
46
+ delete_if { |k,v| other_hash[k] == v }
47
+ end
48
+ end
49
+
50
+ class MoreOpenStruct < OpenStruct
51
+ def _to_hash
52
+ h = @table
53
+ #handles nested structures
54
+ h.each do |k,v|
55
+ if v.class == MoreOpenStruct
56
+ h[k] = v._to_hash
57
+ end
58
+ end
59
+ return h
60
+ end
61
+
62
+ def _table
63
+ @table #table is the hash structure used in OpenStruct
64
+ end
65
+
66
+ def _manual_set(hash)
67
+ if hash && (hash.class == Hash)
68
+ for k,v in hash
69
+ @table[k.to_sym] = v
70
+ new_ostruct_member(k)
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,34 @@
1
+ require 'log4r'
2
+
3
+ #Set Logger
4
+ #TODO: Create spec
5
+ module TinkitLog
6
+ include Log4r
7
+
8
+ class << self; attr_accessor :default_level, :fatal_log, :log_output end
9
+ TinkitLog.default_level = :info
10
+ TinkitLog.log_output = 'stdout'
11
+ TinkitLog.fatal_log = Logger.new('fatal_log')
12
+ TinkitLog.fatal_log.level = FATAL
13
+ TinkitLog.fatal_log.outputters = Outputter[TinkitLog.log_output]
14
+
15
+ @@log_levels = { :debug => DEBUG,
16
+ :info => INFO,
17
+ :warn => WARN,
18
+ :error => ERROR,
19
+ :fatal => FATAL
20
+ }
21
+
22
+ def self.set(name, level=TinkitLog.default_level, out=Outputter.stdout)
23
+ log = Logger[name] || Logger.new(name)
24
+ log.outputters = out
25
+ log.level = @@log_levels[level]
26
+ log.trace = true if log.level <= DEBUG
27
+ log
28
+ end
29
+
30
+ def self.log_raise(error_msg, exc_type= RuntimeError)
31
+ self.fatal_log.fatal("#{__LINE__} #{error_msg}")
32
+ raise exc_type, error_msg
33
+ end
34
+ end
@@ -0,0 +1,126 @@
1
+ #Copyright (C) 2010 David Martin
2
+ #
3
+ #David Martin mailto:dmarti21@gmail.com
4
+
5
+
6
+ require 'mime/types'
7
+
8
+ #This class will include the Office 2007 extension types when looking up MIME types.
9
+ class MimeNew
10
+
11
+ DefaultUnknownContentType = "application/octet-stream"
12
+ #Returns the mime type of a file
13
+ # MimeNew.for_ofc_x('a_new_word_doc.docx')
14
+ # #=> "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
15
+ def self.for_ofc_x(fname)
16
+ cont_type = nil
17
+ old_ext = File.extname(fname)
18
+ cont_type =case old_ext
19
+ #New Office Formats
20
+ when '.docx'
21
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]
22
+ when '.dotx'
23
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.template"]
24
+ when '.pptx'
25
+ ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]
26
+ when '.ppsx'
27
+ ["application/vnd.openxmlformats-officedocument.presentationml.slideshow"]
28
+ when '.potx'
29
+ ["application/vnd.openxmlformats-officedocument.presentationml.template"]
30
+ when '.xlsx'
31
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]
32
+ when '.xltx'
33
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.template"]
34
+ else
35
+ self.other_content_types(fname)
36
+ end#case
37
+ cont_type = [cont_type].flatten.first
38
+ #puts "Content Type returned: #{cont_type.inspect}"
39
+ return cont_type
40
+ end# def
41
+
42
+ def self.just_ofc_x(ext)
43
+ cont_type = case File.extname(fname)
44
+ #New Office Formats
45
+ when '.docx'
46
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]
47
+ when '.dotx'
48
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.template"]
49
+ when '.pptx'
50
+ ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]
51
+ when '.ppsx'
52
+ ["application/vnd.openxmlformats-officedocument.presentationml.slideshow"]
53
+ when '.potx'
54
+ ["application/vnd.openxmlformats-officedocument.presentationml.template"]
55
+ when '.xlsx'
56
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]
57
+ when '.xltx'
58
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.template"]
59
+ end
60
+ end
61
+
62
+ def self.other_content_types(fname)
63
+ std_type = MIME::Types.type_for(fname).first
64
+ rtn = if std_type
65
+ std_type.content_type
66
+ else
67
+ DefaultUnknownContentType
68
+ end
69
+ return rtn
70
+ end#def
71
+ end
72
+
73
+
74
+ #duck punching RestClient's duck punch for bufs because libraries are using MIME::Types directly
75
+ =begin
76
+ module MIME
77
+ class Types
78
+
79
+ # Return the first found content-type for a value considered as an extension or the value itself
80
+ def type_for_extension ext
81
+ puts "Duck Punch ext: #{ext.inspect}"
82
+ candidates = @extension_index[ext]
83
+ puts "Duck Punch candidates: #{candidates.inspect}"
84
+ candidates.empty? ? ext : candidates[0].content_type
85
+ end
86
+ end
87
+ end
88
+ =end
89
+ =begin
90
+ class MIME::Types
91
+ def type_for(filename, platform = false)
92
+ puts "Duck Punched MIME::Types"
93
+ puts "--filename: #{filename.inspect}"
94
+
95
+ ext = filename.chomp.downcase.gsub(/.*\./o, '')
96
+ list = @extension_index[ext]
97
+ list.delete_if { |e| not e.platform? } if platform
98
+ list
99
+
100
+ new_ext = File.extname(filename)
101
+ cont_type =case new_ext
102
+ #New Office Formats
103
+ when '.docx'
104
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"]
105
+ when '.dotx'
106
+ ["application/vnd.openxmlformats-officedocument.wordprocessingml.template"]
107
+ when '.pptx'
108
+ ["application/vnd.openxmlformats-officedocument.presentationml.presentation"]
109
+ when '.ppsx'
110
+ ["application/vnd.openxmlformats-officedocument.presentationml.slideshow"]
111
+ when '.potx'
112
+ ["application/vnd.openxmlformats-officedocument.presentationml.template"]
113
+ when '.xlsx'
114
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]
115
+ when '.xltx'
116
+ ["application/vnd.openxmlformats-officedocument.spreadsheetml.template"]
117
+ end
118
+
119
+ puts "Duck New Cont Type: #{cont_type.inspect}"
120
+ (list + cont_type).compact! if cont_type
121
+ puts "Duck Mime Extension: #{ext.inspect}"
122
+ puts "Duck Content Types: #{ list.map{|m| m.content_type} }"
123
+ list
124
+ end
125
+ end
126
+ =end
@@ -0,0 +1,28 @@
1
+ require 'ostruct'
2
+
3
+ class MoreOpenStruct < OpenStruct
4
+ def _to_hash
5
+ h = @table
6
+ #handles nested structures
7
+ h.each do |k,v|
8
+ if v.class == MoreOpenStruct
9
+ h[k] = v._to_hash
10
+ end
11
+ end
12
+ return h
13
+ end
14
+
15
+ def _table
16
+ @table #table is the hash structure used in OpenStruct
17
+ end
18
+
19
+ def _manual_set(hash)
20
+ if hash && (hash.class == Hash)
21
+ for k,v in hash
22
+ @table[k.to_sym] = v
23
+ new_ostruct_member(k)
24
+ end
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,45 @@
1
+ #Tinkit Library Locations
2
+ module Tinkit
3
+ @@top = File.join(File.dirname(__FILE__), '../..') #main bufs directory
4
+ @@lib = File.join(@@top, 'lib/')
5
+ @@helpers = File.join(@@top, 'lib/helpers/')
6
+ @@moabs = File.join(@@lib, 'moabs')
7
+ @@midas = File.join(@@lib, 'midas')
8
+ @@glue = File.join(@@lib, 'glue_envs')
9
+ @@specs = File.join(@@top, 'spec')
10
+ @@spec_helpers = File.join(@@specs, 'helpers')
11
+ @@fixtures = File.join(@@top, 'bufs_fixtures')
12
+
13
+ def self.lib(req_file)
14
+ File.expand_path(File.join(@@lib, req_file))
15
+ end
16
+
17
+ def self.helpers(req_file)
18
+ File.expand_path(File.join(@@helpers, req_file))
19
+ end
20
+
21
+ def self.spec(req_file)
22
+ File.expand_path(File.join(@@specs, req_file))
23
+ end
24
+
25
+ def self.spec_helpers(req_file)
26
+ File.expand_path(File.join(@@spec_helpers, req_file))
27
+ end
28
+
29
+ def self.fixtures(req_file)
30
+ File.expand_path(File.join(@@fixtures, req_file))
31
+ end
32
+
33
+ def self.moabs(req_file)
34
+ File.expand_path(File.join(@@moabs, req_file))
35
+ end
36
+
37
+ def self.midas(req_file)
38
+ File.expand_path(File.join(@@midas, req_file))
39
+ end
40
+
41
+ def self.glue(req_file)
42
+ File.expand_path(File.join(@@glue, req_file))
43
+ end
44
+ end
45
+
@@ -0,0 +1,17 @@
1
+ require 'cgi' #Can replace with url_escape if performance is an issue
2
+
3
+ class TkEscape
4
+ def self.escape(str)
5
+ esc_str = str.gsub(/([^a-zA-Z0-9_.-]+)/n, '_')
6
+ #str.gsub!('+', ' ')
7
+ #str = CGI.escape(str)
8
+ #str.gsub!('%2B', '+')
9
+ return esc_str
10
+ end
11
+
12
+ #TODO: Continue using cgi or create unescape specific to Tinkit?
13
+ def self.unescape(str)
14
+ return CGI.unescape(str)
15
+ end
16
+ end
17
+
@@ -0,0 +1,84 @@
1
+ module DataStructureModels
2
+ module Tinkit
3
+ #Required Keys on instantiation
4
+ RequiredInstanceKeys = [:my_category]
5
+ RequiredSaveKeys = [:my_category] #duplicative?
6
+ NodeKey = :my_category #TODO look at supporting multiple node keys
7
+ end
8
+ end
9
+
10
+ =begin
11
+ module NodeElementOperations
12
+ #TODO the hash inside the proc is confusing (the curly braces) update to better readability
13
+ MyCategoryAddOp = lambda {|this,other| Hash[:update_this => this] } #my cat is not allowed to change
14
+ MyCategorySubtractOp = lambda{ |this, other| Hash[:update_this => this] } #TODO use this to delete a node?
15
+ MyCategoryOps = {:add => MyCategoryAddOp, :subtract => MyCategorySubtractOp}
16
+ ParentCategoryAddOp = lambda {|this,other|
17
+ this = this || []
18
+ other = other || []
19
+ this = this + [other].flatten
20
+ this.uniq!; this.compact!
21
+ Hash[:update_this => this]
22
+ }
23
+ ParentCategorySubtractOp = lambda {|this,other|
24
+ this = [this] || []
25
+ other = [other] || []
26
+ this.flatten!
27
+ other.flatten!
28
+ this -= other
29
+ this.uniq!
30
+ this.compact!
31
+ Hash[:update_this => this]
32
+ }
33
+ ParentCategoryOps = {:add => ParentCategoryAddOp, :subtract => ParentCategorySubtractOp}
34
+ LinkAddOp = lambda {|this, other|
35
+ this = this || {} #investigate why its passed as nil (probably hasn't been built yet
36
+ other = other || {}
37
+ srcs = other.keys
38
+ srcs.each {|s| if this[s]
39
+ #this[s] = [ other[s] ].flatten
40
+ this[s] = other[s]
41
+ else
42
+ #this[s] = [ other[s] ].flatten
43
+ this[s] = other[s]
44
+ end }
45
+ #this[s].uniq!
46
+ #this[s].compact! }
47
+ Hash[:update_this => this] }
48
+ #if link_name is used besides other, then all link_names would need to be unique, so we use other
49
+ LinkSubtractOp = lambda {|this, other| this = this || {}
50
+ #Hacked together needs thought out (and TESTED!!)
51
+ other = other || {}
52
+ puts "This / Other: #{this.inspect} / #{other.inspect}"
53
+ #srcs = [other].flatten
54
+ other.keys.each { |s|
55
+ #other[s].each {|olnk| this[s].delete(olnk) if this[s]}
56
+ puts "delete #{other[s].inspect} from #{this[s].inspect}"
57
+ #this[s].delete(other[s]) if this[s]
58
+ this.delete(s)
59
+ #this.delete(s) if (this[s].nil? || this[s].empty?)
60
+ }
61
+ Hash[:update_this => this]
62
+ }
63
+ #think if this is what you want, returning a single uri if only one exists, while an array if more than one?
64
+ #I think so since it's *almost* an error case if more than one url exists for a name, but I'm not sure this is the best approach
65
+ LinkGetOp = lambda {|this, link_name|
66
+ this_ary = this.to_a
67
+ rtn_val = nil
68
+ rtn_val = if this_ary.flatten.include? link_name
69
+ srcs = []
70
+ this_ary.each { |s, ls| srcs << s if ls.include? link_name }
71
+ rtn_val = {:return_value => srcs, :update_this => this } if srcs.size > 1
72
+ rtn_val = {:return_value => srcs.first, :update_this => this } if srcs.size == 1
73
+ rtn_val
74
+ else
75
+ rtn_val = {:return_value => nil, :update_this => this}
76
+ end
77
+ rtn_val
78
+ }
79
+
80
+ LinkOps = {:add => LinkAddOp, :subtract => LinkSubtractOp, :get => LinkGetOp}
81
+
82
+ Ops = {:my_category => MyCategoryOps, :parent_categories => ParentCategoryOps, :links => LinkOps}
83
+ end
84
+ =end