pyradise 0.2.1

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/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Marcos Piccinini
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,47 @@
1
+ = PYradise
2
+
3
+ Fetch/search and store Paraguay's prices!
4
+
5
+
6
+ == Install
7
+
8
+ sudo gem install nofxx-pyradise
9
+
10
+ == Use
11
+
12
+ Fetch all:
13
+
14
+ pyradise fetch
15
+
16
+
17
+ List all:
18
+
19
+ pyradise list
20
+
21
+
22
+ Search for a new 1TB Sata drive:
23
+
24
+ pyradise search SATA2%1000
25
+
26
+ Searching "SATA2%1000"... Order by: name
27
+ ____________________________________________________________
28
+ master | 56446 | HD SATA2-1000G MAXTOR 7200 96 | R$ 274
29
+ master | 21054 | HD SATA2-1000G SAMSUNG 5400 87 | R$ 248
30
+ master | 17232 | HD SATA2-1000G SEAGATE 7200 93 | R$ 265
31
+ ____________________________________________________________
32
+ Total: 3 (0.010016s)
33
+
34
+
35
+ View the price oscillation of a item:
36
+
37
+ pyradise info <ID>
38
+
39
+ 07/07 =======================| 50
40
+ 07/08 ===================| 40
41
+ 07/09 ===============| 30
42
+ 07/10 ==========| 25
43
+
44
+
45
+ == Copyright
46
+
47
+ Copyright (c) 2009 Marcos Piccinini. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "pyradise"
8
+ gem.summary = "Paraguay gem!"
9
+ gem.email = "x@nofxx.com"
10
+ gem.homepage = "http://github.com/nofxx/pyradise"
11
+ gem.authors = ["Marcos Piccinini"]
12
+ gem.add_dependency 'sequel'
13
+ end
14
+ rescue LoadError
15
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
16
+ end
17
+
18
+ require 'rake/testtask'
19
+ Rake::TestTask.new(:spec) do |spec|
20
+ spec.libs << 'lib' << 'spec'
21
+ spec.pattern = 'spec/**/*_spec.rb'
22
+ spec.verbose = true
23
+ end
24
+
25
+ begin
26
+ require 'rcov/rcovtask'
27
+ Rcov::RcovTask.new do |spec|
28
+ spec.libs << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.verbose = true
31
+ end
32
+ rescue LoadError
33
+ task :rcov do
34
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
35
+ end
36
+ end
37
+
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ if File.exist?('VERSION.yml')
44
+ config = YAML.load(File.read('VERSION.yml'))
45
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
46
+ else
47
+ version = ""
48
+ end
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "pyradise #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
55
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.1
data/bin/pyradise ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Pyradise
4
+ #
5
+ # Created on 2008-9-4.
6
+ # Copyright (c) 2008. All rights reserved.
7
+ #
8
+ begin
9
+ require 'rubygems'
10
+ rescue LoadError
11
+ # no rubygems to load, so we fail silently
12
+ end
13
+ require 'optparse'
14
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
15
+ require 'pyradise'
16
+ include Pyradise
17
+
18
+ OPTIONS = {}
19
+ MANDATORY_OPTIONS = %w( )
20
+
21
+ parser = OptionParser.new do |opts|
22
+ opts.banner = <<BANNER
23
+ Pyradise - PY ftw
24
+
25
+ Usage: #{File.basename($0)} command [args]
26
+
27
+ Options are:
28
+
29
+ fetch - Get fresh info
30
+ list/search - List and filter items
31
+ info/show - More info about an item
32
+
33
+ BANNER
34
+ opts.separator ""
35
+ opts.parse!(ARGV)
36
+ end
37
+
38
+ if ARGV.empty?
39
+ puts parser.banner
40
+ exit
41
+ else
42
+ Pyradise.run! ARGV, OPTIONS
43
+ 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
@@ -0,0 +1,16 @@
1
+ class Product < Sequel::Model
2
+
3
+ def before_save
4
+ phist = { Time.now.to_i => price }
5
+ self[:prices] = Marshal.dump(prices ? prices.merge(phist) : phist)
6
+ end
7
+
8
+ def prices
9
+ self[:prices] ? Marshal.load(self[:prices]) : nil
10
+ end
11
+
12
+ def new_price!(np)
13
+ self.update(:prices => Marshal.dump(prices ? prices.merge({Time.now.to_i => np}) : np))
14
+ end
15
+
16
+ end
data/lib/pyradise.rb ADDED
@@ -0,0 +1,145 @@
1
+ require 'rubygems'
2
+ require 'open-uri'
3
+ require 'sequel'
4
+
5
+ #TODO: def init
6
+ HOME = ENV['HOME'] + "/.pyradise"
7
+ unless File.exists? HOME
8
+ FileUtils.mkdir_p HOME
9
+ conf = open(HOME + "/conf.yml", "wb")
10
+ conf.write(":rate: 2.0\n:tax: 1.3\n")
11
+ conf.close
12
+ end
13
+
14
+ DB = Sequel.connect("sqlite://#{HOME}/py.sqlite3")
15
+ require 'pyradise/product'
16
+ # require 'pyradise/stat'
17
+
18
+ unless DB.table_exists? :products
19
+ require 'pyradise/migrate'
20
+ CreatePyradise.apply DB, :up
21
+ end
22
+
23
+ module Pyradise
24
+
25
+ CONF = YAML.load(File.new(HOME + "/conf.yml"))
26
+ RATE = CONF[:rate] || 2.0
27
+ TAX = CONF[:tax] || 1.3
28
+
29
+ class << self
30
+
31
+ def run! comm, opts
32
+ if respond_to? comm[0]
33
+ send(*comm)
34
+ else
35
+ puts "Can't do that..."
36
+ exit
37
+ end
38
+ end
39
+
40
+ def fetch
41
+ create from_stores
42
+ end
43
+
44
+ def list(*query)
45
+ t = Time.now
46
+ w = terminal_size[0]
47
+ s = w - 35
48
+ puts "Searching #{'"' + query[0] + '"' if query[0]}... Order by: #{query[1] || 'name'}"
49
+ puts "_" * w
50
+ prods = Product.filter(:name.like("%#{query[0]}%")).order(query[1] ? query[1].to_sym : :name)
51
+ prods.each_with_index do |prod, i|
52
+ name = prod.name.length > s ? prod.name[0..s] + ".." : prod.name
53
+ out = sprintf("%-6s | %-5s | %-#{w-38}s %-3d | R$ %d", prod.store, prod.sid, name, prod.price, prod.price * RATE * TAX)
54
+ puts i % 2 == 0 ? bold(out) : out
55
+ end
56
+ puts "_" * w
57
+ puts green("Total: #{prods.all.length} (#{Time.now - t}s)")
58
+ end
59
+ alias :search :list
60
+
61
+ def info(sid=nil)
62
+ if !sid
63
+ puts red("Use: pyradise view <ID>")
64
+ elsif !prod = Product.filter(:sid => sid.to_i).first
65
+ puts yellow("Product not found.")
66
+ else
67
+ w = terminal_size[0] - 20
68
+ prices = prod.prices
69
+ max = prices.values.max.to_f
70
+ prices.keys.sort.each do |k|
71
+ rel = "=" * (prices[k] / max * w)
72
+ puts "#{Time.at(k).strftime('%M/%d')} #{rel}| #{prices[k]}"
73
+ end
74
+ end
75
+ end
76
+ alias :show :info
77
+
78
+ def clear
79
+ Product.dataset.delete
80
+ end
81
+
82
+ private
83
+
84
+ def create txts
85
+ products = []
86
+ for txt in txts
87
+ print "Parsing #{txt[:store]}..."
88
+ c = Product.all.length
89
+ parse(txt[:txt], txt[:delimiter]).each do |t|
90
+ next if t[:price] == 0
91
+ create_product(t, txt[:store].to_s)
92
+ end
93
+ puts "#{Product.all.length - c} products created."
94
+ end
95
+ end
96
+
97
+ def create_product(t, store)
98
+ if prod = Product.filter(:name => t[:name], :store => store).first
99
+ prod.new_price!(t[:price]) if t[:price] != prod.price
100
+ else
101
+ Product.create(t.merge(:store => store))
102
+ end
103
+ rescue => e
104
+ puts "SQLITE Err => #{e}, #{t.inspect} - #{store} #{prod}"
105
+ end
106
+
107
+ def from_stores
108
+ stores = []
109
+ for store in YAML.load(File.new(File.dirname(__FILE__) + '/stores.yml'))[:stores]
110
+ data = {}
111
+ data[:store] = store[0]
112
+ data[:delimiter] = store[1][:delimiter]
113
+ dump = open("#{HOME}#{store[0]}-#{Time.now.to_i}.txt", "wb")
114
+ data[:txt] = open(store[1][:txt]).read
115
+ dump.write(data[:txt])
116
+ dump.close
117
+ puts "Store #{store[0]} dumped... "
118
+ stores << data
119
+ end
120
+ stores
121
+ end
122
+
123
+ def parse(txt, del)
124
+ products = []
125
+ txt.each_line do |l|
126
+ sid, *info = l.split(del)
127
+ next if info.length < 2
128
+ price = info.delete_at(-1).strip.to_i
129
+ next if price.nil? || price.zero?
130
+ products << { :sid => sid.strip, :name => info.join("").strip.gsub(/\.{2,}/, ""), :price => price }
131
+ end
132
+ products
133
+ end
134
+
135
+ #from highliner
136
+ def terminal_size
137
+ `stty size`.split.map { |x| x.to_i }.reverse
138
+ end
139
+
140
+ def red(txt); "\e[31m#{txt}\e[0m"; end
141
+ def green(txt); "\e[32m#{txt}\e[0m"; end
142
+ def yellow(txt); "\e[33m#{txt}\e[0m"; end
143
+ def bold(txt); "\e[2m#{txt}\e[0m"; end
144
+ end
145
+ end
data/lib/stores.yml ADDED
@@ -0,0 +1,20 @@
1
+ :stores:
2
+ :master:
3
+ :url: http://www.master10.com
4
+ :txt: http://www.master10.com.py/importar/arquivos/lista.master.txt
5
+ :delimiter: "|"
6
+ :nave:
7
+ :url: http://www.navenet.com
8
+ :txt: http://www.navenet.com/gerartxt.aspx
9
+ :delimiter: !ruby/regexp /\s{3,}/
10
+ :nova:
11
+ :url: http://www.novadvance.com.br
12
+ :txt: http://www.novadvance.com.br/database/lista/lista.txt
13
+ :delimiter: !ruby/regexp /\s{3,}/
14
+ :albor:
15
+ :url: http://www.alboradainfo.com
16
+ :txt: http://www.alboradainfo.com/lista/lista_alborada.txt
17
+ :delimiter: !ruby/regexp /\s{1,}/
18
+
19
+ # TODO
20
+ # http://www.icompy.com/upload/precios/200907251505270.lista.txt
data/pyradise.gemspec ADDED
@@ -0,0 +1,61 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{pyradise}
8
+ s.version = "0.2.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Marcos Piccinini"]
12
+ s.date = %q{2009-10-10}
13
+ s.default_executable = %q{pyradise}
14
+ s.email = %q{x@nofxx.com}
15
+ s.executables = ["pyradise"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".gitignore",
23
+ "LICENSE",
24
+ "README.rdoc",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/pyradise",
28
+ "lib/pyradise.rb",
29
+ "lib/pyradise/migrate.rb",
30
+ "lib/pyradise/product.rb",
31
+ "lib/stores.yml",
32
+ "pyradise.gemspec",
33
+ "script/console",
34
+ "spec/pyradise/product_spec.rb",
35
+ "spec/pyradise_spec.rb",
36
+ "spec/spec_helper.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/nofxx/pyradise}
39
+ s.rdoc_options = ["--charset=UTF-8"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.5}
42
+ s.summary = %q{Paraguay gem!}
43
+ s.test_files = [
44
+ "spec/spec_helper.rb",
45
+ "spec/pyradise_spec.rb",
46
+ "spec/pyradise/product_spec.rb"
47
+ ]
48
+
49
+ if s.respond_to? :specification_version then
50
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
51
+ s.specification_version = 3
52
+
53
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
54
+ s.add_runtime_dependency(%q<sequel>, [">= 0"])
55
+ else
56
+ s.add_dependency(%q<sequel>, [">= 0"])
57
+ end
58
+ else
59
+ s.add_dependency(%q<sequel>, [">= 0"])
60
+ end
61
+ end
data/script/console ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # Pyradise
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ ['irb', 'pyradise', 'readline', 'rubygems'].each {|e| require e }
6
+
7
+ #history_file = File.join(ENV["HOME"], '.myrb_history')
8
+ #IO.readlines(history_file).each {|e| Readline::HISTORY << e.chomp } if File.exists?(history_file)
9
+ while (input = Readline.readline('>> ', true)) != 'exit'
10
+ begin puts "=> #{eval(input).inspect}"; rescue Exception; puts "Error: #{$!}" end
11
+ end
12
+ #File.open(history_file, 'w') {|f| f.write Readline::HISTORY.to_a.join("\n") }
@@ -0,0 +1,40 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "Product" do
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
9
+ end
10
+
11
+ it "should have a price" do
12
+ @p.price.should eql(1000)
13
+ end
14
+
15
+ it "should have a store" do
16
+ @p.store.should eql("foo")
17
+ end
18
+
19
+ it "should have prices" do
20
+ @p.prices.should eql({88=>1000})
21
+ end
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
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
40
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ describe "Pyradise" do
4
+ it "should fetch the stores" do
5
+ pending
6
+ Time.stub_chain(:now, :to_i).and_return(55)
7
+ Pyradise.should_receive(:open).with("a","wb").and_return(mf = mock("File"))
8
+ Pyradise.should_receive(:open).with("http://www.master10.com.py/importar/arquivos/lista.master.txt").and_return(mr = mock("Remote"))
9
+ mr.should_receive(:read).and_return("11| Cool stuff | 20.00")
10
+ mf.should_receive(:write).with("11| Cool stuff | 20.00").and_return true
11
+ mf.should_receive(:close).and_return true
12
+ Product.should_receive(:create).with({:store=>:master,:sid=>"11", :price=>" 20.00", :name=>" Cool stuff "})
13
+ Pyradise.fetch.should be_true
14
+ end
15
+
16
+
17
+ end
18
+
@@ -0,0 +1,16 @@
1
+ require 'spec'
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
+ require 'pyradise'
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
12
+
13
+ Spec::Runner.configure do |config|
14
+
15
+ end
16
+
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pyradise
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Marcos Piccinini
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-10 00:00:00 -03:00
13
+ default_executable: pyradise
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: sequel
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
+ description:
26
+ email: x@nofxx.com
27
+ executables:
28
+ - pyradise
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Rakefile
40
+ - VERSION
41
+ - bin/pyradise
42
+ - lib/pyradise.rb
43
+ - lib/pyradise/migrate.rb
44
+ - lib/pyradise/product.rb
45
+ - lib/stores.yml
46
+ - pyradise.gemspec
47
+ - script/console
48
+ - spec/pyradise/product_spec.rb
49
+ - spec/pyradise_spec.rb
50
+ - spec/spec_helper.rb
51
+ has_rdoc: true
52
+ homepage: http://github.com/nofxx/pyradise
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --charset=UTF-8
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.3.5
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Paraguay gem!
79
+ test_files:
80
+ - spec/spec_helper.rb
81
+ - spec/pyradise_spec.rb
82
+ - spec/pyradise/product_spec.rb