python-pickle 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +7 -0
  2. data/.document +3 -0
  3. data/.github/workflows/ruby.yml +27 -0
  4. data/.gitignore +5 -0
  5. data/.rspec +1 -0
  6. data/.yardopts +1 -0
  7. data/ChangeLog.md +14 -0
  8. data/Gemfile +15 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +149 -0
  11. data/Rakefile +13 -0
  12. data/gemspec.yml +25 -0
  13. data/lib/python/pickle/byte_array.rb +40 -0
  14. data/lib/python/pickle/deserializer.rb +595 -0
  15. data/lib/python/pickle/exceptions.rb +12 -0
  16. data/lib/python/pickle/instruction.rb +52 -0
  17. data/lib/python/pickle/instructions/add_items.rb +26 -0
  18. data/lib/python/pickle/instructions/append.rb +24 -0
  19. data/lib/python/pickle/instructions/appends.rb +26 -0
  20. data/lib/python/pickle/instructions/bin_bytes.rb +32 -0
  21. data/lib/python/pickle/instructions/bin_bytes8.rb +32 -0
  22. data/lib/python/pickle/instructions/bin_float.rb +29 -0
  23. data/lib/python/pickle/instructions/bin_get.rb +27 -0
  24. data/lib/python/pickle/instructions/bin_int1.rb +29 -0
  25. data/lib/python/pickle/instructions/bin_put.rb +29 -0
  26. data/lib/python/pickle/instructions/bin_string.rb +32 -0
  27. data/lib/python/pickle/instructions/bin_unicode.rb +32 -0
  28. data/lib/python/pickle/instructions/bin_unicode8.rb +32 -0
  29. data/lib/python/pickle/instructions/build.rb +24 -0
  30. data/lib/python/pickle/instructions/byte_array8.rb +32 -0
  31. data/lib/python/pickle/instructions/dict.rb +17 -0
  32. data/lib/python/pickle/instructions/dup.rb +24 -0
  33. data/lib/python/pickle/instructions/empty_dict.rb +26 -0
  34. data/lib/python/pickle/instructions/empty_list.rb +26 -0
  35. data/lib/python/pickle/instructions/empty_set.rb +26 -0
  36. data/lib/python/pickle/instructions/empty_tuple.rb +26 -0
  37. data/lib/python/pickle/instructions/ext1.rb +29 -0
  38. data/lib/python/pickle/instructions/ext2.rb +29 -0
  39. data/lib/python/pickle/instructions/ext4.rb +29 -0
  40. data/lib/python/pickle/instructions/float.rb +24 -0
  41. data/lib/python/pickle/instructions/frame.rb +29 -0
  42. data/lib/python/pickle/instructions/frozen_set.rb +26 -0
  43. data/lib/python/pickle/instructions/get.rb +27 -0
  44. data/lib/python/pickle/instructions/global.rb +62 -0
  45. data/lib/python/pickle/instructions/has_length_and_value.rb +58 -0
  46. data/lib/python/pickle/instructions/has_value.rb +50 -0
  47. data/lib/python/pickle/instructions/int.rb +24 -0
  48. data/lib/python/pickle/instructions/list.rb +24 -0
  49. data/lib/python/pickle/instructions/long.rb +24 -0
  50. data/lib/python/pickle/instructions/long1.rb +32 -0
  51. data/lib/python/pickle/instructions/long4.rb +32 -0
  52. data/lib/python/pickle/instructions/long_bin_get.rb +27 -0
  53. data/lib/python/pickle/instructions/mark.rb +24 -0
  54. data/lib/python/pickle/instructions/memoize.rb +26 -0
  55. data/lib/python/pickle/instructions/new_false.rb +24 -0
  56. data/lib/python/pickle/instructions/new_obj.rb +26 -0
  57. data/lib/python/pickle/instructions/new_obj_ex.rb +26 -0
  58. data/lib/python/pickle/instructions/new_true.rb +24 -0
  59. data/lib/python/pickle/instructions/next_buffer.rb +26 -0
  60. data/lib/python/pickle/instructions/none.rb +24 -0
  61. data/lib/python/pickle/instructions/pop.rb +24 -0
  62. data/lib/python/pickle/instructions/pop_mark.rb +24 -0
  63. data/lib/python/pickle/instructions/proto.rb +29 -0
  64. data/lib/python/pickle/instructions/put.rb +24 -0
  65. data/lib/python/pickle/instructions/readonly_buffer.rb +26 -0
  66. data/lib/python/pickle/instructions/reduce.rb +24 -0
  67. data/lib/python/pickle/instructions/set_item.rb +24 -0
  68. data/lib/python/pickle/instructions/set_items.rb +26 -0
  69. data/lib/python/pickle/instructions/short_bin_bytes.rb +32 -0
  70. data/lib/python/pickle/instructions/short_bin_string.rb +32 -0
  71. data/lib/python/pickle/instructions/short_bin_unicode.rb +32 -0
  72. data/lib/python/pickle/instructions/stack_global.rb +26 -0
  73. data/lib/python/pickle/instructions/stop.rb +24 -0
  74. data/lib/python/pickle/instructions/string.rb +24 -0
  75. data/lib/python/pickle/instructions/tuple.rb +24 -0
  76. data/lib/python/pickle/instructions/tuple1.rb +24 -0
  77. data/lib/python/pickle/instructions/tuple2.rb +24 -0
  78. data/lib/python/pickle/instructions/tuple3.rb +24 -0
  79. data/lib/python/pickle/protocol.rb +56 -0
  80. data/lib/python/pickle/protocol0.rb +399 -0
  81. data/lib/python/pickle/protocol1.rb +183 -0
  82. data/lib/python/pickle/protocol2.rb +229 -0
  83. data/lib/python/pickle/protocol3.rb +163 -0
  84. data/lib/python/pickle/protocol4.rb +285 -0
  85. data/lib/python/pickle/protocol5.rb +218 -0
  86. data/lib/python/pickle/py_class.rb +75 -0
  87. data/lib/python/pickle/py_object.rb +141 -0
  88. data/lib/python/pickle/tuple.rb +19 -0
  89. data/lib/python/pickle/version.rb +6 -0
  90. data/lib/python/pickle.rb +226 -0
  91. data/python-pickle.gemspec +62 -0
  92. data/spec/byte_array_spec.rb +54 -0
  93. data/spec/deserializer_spec.rb +1201 -0
  94. data/spec/fixtures/ascii_str_v3.pkl +0 -0
  95. data/spec/fixtures/ascii_str_v4.pkl +0 -0
  96. data/spec/fixtures/ascii_str_v5.pkl +0 -0
  97. data/spec/fixtures/bin_str_v0.pkl +3 -0
  98. data/spec/fixtures/bin_str_v1.pkl +0 -0
  99. data/spec/fixtures/bin_str_v2.pkl +0 -0
  100. data/spec/fixtures/bin_str_v3.pkl +0 -0
  101. data/spec/fixtures/bin_str_v4.pkl +0 -0
  102. data/spec/fixtures/bin_str_v5.pkl +0 -0
  103. data/spec/fixtures/bytearray_v0.pkl +10 -0
  104. data/spec/fixtures/bytearray_v1.pkl +0 -0
  105. data/spec/fixtures/bytearray_v2.pkl +0 -0
  106. data/spec/fixtures/bytearray_v3.pkl +0 -0
  107. data/spec/fixtures/bytearray_v4.pkl +0 -0
  108. data/spec/fixtures/bytearray_v5.pkl +0 -0
  109. data/spec/fixtures/class_v0.pkl +4 -0
  110. data/spec/fixtures/class_v1.pkl +0 -0
  111. data/spec/fixtures/class_v2.pkl +0 -0
  112. data/spec/fixtures/class_v3.pkl +0 -0
  113. data/spec/fixtures/class_v4.pkl +0 -0
  114. data/spec/fixtures/class_v5.pkl +0 -0
  115. data/spec/fixtures/dict_v0.pkl +6 -0
  116. data/spec/fixtures/dict_v1.pkl +0 -0
  117. data/spec/fixtures/dict_v2.pkl +0 -0
  118. data/spec/fixtures/dict_v3.pkl +0 -0
  119. data/spec/fixtures/dict_v4.pkl +0 -0
  120. data/spec/fixtures/dict_v5.pkl +0 -0
  121. data/spec/fixtures/escaped_str_v0.pkl +3 -0
  122. data/spec/fixtures/escaped_str_v1.pkl +0 -0
  123. data/spec/fixtures/escaped_str_v2.pkl +0 -0
  124. data/spec/fixtures/false_v0.pkl +2 -0
  125. data/spec/fixtures/false_v1.pkl +2 -0
  126. data/spec/fixtures/false_v2.pkl +1 -0
  127. data/spec/fixtures/false_v3.pkl +1 -0
  128. data/spec/fixtures/false_v4.pkl +1 -0
  129. data/spec/fixtures/false_v5.pkl +1 -0
  130. data/spec/fixtures/float_v0.pkl +2 -0
  131. data/spec/fixtures/float_v1.pkl +1 -0
  132. data/spec/fixtures/float_v2.pkl +1 -0
  133. data/spec/fixtures/float_v3.pkl +1 -0
  134. data/spec/fixtures/float_v4.pkl +0 -0
  135. data/spec/fixtures/float_v5.pkl +0 -0
  136. data/spec/fixtures/function_v0.pkl +4 -0
  137. data/spec/fixtures/function_v1.pkl +0 -0
  138. data/spec/fixtures/function_v2.pkl +0 -0
  139. data/spec/fixtures/function_v3.pkl +0 -0
  140. data/spec/fixtures/function_v4.pkl +0 -0
  141. data/spec/fixtures/function_v5.pkl +0 -0
  142. data/spec/fixtures/hex_str_v0.pkl +3 -0
  143. data/spec/fixtures/hex_str_v1.pkl +0 -0
  144. data/spec/fixtures/hex_str_v2.pkl +0 -0
  145. data/spec/fixtures/int_v0.pkl +2 -0
  146. data/spec/fixtures/int_v1.pkl +1 -0
  147. data/spec/fixtures/int_v2.pkl +1 -0
  148. data/spec/fixtures/int_v3.pkl +1 -0
  149. data/spec/fixtures/int_v4.pkl +1 -0
  150. data/spec/fixtures/int_v5.pkl +1 -0
  151. data/spec/fixtures/list_v0.pkl +7 -0
  152. data/spec/fixtures/list_v1.pkl +0 -0
  153. data/spec/fixtures/list_v2.pkl +0 -0
  154. data/spec/fixtures/list_v3.pkl +0 -0
  155. data/spec/fixtures/list_v4.pkl +0 -0
  156. data/spec/fixtures/list_v5.pkl +0 -0
  157. data/spec/fixtures/long_v0.pkl +2 -0
  158. data/spec/fixtures/long_v1.pkl +2 -0
  159. data/spec/fixtures/long_v2.pkl +0 -0
  160. data/spec/fixtures/long_v3.pkl +0 -0
  161. data/spec/fixtures/long_v4.pkl +0 -0
  162. data/spec/fixtures/long_v5.pkl +0 -0
  163. data/spec/fixtures/nested_dict_v0.pkl +12 -0
  164. data/spec/fixtures/nested_dict_v1.pkl +0 -0
  165. data/spec/fixtures/nested_dict_v2.pkl +0 -0
  166. data/spec/fixtures/nested_dict_v3.pkl +0 -0
  167. data/spec/fixtures/nested_dict_v4.pkl +0 -0
  168. data/spec/fixtures/nested_dict_v5.pkl +0 -0
  169. data/spec/fixtures/nested_list_v0.pkl +9 -0
  170. data/spec/fixtures/nested_list_v1.pkl +0 -0
  171. data/spec/fixtures/nested_list_v2.pkl +0 -0
  172. data/spec/fixtures/nested_list_v3.pkl +0 -0
  173. data/spec/fixtures/nested_list_v4.pkl +0 -0
  174. data/spec/fixtures/nested_list_v5.pkl +0 -0
  175. data/spec/fixtures/none_v0.pkl +1 -0
  176. data/spec/fixtures/none_v1.pkl +1 -0
  177. data/spec/fixtures/none_v2.pkl +1 -0
  178. data/spec/fixtures/none_v3.pkl +1 -0
  179. data/spec/fixtures/none_v4.pkl +1 -0
  180. data/spec/fixtures/none_v5.pkl +1 -0
  181. data/spec/fixtures/object_v0.pkl +19 -0
  182. data/spec/fixtures/object_v1.pkl +0 -0
  183. data/spec/fixtures/object_v2.pkl +0 -0
  184. data/spec/fixtures/object_v3.pkl +0 -0
  185. data/spec/fixtures/object_v4.pkl +0 -0
  186. data/spec/fixtures/object_v5.pkl +0 -0
  187. data/spec/fixtures/str_v0.pkl +3 -0
  188. data/spec/fixtures/str_v1.pkl +0 -0
  189. data/spec/fixtures/str_v2.pkl +0 -0
  190. data/spec/fixtures/str_v3.pkl +0 -0
  191. data/spec/fixtures/str_v4.pkl +0 -0
  192. data/spec/fixtures/str_v5.pkl +0 -0
  193. data/spec/fixtures/true_v0.pkl +2 -0
  194. data/spec/fixtures/true_v1.pkl +2 -0
  195. data/spec/fixtures/true_v2.pkl +1 -0
  196. data/spec/fixtures/true_v3.pkl +1 -0
  197. data/spec/fixtures/true_v4.pkl +1 -0
  198. data/spec/fixtures/true_v5.pkl +1 -0
  199. data/spec/fixtures/unicode_str_v0.pkl +3 -0
  200. data/spec/fixtures/unicode_str_v1.pkl +0 -0
  201. data/spec/fixtures/unicode_str_v2.pkl +0 -0
  202. data/spec/fixtures/unicode_str_v3.pkl +0 -0
  203. data/spec/fixtures/unicode_str_v4.pkl +0 -0
  204. data/spec/fixtures/unicode_str_v5.pkl +0 -0
  205. data/spec/generate_pickles2.py +41 -0
  206. data/spec/generate_pickles3.py +40 -0
  207. data/spec/integration/load/protocol0_spec.rb +258 -0
  208. data/spec/integration/load/protocol1_spec.rb +258 -0
  209. data/spec/integration/load/protocol2_spec.rb +258 -0
  210. data/spec/integration/load/protocol3_spec.rb +258 -0
  211. data/spec/integration/load/protocol4_spec.rb +258 -0
  212. data/spec/integration/load/protocol5_spec.rb +258 -0
  213. data/spec/integration/parse/protocol0_spec.rb +467 -0
  214. data/spec/integration/parse/protocol1_spec.rb +459 -0
  215. data/spec/integration/parse/protocol2_spec.rb +471 -0
  216. data/spec/integration/parse/protocol3_spec.rb +407 -0
  217. data/spec/integration/parse/protocol4_spec.rb +439 -0
  218. data/spec/integration/parse/protocol5_spec.rb +419 -0
  219. data/spec/pickle_spec.rb +163 -0
  220. data/spec/protocol0_read_instruction_examples.rb +211 -0
  221. data/spec/protocol0_spec.rb +445 -0
  222. data/spec/protocol1_read_instruction_examples.rb +156 -0
  223. data/spec/protocol1_spec.rb +59 -0
  224. data/spec/protocol2_read_instruction_examples.rb +135 -0
  225. data/spec/protocol2_spec.rb +128 -0
  226. data/spec/protocol3_read_instruction_examples.rb +29 -0
  227. data/spec/protocol3_spec.rb +32 -0
  228. data/spec/protocol4_read_instruction_examples.rb +142 -0
  229. data/spec/protocol4_spec.rb +58 -0
  230. data/spec/protocol5_spec.rb +68 -0
  231. data/spec/py_class_spec.rb +62 -0
  232. data/spec/py_object_spec.rb +149 -0
  233. data/spec/spec_helper.rb +3 -0
  234. data/spec/tuple_spec.rb +18 -0
  235. metadata +325 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ea86f43e4b83bacac94635b88e2c9deeb6eb4aaa553f1770e4943554389422fc
