-
Notifications
You must be signed in to change notification settings - Fork 28
Use endpoint as default connection option (ADR-119) #590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -9,15 +9,20 @@ | |||||||||||||||
|
||||||||||||||||
class Options(AuthOptions): | ||||||||||||||||
def __init__(self, client_id=None, log_level=0, tls=True, rest_host=None, realtime_host=None, port=0, | ||||||||||||||||
tls_port=0, use_binary_protocol=True, queue_messages=False, recover=False, environment=None, | ||||||||||||||||
http_open_timeout=None, http_request_timeout=None, realtime_request_timeout=None, | ||||||||||||||||
http_max_retry_count=None, http_max_retry_duration=None, fallback_hosts=None, | ||||||||||||||||
fallback_retry_timeout=None, disconnected_retry_timeout=None, idempotent_rest_publishing=None, | ||||||||||||||||
loop=None, auto_connect=True, suspended_retry_timeout=None, connectivity_check_url=None, | ||||||||||||||||
tls_port=0, use_binary_protocol=True, queue_messages=False, recover=False, endpoint=None, | ||||||||||||||||
environment=None, http_open_timeout=None, http_request_timeout=None, | ||||||||||||||||
realtime_request_timeout=None, http_max_retry_count=None, http_max_retry_duration=None, | ||||||||||||||||
fallback_hosts=None, fallback_retry_timeout=None, disconnected_retry_timeout=None, | ||||||||||||||||
idempotent_rest_publishing=None, loop=None, auto_connect=True, | ||||||||||||||||
suspended_retry_timeout=None, connectivity_check_url=None, | ||||||||||||||||
Comment on lines
+12
to
+17
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainAdd deprecation warnings for legacy options. Since Adding deprecation warnings will help users migrate to the new API: def __init__(self, client_id=None, log_level=0, tls=True, rest_host=None, realtime_host=None, port=0,
tls_port=0, use_binary_protocol=True, queue_messages=False, recover=False, endpoint=None,
environment=None, http_open_timeout=None, http_request_timeout=None,
realtime_request_timeout=None, http_max_retry_count=None, http_max_retry_duration=None,
fallback_hosts=None, fallback_retry_timeout=None, disconnected_retry_timeout=None,
idempotent_rest_publishing=None, loop=None, auto_connect=True,
suspended_retry_timeout=None, connectivity_check_url=None,
channel_retry_timeout=Defaults.channel_retry_timeout, add_request_ids=False, **kwargs):
super().__init__(**kwargs)
+ # Issue deprecation warnings for legacy options
+ import warnings
+ if environment is not None and endpoint is None:
+ warnings.warn(
+ "The 'environment' parameter is deprecated, use 'endpoint' instead.",
+ DeprecationWarning,
+ stacklevel=2
+ )
+ if rest_host is not None:
+ warnings.warn(
+ "The 'rest_host' parameter is deprecated, use 'endpoint' instead.",
+ DeprecationWarning,
+ stacklevel=2
+ )
+ if realtime_host is not None:
+ warnings.warn(
+ "The 'realtime_host' parameter is deprecated, use 'endpoint' instead.",
+ DeprecationWarning,
+ stacklevel=2
+ ) 🌐 Web query:
💡 Result: To add deprecation warnings in Python, you can use the built-in import warnings
def deprecated_function():
warnings.warn(
"deprecated_function() is deprecated and will be removed in a future version.",
DeprecationWarning,
stacklevel=2
)
# Function implementation here
print("This function is deprecated.")
# Usage
deprecated_function() Explanation:
By default, import warnings
warnings.simplefilter('always', DeprecationWarning) Let me know if you want me to provide an example for a deprecated class or decorator-style usage as well! 🏁 Script executed: #!/bin/bash
set -e
# Verify presence of legacy parameters in the signature
rg -n "def __init__" ably/types/options.py
rg -n "rest_host" ably/types/options.py
rg -n "realtime_host" ably/types/options.py Length of output: 2741 Add deprecation warnings for legacy options in init In ably/types/options.py, inside the super().__init__(**kwargs) call—insert warnings for any use of class Options:
def __init__(self, client_id=None, log_level=0, tls=True,
- rest_host=None, realtime_host=None, port=0,
+ rest_host=None, realtime_host=None, port=0,
tls_port=0, use_binary_protocol=True, queue_messages=False,
recover=False, endpoint=None, environment=None,
http_open_timeout=None, …, **kwargs):
- super().__init__(**kwargs)
+ super().__init__(**kwargs)
+
+ # Deprecation warnings for legacy connection parameters
+ import warnings
+ if environment is not None:
+ warnings.warn(
+ "The ‘environment’ parameter is deprecated; please use ‘endpoint’ instead.",
+ DeprecationWarning,
+ stacklevel=2
+ )
+ if rest_host is not None:
+ warnings.warn(
+ "The ‘rest_host’ parameter is deprecated; please use ‘endpoint’ instead.",
+ DeprecationWarning,
+ stacklevel=2
+ )
+ if realtime_host is not None:
+ warnings.warn(
+ "The ‘realtime_host’ parameter is deprecated; please use ‘endpoint’ instead.",
+ DeprecationWarning,
+ stacklevel=2
+ )
# existing validation logic follows…
This will surface 🤖 Prompt for AI Agents
|
||||||||||||||||
channel_retry_timeout=Defaults.channel_retry_timeout, add_request_ids=False, **kwargs): | ||||||||||||||||
|
||||||||||||||||
super().__init__(**kwargs) | ||||||||||||||||
|
||||||||||||||||
if endpoint is not None: | ||||||||||||||||
if environment is not None or rest_host is not None or realtime_host is not None: | ||||||||||||||||
raise ValueError('endpoint is incompatible with any of environment, rest_host or realtime_host') | ||||||||||||||||
|
||||||||||||||||
Comment on lines
+22
to
+25
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Simplify validation condition for incompatible options. The nested if statement can be simplified as suggested by the static analysis tool. Also, consider checking for all incompatible options at once. - if endpoint is not None:
- if environment is not None or rest_host is not None or realtime_host is not None:
- raise ValueError('endpoint is incompatible with any of environment, rest_host or realtime_host')
+ if endpoint is not None and (
+ environment is not None or rest_host is not None or realtime_host is not None
+ ):
+ raise ValueError('endpoint is incompatible with any of environment, rest_host or realtime_host') 📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.11.9)22-23: Use a single (SIM102) 🤖 Prompt for AI Agents
|
||||||||||||||||
# TODO check these defaults | ||||||||||||||||
if fallback_retry_timeout is None: | ||||||||||||||||
fallback_retry_timeout = Defaults.fallback_retry_timeout | ||||||||||||||||
|
@@ -46,8 +51,11 @@ def __init__(self, client_id=None, log_level=0, tls=True, rest_host=None, realti | |||||||||||||||
from ably import api_version | ||||||||||||||||
idempotent_rest_publishing = api_version >= '1.2' | ||||||||||||||||
|
||||||||||||||||
if environment is None: | ||||||||||||||||
environment = Defaults.environment | ||||||||||||||||
if environment is not None and endpoint is None: | ||||||||||||||||
endpoint = environment | ||||||||||||||||
|
||||||||||||||||
if endpoint is None: | ||||||||||||||||
endpoint = Defaults.endpoint | ||||||||||||||||
|
||||||||||||||||
self.__client_id = client_id | ||||||||||||||||
self.__log_level = log_level | ||||||||||||||||
|
@@ -59,7 +67,7 @@ def __init__(self, client_id=None, log_level=0, tls=True, rest_host=None, realti | |||||||||||||||
self.__use_binary_protocol = use_binary_protocol | ||||||||||||||||
self.__queue_messages = queue_messages | ||||||||||||||||
self.__recover = recover | ||||||||||||||||
self.__environment = environment | ||||||||||||||||
self.__endpoint = endpoint | ||||||||||||||||
self.__http_open_timeout = http_open_timeout | ||||||||||||||||
self.__http_request_timeout = http_request_timeout | ||||||||||||||||
self.__realtime_request_timeout = realtime_request_timeout | ||||||||||||||||
|
@@ -163,8 +171,8 @@ def recover(self, value): | |||||||||||||||
self.__recover = value | ||||||||||||||||
|
||||||||||||||||
@property | ||||||||||||||||
def environment(self): | ||||||||||||||||
return self.__environment | ||||||||||||||||
def endpoint(self): | ||||||||||||||||
return self.__endpoint | ||||||||||||||||
|
||||||||||||||||
@property | ||||||||||||||||
def http_open_timeout(self): | ||||||||||||||||
|
@@ -268,27 +276,19 @@ def __get_rest_hosts(self): | |||||||||||||||
# Defaults | ||||||||||||||||
host = self.rest_host | ||||||||||||||||
if host is None: | ||||||||||||||||
host = Defaults.rest_host | ||||||||||||||||
|
||||||||||||||||
environment = self.environment | ||||||||||||||||
host = Defaults.get_hostname(self.endpoint) | ||||||||||||||||
|
||||||||||||||||
http_max_retry_count = self.http_max_retry_count | ||||||||||||||||
if http_max_retry_count is None: | ||||||||||||||||
http_max_retry_count = Defaults.http_max_retry_count | ||||||||||||||||
|
||||||||||||||||
# Prepend environment | ||||||||||||||||
if environment != 'production': | ||||||||||||||||
host = '%s-%s' % (environment, host) | ||||||||||||||||
|
||||||||||||||||
# Fallback hosts | ||||||||||||||||
fallback_hosts = self.fallback_hosts | ||||||||||||||||
if fallback_hosts is None: | ||||||||||||||||
if host == Defaults.rest_host: | ||||||||||||||||
fallback_hosts = Defaults.fallback_hosts | ||||||||||||||||
elif environment != 'production': | ||||||||||||||||
fallback_hosts = Defaults.get_environment_fallback_hosts(environment) | ||||||||||||||||
else: | ||||||||||||||||
if self.rest_host is not None: | ||||||||||||||||
fallback_hosts = [] | ||||||||||||||||
else: | ||||||||||||||||
fallback_hosts = Defaults.get_fallback_hosts(self.endpoint) | ||||||||||||||||
|
||||||||||||||||
# Shuffle | ||||||||||||||||
fallback_hosts = list(fallback_hosts) | ||||||||||||||||
|
@@ -304,11 +304,8 @@ def __get_realtime_hosts(self): | |||||||||||||||
if self.realtime_host is not None: | ||||||||||||||||
host = self.realtime_host | ||||||||||||||||
return [host] | ||||||||||||||||
elif self.environment != "production": | ||||||||||||||||
host = f'{self.environment}-{Defaults.realtime_host}' | ||||||||||||||||
else: | ||||||||||||||||
host = Defaults.realtime_host | ||||||||||||||||
|
||||||||||||||||
host = Defaults.get_hostname(self.endpoint) | ||||||||||||||||
return [host] + self.__fallback_hosts | ||||||||||||||||
|
||||||||||||||||
def get_rest_hosts(self): | ||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import pytest | ||
|
||
from ably.types.options import Options | ||
|
||
|
||
def test_options_should_fail_early_with_incompatible_client_options(): | ||
with pytest.raises(ValueError): | ||
Options(endpoint="foo", environment="foo") | ||
|
||
with pytest.raises(ValueError): | ||
Options(endpoint="foo", rest_host="foo") | ||
|
||
with pytest.raises(ValueError): | ||
Options(endpoint="foo", realtime_host="foo") | ||
|
||
|
||
# REC1a | ||
def test_options_should_return_the_default_hostnames(): | ||
opts = Options() | ||
assert opts.get_realtime_host() == "main.realtime.ably.net" | ||
assert "main.a.fallback.ably-realtime.com" in opts.get_fallback_realtime_hosts() | ||
|
||
|
||
# REC1b4 | ||
def test_options_should_return_the_correct_routing_policy_hostnames(): | ||
opts = Options(endpoint="foo") | ||
assert opts.get_realtime_host() == "foo.realtime.ably.net" | ||
assert "foo.a.fallback.ably-realtime.com" in opts.get_fallback_realtime_hosts() | ||
|
||
|
||
# REC1b3 | ||
def test_options_should_return_the_correct_nonprod_routing_policy_hostnames(): | ||
opts = Options(endpoint="nonprod:foo") | ||
assert opts.get_realtime_host() == "foo.realtime.ably-nonprod.net" | ||
assert "foo.a.fallback.ably-realtime-nonprod.com" in opts.get_fallback_realtime_hosts() | ||
|
||
|
||
# REC1b2 | ||
def test_options_should_return_the_correct_fqdn_hostnames(): | ||
opts = Options(endpoint="foo.com") | ||
assert opts.get_realtime_host() == "foo.com" | ||
assert not opts.get_fallback_realtime_hosts() | ||
|
||
|
||
# REC1b2 | ||
def test_options_should_return_an_ipv4_address(): | ||
opts = Options(endpoint="127.0.0.1") | ||
assert opts.get_realtime_host() == "127.0.0.1" | ||
assert not opts.get_fallback_realtime_hosts() | ||
|
||
|
||
# REC1b2 | ||
def test_options_should_return_an_ipv6_address(): | ||
opts = Options(endpoint="::1") | ||
assert opts.get_realtime_host() == "::1" | ||
|
||
|
||
# REC1b2 | ||
def test_options_should_return_localhost(): | ||
opts = Options(endpoint="localhost") | ||
assert opts.get_realtime_host() == "localhost" |
Uh oh!
There was an error while loading. Please reload this page.