October 11, 2023
From zero to open source: Contributing to quantum open source projects
The following is a guest post by Emiliano Godinez from the Technical University of Munich, sharing his experience and advice on contributing to quantum open source software and going from beginner to confident.
As a physics student, I was used to writing scientific code. Code that only I would use or, at most, that I would show my thesis supervisor. That is why most of my code consisted of functions and one-line comments.
Object-oriented and proper docstrings, who? It was only when I started working on projects with other people that I started caring not only about what I was writing, but also how I was writing it.
In particular, one of the experiences that have shaped me the most as a “quantum software developer” has been contributing to open-source projects; first for my work-related projects, later during my participation at unitaryHACK, and currently for my own projects, too.
The very first time I had the chance to contribute to an open-source library was less than a year ago, in October of 2022. At that time, I was working on a project where I was using the quantum optimization library OpenQAOA. At one point I realized I needed a new feature to be implemented in the library. When I asked the developers for it, they told me that at the moment it was not on the project roadmap… but that I could help them develop it!
The possibility of helping develop a library that I used in my projects sounded amazing. However, silly me, I thought all I had to do was to send them my Python file and they would add it to their repository!
Reality was different. Writing the code is just the “ham” of the open-sourcing “sandwich”. The actual workflow includes steps ranging from navigating version control (for example, Git) and setting up a development environment to getting acquainted with the project’s coding guidelines and testing, along with a review process.
So, does that mean that you have to master all of these things before even thinking of contributing to a project? Fortunately, the answer is NO — au contraire!
I was pleasantly surprised by how well-received my poorly tested first draft was. Of course, there was a lot I had to learn and work on to get my contribution up to the standard of the project, but this is all part of the process, so you shouldn’t worry about making your first draft perfect! This is the reason why your code goes through a review by the code maintainers. During the review process, you can expect to get valuable and constructive comments on how to improve your code. It is also a great way to learn from others’ coding styles, their best practices, and to have fruitful discussions on, for instance, better-performing implementations or creative alternatives to your code.
And the best part, and something I always try to keep in mind, is: people are actually really happy that you are interested in contributing to their project, and they are really open to helping you successfully submit your contribution!
I really believe this is the essence of open-sourcing: a sort of symbiosis where you as a contributor can foster your skills and knowledge while helping your favorite open-source projects grow and improve! It is really a win-win situation for everyone involved. 😀
First Steps
While I mentioned that your first draft doesn’t need to be perfect, checking the contribution guidelines of the project is always a good first step towards a successful contribution. Through these guidelines you can get an idea of the general best practices followed by the developers, the architecture overview of the code, and the style followed throughout the project.
These are some of the first things I learned from contribution guidelines:
- How to install a project from source in development mode. I.e. how to install a library so you can edit the source code and see the changes when importing it in your scripts. This is different from a “standard” installation as an end user, where even though you might be able to see the source code on your IDE (integrated development environment), the changes you make in the code would not be reflected in the functionality of the package you have installed.
- The importance of setting and working in a clean development environment. Whether using Pip or Conda, using a new clean environment specific to the development of a library can save you hours of trying to handle compatibility issues between different libraries. This includes using the explicitly recommended Python version, as some libraries only support a certain range of versions.
- How to make the best out of the development toolkit and workflow of the project. Different projects use different tools and follow different workflows, but in general, they all include a variety of tests that ensure your changes do what they intend to do, and that they do not break existing code. In addition, to ensure uniformity and quality of the code, linters, code coverages, and other custom automatic checks can be part of the pipeline. Learning how to manage these tools can save you a lot of time, and help you make your code cleaner and coherent with the rest of the project. We’ll see a couple of examples of this further on.
Paying attention to the contribution guidelines became particularly helpful to me when I was contributing to different projects, as each of them has its own documentation style, test suite, and specific requirements to be satisfied. This was the case when I participated in this year’s edition of unitaryHACK, where among other projects available, I had the opportunity to contribute to PennyLane and QuTip while collecting bounties. Without a doubt, this was a great experience that helped me deepen my knowledge of the open-sourcing world and become more confident and comfortable when contributing to different libraries or managing several code environments and workflows at the same time.
Don’t be scared of Git
Git is actually something that took me a decent time to get comfortable with. Even after working as a front-end developer for some months, I was still a bit “scared” of pushing or pulling the wrong wires (pun intended). Until I realized that Git was exactly the solution to the problems I was scared of!
- If you want to make sure your changes don’t get lost:
commit
! - If you think that you messed up and want to go back to a previous state:
reset
! - If you want to save your changes for later:
stash
! - If you want to get the latest updates on what others have been working on:
fetch
!
I think you get the idea. 😉 Git is a really powerful tool for developers and the key to unleashing its immense potential is, most of the time, just one search away. There are some great tutorials out there that guide you through what Git is all about, but in my opinion, once you get the basics (how to clone, add, push, commit, …), you will learn the most by working through different projects, messing up, and stack-overflowing your way out.
Some useful “theory”, however, that I can recommend you read is Git history
(another resource here). Understanding the git commit
history can help you
navigate through branches, rewrite history, rebase and merge, among other
things. Talking about merging, merge conflicts are also something I was scared
of for some time (or maybe I am just easily scared). I still remember one of my
colleagues teasing me with “Have fun merging and solving the conflicts!” Having
to merge conflicts can feel daunting sometimes, but, once again, there are
pretty cool tools out there to help you go through with it! In particular, I
find using IDEs like VS Code quite helpful. With tools like their 3-way editor,
you can display the incoming and current changes in parallel, together with the
final result of your merge, while interactively resolving the conflicts.
Tip: If after an attempted merge you find your files looking like:
<<<<<<< HEAD:file.txt Hello world ======= Goodbye >>>>>>> 77976da35a11db4580b80ae27e8d65caf5208086:file.txt
Don’t panic! This is just showing you the current (from <<<<<<<
to =======
) and the incoming changes
(from =======
to >>>>>>>
), as explained here. By using IDE tools, you can easily
get rid of these strange symbols by simply resolving the merge conflicts and solving the problem.
To end this section, I would like to draw your attention to the importance of committing… both to the project and in Git (😜). Git commits help you create a snapshot of your staged changes, adding them to your project timeline. So, committing often is good practice. This can be useful, for instance, to make sure your progress is saved and to let you go back to what the project looked like at specific points in time.
Equally important is creating good commits. This means making sure your commits are accompanied by a meaningful message, and that they encompass a full logical component and related changes. To think of an appropriate commit message, you can ask yourself: “What happens to the code when the changes in this commit are applied?” If you find that the answer is rather long, this probably means you are cluttering too many changes into one commit, and you should restructure them into atomic changes. This is especially helpful when collaborating with other developers.
Testing suites: your best friend in continuous integration
As we discussed at the beginning of this blog post, to ensure your contributions do not introduce errors and that they follow the project standards, a common software practice is to automatically test your code after it is pushed to the repository, known as continuous integration (CI). Among CI tools, some of the most popular ones include:
- Black: an automatic code formatter that changes your code to comply with the PEP 8 standards. It is as easy as installing it and running it on a file:
- Pylint: a code analyzer that helps you adhere to the coding standards of the project by displaying warnings and errors:
The standard of the modules can be found in the .pylintrc
file of each
directory. If at some point you find yourself wanting to ignore certain checks,
you can also configure this for the whole project using the disable
tag in
this file, or you can use it at a block or line level with a comment:
global VAR # pylint: disable=global-statement
- Pytest: a framework for software tests.
Although other options for testing frameworks do exist, Pytest allows you to
mark your tests with customary labels, which gives you better control over the
tests you run. For example, this can be seen on the interface-specific markers
in PennyLane:
@pytest.mark.autograd
,@pytest.mark.torch
,@pytest.mark.tf
, and@pytest.mark.jax
. Something I find particularly useful is the flexibility of re-running only the failed tests usingpytest --lf
or running a specific method within a class in a module:
pytest test_mod.py::TestClass::test_method
And these options are just the tip of the iceberg, with many other possibilities to address specific tests.
Tip: While tests are often run automatically after pushing to the remote repository, it is very useful to install the testing packages and tools locally to speed up the process (otherwise you would have to wait for all tests and checks to pass every time you push to make sure your changes work as expected).
From beginner to beginner
If you want to get started in the world of open-sourcing but don’t know how, here are a couple of tips that I believe could help you:
- Most projects add labels to their open issues, and one of these labels is “good first issue”, which is given to, as you might guess, good first issues (😜) for new developers who want to start contributing to open-source projects. Some examples include erasing deprecated imports, adding a warning when a function is called, adding a property to a class, or restructuring files.
- However, if you think that those “good first issues” are still far from the expertise you currently have, you can come up with your own “simple” PR (with or without creating an issue for it). For instance, fixing a typo in the documentation can be a good way for you to get acquainted with the whole workflow of contributing and the tools used, without the additional load of coming up with a solution to a problem.
- People don’t expect you to be an expert, so don’t worry about asking questions and making mistakes: it is all part of the journey! Ask for clarifications, ask for additional sources to get acquainted with a topic, ask for examples, ASK, ASK, ASK! Also, remember: you don’t need to be an expert to start, but you do need to start if you want to become an expert at some point. 🙂
- In particular, if you are planning on contributing to PennyLane (or any other open-source project), taking a look at the specific instructions in the project’s development guide can help you a lot! In my unitaryHACK contribution to PennyLane, I wrote a new class for qutrit state preparation. To do so, I first looked at other similar classes and inferred what elements would be needed. But during the review process I realized that there is an introduction page that talks about exactly what I was trying to figure out on my own! If you look around, you might be surprised at how many resources are already out there to help you. 😀
- Every contribution counts! No matter if you are developing a totally new functionality, fixing a bug, or correcting a typo, every new contribution is a new experience from which you can learn, acquire more tricks, and be a step closer to becoming a seasoned developer… while helping your favorite library improve. 😎
About the author
Emiliano Godinez
Passionate about cheese cake, football, and pretty proofs.