4
+ data.tar.gz: 973327ecbd8f2c1df7d0ac10f37d76628745e00da9317ab655a9f12644fef441
5
+ SHA512:
6
+ metadata.gz: 8b95a73ff2ebfba7c9ca97648df7c7b3b6be14df61e0e6f4943e3e263a5f300696e79d8cf57aacc7bd9d572bcf3c00a5ec88162e1dd8cc627617afe01414499d
7
+ data.tar.gz: 73a9a106cfa346d3d74835cf9369732f041fdb2faafdb8a030f1e9ec6b58831e8b7c8aee3a05bec687d11d2d4ea9d48a00d4fcf164f0c686eb84c1248b15f056
data/.document ADDED
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.*
3
+ LICENSE.txt
@@ -0,0 +1,27 @@
1
+ name: CI
2
+
3
+ on: [ push, pull_request ]
4
+
5
+ jobs:
6
+ tests:
7
+ runs-on: ubuntu-latest
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ ruby:
12
+ - 3.0
13
+ - 3.1
14
+ - 3.2
15
+ - jruby
16
+ # - truffleruby
17
+ name: Ruby ${{ matrix.ruby }}
18
+ steps:
19
+ - uses: actions/checkout@v2
20
+ - name: Set up Ruby
21
+ uses: ruby/setup-ruby@v1
22
+ with:
23
+ ruby-version: ${{ matrix.ruby }}
24
+ - name: Install dependencies
25
+ run: bundle install --jobs 4 --retry 3
26
+ - name: Run tests
27
+ run: bundle exec rake test
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ /Gemfile.lock
2
+ /coverage
3
+ /doc/
4
+ /pkg/
5
+ /vendor/bundle/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --format documentation
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup markdown --title "Python::Pickle Documentation" --protected --quiet
data/ChangeLog.md ADDED
@@ -0,0 +1,14 @@
1
+ ### 0.1.0 / 2023-02-18
2
+
3
+ * Initial release:
4
+ * Supports deserializing Python Pickle data into Ruby objects.
5
+ * Supports serializing Ruby objects into Python Pickle data.
6
+ * Optionally supports only parsing Python Pickle data streams for debugging
7
+ purposes.
8
+ * Supports Pickle protocol 0, protocol 1, protocol 2, protocol 3, protocol 4,
9
+ and protocol 5.
10
+ * Can parse both Python 2 and Python 3 Pickled data.
11
+ * Supports deserializing Python `tuple` and `bytearray` objects.
12
+ * Supports mapping Python functions to Ruby methods.
13
+ * Supports mapping Python classes to Ruby classes.
14
+
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'rake'
7
+ gem 'rubygems-tasks', '~> 0.2'
8
+ gem 'rspec', '~> 3.0'
9
+ gem 'simplecov', '~> 0.20'
10
+ gem 'kramdown'
11
+ gem 'redcarpet', platform: :mri
12
+ gem 'yard', '~> 0.9'
13
+ gem 'yard-spellcheck', require: false
14
+ gem 'dead_end', require: false
15
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2023 Hal Brodigan
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.md ADDED
@@ -0,0 +1,149 @@
1
+ # python-pickle.rb
2
+
3
+ [![CI](https://github.com/postmodern/python-pickle.rb/actions/workflows/ruby.yml/badge.svg)](https://github.com/postmodern/python-pickle.rb/actions/workflows/ruby.yml)
4
+ [![Gem Version](https://badge.fury.io/rb/python-pickle.svg)](https://badge.fury.io/rb/python-pickle)
5
+
6
+ * [Source](https://github.com/postmodern/python-pickle.rb)
7
+ * [Issues](https://github.com/postmodern/python-pickle.rb/issues)
8
+ * [Documentation](https://rubydoc.info/gems/python-pickle)
9
+
10
+ ## Description
11
+
12
+ python-pickle is a modern Ruby implementation of the Python Pickle serialization
13
+ format.
14
+
15
+ ## Features
16
+
17
+ * Supports deserializing Python Pickle data into Ruby objects.
18
+ * Optionally supports only parsing Python Pickle data streams for debugging
19
+ purposes.
20
+ * Supports Pickle protocol 0, protocol 1, protocol 2, protocol 3, protocol 4,
21
+ and protocol 5.
22
+ * Can parse both Python 2 and Python 3 Pickled data.
23
+ * Supports deserializing Python `tuple` and `bytearray` objects.
24
+ * Supports mapping Python functions to Ruby methods.
25
+ * Supports mapping Python classes to Ruby classes.
26
+
27
+ ## TODO
28
+
29
+ * Add support for writing Python Pickle data.
30
+ * Add support for serializing Ruby objects to Python Pickle data.
31
+
32
+ ## Requirements
33
+
34
+ * [Ruby] >= 3.0.0
35
+
36
+ [Ruby]: https://www.ruby-lang.org/
37
+
38
+ ## Install
39
+
40
+ ```shell
41
+ $ gem install python-pickle
42
+ ```
43
+
44
+ ### gemspec
45
+
46
+ ```ruby
47
+ gem.add_dependency 'python-pickle', '~> 1.0'
48
+ ```
49
+
50
+ ### Gemfile
51
+
52
+ ```ruby
53
+ gem 'python-pickle', '~> 1.0'
54
+ ```
55
+
56
+ ## Examples
57
+
58
+ Load a Python Pickle string:
59
+
60
+ ```ruby
61
+ Python::Pickle.load("\x80\x04\x95\x10\x00\x00\x00\x00\x00\x00\x00}\x94\x8C\x03foo\x94\x8C\x03bar\x94s.")
62
+ # => {"foo"=>"bar"}
63
+ ```
64
+
65
+ Load a Python Pickle stream:
66
+
67
+ ```ruby
68
+ Python::Pickle.load(io)
69
+ # => ...
70
+ ```
71
+
72
+ Loading a Python Pickle file:
73
+
74
+ ```ruby
75
+ Python::Pickle.load_file('dict.pkl')
76
+ # => {"foo"=>"bar"}
77
+ ```
78
+
79
+ Loading Python `bytearray` objects:
80
+
81
+ ```ruby
82
+ pickle = "\x80\x05\x95\x0E\x00\x00\x00\x00\x00\x00\x00\x96\x03\x00\x00\x00\x00\x00\x00\x00ABC\x94."
83
+
84
+ Python::Pickle.load(pickle)
85
+ # => #<Python::Pickle::ByteArray: "ABC">
86
+ ```
87
+
88
+ Loading Python objects:
89
+
90
+ ```ruby
91
+ ickle = "\x80\x04\x95,\x00\x00\x00\x00\x00\x00\x00\x8C\b__main__\x94\x8C\aMyClass\x94\x93\x94)\x81\x94}\x94(\x8C\x01x\x94KA\x8C\x01y\x94KBub."
92
+
93
+ Python::Pickle.load(pickle)
94
+ # =>
95
+ # #<Python::Pickle::PyObject:0x00007f48c9ba7598
96
+ # @attributes={"y"=>66, "x"=>65},
97
+ # @init_args=[],
98
+ # @init_kwargs={},
99
+ # @py_class=#<Python::Pickle::PyClass: __main__.MyClass>>
100
+ ```
101
+
102
+ Mapping Python classes to Ruby classes:
103
+
104
+ ```ruby
105
+ class MyClass
106
+
107
+ attr_reader :x
108
+ attr_reader :y
109
+
110
+ def __setstate__(attributes)
111
+ @x = attributes['x']
112
+ @y = attributes['y']
113
+ end
114
+
115
+ end
116
+
117
+ pickle = "\x80\x04\x95,\x00\x00\x00\x00\x00\x00\x00\x8C\b__main__\x94\x8C\aMyClass\x94\x93\x94)\x81\x94}\x94(\x8C\x01x\x94KA\x8C\x01y\x94KBub."
118
+
119
+ Python::Pickle.load(pickle, constants: {
120
+ '__main__' => {
121
+ 'MyClass' => MyClass
122
+ }
123
+ })
124
+ # => #<MyClass:0x00007f48c5c28980 @x=65, @y=66>
125
+ ```
126
+
127
+ Parsing and inspecting a pickle file:
128
+
129
+ ```ruby
130
+ require 'python/pickle'
131
+
132
+ Python::Pickle.parse(File.open('dict.pkl'))
133
+ # =>
134
+ # [#<Python::Pickle::Instructions::Mark: MARK>,
135
+ # #<Python::Pickle::Instructions::Dict: DICT>,
136
+ # #<Python::Pickle::Instructions::Put: PUT 0>,
137
+ # #<Python::Pickle::Instructions::String: STRING "foo">,
138
+ # #<Python::Pickle::Instructions::Put: PUT 1>,
139
+ # #<Python::Pickle::Instructions::String: STRING "bar">,
140
+ # #<Python::Pickle::Instructions::Put: PUT 2>,
141
+ # #<Python::Pickle::Instructions::SetItem: SETITEM>,
142
+ # #<Python::Pickle::Instructions::Stop: STOP>]
143
+ ```
144
+
145
+ ## Copyright
146
+
147
+ Copyright (c) 2023 Hal Brodigan
148
+
149
+ See {file:LICENSE.txt} for details.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+
3
+ require 'rubygems/tasks'
4
+ Gem::Tasks.new
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new
8
+ task :test => :spec
9
+ task :default => :spec
10
+
11
+ require 'yard'
12
+ YARD::Rake::YardocTask.new
13
+ task :doc => :yard
data/gemspec.yml ADDED
@@ -0,0 +1,25 @@
1
+ name: python-pickle
2
+ summary: A modern Ruby implementation of the Python Pickle serialization format.
3
+ description: |
4
+ python-pickle is a modern Ruby implementation of the Python Pickle
5
+ serialization format. It supports protocol 0, protocol 1, protocol 2,
6
+ protocol 3, protocol 4, and protocol 5, allowing it to parse both Python 2
7
+ and Python 3 pickle data.
8
+
9
+ license: MIT
10
+ authors: Postmodern
11
+ email: postmodern.mod3@gmail.com
12
+ homepage: https://github.com/postmodern/python-pickle.rb#readme
13
+ has_yard: true
14
+
15
+ metadata:
16
+ documentation_uri: https://rubydoc.info/gems/python-pickle
17
+ source_code_uri: https://github.com/postmodern/python-pickle.rb
18
+ bug_tracker_uri: https://github.com/postmodern/python-pickle.rb/issues
19
+ changelog_uri: https://github.com/postmodern/python-pickle.rb/blob/master/ChangeLog.md
20
+ rubygems_mfa_required: 'true'
21
+
22
+ required_ruby_version: ">= 3.0.0"
23
+
24
+ development_dependencies:
25
+ bundler: ~> 2.0
@@ -0,0 +1,40 @@
1
+ module Python
2
+ module Pickle
3
+ #
4
+ # Represents a Python `bytearray` object.
5
+ #
6
+ class ByteArray < String
7
+
8
+ # Mapping of python `codecs` encoding names and their Ruby equivalents.
9
+ #
10
+ # @api private
11
+ ENCODINGS = {
12
+ nil => Encoding::ASCII_8BIT,
13
+ 'latin-1' => Encoding::ISO_8859_1
14
+ }
15
+
16
+ #
17
+ # Initializes the byte array.
18
+ #
19
+ # @param [String] string
20
+ # The contents of the byte array.
21
+ #
22
+ # @param [String, nil] encoding
23
+ # The optional encoding name.
24
+ #
25
+ def initialize(string='', encoding=nil)
26
+ super(string, encoding: ENCODINGS.fetch(encoding))
27
+ end
28
+
29
+ #
30
+ # Inspects the byte array object.
31
+ #
32
+ # @return [String]
33
+ #
34
+ def inspect
35
+ "#<#{self.class}: #{super}>"
36
+ end
37
+
38
+ end
39
+ end
40
+ end