cloud_events 0.7.0 → 0.8.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 +4 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +13 -0
- data/CONTRIBUTING.md +167 -0
- data/MAINTAINERS.md +5 -0
- data/README.md +8 -38
- data/RELEASING.md +25 -0
- data/lib/cloud_events/content_type.rb +32 -32
- data/lib/cloud_events/event/field_interpreter.rb +46 -38
- data/lib/cloud_events/event/opaque.rb +3 -3
- data/lib/cloud_events/event/utils.rb +9 -9
- data/lib/cloud_events/event/v0.rb +19 -19
- data/lib/cloud_events/event/v1.rb +21 -21
- data/lib/cloud_events/event.rb +4 -4
- data/lib/cloud_events/format.rb +13 -14
- data/lib/cloud_events/http_binding.rb +88 -88
- data/lib/cloud_events/json_format.rb +65 -66
- data/lib/cloud_events/text_format.rb +6 -7
- data/lib/cloud_events/version.rb +1 -1
- metadata +9 -10
- data/LICENSE.md +0 -202
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e92a0db6d57da2784f958e81f3416ade3c4c6c1e5e7830571be444c84a1001a0
|
|
4
|
+
data.tar.gz: e48bad4cf6cf8797c6f5a16817f6951a1c3b2138778fa2e6779b58fd49f28f21
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4429473d95e6150514f796a907f74a96741ab9378e2c833ed6945fbe4f5d85fe654d0bb6502960900c349721b167f90fc62994a2525a3fd372bc7ea9468c66f6
|
|
7
|
+
data.tar.gz: 91f22bf6c0b20357326166d896e0036dd90ae32f66b7c233a63cb3e060abac51827b2a9d560f6324830db2b5240e436d0f942c99a41bf8a1c711a48fe6af8d80
|
data/.yardopts
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
### v0.8.0 / 2025-11-04
|
|
4
|
+
|
|
5
|
+
* BREAKING CHANGE: Raise AttributeError if an illegal attribute name is used
|
|
6
|
+
* ADDED: Require Ruby 2.7 or later
|
|
7
|
+
* FIXED: Improved hashing algorithm for opaque event objects
|
|
8
|
+
* FIXED: Removed dependency on base64 gem
|
|
9
|
+
* FIXED: Raise AttributeError if an illegal attribute name is used
|
|
10
|
+
* DOCS: Add link to the security mailing list
|
|
11
|
+
|
|
12
|
+
### v0.7.1 / 2023-10-04
|
|
13
|
+
|
|
14
|
+
* DOCS: Governance docs per CE PR 1226
|
|
15
|
+
|
|
3
16
|
### v0.7.0 / 2022-01-14
|
|
4
17
|
|
|
5
18
|
* HttpBinding#probable_event? returns false if the request method is GET or HEAD.
|
data/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# Contributing to CloudEvents' Ruby SDK
|
|
2
|
+
|
|
3
|
+
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
|
4
|
+
|
|
5
|
+
We welcome contributions from the community! Please take some time to become
|
|
6
|
+
acquainted with the process before submitting a pull request. There are just
|
|
7
|
+
a few things to keep in mind.
|
|
8
|
+
|
|
9
|
+
# Pull Requests
|
|
10
|
+
|
|
11
|
+
Typically, a pull request should relate to an existing issue. If you have
|
|
12
|
+
found a bug, want to add an improvement, or suggest an API change, please
|
|
13
|
+
create an issue before proceeding with a pull request. For very minor changes
|
|
14
|
+
such as typos in the documentation this isn't really necessary.
|
|
15
|
+
|
|
16
|
+
## Pull Request Guidelines
|
|
17
|
+
|
|
18
|
+
Here you will find step by step guidance for creating, submitting and updating
|
|
19
|
+
a pull request in this repository. We hope it will help you have an easy time
|
|
20
|
+
managing your work and a positive, satisfying experience when contributing
|
|
21
|
+
your code. Thanks for getting involved! :rocket:
|
|
22
|
+
|
|
23
|
+
* [Getting Started](#getting-started)
|
|
24
|
+
* [Branches](#branches)
|
|
25
|
+
* [Commit Messages](#commit-messages)
|
|
26
|
+
* [Staying current with main](#staying-current-with-main)
|
|
27
|
+
* [Submitting and Updating a Pull Request](#submitting-and-updating-a-pull-request)
|
|
28
|
+
* [Congratulations!](#congratulations)
|
|
29
|
+
|
|
30
|
+
## Getting Started
|
|
31
|
+
|
|
32
|
+
When creating a pull request, first fork this repository and clone it to your
|
|
33
|
+
local development environment. Then add this repository as the upstream.
|
|
34
|
+
|
|
35
|
+
```console
|
|
36
|
+
git clone https://github.com/mygithuborg/sdk-ruby.git
|
|
37
|
+
cd sdk-ruby
|
|
38
|
+
git remote add upstream https://github.com/cloudevents/sdk-ruby.git
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Branches
|
|
42
|
+
|
|
43
|
+
The first thing you'll need to do is create a branch for your work.
|
|
44
|
+
If you are submitting a pull request that fixes or relates to an existing
|
|
45
|
+
GitHub issue, you can use the issue number in your branch name to keep things
|
|
46
|
+
organized.
|
|
47
|
+
|
|
48
|
+
```console
|
|
49
|
+
git fetch upstream
|
|
50
|
+
git reset --hard upstream/main
|
|
51
|
+
git checkout FETCH_HEAD
|
|
52
|
+
git checkout -b 48-fix-http-agent-error
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Commit Messages
|
|
56
|
+
|
|
57
|
+
Please follow the
|
|
58
|
+
[Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/#summary).
|
|
59
|
+
The first line of your commit should be prefixed with a type, be a single
|
|
60
|
+
sentence with no period, and succinctly indicate what this commit changes.
|
|
61
|
+
|
|
62
|
+
All commit message lines should be kept to fewer than 80 characters if possible.
|
|
63
|
+
|
|
64
|
+
An example of a good commit message.
|
|
65
|
+
|
|
66
|
+
```log
|
|
67
|
+
docs: remove 0.1, 0.2 spec support from README
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Signing your commits
|
|
71
|
+
|
|
72
|
+
Each commit must be signed. Use the `--signoff` flag for your commits.
|
|
73
|
+
|
|
74
|
+
```console
|
|
75
|
+
git commit --signoff
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This will add a line to every git commit message:
|
|
79
|
+
|
|
80
|
+
Signed-off-by: Joe Smith <joe.smith@email.com>
|
|
81
|
+
|
|
82
|
+
Use your real name (sorry, no pseudonyms or anonymous contributions.)
|
|
83
|
+
|
|
84
|
+
The sign-off is a signature line at the end of your commit message. Your
|
|
85
|
+
signature certifies that you wrote the patch or otherwise have the right to pass
|
|
86
|
+
it on as open-source code. See [developercertificate.org](http://developercertificate.org/)
|
|
87
|
+
for the full text of the certification.
|
|
88
|
+
|
|
89
|
+
Be sure to have your `user.name` and `user.email` set in your git config.
|
|
90
|
+
If your git config information is set properly then viewing the `git log`
|
|
91
|
+
information for your commit will look something like this:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
Author: Joe Smith <joe.smith@email.com>
|
|
95
|
+
Date: Thu Feb 2 11:41:15 2018 -0800
|
|
96
|
+
|
|
97
|
+
Update README
|
|
98
|
+
|
|
99
|
+
Signed-off-by: Joe Smith <joe.smith@email.com>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Notice the `Author` and `Signed-off-by` lines match. If they don't your PR will
|
|
103
|
+
be rejected by the automated DCO check.
|
|
104
|
+
|
|
105
|
+
## Staying Current with `main`
|
|
106
|
+
|
|
107
|
+
As you are working on your branch, changes may happen on `main`. Before
|
|
108
|
+
submitting your pull request, be sure that your branch has been updated
|
|
109
|
+
with the latest commits.
|
|
110
|
+
|
|
111
|
+
```console
|
|
112
|
+
git fetch upstream
|
|
113
|
+
git rebase upstream/main
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
This may cause conflicts if the files you are changing on your branch are
|
|
117
|
+
also changed on main. Error messages from `git` will indicate if conflicts
|
|
118
|
+
exist and what files need attention. Resolve the conflicts in each file, then
|
|
119
|
+
continue with the rebase with `git rebase --continue`.
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
If you've already pushed some changes to your `origin` fork, you'll
|
|
123
|
+
need to force push these changes.
|
|
124
|
+
|
|
125
|
+
```console
|
|
126
|
+
git push -f origin 48-fix-http-agent-error
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Submitting and Updating Your Pull Request
|
|
130
|
+
|
|
131
|
+
Before submitting a pull request, you should make sure that all of the tests
|
|
132
|
+
successfully pass.
|
|
133
|
+
|
|
134
|
+
Once you have sent your pull request, `main` may continue to evolve
|
|
135
|
+
before your pull request has landed. If there are any commits on `main`
|
|
136
|
+
that conflict with your changes, you may need to update your branch with
|
|
137
|
+
these changes before the pull request can land. Resolve conflicts the same
|
|
138
|
+
way as before.
|
|
139
|
+
|
|
140
|
+
```console
|
|
141
|
+
git fetch upstream
|
|
142
|
+
git rebase upstream/main
|
|
143
|
+
# fix any potential conflicts
|
|
144
|
+
git push -f origin 48-fix-http-agent-error
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This will cause the pull request to be updated with your changes, and
|
|
148
|
+
CI will rerun.
|
|
149
|
+
|
|
150
|
+
A maintainer may ask you to make changes to your pull request. Sometimes these
|
|
151
|
+
changes are minor and shouldn't appear in the commit log. For example, you may
|
|
152
|
+
have a typo in one of your code comments that should be fixed before merge.
|
|
153
|
+
You can prevent this from adding noise to the commit log with an interactive
|
|
154
|
+
rebase. See the [git documentation](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History)
|
|
155
|
+
for details.
|
|
156
|
+
|
|
157
|
+
```console
|
|
158
|
+
git commit -m "fixup: fix typo"
|
|
159
|
+
git rebase -i upstream/main # follow git instructions
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Once you have rebased your commits, you can force push to your fork as before.
|
|
163
|
+
|
|
164
|
+
## Congratulations!
|
|
165
|
+
|
|
166
|
+
Congratulations! You've done it! We really appreciate the time and energy
|
|
167
|
+
you've given to the project. Thank you.
|
data/MAINTAINERS.md
ADDED
data/README.md
CHANGED
|
@@ -184,31 +184,6 @@ few things to keep in mind.
|
|
|
184
184
|
* **Make sure CI passes.** Invoke `toys ci` to run the tests locally before
|
|
185
185
|
opening a pull request. This will include code style checks.
|
|
186
186
|
|
|
187
|
-
### Releasing
|
|
188
|
-
|
|
189
|
-
Releases can be performed only by users with write access to the repository.
|
|
190
|
-
|
|
191
|
-
To perform a release:
|
|
192
|
-
|
|
193
|
-
1. Go to the GitHub Actions tab, and launch the "Request Release" workflow.
|
|
194
|
-
You can leave the input field blank.
|
|
195
|
-
|
|
196
|
-
2. The workflow will analyze the commit messages since the last release, and
|
|
197
|
-
open a pull request with a new version and a changelog entry. You can
|
|
198
|
-
optionally edit this pull request to modify the changelog or change the
|
|
199
|
-
version released.
|
|
200
|
-
|
|
201
|
-
3. Merge the pull request (keeping the `release: pending` label set.) Once the
|
|
202
|
-
CI tests have run successfully, a job will run automatically to perform the
|
|
203
|
-
release, including tagging the commit in git, building and releasing a gem,
|
|
204
|
-
and building and pushing documentation.
|
|
205
|
-
|
|
206
|
-
These tasks can also be performed manually by running the appropriate scripts
|
|
207
|
-
locally. See `toys release request --help` and `toys release perform --help`
|
|
208
|
-
for more information.
|
|
209
|
-
|
|
210
|
-
If a release fails, you may need to delete the release tag before retrying.
|
|
211
|
-
|
|
212
187
|
### For more information
|
|
213
188
|
|
|
214
189
|
* Library documentation: https://cloudevents.github.io/sdk-ruby
|
|
@@ -243,18 +218,13 @@ for how PR reviews and approval, and our
|
|
|
243
218
|
[Code of Conduct](https://github.com/cloudevents/spec/blob/master/community/GOVERNANCE.md#additional-information)
|
|
244
219
|
information.
|
|
245
220
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
Licensed under the Apache License, Version 2.0 (the "License");
|
|
251
|
-
you may not use this software except in compliance with the License.
|
|
252
|
-
You may obtain a copy of the License at
|
|
221
|
+
If there is a security concern with one of the CloudEvents specifications, or
|
|
222
|
+
with one of the project's SDKs, please send an email to
|
|
223
|
+
[cncf-cloudevents-security@lists.cncf.io](mailto:cncf-cloudevents-security@lists.cncf.io).
|
|
253
224
|
|
|
254
|
-
|
|
225
|
+
## Additional SDK Resources
|
|
255
226
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
limitations under the License.
|
|
227
|
+
- [List of current active maintainers](MAINTAINERS.md)
|
|
228
|
+
- [How to contribute to the project](CONTRIBUTING.md)
|
|
229
|
+
- [SDK's License](LICENSE)
|
|
230
|
+
- [SDK's Release process](RELEASING.md)
|
data/RELEASING.md
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
Releases can be performed only by users with write access to the repository.
|
|
4
|
+
|
|
5
|
+
To perform a release:
|
|
6
|
+
|
|
7
|
+
1. Go to the GitHub Actions tab, and launch the "Request Release" workflow.
|
|
8
|
+
You can leave the input field blank.
|
|
9
|
+
|
|
10
|
+
2. The workflow will analyze the commit messages since the last release, and
|
|
11
|
+
open a pull request with a new version and a changelog entry. You can
|
|
12
|
+
optionally edit this pull request to modify the changelog or change the
|
|
13
|
+
version released.
|
|
14
|
+
|
|
15
|
+
3. Merge the pull request (keeping the `release: pending` label set.) Once the
|
|
16
|
+
CI tests have run successfully, a job will run automatically to perform the
|
|
17
|
+
release, including tagging the commit in git, building and releasing a gem,
|
|
18
|
+
and building and pushing documentation.
|
|
19
|
+
|
|
20
|
+
These tasks can also be performed manually by running the appropriate scripts
|
|
21
|
+
locally. See `toys release request --help` and `toys release perform --help`
|
|
22
|
+
for more information.
|
|
23
|
+
|
|
24
|
+
If a release fails, you may need to delete the release tag before retrying.
|
|
25
|
+
|
|
@@ -24,7 +24,7 @@ module CloudEvents
|
|
|
24
24
|
# @param default_charset [String] Optional. The charset to use if none is
|
|
25
25
|
# specified. Defaults to `us-ascii`.
|
|
26
26
|
#
|
|
27
|
-
def initialize
|
|
27
|
+
def initialize(string, default_charset: nil)
|
|
28
28
|
@string = string.to_s
|
|
29
29
|
@media_type = "text"
|
|
30
30
|
@subtype_base = @subtype = "plain"
|
|
@@ -32,9 +32,9 @@ module CloudEvents
|
|
|
32
32
|
@params = []
|
|
33
33
|
@charset = default_charset || "us-ascii"
|
|
34
34
|
@error_message = nil
|
|
35
|
-
parse
|
|
35
|
+
parse(consume_comments(@string.strip))
|
|
36
36
|
@canonical_string = "#{@media_type}/#{@subtype}" +
|
|
37
|
-
@params.map { |k, v| "; #{k}=#{maybe_quote
|
|
37
|
+
@params.map { |k, v| "; #{k}=#{maybe_quote(v)}" }.join
|
|
38
38
|
full_freeze
|
|
39
39
|
end
|
|
40
40
|
|
|
@@ -102,13 +102,13 @@ module CloudEvents
|
|
|
102
102
|
# @param key [String]
|
|
103
103
|
# @return [Array<String>]
|
|
104
104
|
#
|
|
105
|
-
def param_values
|
|
105
|
+
def param_values(key)
|
|
106
106
|
key = key.downcase
|
|
107
107
|
@params.inject([]) { |a, (k, v)| key == k ? a << v : a }
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
## @private
|
|
111
|
-
def ==
|
|
111
|
+
def ==(other)
|
|
112
112
|
other.is_a?(ContentType) && canonical_string == other.canonical_string
|
|
113
113
|
end
|
|
114
114
|
alias eql? ==
|
|
@@ -124,16 +124,16 @@ module CloudEvents
|
|
|
124
124
|
|
|
125
125
|
private
|
|
126
126
|
|
|
127
|
-
def parse
|
|
128
|
-
@media_type, str = consume_token
|
|
129
|
-
str = consume_special
|
|
130
|
-
@subtype, str = consume_token
|
|
131
|
-
@subtype_base, @subtype_format = @subtype.split
|
|
127
|
+
def parse(str)
|
|
128
|
+
@media_type, str = consume_token(str, downcase: true, error_message: "Failed to parse media type")
|
|
129
|
+
str = consume_special(str, "/")
|
|
130
|
+
@subtype, str = consume_token(str, downcase: true, error_message: "Failed to parse subtype")
|
|
131
|
+
@subtype_base, @subtype_format = @subtype.split("+", 2)
|
|
132
132
|
until str.empty?
|
|
133
|
-
str = consume_special
|
|
134
|
-
name, str = consume_token
|
|
135
|
-
str = consume_special
|
|
136
|
-
val, str = consume_token_or_quoted
|
|
133
|
+
str = consume_special(str, ";")
|
|
134
|
+
name, str = consume_token(str, downcase: true, error_message: "Faled to parse attribute name")
|
|
135
|
+
str = consume_special(str, "=", error_message: "Failed to find value for attribute #{name}")
|
|
136
|
+
val, str = consume_token_or_quoted(str, error_message: "Failed to parse value for attribute #{name}")
|
|
137
137
|
@params << [name, val]
|
|
138
138
|
@charset = val if name == "charset"
|
|
139
139
|
end
|
|
@@ -141,34 +141,34 @@ module CloudEvents
|
|
|
141
141
|
@error_message = e.message
|
|
142
142
|
end
|
|
143
143
|
|
|
144
|
-
def consume_token
|
|
145
|
-
match = /^([\w!#$%&'*+.\^`{|}-]+)(.*)$/.match
|
|
146
|
-
raise
|
|
144
|
+
def consume_token(str, downcase: false, error_message: nil)
|
|
145
|
+
match = /^([\w!#$%&'*+.\^`{|}-]+)(.*)$/.match(str)
|
|
146
|
+
raise(ParseError, error_message || "Expected token") unless match
|
|
147
147
|
token = match[1]
|
|
148
148
|
token.downcase! if downcase
|
|
149
|
-
str = consume_comments
|
|
149
|
+
str = consume_comments(match[2].strip)
|
|
150
150
|
[token, str]
|
|
151
151
|
end
|
|
152
152
|
|
|
153
|
-
def consume_special
|
|
154
|
-
raise
|
|
155
|
-
consume_comments
|
|
153
|
+
def consume_special(str, expected, error_message: nil)
|
|
154
|
+
raise(ParseError, error_message || "Expected #{expected.inspect}") unless str.start_with?(expected)
|
|
155
|
+
consume_comments(str[1..].strip)
|
|
156
156
|
end
|
|
157
157
|
|
|
158
|
-
def consume_token_or_quoted
|
|
159
|
-
return consume_token
|
|
158
|
+
def consume_token_or_quoted(str, error_message: nil)
|
|
159
|
+
return consume_token(str) unless str.start_with?('"')
|
|
160
160
|
arr = []
|
|
161
161
|
index = 1
|
|
162
162
|
loop do
|
|
163
163
|
char = str[index]
|
|
164
164
|
case char
|
|
165
165
|
when nil
|
|
166
|
-
raise
|
|
166
|
+
raise(ParseError, error_message || "Quoted-string never finished")
|
|
167
167
|
when "\""
|
|
168
168
|
break
|
|
169
169
|
when "\\"
|
|
170
170
|
char = str[index + 1]
|
|
171
|
-
raise
|
|
171
|
+
raise(ParseError, error_message || "Quoted-string never finished") unless char
|
|
172
172
|
arr << char
|
|
173
173
|
index += 2
|
|
174
174
|
else
|
|
@@ -177,34 +177,34 @@ module CloudEvents
|
|
|
177
177
|
end
|
|
178
178
|
end
|
|
179
179
|
index += 1
|
|
180
|
-
str = consume_comments
|
|
180
|
+
str = consume_comments(str[index..].strip)
|
|
181
181
|
[arr.join, str]
|
|
182
182
|
end
|
|
183
183
|
|
|
184
|
-
def consume_comments
|
|
185
|
-
return str unless str.start_with?
|
|
184
|
+
def consume_comments(str)
|
|
185
|
+
return str unless str.start_with?("(")
|
|
186
186
|
index = 1
|
|
187
187
|
loop do
|
|
188
188
|
char = str[index]
|
|
189
189
|
case char
|
|
190
190
|
when nil
|
|
191
|
-
raise
|
|
191
|
+
raise(ParseError, "Comment never finished")
|
|
192
192
|
when ")"
|
|
193
193
|
break
|
|
194
194
|
when "\\"
|
|
195
195
|
index += 2
|
|
196
196
|
when "("
|
|
197
|
-
str = consume_comments
|
|
197
|
+
str = consume_comments(str[index..])
|
|
198
198
|
index = 0
|
|
199
199
|
else
|
|
200
200
|
index += 1
|
|
201
201
|
end
|
|
202
202
|
end
|
|
203
203
|
index += 1
|
|
204
|
-
consume_comments
|
|
204
|
+
consume_comments(str[index..].strip)
|
|
205
205
|
end
|
|
206
206
|
|
|
207
|
-
def maybe_quote
|
|
207
|
+
def maybe_quote(str)
|
|
208
208
|
return str if /^[\w!#$%&'*+.\^`{|}-]+$/ =~ str
|
|
209
209
|
str = str.gsub("\\", "\\\\\\\\").gsub("\"", "\\\\\"")
|
|
210
210
|
"\"#{str}\""
|
|
@@ -9,60 +9,61 @@ module CloudEvents
|
|
|
9
9
|
# @private
|
|
10
10
|
#
|
|
11
11
|
class FieldInterpreter
|
|
12
|
-
def initialize
|
|
13
|
-
@args = Utils.keys_to_strings
|
|
12
|
+
def initialize(args)
|
|
13
|
+
@args = Utils.keys_to_strings(args)
|
|
14
14
|
@attributes = {}
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def finish_attributes
|
|
17
|
+
def finish_attributes(requires_lc_start: false)
|
|
18
18
|
@args.each do |key, value|
|
|
19
|
+
check_attribute_name(key, requires_lc_start)
|
|
19
20
|
@attributes[key.freeze] = value.to_s.freeze unless value.nil?
|
|
20
21
|
end
|
|
21
22
|
@args = {}
|
|
22
23
|
@attributes.freeze
|
|
23
24
|
end
|
|
24
25
|
|
|
25
|
-
def string
|
|
26
|
-
object
|
|
26
|
+
def string(keys, required: false, allow_empty: false)
|
|
27
|
+
object(keys, required: required) do |value|
|
|
27
28
|
case value
|
|
28
29
|
when ::String
|
|
29
|
-
raise
|
|
30
|
+
raise(AttributeError, "The #{keys.first} field cannot be empty") if value.empty? && !allow_empty
|
|
30
31
|
value.freeze
|
|
31
32
|
[value, value]
|
|
32
33
|
else
|
|
33
|
-
raise
|
|
34
|
-
"
|
|
34
|
+
raise(AttributeError, "Illegal type for #{keys.first}: " \
|
|
35
|
+
"String expected but #{value.class} found")
|
|
35
36
|
end
|
|
36
37
|
end
|
|
37
38
|
end
|
|
38
39
|
|
|
39
|
-
def uri
|
|
40
|
-
object
|
|
40
|
+
def uri(keys, required: false)
|
|
41
|
+
object(keys, required: required) do |value|
|
|
41
42
|
case value
|
|
42
43
|
when ::String
|
|
43
|
-
raise
|
|
44
|
+
raise(AttributeError, "The #{keys.first} field cannot be empty") if value.empty?
|
|
44
45
|
begin
|
|
45
46
|
[Utils.deep_freeze(::URI.parse(value)), value.freeze]
|
|
46
47
|
rescue ::URI::InvalidURIError => e
|
|
47
|
-
raise
|
|
48
|
+
raise(AttributeError, "Illegal format for #{keys.first}: #{e.message}")
|
|
48
49
|
end
|
|
49
50
|
when ::URI::Generic
|
|
50
51
|
[Utils.deep_freeze(value), value.to_s.freeze]
|
|
51
52
|
else
|
|
52
|
-
raise
|
|
53
|
-
"
|
|
53
|
+
raise(AttributeError, "Illegal type for #{keys.first}: " \
|
|
54
|
+
"String or URI expected but #{value.class} found")
|
|
54
55
|
end
|
|
55
56
|
end
|
|
56
57
|
end
|
|
57
58
|
|
|
58
|
-
def rfc3339_date_time
|
|
59
|
-
object
|
|
59
|
+
def rfc3339_date_time(keys, required: false)
|
|
60
|
+
object(keys, required: required) do |value|
|
|
60
61
|
case value
|
|
61
62
|
when ::String
|
|
62
63
|
begin
|
|
63
64
|
[Utils.deep_freeze(::DateTime.rfc3339(value)), value.freeze]
|
|
64
65
|
rescue ::Date::Error => e
|
|
65
|
-
raise
|
|
66
|
+
raise(AttributeError, "Illegal format for #{keys.first}: #{e.message}")
|
|
66
67
|
end
|
|
67
68
|
when ::DateTime
|
|
68
69
|
[Utils.deep_freeze(value), value.rfc3339.freeze]
|
|
@@ -70,44 +71,44 @@ module CloudEvents
|
|
|
70
71
|
value = value.to_datetime
|
|
71
72
|
[Utils.deep_freeze(value), value.rfc3339.freeze]
|
|
72
73
|
else
|
|
73
|
-
raise
|
|
74
|
-
"
|
|
74
|
+
raise(AttributeError, "Illegal type for #{keys.first}: " \
|
|
75
|
+
"String, Time, or DateTime expected but #{value.class} found")
|
|
75
76
|
end
|
|
76
77
|
end
|
|
77
78
|
end
|
|
78
79
|
|
|
79
|
-
def content_type
|
|
80
|
-
object
|
|
80
|
+
def content_type(keys, required: false)
|
|
81
|
+
object(keys, required: required) do |value|
|
|
81
82
|
case value
|
|
82
83
|
when ::String
|
|
83
|
-
raise
|
|
84
|
+
raise(AttributeError, "The #{keys.first} field cannot be empty") if value.empty?
|
|
84
85
|
[ContentType.new(value), value.freeze]
|
|
85
86
|
when ContentType
|
|
86
87
|
[value, value.to_s]
|
|
87
88
|
else
|
|
88
|
-
raise
|
|
89
|
-
"
|
|
89
|
+
raise(AttributeError, "Illegal type for #{keys.first}: " \
|
|
90
|
+
"String, or ContentType expected but #{value.class} found")
|
|
90
91
|
end
|
|
91
92
|
end
|
|
92
93
|
end
|
|
93
94
|
|
|
94
|
-
def spec_version
|
|
95
|
-
object
|
|
95
|
+
def spec_version(keys, accept:)
|
|
96
|
+
object(keys, required: true) do |value|
|
|
96
97
|
case value
|
|
97
98
|
when ::String
|
|
98
|
-
raise
|
|
99
|
+
raise(SpecVersionError, "Unrecognized specversion: #{value}") unless accept =~ value
|
|
99
100
|
value.freeze
|
|
100
101
|
[value, value]
|
|
101
102
|
else
|
|
102
|
-
raise
|
|
103
|
-
"
|
|
103
|
+
raise(AttributeError, "Illegal type for #{keys.first}: " \
|
|
104
|
+
"String expected but #{value.class} found")
|
|
104
105
|
end
|
|
105
106
|
end
|
|
106
107
|
end
|
|
107
108
|
|
|
108
|
-
def data_object
|
|
109
|
-
object
|
|
110
|
-
Utils.deep_freeze
|
|
109
|
+
def data_object(keys, required: false)
|
|
110
|
+
object(keys, required: required, allow_nil: true) do |value|
|
|
111
|
+
Utils.deep_freeze(value)
|
|
111
112
|
[value, value]
|
|
112
113
|
end
|
|
113
114
|
end
|
|
@@ -116,21 +117,28 @@ module CloudEvents
|
|
|
116
117
|
|
|
117
118
|
private
|
|
118
119
|
|
|
119
|
-
def object
|
|
120
|
+
def object(keys, required: false, allow_nil: false)
|
|
120
121
|
value = UNDEFINED
|
|
121
122
|
keys.each do |key|
|
|
122
|
-
key_present = @args.key?
|
|
123
|
-
val = @args.delete
|
|
124
|
-
value = val if allow_nil && key_present || !allow_nil && !val.nil?
|
|
123
|
+
key_present = @args.key?(key)
|
|
124
|
+
val = @args.delete(key)
|
|
125
|
+
value = val if (allow_nil && key_present) || (!allow_nil && !val.nil?)
|
|
125
126
|
end
|
|
126
127
|
if value == UNDEFINED
|
|
127
|
-
raise
|
|
128
|
+
raise(AttributeError, "The #{keys.first} field is required") if required
|
|
128
129
|
return allow_nil ? UNDEFINED : nil
|
|
129
130
|
end
|
|
130
|
-
converted, raw = yield
|
|
131
|
+
converted, raw = yield(value)
|
|
131
132
|
@attributes[keys.first.freeze] = raw
|
|
132
133
|
converted
|
|
133
134
|
end
|
|
135
|
+
|
|
136
|
+
def check_attribute_name(key, requires_lc_start)
|
|
137
|
+
regex = requires_lc_start ? /^[a-z][a-z0-9]*$/ : /^[a-z0-9]+$/
|
|
138
|
+
unless regex.match?(key)
|
|
139
|
+
raise(AttributeError, "Illegal key: #{key.inspect} must consist only of digits and lower-case letters")
|
|
140
|
+
end
|
|
141
|
+
end
|
|
134
142
|
end
|
|
135
143
|
end
|
|
136
144
|
end
|
|
@@ -24,7 +24,7 @@ module CloudEvents
|
|
|
24
24
|
# or not provided, the value will be inferred from the content type
|
|
25
25
|
# if possible, or otherwise set to `nil` indicating not known.
|
|
26
26
|
#
|
|
27
|
-
def initialize
|
|
27
|
+
def initialize(content, content_type, batch: nil)
|
|
28
28
|
@content = content.freeze
|
|
29
29
|
@content_type = content_type
|
|
30
30
|
if batch.nil? && content_type&.media_type == "application"
|
|
@@ -63,7 +63,7 @@ module CloudEvents
|
|
|
63
63
|
end
|
|
64
64
|
|
|
65
65
|
## @private
|
|
66
|
-
def ==
|
|
66
|
+
def ==(other)
|
|
67
67
|
Opaque === other &&
|
|
68
68
|
@content == other.content &&
|
|
69
69
|
@content_type == other.content_type &&
|
|
@@ -73,7 +73,7 @@ module CloudEvents
|
|
|
73
73
|
|
|
74
74
|
## @private
|
|
75
75
|
def hash
|
|
76
|
-
@content
|
|
76
|
+
[@content, @content_type, @batch].hash
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
end
|