diff --git a/doc/contributors_guide/code_changes.md b/doc/contributors_guide/code_changes.md new file mode 100644 index 000000000..f5ddb479f --- /dev/null +++ b/doc/contributors_guide/code_changes.md @@ -0,0 +1,77 @@ +Code changes +============ +Although that DLite haven't reached version 1.0.0, it strives to be stable and not introduce unnecessary backward-incompatible changes. + + +Versioning +---------- +Before reaching v 1.0.0, DLite follows the following versioning rules that are well-known from Python: + +* **patch release**: Only backward-compatible changes. + - Addition of new backward-compatible features. + - New deprecation warnings can be added. + +* **minor release**: Backward-incompatible changes. + - Addition of new backward-incompatible features. + - Removal of deprecated features. + - Changing default behavior. + +After version 1.0.0, DLite should strictly follow the [semantic versioning] rules. + + +Feature deprecation +------------------- +In Python, use `dlite.deprecation_warning()` (function to be added) to mark deprecation warnings. +This function is a simple wrapper around `warnings.warn(msg, DeprecationWarning, stacklevel=2)` with the release version when the feature is planned to be removed as an additional argument. + +In C, use the `deprecation_warning()` function (to be added) to mark a +deprecation warning. + +The idea with these functions is to make it easy to grep for deprecation warnings that should be remove in a new backward-incompatible release. +The following command can e.g. be used to find all deprecation warnings: + + find \( -name '*.py' -o -name '*.i' -o -name '*.c' \) ! -path './build*' | xargs grep -n -A1 deprecation_warning + + +How to handle different types of code changes +--------------------------------------------- + +### Backward-compatible API changes +The easiest API changes are those that only adds new functions or classes without changing the existing code, apart from adding deprecation warnings hinting about how to use the new API. + +Adding new arguments to an existing function or new methods to existing classes falls also into this category. +**Note**, new (positional) arguments should be added to the end of the argument list, such that existing code using positional arguments will be unaffected by the change. + +### New behavior +All changes in behavior should be considered backward-incompatible. + +Where it make sense, DLite will try to optionally keep the new/old behaviour over some releases in order for users to adapt to the new behavior. + +Each optional new behavior should have a: +- name +- description +- release number for when the behavior was introduced (keeping old behavior as default) +- release number for when the new behavior should be the default (managed automatically) +- expected release number for when the old behavior should be removed (require developer effort) + +All behaviors are described in a single source file `src/dlite-behavior.c`. + +Behavior can be selected in several ways: + +- **programmatically from Python**: + + >>> from dlite.behavior import Behavior + >>> Behavior. = True # true means use the new behavior + +- **programmatically from C**: + + dlite_behavior("", 1); + +- **via environment variables**: + + export DLITE_BEHAVIOR_ + +A warning will automatically be issued if a behavior is not selected explicitly. + + +[semantic versioning]: https://semver.org/ diff --git a/doc/contributors_guide/index.rst b/doc/contributors_guide/index.rst index 65900486e..f0aa51c4e 100644 --- a/doc/contributors_guide/index.rst +++ b/doc/contributors_guide/index.rst @@ -9,4 +9,5 @@ Contributor's Guide documentation_contributors documentation_testing release_instructions + code_changes tips_and_tricks