nofxx-pyradise 0.1.1 → 0.2.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.
data/README.rdoc CHANGED
@@ -5,12 +5,8 @@ Fetch/search and store Paraguay's prices!
5
5
 
6
6
  == Install
7
7
 
8
- * dm-core
9
- * do_sqlite
10
-
11
8
  sudo gem install nofxx-pyradise
12
9
 
13
-
14
10
  == Use
15
11
 
16
12
  Fetch all:
@@ -25,7 +21,7 @@ List all:
25
21
 
26
22
  Search for a new 1TB Sata drive:
27
23
 
28
- pyradise list SATA2%1000
24
+ pyradise search SATA2%1000
29
25
 
30
26
  Searching "SATA2%1000"... Order by: name
31
27
  ____________________________________________________________
@@ -38,7 +34,7 @@ Search for a new 1TB Sata drive:
38
34
 
39
35
  View the price oscillation of a item:
40
36
 
41
- pyradise view <ID>
37
+ pyradise info <ID>
42
38
 
43
39
  07/07 =======================| 50
44
40
  07/08 ===================| 40
data/Rakefile CHANGED
@@ -9,8 +9,7 @@ begin
9
9
  gem.email = "x@nofxx.com"
10
10
  gem.homepage = "http://github.com/nofxx/pyradise"
11
11
  gem.authors = ["Marcos Piccinini"]
12
- gem.add_dependency 'dm-core'
13
- gem.add_dependency 'do_sqlite3'
12
+ gem.add_dependency 'sequel'
14
13
  end
15
14
  rescue LoadError
16
15
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
data/bin/pyradise CHANGED
@@ -8,7 +8,6 @@ begin
8
8
  require 'rubygems'
9
9
  rescue LoadError
10
10
  # no rubygems to load, so we fail silently
11
- require 'lib/pyradise'
12
11
  end
13
12
 
14
13
  require 'optparse'
@@ -28,10 +27,14 @@ parser = OptionParser.new do |opts|
28
27
  opts.banner = <<BANNER
29
28
  Pyradise - PY ftw
30
29
 
31
- Usage: #{File.basename($0)} command [options]
30
+ Usage: #{File.basename($0)} command [args]
32
31
 
33
32
  Options are:
34
33
 
34
+ fetch - Get fresh info
35
+ list/search - List and filter items
36
+ info/show - More info about an item
37
+
35
38
  BANNER
36
39
  opts.separator ""
37
40
 
data/lib/pyradise.rb CHANGED
@@ -1,53 +1,104 @@
1
1
  require 'rubygems'
2
2
  require 'open-uri'
3
- require 'do_sqlite3'
4
- require 'dm-core'
5
- #require "dm-tokyo-adapter"
6
- require 'pyradise/product'
7
- require 'pyradise/stat'
3
+ require 'sequel'
8
4
 
9
5
  #TODO: def init
10
- HOME = ENV['HOME'] + "/.pyradise/"
11
- #DataMapper.setup(:default, :adapter => 'tokyo_cabinet', :database => 'data.tct', :path => HOME)
12
- DataMapper.setup(:default, :adapter => 'sqlite3', :database => HOME + "py.sqlite3")
6
+ HOME = ENV['HOME'] + "/.pyradise"
7
+ FileUtils.mkdir_p HOME unless File.exists? HOME
8
+
9
+ DB = Sequel.connect("sqlite://#{HOME}/py.sqlite3")
10
+ require 'pyradise/product'
11
+ # require 'pyradise/stat'
13
12
 
14
- unless File.exists? HOME
15
- FileUtils.mkdir_p HOME
16
- DataMapper.auto_migrate!
13
+ unless DB.table_exists? :products
14
+ require 'pyradise/migrate'
15
+ CreatePyradise.apply DB, :up
17
16
  end
18
17
 
19
18
  module Pyradise
20
19
 
21
- CONF = YAML.load(File.new(HOME + "conf.yml"))
20
+ CONF = YAML.load(File.new(HOME + "/conf.yml"))
22
21
  RATE = CONF[:rate] || 2.1
23
22
  TAX = CONF[:tax] || 1.3
24
23
 
25
24
  class << self
26
25
 
27
26
  def run! comm, opts
