iostreams 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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/docs/config.md +13 -9
  3. data/docs/copy_files.md +20 -2
  4. data/docs/extensions.md +18 -4
  5. data/docs/formats.md +644 -16
  6. data/docs/path.md +18 -2
  7. data/docs/streams.md +54 -9
  8. data/docs/tutorial.md +14 -2
  9. data/docs/upgrading.md +470 -23
  10. data/lib/io_streams/builder/deprecations.rb +250 -0
  11. data/lib/io_streams/builder.rb +256 -39
  12. data/lib/io_streams/bzip2/reader.rb +18 -2
  13. data/lib/io_streams/bzip2/writer.rb +11 -2
  14. data/lib/io_streams/deprecation/methods.rb +51 -0
  15. data/lib/io_streams/deprecation/once.rb +27 -0
  16. data/lib/io_streams/deprecation/option_names.rb +26 -0
  17. data/lib/io_streams/deprecation/words.rb +42 -0
  18. data/lib/io_streams/deprecation.rb +259 -0
  19. data/lib/io_streams/encode/reader.rb +54 -3
  20. data/lib/io_streams/encode/writer.rb +19 -2
  21. data/lib/io_streams/encode.rb +99 -0
  22. data/lib/io_streams/errors.rb +51 -0
  23. data/lib/io_streams/gzip/reader.rb +11 -0
  24. data/lib/io_streams/io_streams.rb +365 -35
  25. data/lib/io_streams/line/reader.rb +2 -1
  26. data/lib/io_streams/line/utf8_reader.rb +23 -0
  27. data/lib/io_streams/path.rb +125 -35
  28. data/lib/io_streams/paths/file.rb +72 -9
  29. data/lib/io_streams/paths/http.rb +48 -2
  30. data/lib/io_streams/paths/matcher.rb +6 -3
  31. data/lib/io_streams/paths/s3.rb +180 -9
  32. data/lib/io_streams/paths/sftp.rb +47 -3
  33. data/lib/io_streams/paths.rb +23 -0
  34. data/lib/io_streams/pgp/reader.rb +18 -0
  35. data/lib/io_streams/pgp/writer.rb +16 -0
  36. data/lib/io_streams/pgp.rb +16 -2
  37. data/lib/io_streams/reader.rb +44 -0
  38. data/lib/io_streams/record/reader.rb +59 -68
  39. data/lib/io_streams/record/writer.rb +17 -10
  40. data/lib/io_streams/row/header_row.rb +21 -0
  41. data/lib/io_streams/row/reader.rb +52 -15
  42. data/lib/io_streams/row/writer.rb +64 -13
  43. data/lib/io_streams/schema/columns.rb +456 -0
  44. data/lib/io_streams/schema/constraints.rb +99 -0
  45. data/lib/io_streams/schema/field.rb +967 -0
  46. data/lib/io_streams/schema/json_number.rb +56 -0
  47. data/lib/io_streams/schema/keys.rb +78 -0
  48. data/lib/io_streams/schema/pattern.rb +257 -0
  49. data/lib/io_streams/schema/source.rb +31 -0
  50. data/lib/io_streams/schema.rb +616 -0
  51. data/lib/io_streams/stream.rb +836 -67
  52. data/lib/io_streams/symmetric_encryption/reader.rb +8 -0
  53. data/lib/io_streams/tabular/header.rb +29 -0
  54. data/lib/io_streams/tabular/header_mapping.rb +332 -0
  55. data/lib/io_streams/tabular/mapping.rb +165 -0
  56. data/lib/io_streams/tabular/parser/array.rb +5 -0
  57. data/lib/io_streams/tabular/parser/base.rb +24 -0
  58. data/lib/io_streams/tabular/parser/fixed.rb +197 -0
  59. data/lib/io_streams/tabular/parser/fixed_fields.rb +160 -0
  60. data/lib/io_streams/tabular/parser/hash.rb +10 -0
  61. data/lib/io_streams/tabular/parser/json.rb +17 -0
  62. data/lib/io_streams/tabular/parser/json_fields.rb +132 -0
  63. data/lib/io_streams/tabular/schema_mapping.rb +361 -0
  64. data/lib/io_streams/tabular.rb +344 -30
  65. data/lib/io_streams/utils.rb +441 -6
  66. data/lib/io_streams/version.rb +1 -1
  67. data/lib/io_streams/writer.rb +27 -0
  68. data/lib/io_streams/xlsx/cells.rb +127 -0
  69. data/lib/io_streams/xlsx/reader.rb +56 -0
  70. data/lib/io_streams/xlsx/schema_reader.rb +90 -0
  71. data/lib/io_streams/xlsx/v3_writer.rb +16 -0
  72. data/lib/io_streams/zip/reader.rb +7 -0
  73. data/lib/io_streams/zip/writer.rb +24 -2
  74. data/lib/iostreams.rb +21 -17
  75. metadata +28 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d74053d56262767ee38729e8fc3810416b340ec7e1a318c37a95579f392a92d6
