parallel588_google_drive 0.3.3

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.
data/README.rdoc ADDED
@@ -0,0 +1,91 @@
1
+ This is a Ruby 1.8/1.9 library to read/write files/spreadsheets in Google Drive/Docs.
2
+
3
+ NOTE: This is NOT a library to create Google Drive App.
4
+
5
+
6
+ = How to install
7
+
8
+ $ sudo gem install google_drive
9
+
10
+
11
+ = How to use
12
+
13
+ Example to read/write files in Google Drive:
14
+
15
+ require "rubygems"
16
+ require "google_drive"
17
+
18
+ # Logs in.
19
+ # You can also use OAuth. See document of
20
+ # GoogleDrive.login_with_oauth for details.
21
+ session = GoogleDrive.login("username@gmail.com", "mypassword")
22
+
23
+ # Gets list of remote files.
24
+ for file in session.files
25
+ p file.title
26
+ end
27
+
28
+ # Uploads a local file.
29
+ session.upload_from_file("/path/to/hello.txt", "hello.txt", :convert => false)
30
+
31
+ # Downloads to a local file.
32
+ file = session.file_by_title("hello.txt")
33
+ file.download_to_file("/path/to/hello.txt")
34
+
35
+ # Updates content of the remote file.
36
+ file.update_from_file("/path/to/hello.txt")
37
+
38
+ Example to read/write spreadsheets:
39
+
40
+ require "rubygems"
41
+ require "google_drive"
42
+
43
+ # Logs in.
44
+ # You can also use OAuth. See document of
45
+ # GoogleDrive.login_with_oauth for details.
46
+ session = GoogleDrive.login("username@gmail.com", "mypassword")
47
+
48
+ # First worksheet of
49
+ # https://docs.google.com/spreadsheet/ccc?key=pz7XtlQC-PYx-jrVMJErTcg
50
+ ws = session.spreadsheet_by_key("pz7XtlQC-PYx-jrVMJErTcg").worksheets[0]
51
+
52
+ # Gets content of A2 cell.
53
+ p ws[2, 1] #==> "hoge"
54
+
55
+ # Changes content of cells.
56
+ # Changes are not sent to the server until you call ws.save().
57
+ ws[2, 1] = "foo"
58
+ ws[2, 2] = "bar"
59
+ ws.save()
60
+
61
+ # Dumps all cells.
62
+ for row in 1..ws.num_rows
63
+ for col in 1..ws.num_cols
64
+ p ws[row, col]
65
+ end
66
+ end
67
+
68
+ # Yet another way to do so.
69
+ p ws.rows #==> [["fuga", ""], ["foo", "bar]]
70
+
71
+ # Reloads the worksheet to get changes by other clients.
72
+ ws.reload()
73
+
74
+ API document: http://gimite.net/doc/google-drive-ruby/
75
+
76
+
77
+ = Source code
78
+
79
+ http://github.com/gimite/google-drive-ruby
80
+
81
+ The license of this source is "New BSD Licence"
82
+
83
+
84
+ = Supported environments
85
+
86
+ Ruby 1.8.x and Ruby 1.9.x. Checked with Ruby 1.8.7 and Ruby 1.9.3.
87
+
88
+
89
+ = Author
90
+
91
+ Hiroshi Ichikawa - http://gimite.net/en/index.php?Contact
@@ -0,0 +1,20 @@
1
+ module GoogleDrive
2
+
3
+ class Acl
4
+
5
+ # Returns the number of entries.
6
+ def size
7
+ end
8
+
9
+ # Returns GoogleDrive::AclEntry object at +index+.
10
+ def [](index)
11
+ end
12
+
13
+ # Iterates over GoogleDrive::AclEntry objects.
14
+ def each(&block)
15
+ yield(entry)
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,33 @@
1
+ module GoogleDrive
2
+
3
+ class AclEntry
4
+
5
+ # Type of the scope. One of:
6
+ #
7
+ # - "user": scope is a user's email address.
8
+ # - "group": scope is a Google Group email address.
9
+ # - "domain": scope is a Google Apps domain.
10
+ # - "default": Publicly shared with all users. scope is +nil+.
11
+ attr_reader(:scope_type)
12
+
13
+ # The scope. See scope_type.
14
+ attr_reader(:scope)
15
+
16
+ # The role given to the scope. One of:
17
+ # - "owner": The owner.
18
+ # - "writer": With read/write access.
19
+ # - "reader": With read-only access.
20
+ attr_reader(:role)
21
+
22
+ # Title of the entry.
23
+ attr_reader(:title)
24
+
25
+ # Edit URL of the entry.
26
+ attr_reader(:edit_url)
27
+
28
+ # E-tag of the entry.
29
+ attr_reader(:etag)
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,115 @@
1
+ # Author: Guy Boertje <https://github.com/guyboertje>
2
+ # Author: David R. Albrecht <https://github.com/eldavido>
3
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
4
+ # The license of this source is "New BSD Licence"
5
+
6
+ require "google_drive/acl_entry"
7
+
8
+ module GoogleDrive
9
+
10
+ # ACL (access control list) of a spreadsheet.
11
+ #
12
+ # Use GoogleDrive::Spreadsheet#acl to get GoogleDrive::Acl object.
13
+ # See GoogleDrive::Spreadsheet#acl for usage example.
14
+ #
15
+ # This code is based on https://github.com/guyboertje/gdata-spreadsheet-ruby .
16
+ class Acl
17
+
18
+ include(Util)
19
+ extend(Forwardable)
20
+
21
+ def initialize(session, acls_feed_url) #:nodoc:
22
+ @session = session
23
+ @acls_feed_url = acls_feed_url
24
+ header = {"GData-Version" => "3.0"}
25
+ doc = @session.request(:get, @acls_feed_url, :header => header, :auth => :writely)
26
+ @acls = doc.css("entry").map(){ |e| AclEntry.new(entry_to_params(e)) }
27
+ end
28
+
29
+ def_delegators(:@acls, :size, :[], :each)
30
+
31
+ # Adds a new entry. +entry+ is either a GoogleDrive::AclEntry or a Hash with keys
32
+ # :scope_type, :scope and :role. See GoogleDrive::AclEntry#scope_type and
33
+ # GoogleDrive::AclEntry#role for the document of the fields.
34
+ #
35
+ # NOTE: This sends email to the new people.
36
+ #
37
+ # e.g.
38
+ # # A specific user can read or write.
39
+ # spreadsheet.acl.push(
40
+ # {:scope_type => "user", :scope => "example2@gmail.com", :role => "reader"})
41
+ # spreadsheet.acl.push(
42
+ # {:scope_type => "user", :scope => "example3@gmail.com", :role => "writer"})
43
+ # # Publish on the Web.
44
+ # spreadsheet.acl.push(
45
+ # {:scope_type => "default", :role => "reader"})
46
+ # # Anyone who knows the link can read.
47
+ # spreadsheet.acl.push(
48
+ # {:scope_type => "default", :with_key => true, :role => "reader"})
49
+ def push(entry)
50
+
51
+ entry = AclEntry.new(entry) if entry.is_a?(Hash)
52
+
53
+ header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
54
+ doc = @session.request(
55
+ :post, @acls_feed_url, :data => entry.to_xml(), :header => header, :auth => :writely)
56
+
57
+ entry.params = entry_to_params(doc.root)
58
+ @acls.push(entry)
59
+ return entry
60
+
61
+ end
62
+
63
+ # Deletes an ACL entry.
64
+ #
65
+ # e.g.
66
+ # spreadsheet.acl.delete(spreadsheet.acl[1])
67
+ def delete(entry)
68
+ header = {"GData-Version" => "3.0"}
69
+ @session.request(:delete, entry.edit_url, :header => header, :auth => :writely)
70
+ @acls.delete(entry)
71
+ end
72
+
73
+ def update_role(entry, role) #:nodoc:
74
+
75
+ header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
76
+ doc = @session.request(
77
+ :put, entry.edit_url, :data => entry.to_xml(), :header => header, :auth => :writely)
78
+
79
+ entry.params = entry_to_params(doc.root)
80
+ return entry
81
+
82
+ end
83
+
84
+ def inspect
85
+ return "\#<%p %p>" % [self.class, @acls]
86
+ end
87
+
88
+ private
89
+
90
+ def entry_to_params(entry)
91
+
92
+ if !entry.css("gAcl|withKey").empty?
93
+ with_key = true
94
+ role = entry.css("gAcl|withKey gAcl|role")[0]["value"]
95
+ else
96
+ with_key = false
97
+ role = entry.css("gAcl|role")[0]["value"]
98
+ end
99
+
100
+ return {
101
+ :acl => self,
102
+ :scope_type => entry.css("gAcl|scope")[0]["type"],
103
+ :scope => entry.css("gAcl|scope")[0]["value"],
104
+ :with_key => with_key,
105
+ :role => role,
106
+ :title => entry.css("title").text,
107
+ :edit_url => entry.css("link[rel='edit']")[0]["href"],
108
+ :etag => entry["etag"],
109
+ }
110
+
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,89 @@
1
+ # Author: Guy Boertje <https://github.com/guyboertje>
2
+ # Author: David R. Albrecht <https://github.com/eldavido>
3
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
4
+ # Author: Phuogn Nguyen <https://github.com/phuongnd08>
5
+ # The license of this source is "New BSD Licence"
6
+
7
+ module GoogleDrive
8
+
9
+ # An entry of an ACL (access control list) of a spreadsheet.
10
+ #
11
+ # Use GoogleDrive::Acl#[] to get GoogleDrive::AclEntry object.
12
+ #
13
+ # This code is based on https://github.com/guyboertje/gdata-spreadsheet-ruby .
14
+ class AclEntry
15
+
16
+ include(Util)
17
+
18
+ PARAM_NAMES = [:acl, :scope_type, :scope, :with_key, :role, :title, :edit_url, :etag] #:nodoc:
19
+
20
+ # +params+ is a Hash object with keys +:scope_type+, +:scope+ and +:role+.
21
+ # See scope_type and role for the document of the fields.
22
+ def initialize(params)
23
+ @params = {:role => "reader"}
24
+ for name, value in params
25
+ if !name.is_a?(Symbol)
26
+ raise(ArgumentError, "Key must be Symbol, but is %p" % name)
27
+ elsif !PARAM_NAMES.include?(name)
28
+ raise(ArgumentError, "Invalid key: %p" % name)
29
+ end
30
+ @params[name] = value
31
+ end
32
+ end
33
+
34
+ attr_accessor(:params) #:nodoc:
35
+
36
+ PARAM_NAMES.each() do |name|
37
+ define_method(name) do
38
+ return @params[name]
39
+ end
40
+ end
41
+
42
+ # Changes the role of the scope.
43
+ #
44
+ # e.g.
45
+ # spreadsheet.acl[1].role = "writer"
46
+ def role=(role)
47
+ @params[:acl].update_role(self, role)
48
+ end
49
+
50
+ def inspect
51
+ return "\#<%p scope_type=%p, scope=%p, with_key=%p, role=%p>" %
52
+ [self.class, @params[:scope_type], @params[:scope], @params[:with_key], @params[:role]]
53
+ end
54
+
55
+ def to_xml() #:nodoc:
56
+
57
+ etag_attr = self.etag ? "gd:etag='#{h(self.etag)}'" : ""
58
+ value_attr = self.scope ? "value='#{h(self.scope)}'" : ""
59
+ if self.with_key
60
+ role_tag = <<-EOS
61
+ <gAcl:withKey key='[ACL KEY]'>
62
+ <gAcl:role value='#{h(self.role)}'/>
63
+ </gAcl:withKey>
64
+ EOS
65
+ else
66
+ role_tag = <<-EOS
67
+ <gAcl:role value='#{h(self.role)}'/>
68
+ EOS
69
+ end
70
+
71
+ return <<-EOS
72
+ <entry
73
+ xmlns='http://www.w3.org/2005/Atom'
74
+ xmlns:gAcl='http://schemas.google.com/acl/2007'
75
+ xmlns:gd='http://schemas.google.com/g/2005'
76
+ #{etag_attr}>
77
+ <category scheme='http://schemas.google.com/g/2005#kind'
78
+ term='http://schemas.google.com/acl/2007#accessRule'/>
79
+ #{role_tag}
80
+ <gAcl:scope type='#{h(self.scope_type)}' #{value_attr}/>
81
+ </entry>
82
+ EOS
83
+
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+
@@ -0,0 +1,14 @@
1
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
2
+ # The license of this source is "New BSD Licence"
3
+
4
+ require "google_drive/error"
5
+
6
+
7
+ module GoogleDrive
8
+
9
+ # Raised when GoogleDrive.login has failed.
10
+ class AuthenticationError < GoogleDrive::Error
11
+
12
+ end
13
+
14
+ end
@@ -0,0 +1,56 @@
1
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
2
+ # The license of this source is "New BSD Licence"
3
+
4
+ require "net/https"
5
+ require "uri"
6
+ Net::HTTP.version_1_2
7
+
8
+
9
+ module GoogleDrive
10
+
11
+ class ClientLoginFetcher #:nodoc:
12
+
13
+ def initialize(auth_tokens, proxy)
14
+ @auth_tokens = auth_tokens
15
+ if proxy
16
+ @proxy = proxy
17
+ elsif ENV["http_proxy"] && !ENV["http_proxy"].empty?
18
+ proxy_url = URI.parse(ENV["http_proxy"])
19
+ @proxy = Net::HTTP.Proxy(proxy_url.host, proxy_url.port)
20
+ else
21
+ @proxy = Net::HTTP
22
+ end
23
+ end
24
+
25
+ attr_accessor(:auth_tokens)
26
+
27
+ def request_raw(method, url, data, extra_header, auth)
28
+ uri = URI.parse(url)
29
+ http = @proxy.new(uri.host, uri.port)
30
+ http.use_ssl = true
31
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
32
+ http.start() do
33
+ path = uri.path + (uri.query ? "?#{uri.query}" : "")
34
+ header = auth_header(auth).merge(extra_header)
35
+ if method == :delete || method == :get
36
+ return http.__send__(method, path, header)
37
+ else
38
+ return http.__send__(method, path, data, header)
39
+ end
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def auth_header(auth)
46
+ token = auth == :none ? nil : @auth_tokens[auth]
47
+ if token
48
+ return {"Authorization" => "GoogleLogin auth=#{token}"}
49
+ else
50
+ return {}
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ end
@@ -0,0 +1,139 @@
1
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
2
+ # The license of this source is "New BSD Licence"
3
+
4
+ require "google_drive/util"
5
+ require "google_drive/error"
6
+ require "google_drive/spreadsheet"
7
+
8
+
9
+ module GoogleDrive
10
+
11
+ # Use GoogleDrive::Session#root_collection, GoogleDrive::Collection#subcollections,
12
+ # or GoogleDrive::Session#collection_by_url to get GoogleDrive::Collection object.
13
+ class Collection < GoogleDrive::File
14
+
15
+ include(Util)
16
+
17
+ ROOT_URL = "#{DOCS_BASE_URL}/folder%3Aroot" #:nodoc:
18
+
19
+ alias collection_feed_url document_feed_url
20
+
21
+ def contents_url
22
+ if self.root?
23
+ # The root collection doesn't have document feed.
24
+ return concat_url(ROOT_URL, "/contents")
25
+ else
26
+ return self.document_feed_entry.css(
27
+ "content[type='application/atom+xml;type=feed']")[0]["src"]
28
+ end
29
+ end
30
+
31
+ # Title of the collection.
32
+ #
33
+ # Set <tt>params[:reload]</tt> to true to force reloading the title.
34
+ def title(params = {})
35
+ if self.root?
36
+ # The root collection doesn't have document feed.
37
+ return nil
38
+ else
39
+ return super
40
+ end
41
+ end
42
+
43
+ def resource_id
44
+ return self.root? ? nil : super
45
+ end
46
+
47
+ # Adds the given GoogleDrive::File to the collection.
48
+ def add(file)
49
+ header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
50
+ xml = <<-"EOS"
51
+ <entry xmlns="http://www.w3.org/2005/Atom">
52
+ <id>#{h(file.document_feed_url)}</id>
53
+ </entry>
54
+ EOS
55
+ @session.request(
56
+ :post, self.contents_url, :data => xml, :header => header, :auth => :writely)
57
+ return nil
58
+ end
59
+
60
+ # Creates a sub-collection with given title. Returns GoogleDrive::Collection object.
61
+ def create_subcollection(title)
62
+ header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
63
+ xml = <<-EOS
64
+ <entry xmlns="http://www.w3.org/2005/Atom">
65
+ <category scheme="http://schemas.google.com/g/2005#kind"
66
+ term="http://schemas.google.com/docs/2007#folder"/>
67
+ <title>#{h(title)}</title>
68
+ </entry>
69
+ EOS
70
+ doc = @session.request(
71
+ :post, contents_url, :data => xml, :header => header, :auth => :writely)
72
+ return @session.entry_element_to_file(doc)
73
+ end
74
+
75
+ # Removes the given GoogleDrive::File from the collection.
76
+ def remove(file)
77
+ url = to_v3_url("#{contents_url}/#{file.resource_id}")
78
+ @session.request(:delete, url, :auth => :writely, :header => {"If-Match" => "*"})
79
+ end
80
+
81
+ # Returns true if this is a root collection
82
+ def root?
83
+ self.document_feed_url == ROOT_URL
84
+ end
85
+
86
+ # Returns all the files (including spreadsheets, documents, subcollections) in the collection.
87
+ #
88
+ # You can specify query parameters described at
89
+ # https://developers.google.com/google-apps/documents-list/#getting_a_list_of_documents_and_files
90
+ #
91
+ # e.g.
92
+ #
93
+ # # Gets all the files in collection, including subcollections.
94
+ # collection.files
95
+ #
96
+ # # Gets only files with title "hoge".
97
+ # collection.files("title" => "hoge", "title-exact" => "true")
98
+ def files(params = {})
99
+ return files_with_type(nil, params)
100
+ end
101
+
102
+ alias contents files
103
+
104
+ # Returns all the spreadsheets in the collection.
105
+ def spreadsheets(params = {})
106
+ return files_with_type("spreadsheet", params)
107
+ end
108
+
109
+ # Returns all the Google Docs documents in the collection.
110
+ def documents(params = {})
111
+ return files_with_type("document", params)
112
+ end
113
+
114
+ # Returns all its subcollections.
115
+ def subcollections(params = {})
116
+ return files_with_type("folder", params)
117
+ end
118
+
119
+ # Returns its subcollection whose title exactly matches +title+ as GoogleDrive::Collection.
120
+ # Returns nil if not found. If multiple collections with the +title+ are found, returns
121
+ # one of them.
122
+ def subcollection_by_title(title)
123
+ return subcollections("title" => title, "title-exact" => "true")[0]
124
+ end
125
+
126
+ private
127
+
128
+ def files_with_type(type, params = {})
129
+ contents_url = self.contents_url
130
+ contents_url = concat_url(contents_url, "/-/#{type}") if type
131
+ contents_url = concat_url(contents_url, "?" + encode_query(params))
132
+ header = {"GData-Version" => "3.0", "Content-Type" => "application/atom+xml"}
133
+ doc = @session.request(:get, contents_url, :header => header, :auth => :writely)
134
+ return doc.css("feed > entry").map(){ |e| @session.entry_element_to_file(e) }
135
+ end
136
+
137
+ end
138
+
139
+ end
@@ -0,0 +1,12 @@
1
+ # Author: Hiroshi Ichikawa <http://gimite.net/>
2
+ # The license of this source is "New BSD Licence"
3
+
4
+
5
+ module GoogleDrive
6
+
7
+ # Raised when spreadsheets.google.com has returned error.
8
+ class Error < RuntimeError
9
+
10
+ end
11
+
12
+ end