28
- send(*comm)
27
+ if respond_to? comm[0]
28
+ send(*comm)
29
+ else
30
+ puts "Can't do that..."
31
+ exit
32
+ end
29
33
  end
30
34
 
31
35
  def fetch
32
36
  create fetch_stores
33
37
  end
34
38
 
39
+ def list(*query)
40
+ t = Time.now
41
+ w = terminal_size[0]
42
+ s = w - 35
43
+ puts "Searching #{'"' + query[0] + '"' if query[0]}... Order by: #{query[1] || 'name'}"
44
+ puts "_" * w
45
+ prods = Product.filter(:name.like("%#{query[0]}%")).order(query[1] ? query[1].to_sym : :name)
46
+ prods.each_with_index do |prod, i|
47
+ name = prod.name.length > s ? prod.name[0..s] + ".." : prod.name
48
+ out = sprintf("%-6s | %-5s | %-#{w-38}s %-3d | R$ %d", prod.store, prod.sid, name, prod.price, prod.price * RATE * TAX)
49
+ puts i % 2 == 0 ? bold(out) : out
50
+ end
51
+ puts "_" * w
52
+ puts green("Total: #{prods.all.length} (#{Time.now - t}s)")
53
+ end
54
+ alias :search :list
55
+
56
+ def info(sid=nil)
57
+ if !sid
58
+ puts red("Use: pyradise view <ID>")
59
+ elsif !prod = Product.filter(:sid => sid.to_i).first
60
+ puts yellow("Product not found.")
61
+ else
62
+ w = terminal_size[0] - 20
63
+ prices = prod.prices
64
+ max = prices.values.max.to_f
65
+ prices.keys.sort.each do |k|
66
+ rel = "=" * (prices[k] / max * w)
67
+ puts "#{Time.at(k).strftime('%M/%d')} #{rel}| #{prices[k]}"
68
+ end
69
+ end
70
+ end
71
+ alias :show :info
72
+
73
+ def clear
74
+ Product.dataset.delete
75
+ end
76
+
77
+ private
78
+
35
79
  def create txts
36
80
  products = []
37
81
  for txt in txts
38
82
  print "Parsing #{txt[:store]}..."
39
83
  c = Product.all.length
40
- parse(txt[:txt], txt[:delimiter]).each do |p|
41
- if prod = Product.first(:name => p[:name], :store => txt[:store])
42
- prod.price = p[:price]
43
- else
44
- Product.create(p.merge(:store => txt[:store]))
45
- end
84
+ parse(txt[:txt], txt[:delimiter]).each do |t|
85
+ next if t[:price] == 0
86
+ create_product(t, txt[:store].to_s)
46
87
  end
47
88
  puts "#{Product.all.length - c} products created."
48
89
  end
49
90
  end
50
91
 
92
+ def create_product(t, store)
93
+ if prod = Product.filter(:name => t[:name], :store => store).first
94
+ prod.new_price!(t[:price]) if t[:price] != prod.price
95
+ else
96
+ Product.create(t.merge(:store => store))
97
+ end
98
+ rescue => e
99
+ puts "SQLITE Err #{e}, #{t.inspect} - #{store} #{prod}"
100
+ end
101
+
51
102
  def fetch_stores
52
103
  stores = []
53
104
  for store in YAML.load(File.new(File.dirname(__FILE__) + '/stores.yml'))[:stores]
@@ -67,52 +118,15 @@ module Pyradise
67
118
  def parse(txt, del)
68
119
  products = []
69
120
  txt.each_line do |l|
70
- sid, name, price = l.split(del)
71
- next unless price
72
- products << { :sid => sid.strip, :name => name.strip.gsub(/\.{2,}/, ""), :price => price.to_i }
121
+ sid, *info = l.split(del)
122
+ next if info.length < 2
123
+ price = info.delete_at(-1).strip.to_i
124
+ next if price.nil? || price.zero?
125
+ products << { :sid => sid.strip, :name => info.join("").strip.gsub(/\.{2,}/, ""), :price => price }
73
126
  end
74
127
  products
75
128
  end
76
129
 
