Skip to content

Commit

Permalink
add type hints to some of the public facing api.
Browse files Browse the repository at this point in the history
update some docs
  • Loading branch information
apache-hb committed Sep 28, 2020
1 parent b5213b2 commit c35fa61
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 120 deletions.
13 changes: 3 additions & 10 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,6 @@ orbs:
workflows:
test:
jobs:
- test-linux:
name: Python 3.3
docker-image: circleci/python:3.3-jessie
consul-supported: false # Consul isn't supported in 3.3
filesource-supported: false # FileDataSource isn't supported in 3.3
test-packaging: false # packaging test requires virtualenv, which isn't supported in 3.3
- test-linux:
name: Python 3.4
docker-image: circleci/python:3.4-jessie
consul-supported: false # Consul isn't supported in 3.4
- test-linux:
name: Python 3.5
docker-image: circleci/python:3.5-jessie
Expand All @@ -28,6 +18,9 @@ workflows:
- test-linux:
name: Python 3.8
docker-image: circleci/python:3.8-buster
- test-linux:
name: Python 3.9 prerelease
docker-image: circleci/python:3.9.0rc2
- test-windows:
name: Windows Py3.3
py3: true
Expand Down
6 changes: 3 additions & 3 deletions ldclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
__lock = ReadWriteLock()


def set_config(config):
def set_config(config: Config):
"""Sets the configuration for the shared SDK client instance.
If this is called prior to :func:`ldclient.get()`, it stores the configuration that will be used when the
Expand All @@ -48,7 +48,7 @@ def set_config(config):
__lock.unlock()


def set_sdk_key(sdk_key):
def set_sdk_key(sdk_key: str):
"""Sets the SDK key for the shared SDK client instance.
If this is called prior to :func:`ldclient.get()`, it stores the SDK key that will be used when the client is
Expand Down Expand Up @@ -87,7 +87,7 @@ def set_sdk_key(sdk_key):
__lock.unlock()


def get():
def get() -> LDClient:
"""Returns the shared SDK client instance, using the current global configuration.
To use the SDK as a singleton, first make sure you have called :func:`ldclient.set_sdk_key()` or
Expand Down
22 changes: 11 additions & 11 deletions ldclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class LDClient:
Client instances are thread-safe.
"""
def __init__(self, sdk_key=None, config=None, start_wait=5):
def __init__(self, sdk_key: str=None, config: Config=None, start_wait: float=5):
"""Constructs a new LDClient instance.
:param string sdk_key: the SDK key for your LaunchDarkly environment
Expand Down Expand Up @@ -115,7 +115,7 @@ def __init__(self, sdk_key=None, config=None, start_wait=5):
log.warning("Initialization timeout exceeded for LaunchDarkly Client or an error occurred. "
"Feature Flags may not yet be available.")

def _set_event_processor(self, config):
def _set_event_processor(self, config: Config):
if config.offline or not config.send_events:
self._event_processor = NullEventProcessor()
return None
Expand Down Expand Up @@ -175,7 +175,7 @@ def __exit__(self, type, value, traceback):
def _send_event(self, event):
self._event_processor.send_event(event)

def track(self, event_name, user, data=None, metric_value=None):
def track(self, event_name: str, user: dict, data=None, metric_value=None):
"""Tracks that a user performed an event.
LaunchDarkly automatically tracks pageviews and clicks that are specified in the Goals
Expand All @@ -194,7 +194,7 @@ def track(self, event_name, user, data=None, metric_value=None):
else:
self._send_event(self._event_factory_default.new_custom_event(event_name, user, data, metric_value))

def identify(self, user):
def identify(self, user: dict):
"""Registers the user.
This simply creates an analytics event that will transmit the given user properties to
Expand All @@ -208,14 +208,14 @@ def identify(self, user):
else:
self._send_event(self._event_factory_default.new_identify_event(user))

def is_offline(self):
def is_offline(self) -> bool:
"""Returns true if the client is in offline mode.
:rtype: bool
"""
return self._config.offline

def is_initialized(self):
def is_initialized(self) -> bool:
"""Returns true if the client has successfully connected to LaunchDarkly.
If this returns false, it means that the client has not yet successfully connected to LaunchDarkly.
Expand Down Expand Up @@ -247,7 +247,7 @@ def toggle(self, key, user, default):
log.warning("Deprecated method: toggle() called. Use variation() instead.")
return self.variation(key, user, default)

def variation(self, key, user, default):
def variation(self, key: str, user: dict, default: object) -> object:
"""Determines the variation of a feature flag for a user.
:param string key: the unique key for the feature flag
Expand All @@ -258,7 +258,7 @@ def variation(self, key, user, default):
"""
return self._evaluate_internal(key, user, default, self._event_factory_default).value

