http 2.0.1 → 2.0.2

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 (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/.travis.yml +1 -0
  4. data/CHANGES.md +8 -0
  5. data/Gemfile +7 -9
  6. data/http.gemspec +2 -0
  7. data/lib/http.rb +1 -0
  8. data/lib/http/client.rb +2 -5
  9. data/lib/http/connection.rb +6 -3
  10. data/lib/http/content_type.rb +1 -0
  11. data/lib/http/errors.rb +1 -0
  12. data/lib/http/headers.rb +1 -0
  13. data/lib/http/headers/mixin.rb +1 -0
  14. data/lib/http/mime_type.rb +1 -0
  15. data/lib/http/mime_type/adapter.rb +1 -0
  16. data/lib/http/mime_type/json.rb +1 -0
  17. data/lib/http/options.rb +1 -0
  18. data/lib/http/redirector.rb +1 -0
  19. data/lib/http/response.rb +1 -0
  20. data/lib/http/response/body.rb +4 -2
  21. data/lib/http/response/parser.rb +1 -0
  22. data/lib/http/response/status.rb +1 -0
  23. data/lib/http/response/status/reasons.rb +1 -0
  24. data/lib/http/timeout/global.rb +1 -0
  25. data/lib/http/timeout/null.rb +1 -0
  26. data/lib/http/timeout/per_operation.rb +1 -0
  27. data/lib/http/version.rb +2 -1
  28. data/spec/lib/http/client_spec.rb +1 -0
  29. data/spec/lib/http/content_type_spec.rb +1 -0
  30. data/spec/lib/http/headers/mixin_spec.rb +1 -0
  31. data/spec/lib/http/headers_spec.rb +1 -0
  32. data/spec/lib/http/options/body_spec.rb +1 -0
  33. data/spec/lib/http/options/form_spec.rb +1 -0
  34. data/spec/lib/http/options/headers_spec.rb +1 -0
  35. data/spec/lib/http/options/json_spec.rb +1 -0
  36. data/spec/lib/http/options/merge_spec.rb +24 -20
  37. data/spec/lib/http/options/new_spec.rb +1 -0
  38. data/spec/lib/http/options/proxy_spec.rb +1 -0
  39. data/spec/lib/http/options_spec.rb +1 -0
  40. data/spec/lib/http/redirector_spec.rb +1 -0
  41. data/spec/lib/http/request/writer_spec.rb +1 -0
  42. data/spec/lib/http/request_spec.rb +1 -0
  43. data/spec/lib/http/response/body_spec.rb +5 -4
  44. data/spec/lib/http/response/status_spec.rb +1 -0
  45. data/spec/lib/http/response_spec.rb +1 -0
  46. data/spec/lib/http/uri_spec.rb +1 -0
  47. data/spec/lib/http_spec.rb +2 -1
  48. data/spec/regression_specs.rb +1 -0
  49. data/spec/spec_helper.rb +1 -0
  50. data/spec/support/black_hole.rb +1 -0
  51. data/spec/support/capture_warning.rb +1 -0
  52. data/spec/support/dummy_server.rb +1 -0
  53. data/spec/support/dummy_server/servlet.rb +1 -0
  54. data/spec/support/http_handling_shared.rb +1 -0
  55. data/spec/support/proxy_server.rb +1 -0
  56. data/spec/support/servers/config.rb +1 -0
  57. data/spec/support/servers/runner.rb +1 -0
  58. data/spec/support/ssl_helper.rb +1 -0
  59. metadata +3 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 21f055f29a48247045d37ed9be74484f3116d0c1
4
- data.tar.gz: de2b1a88f332b6f2c1848f85b1ff3fe6d01ba49d
3
+ metadata.gz: cd857e2ad6dc7552b81641ec83c3a60e99087fae
4
+ data.tar.gz: b31ec2d4637bc449f29ff01f6df6568672c04cd4
5
5
  SHA512:
6
- metadata.gz: e3f82de8ae1a6947a667216d9cb865eef7c18d068384db44fde9bb8c4c81db2fbf6f36161b559306e9822bdf1186b61cc1053789ebfc9787c7a4179c54a40f47
7
- data.tar.gz: 0d8c22f1fa37b8da65a978cd82ca4f7fa42dd52c9307232c2df329f27b046aa14d9f91445197e1018de761d6ce9e5c8e2379f8e0530b7d938fbe4a4e61878328
6
+ metadata.gz: 6efddbaf1df00256de1e58fc512357165e343a421a7d67f5b7d0103f241ea0eb77d9a19c33377624d954b68f5b7d016e0d15ffbb5eab0c8acb49d827b3f7f7b4
7
+ data.tar.gz: 2a0dec9c76defd8f85d57da8eb4ef46251519bd49be93c57955995e6e91a1b55122ad3d86cd96ba4130e3380871be8e6c329bc0503a5fbf021c8bbca9bee7b03
@@ -55,6 +55,9 @@ Style/EachWithObject:
55
55
  Style/Encoding:
56
56
  Enabled: false
57
57
 
58
+ Style/EmptyCaseCondition:
59
+ Enabled: false
60
+
58
61
  Style/HashSyntax:
59
62
  EnforcedStyle: hash_rockets
60
63
 
@@ -12,6 +12,7 @@ rvm:
12
12
  - 2.1
13
13
  - 2.2
14
14
  - 2.3.0
15
+ - 2.3.1
15
16
  - jruby-9.1.0.0
16
17
  - jruby-head
17
18
  - ruby-head
data/CHANGES.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 2.0.2 (2016-06-24)
2
+
3
+ * [#353](https://github.com/httprb/http/pull/353)
4
+ Avoid a dependency cycle between Client and Connection classes.
5
+ ([@jhbabon])
6
+
7
+
1
8
  ## 2.0.1 (2016-05-12)
2
9
 
3
10
  * [#341](https://github.com/httprb/http/pull/341)
@@ -529,3 +536,4 @@ end
529
536
  [@smudge]: https://github.com/smudge
530
537
  [@mwitek]: https://github.com/mwitek
531
538
  [@tonyta]: https://github.com/tonyta
539
+ [@jhbabon]: https://github.com/jhbabon
data/Gemfile CHANGED
@@ -3,24 +3,22 @@ source "https://rubygems.org"
3
3
  gem "rake"
4
4
 
5
5
  group :development do
6
- gem "celluloid-io"
7
- gem "guard"
8
6
  gem "guard-rspec", :require => false
9
- gem "nokogiri", :require => false
10
- gem "pry"
7
+ gem "nokogiri", :require => false
8
+ gem "pry", :require => false
11
9
 
12
- platforms :ruby_19, :ruby_20 do
13
- gem "pry-debugger"
14
- gem "pry-stack_explorer"
10
+ platform :ruby_20 do
11
+ gem "pry-debugger", :require => false
12
+ gem "pry-stack_explorer", :require => false
15
13
  end
16
14
  end
17
15
 
18
16
  group :test do
19
17
  gem "backports"
20
- gem "coveralls"
18
+ gem "coveralls", :require => false
21
19
  gem "simplecov", ">= 0.9"
22
20
  gem "json", ">= 1.8.1"
23
- gem "rubocop", "= 0.39.0"
21
+ gem "rubocop", "= 0.40.0"
24
22
  gem "rspec", "~> 3.0"
25
23
  gem "rspec-its"
26
24
  gem "yardstick"
@@ -23,6 +23,8 @@ Gem::Specification.new do |gem|
23
23
  gem.require_paths = ["lib"]
24
24
  gem.version = HTTP::VERSION
25
25
 
26
+ gem.required_ruby_version = ">= 2.0"
27
+
26
28
  gem.add_runtime_dependency "http_parser.rb", "~> 0.6.0"
27
29
  gem.add_runtime_dependency "http-form_data", "~> 1.0.1"
28
30
  gem.add_runtime_dependency "http-cookie", "~> 1.0"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "http/parser"
2
3
 
3
4
  require "http/errors"
@@ -14,10 +14,7 @@ module HTTP
14
14
  extend Forwardable
15
15
  include Chainable
16
16
 
17
- KEEP_ALIVE = "Keep-Alive".freeze
18
- CLOSE = "close".freeze
19
-
20
- HTTP_OR_HTTPS_RE = %r{^https?://}i
17
+ HTTP_OR_HTTPS_RE = %r{^https?://}i
21
18
 
22
19
  def initialize(default_options = {})
23
20
  @default_options = HTTP::Options.new(default_options)
@@ -139,7 +136,7 @@ module HTTP
139
136
  headers = opts.headers
140
137
 
141
138
  # Tell the server to keep the conn open
142
- headers[Headers::CONNECTION] = default_options.persistent? ? KEEP_ALIVE : CLOSE
139
+ headers[Headers::CONNECTION] = default_options.persistent? ? Connection::KEEP_ALIVE : Connection::CLOSE
143
140
 
144
141
  cookies = opts.cookies.values
145
142
 
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "forwardable"
3
3
 
4
- require "http/client"
5
4
  require "http/headers"
6
5
  require "http/response/parser"
7
6
 
@@ -10,6 +9,10 @@ module HTTP
10
9
  class Connection
11
10
  extend Forwardable
12
11
 
12
+ # Allowed values for CONNECTION header
13
+ KEEP_ALIVE = "Keep-Alive".freeze
14
+ CLOSE = "close".freeze
15
+
13
16
  # Attempt to read this much data
14
17
  BUFFER_SIZE = 16_384
15
18
 
@@ -193,9 +196,9 @@ module HTTP
193
196
  @keep_alive =
194
197
  case @parser.http_version
195
198
  when HTTP_1_0 # HTTP/1.0 requires opt in for Keep Alive
196
- @parser.headers[Headers::CONNECTION] == Client::KEEP_ALIVE
199
+ @parser.headers[Headers::CONNECTION] == KEEP_ALIVE
197
200
  when HTTP_1_1 # HTTP/1.1 is opt-out
198
- @parser.headers[Headers::CONNECTION] != Client::CLOSE
201
+ @parser.headers[Headers::CONNECTION] != CLOSE
199
202
  else # Anything else we assume doesn't supportit
200
203
  false
201
204
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module HTTP
2
3
  ContentType = Struct.new(:mime_type, :charset) do
3
4
  MIME_TYPE_RE = %r{^([^/]+/[^;]+)(?:$|;)}
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module HTTP
2
3
  # Generic error
3
4
  class Error < StandardError; end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "forwardable"
2
3
 
3
4
  require "http/errors"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "forwardable"
2
3
 
3
4
  module HTTP
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module HTTP
2
3
  # MIME type encode/decode adapters
3
4
  module MimeType
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "forwardable"
2
3
  require "singleton"
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "json"
2
3
  require "http/mime_type/adapter"
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "http/headers"
2
3
  require "openssl"
3
4
  require "socket"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "set"
2
3
 
3
4
  require "http/headers"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "forwardable"
2
3
 
3
4
  require "http/headers"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "forwardable"
2
3
  require "http/client"
3
4
 
@@ -43,8 +44,9 @@ module HTTP
43
44
  end
44
45
 
45
46
  begin
46
- @streaming = false
47
- @contents = "".force_encoding(encoding)
47
+ @streaming = false
48
+ @contents = String.new("").force_encoding(encoding)
49
+
48
50
  while (chunk = @client.readpartial)
49
51
  @contents << chunk.force_encoding(encoding)
50
52
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module HTTP
2
3
  class Response
3
4
  class Parser
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "delegate"
2
3
 
3
4
  require "http/response/status/reasons"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # AUTO-GENERATED FILE, DO NOT CHANGE IT MANUALLY
2
3
 
3
4
  require "delegate"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "timeout"
2
3
  require "io/wait"
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "forwardable"
2
3
  require "io/wait"
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "timeout"
2
3
 
3
4
  require "http/timeout/null"
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module HTTP
3
- VERSION = "2.0.1".freeze
4
+ VERSION = "2.0.2".freeze
4
5
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # coding: utf-8
2
3
 
3
4
  require "support/http_handling_shared"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::ContentType do
2
3
  describe ".parse" do
3
4
  context "with text/plain" do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Headers::Mixin do
2
3
  let :dummy_class do
3
4
  Class.new do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Headers do
2
3
  subject(:headers) { described_class.new }
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Options, "body" do
2
3
  let(:opts) { HTTP::Options.new }
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Options, "form" do
2
3
  let(:opts) { HTTP::Options.new }
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Options, "headers" do
2
3
  let(:opts) { HTTP::Options.new }
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Options, "json" do
2
3
  let(:opts) { HTTP::Options.new }
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  RSpec.describe HTTP::Options, "merge" do
3
4
  let(:opts) { HTTP::Options.new }
@@ -23,7 +24,8 @@ RSpec.describe HTTP::Options, "merge" do
23
24
  :body => "body-foo",
24
25
  :json => {:foo => "foo"},
25
26
  :headers => {:accept => "json", :foo => "foo"},
26
- :proxy => {})
27
+ :proxy => {}
28
+ )
27
29
 
28
30
  bar = HTTP::Options.new(
29
31
  :response => :parsed_body,
@@ -36,27 +38,29 @@ RSpec.describe HTTP::Options, "merge" do
36
38
  :headers => {:accept => "xml", :bar => "bar"},
37
39
  :timeout_options => {:foo => :bar},
38
40
  :ssl => {:foo => "bar"},
39
- :proxy => {:proxy_address => "127.0.0.1", :proxy_port => 8080})
41
+ :proxy => {:proxy_address => "127.0.0.1", :proxy_port => 8080}
42
+ )
40
43
 
41
44
  expect(foo.merge(bar).to_hash).to eq(
42
- :response => :parsed_body,
43
- :timeout_class => described_class.default_timeout_class,
44
- :timeout_options => {:foo => :bar},
45
- :params => {:plop => "plip"},
46
- :form => {:bar => "bar"},
47
- :body => "body-bar",
48
- :json => {:bar => "bar"},
49
- :persistent => "https://www.googe.com",
45
+ :response => :parsed_body,
46
+ :timeout_class => described_class.default_timeout_class,
47
+ :timeout_options => {:foo => :bar},
48
+ :params => {:plop => "plip"},
49
+ :form => {:bar => "bar"},
50
+ :body => "body-bar",
51
+ :json => {:bar => "bar"},
52
+ :persistent => "https://www.googe.com",
50
53
  :keep_alive_timeout => 10,
51
- :ssl => {:foo => "bar"},
52
- :headers => {"Foo" => "foo", "Accept" => "xml", "Bar" => "bar"},
53
- :proxy => {:proxy_address => "127.0.0.1", :proxy_port => 8080},
54
- :follow => nil,
55
- :socket_class => described_class.default_socket_class,
56
- :nodelay => false,
57
- :ssl_socket_class => described_class.default_ssl_socket_class,
58
- :ssl_context => nil,
59
- :cookies => {},
60
- :encoding => nil)
54
+ :ssl => {:foo => "bar"},
55
+ :headers => {"Foo" => "foo", "Accept" => "xml", "Bar" => "bar"},
56
+ :proxy => {:proxy_address => "127.0.0.1", :proxy_port => 8080},
57
+ :follow => nil,
58
+ :socket_class => described_class.default_socket_class,
59
+ :nodelay => false,
60
+ :ssl_socket_class => described_class.default_ssl_socket_class,
61
+ :ssl_context => nil,
62
+ :cookies => {},
63
+ :encoding => nil
64
+ )
61
65
  end
62
66
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Options, "new" do
2
3
  it "supports a Options instance" do
3
4
  opts = HTTP::Options.new
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Options, "proxy" do
2
3
  let(:opts) { HTTP::Options.new }
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Options do
2
3
  subject { described_class.new(:response => :body) }
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Redirector do
2
3
  def simple_response(status, body = "", headers = {})
3
4
  HTTP::Response.new(
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # coding: utf-8
2
3
 
3
4
  RSpec.describe HTTP::Request::Writer do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # coding: utf-8
2
3
 
3
4
  RSpec.describe HTTP::Request do
@@ -1,17 +1,18 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Response::Body do
2
3
  let(:client) { double(:sequence_id => 0) }
3
- let(:chunks) { ["Hello, ", "World!"] }
4
+ let(:chunks) { [String.new("Hello, "), String.new("World!")] }
4
5
 
5
6
  before { allow(client).to receive(:readpartial) { chunks.shift } }
6
7
 
7
- subject(:body) { described_class.new client, Encoding::UTF_8 }
8
+ subject(:body) { described_class.new(client, Encoding::UTF_8) }
8
9
 
9
10
  it "streams bodies from responses" do
10
- expect(subject.to_s).to eq "Hello, World!"
11
+ expect(subject.to_s).to eq("Hello, World!")
11
12
  end
12
13
 
13
14
  context "when body empty" do
14
- let(:chunks) { [""] }
15
+ let(:chunks) { [String.new("")] }
15
16
 
16
17
  it "returns responds to empty? with true" do
17
18
  expect(subject).to be_empty
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Response::Status do
2
3
  describe ".new" do
3
4
  it "fails if given value does not respond to #to_i" do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::Response do
2
3
  let(:body) { "Hello world!" }
3
4
  let(:uri) { "http://example.com/" }
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.describe HTTP::URI do
2
3
  let(:example_http_uri_string) { "http://example.com" }
3
4
  let(:example_https_uri_string) { "https://example.com" }
@@ -1,4 +1,5 @@
1
- # encoding: UTF-8
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
2
3
 
3
4
  require "json"
4
5
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "spec_helper"
2
3
 
3
4
  RSpec.describe "Regression testing" do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # coding: utf-8
2
3
 
3
4
  require "simplecov"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module BlackHole
2
3
  def self.method_missing(*)
3
4
  self
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  def capture_warning
2
3
  old_stderr = $stderr
3
4
  $stderr = StringIO.new
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "webrick"
2
3
  require "webrick/ssl"
3
4
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # encoding: UTF-8
2
3
 
3
4
  class DummyServer < WEBrick::HTTPServer
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  RSpec.shared_context "HTTP handling" do
2
3
  describe "timeouts" do
3
4
  let(:conn_timeout) { 1 }
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "webrick/httpproxy"
2
3
 
3
4
  require "support/black_hole"
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ServerConfig
2
3
  def addr
3
4
  config[:BindAddress]
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module ServerRunner
2
3
  def run_server(name)
3
4
  let! name do
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require "pathname"
2
3
 
3
4
  require "certificate_authority"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2016-05-12 00:00:00.000000000 Z
14
+ date: 2016-06-24 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: http_parser.rb
@@ -175,7 +175,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
175
175
  requirements:
176
176
  - - ">="
177
177
  - !ruby/object:Gem::Version
178
- version: '0'
178
+ version: '2.0'
179
179
  required_rubygems_version: !ruby/object:Gem::Requirement
180
180
  requirements:
181
181
  - - ">="