sie 2.1.0 → 2.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.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MTZiMGU5Y2JlZWE3MjJkMDIxZGQ1NzQwNjlmZDRmZDk1YTYxMTk5Ng==
4
+ OTRlMWFiNTRkMmRjZDllMmY2MWYzYjFiMWYxZWI1MTNjNDNhODZkYw==
5
5
  data.tar.gz: !binary |-
6
- MTQzMTQ5ZTliZTc5NzA5ZGE5MWViNThkZjE1OTgwMGFkNTI3ODg5Nw==
6
+ MzliZThiOGNhNjZmODMyNzVkNTJhZWY0NzYzOTRjMGIyMjFkYTM1Zg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NzRiMTUwZTEyMzhmOTE4YTE2ZGU0Zjg0ZTk1Mzc5MTM0MTI0YjNhODVmMGRm
10
- ZTY2ZDFjZjFlM2YxZmQ4NGZkODIzZjhmNTRlNTY2NmMwZmE4NGVlNGM3Nzk0
11
- MTYxNGRiNjRkZjE2ZWI4NzJhMTllOGNmMWVmYWRiMWFhYTZjZmI=
9
+ ODJiZjc3ZDI5YWFiN2YxZTg0NTEwMTNjYjVjZDI4NjhlYWJhOGM4YzUyZjNi
10
+ Y2QxMDA2YmI4MjFiMDU3OWFhMjE5NmNjZTM2ZTRjYTdlMzFiOTA5OTcyNmQ4
11
+ ODdmNDAwYjZmNDRmZmM2NjY4ZDFhYzI0NTEwZDcyYTFkYmVkNzM=
12
12
  data.tar.gz: !binary |-
13
- MmExNTViM2VkY2M1OGExZmM4YjcwNzFhOTliNTQ1OWY5M2IzZjI0NzRlNjUx
14
- YTdhZmNlNTlkYTI5OWFhNjNlZjIyYWRjMjhkZGMzNDkxZjc3MGM2MTMzMDdm
15
- YWU2OWIwYTkwOGQ5NDU2NDc5N2Y1MDU0ZWY3ZGExMTBiYmZmYTg=
13
+ MzBlMzIzZTAyMGVkYTE1YWYyM2E4MDQ1NjM0MjMyMmU1Yjg3NGQ5MzBiMjFj
14
+ ZGJlMDY1MjhhZGJiZTQ4NTRmNzg0OTFkMGNmMjA5MTlmMjdmOGU0N2M1NzMz
15
+ NjI5ZjFjYzBhMTg5YzFlMTVmMjg1MGM0ZWY5YjQzZDIxODNkN2Q=
data/README.md CHANGED
@@ -124,6 +124,12 @@ File.open("path/to/file.se") do |f|
124
124
  end
