From e50d646123fb3b21b90cef46d6b3e758aa86a122 Mon Sep 17 00:00:00 2001 From: Gui-FernandesBR <63590233+Gui-FernandesBR@users.noreply.github.com> Date: Sat, 30 Nov 2024 00:46:52 -0300 Subject: [PATCH] DOC: improvements to developers documentation (#732) * DOC: improvements to developers documentation * MNT: git rename a few files from the root directory * DOC: more upgrades to development docs * DEV: create script to delete local branches that no longer exist on remote * DOC: I followed the step by step, looked at other parts of the documentation, and didn't find anything to correct or improve. I think it's fine as it is. I added a model to requirements.txt, which was missing when I ran the make html command. * DOC: Update developer docs on sphinx building. * DOC: Clarify testing structure on testing docs. * DOC: Re-run docs requirements freeze. * DOC: Introduce Conflicts Guideline and update First PR. * DOC: fixing typos on development docs. * DOC: Solve review comments of dev docs. * DOC: final touches to developers documentation * DOC: update cSpell configuration to enable additional file types * DEV: move docker ignore file --------- Co-authored-by: Julio Machado Co-authored-by: Pedro Bressan Co-authored-by: Lucas de Oliveira Prates --- CITATION.cff => .github/CITATION.cff | 0 CODEOWNERS => .github/CODEOWNERS | 0 .../CODE_OF_CONDUCT.md | 0 CONTRIBUTING.md => .github/CONTRIBUTING.md | 0 .github/clear-local-branches.ps1 | 2 + .vscode/settings.json | 14 +- .dockerignore => docker/.dockerignore | 0 Dockerfile => docker/Dockerfile | 0 .../docker-compose.yml | 0 docs/conf.py | 1 + docs/development/build_docs.rst | 61 ++-- docs/development/conflicts.rst | 123 ++++++++ docs/development/docker.rst | 42 +-- docs/development/first_pr.rst | 139 +++++++++ docs/development/index.rst | 19 +- docs/development/pro_tips.rst | 99 +++++++ docs/development/rocketpy_as_developer.rst | 277 ------------------ docs/development/setting_up.rst | 122 ++++++++ docs/development/style_guide.rst | 95 ++++-- docs/development/testing.rst | 52 +++- docs/requirements.in | 1 + docs/requirements.txt | 5 + docs/user/motors/motors.rst | 8 +- 23 files changed, 699 insertions(+), 361 deletions(-) rename CITATION.cff => .github/CITATION.cff (100%) rename CODEOWNERS => .github/CODEOWNERS (100%) rename CODE_OF_CONDUCT.md => .github/CODE_OF_CONDUCT.md (100%) rename CONTRIBUTING.md => .github/CONTRIBUTING.md (100%) create mode 100644 .github/clear-local-branches.ps1 rename .dockerignore => docker/.dockerignore (100%) rename Dockerfile => docker/Dockerfile (100%) rename docker-compose.yml => docker/docker-compose.yml (100%) create mode 100644 docs/development/conflicts.rst create mode 100644 docs/development/first_pr.rst create mode 100644 docs/development/pro_tips.rst delete mode 100644 docs/development/rocketpy_as_developer.rst create mode 100644 docs/development/setting_up.rst diff --git a/CITATION.cff b/.github/CITATION.cff similarity index 100% rename from CITATION.cff rename to .github/CITATION.cff diff --git a/CODEOWNERS b/.github/CODEOWNERS similarity index 100% rename from CODEOWNERS rename to .github/CODEOWNERS diff --git a/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT.md rename to .github/CODE_OF_CONDUCT.md diff --git a/CONTRIBUTING.md b/.github/CONTRIBUTING.md similarity index 100% rename from CONTRIBUTING.md rename to .github/CONTRIBUTING.md diff --git a/.github/clear-local-branches.ps1 b/.github/clear-local-branches.ps1 new file mode 100644 index 000000000..f06055c08 --- /dev/null +++ b/.github/clear-local-branches.ps1 @@ -0,0 +1,2 @@ +# Delete local branches that no longer exists on remote (windows command line) +git branch -vv | Where-Object { $_ -match 'gone\]' } | ForEach-Object { $_.Trim().Split()[0] } | ForEach-Object { git branch -D $_ } diff --git a/.vscode/settings.json b/.vscode/settings.json index 62481957c..98010d539 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,12 +5,14 @@ "python.testing.unittestEnabled": false, "python.testing.pytestEnabled": true, "autoDocstring.docstringFormat": "numpy", - "cSpell.enableFiletypes": [ - "python", - "jupyter", - "markdown", - "restructuredtext" - ], + "cSpell.enabledFileTypes": { + "plaintext": true, + "python": true, + "jupyter": true, + "markdown": true, + "tex": true, + "rst": true + }, "cSpell.language": "en-US", "cSpell.words": [ "Abdulklech", diff --git a/.dockerignore b/docker/.dockerignore similarity index 100% rename from .dockerignore rename to docker/.dockerignore diff --git a/Dockerfile b/docker/Dockerfile similarity index 100% rename from Dockerfile rename to docker/Dockerfile diff --git a/docker-compose.yml b/docker/docker-compose.yml similarity index 100% rename from docker-compose.yml rename to docker/docker-compose.yml diff --git a/docs/conf.py b/docs/conf.py index e834d180e..9324ad9a6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -40,6 +40,7 @@ "sphinx.ext.napoleon", "sphinx.ext.viewcode", "sphinx.ext.mathjax", + "sphinx_tabs.tabs", "sphinx_copybutton", "sphinx_design", "jupyter_sphinx", diff --git a/docs/development/build_docs.rst b/docs/development/build_docs.rst index f94c4f0fb..398781399 100644 --- a/docs/development/build_docs.rst +++ b/docs/development/build_docs.rst @@ -31,64 +31,67 @@ requirements that are needed to run the sphinx generator. All these requirements are listed in the ``requirements.txt`` file inside the ``docs`` folder. -To install the requirements, navigate the terminal to the ``docs`` folder and -run the following command: +The easiest way to install the requirements and build the documentation is by +RocketPy's ``Makefile`` command: .. code-block:: bash - - pip install -r requirements.txt -After installing the requirements, you can build the documentation by running -the following command in your terminal: + make build-docs -.. code-block:: bash - - make html +This command will install the requirements and generate the documentation in the +``docs/_build/html`` folder. + +.. note:: -The file named ``Makefile`` contains the commands to build the documentation. -The ``make html`` command will generate the documentation in the ``docs/_build/html`` -folder. + This requires the ``make`` command to be available in your system. Check out + GNU Make documentation on how to install it. To see the documentation, open the ``docs/_build/html/index.html`` file in your browser. -.. note:: Watch out for any warnings or errors that may appear in the terminal - when building the documentation. If you find any, fix them before - pushing the changes to the repository or at least warn the team about - them. +.. important:: + + Watch out for any introduced warnings or errors that may appear in the terminal + when building the documentation. If you find any, fix them before + pushing the changes to the repository or at least warn the team about + them. Sometimes you may face problems when building the documentation after several -times of building it. -This may happen because sphinx does not clean the ``docs/_build`` folder before -building the documentation again. -To clean the ``docs/_build`` folder, run the following command in your terminal: +times of building it. This may happen because sphinx does not clean the ``docs/_build`` +folder before building the documentation again. + +One can use the internal Makefile inside the ``docs`` folder generated by sphinx +to have specific commands to build and clean the documentation. + +To clean the ``docs/_build`` folder, run the following commands in your terminal: .. code-block:: bash + cd docs/ make clean After cleaning the ``docs/_build`` folder, you can build the documentation again -by running the ``make html`` command. +by going back to rocketpy root directory and using the ``make build-docs`` command +described above. If the error persists, it may be related to other files, such as the ``.rst`` files or the ``conf.py`` file. .. danger:: - Do not modify the Makefile or the ``make.bat`` files. These files are \ - automatically generated by sphinx and any changes will be lost. + Do not modify sphinx internal Makefile or the ``docs/make.bat`` files. + These files are automatically generated by sphinx and any changes will be lost. How to integrate the documentation with ReadTheDocs --------------------------------------------------- The documentation is automatically built and hosted by `ReadTheDocs`. -Every time a commit is pushed to the repository, `ReadTheDocs` will build the -documentation and host it automatically. -This includes other branches besides the master branch. -However, the documentation will only be available for the master branch, and you -need to configure the `ReadTheDocs` project to build the documentation for other -branches. +Every time a commit is pushed to selected branches of the repository (such as `master` and `develop`), +`ReadTheDocs` will build the documentation and host it automatically. + +However, custom branches need to be manually added. If you need to have your branch +available on `ReadTheDocs`, ask to a maintainer for help. The connection between the GitHub repository and the `ReadTheDocs` project is already configured and defined in the ``readthedocs.yml`` file, available at the diff --git a/docs/development/conflicts.rst b/docs/development/conflicts.rst new file mode 100644 index 000000000..dbdb09e61 --- /dev/null +++ b/docs/development/conflicts.rst @@ -0,0 +1,123 @@ +Solving Git Conflicts +===================== + +What Are Git Conflicts? +----------------------- + +Git conflicts occur when Git is unable to automatically merge changes made to the \ +same lines of code or when changes overlap in a file across branches. +This often occurs in RocketPy repository when two developers make changes to the same \ +file and try to merge them. +In this scenario, Git pauses the operation and marks the conflicting files, \ +requiring manual intervention. + +Merge vs Rebase +--------------- + +**Merge** + +The ``merge`` operation combines the changes from one branch into another. \ +It creates a new commit that marks the merging of the two branches together. + +* Retains the full history of both branches. +* Non-linear history shows how changes were combined. +* The history can become cluttered if there are many branches, due to the number of merge commits. + +**Rebase** + +The ``rebase`` operation integrates changes from one branch into another by reapplying \ +the commits on top of the target branch. It results in a more linear history. + +* Produces a cleaner, linear commit history. +* Easier to follow the sequence of changes. +* Can rewrite history, leading to potential issues when working on shared branches. + +Example Commands +---------------- + +Let's consider a common scenario from which conflicts can arise: +updating a feature branch with the latest changes from the branch it was created. +Both ``merge`` and ``rebase`` can be used to update the feature branch. +However, the ``rebase`` option is highly recommended to keep a more linear history. + +Merge +~~~~~ + +Suppose you have two branches, ``enh/feature`` that was branched off ``develop``. +It is likely that ``develop`` has been updated since you branched off ``enh/feature``, \ +therefore before merging ``enh/feature`` into ``develop``, you should update ``enh/feature`` \ +with the latest changes from ``develop``. + +One way to do this is by merging ``develop`` into ``enh/feature`` as follows: + +.. code-block:: console + + git checkout develop + git pull + git checkout enh/feature + git merge develop + +If there are conflicts, Git will pause the operation and mark the conflicting files. \ +VS Code provides a visual interface to resolve these conflicts in the **Merge Editor**. +If you want to abort the merge, you can use ``git merge --abort``. + +Rebase +~~~~~~ + +Similarly, another way to update ``enh/feature`` with the latest changes from ``develop`` \ +is by rebasing ``enh/feature`` onto ``develop`` as follows: + +.. code-block:: console + + git checkout develop + git pull + git checkout enh/feature + git rebase develop + +Differently from merge, if there are conflicts, they must be resolved commit by commit. \ +After resolving each step conflicts, you can continue the rebase with ``git rebase --continue``. \ +If you want to abort the rebase, you can use ``git rebase --abort``. + +When to Use Merge or Rebase +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Generally, the maintainers will inform you which operation to use when merging your PR. \ +Notice that there is no wrong way to merge branches, but ``rebase`` is usually preferred \ +to keep a more linear history. + +Furthermore, it is important to avoid letting conflicts accumulate, since they can become \ +harder to resolve. It is recommended to update your feature branch frequently with the latest \ +changes from the branch it was branched off. + +Solving Conflicts +----------------- + +When conflicts arise, Git marks the conflicting files. The file will contain markers like: + +.. code-block:: console + + <<<<<<< HEAD + Current branch changes + ======= + Incoming branch changes + >>>>>>> branch-name + +The ``HEAD`` section contains the changes from the current branch, while the ``branch-name`` section \ +contains the changes from the incoming branch. +The ``=======`` line separates the two sections. +One can manually edit the file to resolve the conflict, removing the markers and keeping the desired changes, however \ +for convenience it is recommended to use a visual tool like the *Merge Editor* in VS Code. + +Resolving Conflicts in VS Code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When a conflict occurs, VS Code will open the *Merge Editor* to help you resolve it.\ + +1. Open the conflicting file (marked with a ``!``). +2. The *Merge Editor* will show the conflicting sections side by side. +3. Click on the ``Accept Current Change`` or ``Accept Incoming Change`` buttons to keep the desired changes, sometimes both changes will be kept or even a manual edit will be necessary. + +More details on VS Code interface and conflict solver can be found in `VS Code Docs `_. +After resolving the conflicts, save the files, make sure all conflicts are resolved, and then \ +commit the changes. + diff --git a/docs/development/docker.rst b/docs/development/docker.rst index 91aafb1d2..bc1de8745 100644 --- a/docs/development/docker.rst +++ b/docs/development/docker.rst @@ -2,7 +2,7 @@ RocketPy with docker ===================== RocketPy does not provide an official docker image, but you can build one -yourself using the provided `Dockerfile` and `docker-compose.yml` files. +yourself using the provided ``Dockerfile`` and ``docker-compose.yml`` files. Benefits -------- @@ -14,13 +14,13 @@ using docker are: worrying about dependencies. 2. **Portability**: run RocketPy on any operational system that supports docker, including the 3 main operational systems (Windows, Linux and Mac). -3. **Reproducibility**: ensure that tour code is working regardless of the +3. **Reproducibility**: ensure that our code is working regardless of the operational system. Using docker will be specially important when you are not sure if the code additions will still run on different operational systems. -Although we have a set of GitHub actions to test the code on different +Although we have a set of GitHub actions to test the code on different operational systems every time a pull request is made, it is important to submit a PR only after you are sure that the code will run flawlessly, otherwise quota limits may be reached on GitHub. @@ -28,7 +28,7 @@ otherwise quota limits may be reached on GitHub. Requirements ------------- -Before you start, you need to install on your machine: +Before you start, you need to install on your machine: 1. `Docker `__, to build and run the image. 2. `Docker Compose `__, to compose multiple images at once. @@ -40,11 +40,11 @@ Build the image To build the image, run the following command on your terminal: .. code-block:: console - + docker build -t rocketpy-image -f Dockerfile . -This will build the image and tag it as `rocketpy-image` (you can apply another +This will build the image and tag it as ``rocketpy-image`` (you can apply another name of your preference if you want). An image is a read-only template with instructions for creating a Docker @@ -82,7 +82,7 @@ Run the unit tests -------------------- You might have noticed that the container is running in an isolated environment -with no access to your machine's files, but the `Dockerfile` already copied the +with no access to your machine's files, but the ``Dockerfile`` already copied the RocketPy repository to the container. This means that you can run tests (and simulations!) as if you were running RocketPy on your machine. @@ -90,37 +90,37 @@ RocketPy on your machine. As simple as that, you can run the unit tests: .. code-block:: console - + pytest To access a list of all available execution options, see the `pytest docs `__. -Compose docker images +Compose docker images --------------------- -We also made available a `docker-compose.yml` file that allows you to compose +We also made available a ``docker-compose.yml`` file that allows you to compose multiple docker images at once. -Unfortunately, this file will not allow you to test the code on different +Unfortunately, this file will not allow you to test the code on different operational systems at once, since docker images inherits from the host operational system. However, it is still useful to run the unit tests on different python versions. -Currently, the `docker-compose.yml` file is configured to run the unit tests +Currently, the ``docker-compose.yml`` file is configured to run the unit tests on python 3.9 and 3.12. To run the unit tests on both python versions, run the following command **on your machine**: .. code-block:: console - + docker-compose up Also, you can check the logs of the containers by running: .. code-block:: console - + docker-compose logs @@ -131,7 +131,7 @@ After you're done testing, or if you wish to stop the containers and remove the services, use the command: .. code-block:: console - + docker-compose down @@ -142,31 +142,31 @@ images created by up. Changing to other operational systems ------------------------------------- -The default image in the `Dockerfile` is based on a Linux distribution. +The default image in the ``Dockerfile`` is based on a Linux distribution. However, you can alter the base image to use different operating systems, though the process may require additional steps depending on the OS's compatibility with your project setup. For instance, certain dependencies or scripts may behave differently or require different installation procedures, so use it with caution. -To change the base image, you will need to modify the `FROM` statement in the -`Dockerfile`. +To change the base image, you will need to modify the ``FROM`` statement in the +``Dockerfile``. For example, to use a Windows-based image, you might change: .. code-block:: Dockerfile - + FROM python:latest to .. code-block:: Dockerfile - + FROM mcr.microsoft.com/windows/servercore:ltsc2019 Please note, the above is just an example, and using a different OS may require -further adjustments in the `Dockerfile`. +further adjustments in the ``Dockerfile``. We recommend you to see the official Python images on the Docker Hub for different OS options: `Docker Hub Python Tags `__. diff --git a/docs/development/first_pr.rst b/docs/development/first_pr.rst new file mode 100644 index 000000000..5f3eb876c --- /dev/null +++ b/docs/development/first_pr.rst @@ -0,0 +1,139 @@ +Your first Pull Request (PR) +============================ + +This page describes a few steps to help you get started with your first PR to RocketPy. +We are excited to have you here! + +Picking an issue +---------------- + +Before you start coding, you should pick an issue to work on. You can find a +list of issues in the ``Issues`` tab on GitHub (https://github.com/RocketPy-Team/RocketPy/issues). +If you are new here, it is really recommended that you talk to maintainers +before starting to work on an issue. +That way you avoid working on something that is already being worked on or +something that is not in line with the project's goals. + +If you want to develop a new feature that is not in the issues list, please open +a new issue to discuss it with the maintainers before submitting a PR. + +Once the issue is assigned to you, you can start working on it. + +.. note:: + + In order to open an issue at our repo, you must have a GitHub account. \ + In case you do not want to open an account yet, you can contact the maintainers \ + through our Discord server. But keep in mind that you you need an account to \ + open a Pull Request (PR). + +Creating a new branch +--------------------- + +At your local machine, make sure you already have `git `_ \ +installed and set up. +In order to create a new branch, you should run the following command in your +preferred terminal: + +.. code-block:: console + + git checkout -b + +This command will create a new branch named ``branch_name`` from the current branch you are in. +Your branch name should follow the guidelines described in :doc:`/development/style_guide`. + +.. tip:: + + VS Code has a built-in integration with git, this allows you to run git commands \ + quite easily through the editor's interface. For example, you could search for \ + "git checkout" in the command palette and run the command from there. + + +Opening the PR +-------------- + +After you finish your work, you are more than welcome opening a PR to the RocketPy repository. +Here are some checks to do before opening a PR: + +* Check if the test suite is passing. +* Format your code using ``black`` and ``isort``. + +Check the :doc:`/development/pro_tips` section for more information on how to run these commands. + +When you open a PR, you should: + +* Provide a clear and concise title. +* Fill the PR description following the standard template. +* Use labels to help maintainers understand what the PR is about. +* Link any issue that may be closed when the PR is merged. + +Remember, the PR is yours, not ours! You should keep track of it and update it as needed. + +.. important:: + + See the :doc:`/development/style_guide` for more information on how to name and \ + describe your PR. + +Continuous Integration (CI) +--------------------------- + +There are several automation on our repository to help us maintain the code quality. +Currently, our CI pipeline runs the following checks: + +* **Linting**: we run ``flake8``, ``pylint``, ``black`` and ``isort`` on top of your latest commit in order to check for code style issues. To understand more about these tools, please read the :doc:`/development/pro_tips` section. +* **Testing**: we run the tests defined in the ``tests`` folder to make sure your changes do not break any existing functionality. The tests will be executed 6 times, each time with a different Python version (the oldest and newest supported versions) and with three different operating systems (Windows, Linux and MacOS). +* **Coverage**: based on the tests results, we also check the code coverage results from our test suite. There is an automation to check if the code coverage increased or decreased with your PR. It also points to potential introduced lines of code that should be tested. + +Once you open your PR or commit and push to your branch, the CI will be initialized. +Please correct any issues that may arise from the CI checks. + +.. important:: + + All the commands we run in the CI pipeline can also be run locally. It is \ + important that you run the checks locally before pushing your changes to \ + the repository. + +The CHANGELOG file +------------------ + +We keep track of the changes in the ``CHANGELOG.md`` file. +When you open a PR, you should add a new entry to the "Unreleased" section of the file. +This entry should simply be the title of your PR. + +.. note:: + + In the future we would like to automate the CHANGELOG update, but for now \ + it is a manual process, unfortunately. + + +The review process +------------------ + +After you open a PR, the maintainers will review your code. +This review process is a way to ensure that the code is in line with the +project's goals and that it is well written and documented. + +The maintainers may ask you to make changes to your code. +You should address these changes or explain why you think they are not necessary. +This is the best time to learn from the maintainers and improve your coding skills. + +In case you do not address the comments in a timely manner, the maintainers may +either close the PR or make the changes themselves. + + +Merging the PR +-------------- + +There are 3 different ways of merging a PR: + +1. **Create a merge commit**: this is the default option on GitHub. +2. **Squash and merge**: this option will squash all your commits into a single one. This is useful when you have many commits and you want to keep the history clean, therefore this is the recommended option. +3. **Rebase and merge**: this option will add your commits directly to the target branch, without creating a merge commit. This is useful to keep the history linear, however it also requires handling potential conflicts one at a time, which can be a bit more complex. + +.. note:: + + Overall, you will not have permission to merge your PR. The maintainers will \ + take care of that for you. This is here just for you to understand the process. + +All in all, there is no right or wrong way to merge a PR. +The maintainers will decide which option is the best for the project. +What you should care though is about conflicting changes, let's talk about that next in :doc:`/development/conflicts`. diff --git a/docs/development/index.rst b/docs/development/index.rst index 4837fa375..5d8cc490f 100644 --- a/docs/development/index.rst +++ b/docs/development/index.rst @@ -1,14 +1,27 @@ Contributing to RocketPy ======================== +Here you will find information on how to contribute to our code base. +RocketPy is an open-source project and we welcome contributions from everyone. +There are a few guidelines we would like to share with you to make your +contribution as smooth as possible: + .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :caption: Contents: - Running RocketPy as a Developer + setting_up.rst + Your First Pull Request (PR) + Solving git conflicts Style Guide Testing Guidelines RocketPy with Docker Building the Documentation + Pro Tips + + +.. important:: -This section is still a work in progress. Here you will find information on how to contribute to our code base. \ No newline at end of file + Our Development Documentation matters as much as the Usage Documentation to us. \ + In case you find any trouble when following this guide, please let us know so \ + we can improve it. diff --git a/docs/development/pro_tips.rst b/docs/development/pro_tips.rst new file mode 100644 index 000000000..465ff7982 --- /dev/null +++ b/docs/development/pro_tips.rst @@ -0,0 +1,99 @@ +Pro Tips +======== + +Last but not least, here are some pro tips that can help you to be more +productive when developing in the project (or any other project). + + +Makefile +-------- + +We have a ``Makefile`` in the repository that contains some useful commands to +help you with the development process. + +Some examples of commands are: + +* ``make black``: runs the black formatter on the code. +* ``make format``: runs the isort and black formatters on the code. +* ``make lint``: runs the flake8 and pylint tools. +* ``make build-docs``: This will build the documentation locally, so you can check if everything is working as expected. +* ``make pytest-slow``: runs only the slow tests (marked with the ``@pytest.mark.slow`` decorator). + +These commands are meant to be system agnostic, so you can run them on any +Operational System (OS). + +Knowing your editor +------------------- + +Something we usually notice on beginners is that they don't know all the power +their editor can provide. Knowing your editor can save you a lot of time and +make you more productive. + +As stated earlier, we recommend using VS Code as your editor, as most of the +RocketPy developers use it. Therefore it is easier to help you if you are using +the same editor. + +Some of the features that can help you are: + +1. **Code navigation**: Jump to definitions, find references, etc. +2. **Integrated tests**: Run tests directly from the editor. +3. **Python Debugger**: Debug your code directly from the editor. +4. **GitHub Pull Requests**: Open, review, comment, and merge pull requests directly from the editor + +Extensions +---------- + +We have listed some recommended extensions in the ``.vscode/extensions.json`` file. +These are general recommendations based on what our developers usually install +in their VSCode. +Obviously, it is not mandatory to install them, but they can help you to be more +productive. + + +Code assistance +--------------- + +Artificial Intelligence (AI) assistance has becoming more and more common in +software development. +Some editors have AI assistance built-in. +Famous options are GitHub Copilot, JetBrains AI and TabNine. + +At this repo, the use of AI tools is welcome, we don't have any restrictions +against it. + +A few possible applications of AI tools are: + +* Writing documentation. +* Writing tests. +* Getting explanations of code sections. + +.. tip:: + + As of today, November 2024, GitHub Copilot still provides free access for \ + university email addresses. We can't guarantee this will still be the case \ + when you are reading this, so check the GitHub Copilot website for more \ + information. + + +If you are against the use of AI tools, do not worry, you can still contribute +to the project without using them. + + +Engaging with the community +--------------------------- + +The most important part of contributing to an open-source project is engaging +with the community. +Our developers are frequently available on our server, and you can +ask any questions you may have there. +Either a question about the project, or a question about how to contribute, or +even a suggestion of a new feature. +Any kind of interaction is welcome. + + +.. tip:: + + The official supported language in our server is English. \ + However, the RocketPy Team is lucky to have developers from all around the \ + world, so you may find people speaking other languages as well. \ + Don't let the language barrier keep you from engaging with the community. diff --git a/docs/development/rocketpy_as_developer.rst b/docs/development/rocketpy_as_developer.rst deleted file mode 100644 index df3608c77..000000000 --- a/docs/development/rocketpy_as_developer.rst +++ /dev/null @@ -1,277 +0,0 @@ -======================== -Introduction to RocketPy -======================== - -This tutorial part shows how to open rocketpy files and run a simple simulation. - -Opening rocketpy folder -======================= - -Go into the cloned repository folder by typing on a terminal - -.. code-block:: console - - cd - -Open your preference editor by typing on a terminal - -.. code-block:: console - - . - -For example, to open VS Code type on terminal - -.. code-block:: console - - code . - -Alternatively, you can open the folder directly through your editor's interface. - -Preparing directory for code editing -==================================== - -You may create a testing file in any directory, but you must remember that they -should not be included in the commits and pull requests unless they are part of -the proposed solution. -With that in mind, we suggest you to create a folder with all testing files, so -they can be added in the ``.gitignore`` file, which contains the name of all the -files and folders that will not be added to the commits. -To create the folder, type on the terminal: - -.. code-block:: console - - mkdir - -And, to add it on .gitignore, type: - -.. code-block:: console - - echo / >> .gitignore - -It is important to remember that all the files inside this folder will not be included in any commit so, if it is important to the solution, do not add them inside it. - -Running a simulation with RocketPy -================================== - -Importing the RocketPy files ----------------------------- - -First, create a python (or .ipynb) file to make the simulation. -To ensure you are using the local files and not the files as a python package (if you installed the library via pip for example), add - -.. code-block:: python - - pip install -e . - -Alternatively you can use the following command to pip install the local library: - -.. code-block:: console - - import sys - sys.path.append('../') # if you are using a notebook - sys.path.append('../rocketpy') # if you are using a script - -Import the classes that will be used, in case: - -.. code-block:: python - - from rocketpy import Environment, SolidMotor, Rocket, Flight, Function - -If it is the first time you are using rocketpy and you do not have all required libraries installed, you could use the command: - -.. code-block:: python - - pip install -r - -Alternatively, if you are in rocketpy folder, just type - -.. code-block:: python - - pip install -r requirements.txt - -Creating an Environment ------------------------ - -Here we create the environment object that will be used in the simulation. -It contains information about the local pressure profile, temperature, speed of sound, wind direction and intensity, etc. - -.. code-block:: python - - env = Environment(latitude=32.990254, longitude=-106.974998, elevation=1400) - -RocketPy can use local files via the Ensemble method or meteorological forecasts through OpenDAP protocol. -To work with environment files, it will be very important ensuring tha that you have the netCDF4 library installed. -Assuming we are using forecast, first we set the simulated data with: - -.. code-block:: python - - import datetime - tomorrow = datetime.date.today() + datetime.timedelta(days=1) - env.set_date((tomorrow.year, tomorrow.month, tomorrow.day, 12)) # Hour given in UTC time - -Then we set the atmospheric model, in this case, GFS forecast: - -.. code-block:: python - - env.set_atmospheric_model(type="Forecast", file="GFS") - -Weather forecast data can be visualized through two info methods. - -``env.info()`` or ``env.all_info()`` - -Creating the motor that boosts the rocket ------------------------------------------ - -Now we need to create the motor. -For example, we will use a solid motor called Pro75M1670, but other configurations are also possible. -The motor class contains information about the thrust curve and uses some geometric parameters to calculate the mass variation over time, as well as the total thrust and other important outputs. - -.. code-block:: python - - Pro75M1670 = SolidMotor( - thrust_source="../data/motors/cesaroni/Cesaroni_M1670.eng", #copy here the path to the thrust source file - burn_time=3.9, - grain_number=5, - grain_separation=5 / 1000, - grain_density=1815, - grain_outer_radius=33 / 1000, - grain_initial_inner_radius=15 / 1000, - grain_initial_height=120 / 1000, - nozzle_radius=33 / 1000, - throat_radius=11 / 1000, - interpolation_method="linear", - ) - -Motor data can be visualized through the following methods: - -``Pro75M1670.info()`` or ``Pro75M1670.all_info()`` - - -Creating the rocket -------------------- - -The Rocket class contains all information about the rocket that are necessary to the simulation, including the motor, rocket mass and inertia, aerodynamic surfaces, parachutes, etc. -The first step is to initialize the class with the vital data: - -.. code-block:: python - - calisto = Rocket( - radius=127 / 2000, - mass=19.197 - 2.956, - inertia_i=6.60, - inertia_z=0.0351, - power_off_drag="../../data/rockets/calisto/powerOffDragCurve.csv", - power_on_drag="../../data/rockets/calisto/powerOnDragCurve.csv", - center_of_dry_mass_position=0, - coordinate_system_orientation="tail_to_nose", - ) - - calisto.add_motor(Pro75M1670, position=-1.255) - -Then the rail buttons must be set: - -.. code-block:: python - - calisto.set_rail_buttons(0.2, -0.5) - -In sequence, the aerodynamic surfaces must be set. -If a lift curve for the fin set is not specified, it is assumed that they behave according to a linearized model with a coefficient calculated with Barrowman's theory. -In the example, a nosecone, one fin set and one tail were added, but each case can be designed differently. - -.. code-block:: python - - nosecone = calisto.add_nose(length=0.55829, kind="vonKarman", position=0.71971 + 0.55829) - - fin_set = calisto.add_trapezoidal_fins( - n=4, - root_chord=0.120, - tip_chord=0.040, - span=0.100, - position=-1.04956, - cant_angle=0, - radius=None, - airfoil=None, - ) - - tail = calisto.add_tail( - top_radius=0.0635, bottom_radius=0.0435, length=0.060, position=-1.194656 - ) - -If you are considering the parachutes in the simulation, they also have to be added to the rocket object. -A trigger function must be supplied to trigger the parachutes. -Currently, the pressure `(p)`, the height above ground level considering noise `(h)`, and the state-space variables `(y)` are necessary inputs for the function. -The state-space contains information about the rocket's position and velocities (translation and rotation). -For example: - -.. code-block:: python - - def drogue_trigger(p, h, y): - # p = pressure considering parachute noise signal - # h = height above ground level considering parachute noise signal - # y = [x, y, z, vx, vy, vz, e0, e1, e2, e3, w1, w2, w3] - - # activate drogue when vz < 0 m/s. - return True if y[5] < 0 else False - - - def main_trigger(p, h, y): - # p = pressure considering parachute noise signal - # h = height above ground level considering parachute noise signal - # y = [x, y, z, vx, vy, vz, e0, e1, e2, e3, w1, w2, w3] - - # activate main when vz < 0 m/s and z < 800 m - return True if y[5] < 0 and h < 800 else False - -After having the trigger functions defined, the parachute must be added to the rocket: - -.. code-block:: python - - Main = calisto.add_parachute( - "Main", - cd_s=10.0, - trigger=main_trigger, - sampling_rate=105, - lag=1.5, - noise=(0, 8.3, 0.5), - ) - - Drogue = calisto.add_parachute( - "Drogue", - cd_s=1.0, - trigger=drogue_trigger, - sampling_rate=105, - lag=1.5, - noise=(0, 8.3, 0.5), - ) - -Simulating the flight ---------------------- - -Finally, the flight can be simulated with the provided data. -The rocket and environment classes are supplied as inputs, as well as the rail length, inclination and heading angle. - -.. code-block:: python - - test_flight = Flight(rocket=calisto, environment=env, rail_length=5.2, inclination=85, heading=0) - -Flight data can be retrieved through: - -``test_flight.info()`` or ``test_flight.all_info()`` - -This function plots a comprehensive amount of flight data and graphs but, if you want to access one specific variable, for example Z position, this may be achieved by `test_flight.z`. -If you insert `test_flight.z()` the graph of the function will be plotted. -This and other features can be found in the documentation of the `Function` class, which allows data to be treated in an easier way. -The documentation of each variable used in the class can be found on `Flight.py` file. - -Further considerations -====================== - -RocketPy's classes documentation can be accessed in code via `help()` command. -For example, to access Flight class parameters, you can use: - -.. code-block:: python - - help(Flight) - -More documentation materials can be found at `read the docs `_. -It can also be found on RocketPy's GitHub page on the badge "docs". \ No newline at end of file diff --git a/docs/development/setting_up.rst b/docs/development/setting_up.rst new file mode 100644 index 000000000..9bf0981fd --- /dev/null +++ b/docs/development/setting_up.rst @@ -0,0 +1,122 @@ +Setting up RocketPy as a Developer +================================== + +Your first step to contribute to RocketPy is to set up your development environment. +If you are an experienced developer, you may skip to the final sections of this page. + +Forking the repository +---------------------- + +First you need to fork the RocketPy repository. You can do this by clicking +the **Fork** button on the top right corner of the repository page on GitHub. + +By default, the fork will only have the ``master`` branch. +You should also fork the ``develop`` branch. +You can do this by **disabling** the "Copy the master branch only" option when +forking. + +.. important:: + + Our ``master`` branch is the stable branch, and the ``develop`` branch is the \ + development branch. You should always create your PRs against the ``develop`` \ + branch, unless it is a really important hotfix. + +Alternatively, one may clone the repository directly from the RocketPy repository +and then add the fork as a remote. +However, this option is less frequently used. + +Cloning the Repository +---------------------- + +Next step is to clone the repository to your local machine. +There are different ways to do this, but most of them will involve the following command: + +.. code-block:: bash + + git clone https://github.com//RocketPy.git + + +After cloning the repository, you will have a copy of the RocketPy repository on your \ +local machine and, by default, you will be on the ``master`` branch. + +.. tip:: + + Cloning a repo means downloading the repository to your local machine and \ + creating a local copy of it. We call this local copy a "local repository", \ + and the original repository is called the "remote repository". + + When you clone a repository, you are creating a connection between your local \ + repository and the remote repository. This connection allows you to push and \ + pull changes between the two repositories. + +Navigating through the project +------------------------------ + +In order to work on your local repository, you will need to open the directory where you \ +cloned it. We recommend using VS Code as your editor, but you can use any editor you prefer. +If you are using VS Code, you can open the project by running the following command: + +.. code-block:: console + + code + +After opening the project for the first time, you will be at the ``master`` branch. +To switch to another branch, such as the ``develop`` branch, you will need to fetch \ +it from the remote repository and then checkout to it. + +.. code-block:: console + + git fetch origin develop + git checkout develop + + +Installation +------------ + +We highly recommend creating a python virtual environment first. +However, we will not describe how to do this here, since this is a common task. +Run the commands below inside Rocketpy folder to install the library and +development requirements: + +.. code-block:: console + + pip install -e . # install the rocketpy lib in editable mode + pip install -r requirements-optional.txt # install optional requirements + pip install -r requirements-tests.txt # install test/dev requirements + +.. tip:: + + When installing the ``rocketpy`` library, the requirements listed in the \ + ``requirements.txt`` file will automatically be installed. + +Running the tests +----------------- + +One simple sanity check you can do after installing rocketpy is to run the unit and integration tests. +One may achieve this by running the following commands: + +Running all tests: + +.. code-block:: console + + make pytest + +Running the slow tests only: + +.. code-block:: console + + make pytest-slow + +Creating a .html coverage report, where you could see the coverage of the tests: + +.. code-block:: console + + make coverage-report + + +.. note:: + + The slow tests are the tests marked with the ``@pytest.mark.slow`` decorator. \ + These tests are usually the ones that take longer to run, and therefore are \ + not run by default. More about the tests can be found in the \ + :ref:`testing_guidelines` section diff --git a/docs/development/style_guide.rst b/docs/development/style_guide.rst index de738d53a..510a49560 100644 --- a/docs/development/style_guide.rst +++ b/docs/development/style_guide.rst @@ -1,31 +1,41 @@ Style Guide =========== -This page describes code, documentation and git branching styles used throughout RocketPy's development. +This page describes code, documentation and git branching styles used throughout +RocketPy's development. Code Style ---------- -We mostly follow the standard Python style conventions as described here: `Style Guide for Python Code `_ +We mostly follow the standard Python style conventions as described here: +`Style Guide for Python Code `_ Naming Conventions ^^^^^^^^^^^^^^^^^^ -RocketPy was, unfortunately, initially coded using `Camel Case `_. +RocketPy was, unfortunately, initially coded using +`camelCase `_. However, PEP8 specifies the following:: - Function names should be lowercase, with words separated by underscores as necessary to improve readability. + Function names should be lowercase, with words separated by underscores as \ + necessary to improve readability. Variable names follow the same convention as function names. mixedCase is allowed only in contexts where that is already the prevailing style (e.g. threading.py), to retain backwards compatibility. -Therefore, `Snake Case `_ is preferred. -For this reason, RocketPy is being converted from Camel to Snake as of version ``1.0.0``. -New contributions should strive to follow Snake case as well. +Therefore, `snake_case `_ is preferred. +For this reason, RocketPy has being fully converted from ``CamelCase`` to ``snake_case`` as of version ``1.0.0``. -Furthermore, when it comes to naming new variables, functions, classes or anything in RocketPy, always try to use descriptive names. +.. important:: -As an example, instead of using `a` or `alpha` as a variable for a rocket's angle of attack, `angle_of_attack` is preferred. -Such descriptive names make the code significantly easier to understand, review and maintain. + New contributions should only follow ``snake_case`` naming conventions. + +Furthermore, when it comes to naming new variables, functions, classes or +anything in RocketPy, always try to use descriptive names. + +As an example, instead of using ``a`` or ``alpha`` as a variable for a rocket's +angle of attack, ``angle_of_attack`` is preferred. +Such descriptive names make the code significantly easier to understand, review +and maintain. In summary: @@ -38,18 +48,37 @@ In summary: angle_of_attack = 0.2 # in rad -Linting -^^^^^^^ -As far as line wrapping, parentheses, calling chains and other code style related matter goes, RocketPy currently employs `Black style `_. +Linting and formatting +^^^^^^^^^^^^^^^^^^^^^^ + +As far as line wrapping, parentheses, calling chains and other code style +related matter goes, RocketPy currently employs `Black style `_. Installing Black and running it before submitting a pull request is highly recommend. Currently, there are pull request tests in place to enforce that Black style is used. +Aside from Black, RocketPy also uses `Flake8 `_ +and `Pylint `_ to check for code style issues. + +Running these commands before submitting a pull request is also highly recommended: + +.. code-block:: bash + + make format + make flake8 + make pylint + +These commands will check for any code style issues in the codebase. +The ``flake8`` command will throw a report directly to the console, while the +``pylint`` command will create a ``.pylint_report.txt`` file in the root directory, +which you can open to see the report. Documentation Style ------------------- -Every class, method, attribute and function added to RocketPy should be well documented using docstrings. -RocketPy follows NumPy style docstrings, which are very well explained here: `NumPyDoc Style Guide `_. +Every class, method, attribute and function added to RocketPy should be well +documented using docstrings. +RocketPy follows NumPy style docstrings, which are very well explained here: +`NumPyDoc Style Guide `_. Git Style --------- @@ -86,7 +115,12 @@ Here are a couple of example branch names: Once you are ready to create a Pull Request for your branch, we advise you to merge with the ``develop`` branch instead of the default ``master`` branch. This way, we keep the ``master`` branch stable and use the ``develop`` branch to test out new features! -If you have any doubts, just open an issue! And don't forget that these are recommendations. Don't let them keep you from contributing. +.. important:: + + If you have any doubts, just open an issue or ask in our Discord server. \ + And don't forget that these are recommendations. \ + Don't let them keep you from contributing. + Commit Messages ^^^^^^^^^^^^^^^ @@ -103,9 +137,8 @@ Commit messages should be clear and follow a few basic rules. Example:: Describing the motivation for a change, the nature of a bug for bug fixes or some details on what an enhancement does are also good to include in a commit -message. Messages should be understandable without looking at the code -changes. A commit message like ``MNT: fixed another one`` is an example of -what not to do; the reader has to go look for context elsewhere. +message. +Messages should be understandable without looking at the code changes. Standard acronyms to start the commit message with are:: @@ -120,3 +153,27 @@ Standard acronyms to start the commit message with are:: STY: style fix (whitespace, PEP8) TST: addition or modification of tests REL: related to releasing RocketPy + +.. note:: + + A commit message like ``MNT: fixed another one`` is an example of what not to do; \ + the reader has to go look for context elsewhere. + +Pull Requests +^^^^^^^^^^^^^ + +When opening a Pull Request, the name of the PR should be clear and concise. +Similarly to the commit messages, the PR name should start with an acronym indicating the type of PR +and then a brief description of the changes. + +Here is an example of a good PR name: + +- ``BUG: fix the Frequency Response plot of the Flight class`` + +The PR description explain the changes and motivation behind them. There is a template \ +available when opening a PR that can be used to guide you through the process of both \ +describing the changes and making sure all the necessary steps were taken. Of course, \ +you can always modify the template or add more information if you think it is necessary. + + + diff --git a/docs/development/testing.rst b/docs/development/testing.rst index 032287ee3..fd521167b 100644 --- a/docs/development/testing.rst +++ b/docs/development/testing.rst @@ -1,3 +1,5 @@ +.. _testing_guidelines: + Testing Guidelines ================== @@ -68,6 +70,49 @@ Do not get caught by the size of that docstring. The only requirements it has to that the docstring contains precise information on the expected behaviour and/or behaviour to be tested. +Testing Structure +----------------- + +In order to keep the tests easily readable and maintainable, RocketPy encourages +the use of the AAA pattern (Arrange, Act, Assert) for structuring the tests. + +* **Arrange:** Set up the necessary preconditions and inputs (often done by *Fixtures* as it will be described below); +* **Act:** Execute the code under test; +* **Assert:** Verify that the code under test behaves as expected. + +The following example illustrates the AAA pattern: + +.. code-block:: python + + @pytest.mark.parametrize( + "latitude, longitude", [(-21.960641, -47.482122), (0, 0), (21.960641, 47.482122)] + ) # Arrange: Done by the fixtures and the parameters of the test + def test_location_set_location_saves_location(latitude, longitude, example_plain_env): + """Tests location is saved correctly in the environment obj. + + Parameters + ---------- + example_plain_env : rocketpy.Environment + latitude: float + The latitude in decimal degrees. + longitude: float + The longitude in decimal degrees. + """ + # Act: Set the location + example_plain_env.set_location(latitude, longitude) + # Assert: Check if the location was saved correctly + assert example_plain_env.latitude == latitude + assert example_plain_env.longitude == longitude + +This pattern is a general guideline, of course specific tests cases might +modify it to better fit the specific needs of the test. + +.. note:: + + Parameterization is a powerful feature of ``pytest.mark.parametrize`` that allows + you to run the same test with different inputs. This is highly recommended when + there multiple testing scenarios for the same method. + Directory Structure ------------------- @@ -234,7 +279,7 @@ This test contains two fundamental traits which defines it as an integration tes The motivation behind lies in the fact that it interacts and calls too many methods, being too broad to be considered an unit test. -Please be aware that Integration tests are not solely classfied when interacting with external dependencies, +Please be aware that Integration tests are not solely classified when interacting with external dependencies, but also encompass verifying the interaction between classes or too many methods at once, such as ``all_info()``. Further clarification: Even if the test contains traits of unit tests and use dependencies which are stable, such as @@ -305,5 +350,6 @@ documenting purposes, such as below: [[-10. 10.]] """ -This is not common practice, but it is optional and can be done. RocketPy however encourages -the use of other means to test its software, as described. +This is not common practice, but it is optional and can be done, specially to provide +an usage example for the function under testing. RocketPy however encourages the use +of other means to test its software, as described. diff --git a/docs/requirements.in b/docs/requirements.in index ea736a11a..b5138ee0c 100644 --- a/docs/requirements.in +++ b/docs/requirements.in @@ -6,3 +6,4 @@ ipykernel==6.29.4 pandas==2.2.2 lxml_html_clean==0.1.1 sphinx-copybutton==0.5.2 +sphinx-tabs==3.4.7 diff --git a/docs/requirements.txt b/docs/requirements.txt index a5d9c279d..c56c20cae 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -43,6 +43,7 @@ docutils==0.20.1 # nbsphinx # pydata-sphinx-theme # sphinx + # sphinx-tabs entrypoints==0.4 # via nbconvert executing==2.0.1 @@ -159,6 +160,7 @@ pygments==2.18.0 # nbconvert # pydata-sphinx-theme # sphinx + # sphinx-tabs python-dateutil==2.9.0.post0 # via # jupyter-client @@ -195,10 +197,13 @@ sphinx==7.3.7 # pydata-sphinx-theme # sphinx-copybutton # sphinx-design + # sphinx-tabs sphinx-copybutton==0.5.2 # via -r requirements.in sphinx-design==0.5.0 # via -r requirements.in +sphinx-tabs==3.4.7 + # via -r requirements.in sphinxcontrib-applehelp==1.0.8 # via sphinx sphinxcontrib-devhelp==1.0.6 diff --git a/docs/user/motors/motors.rst b/docs/user/motors/motors.rst index a6bc6ef4b..b690cf9e8 100644 --- a/docs/user/motors/motors.rst +++ b/docs/user/motors/motors.rst @@ -1,3 +1,5 @@ +.. _motors_usage: + Motors Usage ============ @@ -12,13 +14,13 @@ Motors Usage :caption: Solid Motors Solid Motor Usage - + .. toctree:: :maxdepth: 3 :caption: Hybrid Motors Hybrid Motor Usage - + .. toctree:: :maxdepth: 3 :caption: Liquid Motors @@ -30,7 +32,7 @@ Motors Usage :caption: Generic Motors Generic Motor Usage - + .. toctree:: :maxdepth: 3 :caption: Tanks and Fluid