This repository is intended as an example RAIMAD package, demonstrating the bare basics needed to share your components as a package.
It's a good idea to include an installing
section
in your project's README, even if it's as simple as
pip install git+https://gitlab.example.com/exp-ast/rai_smiley
The rest of this README explains what each file in this example repository does. The overall file structure looks like this:
<repository root>
│
├── src
│ └── rai_smiley
│ ├── __init__.py
│ │
│ ├── resources
│ │ ├── __init__.py
│ │ └── facial_data.csv
│ │
│ └── smiley.py
│
├── .gitignore
├── pyproject.toml
├── MANIFEST.in
├── README.md
├── LICENSE.txt
├── img
│ └── smiley.png
│
└── tests
└── test_smiley.py
This is the star of the show, the file which contains our component.
Note that almost every single line starts with at least an indent block.
The only lines which are in the toplevel of the file are the
module docstring at the very top,
the import raimad
line,
and the Smiley
class declaration.
You might have some stray code in your file that
tests something,
or exports the component.
Delete it!
Otherwise, all of that code will run the moment
the user runs import rai_smiley
!
This file is necessary to get Python to recognize rai_smiley
as a package.
You should put this __init__.py
file inside every directory
that has python code files in it.
In most cases, it suffices to leave __init__.py
files empty.
However, this specific __init__.py
does a small
but very useful thing called namespace flattening.
Read the comment inside __init__.py
to find out more!
Note that technically, things should work without an __init__.py
,
but then you would be creating something called a namespace package,
which is not what you want most of the time.
Sometimes it is desirable to include non-python files (resources)
within your package.
For example, you could have data generated by an external tool stored
in .csv
files.
For this, we have the directory called resources
.
In our case, there is just one data file facial_data.csv
.
Note that there is also an (empty) __init__.py
,
since this directory should also be counted as a module.
It may be tempting to use the __file__
dunder to find
the path to facial_data.csv
and read it this way.
However, there are many sharp corners with this approach
(Does the end user's OS use forward slashes or backslashes?
Is their filesystem case sensitive or not?
Is the package installed normally on-disk,
or is it all inside of a .zip
file?)
To avoid these pains, we use importlib.resources
to read in resource files.
Take a look inside smiley.py
to learn how this works.
.gitignore
tells git what files to ignore.
This can be stuff like temporary files created by your text
editor or IDE.
It's also nice to include files that may accidentally end
up in the repository (e.g. .cif
output files).
Note that since .gitignore
starts with a dot,
you might not be able to see this file in GUI file browsers.
This repository contains a reasonable .gitignore
,
but you should do your own research and add any unwanted files
that your development environment creates.
Usually, it's enough to look up
<name of thing you're using to write python> .gitignore
in your search engine of choice.
This file tells pip about your package.
It contains metadata like package name, version, author,
and licensing information.
It also contains a list of dependencies and
instructions that pip will use to setup your package.
You can read the comments inside pyproject.toml
for more information.
Not that long ago, the function of pyproject.toml
was done by a different
file called setup.py
.
Indeed, many large projects still rely on setup.py
,
and you are free to do so too.
This file declares that everything under rai_smiley/resources
are part of this package and should never be ignored.
You can read the comment inside MANIFEST.in
for more information.
This is the file you're reading right now!
This file is an (optional (but strongly recommended)) description of your package to help other people understand what it's all about.
The .md
file extension indicates that it's written in the
Markdown format.
Markdown files are just plaintext files with some extra
formatting.
You are probably already familiar with Markdown
from Reddit, Discord, Whatsapp, Jupyter Notebook, ...
Here is a quick refresher:
# This is a heading
## This is a subheading
### This is a subsubheading
this is a normal text
this is normal text on a new paragraph
but this is normal text on the same paragraph,
since there is no skipped line
*this text is bold*
_this text is italic_
`this is inline code`
```
this is a code block
```
```python
this is a code block with Python syntax highlighting
```
[this](http://example.com) is a hyperlink
If your normal text containst asterisks, underscores,
or other format characters,
you have to escape them with backslashes,
like this: \_\_init.py\_\_
Below (would be) an image:
![image description](path/to/image.png)
| Table column 1 | Table column 2 |
| ------------------- | -------------- |
| This | Is |
| A | Table |
This is $` A = 2 \pi r^2 `$ inline math.
This is also $ A = 2 \pi r^2 $ inline math.
This is math on a separate line:
$$
A = 2 \pi r^2
$$
This file contains the license under which you distribute your project.
There is not set convention for what this file should be called,
so any reasonable name should be okay, as long as it matches
with the license file specified in pyproject.toml
.
You can put any pictures you want to include in your README.md
into this directory.
It's a good idea to include a screenshot of your component(s)
in KLayout.
If you're only going to have one picture,
you can put it into the root of the repository as well,
and skip having an img
directory.
If you are opposed to storing images in git due to religious reasons, feel free to skip out on this. However, please be mindful that some people have no problem with this, and it is their right to put binary files into version control systems. Tolerance and intercultural understanding are paramount to effective collaborative programming.
It is always a good idea to have automatic tests for your project. Think of it this way: programming is like installing a fitted carpet: just when you get one part of it to be nice and flat, another part at the opposite end of the room bulges up and needs to be fitted again. Programming without automatic tests is like trying to do the same, but in complete darkness: you can't even tell when there is a part that needs to be flattened!
For more information on writing unit tests for Python, consult the official documentation.