125
125
  ```
126
126
 
127
+ By default the parser will raise an error if it encounters unknown entry types. Use the `lenient` option to avoid this:
128
+
129
+ ```ruby
130
+ parser = Sie::Parser.new(lenient: true)
131
+ ```
132
+
127
133
  For more info, see the specs.
128
134
 
129
135
  ## Developing
@@ -144,9 +150,10 @@ Getting the latest code and gems:
144
150
 
145
151
  1. Fork it
146
152
  2. Create your feature branch (`git checkout -b my-new-feature`)
147
- 3. Commit your changes (`git commit -am 'Add some feature'`)
148
- 4. Push to the branch (`git push origin my-new-feature`)
149
- 5. Create new Pull Request
153
+ 3. Try to be consistent with the local code style. `[ foo ]` not `[foo]`, double quotes not single quotes, small and well named methods, etc.
154
+ 4. Commit your changes (`git commit -am 'Add some feature'`)
155
+ 5. Push to the branch (`git push origin my-new-feature`)
156
+ 6. Create new Pull Request
150
157
 
151
158
  ## Credits and license
152
159
 
data/lib/sie/document.rb CHANGED
@@ -5,10 +5,11 @@ require "active_support/core_ext/module/delegation"
5
5
 
6
6
  module Sie
7
7
  class Document
8
- pattr_initialize :data_source
9
8
  # Because fortnox imposes these limits
10
9
  DESCRIPTION_LENGTH_MAX = 30
11
10
 
11
+ pattr_initialize :data_source
12
+
12
13
  def render
13
14
  add_header
14
15
  add_financial_years
data/lib/sie/parser.rb CHANGED
@@ -9,6 +9,12 @@ module Sie
9
9
  END_OF_ARRAY = "}"
10
10
  ENTRY = /^#/
11
11
 
12
+ attr_private :options
13
+
14
+ def initialize(options = {})
15
+ @options = options
16
+ end
17
+
12
18
  def parse(io)
13
19
  stack = []
14
20
  sie_file = SieFile.new
@@ -34,7 +40,13 @@ module Sie
34
40
  private
35
41
 
36
42
  def parse_line(line)
37
- LineParser.new(line).parse
43
+ LineParser.new(line, lenient: lenient).parse
44
+ rescue BuildEntry::InvalidEntryError => ex
45
+ raise ex, "#{ex.message}. Pass 'lenient: true' to Parser.new to avoid this exception."
46
+ end
47
+
48
+ def lenient
49
+ options.fetch(:lenient, false)
38
50
  end
39
51
  end
40
52
  end
@@ -0,0 +1,57 @@
1
+ module Sie
2
+ class Parser
3
+ class BuildEntry
4
+ method_object :line, :first_token, :tokens, :lenient
5
+
6
+ InvalidEntryError = Class.new(StandardError)
7
+
8
+ def call
9
+ if first_token.known_entry_type?
10
+ build_complete_entry
11
+ elsif lenient
12
+ build_empty_entry
13
+ else
14
+ raise_invalid_entry_error
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def build_complete_entry
21
+ entry = build_empty_entry
22
+ entry_type = first_token.entry_type
23
+
24
+ entry_type.each_with_index do |entry_type, i|
25
+ break if i >= tokens.size
26
+
27
+ if entry_type.is_a?(Hash)
28
+ skip_array(tokens, i)
29
+ next
30
+ else
31
+ label = entry_type
32
+ entry.attributes[label] = tokens[i].value
33
+ end
34
+ end
35
+
36
+ entry
37
+ end
38
+
39
+ def build_empty_entry
40
+ Entry.new(first_token.label)
41
+ end
42
+
43
+ def raise_invalid_entry_error
44
+ raise InvalidEntryError, "Unknown entry type: #{first_token.label}"
45
+ end
46
+
47
+ def skip_array(tokens, i)
48
+ if tokens[i].is_a?(Tokenizer::BeginArrayToken) &&
49
+ !tokens[i+1].is_a?(Tokenizer::EndArrayToken)
50
+ raise "We currently don't support metadata within entries as we haven't had a need for it yet (the data between {} in #{line})."
51
+ end
52
+
53
+ tokens.reject! { |token| token.is_a?(Tokenizer::EndArrayToken) }
54
+ end
55
+ end
56
+ end
57
+ end
@@ -1,32 +1,17 @@
1
1
  require "sie/parser/tokenizer"
2
2
  require "sie/parser/entry"
3
3
  require "sie/parser/sie_file"
4
+ require "sie/parser/build_entry"
4
5
 
5
6
  module Sie
6
7
  class Parser
7
8
  class LineParser
8
- pattr_initialize :line
9
+ pattr_initialize :line, [ :lenient ]
9
10
 
10
11
  def parse
11
12
  tokens = tokenize(line)
12
13
  first_token = tokens.shift
13
-
14
- entry = Entry.new(first_token.label)
15
- entry_type = first_token.entry_type
16
-
17
- entry_type.each_with_index do |entry_type, i|
18
- break if i >= tokens.size
19
-
20
- if entry_type.is_a?(Hash)
21
- skip_array(tokens, i)
22
- next
23
- else
24
- label = entry_type
25
- entry.attributes[label] = tokens[i].value
26
- end
27
- end
28
-
29
- entry
14
+ build_entry(first_token, tokens)
30
15
  end
31
16
 
32
17
  private
@@ -35,13 +20,8 @@ module Sie
35
20
  Tokenizer.new(line).tokenize
36
21
  end
37
22
 
38
- def skip_array(tokens, i)
39
- if tokens[i].is_a?(Tokenizer::BeginArrayToken) &&
40
- !tokens[i+1].is_a?(Tokenizer::EndArrayToken)
41
- raise "We currently don't support metadata within entries as we haven't had a need for it yet (the data between {} in #{line})."
42
- end
43
-
44
- tokens.reject! { |token| token.is_a?(Tokenizer::EndArrayToken) }
23
+ def build_entry(first_token, tokens)
24
+ BuildEntry.call(line, first_token, tokens, lenient)
45
25
  end
46
26
  end
47
27
  end
@@ -10,6 +10,10 @@ module Sie
10
10
  @value = value
11
11
  end
12
12
 
13
+ def known_entry_type?
14
+ Sie::Parser::ENTRY_TYPES.has_key?(label)
15
+ end
16
+
13
17
  def entry_type
14
18
  Sie::Parser::ENTRY_TYPES.fetch(label)
15
19
  end
data/lib/sie/version.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  module Sie
2
- VERSION = "2.1.0"
2
+ # For versioning see: http://semver.org/
3
+ VERSION = "2.2.0"
3
4
  end
@@ -0,0 +1,32 @@
1
+ #FLAGGA 0
2
+ #PROGRAM "fooconomic" "1.0"
3
+ #FORMAT PC8
4
+ #GEN 20130101
5
+ #SIETYP 4
6
+ #ORGNR 555555-5555
7
+ #FNAMN "Foocorp"
8
+ #ADRESS "Foocorp" "" "12345 City" "555-12345"
9
+ #KONTO 1510 "Accounts receivable"
10
+ #KTYP 1510 T
11
+ #SRU 1510 204
12
+ #KONTO 1930 "Bank account"
13
+ #KTYP 1930 T
14
+ #SRU 1930 200
15
+ #KONTO 2440 Supplier
16
+ #KTYP 2440 S
17
+ #SRU 2440 300
18
+ #KONTO 2610 "Utgaende moms, oreducerad "
19
+ #KTYP 2610 S
20
+ #SRU 2610 7369
21
+ #MOMSKOD 2610 10
22
+ #VER A 1 20130101 "Invoice" 20120105
23
+ {
24
+ #TRANS 1510 {} -200 20130101 "Coffee machine"
25
+ #TRANS 4100 {} 180 20130101 "Coffee machine"
26
+ #TRANS 2611 {} -20 20130101 "VAT"
27
+ }
28
+ #VER A 2 20130102 "Payment" 20120105
29
+ {
30
+ #TRANS 1510 {} -200 20130101 "Payment: Coffee machine"
31
+ #TRANS 1970 {} 200 20130101 "Payment: Coffee machine"
32
+ }
@@ -18,7 +18,39 @@ describe Sie::Parser do
18
18
  end
19
19
  end
20
20
 
21
- def open_file(fixture_file)
22
- File.open(File.join(File.dirname(__FILE__), "../#{fixture_file}"))
21
+ context "with unknown entries" do
22
+ let(:file_with_unknown_entries) { "fixtures/sie_file_with_unknown_entries.se" }
23
+
24
+ context "using a lenient parser" do
25
+ let(:parser) { Sie::Parser.new(lenient: true) }
26
+
27
+ it "handles unknown entries without raising error" do
28
+ open_file(file_with_unknown_entries) do |f|
29
+ expect { parser.parse(f) }.not_to raise_error
30
+ end
31
+ end
32
+
33
+ it "continues to parse the complete file after unknown entries" do
34
+ open_file(file_with_unknown_entries) do |f|
35
+ sie_file = parser.parse(f)
36
+
37
+ expect(sie_file.entries_with_label("ver").size).to eq(2)
38
+ end
39
+ end
40
+ end
41
+
42
+ context "with strict parser" do
43
+ let(:parser) { Sie::Parser.new }
44
+
45
+ it "raises error when encountering unknown entries" do
46
+ open_file(file_with_unknown_entries) do |f|
47
+ expect { parser.parse(f) }.to raise_error(/Unknown entry type: momskod.+Pass 'lenient: true'/)
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ def open_file(fixture_file, &block)
54
+ File.open(File.join(File.dirname(__FILE__), "../#{fixture_file}"), &block)
23
55
  end
24
56
  end
@@ -14,6 +14,26 @@ describe Sie::Parser::LineParser, "parse" do
14
14
  })
15
15
  end
16
16
 
17
+ context "with unknown entry" do
18
+ let(:line) { "#MOMSKOD 2611 10"}
19
+
20
+ context "using a lenient parser" do
21
+ let(:parser) { Sie::Parser::LineParser.new(line, lenient: true) }
22
+
23
+ it "raises no error when encountering unknown entries" do
24
+ expect { parser.parse }.not_to raise_error
25
+ end
26
+ end
27
+
28
+ context "using a strict parser" do
29
+ let(:parser) { Sie::Parser::LineParser.new(line) }
30
+
31
+ it "raises error when encountering unknown entries" do
32
+ expect { parser.parse }.to raise_error(/Unknown entry type/)
33
+ end
34
+ end
35
+ end
36
+
17
37
  it "fails if you have non empty metadata arrays until there is a need to support that" do
18
38
  parser = Sie::Parser::LineParser.new('#TRANS 2400 { 1 "2" } -200 20130101 "Foocorp expense"')
19
39
  expect(-> { parser.parse }).to raise_error(/don't support metadata/)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sie
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.0
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Barsoom AB
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-09 00:00:00.000000000 Z
11
+ date: 2015-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: attr_extras
@@ -99,6 +99,7 @@ files:
99
99
  - lib/sie/document/renderer.rb
100
100
  - lib/sie/document/voucher_series.rb
101
101
  - lib/sie/parser.rb
102
+ - lib/sie/parser/build_entry.rb
102
103
  - lib/sie/parser/entry.rb
103
104
  - lib/sie/parser/entry_types.rb
104
105
  - lib/sie/parser/line_parser.rb
@@ -113,6 +114,7 @@ files:
113
114
  - script/turbux_rspec
114
115
  - sie.gemspec
115
116
  - spec/fixtures/sie_file.se
117
+ - spec/fixtures/sie_file_with_unknown_entries.se
116
118
  - spec/integration/parser_spec.rb
117
119
  - spec/spec_helper.rb
118
120
  - spec/unit/document/renderer_spec.rb
@@ -147,6 +149,7 @@ specification_version: 4
147
149
  summary: Parses and generates SIE files (http://sie.se/)
148
150
  test_files:
149
151
  - spec/fixtures/sie_file.se
152
+ - spec/fixtures/sie_file_with_unknown_entries.se
150
153
  - spec/integration/parser_spec.rb
151
154
  - spec/spec_helper.rb
152
155
  - spec/unit/document/renderer_spec.rb