# Contributing to `perpetual` ## Development Setup The repository comes with a predefined set of development tools in the `Makefile` which can be listed by running `make help` or `make`. Before you start contributing or developing further it is required that you initialize the artifacts and dependencies needed for conducting the unit-tests. To do this run the following command: ```sh make init ``` For development, it is assumed you have stable Rust installed, and at least Python 3.10. ### Running tests To run the tests in the repository use `make test` - this will run all tests available in the repository. For Python or Rust specific tests that has no downstream or upstream changes use `make py-test` or `make rust-test`, respectively. ## Benchmarking Benchmarking is run using the [`criterion`](https://github.com/bheisler/criterion.rs) Rust crate. To run the benchmarks, you can run the following command from your terminal. ```sh cargo bench ``` specific benchmarks can be targeted by referring to them by name. ```sh cargo bench "fast sum" ``` ## Pre-commit The [`pre-commit`](https://pre-commit.com/) framework should be installed and used to ensure all commits meet the required formatting, and linting checks prior to a commit being made to the repository. This is installed by `make init` too. ## Serialization The saving and loading of the model is all handled by the [`serde`](https://docs.rs/serde/1.0.163/serde/) and [`serde_json`](https://docs.rs/serde_json/latest/serde_json/) crates. Because of this you will see the following attribue calls sprinkled throughout the package. ```rust #[derive(Deserialize, Serialize)] ``` Additionally in order to not break backwards compatibility with models saved in previous versions, any new items added to the `Tree` or `PerpetualBooster` struts, should have a default value defined. This way models can be loaded, even if they were saved before the new fields was added. A default value can be added for a fields using the `#[#[serde(default = "default_sample_method")]]` attribute. Where the string that default is referring to must be the name of a valid function, the following is a complete example of this. ```rust use crate::sampler::SampleMethod, Sampler; #[derive(Deserialize, Serialize)] pub struct PerpetualBooster { // ... #[serde(default = "default_sample_method")] pub sample_method: SampleMethod, // ... } fn default_sample_method() -> SampleMethod { SampleMethod::None } ```