panda 1.3.0 → 1.4.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.
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
File without changes
@@ -0,0 +1,52 @@
1
+ ## 1.4.0 (...)
2
+
3
+ Features:
4
+
5
+ - Replaced Restclient/json by Faraday/Yajl
6
+ - Added Cloud.create, Cloud.all
7
+ - Https support for heroku account
8
+ - Simpler heroku configure method
9
+ - Simpler configure method
10
+ - Url and screenshots method for video
11
+ - `create` method accepts a block
12
+ - Removed support for JSON format
13
+
14
+ Bugfixes:
15
+ - timestamp is UTC
16
+ - `to_json` method
17
+ - `create!` on associations was wrong
18
+
19
+ ## 1.3.0 (January 10, 2011)
20
+
21
+ Features:
22
+
23
+ - Added support for https
24
+
25
+ ## 1.2.2 (December 08, 2010)
26
+
27
+ Bugfixes:
28
+
29
+ - No more warnings about already initialized constants for JSON
30
+
31
+ ## 1.2.0 (November 25, 2010)
32
+
33
+ Features:
34
+
35
+ - Added support for the notification api.
36
+ - Added support for path and url
37
+
38
+ ## 1.1.0 (October 19, 2010)
39
+
40
+ Bugfixes:
41
+
42
+ - Do not cache screenshot array anymore
43
+
44
+ ## 1.0.0 (August 05, 2010)
45
+
46
+ - Simpler and smarter gem
47
+
48
+
49
+
50
+
51
+
52
+ August 05, 2010
data/Gemfile CHANGED
@@ -1,14 +1,2 @@
1
- source :rubygems
2
-
3
- group :development, :test do
4
-
5
- gem "ruby-hmac",">= 0.3.2"
6
- gem "rest-client"
7
- gem "json"
8
-
9
- gem "jeweler"
10
- gem "rake"
11
- gem "rspec", "1.3.1"
12
- gem "webmock", "1.6.1"
13
-
14
- end
1
+ source "http://rubygems.org"
2
+ gemspec
data/README.md CHANGED
@@ -15,30 +15,32 @@ Panda gem provides an interface to access the [Panda](http://pandastream.com) AP
15
15
 
16
16
  ### Creating an instance of the client
17
17
 
18
- Panda.configure do |config|
19
- config.access_key = "panda_access_key"
20
- config.secret_key = "panda_secret_key"
21
- config.cloud_id = "panda_cloud_id"
22
- # config.api_host = "api.eu.pandastream.com" ## for EU accounts
23
- # config.api_port = 80 ## to use http (default 443)
18
+ Panda.configure do
19
+ access_key "panda_access_key"
20
+ secret_key "panda_secret_key"
21
+ cloud_id "panda_cloud_id"
22
+ # api_host "api.eu.pandastream.com" ## for EU accounts
23
+ # api_port 80 ## to use http (default 443)
24
24
  end
25
25
 
26
26
  or Panda.configure({:access_key => ....})
27
27
 
28
- ### Creating an instance using Heroku
28
+ ### Inside a Rails app with a main account or using Heroku Addon
29
29
 
30
- Panda.configure(ENV['PANDASTREAM_URL'])
30
+ Heroku will store your credentials as an environment variable called PANDASTREAM_URL. You can find more information on [Heroku config variable docs](http://docs.heroku.com/config-vars)
31
31
 
32
- ### Inside a Rails app with a main account or using Heroku
33
-
34
- Config is stored in `config/panda.yml` or you must set an the PANDASTREAM_URL environment variable in your `/.bashrc` file (see the [Heroku config variable docs](http://docs.heroku.com/config-vars)).
35
-
36
- Use the following in your `config/initializers/panda.rb`:
32
+ If you use a config file like `config/panda.yml` to support multiple environments, do the following in your `config/initializers/panda.rb` :
37
33
 
38
34
  Panda.configure((ENV['PANDASTREAM_URL'] || YAML::load_file(File.join(File.dirname(__FILE__),"..", "panda.yml"))[RAILS_ENV]))
39
35
 
40
36
  See the [Rails How-to](http://www.pandastream.com/docs/integrate_with_rails) for more details.
41
37
 
38
+ ### Creating an instance using ONLY with Heroku Addon
39
+
40
+ If you don't use a config file and want to simply be setup, do the following (works only on heroku):
41
+
42
+ Panda.configure_heroku
43
+
42
44
  ### Typical usage
43
45
 
44
46
  In most cases you will have used the [panda\_uploader](http://github.com/newbamboo/panda_uploader) jQuery plugin to upload the video (more details about this are in the [Integrating Panda with Ruby on Rails](http://pandastream.com/docs/integrate_with_rails) tutorial). Then you will want to get the video and screenshots urls of your encoding to display to your users.
@@ -346,7 +348,27 @@ The name of the profile can be found in your [Panda account](http://pandastream.
346
348
  or
347
349
  profile.encodings.all(:status => "success")
348
350
  => [...]
349
-
351
+
352
+ ### Clouds
353
+
354
+ #### Find a cloud
355
+
356
+ cloud = Panda::Cloud.find(234324)
357
+ cloud.id
358
+ => 234324
359
+
360
+ ##### Find all clouds
361
+
362
+ clouds = Panda::Cloud.all
363
+ clouds.size
364
+ => 2
365
+
366
+ ##### Create a cloud
367
+
368
+ cloud = Panda::Cloud.create :aws_access_key => 'mys3key', :aws_secret_key => 'mys3secret', :s3_videos_bucket => 'myexistingbucket'
369
+ cloud.id
370
+ => 1234
371
+
350
372
  ### Using multiple clouds
351
373
 
352
374
  By default Cloud.id uses options defined with: Panda.configure do .. end
@@ -368,17 +390,13 @@ The name of the profile can be found in your [Panda account](http://pandastream.
368
390
  cloud_two.profiles
369
391
  cloud_two.profiles.create(:preset_name => "h264")
370
392
  cloud_one.videos.create(:command => "ffmpeg -i $input_file$ -y $output_file$", ....)
371
-
372
- You can also connect directly using Cloud.find
373
-
374
- cloud = Panda::Cloud.find("cloud_id_1", {:access_key => ..., :secret_key => ... })
375
393
 
376
394
 
377
395
  ## Generating signatures
378
396
 
379
- All requests to your Panda cloud are signed using HMAC-SHA256, based on a timestamp and your Panda secret key. This is handled transparently. However, sometimes you will want to generate only this signature, in order to make a request by means other than this library. This is the case when using the [JavaScript panda_uploader](http://github.com/newbamboo/panda_uploader).
397
+ All requests to your Panda cloud are signed using HMAC-SHA256, based on a timestamp and your Panda secret key. This is handled transparently. However, sometimes you will want to generate only this signature, in order to make a request by means other than this library. This is the case when using the [JavaScript panda_uploader](http://github.com/newbamboo/panda_uploader).
380
398
 
381
- To do this, a method `signed_params()` is supported:
399
+ To do this, a method `signed_params()` is supported:
382
400
 
383
401
  Panda.signed_params('POST', '/videos.json')
384
402
  # => {'access_key' => '8df50af4-074f-11df-b278-1231350015b1',
@@ -469,21 +487,9 @@ The name of the profile can be found in your [Panda account](http://pandastream.
469
487
 
470
488
  Panda.delete('/videos/0ee6b656-0063-11df-a433-1231390041c1.json')
471
489
 
472
- ## Hash or JSON
473
- Since Panda 0.6, PandaGem returns a Hash by default. If you want PandaGem to return JSON do the following:
474
-
475
- Panda.connect!({
476
- :cloud_id => 'cloud_id',
477
- :access_key => 'access_key',
478
- :secret_key => 'secret_key',
479
- :format => 'json'
480
- })
481
-
482
-
483
490
  ## Use bundler to setup the test environment (1.0)
484
491
 
485
492
  bundler install
486
493
  rake spec
487
494
 
488
-
489
495
  Copyright (c) 2009-2010 New Bamboo. See LICENSE for details.
data/Rakefile CHANGED
@@ -1,27 +1,9 @@
1
- require 'rubygems'
2
- require 'rake'
3
-
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "panda"
8
- gem.summary = %Q{Panda Client}
9
- gem.description = %Q{Panda Client}
10
- gem.email = "info@pandastream.com"
11
- gem.homepage = "http://github.com/newbamboo/panda_gem"
12
- gem.authors = ["New Bamboo"]
13
- gem.add_dependency "ruby-hmac", ">= 0.3.2"
14
- gem.add_dependency "rest-client", ">= 1.4"
15
- gem.add_dependency "json", ">= 1.2"
16
- end
17
- Jeweler::GemcutterTasks.new
18
- rescue LoadError
19
- puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
20
- end
21
-
22
- desc "Run all the specs"
23
- task :spec do
24
- system "bundle exec spec -O spec/spec.opts spec"
25
- end
26
-
27
- task :default => :spec
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ desc "Run all the specs"
5
+ task :spec do
6
+ system "bundle exec rspec spec"
7
+ end
8
+
9
+ task :default => :spec
@@ -1,22 +1,28 @@
1
+ require 'panda/version'
1
2
  require 'panda/api_authentication'
2
3
  require 'panda/connection'
4
+ require 'panda/config'
3
5
  require 'panda/modules/router'
4
6
  require 'panda/modules/finders'
5
7
  require 'panda/modules/builders'
8
+ require 'panda/modules/destroyers'
6
9
  require 'panda/modules/associations'
7
10
  require 'panda/modules/updatable'
8
- require 'panda/modules/short_status'
11
+ require 'panda/modules/viewable'
12
+ require 'panda/modules/video_state'
9
13
  require 'panda/modules/cloud_connection'
10
14
  require 'panda/proxies/proxy'
11
15
  require 'panda/proxies/scope'
12
16
  require 'panda/proxies/encoding_scope'
13
17
  require 'panda/proxies/video_scope'
14
18
  require 'panda/proxies/profile_scope'
15
- require 'panda/error'
19
+ require 'panda/adapters/adapter'
20
+ require 'panda/adapters/faraday'
21
+ require 'panda/errors'
16
22
  require 'panda/base'
17
23
  require 'panda/resources/resource'
18
24
  require 'panda/resources/cloud'
19
25
  require 'panda/resources/encoding'
20
26
  require 'panda/resources/profile'
21
27
  require 'panda/resources/video'
22
- require 'panda/panda'
28
+ require 'panda/panda'
@@ -0,0 +1,4 @@
1
+ module Panda
2
+ module Adapter
3
+ end
4
+ end
@@ -0,0 +1,70 @@
1
+ require 'faraday'
2
+ require 'yajl/json_gem'
3
+
4
+ module Panda
5
+ module Adapter
6
+ class Faraday
7
+
8
+ def initialize(api_url)
9
+ @api_url = api_url
10
+ end
11
+
12
+ def get(request_uri, params)
13
+ rescue_json_parsing do
14
+ response = connection.get do |req|
15
+ req.url File.join(connection.path_prefix, request_uri), params
16
+ end.body
17
+ end
18
+ end
19
+
20
+ def post(request_uri, params)
21
+ # multipart upload
22
+ if (f=params['file']) && f.is_a?(File)
23
+ params['file'] = ::Faraday::UploadIO.new(f.path, 'multipart/form-data')
24
+ end
25
+
26
+ rescue_json_parsing do
27
+ connection.post do |req|
28
+ req.url File.join(connection.path_prefix, request_uri)
29
+ req.body = params
30
+ end.body
31
+ end
32
+ end
33
+
34
+ def put(request_uri, params)
35
+ rescue_json_parsing do
36
+ connection.put do |req|
37
+ req.url File.join(connection.path_prefix, request_uri)
38
+ req.body = params
39
+ end.body
40
+ end
41
+ end
42
+
43
+ def delete(request_uri, params)
44
+ rescue_json_parsing do
45
+ connection.delete do |req|
46
+ req.url File.join(connection.path_prefix, request_uri), params
47
+ end.body
48
+ end
49
+ end
50
+
51
+ private
52
+
53
+ def connection
54
+ @conn ||= ::Faraday::Connection.new(:url => @api_url) do |builder|
55
+ builder.adapter :net_http
56
+ builder.response :yajl
57
+ end
58
+ end
59
+
60
+ def rescue_json_parsing(&block)
61
+ begin
62
+ yield || raise(ServiceNotAvailable)
63
+ rescue ::Faraday::Error::ParsingError => e
64
+ raise(ServiceNotAvailable)
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,67 @@
1
+ require 'restclient'
2
+ require 'json' unless defined?(ActiveSupport::JSON) || defined?(JSON::JSON_LOADED)
3
+
4
+ module Panda
5
+ module Adapter
6
+ class RestClient
7
+
8
+ def initialize(api_url)
9
+ @api_url = api_url
10
+ end
11
+
12
+ def get(request_uri, params)
13
+ rescue_json_parsing do
14
+ query = ApiAuthentication.hash_to_query(params)
15
+ hash_response connection[request_uri + '?' + query].get
16
+ end
17
+ end
18
+
19
+ def post(request_uri, params)
20
+ rescue_json_parsing do
21
+ hash_response connection[request_uri].post(params)
22
+ end
23
+ end
24
+
25
+ def put(request_uri, params)
26
+ rescue_json_parsing do
27
+ hash_response connection[request_uri].put(params)
28
+ end
29
+ end
30
+
31
+ def delete(request_uri, params)
32
+ rescue_json_parsing do
33
+ query = ApiAuthentication.hash_to_query(params)
34
+ hash_response connection[request_uri + '?' + query].delete
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ def connection
41
+ @conn ||= ::RestClient::Resource.new(@api_url)
42
+ end
43
+
44
+ def hash_response(response)
45
+ begin
46
+ if defined?(ActiveSupport::JSON)
47
+ ActiveSupport::JSON.decode(response)
48
+ else
49
+ JSON.parse(response)
50
+ end
51
+ rescue JSON::ParserError => e
52
+ raise ServiceNotAvailable.new
53
+ end
54
+ end
55
+
56
+ def rescue_json_parsing(&block)
57
+ begin
58
+ yield
59
+ rescue ::RestClient::Exception => e
60
+ hash_response(e.http_body)
61
+ end
62
+ end
63
+
64
+ end
65
+ end
66
+ end
67
+
@@ -24,6 +24,8 @@ module Panda
24
24
  Base64.encode64(hmac.digest).chomp
25
25
  end
26
26
 
27
+ private
28
+
27
29
  # param keys should be strings, not symbols please. return a string joined
28
30
  # by & in canonical order.
29
31
  def self.canonical_querystring(h)
@@ -1,18 +1,22 @@
1
+ require 'forwardable'
2
+
1
3
  module Panda
2
- class Base
4
+ class Base
3
5
  attr_accessor :attributes, :errors
6
+ extend Forwardable
7
+
4
8
  include Panda::Router
9
+ include Panda::Builders
10
+ include Panda::Finders
11
+
12
+ def_delegators :attributes, :to_json
5
13
 
6
14
  def initialize(attributes = {})
7
- init_load
15
+ clear_attributes
8
16
  load(attributes)
9
17
  end
10
18
 
11
19
  class << self
12
- def id(this_id)
13
- find(this_id)
14
- end
15
-
16
20
  def sti_name
17
21
  "#{name.split('::').last}"
18
22
  end
@@ -26,11 +30,6 @@ module Panda
26
30
  id.nil?
27
31
  end
28
32
 
29
- def delete
30
- response = connection.delete(object_url_map(self.class.one_path))
31
- !!response['deleted']
32
- end
33
-
34
33
  def id
35
34
  attributes['id']
36
35
  end
@@ -44,41 +43,44 @@ module Panda
44
43
  self
45
44
  end
46
45
 
47
- def to_json
48
- attributes.to_json
49
- end
50
-
51
46
  private
52
47
 
48
+ def load_and_reset(response)
49
+ load_response(response)
50
+ end
51
+
53
52
  def perform_reload(args={})
54
53
  raise "RecordNotFound" if new?
55
54
 
56
- url = self.class.object_url(self.class.one_path, :id => id)
55
+ url = self.class.create_rest_url(self.class.one_path, :id => id)
57
56
  response = connection.get(url)
58
- init_load
59
57
  load_response(response.merge(args))
60
58
  end
61
59
 
62
- def init_load
60
+ def clear_attributes
63
61
  @attributes = {}
64
62
  @changed_attributes = {}
65
63
  @errors = []
66
64
  end
67
65
 
68
66
  def load(attributes)
67
+ not_a_response = !(attributes['id'] || attributes[:id])
69
68
  attributes.each do |key, value|
70
69
  @attributes[key.to_s] = value
71
- @changed_attributes[key.to_s] = value if !(attributes['id'] || attributes[:id])
70
+ @changed_attributes[key.to_s] = value if not_a_response
72
71
  end
73
72
  true
74
73
  end
75
74
 
76
75
  def load_response(response)
77
76
  if response['error'] || response['id'].nil?
78
- !(@errors << Error.new(response))
77
+ @errors << APIError.new(response)
78
+ @loaded = false
79
79
  else
80
- @errors=[]
80
+ clear_attributes
81
81
  load(response)
82
+ @changed_attributes = {};
83
+ @loaded = true
82
84
  end
83
85
  end
84
86