def variation_detail(self, key, user, default):
def variation_detail(self, key: str, user: dict, default: object) -> EvaluationDetail:
"""Determines the variation of a feature flag for a user, like :func:`variation()`, but also
provides additional information about how this value was calculated, in the form of an
:class:`ldclient.flag.EvaluationDetail` object.
Expand Down Expand Up @@ -328,7 +328,7 @@ def _evaluate_internal(self, key, user, default, event_factory):
self._send_event(event_factory.new_default_event(flag, user, default, reason))
return EvaluationDetail(default, None, reason)

def all_flags(self, user):
def all_flags(self, user: dict) -> dict:
"""Returns all feature flag values for the given user.
This method is deprecated - please use :func:`all_flags_state()` instead. Current versions of the
Expand All @@ -344,7 +344,7 @@ def all_flags(self, user):
return None
return state.to_values_map()

def all_flags_state(self, user, **kwargs):
def all_flags_state(self, user: dict, **kwargs) -> FeatureFlagsState:
"""Returns an object that encapsulates the state of all feature flags for a given user,
including the flag values and also metadata that can be used on the front end. See the
JavaScript SDK Reference Guide on
Expand Down Expand Up @@ -412,7 +412,7 @@ def all_flags_state(self, user, **kwargs):

return state

def secure_mode_hash(self, user):
def secure_mode_hash(self, user: dict) -> str:
"""Computes an HMAC signature of a user signed with the client's SDK key,
for use with the JavaScript SDK.
Expand Down
94 changes: 49 additions & 45 deletions ldclient/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
Note that the same class can also be imported from the ``ldclient.client`` submodule.
"""
from __future__ import annotations


from ldclient.feature_store import InMemoryFeatureStore
from ldclient.util import log

from typing import Callable

GET_LATEST_FEATURES_PATH = '/sdk/latest-flags'
STREAM_FLAGS_PATH = '/flags'

Expand All @@ -23,12 +27,12 @@ class HTTPConfig:
corresponding `Config` properties will be ignored.
"""
def __init__(self,
connect_timeout=10,
read_timeout=15,
http_proxy=None,
ca_certs=None,
cert_file=None,
disable_ssl_verification=False):
connect_timeout: float=10,
read_timeout: float=15,
http_proxy: str=None,
ca_certs: str=None,
cert_file: str=None,
disable_ssl_verification: bool=False):
"""
:param float connect_timeout: The connect timeout for network connections in seconds.
:param float read_timeout: The read timeout for network connections in seconds.
Expand All @@ -54,27 +58,27 @@ def __init__(self,
self.__disable_ssl_verification = disable_ssl_verification

@property
def connect_timeout(self):
def connect_timeout(self) -> float:
return self.__connect_timeout

@property
def read_timeout(self):
def read_timeout(self) -> float:
return self.__read_timeout

@property
def http_proxy(self):
def http_proxy(self) -> str:
return self.__http_proxy

@property
def ca_certs(self):
def ca_certs(self) -> str:
return self.__ca_certs

@property
def cert_file(self):
def cert_file(self) -> str:
return self.__cert_file

@property
def disable_ssl_verification(self):
def disable_ssl_verification(self) -> bool:
return self.__disable_ssl_verification

class Config:
Expand All @@ -84,38 +88,38 @@ class Config:
if you are using the singleton client, or the :class:`ldclient.client.LDClient` constructor otherwise.
"""
def __init__(self,
sdk_key=None,
base_uri='https://app.launchdarkly.com',
events_uri='https://events.launchdarkly.com',
connect_timeout=10,
read_timeout=15,
events_max_pending=10000,
flush_interval=5,
stream_uri='https://stream.launchdarkly.com',
stream=True,
initial_reconnect_delay=1,
verify_ssl=True,
defaults=None,
send_events=None,
events_enabled=True,
update_processor_class=None,
poll_interval=30,
use_ldd=False,
feature_store=None,
feature_requester_class=None,
event_processor_class=None,
sdk_key: str=None,
base_uri: str='https://app.launchdarkly.com',
events_uri: str='https://events.launchdarkly.com',
connect_timeout: float=10,
read_timeout: float=15,
events_max_pending: int=10000,
flush_interval: float=5,
stream_uri: str='https://stream.launchdarkly.com',
stream: bool=True,
initial_reconnect_delay: float=1,
verify_ssl: bool=True,
defaults: dict=None,
send_events: bool=None,
events_enabled: bool=True,
update_processor_class: Callable[[str, Config, FeatureStore], UpdateProcessor]=None,
poll_interval: float=30,
use_ldd: bool=False,
feature_store: FeatureStore=None,
feature_requester_class: Callable[[str, Config, FeatureStore], FeatureRequester]=None,
event_processor_class: Callable[[Config], EventProcessor]=None,
private_attribute_names=(),
all_attributes_private=False,
offline=False,
user_keys_capacity=1000,
user_keys_flush_interval=300,
inline_users_in_events=False,
http_proxy=None,
diagnostic_opt_out=False,
diagnostic_recording_interval=900,
wrapper_name=None,
wrapper_version=None,
http=None):
all_attributes_private: bool=False,
offline: bool=False,
user_keys_capacity: int=1000,
user_keys_flush_interval: float=300,
inline_users_in_events: bool=False,
http_proxy=None, # deprecated: will not type hint
diagnostic_opt_out: bool=False,
diagnostic_recording_interval: int=900,
wrapper_name: str=None,
wrapper_version: str=None,
http: HTTPConfig=None):
"""
:param string sdk_key: The SDK key for your LaunchDarkly account.
:param string base_uri: The base URL for the LaunchDarkly server. Most users should use the default
Expand Down Expand Up @@ -233,14 +237,14 @@ def __init__(self,
self.__http = http

@classmethod
def default(cls):
def default(cls) -> Config:
"""Returns a ``Config`` instance with default values for all properties.
:rtype: ldclient.config.Config
"""
return cls()

def copy_with_new_sdk_key(self, new_sdk_key):
def copy_with_new_sdk_key(self, new_sdk_key: str) -> Config:
"""Returns a new ``Config`` instance that is the same as this one, except for having a different SDK key.
:param string new_sdk_key: the new SDK key
Expand Down
11 changes: 5 additions & 6 deletions ldclient/feature_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from ldclient.interfaces import DiagnosticDescription, FeatureStore
from ldclient.rwlock import ReadWriteLock