77
- def list(*query)
78
- t = Time.now
79
- w = terminal_size[0]
80
- q = {}
81
- q.merge!(:name.like => "%#{query[0]}%") if query[0]
82
- q.merge!(:order => [query[1]]) if query[1]
83
- puts "Searching #{'"' + query[0] + '"' if query[0]}... Order by: #{query[1] || 'name'}"
84
- puts "_" * w
85
- prods = q.empty? ? Product.all : Product.all(q)
86
- prods.each_with_index do |prod, i|
87
- s = w - 35
88
- name = prod.name.length > s ? prod.name[0..s] + ".." : prod.name
89
- out = sprintf("%-6s | %-5s | %-#{w-38}s %-3d | R$ %d", prod.store, prod.sid, name, prod.price, prod.price * RATE * TAX)
90
- puts i % 2 == 0 ? bold(out) : out
91
- end
92
- puts "_" * w
93
- puts green("Total: #{prods.length} (#{Time.now - t}s)")
94
- end
95
-
96
- def view(sid=nil)
97
- if !sid
98
- puts red("Use: pyradise view <ID>")
99
- elsif !prod = Product.first(:sid => sid.to_i)
100
- puts yellow("Product not found.")
101
- else
102
- w = terminal_size[0] - 20
103
- prices = prod.prices
104
- max = prices.values.max.to_f
105
- prices.keys.sort.each do |k|
106
- rel = "=" * (prices[k] / max * w)
107
- puts "#{Time.at(k).strftime('%M/%d')} #{rel}| #{prices[k]}"
108
- end
109
- end
110
- end
111
-
112
- def clear
113
- Product.all.destroy
114
- end
115
-
116
130
  #from highliner
117
131
  def terminal_size
118
132
  `stty size`.split.map { |x| x.to_i }.reverse
@@ -121,6 +135,6 @@ module Pyradise
121
135
  def red(txt); "\e[31m#{txt}\e[0m"; end
122
136
  def green(txt); "\e[32m#{txt}\e[0m"; end
123
137
  def yellow(txt); "\e[33m#{txt}\e[0m"; end
124
- def bold(txt); "\e[2m#{txt}\e[0m"; end
138
+ def bold(txt); "\e[2m#{txt}\e[0m"; end
125
139
  end
126
140
  end
@@ -0,0 +1,18 @@
1
+ require 'sequel/extensions/migration'
2
+
3
+ class CreatePyradise < Sequel::Migration
4
+ def up
5
+ create_table :products do
6
+ primary_key :id
7
+ varchar :sid
8
+ varchar :name
9
+ varchar :store
10
+ integer :price
11
+ text :prices
12
+ end
13
+ end
14
+
15
+
16
+ def down() drop_table :products end
17
+
18
+ end
@@ -1,38 +1,16 @@
1
- class Product
2
- include DataMapper::Resource
1
+ class Product < Sequel::Model
3
2
 
4
- property :id, Serial
5
- property :sid, String
6
- property :name, String, :nullable => false, :length => (2..20)
7
- property :price, Integer
8
- property :store, String
9
- property :prices, Text
10
- # has n, :orders
11
-
12
- # def self.count
13
- # all.length
14
- # end
15
- # def to_param
16
- # id.to_s
17
- # end
18
- before :save do
19
- # self[:prices] = Marshal.dump({ Time.now.to_i => price })
3
+ def before_save
20
4
  phist = { Time.now.to_i => price }
21
5
  self[:prices] = Marshal.dump(prices ? prices.merge(phist) : phist)
22
-
23
6
  end
24
7
 
25
8
  def prices
26
9
  self[:prices] ? Marshal.load(self[:prices]) : nil
27
10
  end
28
11
 
29
- def prices=(price)
30
- self[:prices] = Marshal.dump(prices ? prices.merge(price) : price)
12
+ def new_price!(np)
13
+ self.update(:prices => Marshal.dump(prices ? prices.merge({Time.now.to_i => np}) : np))
31
14
  end
32
15
 
33
-
34
- #no idea why..
35
- def self.identity_field
36
- "product"
37
- end
38
16
  end
data/lib/stores.yml CHANGED
@@ -14,7 +14,7 @@
14
14
  :albor:
15
15
  :url: http://www.alboradainfo.com
16
16
  :txt: http://www.alboradainfo.com/lista/lista_alborada.txt
17
- :delimiter: !ruby/regexp /\s{3,}/
17
+ :delimiter: !ruby/regexp /\s{1,}/
18
18
 
19
19
  # TODO
