ipynbdiff 0.3.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c0839dd5e5fbcdf19b5525d859fa7d224ec1bb647d7131f9cc20487190ccea80
4
+ data.tar.gz: ca32de2c784712f66f2f1c8b5642b32fca0078eae0279c8b30f975216101d143
5
+ SHA512:
6
+ metadata.gz: 45353d2e38a4378cb5f785edb6b38d250bf38ce4934f8943dcbe08973e4c187942449d185d4a3af59649d9459c74071475b33f23033c192b4345b24f95a2fd78
7
+ data.tar.gz: 7d8df2c34356018dfe098c0f36e8fb8f3c189c8121411826b9923b406ead730856a9e46ca57124b4e4e23e0409e1fdf83c5785686ab6aa0254bcedca07b95246
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .tool-versions
2
+ .bundle
3
+
4
+
5
+ *.gem
6
+
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ gem 'diffy', '3.3.0'
4
+ gem 'json', '2.5.1'
5
+ gem 'rspec', '3.10.0'
data/Gemfile.lock ADDED
@@ -0,0 +1,29 @@
1
+ GEM
2
+ specs:
3
+ diff-lcs (1.4.4)
4
+ diffy (3.3.0)
5
+ json (2.5.1)
6
+ rspec (3.10.0)
7
+ rspec-core (~> 3.10.0)
8
+ rspec-expectations (~> 3.10.0)
9
+ rspec-mocks (~> 3.10.0)
10
+ rspec-core (3.10.1)
11
+ rspec-support (~> 3.10.0)
12
+ rspec-expectations (3.10.1)
13
+ diff-lcs (>= 1.2.0, < 2.0)
14
+ rspec-support (~> 3.10.0)
15
+ rspec-mocks (3.10.2)
16
+ diff-lcs (>= 1.2.0, < 2.0)
17
+ rspec-support (~> 3.10.0)
18
+ rspec-support (3.10.2)
19
+
20
+ PLATFORMS
21
+ x86_64-darwin-20
22
+
23
+ DEPENDENCIES
24
+ diffy (= 3.3.0)
25
+ json (= 2.5.1)
26
+ rspec (= 3.10.0)
27
+
28
+ BUNDLED WITH
29
+ 2.2.28
data/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # rb-ipynbdiff: Better Jupyter Notebook diffs, in Ruby
2
+
3
+ This is a port of [ipynbdiff](https://gitlab.com/gitlab-org/incubation-engineering/mlops/ipynbdiff)
data/ipynbdiff.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'ipynbdiff'
5
+ s.version = '0.3.1'
6
+ s.summary = 'Human Readble diffs for Jupyter Notebooks'
7
+ s.description = 'A simple hello world gem'
8
+ s.authors = ['Eduardo Bonet']
9
+ s.email = 'ebonet@gitlab.com'
10
+ # Specify which files should be added to the gem when it is released.
11
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
12
+ s.files = Dir.chdir(File.expand_path('..', __FILE__)) do
13
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|example)/}) }
14
+ end
15
+ s.homepage =
16
+ 'https://gitlab.com/gitlab-org/incubation-engineering/mlops/rb-ipynbdiff'
17
+ s.license = 'MIT'
18
+
19
+ s.require_paths = ['lib']
20
+
21
+ s.add_runtime_dependency 'diffy', '3.3.0'
22
+ s.add_runtime_dependency 'json', '2.5.1'
23
+
24
+ s.add_development_dependency 'bundler', '~> 2.2'
25
+ s.add_development_dependency 'guard-rspec'
26
+ s.add_development_dependency 'pry'
27
+ s.add_development_dependency 'rake'
28
+ s.add_development_dependency 'rspec'
29
+ end
data/lib/ipynbdiff.rb ADDED
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Human Readable Jupyter Diffs
4
+ module IpynbDiff
5
+ require 'transformer.rb'
6
+ require 'diffy'
7
+
8
+ @default_options = {
9
+ preprocess_input: TRUE,
10
+ write_output_to: nil,
11
+ format: :text,
12
+ sources_are_files: FALSE,
13
+ diff_opts: {
14
+ include_diff_info: FALSE
15
+ }
16
+ }.freeze
17
+
18
+ def self.prepare_input(to_prepare, load_from_file, preprocess)
19
+ prepared = to_prepare
20
+ prepared = File.read(prepared) if load_from_file
21
+ prepared = Transformer.transform(prepared) if preprocess
22
+
23
+ prepared
24
+ end
25
+
26
+ def self.diff(
27
+ from_notebook,
28
+ to_notebook,
29
+ options = {}
30
+ )
31
+ options = @default_options.merge(options)
32
+
33
+ from = prepare_input(from_notebook, options[:sources_are_files], options[:preprocess_input])
34
+ to = prepare_input(to_notebook, options[:sources_are_files], options[:preprocess_input])
35
+
36
+ d = Diffy::Diff.new(from, to, **options[:diff_opts]).to_s(options[:format])
37
+
38
+ File.write(options[:write_output_to], d) if options[:write_output_to]
39
+
40
+ d
41
+ end
42
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IpynbDiff
4
+ # Returns a markdown version of the Jupyter Notebook
5
+ class Transformer
6
+ require 'json'
7
+ require 'yaml'
8
+
9
+ def self.transform(notebook, include_metadata: TRUE)
10
+ notebook_json = JSON.parse(notebook)
11
+ transformed_blocks = notebook_json['cells'].map { |cell| transform_cell(cell, notebook_json) }
12
+ transformed_blocks.prepend(transform_metadata(notebook_json)) if include_metadata
13
+ transformed_blocks.join("\n")
14
+ end
15
+
16
+ def self.transform_cell(cell, notebook)
17
+ cell['cell_type'] == 'code' ? transform_code_cell(cell, notebook) : transform_text_cell(cell)
18
+ end
19
+
20
+ def self.transform_code_cell(cell, notebook)
21
+ tags = cell['metadata'].fetch('tags', []).join(' ')
22
+
23
+ [
24
+ %(<div class="cell code" data-id="#{cell['id']}" data-tags="#{tags}">\n\n),
25
+ %(``` #{notebook['metadata']['kernelspec']['language']}\n),
26
+ *cell['source'],
27
+ "\n```\n",
28
+ *cell['outputs'].map { |output| transform_output(output) },
29
+ "\n</div>\n"
30
+ ].join('')
31
+ end
32
+
33
+ def self.format_traceback(traceback)
34
+ traceback.map do |t|
35
+ t.split("\n").map do |line|
36
+ line.gsub(/\[[0-9][0-9;]*m/, '').sub("\u001B", ' ').gsub(/\u001B/, '').rstrip
37
+ end
38
+ end.join("\n")
39
+ end
40
+
41
+ def self.transform_execute_result(output)
42
+ [
43
+ %(\n<div class="output execute_result">\n\n),
44
+ *output['data']['text/plain'].map { |line| " #{line}" },
45
+ "\n\n</div>\n"
46
+ ].join('')
47
+ end
48
+
49
+ def self.transform_image_result(output)
50
+ if output['data'].key?('image/png')
51
+ [
52
+ %(\n<div class="output display_data">\n\n),
53
+ "![](data:image/png;base64,#{output['data']['image/png'].gsub("\n", '')})",
54
+ "\n\n</div>\n"
55
+ ].join('')
56
+ end
57
+ end
58
+
59
+ def self.transform_error_result(output)
60
+ [
61
+ %(\n<div class="output error">\n\n),
62
+ format_traceback(output['traceback']),
63
+ "\n\n</div>\n"
64
+ ].join('')
65
+ end
66
+
67
+ def self.transform_output(output)
68
+ case output['output_type']
69
+ when 'execute_result'
70
+ transform_execute_result(output)
71
+ when 'display_data'
72
+ transform_image_result(output)
73
+ when 'error'
74
+ transform_error_result(output)
75
+ end
76
+ end
77
+
78
+ def self.transform_text_cell(cell)
79
+ tags = cell['metadata'].fetch('tags', []).join(' ')
80
+ id = cell['id']
81
+ cell_type = cell['cell_type']
82
+
83
+ [
84
+ %(<div class="cell #{cell_type}" data-id="#{id}" data-tags="#{tags}">\n\n),
85
+ *cell['source'],
86
+ "\n\n</div>\n"
87
+ ].join('')
88
+ end
89
+
90
+ def self.transform_metadata(notebook_json)
91
+ {
92
+ 'jupyter' => {
93
+ 'kernelspec' => notebook_json['metadata']['kernelspec'],
94
+ 'language_info' => notebook_json['metadata']['language_info'],
95
+ 'nbformat' => notebook_json['nbformat'],
96
+ 'nbformat_minor' => notebook_json['nbformat_minor']
97
+ }
98
+ }.to_yaml + "---\n"
99
+ end
100
+ end
101
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ipynbdiff
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ platform: ruby
6
+ authors:
7
+ - Eduardo Bonet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-10-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: diffy
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.3.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.3.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 2.5.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 2.5.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard-rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: A simple hello world gem
112
+ email: ebonet@gitlab.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - ".gitignore"
118
+ - Gemfile
119
+ - Gemfile.lock
120
+ - README.md
121
+ - ipynbdiff.gemspec
122
+ - lib/ipynbdiff.rb
123
+ - lib/transformer.rb
124
+ homepage: https://gitlab.com/gitlab-org/incubation-engineering/mlops/rb-ipynbdiff
125
+ licenses:
126
+ - MIT
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 3.1.6
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Human Readble diffs for Jupyter Notebooks
147
+ test_files: []