4
- data.tar.gz: 7e6e2fa0088656a52a8fd9c45c78b96ed8b2c324e9f9379a091fcfdd3939dde9
3
+ metadata.gz: fedc839021ed6f9515ed91d584477debad754f05476169ee1bff4d0b5b161ee6
4
+ data.tar.gz: 8ac9d35f276306b6eb3feff0667229e0b8e5c61b7b37b05682c7a192f201a713
5
5
  SHA512:
6
- metadata.gz: a492f9f89787eae3675fcf0aef1a1fbc9f67e461a0c1d0c9422888fa4cc66277c55d39248041b79a50de1b0d321a51a013445379de93404b0f85105d48914962
7
- data.tar.gz: 2e6303a89a55bbbda4a9c73a19bdd6780823633afa4391d2fe3071ba8ca85e360a08214e76ed2e869182d8ed94388ed0454769b5d6dc41e540abf704d1c8a794
6
+ metadata.gz: 24aa6dd4c78acaed7bcc50d3c807a328e8f6828714fd17f8af245d68d32d8e5cc8e8810938e5f3f4ed66295369fc786b5c158fa2ef9a2d6037760a732bc35326
7
+ data.tar.gz: a2bd8ce524d37ab054de318b16176203515da7e24bf6907711fd521f5e7043ef55114c87529595a7fec727c73138b29baab55e80da1d20dee0c5b231dfabbe63
data/docs/config.md CHANGED
@@ -85,6 +85,15 @@ IOStreams.root(:downloads).to_s
85
85
  # => "s3://my-app-bucket-name/downloads"
86
86
  ~~~
87
87
 
88
+ The whole process shares a root, so set the streams, options, encoding, format and schema of a file on the path
89
+ joined to the root, rather than on the root itself. A path joined to a root keeps the arguments of the root, such as
90
+ its credentials or S3 options, but not the streams, options, encoding, format or schema set on the root:
91
+ ~~~ruby
92
+ IOStreams.join("daily.csv.pgp", root: :uploads).option(:pgp, passphrase: "secret").each(:hash) do |record|
93
+ p record
94
+ end
95
+ ~~~
96
+
88
97
  ## temp_dir
89
98
 
90
99
  When working with large files the standard temp file system location can be too small to handle downloading large
@@ -146,12 +155,7 @@ IOStreams also logs warnings for behavior that will change in the next major ver
146
155
 
147
156
  ## enforce_column_restrictions
148
157
 
