<jupyter_start><jupyter_text>Package Building DemoAuthor: [<NAME>](http://benjaminroulston.com)Last Updated: 12 May 2020  Introduction to Packages Notice: Please run the code in the cell below before we begin. This code allows python to reload packages as they are run. This is useful when working on making a package because python by default only loads a package once. So if you made changes, you'd need to exit python. This magic function allows the packages to be reloaded each time they are run.<jupyter_code>%load_ext autoreload
%autoreload 2<jupyter_output><empty_output><jupyter_text>In this demo we will work on building an example package in Python. Packages are a vital part of making your code reusable by yourself and others. They help in organizing scripts, functions, and classes that you've made into one coherent grouping. Over the course of these workshops you've been using packages the entire time. A few that you have been using would be the `numpy` and `astropy` packages. There are many many packages available for Python, and generally a internet search will find what you need. In Python, a package is a collection of files (called modules) that make up a grouping of similar features, such as functions or classes. Using the `numpy` example, this package is a grouping of modules that contain functions, classes, and other tools to work with arrays in a fast and efficient way. `astropy` is a grouping of modules that are for use in scientific astronomy.  Python packages can contain sub-packages, which can contain further sub-packages. Think of these as folders (or directories) on a computers file system. The package is the top folder, and each sub-package would be a folder down a level. This sub-package would contain one kind of specific type of functions and modules that connects back to the theme of the main package. For example, `astropy` has a sub-package called `io` that as a module named `fits`. This can be imported as the following:``` pythonfrom astropy.io import fits``` Python uses this `dot` notation to link packages with sub-packages with modules. `Dot` notation means that you use a dot in the import to import things in lower sub-packages and then from modules. Think of this like moving down in the folder levels. Python has a few different kinds of import abilities. Direct import:``` pythonimport numpy```Direct import with an alias:``` pythonimport numpy as np```Direct import of a sub-package (with optional alias)``` pythonimport numpy.randomimport numpy.random as random```These are called as `x = numpy.random.rand()` and `x = random.rand()` respectively.   Creating our Own Packages We can create our own packages in Python quite easily. In this workshop we will build a package together. Because of time limitations, we will build a simple package to just demonstrate the concept of package building. Our demo package will be based on a farm, and we will call our package `farm`. This package will have sub-packages to deal with the farm animals, and the farm buildings. These sub-packages will allow us to create farm animals such as cows, horses, farm pets like cats and dogs as well as farm buildings like a barn.  Before we used folders as a way to think about packages and sub-packages. In truth this is actually exactly how packages are made!A package is simply a folder with all the Python files needed inside of it. But in order for Python to know a folder is a package, we need to tell it by using a special file.__init__.py: This special Python file tells Python that the folder it resides in is a Python package.The `__init__.py` file is placed inside of a folder to make it a package. This file can be blank, but usually has code that tells Python what to do when the package is imported. The general layout of a package (in this case the one we want to build) looks something along these lines:```package/    __init__.py    some_code.py    sub-package1/        __init__.py        more_code.py    sub-package2/        __init__.py        more_more_code.py```so for us and our `farm` package might look something like this:```farm/    __init__.py    main.py    animals/        __init__.py        barnanimals.py        pets.py    buildings/        __init__.py        barn.py        house.py```  making the main `__init__.py` fileIn your JupyterLab session, go to the File Browser. Use the File Browser to create a new folder and name it `farm`. Double click this folder to enter it. This is where we will make all the package files and folders.In this folder, create a new file named `__init__.py` and open it to edit.We can then add these lines, replacing values with your own:```python__author__ = """<NAME>"""__email__ = '<EMAIL>'__version__ = '0.1.0'```You can add other information that you think is valuable or needed for your package. This `__init__.py` file tells Python that the `farm` folder is a package and we can now import it and check what attributes it has!<jupyter_code>import farm

# package_attributes = dir(farm)
# print(package_attributes)

# print(farm.__author__)
# print(farm.__email__)
# print(farm.__version__)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.05547985205372786, 'fraction_numerical': 0.0023359937706832782, 'mean_word_length': 4.242857142857143, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '562588', 'license': 'MIT', 'n_tokens_mistral': 1282, 'n_tokens_neox': 1235, 'n_words': 773, 'path': 'demo_guide.ipynb', 'repo_name': 'broulston/PackageBuilding_demo', 'size': '5185'}