# Using an EI Python Project
Checkout the files from Github.
cd /path/to/where/you/want/it
git clone https://github.com/danielpi/JGRAB-Processing.git
cd JGRAB-Processing
Create a virtual environment
python3 -m venv .venv
source .venv/bin/activate
Install the required packages
pip install -r requirements.txt
Then follow the instructions in the README file for how to use the program.
# Creating a Python Project
This file describes some best practices for setting up a python project.
Create a new repository on Github (should we have a template???)
Add a README.md file and fill it in. This file will be rendered on the first page of your github project page. It should contain all the information required for someone to make use of your project. The file is a text file with [Markdown](https://daringfireball.net/projects/markdown/syntax) formatting.
## Virtual Environments
Create a [virtual environment](https://docs.python.org/3/library/venv.html) and then [activate](https://docs.python.org/3/tutorial/venv.html) it. This will allow your project to have its own set of independent python packages (avoiding conflicts or dependancy issues).
In your project folder type
python3 -m venv .venv
source .venv/bin/activate
This will create a hidden folder called .venv in your project directory. It will
## Setup.py
The most important file is `setup.py` which exists at the root of your project directory. For an example, see the [setup.py](https://github.com/pypa/sampleproject/blob/db5806e0a3204034c51b1c00dde7d5eb3fa2532e/setup.py) in the [PyPA sample project](https://github.com/pypa/sampleproject).
`setup.py` serves two primary functions:
1. It’s the file where various aspects of your project are configured. The primary feature of `setup.py`is that it contains a global `setup()` function. The keyword arguments to this function are how specific details of your project are defined. The most relevant arguments are explained in [the section below](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/#setup-args).
2. It’s the command line interface for running various commands that relate to packaging tasks. To get a listing of available commands, run `python setup.py --help-commands`.
Add __init__.py and files. You can then install the program in development mode with
pip install -e ./
If everything has worked you can open a python REPL and import your package.
### Project Workflow
Use a Make file for creating project workflows
https://makefiletutorial.com
## Type Checking
Python is a strongly typed, dynamic programming language. This means that types don't need to be specified because they will be inferred by the compiler. This makes the language able to be written quickly, but it does mean that code can be more difficult to reason about. To help in this area type hinting was added, meaning that you can write out the expected type signatures. However by default they won't be checked.
To make code easier to follow it is recommended to use [Type Hinting](https://fastapi.tiangolo.com/python-types/)
To help catch issues with the code it is recommended to use a [Type Checker](https://www.infoworld.com/article/3575079/4-python-type-checkers-to-keep-your-code-clean.html) such as [Mypy](https://mypy-lang.org)
To use Mypy add the following to your make file
check:
mypy jgrab_processing
Then periodically call
make check
## Importing 3rd Party Packages
In your projects virtual environment install the packages that you need using pip.
pip install matplotlib
You can check which packages are installed by typing
pip freeze
To update your requirements file
pip freeze > requirements.txt
Then you can import them all with
pip install -r requirements.txt
### Further Reading
- https://docs.python-guide.org/writing/structure/
- https://changhsinlee.com/python-package/
- https://antonz.org/makefile-automation/
- https://packaging.python.org/en/latest/
# Testing
https://www.dataquest.io/blog/unit-tests-python/
Create a file in your project folder called test.py
You then need to import the unittest framework (a part of Python) and your own code
```python
import unittest
from myCode import myModule
```
You can then create a class to hold your tests
```python
class TestCalculations(unittest.TestCase):
```
Then write a method for each test. Use the assert range of functions from unittest to check calculations made by your code
```python
def test_sum(self):
calculation = Calculations(8, 2)
self.assertEqual(calculation.get_sum(), 10, 'The sum is wrong.')
```
At the bottom of the file add some code so that the unittest.main function will run your tests
```python
if __name__ == '__main__':
unittest.main()
```
You can then run all of your tests by running the test file
```shell
python test.py
```
# Tips, tricks and other oddities
## Why do we use the "-m" switch on the command line sometimes
The -m switch tells python that you are providing a module name rather than a file name. This is especially useful for stdlib modules because we often know the module name but not the filename
$ python -m venv .venv
In the example above the module name is venv, which is part of the python standard library (.venv is the path to a new directory that is required by the venv module).
A good explanation from [stack overflow](https://stackoverflow.com/questions/7610001/what-is-the-purpose-of-the-m-switch). The detailed descriptions are included in [PEP338](https://peps.python.org/pep-0338/) and [PEP366](https://peps.python.org/pep-0366/).
[Boring Python (Dependency Management)](https://www.b-list.org/weblog/2022/may/13/boring-python-dependencies/)
https://alpopkes.com/posts/python/packaging_tools/