crack 0.1.8 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of crack might be problematic. Click here for more details.
- data/README.rdoc +1 -1
- data/Rakefile +6 -26
- data/crack.gemspec +25 -36
- data/lib/crack.rb +1 -1
- data/lib/crack/core_extensions.rb +2 -2
- data/lib/crack/json.rb +15 -4
- data/lib/crack/xml.rb +6 -2
- data/test/hash_test.rb +7 -6
- data/test/json_test.rb +18 -5
- data/test/xml_test.rb +10 -0
- metadata +15 -18
- data/.gitignore +0 -6
data/README.rdoc
CHANGED
@@ -7,7 +7,7 @@ Really simple JSON and XML parsing, ripped from Merb and Rails. The XML parser i
|
|
7
7
|
Releases are tagged on github and also released as gems on github and rubyforge. Master is pushed to whenever I add a patch or a new feature. To build from master, you can clone the code, generate the updated gemspec, build the gem and install.
|
8
8
|
|
9
9
|
* rake gemspec
|
10
|
-
* gem build
|
10
|
+
* gem build crack.gemspec
|
11
11
|
* gem install the gem that was built
|
12
12
|
|
13
13
|
== note on patches/pull requests
|
data/Rakefile
CHANGED
@@ -1,6 +1,9 @@
|
|
1
|
+
$:.unshift("lib")
|
1
2
|
require 'rubygems'
|
2
3
|
require 'rake'
|
3
|
-
|
4
|
+
|
5
|
+
$:.unshift(File.expand_path('lib', File.dirname(__FILE__)))
|
6
|
+
require 'crack'
|
4
7
|
|
5
8
|
begin
|
6
9
|
require 'jeweler'
|
@@ -16,16 +19,7 @@ begin
|
|
16
19
|
end
|
17
20
|
Jeweler::GemcutterTasks.new
|
18
21
|
rescue LoadError
|
19
|
-
puts "Jeweler not available. Install it with: sudo gem install
|
20
|
-
end
|
21
|
-
|
22
|
-
require 'rake/rdoctask'
|
23
|
-
Rake::RDocTask.new do |rdoc|
|
24
|
-
rdoc.rdoc_dir = 'rdoc'
|
25
|
-
rdoc.title = 'crack'
|
26
|
-
rdoc.options << '--line-numbers' << '--inline-source'
|
27
|
-
rdoc.rdoc_files.include('README*')
|
28
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
puts "Jeweler not available. Install it with: sudo gem install jeweler"
|
29
23
|
end
|
30
24
|
|
31
25
|
require 'rake/testtask'
|
@@ -35,18 +29,4 @@ Rake::TestTask.new(:test) do |test|
|
|
35
29
|
test.verbose = false
|
36
30
|
end
|
37
31
|
|
38
|
-
|
39
|
-
require 'rcov/rcovtask'
|
40
|
-
Rcov::RcovTask.new do |test|
|
41
|
-
test.libs << 'test'
|
42
|
-
test.pattern = 'test/**/*_test.rb'
|
43
|
-
test.verbose = true
|
44
|
-
end
|
45
|
-
rescue LoadError
|
46
|
-
task :rcov do
|
47
|
-
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
task :default => :test
|
32
|
+
task :default => :test
|
data/crack.gemspec
CHANGED
@@ -1,60 +1,49 @@
|
|
1
1
|
# Generated by jeweler
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{crack}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = [
|
12
|
-
s.date = %q{
|
11
|
+
s.authors = [%q{John Nunemaker}, %q{Wynn Netherland}]
|
12
|
+
s.date = %q{2011-09-17}
|
13
13
|
s.email = %q{nunemaker@gmail.com}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
16
|
-
|
16
|
+
"README.rdoc"
|
17
17
|
]
|
18
18
|
s.files = [
|
19
|
-
"
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
"test/xml_test.rb"
|
19
|
+
"History",
|
20
|
+
"LICENSE",
|
21
|
+
"README.rdoc",
|
22
|
+
"Rakefile",
|
23
|
+
"crack.gemspec",
|
24
|
+
"lib/crack.rb",
|
25
|
+
"lib/crack/core_extensions.rb",
|
26
|
+
"lib/crack/json.rb",
|
27
|
+
"lib/crack/xml.rb",
|
28
|
+
"test/crack_test.rb",
|
29
|
+
"test/data/twittersearch-firefox.json",
|
30
|
+
"test/data/twittersearch-ie.json",
|
31
|
+
"test/hash_test.rb",
|
32
|
+
"test/json_test.rb",
|
33
|
+
"test/string_test.rb",
|
34
|
+
"test/test_helper.rb",
|
35
|
+
"test/xml_test.rb"
|
37
36
|
]
|
38
37
|
s.homepage = %q{http://github.com/jnunemaker/crack}
|
39
|
-
s.
|
40
|
-
s.require_paths = ["lib"]
|
38
|
+
s.require_paths = [%q{lib}]
|
41
39
|
s.rubyforge_project = %q{crack}
|
42
|
-
s.rubygems_version = %q{1.
|
40
|
+
s.rubygems_version = %q{1.8.9}
|
43
41
|
s.summary = %q{Really simple JSON and XML parsing, ripped from Merb and Rails.}
|
44
|
-
s.test_files = [
|
45
|
-
"test/crack_test.rb",
|
46
|
-
"test/hash_test.rb",
|
47
|
-
"test/json_test.rb",
|
48
|
-
"test/string_test.rb",
|
49
|
-
"test/test_helper.rb",
|
50
|
-
"test/xml_test.rb"
|
51
|
-
]
|
52
42
|
|
53
43
|
if s.respond_to? :specification_version then
|
54
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
55
44
|
s.specification_version = 3
|
56
45
|
|
57
|
-
if Gem::Version.new(Gem::
|
46
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
58
47
|
else
|
59
48
|
end
|
60
49
|
else
|
data/lib/crack.rb
CHANGED
@@ -122,7 +122,7 @@ class Hash #:nodoc:
|
|
122
122
|
# #=> 'one="1" two="TWO"'
|
123
123
|
def to_xml_attributes
|
124
124
|
map do |k,v|
|
125
|
-
%{#{k.to_s.snake_case.sub(/^(.{1,1})/) { |m| m.downcase }}="#{v}"}
|
125
|
+
%{#{k.to_s.snake_case.sub(/^(.{1,1})/) { |m| m.downcase }}="#{v.to_s.gsub('"', '"')}"}
|
126
126
|
end.join(' ')
|
127
127
|
end
|
128
|
-
end
|
128
|
+
end
|
data/lib/crack/json.rb
CHANGED
@@ -16,16 +16,21 @@ module Crack
|
|
16
16
|
|
17
17
|
protected
|
18
18
|
def self.unescape(str)
|
19
|
-
|
19
|
+
# Force the encoding to be UTF-8 so we can perform regular expressions
|
20
|
+
# on 1.9.2 without blowing up.
|
21
|
+
# see http://stackoverflow.com/questions/1224204/ruby-mechanize-getting-force-encoding-exception for a similar issue
|
22
|
+
str.force_encoding('UTF-8') if defined?(Encoding) && str.respond_to?(:force_encoding)
|
23
|
+
str.gsub(/\\u0000/, "").gsub(/\\[u|U]([0-9a-fA-F]{4})/) { [$1.hex].pack("U") }
|
20
24
|
end
|
21
|
-
|
25
|
+
|
22
26
|
# matches YAML-formatted dates
|
23
27
|
DATE_REGEX = /^\d{4}-\d{2}-\d{2}$|^\d{4}-\d{1,2}-\d{1,2}[T \t]+\d{1,2}:\d{2}:\d{2}(\.[0-9]*)?(([ \t]*)Z|[-+]\d{2}?(:\d{2})?)?$/
|
24
28
|
|
25
29
|
# Ensure that ":" and "," are always followed by a space
|
26
30
|
def self.convert_json_to_yaml(json) #:nodoc:
|
31
|
+
json = String.new(json) #can't modify a frozen string
|
27
32
|
scanner, quoting, marks, pos, times = StringScanner.new(json), false, [], nil, []
|
28
|
-
while scanner.scan_until(/(\\['"]|['"
|
33
|
+
while scanner.scan_until(/(\\['"]|['":,\/\\]|\\.)/)
|
29
34
|
case char = scanner[1]
|
30
35
|
when '"', "'"
|
31
36
|
if !quoting
|
@@ -41,11 +46,17 @@ module Crack
|
|
41
46
|
end
|
42
47
|
quoting = false
|
43
48
|
end
|
49
|
+
when "/"
|
50
|
+
if !quoting
|
51
|
+
json[scanner.pos - 1] = "!ruby/regexp /"
|
52
|
+
scanner.pos += 13
|
53
|
+
scanner.scan_until(/\/[mix]*/)
|
54
|
+
end
|
44
55
|
when ":",","
|
45
56
|
marks << scanner.pos - 1 unless quoting
|
46
57
|
when "\\"
|
47
58
|
scanner.skip(/\\/)
|
48
|
-
end
|
59
|
+
end
|
49
60
|
end
|
50
61
|
|
51
62
|
if marks.empty?
|
data/lib/crack/xml.rb
CHANGED
@@ -82,8 +82,12 @@ class REXMLUtilityNode #:nodoc:
|
|
82
82
|
|
83
83
|
if @text
|
84
84
|
t = typecast_value( unnormalize_xml_entities( inner_html ) )
|
85
|
-
t.
|
86
|
-
|
85
|
+
if t.is_a?(String)
|
86
|
+
class << t
|
87
|
+
attr_accessor :attributes
|
88
|
+
end
|
89
|
+
t.attributes = attributes
|
90
|
+
end
|
87
91
|
return { name => t }
|
88
92
|
else
|
89
93
|
#change repeating groups into an array
|
data/test/hash_test.rb
CHANGED
@@ -3,16 +3,17 @@ require 'test_helper'
|
|
3
3
|
class CrackTest < Test::Unit::TestCase
|
4
4
|
context "to_xml_attributes" do
|
5
5
|
setup do
|
6
|
-
@hash = { :one => "ONE", "two" => "TWO" }
|
6
|
+
@hash = { :one => "ONE", "two" => "TWO", :three => "it \"should\" work" }
|
7
7
|
end
|
8
8
|
|
9
|
-
should "
|
9
|
+
should "turn the hash into xml attributes" do
|
10
10
|
attrs = @hash.to_xml_attributes
|
11
11
|
attrs.should =~ /one="ONE"/m
|
12
12
|
attrs.should =~ /two="TWO"/m
|
13
|
+
attrs.should =~ /three="it "should" work"/m
|
13
14
|
end
|
14
15
|
|
15
|
-
should '
|
16
|
+
should 'preserve _ in hash keys' do
|
16
17
|
attrs = {
|
17
18
|
:some_long_attribute => "with short value",
|
18
19
|
:crash => :burn,
|
@@ -38,7 +39,7 @@ class CrackTest < Test::Unit::TestCase
|
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
41
|
-
should '
|
42
|
+
should 'not leave a trailing &' do
|
42
43
|
{
|
43
44
|
:name => 'Bob',
|
44
45
|
:address => {
|
@@ -49,8 +50,8 @@ class CrackTest < Test::Unit::TestCase
|
|
49
50
|
}.to_params.should_not =~ /&$/
|
50
51
|
end
|
51
52
|
|
52
|
-
should '
|
53
|
+
should 'URL encode unsafe characters' do
|
53
54
|
{:q => "?&\" +"}.to_params.should == "q=%3F%26%22%20%2B"
|
54
55
|
end
|
55
56
|
end
|
56
|
-
end
|
57
|
+
end
|
data/test/json_test.rb
CHANGED
@@ -4,6 +4,7 @@ require 'test_helper'
|
|
4
4
|
class JsonTest < Test::Unit::TestCase
|
5
5
|
TESTS = {
|
6
6
|
%q({"data": "G\u00fcnter"}) => {"data" => "Günter"},
|
7
|
+
%q({"html": "\u003Cdiv\\u003E"}) => {"html" => "<div>"},
|
7
8
|
%q({"returnTo":{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
|
8
9
|
%q({returnTo:{"\/categories":"\/"}}) => {"returnTo" => {"/categories" => "/"}},
|
9
10
|
%q({"return\\"To\\":":{"\/categories":"\/"}}) => {"return\"To\":" => {"/categories" => "/"}},
|
@@ -19,6 +20,9 @@ class JsonTest < Test::Unit::TestCase
|
|
19
20
|
# no time zone
|
20
21
|
%({a: "2007-01-01 01:12:34"}) => {'a' => "2007-01-01 01:12:34"},
|
21
22
|
%({"bio": "1985-01-29: birthdate"}) => {'bio' => '1985-01-29: birthdate'},
|
23
|
+
%({"regex": /foo.*/}) => {'regex' => /foo.*/},
|
24
|
+
%({"regex": /foo.*/i}) => {'regex' => /foo.*/i},
|
25
|
+
%({"regex": /foo.*/mix}) => {'regex' => /foo.*/mix},
|
22
26
|
%([]) => [],
|
23
27
|
%({}) => {},
|
24
28
|
%(1) => 1,
|
@@ -27,24 +31,33 @@ class JsonTest < Test::Unit::TestCase
|
|
27
31
|
%(null) => nil,
|
28
32
|
%(true) => true,
|
29
33
|
%(false) => false,
|
30
|
-
%q("http:\/\/test.host\/posts\/1") => "http://test.host/posts/1"
|
34
|
+
%q("http:\/\/test.host\/posts\/1") => "http://test.host/posts/1",
|
35
|
+
|
36
|
+
# \u0000 and \x00 escape sequences
|
37
|
+
%q({"foo":"bar\u0000"}) => {"foo" => "bar"},
|
38
|
+
%q({"foo":"bar\u0000baz"}) => {"foo" => "barbaz"},
|
39
|
+
%q(bar\u0000) => "bar",
|
40
|
+
%q(bar\u0000baz) => "barbaz",
|
41
|
+
|
42
|
+
%q({"foo":"bar\x00"}) => {"foo" => "bar\x00"},
|
43
|
+
%q({"foo":"bar\x00baz"}) => {"foo" => "bar\x00baz"}
|
31
44
|
}
|
32
45
|
|
33
46
|
TESTS.each do |json, expected|
|
34
|
-
should "
|
47
|
+
should "decode json (#{json})" do
|
35
48
|
lambda {
|
36
49
|
Crack::JSON.parse(json).should == expected
|
37
50
|
}.should_not raise_error
|
38
51
|
end
|
39
52
|
end
|
40
53
|
|
41
|
-
should "
|
54
|
+
should "raise error for failed decoding" do
|
42
55
|
lambda {
|
43
56
|
Crack::JSON.parse(%({: 1}))
|
44
57
|
}.should raise_error(Crack::ParseError)
|
45
58
|
end
|
46
59
|
|
47
|
-
should "
|
60
|
+
should "be able to parse a JSON response from a Twitter search about 'firefox'" do
|
48
61
|
data = ''
|
49
62
|
File.open(File.dirname(__FILE__) + "/data/twittersearch-firefox.json", "r") { |f|
|
50
63
|
data = f.read
|
@@ -55,7 +68,7 @@ class JsonTest < Test::Unit::TestCase
|
|
55
68
|
}.should_not raise_error(Crack::ParseError)
|
56
69
|
end
|
57
70
|
|
58
|
-
should "
|
71
|
+
should "be able to parse a JSON response from a Twitter search about 'internet explorer'" do
|
59
72
|
data = ''
|
60
73
|
File.open(File.dirname(__FILE__) + "/data/twittersearch-ie.json", "r") { |f|
|
61
74
|
data = f.read
|
data/test/xml_test.rb
CHANGED
@@ -98,6 +98,16 @@ class XmlTest < Test::Unit::TestCase
|
|
98
98
|
should "default attributes to empty hash if not present" do
|
99
99
|
@data['opt']['user'][1].attributes.should == {}
|
100
100
|
end
|
101
|
+
|
102
|
+
should "add 'attributes' accessor methods to parsed instances of String" do
|
103
|
+
@data['opt']['user'][0].respond_to?(:attributes).should be(true)
|
104
|
+
@data['opt']['user'][0].respond_to?(:attributes=).should be(true)
|
105
|
+
end
|
106
|
+
|
107
|
+
should "not add 'attributes' accessor methods to all instances of String" do
|
108
|
+
"some-string".respond_to?(:attributes).should be(false)
|
109
|
+
"some-string".respond_to?(:attributes=).should be(false)
|
110
|
+
end
|
101
111
|
end
|
102
112
|
|
103
113
|
should "should typecast an integer" do
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
hash: 23
|
5
|
+
prerelease:
|
5
6
|
segments:
|
6
7
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- John Nunemaker
|
@@ -15,8 +16,7 @@ autorequire:
|
|
15
16
|
bindir: bin
|
16
17
|
cert_chain: []
|
17
18
|
|
18
|
-
date:
|
19
|
-
default_executable:
|
19
|
+
date: 2011-09-17 00:00:00 Z
|
20
20
|
dependencies: []
|
21
21
|
|
22
22
|
description:
|
@@ -29,7 +29,6 @@ extra_rdoc_files:
|
|
29
29
|
- LICENSE
|
30
30
|
- README.rdoc
|
31
31
|
files:
|
32
|
-
- .gitignore
|
33
32
|
- History
|
34
33
|
- LICENSE
|
35
34
|
- README.rdoc
|
@@ -47,40 +46,38 @@ files:
|
|
47
46
|
- test/string_test.rb
|
48
47
|
- test/test_helper.rb
|
49
48
|
- test/xml_test.rb
|
50
|
-
has_rdoc: true
|
51
49
|
homepage: http://github.com/jnunemaker/crack
|
52
50
|
licenses: []
|
53
51
|
|
54
52
|
post_install_message:
|
55
|
-
rdoc_options:
|
56
|
-
|
53
|
+
rdoc_options: []
|
54
|
+
|
57
55
|
require_paths:
|
58
56
|
- lib
|
59
57
|
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
60
59
|
requirements:
|
61
60
|
- - ">="
|
62
61
|
- !ruby/object:Gem::Version
|
62
|
+
hash: 3
|
63
63
|
segments:
|
64
64
|
- 0
|
65
65
|
version: "0"
|
66
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
67
|
+
none: false
|
67
68
|
requirements:
|
68
69
|
- - ">="
|
69
70
|
- !ruby/object:Gem::Version
|
71
|
+
hash: 3
|
70
72
|
segments:
|
71
73
|
- 0
|
72
74
|
version: "0"
|
73
75
|
requirements: []
|
74
76
|
|
75
77
|
rubyforge_project: crack
|
76
|
-
rubygems_version: 1.
|
78
|
+
rubygems_version: 1.8.9
|
77
79
|
signing_key:
|
78
80
|
specification_version: 3
|
79
81
|
summary: Really simple JSON and XML parsing, ripped from Merb and Rails.
|
80
|
-
test_files:
|
81
|
-
|
82
|
-
- test/hash_test.rb
|
83
|
-
- test/json_test.rb
|
84
|
-
- test/string_test.rb
|
85
|
-
- test/test_helper.rb
|
86
|
-
- test/xml_test.rb
|
82
|
+
test_files: []
|
83
|
+
|