Skip to content

Commit ea9e1f4

Browse files
prepare 7.4.0 release (#164)
1 parent 5f9b0b7 commit ea9e1f4

File tree

10 files changed

+957
-12
lines changed

10 files changed

+957
-12
lines changed

.circleci/config.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,7 @@ jobs:
9393
name: verify typehints
9494
command: |
9595
export PATH="/home/circleci/.local/bin:$PATH"
96-
mypy --install-types --non-interactive ldclient testing
97-
mypy --config-file mypy.ini ldclient testing
96+
make lint
9897
9998
- unless:
10099
condition: <<parameters.skip-sse-contract-tests>>

CONTRIBUTING.md

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,64 @@ The additional requirements files `consul-requirements.txt`, `dynamodb-requireme
3232

3333
### Testing
3434

35-
To run all unit tests:
35+
To run all unit tests except for the database integrations:
3636

37+
```shell
38+
make test
3739
```
38-
pytest
39-
```
4040

41-
By default, the full unit test suite includes live tests of the integrations for Consul, DynamoDB, and Redis. Those tests expect you to have instances of all of those databases running locally. To skip them, set the environment variable `LD_SKIP_DATABASE_TESTS=1` before running the tests.
41+
To run all unit tests including the database integrations (this requires you to have instances of Consul, DynamoDB, and Redis running locally):
42+
43+
```shell
44+
make test-all
45+
```
4246

4347
There are also integration tests that can be run against the LaunchDarkly service. To enable them, set the environment variable `LD_SDK_KEY` to a valid production SDK Key.
4448

45-
### Portability
49+
It is preferable to run tests against all supported minor versions of Python (as described in `README.md` under Requirements), or at least the lowest and highest versions, prior to submitting a pull request. However, LaunchDarkly's CI tests will run automatically against all supported versions.
4650

47-
Most portability issues are addressed by using the `six` package. We are avoiding the use of `__future__` imports, since they can easily be omitted by mistake causing code in one file to behave differently from another; instead, whenever possible, use an explicit approach that makes it clear what the desired behavior is in all Python versions (e.g. if you want to do floor division, use `//`; if you want to divide as floats, explicitly cast to floats).
51+
### Building documentation
4852

49-
It is preferable to run tests against all supported minor versions of Python (as described in `README.md` under Requirements), or at least the lowest and highest versions, prior to submitting a pull request. However, LaunchDarkly's CI tests will run automatically against all supported versions.
53+
See "Documenting types and methods" below. To build the documentation locally, so you can see the effects of any changes before a release:
54+
55+
```shell
56+
make docs
57+
```
58+
59+
The output will appear in `docs/build/html`. Its formatting will be somewhat different since it does not have the same stylesheets used on readthedocs.io.
60+
61+
### Running the linter
62+
63+
The `mypy` tool is used in CI to verify type hints and warn of potential code problems. To run it locally:
64+
65+
```shell
66+
make lint
67+
```
68+
69+
## Code organization
70+
71+
The SDK's module structure is as follows:
72+
73+
* `ldclient`: This module exports the most commonly used classes and methods in the SDK, such as `LDClient`. The implementations may live in other modules, but applications should not need to import a more specific module such as `ldclient.client` to get those symbols.
74+
* `ldclient.integrations`: This module contains entry points for optional features that are related to how the SDK communicates with other systems, such as `Redis`.
75+
* `ldclient.interfaces`: This namespace contains types that do not do anything by themselves, but may need to be referenced if you are using optional features or implementing a custom component.
76+
77+
A special case is the module `ldclient.impl`, and any modules within it. Everything under `impl` is considered a private implementation detail: all files there are excluded from the generated documentation, and are considered subject to change at any time and not supported for direct use by application developers. Alternately, class names can be prefixed with an underscore to be "private by convention"; that will at least prevent them from being included in wildcard imports like `from ldclient import *`, but it is still preferable to avoid a proliferation of implementation-only modules within the main `ldclient` module, since developers may wrongly decide to reference such modules in imports.
78+
79+
So, if there is a class whose existence is entirely an implementation detail, it should be in `impl`. Similarly, classes that are _not_ in `impl` must not expose any public members (i.e. symbols that do not have an underscore prefix) that are not meant to be part of the supported public API. This is important because of our guarantee of backward compatibility for all public APIs within a major version: we want to be able to change our implementation details to suit the needs of the code, without worrying about breaking a customer's code. Due to how the language works, we can't actually prevent an application developer from referencing those classes in their code, but this convention makes it clear that such use is discouraged and unsupported.
80+
81+
### Type hints
82+
83+
Python does not require the use of type hints, but they can be extremely helpful for spotting mistakes and for improving the IDE experience, so we should always use them in the SDK. Every method in the public API is expected to have type hints for all non-`self` parameters, and for its return value if any.
84+
85+
It's also desirable to use type hints for private attributes, to catch possible mistakes in their use. Until all versions of Python that we support allow the PEP 526 syntax for doing this, we must do it via a comment in the format that `mypy` understands, for instance:
86+
87+
```python
88+
self._some_attribute = None # type: Optional[int]
89+
```
90+
91+
## Documenting types and methods
92+
93+
All classes and public methods outside of `ldclient.impl` should have docstrings in Sphinx format. These are used to build the documentation that is published on [readthedocs.io](https://launchdarkly-python-sdk.readthedocs.io/). See the [Sphinx documentation](https://www.sphinx-doc.org/en/master/) for details of the docstring format.
94+
95+
Please try to make the style and terminology in documentation comments consistent with other documentation comments in the SDK. Also, if a class or method is being added that has an equivalent in other SDKs, and if we have described it in a consistent away in those other SDKs, please reuse the text whenever possible (with adjustments for anything language-specific) rather than writing new text.

Makefile

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
2+
PYTEST_FLAGS=-W error::SyntaxWarning
3+
4+
test:
5+
LD_SKIP_DATABASE_TESTS=1 pytest $(PYTEST_FLAGS)
6+
7+
test-all:
8+
pytest $(PYTEST_FLAGS)
9+
10+
lint:
11+
mypy --install-types --non-interactive --config-file mypy.ini ldclient testing
12+
13+
docs:
14+
cd docs && make html
15+
16+
.PHONY: test test-all lint docs
17+
18+
119
TEMP_TEST_OUTPUT=/tmp/contract-test-service.log
220

321
# port 8000 and 9000 is already used in the CI environment because we're

docs/api-testing.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Test fixtures
2+
=============
3+
4+
ldclient.integrations.test_data module
5+
--------------------------------------
6+
7+
The entry point for this feature is :class:`ldclient.integrations.test_data.TestData`.
8+
9+
.. automodule:: ldclient.integrations.test_data
10+
:members:
11+
:special-members: __init__
12+
:show-inheritance:

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ For more information, see LaunchDarkly's `Quickstart <https://docs.launchdarkly.
1919
api-main
2020
api-integrations
2121
api-extending
22+
api-testing
2223
api-deprecated

ldclient/impl/integrations/test_data/__init__.py

Whitespace-only changes.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import copy
2+
from ldclient.versioned_data_kind import FEATURES
3+
from ldclient.rwlock import ReadWriteLock
4+
5+
6+
class _TestDataSource():
7+
8+
def __init__(self, feature_store, test_data):
9+
self._feature_store = feature_store
10+
self._test_data = test_data
11+
12+
def start(self):
13+
self._feature_store.init(self._test_data._make_init_data())
14+
15+
def stop(self):
16+
self._test_data._closed_instance(self)
17+
18+
def initialized(self):
19+
return True
20+
21+
def upsert(self, new_flag):
22+
self._feature_store.upsert(FEATURES, new_flag)

ldclient/integrations.py renamed to ldclient/integrations/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,9 +206,9 @@ class Files:
206206
"""
207207

208208
@staticmethod
209-
def new_data_source(paths: List[str],
210-
auto_update: bool=False,
211-
poll_interval: float=1,
209+
def new_data_source(paths: List[str],
210+
auto_update: bool=False,
211+
poll_interval: float=1,
212212
force_polling: bool=False) -> object:
213213
"""Provides a way to use local files as a source of feature flag state. This would typically be
214214
used in a test environment, to operate using a predetermined feature flag state without an

0 commit comments

Comments
 (0)