20
20
  # http://www.icompy.com/upload/precios/200907251505270.lista.txt
data/pyradise.gemspec CHANGED
@@ -1,12 +1,15 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
1
4
  # -*- encoding: utf-8 -*-
2
5
 
3
6
  Gem::Specification.new do |s|
4
7
  s.name = %q{pyradise}
5
- s.version = "0.1.1"
8
+ s.version = "0.2.0"
6
9
 
7
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
11
  s.authors = ["Marcos Piccinini"]
9
- s.date = %q{2009-07-27}
12
+ s.date = %q{2009-09-13}
10
13
  s.default_executable = %q{pyradise}
11
14
  s.email = %q{x@nofxx.com}
12
15
  s.executables = ["pyradise"]
@@ -23,13 +26,12 @@ Gem::Specification.new do |s|
23
26
  "VERSION",
24
27
  "bin/pyradise",
25
28
  "lib/pyradise.rb",
29
+ "lib/pyradise/migrate.rb",
26
30
  "lib/pyradise/product.rb",
27
- "lib/pyradise/stat.rb",
28
31
  "lib/stores.yml",
29
32
  "pyradise.gemspec",
30
33
  "script/console",
31
34
  "spec/pyradise/product_spec.rb",
32
- "spec/pyradise/stat_spec.rb",
33
35
  "spec/pyradise_spec.rb",
34
36
  "spec/spec_helper.rb"
35
37
  ]
@@ -41,7 +43,6 @@ Gem::Specification.new do |s|
41
43
  s.test_files = [
42
44
  "spec/spec_helper.rb",
43
45
  "spec/pyradise_spec.rb",
44
- "spec/pyradise/stat_spec.rb",
45
46
  "spec/pyradise/product_spec.rb"
46
47
  ]
47
48
 
@@ -50,14 +51,11 @@ Gem::Specification.new do |s|
50
51
  s.specification_version = 3
51
52
 
52
53
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
53
- s.add_runtime_dependency(%q<dm-core>, [">= 0"])
54
- s.add_runtime_dependency(%q<do_sqlite3>, [">= 0"])
54
+ s.add_runtime_dependency(%q<sequel>, [">= 0"])
55
55
  else
56
- s.add_dependency(%q<dm-core>, [">= 0"])
57
- s.add_dependency(%q<do_sqlite3>, [">= 0"])
56
+ s.add_dependency(%q<sequel>, [">= 0"])
58
57
  end
59
58
  else
60
- s.add_dependency(%q<dm-core>, [">= 0"])
61
- s.add_dependency(%q<do_sqlite3>, [">= 0"])
59
+ s.add_dependency(%q<sequel>, [">= 0"])
62
60
  end
63
61
  end
@@ -1,26 +1,40 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper.rb'
2
2
 
3
3
  describe "Product" do
4
- it "should create a product" do
5
- Product.create(:sid => "111", :name => "CPU", :price => 1000).should be_true
4
+
5
+ before do
6
+ Product.dataset.delete
7
+ Time.stub_chain(:now, :to_i).and_return(88)
8
+ @p = Product.create(:sid => "111", :store => "foo", :name => "CPU", :price => 1000).should be_true
6
9
  end
7
10
 
8
- it "should list products" do
9
- Product.all.length.should eql(1)
11
+ it "should have a price" do
12
+ @p.price.should eql(1000)
10
13
  end
11
14
 
12
- it "should clean up" do
13
- Product.first.destroy
14
- Product.all.should be_empty
15
+ it "should have a store" do
16
+ @p.store.should eql("foo")
15
17
  end
16
18
 
17
- it "should store all prices" do
18
- Time.stub_chain(:now, :to_i).and_return(1)
19
- p = Product.create(:name => "foo", :price => 1300)
20
- p.prices.should eql({1 => 1300})
21
- p.prices = { 2 => 1000 }
22
- p.prices.should eql({1 => 1300, 2 => 1000})
19
+ it "should have prices" do
20
+ @p.prices.should eql({88=>1000})
23
21
  end
24
22
 
23
+ it "should store another price in prices (merge)" do
24
+ Time.stub_chain(:now, :to_i).and_return(99)
25
+ @p.price = 1300
26
+ @p.save
27
+ @p.prices.should eql({88=>1000, 99=>1300})
28
+ end
25
29
 