149
- Applies `allowed_columns`, `required_columns` and `skip_unknown` to every input when reading
150
- records, including JSON records, so that renaming an uploaded file from `.csv` to `.json` cannot
151
- bypass them. Set it in an initializer:
152
-
153
- ~~~ruby
154
- IOStreams.enforce_column_restrictions = true
155
- ~~~
156
-
157
- Default: false. It will default to true in v3.0. See [Header options](formats#header-options).
158
+ Deprecated in v2.2, and removed in v3.0, with the column options that it applies to every input,
159
+ such as `allowed_columns`. A [schema](formats#schema) applies to every input instead, including the
160
+ keys of each JSON record, see
161
+ [Moving the column options to a schema](upgrading#moving-the-column-options-to-a-schema).
data/docs/copy_files.md CHANGED
@@ -59,7 +59,7 @@ Custom stream conversions can be applied to both the source and the target in a
59
59
  Here the source is read as binary and the target is PGP encrypted:
60
60
 
61
61
  ~~~ruby
62
- source = IOStreams.path("source_file").stream(:encode, encoding: "BINARY")
62
+ source = IOStreams.path("source_file").encoding("BINARY")
63
63
  IOStreams.path("target_file.pgp").option(:pgp, passphrase: "hello").copy_from(source)
64
64
  ~~~
65
65
 
@@ -72,4 +72,22 @@ IOStreams.path("target_file.json").copy_from(source, mode: :hash)
72
72
  ~~~
73
73
 
74
74
  Notes:
75
- * `mode` accepts `:line`, `:array`, or `:hash`, and only applies when `convert` is `true`.
75
+ * `mode` accepts `:line`, `:array`, or `:hash`, and only applies when `convert` is `true`. Any other mode raises
76
+ `ArgumentError` before the source or the target is opened.
77
+ * Without a `mode`, a copy into a file of another format, such as `people.csv` into `people.json` or `people.psv`,
78
+ copies the text of the source as it is, so that the target holds CSV text. This is deprecated, and reports a
79
+ deprecation warning, since IOStreams 3.0 converts the rows of such a copy into the format of the target, as the
80
+ `:array` mode does: supply `mode: :array` to convert the rows, or `mode: :hash` when either file is JSON, whose rows
81
+ are records, or `mode: :line` to copy the text as it is, which give the same result in both versions. A copy within
82
+ a format, such as `.csv.gz` into `.csv`, from or to a file whose format is not known, such as an IO or a `.txt` file,
83
+ or with `#raw`, is copied as it is in both, and so is a spreadsheet into CSV, since its text is CSV.
84
+
85
+ ## When a copy fails
86
+
87
+ * The source is opened before the target, so a source that does not exist, or cannot be read, raises before the target
88
+ is changed.
89
+ * A copy that raises before the target is opened, such as for a schema file that does not exist, leaves the target as
90
+ it was.
91
+ * When the copy fails part way, the target is not left with part of the file: a local file is removed, and an S3 or
92
+ SFTP file is only uploaded once the copy has written all of it, so an existing S3 object is kept.
93
+ * A move only deletes the source once the copy completed.
data/docs/extensions.md CHANGED
@@ -42,7 +42,9 @@ IOStreams.path("sample.csv.bz2").option(:bz2, small: true).read
42
42
 
43
43
  Options are strict, so an option that a stream does not accept raises an `ArgumentError`.
44
44
  See [Streams](streams#reading-and-writing-need-separate-options). The exception is BZip2, which
45
- ignores any other option and logs a warning. In v3.0 it will raise an `ArgumentError` too.
45
+ ignores any other option and logs a warning. One that neither reading nor writing takes also reports a
46
+ deprecation warning when it is set, since in v3.0 it will raise an `ArgumentError` too, while v3.0
47
+ ignores an option of the other direction, as BZip2 does.
46
48
 
47
49
  ## Reading an Excel Spreadsheet
48
50
 
@@ -56,23 +58,35 @@ end
56
58
  ~~~
57
59
 
58
60
  Notes:
61
+ * Its rows are read as CSV, so leave the format of the path unset, or set it to `format(:csv)`.
59
62
  * Since the underlying `creek` gem operates on files, when reading from a stream (for example S3 or HTTP)
60
63
  the contents are first downloaded into a temp file.
61
64
  * Writing xlsx files is not supported.
62
65
 
63
66
  ## Character encoding
64
67
 
65
- The special `:encode` stream converts the character encoding of the data being read or written.
66
- It is applied with `option` or `stream` rather than a file name extension:
68
+ The encode stream converts the character encoding of the text that the application reads or writes.
69
+ Set it with `encoding`, which keeps the streams that the file name implies, and also works for a stream without a
70
+ file name, or with streams set with `stream`:
67
71
 
68
72
  ~~~ruby
69
73
  IOStreams.path("sample.csv.gz").
70
- option(:encode, encoding: "UTF-8", cleaner: :printable, replace: "").
74
+ encoding("UTF-8", cleaner: :printable, replace: "").
71
75
  each do |line|
72
76
  puts line
73
77
  end
74
78
  ~~~
75
79
 
80
+ The encode stream is applied closest to the application, so above the data is decompressed first, and then
81
+ converted. Each call to `encoding` merges its options with those already set, and `encoding` without any
82
+ arguments returns the encoding that was set, or nil. An option that the encode stream does not take, or a value
83
+ that it does not accept, such as an encoding that Ruby does not know, raises `ArgumentError` when it is set, before
84
+ any file is written.
85
+
86
+ `encoding` replaces `option(:encode, ...)`, `stream(:encode, ...)` and a file name ending in `.encode`, which also
87
+ apply the encode stream. They are deprecated: each still works, and reports a deprecation warning, see
88
+ [Upgrading](upgrading#deprecated-and-what-replaces-it).
89
+
76
90
  Options:
77
91
 
78
92
  * `encoding: [String|Encoding]`