class CacheConfig:
"""Encapsulates caching parameters for feature store implementations that support local caching.
"""
Expand All @@ -20,8 +19,8 @@ class CacheConfig:
DEFAULT_CAPACITY = 1000

def __init__(self,
expiration = DEFAULT_EXPIRATION,
capacity = DEFAULT_CAPACITY):
expiration: float = DEFAULT_EXPIRATION,
capacity: int = DEFAULT_CAPACITY):
"""Constructs an instance of CacheConfig.
:param float expiration: the cache TTL, in seconds. Items will be evicted from the cache after
Expand Down Expand Up @@ -50,23 +49,23 @@ def disabled():
return CacheConfig(expiration = 0)

@property
def enabled(self):
def enabled(self) -> bool:
"""Returns True if caching is enabled in this configuration.
:rtype: bool
"""
return self._expiration > 0

@property
def expiration(self):
def expiration(self) -> float:
"""Returns the configured cache TTL, in seconds.
:rtype: float
"""
return self._expiration

@property
def capacity(self):
def capacity(self) -> int:
"""Returns the configured maximum number of cacheable items.
:rtype: int
Expand Down
10 changes: 5 additions & 5 deletions ldclient/feature_store_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

from expiringdict import ExpiringDict

from ldclient.interfaces import DiagnosticDescription, FeatureStore

from ldclient.interfaces import DiagnosticDescription, FeatureStore, FeatureStoreCore
from ldclient.feature_store import CacheConfig

class CachingStoreWrapper(DiagnosticDescription, FeatureStore):
"""A partial implementation of :class:`ldclient.interfaces.FeatureStore`.
Expand All @@ -17,7 +17,7 @@ class CachingStoreWrapper(DiagnosticDescription, FeatureStore):
"""
__INITED_CACHE_KEY__ = "$inited"

def __init__(self, core, cache_config):
def __init__(self, core: FeatureStoreCore, cache_config: CacheConfig):
"""Constructs an instance by wrapping a core implementation object.
:param FeatureStoreCore core: the implementation object
Expand Down Expand Up @@ -84,7 +84,7 @@ def upsert(self, kind, item):
self._cache.pop(self._all_cache_key(kind), None)

@property
def initialized(self):
def initialized(self) -> bool:
"""
"""
if self._inited:
Expand All @@ -100,7 +100,7 @@ def initialized(self):
self._inited = True
return result

def describe_configuration(self, config):
def describe_configuration(self, config) -> str:
if callable(getattr(self._core, 'describe_configuration', None)):
return self._core.describe_configuration(config)
return "custom"
Expand Down
Loading

0 comments on commit c35fa61

Please sign in to comment.