30
+ it "should have a better way to do that.." do
31
+ Time.stub_chain(:now, :to_i).and_return(99)
32
+ @p.new_price!(800)
33
+ @p.prices.should eql({88=>1000, 99=>800})
34
+ end
35
+
36
+ it "should clean up" do
37
+ Product.all.each(&:destroy)
38
+ Product.all.should be_empty
39
+ end
26
40
  end
@@ -13,10 +13,6 @@ describe "Pyradise" do
13
13
  Pyradise.fetch.should be_true
14
14
  end
15
15
 
16
- it "should create a home folder" do
17
- Pyradise.get_or_create_home.should match("pyradise")
18
- end
19
-
20
16
 
21
17
  end
22
18
 
data/spec/spec_helper.rb CHANGED
@@ -3,9 +3,14 @@ require 'spec'
3
3
  $LOAD_PATH.unshift(File.dirname(__FILE__))
4
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
5
  require 'pyradise'
6
- DataMapper.setup(:default, :adapter => 'sqlite3', :database => HOME + "pytest.sqlite3")
7
- DataMapper.auto_migrate!
6
+ DB = Sequel.connect("sqlite://#{HOME}/py_test.sqlite3")
7
+
8
+ unless DB.table_exists? :products
9
+ require 'pyradise/migrate'
10
+ CreatePyradise.apply DB, :up
11
+ end
8
12
 
9
13
  Spec::Runner.configure do |config|
10
14
 
11
15
  end
16
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nofxx-pyradise
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marcos Piccinini
@@ -9,21 +9,11 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-07-27 00:00:00 -07:00
12
+ date: 2009-09-13 00:00:00 -07:00
13
13
  default_executable: pyradise
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
- name: dm-core
17
- type: :runtime
18
- version_requirement:
19
- version_requirements: !ruby/object:Gem::Requirement
20
- requirements:
21
- - - ">="
22
- - !ruby/object:Gem::Version
23
- version: "0"
24
- version:
25
- - !ruby/object:Gem::Dependency
26
- name: do_sqlite3
16
+ name: sequel
27
17
  type: :runtime
28
18
  version_requirement:
29
19
  version_requirements: !ruby/object:Gem::Requirement
@@ -50,18 +40,16 @@ files:
50
40
  - VERSION
51
41
  - bin/pyradise
52
42
  - lib/pyradise.rb
43
+ - lib/pyradise/migrate.rb
53
44
  - lib/pyradise/product.rb
54
- - lib/pyradise/stat.rb
55
45
  - lib/stores.yml
56
46
  - pyradise.gemspec
57
47
  - script/console
58
48
  - spec/pyradise/product_spec.rb
59
- - spec/pyradise/stat_spec.rb
60
49
  - spec/pyradise_spec.rb
61
50
  - spec/spec_helper.rb
62
51
  has_rdoc: false
63
52
  homepage: http://github.com/nofxx/pyradise
64
- licenses:
65
53
  post_install_message:
66
54
  rdoc_options:
67
55
  - --charset=UTF-8
@@ -82,12 +70,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
70
  requirements: []
83
71
 
84
72
  rubyforge_project:
85
- rubygems_version: 1.3.5
73
+ rubygems_version: 1.2.0
86
74
  signing_key:
87
75
  specification_version: 3
88
76
  summary: Paraguay gem!
89
77
  test_files:
90
78
  - spec/spec_helper.rb
91
79
  - spec/pyradise_spec.rb
92
- - spec/pyradise/stat_spec.rb
93
80
  - spec/pyradise/product_spec.rb
data/lib/pyradise/stat.rb DELETED
@@ -1,8 +0,0 @@
1
- class Stat
2
- include DataMapper::Resource
3
-
4
- property :id, Serial
5
- property :key, String
6
- property :value, String, :nullable => false, :length => (2..20)
7
-
8
- end
@@ -1,13 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper.rb'
2
-
3
- describe "Product" do
4
- it "should create a product" do
5
- Stat.create(:key => "update", :value => Marshal.dump(Time.now))
6
- # Stat.first.destroy
7
- Stat.all.length.should eql(1)
8
- end
9
-
10
- it "should list products" do
11
- Stat.all.should_not be_empty
12
- end
13
- end