<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://info.stat.cmu.edu/index.php?action=history&amp;feed=atom&amp;title=Developing_python_packages</id>
	<title>Developing python packages - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://info.stat.cmu.edu/index.php?action=history&amp;feed=atom&amp;title=Developing_python_packages"/>
	<link rel="alternate" type="text/html" href="https://info.stat.cmu.edu/index.php?title=Developing_python_packages&amp;action=history"/>
	<updated>2026-11-05T04:52:38Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://info.stat.cmu.edu/index.php?title=Developing_python_packages&amp;diff=809&amp;oldid=prev</id>
		<title>Ajshen at 03:13, 29 June 2026</title>
		<link rel="alternate" type="text/html" href="https://info.stat.cmu.edu/index.php?title=Developing_python_packages&amp;diff=809&amp;oldid=prev"/>
		<updated>2026-06-29T03:13:56Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 03:13, 29 June 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Package Development and Distribution]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This wiki presents a motivational example of a lot of properties of python packages and how to use them. Please see [[packages motivation]] for motivation about why you should utilize the package framework while doing research. This material captures the basics presented by [https://py-pkgs.org/ py-pkgs], (recently) developed by UBC professors. As such you’ll find that python packages online may have different structures. Still, &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt; provides a lot of helpful tools to automate python package development. The &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt; project was actually started to mirror the helpful [[Developing_R_packages|package development tools in &amp;lt;code&amp;gt;R&amp;lt;/code&amp;gt;]]. Note that this wiki page does provide additional commentary but the process proposed is very similar to &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt;’s approach.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;This wiki presents a motivational example of a lot of properties of python packages and how to use them. Please see [[packages motivation]] for motivation about why you should utilize the package framework while doing research. This material captures the basics presented by [https://py-pkgs.org/ py-pkgs], (recently) developed by UBC professors. As such you’ll find that python packages online may have different structures. Still, &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt; provides a lot of helpful tools to automate python package development. The &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt; project was actually started to mirror the helpful [[Developing_R_packages|package development tools in &amp;lt;code&amp;gt;R&amp;lt;/code&amp;gt;]]. Note that this wiki page does provide additional commentary but the process proposed is very similar to &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt;’s approach.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key infowiki:diff:1.41:old-70:rev-809:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Ajshen</name></author>
	</entry>
	<entry>
		<id>https://info.stat.cmu.edu/index.php?title=Developing_python_packages&amp;diff=70&amp;oldid=prev</id>
		<title>Skipper at 02:00, 24 May 2024</title>
		<link rel="alternate" type="text/html" href="https://info.stat.cmu.edu/index.php?title=Developing_python_packages&amp;diff=70&amp;oldid=prev"/>
		<updated>2024-05-24T02:00:16Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 02:00, 24 May 2024&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l52&quot;&gt;Line 52:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 52:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# A set of &amp;lt;code&amp;gt;.md&amp;lt;/code&amp;gt; files for document things like general info for viewers (&amp;lt;code&amp;gt;README.md&amp;lt;/code&amp;gt;), info for contributors and their conduct (&amp;lt;code&amp;gt;CONTRIBUTING.md&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CONDUCT.md&amp;lt;/code&amp;gt;) and a file to include information on changes you’ve made &amp;lt;code&amp;gt;CHANGELOG.md&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# A set of &amp;lt;code&amp;gt;.md&amp;lt;/code&amp;gt; files for document things like general info for viewers (&amp;lt;code&amp;gt;README.md&amp;lt;/code&amp;gt;), info for contributors and their conduct (&amp;lt;code&amp;gt;CONTRIBUTING.md&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CONDUCT.md&amp;lt;/code&amp;gt;) and a file to include information on changes you’ve made &amp;lt;code&amp;gt;CHANGELOG.md&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:1200px-Tartanpy folder.png|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;600px&lt;/del&gt;|frame|left|initial directory items]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:1200px-Tartanpy folder.png|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;300px&lt;/ins&gt;|frame|left|initial directory items]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== pyproject.toml file meta-data ====&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== pyproject.toml file meta-data ====&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l58&quot;&gt;Line 58:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 58:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;There are few ways for packages to store their meta-data, and &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt;’s path is through the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt;. Other options include things like &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt; files. If you made a mistake when answering questions via your cookiecutter prompts you can change them by opening up the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file. Our example package’s &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file looks like the image below&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;There are few ways for packages to store their meta-data, and &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt;’s path is through the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt;. Other options include things like &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt; files. If you made a mistake when answering questions via your cookiecutter prompts you can change them by opening up the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file. Our example package’s &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file looks like the image below&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:1200px-Tartanpy pyproject description.png|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;600px&lt;/del&gt;|frame|left|initialized description file]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:1200px-Tartanpy pyproject description.png|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;300px&lt;/ins&gt;|frame|left|initialized description file]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;In a &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file you’ll notice that each section is headed by a &amp;lt;code&amp;gt;[info]&amp;lt;/code&amp;gt; heading. Notice that three of the sections in the image above have &amp;lt;code&amp;gt;tool.poetry&amp;lt;/code&amp;gt; headers. This means that the package &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; can update these sections. As we showcase the power of this package you may find that using poetry to update a lot of these fields is more desirable than manually doing it yourself.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;In a &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file you’ll notice that each section is headed by a &amp;lt;code&amp;gt;[info]&amp;lt;/code&amp;gt; heading. Notice that three of the sections in the image above have &amp;lt;code&amp;gt;tool.poetry&amp;lt;/code&amp;gt; headers. This means that the package &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; can update these sections. As we showcase the power of this package you may find that using poetry to update a lot of these fields is more desirable than manually doing it yourself.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l443&quot;&gt;Line 443:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 443:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;If we remove the silly floating point error assession we get the following:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;If we remove the silly floating point error assession we get the following:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:1200px-Pytest example.png|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;600px&lt;/del&gt;|frame|left|output of pytest]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:1200px-Pytest example.png|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;300px&lt;/ins&gt;|frame|left|output of pytest]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;And if there are errors &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; tries to be very clear about where in your tests you had an error.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;And if there are errors &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; tries to be very clear about where in your tests you had an error.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key infowiki:diff:1.41:old-69:rev-70:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Skipper</name></author>
	</entry>
	<entry>
		<id>https://info.stat.cmu.edu/index.php?title=Developing_python_packages&amp;diff=69&amp;oldid=prev</id>
		<title>Skipper at 01:59, 24 May 2024</title>
		<link rel="alternate" type="text/html" href="https://info.stat.cmu.edu/index.php?title=Developing_python_packages&amp;diff=69&amp;oldid=prev"/>
		<updated>2024-05-24T01:59:05Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 01:59, 24 May 2024&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l52&quot;&gt;Line 52:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 52:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# A set of &amp;lt;code&amp;gt;.md&amp;lt;/code&amp;gt; files for document things like general info for viewers (&amp;lt;code&amp;gt;README.md&amp;lt;/code&amp;gt;), info for contributors and their conduct (&amp;lt;code&amp;gt;CONTRIBUTING.md&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CONDUCT.md&amp;lt;/code&amp;gt;) and a file to include information on changes you’ve made &amp;lt;code&amp;gt;CHANGELOG.md&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;# A set of &amp;lt;code&amp;gt;.md&amp;lt;/code&amp;gt; files for document things like general info for viewers (&amp;lt;code&amp;gt;README.md&amp;lt;/code&amp;gt;), info for contributors and their conduct (&amp;lt;code&amp;gt;CONTRIBUTING.md&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CONDUCT.md&amp;lt;/code&amp;gt;) and a file to include information on changes you’ve made &amp;lt;code&amp;gt;CHANGELOG.md&amp;lt;/code&amp;gt;).&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Tartanpy_folder&lt;/del&gt;.png|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;frameless&lt;/del&gt;|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;600px&lt;/del&gt;|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;alt=initial directory items&lt;/del&gt;|initial directory items]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;1200px-Tartanpy folder&lt;/ins&gt;.png|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;600px&lt;/ins&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;frame&lt;/ins&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;left&lt;/ins&gt;|initial directory items]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== pyproject.toml file meta-data ====&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;==== pyproject.toml file meta-data ====&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l58&quot;&gt;Line 58:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 58:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;There are few ways for packages to store their meta-data, and &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt;’s path is through the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt;. Other options include things like &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt; files. If you made a mistake when answering questions via your cookiecutter prompts you can change them by opening up the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file. Our example package’s &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file looks like the image below&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;There are few ways for packages to store their meta-data, and &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt;’s path is through the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt;. Other options include things like &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt; files. If you made a mistake when answering questions via your cookiecutter prompts you can change them by opening up the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file. Our example package’s &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file looks like the image below&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Tartanpy_pyproject_description&lt;/del&gt;.png|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;frameless&lt;/del&gt;|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;600px&lt;/del&gt;|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;alt=initialized description file&lt;/del&gt;|initialized description file]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;1200px-Tartanpy pyproject description&lt;/ins&gt;.png|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;600px&lt;/ins&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;frame&lt;/ins&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;left&lt;/ins&gt;|initialized description file]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;In a &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file you’ll notice that each section is headed by a &amp;lt;code&amp;gt;[info]&amp;lt;/code&amp;gt; heading. Notice that three of the sections in the image above have &amp;lt;code&amp;gt;tool.poetry&amp;lt;/code&amp;gt; headers. This means that the package &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; can update these sections. As we showcase the power of this package you may find that using poetry to update a lot of these fields is more desirable than manually doing it yourself.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;In a &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file you’ll notice that each section is headed by a &amp;lt;code&amp;gt;[info]&amp;lt;/code&amp;gt; heading. Notice that three of the sections in the image above have &amp;lt;code&amp;gt;tool.poetry&amp;lt;/code&amp;gt; headers. This means that the package &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; can update these sections. As we showcase the power of this package you may find that using poetry to update a lot of these fields is more desirable than manually doing it yourself.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l443&quot;&gt;Line 443:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 443:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;If we remove the silly floating point error assession we get the following:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;If we remove the silly floating point error assession we get the following:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;Pytest_example&lt;/del&gt;.png|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;frameless&lt;/del&gt;|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;600px&lt;/del&gt;|&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;alt=output of pytest&lt;/del&gt;|output of pytest]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[File:&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;1200px-Pytest example&lt;/ins&gt;.png|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;600px&lt;/ins&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;frame&lt;/ins&gt;|&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;left&lt;/ins&gt;|output of pytest]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;And if there are errors &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; tries to be very clear about where in your tests you had an error.&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;And if there are errors &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; tries to be very clear about where in your tests you had an error.&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key infowiki:diff:1.41:old-19:rev-69:php=table --&gt;
&lt;/table&gt;</summary>
		<author><name>Skipper</name></author>
	</entry>
	<entry>
		<id>https://info.stat.cmu.edu/index.php?title=Developing_python_packages&amp;diff=19&amp;oldid=prev</id>
		<title>Skipper: Created page with &quot; This wiki presents a motivational example of a lot of properties of python packages and how to use them. Please see packages motivation for motivation about why you shoul...&quot;</title>
		<link rel="alternate" type="text/html" href="https://info.stat.cmu.edu/index.php?title=Developing_python_packages&amp;diff=19&amp;oldid=prev"/>
		<updated>2024-03-29T23:48:50Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot; This wiki presents a motivational example of a lot of properties of python packages and how to use them. Please see &lt;a href=&quot;/index.php?title=Packages_motivation&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Packages motivation (page does not exist)&quot;&gt;packages motivation&lt;/a&gt; for motivation about why you shoul...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;
This wiki presents a motivational example of a lot of properties of python packages and how to use them. Please see [[packages motivation]] for motivation about why you should utilize the package framework while doing research. This material captures the basics presented by [https://py-pkgs.org/ py-pkgs], (recently) developed by UBC professors. As such you’ll find that python packages online may have different structures. Still, &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt; provides a lot of helpful tools to automate python package development. The &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt; project was actually started to mirror the helpful [[Developing_R_packages|package development tools in &amp;lt;code&amp;gt;R&amp;lt;/code&amp;gt;]]. Note that this wiki page does provide additional commentary but the process proposed is very similar to &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt;’s approach.&lt;br /&gt;
&lt;br /&gt;
== Foundations (what tools will be used) ==&lt;br /&gt;
&lt;br /&gt;
In the package development pipeline that is proposed by &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt; we have a few very power packages to help you develop an &amp;lt;code&amp;gt;python&amp;lt;/code&amp;gt; package as painlessly as possible.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; help build a python package&lt;br /&gt;
* &amp;lt;code&amp;gt;cookiecutter&amp;lt;/code&amp;gt; helps utilize pre-made templates (for our package’s files)&lt;br /&gt;
* &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; provides clean and standardized tools for testing&lt;br /&gt;
* (numpy style code) provides rubrics for documentation&lt;br /&gt;
&lt;br /&gt;
== Building an python package ==&lt;br /&gt;
&lt;br /&gt;
This process is slightly different than the one we demonstrated in the [[Developing_R_packages]] wiki (we set up the structure of the package and then link to github).&lt;br /&gt;
&lt;br /&gt;
=== Step 1: Creating a minimal source package ===&lt;br /&gt;
&lt;br /&gt;
A python (&amp;#039;&amp;#039;source&amp;#039;&amp;#039;) package just files in a directory, formatted in a specific way.&lt;br /&gt;
&lt;br /&gt;
To create the bare bones python package, we will be using the packages &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;cookiecutter&amp;lt;/code&amp;gt;, so if you haven’t already done so, install those two packages (we’ll be using &amp;lt;code&amp;gt;conda&amp;lt;/code&amp;gt;) by typing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;conda install -c conda-forge poetry cookiecutter&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Note that this line is taken directly from [https://py-pkgs.org/02-setup py-pkgs/02-setup], and it is possible that some day these packages can be installed wit ha simple &amp;lt;code&amp;gt;conda install poetry cookiecutter&amp;lt;/code&amp;gt;.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Now&amp;#039;&amp;#039;&amp;#039;, to actually start setting up your python package we will first use &amp;lt;code&amp;gt;cookiecutter&amp;lt;/code&amp;gt; to copy a package structure provided by &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt; by running the following in our terminal:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cookiecutter https://github.com/UBC-MDS/cookiecutter-ubc-mds.git&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
This will prompt you to answer a set of questions including &lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; the author name (can include caps and spaces) &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; github username &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; package name (can include caps and spaces) &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; package slug name (can included underscores but no spaces) &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; a short package description (can include caps and spaces) &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; version number (we recommend either 0.0.1 or 0.1.0) &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; python version 8. open source license (they list the options) &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; if the package should include github actions (we suggest no for now, and plan to have wikis help with this later) &amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Note: our package for this example will be named &amp;lt;code&amp;gt;tartanpy&amp;lt;/code&amp;gt;&amp;#039;&amp;#039; (an a copy of the &amp;quot;final&amp;quot; product can be found on [https://github.com/benjaminleroy/tartanpy|github].&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;Note: the cookiecutter template from &amp;lt;code&amp;gt;py-pkg&amp;lt;/code&amp;gt;s (aka the one above) is still under construction - so it might look slightly different in the future.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
This will create a &amp;lt;code&amp;gt;tartanpy&amp;lt;/code&amp;gt; folder with the following items:&lt;br /&gt;
&lt;br /&gt;
# Directory &amp;lt;code&amp;gt;src/&amp;lt;/code&amp;gt; (where all the function source code goes)&lt;br /&gt;
# Directory &amp;lt;code&amp;gt;docs/&amp;lt;/code&amp;gt; (where all the pretty looking documentation goes &amp;#039;&amp;#039;&amp;#039;- auto generated&amp;#039;&amp;#039;&amp;#039;)&lt;br /&gt;
# Directory &amp;lt;code&amp;gt;tests/&amp;lt;/code&amp;gt; (where you’ll store your test, with a placeholder test file)&lt;br /&gt;
# &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file (a description file about your package, which includes the things you entered when you ran the &amp;lt;code&amp;gt;cookiecutter&amp;lt;/code&amp;gt; call)&lt;br /&gt;
# &amp;lt;code&amp;gt;LICENSE&amp;lt;/code&amp;gt; (booler plate License - don’t really need to deal with this)&lt;br /&gt;
# A set of &amp;lt;code&amp;gt;.md&amp;lt;/code&amp;gt; files for document things like general info for viewers (&amp;lt;code&amp;gt;README.md&amp;lt;/code&amp;gt;), info for contributors and their conduct (&amp;lt;code&amp;gt;CONTRIBUTING.md&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;CONDUCT.md&amp;lt;/code&amp;gt;) and a file to include information on changes you’ve made &amp;lt;code&amp;gt;CHANGELOG.md&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
[[File:Tartanpy_folder.png|frameless|600px|alt=initial directory items|initial directory items]]&lt;br /&gt;
&lt;br /&gt;
==== pyproject.toml file meta-data ====&lt;br /&gt;
&lt;br /&gt;
There are few ways for packages to store their meta-data, and &amp;lt;code&amp;gt;py-pkgs&amp;lt;/code&amp;gt;’s path is through the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt;. Other options include things like &amp;lt;code&amp;gt;setup.py&amp;lt;/code&amp;gt; files. If you made a mistake when answering questions via your cookiecutter prompts you can change them by opening up the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file. Our example package’s &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file looks like the image below&lt;br /&gt;
&lt;br /&gt;
[[File:Tartanpy_pyproject_description.png|frameless|600px|alt=initialized description file|initialized description file]]&lt;br /&gt;
&lt;br /&gt;
In a &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; file you’ll notice that each section is headed by a &amp;lt;code&amp;gt;[info]&amp;lt;/code&amp;gt; heading. Notice that three of the sections in the image above have &amp;lt;code&amp;gt;tool.poetry&amp;lt;/code&amp;gt; headers. This means that the package &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; can update these sections. As we showcase the power of this package you may find that using poetry to update a lot of these fields is more desirable than manually doing it yourself.&lt;br /&gt;
&lt;br /&gt;
=== Step 2: Setting up a Github repo ===&lt;br /&gt;
&lt;br /&gt;
Version control (and discussed in Stat Computing) is a very useful tool to help streamline file management and provide piece of mind. Oftentimes, you will want to have a copy of the repository not just on your personal computer but online (to help with sharing, just in case your computer dies, it’s cool, etc.). As such these steps will walk you through how to set up a github repo for your new package and how to connect that repo to a new python package. This step will mirror thoughts in [https://py-pkgs.org/03-how-to-package-a-python#set-up-remote-version-control py-pkgs/03-how-to-package-a-python].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol style=&amp;quot;list-style-type: decimal;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;In &amp;lt;code&amp;gt;Github&amp;lt;/code&amp;gt;&amp;#039;&amp;#039;&amp;#039;, do the following&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;go to the top-level directory (i.e., &amp;lt;code&amp;gt;github.com/&amp;lt;your user name&amp;gt;&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;click on “+” at top right, and select “New repository”&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;name the repository (e.g., “tartan_python”). Note that if you’d like to share your package with others via pypi you’ll need to make your package name unique!&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;provide a short description of the repository (don’t leave completely blank!)&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;keep the repository public (as students you have access to free private repos https://education.github.com/pack, but for purposes of this example we will keep the repo public)&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;do not&amp;#039;&amp;#039;&amp;#039; initalize with a README, .gitignore, or license (It even says “Skip this step if you’re importing an exisiting repo”!!!)&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;click on “Create Repository”&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;…then in your terminal, do the following&amp;#039;&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;First, initialize your repository with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;git init&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;then add all &amp;lt;code&amp;gt;cookiecutter&amp;lt;/code&amp;gt; files and create your initial commit with &amp;lt;code&amp;gt;bash  git add .  git commit -m &amp;quot;initial package setup&amp;quot;&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;setup connection to github by adding a a remote, your main branch and pushing your first commit with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;git remote add origin https://github.com/benjaminleroy/tartanpy.git&lt;br /&gt;
git branch -M main&lt;br /&gt;
git push -u origin main&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;#039;&amp;#039;Note that github provides you with walk throughs that mirror what was recommended above and showcases 2 approaches if you want to use the command line (&amp;lt;code&amp;gt;https&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt;) as well as how you might do it with github desktop. So helpful - thanks github!&amp;#039;&amp;#039;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 3: Writing a function ===&lt;br /&gt;
&lt;br /&gt;
All of your python code needs to go in &amp;lt;code&amp;gt;.py&amp;lt;/code&amp;gt; files in the &amp;lt;code&amp;gt;src/tartanpy/&amp;lt;/code&amp;gt; directory. Suppose our first set of functions deal with communicating to the user - then we might make a &amp;lt;code&amp;gt;communicate.py&amp;lt;/code&amp;gt; file in &amp;lt;code&amp;gt;src/tartanpy/&amp;lt;/code&amp;gt; folder. &amp;lt;br&amp;gt; Inside this file, let’s image we add the following function&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;def call_scotty_demo(your_name):&lt;br /&gt;
&lt;br /&gt;
    name_length = len(your_name)&lt;br /&gt;
&lt;br /&gt;
    # say Hiiiiii&lt;br /&gt;
    hi_string = &amp;quot;\n&amp;quot; +\&lt;br /&gt;
        &amp;quot;-&amp;quot; * (name_length + 8) + &amp;quot;\n&amp;quot; +\&lt;br /&gt;
        &amp;quot;| Hi &amp;quot; + your_name + &amp;quot;! | \n&amp;quot; +\&lt;br /&gt;
        &amp;quot;|   &amp;quot; + &amp;quot;-&amp;quot; * (name_length + 4) + &amp;quot;\n&amp;quot; +\&lt;br /&gt;
        &amp;quot;| /\n&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    scotty_string = &amp;quot;&amp;quot;+\&lt;br /&gt;
        &amp;quot; |/  |\\_/|          \n&amp;quot; +\&lt;br /&gt;
        &amp;quot; |   |q p|   /}      \n&amp;quot; +\&lt;br /&gt;
        &amp;quot; |   ( 0 )\&amp;quot;\&amp;quot;\&amp;quot;\\   \n&amp;quot; +\&lt;br /&gt;
        &amp;quot;  \\  |\&amp;quot;-\&amp;quot;`    |    \n&amp;quot; +\&lt;br /&gt;
        &amp;quot;     || /=\\\\  |     \n&amp;quot; +\&lt;br /&gt;
        &amp;quot;     \&amp;quot;&amp;#039;\&amp;quot;  &amp;#039;\&amp;quot;\&amp;quot;\&amp;quot;&amp;#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    print(hi_string + scotty_string)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
To get access to this function we can use &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; to locally install our package with the bash command below (that needs to be run in the top folder of our package)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;poetry install&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Note that without poetry this could be done with a &amp;lt;code&amp;gt;pip install -e .&amp;lt;/code&amp;gt; in the same directory and this would actually not require running this line of code every time we update the package. On the other hand - we’ll show the versatility of &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; in the rest of the article.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
To utilize our function we can then open up a interactive python instance (e.g. &amp;lt;code&amp;gt;ipython&amp;lt;/code&amp;gt; in your terminal) and then run&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;In [1]: from tartanpy import communicate&lt;br /&gt;
&lt;br /&gt;
In [2]: communicate.call_scotty_demo(&amp;quot;Andrew Carnegie&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
which will return:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;-----------------------&lt;br /&gt;
| Hi Andrew Carnegie! |&lt;br /&gt;
|   -------------------&lt;br /&gt;
| /&lt;br /&gt;
 |/  |\_/|&lt;br /&gt;
 |   |q p|   /}&lt;br /&gt;
 |   ( 0 )&amp;quot;&amp;quot;&amp;quot;\&lt;br /&gt;
  \  |&amp;quot;-&amp;quot;`    |&lt;br /&gt;
     || /=\\  |&lt;br /&gt;
     &amp;quot;&amp;#039;&amp;quot;  &amp;#039;&amp;quot;&amp;quot;&amp;quot;&amp;#039;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Note that &amp;lt;code&amp;gt;poetry install&amp;lt;/code&amp;gt; can be called over and over if you keep updating your function files and will re-load the newest verion of all your functions.&lt;br /&gt;
&lt;br /&gt;
==== Additional notes: ====&lt;br /&gt;
&lt;br /&gt;
===== Understanding &amp;lt;code&amp;gt;__init__.py&amp;lt;/code&amp;gt; =====&lt;br /&gt;
&lt;br /&gt;
For &amp;lt;code&amp;gt;python&amp;lt;/code&amp;gt; packages you’ll always have an &amp;lt;code&amp;gt;__init__.py&amp;lt;/code&amp;gt; file in this directory. We currently have to import the &amp;lt;code&amp;gt;communicate&amp;lt;/code&amp;gt; file from &amp;lt;code&amp;gt;tartanpy&amp;lt;/code&amp;gt; in order to get access to our amazing function. To make this function come directly with the package, in the &amp;lt;code&amp;gt;__init__.py&amp;lt;/code&amp;gt; file we can write&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;from .communicate import call_scotty_demo&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Note the dot in &amp;lt;code&amp;gt;.communicate&amp;lt;/code&amp;gt; says “in this same directory as this current file”, and we don’t have to include the &amp;lt;code&amp;gt;.py&amp;lt;/code&amp;gt; file link at the end.&amp;#039;&amp;#039; Additionally This approach &amp;#039;&amp;#039;&amp;#039;only&amp;#039;&amp;#039;&amp;#039; imports call_scotty_demo to the global package, we could use &amp;lt;code&amp;gt;... import *&amp;lt;/code&amp;gt; to import all functions (but this approach is smart if we had helper functions we didn’t really need to share with the end user).*&lt;br /&gt;
&lt;br /&gt;
With the above change, we can then do (the &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; part still needs to be at the top directory):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;poetry install&lt;br /&gt;
ipython&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and then in the ipython shell:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;In [1]: import tartanpy&lt;br /&gt;
&lt;br /&gt;
In [2]: tartanpy.call_scotty_demo(&amp;quot;Andrew Mellon&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
which will return:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;---------------------&lt;br /&gt;
| Hi Andrew Mellon! |&lt;br /&gt;
|   -----------------&lt;br /&gt;
| /&lt;br /&gt;
 |/  |\_/|&lt;br /&gt;
 |   |q p|   /}&lt;br /&gt;
 |   ( 0 )&amp;quot;&amp;quot;&amp;quot;\&lt;br /&gt;
  \  |&amp;quot;-&amp;quot;`    |&lt;br /&gt;
     || /=\\  |&lt;br /&gt;
     &amp;quot;&amp;#039;&amp;quot;  &amp;#039;&amp;quot;&amp;quot;&amp;quot;&amp;#039;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
===== Using external packages =====&lt;br /&gt;
&lt;br /&gt;
[You&amp;#039;ll want to read the next section as well for a full understanding of dealing with external packages.]&lt;br /&gt;
&lt;br /&gt;
Suppose I wished to truncate really long names I’m greeting but also give the user a warning that I’m going to do so. I’d need to use the &amp;lt;code&amp;gt;warnings&amp;lt;/code&amp;gt; package. To use this in our package I’d need to change our &amp;lt;code&amp;gt;communicate.py&amp;lt;/code&amp;gt; file to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;import warnings&lt;br /&gt;
&lt;br /&gt;
def call_scotty_demo(your_name):&lt;br /&gt;
    if len(your_name) &amp;gt; 30:&lt;br /&gt;
        warnings.warn(&amp;quot;your name is beyond 30 characters, &amp;quot;+\&lt;br /&gt;
                        &amp;quot;has been truncated&amp;quot;)&lt;br /&gt;
        your_name = your_name[:30]&lt;br /&gt;
&lt;br /&gt;
    name_length = len(your_name)&lt;br /&gt;
&lt;br /&gt;
    # say Hiiiiii&lt;br /&gt;
    hi_string = &amp;quot;\n&amp;quot; +\&lt;br /&gt;
        &amp;quot;-&amp;quot; * (name_length + 8) + &amp;quot;\n&amp;quot; +\&lt;br /&gt;
        &amp;quot;| Hi &amp;quot; + your_name + &amp;quot;! | \n&amp;quot; +\&lt;br /&gt;
        &amp;quot;|   &amp;quot; + &amp;quot;-&amp;quot; * (name_length + 4) + &amp;quot;\n&amp;quot; +\&lt;br /&gt;
        &amp;quot;| /\n&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    scotty_string = &amp;quot;&amp;quot;+\&lt;br /&gt;
        &amp;quot; |/  |\\_/|          \n&amp;quot; +\&lt;br /&gt;
        &amp;quot; |   |q p|   /}      \n&amp;quot; +\&lt;br /&gt;
        &amp;quot; |   ( 0 )\&amp;quot;\&amp;quot;\&amp;quot;\\   \n&amp;quot; +\&lt;br /&gt;
        &amp;quot;  \\  |\&amp;quot;-\&amp;quot;`    |    \n&amp;quot; +\&lt;br /&gt;
        &amp;quot;     || /=\\\\  |     \n&amp;quot; +\&lt;br /&gt;
        &amp;quot;     \&amp;quot;&amp;#039;\&amp;quot;  &amp;#039;\&amp;quot;\&amp;quot;\&amp;quot;&amp;#039;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    print(hi_string + scotty_string)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Notice that we have to impot the &amp;lt;code&amp;gt;warnings&amp;lt;/code&amp;gt; package at the top of our function file.&lt;br /&gt;
&lt;br /&gt;
Now we have the additional funcitonality (after reloading with &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;In [1]: import tartanpy&lt;br /&gt;
&lt;br /&gt;
In [2]: tartanpy.call_scotty_demo(&amp;quot;Oski Bear, your a wonderful, but slightly creepy Berkeley Bear&amp;quot;)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
which returns&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;.../tartanpy/src/tartanpy/communicate.py:6: UserWarning: your name is beyond 30 characters, has been truncated&lt;br /&gt;
  warnings.warn(&amp;quot;your name is beyond 30 characters, &amp;quot;+\&lt;br /&gt;
&lt;br /&gt;
--------------------------------------&lt;br /&gt;
| Hi Oski Bear, your a wonderful, b! |&lt;br /&gt;
|   ----------------------------------&lt;br /&gt;
| /&lt;br /&gt;
 |/  |\_/|&lt;br /&gt;
 |   |q p|   /}&lt;br /&gt;
 |   ( 0 )&amp;quot;&amp;quot;&amp;quot;\&lt;br /&gt;
  \  |&amp;quot;-&amp;quot;`    |&lt;br /&gt;
     || /=\\  |&lt;br /&gt;
     &amp;quot;&amp;#039;&amp;quot;  &amp;#039;&amp;quot;&amp;quot;&amp;quot;&amp;#039;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== Using external packages: declaring dependences &amp;amp; Using local functions in other files ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol style=&amp;quot;list-style-type: decimal;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Declaring dependencies&amp;#039;&amp;#039;&amp;#039;: The &amp;lt;code&amp;gt;warnings&amp;lt;/code&amp;gt; module is actually a built in python package, but suppose we also needed to use &amp;lt;code&amp;gt;numpy&amp;lt;/code&amp;gt; in our package. For example, suppose we created another &amp;lt;code&amp;gt;.py&amp;lt;/code&amp;gt; file called &amp;lt;code&amp;gt;utils.py&amp;lt;/code&amp;gt;, in it we had&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;import numpy as np&lt;br /&gt;
&lt;br /&gt;
def _top_and_bottom(name_length):&lt;br /&gt;
    length_vec = np.array([8,4]) + name_length&lt;br /&gt;
    return(length_vec)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;The first thing we’d need to do (so the code works for others) is to tell the package we require the installation of &amp;lt;code&amp;gt;numpy&amp;lt;/code&amp;gt; for anyone using our package. We do so by running&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;poetry add numpy&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;This will update our &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; and add asssociated dependences (there are none for &amp;lt;code&amp;gt;numpy&amp;lt;/code&amp;gt;), and will put that note under &amp;lt;code&amp;gt;[tool.poetry.dependencies]&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;#039;&amp;#039;Note: as of 8/20/21 this also required restricting my python version (in the &amp;lt;code&amp;gt;pyproject.toml&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;python = &amp;quot;?=3.8,&amp;lt;3.11&amp;quot;&amp;lt;/code&amp;gt;)&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;&amp;#039;&amp;#039;&amp;#039;Internal Functions&amp;#039;&amp;#039;&amp;#039;: To use our interal function &amp;lt;code&amp;gt;_top_and_bottom&amp;lt;/code&amp;gt; we might change the &amp;lt;code&amp;gt;communicate.py&amp;lt;/code&amp;gt; file to:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;import warnings&lt;br /&gt;
from .utils import _top_and_bottom&lt;br /&gt;
&lt;br /&gt;
def call_scotty_demo(your_name):&lt;br /&gt;
    # import warnings&lt;br /&gt;
    if len(your_name) &amp;gt; 30:&lt;br /&gt;
        warnings.warn(&amp;quot;your name is beyond 30 characters, &amp;quot;+\&lt;br /&gt;
                        &amp;quot;has been truncated&amp;quot;)&lt;br /&gt;
        your_name = your_name[:30]&lt;br /&gt;
&lt;br /&gt;
    name_length = len(your_name)&lt;br /&gt;
&lt;br /&gt;
    tb_info = _top_and_bottom(name_length)&lt;br /&gt;
&lt;br /&gt;
    # say Hiiiiii&lt;br /&gt;
    hi_string = &amp;quot;\n&amp;quot; +\&lt;br /&gt;
        &amp;quot;-&amp;quot; * tb_info[0] + &amp;quot;\n&amp;quot; +\&lt;br /&gt;
        &amp;quot;| Hi &amp;quot; + your_name + &amp;quot;! | \n&amp;quot; +\&lt;br /&gt;
        &amp;quot;|   &amp;quot; + &amp;quot;-&amp;quot; * tb_info[1] + &amp;quot;\n&amp;quot; +\&lt;br /&gt;
        &amp;quot;| /\n&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    ...&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Notice that to give &amp;lt;code&amp;gt;call_scotty_demo&amp;lt;/code&amp;gt; and all functions in the &amp;lt;code&amp;gt;communicate.py&amp;lt;/code&amp;gt; file access to &amp;lt;code&amp;gt;_top_and_bottom&amp;lt;/code&amp;gt; we had to import it using &amp;lt;code&amp;gt;from .utils import _top_and_bottom&amp;lt;/code&amp;gt;. Additionally, it’s best practice to use add a &amp;lt;code&amp;gt;_&amp;lt;/code&amp;gt; at the beginning of a function name if you plan to keep it internal.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 4: Documenting your functions ===&lt;br /&gt;
&lt;br /&gt;
Python documentation is simplier than R documentation as when you look at the documentation of a python function you just get show a docstring at the head of function. In this section we’ll discuss a bit about the extra support poetry can do so that you can generate a localized website for your documentation (that you could upload to [https:://readthedocs.org readthedocs] later).&lt;br /&gt;
&lt;br /&gt;
For documentation to be easily publishable at a later date we recommend that your docstrings follow the &amp;lt;code&amp;gt;numpydoc&amp;lt;/code&amp;gt; format (more details can be found at [https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard numpydoc.readthedocs]). Using this guideline we can document &amp;lt;code&amp;gt;call_scotty_demo&amp;lt;/code&amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;def call_scotty_demo(your_name):&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    Greet Scotty, the Scottie Dog&lt;br /&gt;
&lt;br /&gt;
    Scotty, the Scottie Dog greets your by name!&lt;br /&gt;
&lt;br /&gt;
    Parameters&lt;br /&gt;
    ----------&lt;br /&gt;
    your_name: str&lt;br /&gt;
        string of your name (max length 30 characters)&lt;br /&gt;
&lt;br /&gt;
    Returns&lt;br /&gt;
    -------&lt;br /&gt;
    None&lt;br /&gt;
        Though scotty appears on your screen and says Hi to you.&lt;br /&gt;
&lt;br /&gt;
    Examples&lt;br /&gt;
    --------&lt;br /&gt;
    &amp;gt;&amp;gt;&amp;gt; import tartanpy&lt;br /&gt;
    &amp;gt;&amp;gt;&amp;gt; tartanpy.call_scotty_demo(&amp;quot;Andrew Carnegie&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    -----------------------&lt;br /&gt;
    | Hi Andrew Carnegie! |&lt;br /&gt;
    |   -------------------&lt;br /&gt;
    | /&lt;br /&gt;
    |/  |\_/|&lt;br /&gt;
    |   |q p|   /}&lt;br /&gt;
    |   ( 0 )\&amp;quot;\&amp;quot;\&amp;quot;\\&lt;br /&gt;
     \\  |\&amp;quot;-\&amp;quot;`    |&lt;br /&gt;
        || /=\\\\  |&lt;br /&gt;
        \&amp;quot;&amp;#039;\&amp;quot;  &amp;#039;\&amp;quot;\&amp;quot;\&amp;quot;&amp;#039;&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    ...&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The basic structure of the documention is decently straight forward with the title / description of your function first, followed by (1) Parameters header with the parameter name, the type, and the description in the format above (2) Returns header followed by similar structure as Parameters. Adding (3) examples with standard python lines can be helpful as well.&lt;br /&gt;
&lt;br /&gt;
After reloading the package you could see that&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;In [1]: import tartanpy&lt;br /&gt;
&lt;br /&gt;
In [2]: ?tartanpy.call_scotty_demo&lt;br /&gt;
Signature: tartanpy.call_scotty_demo(your_name)&lt;br /&gt;
Docstring:&lt;br /&gt;
Greet Scotty, the Scottie Dog&lt;br /&gt;
&lt;br /&gt;
Scotty, the Scottie Dog greets your by name!&lt;br /&gt;
&lt;br /&gt;
Parameters&lt;br /&gt;
----------&lt;br /&gt;
your_name: str&lt;br /&gt;
    string of your name (max length 30 characters)&lt;br /&gt;
&lt;br /&gt;
Returns&lt;br /&gt;
-------&lt;br /&gt;
None&lt;br /&gt;
    Though scotty appears on your screen and says Hi to you.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
--------&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; import tartanpy&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; tartanpy.call_scotty_demo(&amp;quot;Andrew Carnegie&amp;quot;)&lt;br /&gt;
-----------------------&lt;br /&gt;
| Hi Andrew Carnegie! |&lt;br /&gt;
|   -------------------&lt;br /&gt;
| /&lt;br /&gt;
|/  |\_/|&lt;br /&gt;
|   |q p|   /}&lt;br /&gt;
|   ( 0 )&amp;quot;&amp;quot;&amp;quot;\&lt;br /&gt;
 \  |&amp;quot;-&amp;quot;`    |&lt;br /&gt;
    || /=\\  |&lt;br /&gt;
    &amp;quot;&amp;#039;&amp;quot;  &amp;#039;&amp;quot;&amp;quot;&amp;quot;&amp;#039;&lt;br /&gt;
File:      ..../tartanpy/src/tartanpy/communicate.py&lt;br /&gt;
Type:      function&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== Towards &amp;quot;readthedocs&amp;quot;-style html documentation ====&lt;br /&gt;
&lt;br /&gt;
py-pkgs and poetry also provide a quick way to transform your documentation into a local html website so you can quickly look through your documentation or load it to readthedocs later, with information on how to here: [https://py-pkgs.org/06-documentation py-pkgs/06-documentation].&lt;br /&gt;
&lt;br /&gt;
Generally speaking you have to&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt; install some additional packages to the development side of your package with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;poetry add --dev sphinx nbsphinx ipykernel&amp;lt;/syntaxhighlight&amp;gt; &amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;and then go to your docs folder and make the website locally (the &amp;lt;code&amp;gt;--dev&amp;lt;/code&amp;gt; parameter makes these packages not tracked for those just wanted to use your package, but required as you continue to develop the package locally).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;cd docs&lt;br /&gt;
poetry run make html&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
and this will create a local webpage (just open &amp;lt;code&amp;gt;docs/index.html&amp;lt;/code&amp;gt;) that contains your documentation. If you find the docs website useful maybe bookmark the local file?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 5: Testing ===&lt;br /&gt;
&lt;br /&gt;
Testing is critical to making sure your functions do what you expect. There are few ways to write unit tests in python (e.g. &amp;lt;code&amp;gt;unittest&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;nose&amp;lt;/code&amp;gt;). We recommend using &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; as it requires the least amount of overhead and provides the most details write off the bat.&lt;br /&gt;
&lt;br /&gt;
To use &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; we first to tell &amp;lt;code&amp;gt;poetry&amp;lt;/code&amp;gt; that we’ll use &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; in our development with&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;poetry add --dev pytest&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
==== What’s the philosophy behind &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Assertions&amp;#039;&amp;#039;&amp;#039;: &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt;’s foundation is defined around checking basic assertion statements like&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;In [1]: assert 1 == 1, &amp;quot;a true statement shouldn&amp;#039;t have errored...&amp;quot;&lt;br /&gt;
   ...: assert .3 - .2 == .1, &amp;quot;but sometimes floating points are bad...&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
that return:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;---------------------------------------------------------------------------&lt;br /&gt;
AssertionError                            Traceback (most recent call last)&lt;br /&gt;
&amp;lt;ipython-input-3-0daf5f7e9b9c&amp;gt; in &amp;lt;module&amp;gt;&lt;br /&gt;
      1 assert 1 == 1, &amp;quot;a true statement shouldn&amp;#039;t have errored...&amp;quot;&lt;br /&gt;
----&amp;gt; 2 assert .3 - .2 == .1, &amp;quot;but sometimes floating points are bad...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
AssertionError: but sometimes floating points are bad...&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
as the second line actual fails (due to some floating point silliness). This simple structure can be combined with standard logical &amp;lt;code&amp;gt;and&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;or&amp;lt;/code&amp;gt; as well as other tools like &amp;lt;code&amp;gt;numpy&amp;lt;/code&amp;gt; logic (.e.g &amp;lt;code&amp;gt;np.all()&amp;lt;/code&amp;gt;). Notice that following a logical statement with a string nicely associated a statement to be returned if the assertion is not true.&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Grouping Assertions&amp;#039;&amp;#039;&amp;#039;: We can imagine wishing to combine a set of assertions, and we can do this easily with a function wrapper. For example&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;import tartanpy&lt;br /&gt;
import pytest # only for warning&lt;br /&gt;
&lt;br /&gt;
def test_call_scotty_demo():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    test the basics of call_scotty_demo&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    assert tartanpy.call_scotty_demo(&amp;quot;Oski Bear&amp;quot;) is None, \&lt;br /&gt;
        &amp;quot;the output of call_scotty_demo should be None&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    # test warning&lt;br /&gt;
    with pytest.warns(UserWarning) as record:&lt;br /&gt;
        tartanpy.call_scotty_demo(&amp;quot;Oski Bear, your a wonderful, but slightly creepy Berkeley Bear&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    assert len(record) &amp;gt; 0, \&lt;br /&gt;
        &amp;quot;expect a warning for name_string longer than 30 for call_scotty_demo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    assert .3 - .2 == .1, &amp;quot;but sometimes floating points are bad...&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;To actually leverage &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; we can put &amp;#039;&amp;#039;&amp;#039;A set of grouped tests&amp;#039;&amp;#039;&amp;#039; in single file. When building a package your functions will likelyl live in different &amp;lt;code&amp;gt;.py&amp;lt;/code&amp;gt; files in the &amp;lt;code&amp;gt;src/&amp;lt;packagename&amp;gt;&amp;lt;/code&amp;gt; folder. To mirror this structure we put of our tests associated with a single &amp;lt;code&amp;gt;.py&amp;lt;/code&amp;gt; file into 1 test file. These files sit in the &amp;lt;code&amp;gt;tests/&amp;lt;/code&amp;gt; folder and must start with &amp;lt;code&amp;gt;test&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
In these larger files (relative to group functions) need to make sure our functions are brought in, for example at the head we need to put &amp;lt;code&amp;gt;import tartanpy&amp;lt;/code&amp;gt; as see in the code block above.&lt;br /&gt;
&lt;br /&gt;
To run these tests you can either do&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;pytest&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
or (making sure you have all the correct packages)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;poetry run pytest&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&amp;#039;&amp;#039;Note: we actually have some printouts in &amp;lt;code&amp;gt;call_scotty_demo&amp;lt;/code&amp;gt;, which are not desirable, so we actually follow a suggestion from [https://stackoverflow.com/questions/8391411/how-to-block-calls-to-print stackoverflow] to suppress the printing (doesn’t mess with the testing), and is seen in the code block below:&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;import tartanpy&lt;br /&gt;
import pytest # only for warning&lt;br /&gt;
&lt;br /&gt;
def test_call_scotty_demo():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    test the basics of call_scotty_demo&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    with open(os.devnull, &amp;quot;w&amp;quot;) as f, contextlib.redirect_stdout(f):&lt;br /&gt;
        assert tartanpy.call_scotty_demo(&amp;quot;Oski Bear&amp;quot;) is None, \&lt;br /&gt;
            &amp;quot;the output of call_scotty_demo should be None&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # test warning&lt;br /&gt;
        with pytest.warns(UserWarning) as record:&lt;br /&gt;
            tartanpy.call_scotty_demo(&amp;quot;Oski Bear, your a wonderful, but slightly creepy Berkeley Bear&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        assert len(record) &amp;gt; 0, \&lt;br /&gt;
            &amp;quot;expect a warning for name_string longer than 30 for call_scotty_demo&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        assert .3 - .2 == .1, &amp;quot;but sometimes floating points are bad...&amp;quot;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
If we remove the silly floating point error assession we get the following:&lt;br /&gt;
&lt;br /&gt;
[[File:Pytest_example.png|frameless|600px|alt=output of pytest|output of pytest]]&lt;br /&gt;
&lt;br /&gt;
And if there are errors &amp;lt;code&amp;gt;pytest&amp;lt;/code&amp;gt; tries to be very clear about where in your tests you had an error.&lt;br /&gt;
&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== More comments on testing ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ol&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Hidden and/or not exported functions&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
In our example we have a hidden function &amp;lt;code&amp;gt;_top_and_bottom&amp;lt;/code&amp;gt;. Different thoughts exist on whether or not one should test hidden functions, but to do so we have to be a bit tricker since the function isn’t loaded by the package. We can still test it by using the full path to the function, that is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;import tartanpy&lt;br /&gt;
import numpy as np&lt;br /&gt;
&lt;br /&gt;
def test__top_and_bottom():&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    test for hidden function _top_and_bottom&lt;br /&gt;
    &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
    option4 = tartanpy.utils._top_and_bottom(len(&amp;quot;test&amp;quot;))&lt;br /&gt;
    option17 = tartanpy.utils._top_and_bottom(len(&amp;quot;test_a_longer_one&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
    assert np.all(option17 - option4 == 17-4), \&lt;br /&gt;
        &amp;quot;expect _top_and_bottom values to only differ by length of input&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    assert np.all(option17 - 17 == np.array([8,4])), \&lt;br /&gt;
        &amp;quot;expect that _top_and_bottom adds 8 and 4 to length of input&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Additionally, since we started the name off with a &amp;lt;code&amp;gt;_&amp;lt;/code&amp;gt;, we could also find that if we did&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;from tartanpy.utils import *&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
which should import everything from the &amp;lt;code&amp;gt;util.py&amp;lt;/code&amp;gt; file we won’t actually have access to it, whereas&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;python&amp;quot;&amp;gt;from tartanpy.communicate import *&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
would get access to &amp;lt;code&amp;gt;call_scotty_demo&amp;lt;/code&amp;gt; even if it wasn’t in the &amp;lt;code&amp;gt;__init__.py&amp;lt;/code&amp;gt; file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;#039;&amp;#039;&amp;#039;Numerical instablity&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
We included an example where floating point differnces made &amp;lt;code&amp;gt;.3-.2&amp;lt;/code&amp;gt; not equal to &amp;lt;code&amp;gt;.1&amp;lt;/code&amp;gt;. To avoid such errors we recommend using tools like&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;np.allclose&amp;lt;/code&amp;gt; (which allows user to provide relative and absolute tolerance between vectors)&lt;br /&gt;
* or do something like &amp;lt;code&amp;gt;np.abs(a-b)&amp;lt;1e-08&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;np.abs(a-b)/np.abs(b) &amp;lt; 1e-08&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;/li&amp;gt;&amp;lt;/ol&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Step 6. Sharing / using on other computers ===&lt;br /&gt;
&lt;br /&gt;
You could publish your package to pypi (documented here: [https://py-pkgs.org/07-releasing-versioning py-pkg/07-releasing-versioning]) but if you’re still actively working on a developer version another easy way is to make sure you have a clean copy on github, have the user clone the repo and then run either (when in the top directory of the cloned repo)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;pip install .&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
or&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;pip install -e .&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
where the first installs the package 1 time, and the second actually installs the package and updates the package if that user was to do more pulls / updates the the package.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Step 7. And beyond! ===&lt;br /&gt;
&lt;br /&gt;
In the above example, we still didn’t cover a lot of things, including:&lt;br /&gt;
&lt;br /&gt;
*publishing the package &lt;br /&gt;
*publishing the docs &lt;br /&gt;
*including data &lt;br /&gt;
*CI/CD (which will be provided in another wiki) &lt;br /&gt;
&lt;br /&gt;
See [https://py-pkgs.org py-pkgs] for some good starting blocks for most of these.&lt;/div&gt;</summary>
		<author><name>Skipper</name></author>
	</entry>
</feed>