diff --git a/continuous_integration.md b/continuous_integration.md deleted file mode 100644 index 18feab9..0000000 --- a/continuous_integration.md +++ /dev/null @@ -1,90 +0,0 @@ - -# Continuous Integration - -In this exercise you will create a simple **continuous integration** workflow. - -## What does CI do? - -When anyone pushes to the GitHub repository, GitHub should: - -1. create an empty virtual computer -2. clone the repository -3. install all dependencies -4. run automated tests -5. report whether the tests succeed or fail - -## Step 1: Preparations - -You need: - -* a GitHub repo for your project -* a `requirements.txt` file -* at least one automated test - -## Step 2: Create a workflow - -GitHub Actions needs instructions how to install the program. - -Create a folder `.github/workflows/`. -Place a text file `check.yml` into that folder containing the following: - - name: run_tests - - on: - push: - branches: [ main ] - - jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.9 - uses: actions/setup-python@v2 - with: - python-version: 3.9 - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt - - name: Test with pytest - run: | - pytest - -Adjust the Python version to match yours. - -## Step 3: Requirements - -A best practice is to have a separate file for **development requirements**. - -* Create a separate file `dev_requirements.txt` -* Add pytest to it -* Add a **pip install** line to the yml file. - -## Step 4: Push - -Commit and push the changes. - -## Step 5: Observe - -* Go to GitHub. Check the **Actions** tab. -* Watch the output of your project building. -* Also check your mailbox. - -## Step 6: Badge - -Copy the following code into your `README.md` file: - - ![Python application](https://github.com/USER/REPO/workflows/run_tests/badge.svg) - -Replace **USER** and **REPO** by the data of your project. -**run_tests** is the name from the workflow file. - -You should see a red or green badge in the README that updates itself. - - -### Authors - -**Malte Bonart participated in the writing of this chapter.** diff --git a/images/modomics.jpg b/images/modomics.jpg deleted file mode 100644 index e67d783..0000000 Binary files a/images/modomics.jpg and /dev/null differ diff --git a/images/modomics.png b/images/modomics.png deleted file mode 100644 index e19c99a..0000000 Binary files a/images/modomics.png and /dev/null differ diff --git a/index.rst b/index.rst index 8e61340..48fead4 100644 --- a/index.rst +++ b/index.rst @@ -35,18 +35,6 @@ Planning and Design -------------- -Packaging and Maintenance -------------------------- - -.. toctree:: - :maxdepth: 1 - - pip.md - pip_setup.md - continuous_integration.md - --------------- - Coding Strategies ----------------- diff --git a/pip.md b/pip.md deleted file mode 100644 index 15ddae6..0000000 --- a/pip.md +++ /dev/null @@ -1,84 +0,0 @@ - -# Installing Packages with pip - -`pip` is a tool to install Python packages and resolve dependencies automatically. This section lists a couple of things you can do with `pip`: - -### Install a package - -To install a Python package, call `pip` with the package name: - - pip install pandas - -You can specify the exact version of a package: - - pip install pandas==0.25.0 - ----- - -### Install many packages - -First, create a file `requirements.txt` in your project directory. The file should look similar to this: - - pandas==0.25 - numpy>=1.17 - scikit-learn - requests - -Second, ask `pip` to install everything: - - pip -r requirements.txt - ----- - -### Install from a git repo - -If a repository has a `setup.py` file, you could install directly from git. This is useful to install branches, forks and other work in progress: - - pip install git+https://github.com/pandas-dev/pandas.git - ----- - -### Install a package you are developing - -When developing, you might want to pip-install a working copy. This allows you to import your package (e.g. for testing). Changes to the code directly take effect in the installation. - -For the following to work, your project folder needs to have a `setup.py`: - - pip install --editable . - ----- - -### List all installed packages - -This one prints all packages you have installed and their versions: - - pip freeze - -To search for a pacakge, use `grep`: - - pip freeze | grep pandas - ----- -### Uninstall a package - -`pip` also removes packages: - - pip uninstall pandas - ----- - -### Where does pip store its files? - -Usually, packages are stored in the `site_packages/` folder. Where this one is depends on your distribution and your virtual environment. - -You might want to check your `PYTHONPATH` environment variable. To do so from Python, use: - - import sys - print(sys.path) - ----- - -### Also see - -* The `conda` program (part of the Anaconda distribution) is often a viable alternative to pip -* You find all installable packages on the [Python Package Index pypi.org](http://pypi.org) diff --git a/pip_setup.md b/pip_setup.md deleted file mode 100644 index 0755cd7..0000000 --- a/pip_setup.md +++ /dev/null @@ -1,144 +0,0 @@ - -# Create a pip-installable Package - -Once a python package (a folder with `.py` files), you may want to make it available to other programs – and people. -Making your code pip-installable can be done by adding an extra configuration files called `setup.py`. - -Assume your project folder contains: - - snake_game/ - module folder you want to import - tests/ - the test code for pytest - .git/ - the commit history (managed by git) - README.md - documentation - LICENSE - legal info - setup.py - used by pip (see below) - .gitignore - choose one on Github - - -## The Project Folder - -Your project folder should contain a sub-directory with a name in **lowercase_with_underscores**. -This sub-directory is your python package! -Add your own Python files inside this package folder. -The `setup.py` script will look for the source code there. - - -## The setup.py file - -**setuptools** is a Python library that builds and installs Python packages. -You may need to install it first: - - pip install setuptools - -In order to use setuptools, you need a file called `setup.py` that tells the installer what to install. -You can use the following `setup.py` file as a starting point: - - from setuptools import setup - import os - - def get_readme(): - """returns the contents of the README file""" - return open(os.path.join(os.path.dirname(__file__), "README.md")).read() - - setup( - name="snake_game", # snake is already taken on PyPi - version="0.0.1", # uses *semantic versioning* - description="a terminal-based snake game", - long_description=get_readme(), - author="your_name", - author_email="your@name.com", - packages=["snake_game"], # the name of the folder with .py modules - url="https://github.com/...", - license="MIT", - classifiers=[ - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - ] - ) - -Copy this code to a `setup.py` file in the top-level folder of your project and save it. - -Here is a [video explaining how setup.py works](https://www.youtube.com/watch?v=S-Le3PWHqZA). - ----- - -## Install your program - -When developing a program, the first thing you want to do is to install your program in development mode. -Go to the folder where the ``setup.py`` file is located and run the command: - - python setup.py develop - - OR - - pip install --editable . - -This makes your project available to the rest of your Python environment -(Python creates a link to your project somewhere in the PYTHONPATH). -Now you should be able to run from any other Python program: - - import snake_game - -In other words, you don't actually need to be in your project folder to use your program. -This is super convenient! You can use your package from anywhere as if it were an official library, like **pandas** or **sklearn**. -You should also see your package in the output of ``pip list`` or ``pip freeze``. - -This method has the advantage that you can still edit your code, and the next time you import the library again. - -**WARNING:** for the re-import to work, you need to restart the Python interpreter. -Just executing the import twice does not work. - ----- - -## Installation on other machines - -If you want to use your library but not edit it (e.g. in a production environment), you may want to copy it to where Python stores all the other packages. -This can be done with another one-liner. - - python setup.py install - - OR - - pip install . - -The files are copied to a folder called `site-packages/` . -The location of it depends on your operating system and Python distribution. - ----- - -## Installation from GitHub - -If you have a `setup.py`, you can pip-install your package directly from GitHub: - - pip install - ----- - -## Creating a distribution - -If you want to package all files of your projects into an archive, you can do this with: - - python setup.py sdist - -This creates a `dist/` folder with a `.tar.gz` file that you can move around easily. - ----- - -## Further Reading - -If you would like to upload your program to PyPi, so that anyone can install it with - - pip install snake_game - -you need to follow a few more steps. -This is not difficult but a bit tedious. -We recommend the official `Packaging Python Projects Tutorial `__. - ----- - -## Authors - -This guide was written together with Paul Wlodkowski and Malte Bonart. diff --git a/prototype.rst b/prototype.rst deleted file mode 100644 index 7640b9d..0000000 --- a/prototype.rst +++ /dev/null @@ -1,74 +0,0 @@ -The Prototype -============= - -Before attempting a more costly clean implementation, you may want to -check whether the project is feasible at all. You can do such a check by -implementing a quick and dirty proof of concept: a **prototype**. The -goal of a prototype is usually to reduce risks in a project. - -A prototype can answer questions like: - -- is my programming environment set up properly? -- can we solve a particular algorithmic problem? -- does a library do what we need? -- is the algorithm/library fast enough? -- what safety/security risks are there? -- did we understand the customer correctly? - -A Prototype for a Snake game ----------------------------- - -Let's look at a prototype for a Snake game. -The program is a simple game where you move a symbol around with the ``WASD`` keys. -The goal of this prototype is to prove that you can process keyboard input -and draw 2D graphics in a terminal. - -The prototype helps us to get rid of installation and environment issues right away. - -Exercise 1: Save the code -~~~~~~~~~~~~~~~~~~~~~~~~~ - -Save the code in :download:`snake_prototype.py ` to a Python file. - -Exercise 2: Windows installation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -On Windows, you need to install ``windows-curses``: - -:: - - pip install windows-curses - -Exercise 3: Execute the prototype -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Change to the directory with the ``.py`` file and execute the code with: - -:: - - python prototype.py - -You should see a screen where you can control the ``'O'`` with the keys **W, A, S and D**: - -.. figure:: images/prototype.png - :alt: prototype output - - prototype output - -Exercise 4: Code Review -~~~~~~~~~~~~~~~~~~~~~~~ - -Inspect the Python file. Take notes to answer the following questions: - -* What do you like about the code? -* What do you not like about the code? -* What would you like to know more about? - -Reflection Questions --------------------- - -Discuss the following questions: - -- Can you think of a software project with special risks? -- Could these risks be mitigated by writing a prototype? -- Do you know other engineering disciplines where prototypes are used? diff --git a/snake_prototype.py b/snake_prototype.py deleted file mode 100644 index 227ba0f..0000000 --- a/snake_prototype.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -Proof-of-concept: move around in a 2D frame -""" -import curses - -# WASD keys -KEY_COMMANDS = {97: "left", 100: "right", 119: "up", 115: "down"} - -# prepare the screen -screen = curses.initscr() -curses.start_color() -curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) -curses.curs_set(0) -curses.noecho() -curses.raw() -screen.keypad(False) - -win = curses.newwin(20, 20, 0, 0) -win.nodelay(True) - - -def game_loop(screen): - """called by curses""" - x, y = 5, 5 - - # draw - screen.clear() - screen.addch(y, x, "O", curses.color_pair(1)) - win.refresh() - screen.refresh() - - while True: - - # handle moves - char = win.getch() - direction = KEY_COMMANDS.get(char) - if direction == "left": - x -= 1 - elif direction == "right": - x += 1 - elif direction == "up": - y -= 1 - elif direction == "down": - y += 1 - else: - continue - - # draw - screen.clear() - screen.addch(y, x, "O", curses.color_pair(1)) - win.refresh() - screen.refresh() - - -if __name__ == "__main__": - curses.wrapper(game_loop) - curses.endwin()