<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3430885654094366683</id><updated>2026-09-07T03:02:35.766+01:00</updated><category term="Javascript"/><category term="C#"/><category term="python"/><category term="Database"/><category term="SQL"/><category term="windows-scripting"/><category term="TypeScript"/><category term="VisualStudio"/><category term="SharePoint"/><category term="Unit Testing"/><category term="Performance"/><category term="C++"/><category term="Debugging"/><category term="charts"/><category term="Build Engineering"/><category term="Clean Code"/><category term="Data Visualization"/><category term="Google Chrome"/><category term="HTML"/><category term="Install"/><category term="UI"/><category term="ASP.NET"/><category term="CSS"/><category term="Design Patterns"/><category term="Tools"/><category term="Amazon Athena"/><category term="LINQ"/><category term="Mercurial"/><category term="Pandas"/><category term="scripting"/><category term="Maps"/><category term="Methodologies"/><category term="ArcGIS"/><category term="Code analysis"/><category term="Node.js"/><category term="PDF"/><category term="Powershell"/><category term="Scala"/><category term="TFS"/><category term="Unix"/><category term="Architecture"/><category term="Automation"/><category term="COM"/><category term="Machine Learning"/><category term="Memory"/><category term="Mobile"/><category term="Open Source"/><category term="SSIS"/><category term="Web API"/><category term="git"/><category term="Algorithms"/><category term="Angular2"/><category term="Exception Handling"/><category term="File formats"/><category term="Java"/><category term="Medium"/><category term="Networks"/><category term="Reporting"/><category term="Testing"/><category term="Ubuntu"/><category term="VirtualBox"/><category term="books"/><category term="docs"/><category term="image-processing"/><category term="npm"/><category term="AWS"/><category term="Canvas"/><category term="Cloud"/><category term="Data analysis"/><category term="Group Policy"/><category term="IE"/><category term="Jupyter"/><category term="Logging"/><category term="Ruby"/><category term="SCRUM"/><category term="Service"/><category term="SignalR"/><category term="Threading"/><category term="Visual Basic"/><category term="WiX"/><category term="graphs"/><category term="graphviz"/><category term="kendo"/><category term="knockout"/><category term="markdown"/><category term="matplotlib"/><category term="react"/><category term="AI"/><category term="Amazon EMR"/><category term="AutoIt"/><category term="CORS"/><category term="Interop"/><category term="Jenkins"/><category term="Kerberos"/><category term="Leaks"/><category term="Localization"/><category term="MSMQ"/><category term="Mac"/><category term="Managed C++"/><category term="Microsoft Office"/><category term="Monitoring"/><category term="NTLM"/><category term="ORM"/><category term="Optimization"/><category term="Profiling"/><category term="Proxy"/><category term="Real-time"/><category term="Regex"/><category term="Remote Debugging"/><category term="Rust"/><category term="SVG"/><category term="Selenium"/><category term="UML"/><category term="Video"/><category term="Virtual machines"/><category term="Visitor"/><category term="Visual Code"/><category term="WCF"/><category term="WPF"/><category term="Websocket"/><category term="XAML"/><category term="XML"/><category term="XPmode"/><category term="data"/><category term="layout"/><category term="mobx"/><category term="react-native"/><category term="redux"/><category term="yarn"/><title type='text'>anti patterns codin&#39;</title><subtitle type='html'>problems and solutions for the coding challenges of today - C#, T-SQL, javascript, Windows, Ubuntu, Python ...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>334</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-7671721352275456653</id><published>2025-05-14T15:56:00.002+01:00</published><updated>2025-05-14T15:56:18.101+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="windows-scripting"/><title type='text'>Fixing or Repairing Windows Installation and Checking Disks for Errors</title><content type='html'>&lt;p&gt;To fix or repair Windows (for example if problems with Microsoft Teams):&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;sfc /scannow&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;DISM.exe /Online /Cleanup-image /Restorehealth&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;To check disks for bad clusters on C drive, and try to fix:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;chkdsk /x/r&amp;nbsp; c:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;tips:&lt;/div&gt;&lt;div&gt;- you should always back up your data, just in case.&lt;/div&gt;&lt;div&gt;- all media are subject to &#39;bit rot&#39; over time, including optical media.&lt;/div&gt;&lt;div&gt;- consider holding data on a separate partition from the operating system.&lt;/div&gt;&lt;div&gt;- consider backing up to an offsite target.&lt;/div&gt;&lt;div&gt;- consider backing up the &#39;raw&#39; original files, so that they are easy to restore.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/7671721352275456653/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2025/05/fixing-or-repairing-windows.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/7671721352275456653'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/7671721352275456653'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2025/05/fixing-or-repairing-windows.html' title='Fixing or Repairing Windows Installation and Checking Disks for Errors'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-8863356004609686725</id><published>2025-03-05T08:38:00.004+00:00</published><updated>2025-03-05T08:38:46.000+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Web API"/><title type='text'>REST API guidelines from Microsoft</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;REST API guidelines from Microsoft&lt;/h2&gt;&lt;p&gt;This article notes some REST API guidelines from Microsoft (they are applicable to other tech stacks too, such as Python FastAPI). The Microsoft article has further guidelines, this article presents a selection.&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Organize the API design around resources&lt;/h3&gt;&lt;p&gt;- when designing the URL paths, think in terms of &#39;objects&#39; rather than verbs&lt;/p&gt;&lt;p&gt;Examples:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;https://adventure-works.com/orders // Good&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;https://adventure-works.com/create-order // Avoid&lt;/span&gt;&lt;/p&gt;&lt;p&gt;ref:&amp;nbsp;&lt;a href=&quot;https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design#organize-the-api-design-around-resources&quot;&gt;Web API design best practices - Azure Architecture Center | Microsoft Learn&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Define API operations in terms of HTTP methods&lt;/h3&gt;&lt;div&gt;- use GET and POST appropriately&lt;/div&gt;&lt;div&gt;- combine with URL &#39;paths&#39; to model the hierarchy of objects&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Examples:&lt;/div&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;/customers -&amp;gt; GET = Get all customers, POST = Create a new customer&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;/customers/1 -&amp;gt; GET = Get customer 1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;/customers/1/orders -&amp;gt; GET = Get all orders for customer 1, POST = Create a new order for customer 1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Source&lt;/h2&gt;&lt;p&gt;-&amp;nbsp;&lt;a href=&quot;https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design#define-api-operations-in-terms-of-http-methods&quot;&gt;Web API design best practices - Azure Architecture Center | Microsoft Learn&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/8863356004609686725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2025/03/rest-api-guidelines-from-microsoft.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/8863356004609686725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/8863356004609686725'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2025/03/rest-api-guidelines-from-microsoft.html' title='REST API guidelines from Microsoft'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-1852213380245581235</id><published>2025-02-12T09:00:00.002+00:00</published><updated>2025-02-12T09:00:49.815+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Pydantic: Dynamically creating a model, with field types, examples and descriptions.</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;Pydantic: Dynamically creating a model, with field types, examples and descriptions.&lt;/h2&gt;&lt;p&gt;Normally, Pydantic models are hard-coded and cannot change at runtime. However it is also possibly to build a Pydantic model &#39;on the fly&#39;.&lt;/p&gt;&lt;p&gt;Here is a function to dynamically create a Pydantic model. Each field has a type, description and some examples:&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;typing&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;Any&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Tuple&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;pydantic&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;BaseModel&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;Field&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;create_model&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;FieldDetails&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Tuple&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;type&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;Any&lt;/span&gt;]] &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# field type, description, examples&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;create_dynamic_model&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;model_name&lt;/span&gt;:&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fields_dict&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;dict&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;FieldDetails&lt;/span&gt;]) -&amp;gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;type&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;BaseModel&lt;/span&gt;]:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&amp;nbsp; &amp;nbsp; Create a dynamic Pydantic model based on the provided fields dictionary.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&amp;nbsp; &amp;nbsp; - why: we want to read the examples from example_store, not hard-code them.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&amp;nbsp; &amp;nbsp; :param fields_dict: A dictionary where keys are field names and values are tuples of (type, description, examples)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&amp;nbsp; &amp;nbsp; :return: A dynamically created Pydantic model&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&amp;nbsp; &amp;nbsp; &quot;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;create_model&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;model_name&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;**&lt;/span&gt;{&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;field_name&lt;/span&gt;: (&lt;span style=&quot;color: #dcdcaa;&quot;&gt;field_type&lt;/span&gt;, &lt;span style=&quot;color: #dcdcaa;&quot;&gt;Field&lt;/span&gt;(..., &lt;span style=&quot;color: #9cdcfe;&quot;&gt;description&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;field_desc&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;examples&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;examples&lt;/span&gt;))&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;field_name&lt;/span&gt;, (&lt;span style=&quot;color: #dcdcaa;&quot;&gt;field_type&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;field_desc&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;examples&lt;/span&gt;) &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fields_dict&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;items&lt;/span&gt;()&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;/div&gt;&lt;p&gt;Example usage:&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;__name__&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;==&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;__main__&quot;&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# Define the fields for our dynamic model&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fields&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;name&quot;&lt;/span&gt;: (&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;The name of the person&quot;&lt;/span&gt;, [&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Bob&quot;&lt;/span&gt;]),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;age&quot;&lt;/span&gt;: (&lt;span style=&quot;color: #4ec9b0;&quot;&gt;int&lt;/span&gt;, &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;The age of the person&quot;&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;54&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;email&quot;&lt;/span&gt;: (&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;The email address of the person&quot;&lt;/span&gt;, &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;bob@hotmail.com&quot;&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;is_student&quot;&lt;/span&gt;: (&lt;span style=&quot;color: #4ec9b0;&quot;&gt;bool&lt;/span&gt;, &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Whether the person is a student or not&quot;&lt;/span&gt;, &lt;span style=&quot;color: #4fc1ff;&quot;&gt;False&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; }&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# Create the dynamic model&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;DynamicPerson&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;create_dynamic_model&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Person&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fields&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# Create an instance of the model&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;person&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;DynamicPerson&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;John Doe&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;age&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #b5cea8;&quot;&gt;30&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;email&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;john.doe@example.com&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_student&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;False&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# Print the model&#39;s schema&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;DynamicPerson&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;schema_json&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;indent&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #b5cea8;&quot;&gt;2&lt;/span&gt;))&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# Print the instance&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;person&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# Access fields and their descriptions&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;field_name&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;field&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;DynamicPerson&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;model_fields&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;items&lt;/span&gt;():&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Field: &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;field_name&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;, Description: &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;field&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;description&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/1852213380245581235/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2025/02/pydantic-dynamically-creating-model.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/1852213380245581235'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/1852213380245581235'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2025/02/pydantic-dynamically-creating-model.html' title='Pydantic: Dynamically creating a model, with field types, examples and descriptions.'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-472525001875677918</id><published>2025-02-10T17:53:00.002+00:00</published><updated>2025-02-10T17:53:20.941+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="PDF"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python: Convert a base64 encoded PDF file to a list of PIL (pillow) Images</title><content type='html'>&lt;p&gt;&lt;b&gt;Python: Convert a base64 encoded PDF file to a list of PIL (pillow) Images&lt;/b&gt;&lt;/p&gt;&lt;p&gt;motivation: generally images are easier to work with than PDF files.&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;base64&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;pdf2image&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;PIL&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Image&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;convert_base64_encoded_pdf_to_PIL_image&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;pdf_base64&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;) -&amp;gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Image&lt;/span&gt;.&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Image&lt;/span&gt;]:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;pdf_bytes&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;base64&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;b64decode&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;pdf_base64&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;pdf2image&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;convert_from_bytes&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;pdf_bytes&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/472525001875677918/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2025/02/python-convert-base64-encoded-pdf-file.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/472525001875677918'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/472525001875677918'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2025/02/python-convert-base64-encoded-pdf-file.html' title='Python: Convert a base64 encoded PDF file to a list of PIL (pillow) Images'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-2136414133260851521</id><published>2025-01-29T10:01:00.006+00:00</published><updated>2025-01-29T10:02:09.056+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Problem: poetry does not pick up the current &#39;local&#39; python (set via pyenv)</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;&lt;b&gt;Problem: poetry does not pick up the current &#39;local&#39; python (set via pyenv)&lt;/b&gt;&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/pyenv/pyenv&quot; target=&quot;_blank&quot;&gt;pyenv&lt;/a&gt; is a nice Python version management tool.&lt;/p&gt;&lt;p&gt;Problem: it can happen that poetry does not pick up the current local Python version.&lt;/p&gt;&lt;p&gt;For example, if the global version is 3.11.7, then pyenv can be used to set the local version:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;pyenv local 3.12.7&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Then, using poetry (here it is used to run ruff, to format):&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;poetry run ruff format&lt;/span&gt;&lt;/p&gt;&lt;p&gt;There is an error, as the poetry environment is still using the global Python version:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: red; font-family: courier;&quot;&gt;Current Python version (3.11.7) is not allowed by the project (^3.12).&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;color: red; font-family: courier;&quot;&gt;Please change python executable via the &quot;env use&quot; command.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Solution:&lt;/h3&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;poetry env use python&lt;/span&gt;&lt;/p&gt;&lt;p&gt;This creates a new poetry environment, which picks up the local Python version.&lt;/p&gt;&lt;p&gt;The new environment needs its dependencies installed:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;poetry install&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Now, poetry should run OK:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;poetry run ruff format&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/2136414133260851521/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2025/01/problem-poetry-does-not-pick-up-current.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/2136414133260851521'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/2136414133260851521'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2025/01/problem-poetry-does-not-pick-up-current.html' title='Problem: poetry does not pick up the current &#39;local&#39; python (set via pyenv)'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-4316211853816257775</id><published>2025-01-24T16:03:00.003+00:00</published><updated>2025-01-24T16:33:17.950+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="Tools"/><title type='text'>A starter template for a Python Command Line program</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;A starter template for a Python Command Line program&lt;/h2&gt;&lt;div&gt;There are several ways to create a command line program in Python.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This blog post presents a simple example &#39;template&#39; based around the built-in &lt;a href=&quot;https://docs.python.org/3/library/optparse.html&quot; target=&quot;_blank&quot;&gt;optparse module&lt;/a&gt; (with OptionParser class). The optparse module has good documentation on how to set it up, but seems to lack a few examples of how to actually use it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can copy-paste this code and edit it to suit your particular command line program.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;main.py&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;TODO_DESCRIBE_WHAT_THIS_DOES.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&quot;&quot;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;sys&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;optparse&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;OptionParser&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt;# usage() - prints out the usage text, from the top of this file :-) and the options&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;usage&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;parser&lt;/span&gt;):&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;__doc__&lt;/span&gt;)&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;parser&lt;/span&gt;.print_help()&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #6a9955;&quot;&gt;# optparse - parse the args&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;parser&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;OptionParser&lt;/span&gt;(&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;usage&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;%prog &amp;lt;TODO_ARGS&amp;gt; [options]&quot;,&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;div style=&quot;line-height: 19px;&quot;&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;&quot;0.1.0&quot;&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;)&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;parser&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;add_option&lt;/span&gt;(&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;-i&quot;&lt;/span&gt;, &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;--input&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metavar&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;INPUT_FILE&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;help&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;read data from INPUT_FILE&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;dest&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;input_file&quot;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;)&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;parser&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;add_option&lt;/span&gt;(&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;-l&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;--language&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;dest&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;target_language&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metavar&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;TARGET_LANGUAGE&quot;&lt;/span&gt;, &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# &#39;metavar&#39; helps make &#39;help&#39; messages refer to values and is used to build the help for this option.&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;English&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;help&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;translate to the target output language TARGET_LANGUAGE. Example: English.&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;)&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;parser&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;add_option&lt;/span&gt;(&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;-o&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;--output&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;dest&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;output_dir&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;None&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;help&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;the output directory. By default is None, so output is to stdout (no files are output).&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;)&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;parser&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;add_option&lt;/span&gt;(&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;-v&quot;&lt;/span&gt;, &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;--verbose&quot;&lt;/span&gt;, &amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;action&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;store_true&#39;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;help&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;turn on verbose mode&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;dest&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;is_verbose&quot;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;)&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;options&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;args&lt;/span&gt;) &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;parser&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;parse_args&lt;/span&gt;()&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;len&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;args&lt;/span&gt;) &lt;span style=&quot;color: #d4d4d4;&quot;&gt;!=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;usage&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;parser&lt;/span&gt;)&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;sys&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;exit&lt;/span&gt;(&lt;span style=&quot;color: #b5cea8;&quot;&gt;2&lt;/span&gt;)&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;first_arg&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;args&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;]&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;target_language&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;options&lt;/span&gt;.target_language&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;path_to_output_dir&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;None&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;options&lt;/span&gt;.output_dir:&lt;/div&gt;&lt;div style=&quot;color: #cccccc;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;path_to_output_dir&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;options&lt;/span&gt;.output_dir&lt;/div&gt;&lt;span style=&quot;color: #cccccc;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Running &lt;span style=&quot;font-family: courier;&quot;&gt;python main.py&lt;/span&gt; will output help text like:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;main.py&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;TODO_DESCRIBE_WHAT_THIS_DOES.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Usage: main.py &amp;lt;TODO_ARGS&amp;gt; [options]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Options:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; --version&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;show program&#39;s version number and exit&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; -h, --help&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; show this help message and exit&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; -i INPUT_FILE, --input=INPUT_FILE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; read data from INPUT_FILE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; -l TARGET_LANGUAGE, --language=TARGET_LANGUAGE&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; translate to the target output language&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; TARGET_LANGUAGE. Example: English.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; -o OUTPUT_DIR, --output=OUTPUT_DIR&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; the output directory. By default is None, so output is&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; to stdout (no files are output).&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; -v, --verbose&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;turn on verbose mode&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/4316211853816257775/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2025/01/a-starter-template-for-python-command.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4316211853816257775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4316211853816257775'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2025/01/a-starter-template-for-python-command.html' title='A starter template for a Python Command Line program'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-1184910576650764702</id><published>2025-01-22T10:21:00.002+00:00</published><updated>2025-01-22T10:21:20.440+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>How to read and write a Pydantic class to/from a JSON file.</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;How to read and write a Pydantic class to/from a JSON file.&lt;/h2&gt;&lt;p&gt;Pydantic classes are (de)serializable, although deserializing can be a little tricky.&lt;/p&gt;&lt;p&gt;Here is some example code, with functions to load and save data for an example Pydantic class &#39;MySerializableType&#39;:&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;logging&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;cornsnake&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;util_file&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;util_json&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;pydantic&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;BaseModel&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;TypeAdapter&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;logger&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;logging&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getLogger&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;__file__&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;CustomBaseModel&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;BaseModel&lt;/span&gt;):&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #569cd6;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Config&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;populate_by_name&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;True&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;extra&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;forbid&quot;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;MySerializableType&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;CustomBaseModel&lt;/span&gt;):&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;favourite_color&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;blue&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;file_schema_version&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;0.2&quot;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;read_from_file&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;path_to_file&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;) -&amp;gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;MySerializableType&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;try&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;json_data&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;util_json&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;read_from_json_file&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;path_to_file&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;deserialized&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &amp;nbsp;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;TypeAdapter&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;MySerializableType&lt;/span&gt;).&lt;span style=&quot;color: #dcdcaa;&quot;&gt;validate_python&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;json_data&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;deserialized&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;except&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Exception&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;e&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;logger&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;exception&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;e&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;save_to_file&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;path_to_file&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;MySerializableType&lt;/span&gt;) -&amp;gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;None&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;json_data&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;data&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;model_dump_json&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;by_alias&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;True&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;util_file&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;write_text_to_file&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;json_data&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;path_to_file&lt;/span&gt;)&lt;/div&gt;

&lt;/div&gt;

&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;notes:&lt;/div&gt;&lt;div&gt;- read_from_file(): TypeAdapter is used to validate and map the JSON back to the expected Pydantic class&lt;/div&gt;&lt;div&gt;- save_to_file(): model_dump_json() is used to serialize the Pydantic object to JSON. The parameter by_alias=True ensures that the BaseModel config options are followed (in particular, if camelCasing is specified as opposed to snake_case).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/1184910576650764702/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2025/01/how-to-read-and-write-pydantic-class.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/1184910576650764702'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/1184910576650764702'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2025/01/how-to-read-and-write-pydantic-class.html' title='How to read and write a Pydantic class to/from a JSON file.'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-4861631165393288461</id><published>2024-12-14T10:00:00.002+00:00</published><updated>2024-12-14T10:00:34.524+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Debugging"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Python Debugging Tips</title><content type='html'>&lt;p&gt;Coding a breakpoint, which activates the REPL debugger:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;import pdb&lt;br /&gt;pdb.set_trace()&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Printing out the stack trace of an exception:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;import traceback&lt;br /&gt;try:&lt;br /&gt;&amp;nbsp; &amp;nbsp; print(variable_that_does_not_exist)&lt;br /&gt;except Exception as e:&lt;br /&gt;&amp;nbsp; &amp;nbsp; print(traceback.format_exc())&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre class=&quot;enlighter-clipboard&quot; style=&quot;border: 0px; bottom: 0px; box-sizing: border-box; color: #212529; direction: ltr; font-family: var(--bs-font-monospace); font-size: 16px; height: 1px; left: 0px; margin-bottom: 0px; margin-top: 0px; overflow: hidden; padding: 0px; position: absolute; unicode-bidi: bidi-override; vertical-align: baseline; width: 1px;&quot;&gt;import traceback
try:
    print(variable_that_does_not_exist)
except Exception as e:
    print(traceback.format_exc())&lt;/pre&gt;&lt;pre class=&quot;enlighter-clipboard&quot; style=&quot;border: 0px; bottom: 0px; box-sizing: border-box; color: #212529; direction: ltr; font-family: var(--bs-font-monospace); font-size: 16px; height: 1px; left: 0px; margin-bottom: 0px; margin-top: 0px; overflow: hidden; padding: 0px; position: absolute; unicode-bidi: bidi-override; vertical-align: baseline; width: 1px;&quot;&gt;import traceback
try:
    print(variable_that_does_not_exist)
except Exception as e:
    print(traceback.format_exc())&lt;/pre&gt;&lt;pre class=&quot;enlighter-clipboard&quot; style=&quot;border: 0px; bottom: 0px; box-sizing: border-box; color: #212529; direction: ltr; font-family: var(--bs-font-monospace); font-size: 16px; height: 1px; left: 0px; margin-bottom: 0px; margin-top: 0px; overflow: hidden; padding: 0px; position: absolute; unicode-bidi: bidi-override; vertical-align: baseline; width: 1px;&quot;&gt;import traceback
try:
    print(variable_that_does_not_exist)
except Exception as e:
    print(traceback.format_exc())&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/4861631165393288461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/12/python-debugging-tips.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4861631165393288461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4861631165393288461'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/12/python-debugging-tips.html' title='Python Debugging Tips'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-5107568561723965030</id><published>2024-12-01T11:10:00.005+00:00</published><updated>2024-12-01T11:13:21.399+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="charts"/><category scheme="http://www.blogger.com/atom/ns#" term="Machine Learning"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Adding custom &#39;summary&#39; charts to MLflow: simple bar chart and &#39;grouped&#39; bar chart</title><content type='html'>&lt;p&gt;MLflow is a convenient and OSS (Open Source Software) service for accepting the result of a machine learning evaluation.&lt;/p&gt;&lt;p&gt;By default, the MLflow user interface can be used to add basic charts of metrics, to view results and also compare across runs.&lt;/p&gt;&lt;p&gt;However if there are many metrics, then it can be useful to create a custom &#39;summary&#39; chart.&lt;/p&gt;&lt;p&gt;The approach taken here is to use matplotlib to generate custom charts, and then attach as an artifact using the MLflow API. This follows the &lt;a href=&quot;https://mlflow.org/docs/latest/traditional-ml/hyperparameter-tuning-with-child-runs/notebooks/logging-plots-in-mlflow.html#Logging-Visualizations-with-MLflow&quot; target=&quot;_blank&quot;&gt;MLflow documentation&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;note: To allow for grouping of metrics by category, the following code assumes a convention where the MLflow metrics are named like &#39;&amp;lt;category&amp;gt;__&amp;lt;metric&amp;gt;&#39;.&lt;/p&gt;&lt;p&gt;So the data being logged to MLflow looks like this:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #1f1f1f; color: #6a9955; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; white-space: pre;&quot;&gt;[(&#39;category1__response_time_ms&#39;, 11000.0), (&#39;category2__response_time_ms&#39;, 20000.0)]&lt;/span&gt;&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Simple Bar Chart&lt;/h2&gt;&lt;p&gt;The following code shows how to generate a summary bar chart, with one bar for each metric:&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;logging&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;typing&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;matplotlib&lt;/span&gt;.&lt;span style=&quot;color: #4ec9b0;&quot;&gt;colors&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Colormap&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;matplotlib&lt;/span&gt;.&lt;span style=&quot;color: #4ec9b0;&quot;&gt;figure&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Figure&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;pandas&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;pd&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;matplotlib&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;pyplot&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;plt&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;numpy&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;np&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;logger&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;logging&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getLogger&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;__name__&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MLflowFigure&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;tuple&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Figure&lt;/span&gt;] &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# title and figure&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MetricAndMeasure&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;tuple&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;float&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;None&lt;/span&gt;]&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;METRIC_NAME_DIVIDER&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;__&quot;&lt;/span&gt; &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# MLflow attributes have been setup to have a category, by using a prefix like: metric_name = &amp;lt;category&amp;gt;__&amp;lt;metric&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_build_color_map_by_value&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;values&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;float&lt;/span&gt;]) -&amp;gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Colormap&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;rescale&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;lambda&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;y&lt;/span&gt;: (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;y&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;np&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;min&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;y&lt;/span&gt;)) &lt;span style=&quot;color: #d4d4d4;&quot;&gt;/&lt;/span&gt; (&lt;span style=&quot;color: #4ec9b0;&quot;&gt;np&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;max&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;y&lt;/span&gt;) &lt;span style=&quot;color: #d4d4d4;&quot;&gt;-&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;np&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;min&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;y&lt;/span&gt;))&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;my_cmap&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;plt&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;get_cmap&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;viridis&quot;&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;typing&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;cast&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;Colormap&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;my_cmap&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;rescale&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;np&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;array&lt;/span&gt;(&lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;values&lt;/span&gt;)))))&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_create_bar_chart&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;title&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;yaxis_title&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurements_by_category&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;dict&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;float&lt;/span&gt;], &lt;span style=&quot;color: #9cdcfe;&quot;&gt;unit_short&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;bool&lt;/span&gt;&lt;/div&gt;&lt;div&gt;) -&amp;gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;MLflowFigure&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;measurements_by_category = &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurements_by_category&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; [&lt;span style=&quot;color: #d4d4d4;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurements_by_category&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;keys&lt;/span&gt;()]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;values&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; [&lt;span style=&quot;color: #d4d4d4;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurements_by_category&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;values&lt;/span&gt;()]&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fig&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;plt&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;subplots&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;constrained&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;figsize&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;(&lt;span style=&quot;color: #b5cea8;&quot;&gt;21&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;7&lt;/span&gt;))&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;bar_width&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0.1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bar&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;height&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;values&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;width&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;bar_width&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;align&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;edge&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;label&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;color&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;_build_color_map_by_value&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;values&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;values&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;x&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;np&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;arange&lt;/span&gt;(&lt;span style=&quot;color: #dcdcaa;&quot;&gt;len&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;)) &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# the label locations&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;bar_width&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0.1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;set_xticks&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;x&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;bar_width&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# Add some text for labels, title and custom x-axis tick labels, etc.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;set_ylabel&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;yaxis_title&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;set_title&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;title&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;legend&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;yaxis_title&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ncols&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;len&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;))&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# label each bar with its value&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;rects&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;patches&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;i&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;rect&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;enumerate&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;rects&lt;/span&gt;):&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;label&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;values&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;i&lt;/span&gt;]&lt;span style=&quot;color: #569cd6;&quot;&gt;}{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;unit_short&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;height&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;rect&lt;/span&gt;.get_height()&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;text&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;rect&lt;/span&gt;.get_x() &lt;span style=&quot;color: #d4d4d4;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;rect&lt;/span&gt;.get_width() &lt;span style=&quot;color: #d4d4d4;&quot;&gt;/&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;2&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;height&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;label&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ha&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;center&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;va&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;bottom&quot;&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# scale the y-axis&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;y_max&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0.0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurements_by_category&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurement&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurements_by_category&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;y_max&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;max&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;y_max&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurement&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;set_ylim&lt;/span&gt;(&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;y_max&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1.2&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;plt&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;show&lt;/span&gt;()&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;title&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fig&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_create_summary_figure&lt;/span&gt;(mlflow_&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metrics&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MetricAndMeasure&lt;/span&gt;], &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;bool&lt;/span&gt;) -&amp;gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;MLflowFigure&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# example input: [(&#39;category1__response_time_ms&#39;, 11000.0), (&#39;category2__response_time_ms&#39;, 20000.0)]&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; metrics&lt;span style=&quot;color: #9cdcfe;&quot;&gt;_by_category&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;dict&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;float&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {}&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metrics&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {}&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; [&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurement&lt;/span&gt;] &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; mlflow_&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;split&lt;/span&gt;(&lt;span style=&quot;color: #4fc1ff;&quot;&gt;METRIC_NAME_DIVIDER&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;True&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; metrics&lt;span style=&quot;color: #9cdcfe;&quot;&gt;_by_category&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_from_millis_to_seconds&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurement&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# assumption: there is just 1 time metric:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;len&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metrics&lt;/span&gt;) &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;raise&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;RuntimeError&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Expected 1 time metric, but have: &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metrics&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_create_bar_chart&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Response time by Prompt Category&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;yaxis_title&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Response time (seconds)&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurements_by_category&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;metrics&lt;span style=&quot;color: #9cdcfe;&quot;&gt;_by_category&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;unit_short&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;s&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;create_figures&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mlflow_metrics&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MetricAndMeasure&lt;/span&gt;], &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;bool&lt;/span&gt;&lt;/div&gt;&lt;div&gt;) -&amp;gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MLflowFigure&lt;/span&gt;]:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; [&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_create_summary_figure&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;mlflow_metrics&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;mlflow_metrics&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ]&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;This produces a bar chart like this, showing all the metrics for that run, side-by-side.&lt;/p&gt;&lt;p&gt;- the bars are colored according to their value (higher value = lighter hues)&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhx__B2HUU4KMiIvsG-ZLcRIzMcDX-U_jDPoN-yoLzYFMl7nhEnob8iJ_MC8cwA6UDhhHqplStM60yFNFjoZjeRxD82yESWdw5sLNNVI9vN2y0DVqyXoYOvXDCYfJ0-2mqt0d4Vl5mmX4gj8GXzM7dQcZvzloqOH2iO9M8E8_68E-7hS4fIJcbYuLUMpF0N&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;769&quot; data-original-width=&quot;1369&quot; height=&quot;273&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEhx__B2HUU4KMiIvsG-ZLcRIzMcDX-U_jDPoN-yoLzYFMl7nhEnob8iJ_MC8cwA6UDhhHqplStM60yFNFjoZjeRxD82yESWdw5sLNNVI9vN2y0DVqyXoYOvXDCYfJ0-2mqt0d4Vl5mmX4gj8GXzM7dQcZvzloqOH2iO9M8E8_68E-7hS4fIJcbYuLUMpF0N=w485-h273&quot; width=&quot;485&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Grouped Bar Chart&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;A more advanced technique is to take the categorized metrics (where the metric name is prefixed by a category) and then plot a grouped bar chart, with one group for each category. This allows for comparing categories across multiple metrics (or attributes).&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;logging&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;matplotlib&lt;/span&gt;.&lt;span style=&quot;color: #4ec9b0;&quot;&gt;figure&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Figure&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;matplotlib&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;pyplot&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;plt&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;numpy&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;as&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;np&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;logger&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;logging&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;getLogger&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;__name__&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MLflowFigure&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;tuple&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;Figure&lt;/span&gt;] &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# title and figure&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MetricAndMeasure&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;tuple&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;float&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;None&lt;/span&gt;]&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_create_grouped_bar_chart&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;title&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;yaxis_title&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;],&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;dict&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;float&lt;/span&gt;]],&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;bool&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;decimal_places&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;2&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;) -&amp;gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;MLflowFigure&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;x&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;np&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;arange&lt;/span&gt;(&lt;span style=&quot;color: #dcdcaa;&quot;&gt;len&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;)) &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# the label locations&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;bar_width&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0.1&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;multiplier&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;gap_between_bars&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0.02&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fig&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;plt&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;subplots&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;layout&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;constrained&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;figsize&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;(&lt;span style=&quot;color: #b5cea8;&quot;&gt;21&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;7&lt;/span&gt;))&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;attribute&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurement&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;items&lt;/span&gt;():&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;offset&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;bar_width&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;gap_between_bars&lt;/span&gt;) &lt;span style=&quot;color: #d4d4d4;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;multiplier&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurement&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; [&lt;span style=&quot;color: #dcdcaa;&quot;&gt;round&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;y&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;decimal_places&lt;/span&gt;) &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;y&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurement&lt;/span&gt;]&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;rects&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bar&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;x&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;offset&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;measurement&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;bar_width&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;label&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;attribute&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;bar_label&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;rects&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;padding&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #b5cea8;&quot;&gt;3&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;multiplier&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;+=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# Add some text for labels, title and custom x-axis tick labels, etc.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;set_ylabel&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;yaxis_title&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;set_title&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;title&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;set_xticks&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;x&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;+&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;bar_width&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;legend&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;loc&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;upper left&quot;&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ncols&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #dcdcaa;&quot;&gt;len&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;keys&lt;/span&gt;()))&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;y_max&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0.0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;]:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;y_max&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;max&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;y_max&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;ax&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;set_ylim&lt;/span&gt;(&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;y_max&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1.2&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;plt&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;show&lt;/span&gt;()&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; (&lt;span style=&quot;color: #9cdcfe;&quot;&gt;title&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;fig&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #4fc1ff;&quot;&gt;METRIC_NAME_DIVIDER&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;__&quot;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_create_accuracy_summary_figure&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;accuracy_metrics&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MetricAndMeasure&lt;/span&gt;], &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;bool&lt;/span&gt;) -&amp;gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;MLflowFigure&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# example input: [(&#39;category1__entity_count_accuracy&#39;, 1.0), (&#39;category1__attribute_count_accuracy&#39;, 1.0)]&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;dict&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;dict&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;float&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;|&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;None&lt;/span&gt;]] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {}&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;all_metrics&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; []&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;accuracy_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;METRIC_NAME_DIVIDER&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;]: &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# like &#39;category1__attribute_count_accuracy&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; [&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;].&lt;span style=&quot;color: #dcdcaa;&quot;&gt;split&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;__&quot;&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;: &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;]}&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;else&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;existing&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;existing&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;all_metrics&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;append&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;else&lt;/span&gt;: &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# like &#39;overall_accuracy&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;: &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category_and_metric&lt;/span&gt;[&lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;]}&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;all_metrics&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;append&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# To have same shape of data for plotting, fill in any missing metrics as zero:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;all_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;existing&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;existing&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;existing&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0.0&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #6a9955;&quot;&gt;# project to the structure required by plot:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;shared_metrics&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; []&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;dict&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;str&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #4ec9b0;&quot;&gt;float&lt;/span&gt;]] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {}&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;grouped_and_named_metrics = &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; []&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;append&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sorted_metrics&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;].&lt;span style=&quot;color: #dcdcaa;&quot;&gt;keys&lt;/span&gt;())&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sorted_metrics&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;sort&lt;/span&gt;() &amp;nbsp;&lt;span style=&quot;color: #6a9955;&quot;&gt;# sort the metrics to ensure they are consistent across categories&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;shared_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;shared_metrics&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sorted_metrics&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;elif&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;shared_metrics&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;!=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sorted_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;raise&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;RuntimeError&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #569cd6;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Figure data is misaligned: shared_metrics=&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;shared_metrics&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;, new metrics=&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;sorted_metrics&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;for&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;sorted_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;in&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;] &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; []&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_and_named_metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;category&lt;/span&gt;][&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;not&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0.0&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;metric&lt;/span&gt;].&lt;span style=&quot;color: #dcdcaa;&quot;&gt;append&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;value&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;if&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;categories: &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;metrics: &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;shared_metrics&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;print&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;grouped_metrics: &lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;&lt;/span&gt;)&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_create_grouped_bar_chart&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;title&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Accuracy by Prompt Category&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;yaxis_title&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #ce9178;&quot;&gt;&quot;Accuracy&quot;&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;categories&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;grouped_metrics&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;def&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;create_figures&lt;/span&gt;(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mlflow_metrics&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MetricAndMeasure&lt;/span&gt;], &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;: &lt;span style=&quot;color: #4ec9b0;&quot;&gt;bool&lt;/span&gt;&lt;/div&gt;&lt;div&gt;) -&amp;gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;list&lt;/span&gt;[&lt;span style=&quot;color: #9cdcfe;&quot;&gt;MLflowFigure&lt;/span&gt;]:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; [&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;_create_accuracy_summary_figure&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;accuracy_metrics&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;mlflow_metrics&lt;/span&gt;, &lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;&lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;is_debug&lt;/span&gt;),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ]&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;This produces a grouped bar chart, similar to this:&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEixkwcrfy6T9L9E6f-p1cHVVc_K3FIejKKkCHxRFb8EM4Qp1iVWivsoKHSQ9WcspGGMLLOEylL0jPGgIQjAr5q9YdqIEgKckyiDAag-sKgxvqK-YUnAWgIKeAfXL9vYdhSf7BpP6Uv42G1aOCl0dkAjNk1qUqOX3M6ppL4YKtTMYKpDao-vB5nsqx99iuk-&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;771&quot; data-original-width=&quot;1343&quot; height=&quot;312&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEixkwcrfy6T9L9E6f-p1cHVVc_K3FIejKKkCHxRFb8EM4Qp1iVWivsoKHSQ9WcspGGMLLOEylL0jPGgIQjAr5q9YdqIEgKckyiDAag-sKgxvqK-YUnAWgIKeAfXL9vYdhSf7BpP6Uv42G1aOCl0dkAjNk1qUqOX3M6ppL4YKtTMYKpDao-vB5nsqx99iuk-=w543-h312&quot; width=&quot;543&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;note: since the code involves some projection of data, it can be useful to cover this with unit tests.&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Summary&lt;/h2&gt;&lt;p&gt;Creating custom figures for MLflow is a powerful technique to gain more insights into your ML evaluation results, and better communicate the results to colleagues.&lt;/p&gt;&lt;p&gt;For more information, please see the&amp;nbsp;&lt;a href=&quot;https://mlflow.org/docs/latest/traditional-ml/hyperparameter-tuning-with-child-runs/notebooks/logging-plots-in-mlflow.html#Logging-Visualizations-with-MLflow&quot; target=&quot;_blank&quot;&gt;MLflow documentation&lt;/a&gt;.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/5107568561723965030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/12/adding-custom-summary-charts-to-mlflow.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/5107568561723965030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/5107568561723965030'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/12/adding-custom-summary-charts-to-mlflow.html' title='Adding custom &#39;summary&#39; charts to MLflow: simple bar chart and &#39;grouped&#39; bar chart'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEhx__B2HUU4KMiIvsG-ZLcRIzMcDX-U_jDPoN-yoLzYFMl7nhEnob8iJ_MC8cwA6UDhhHqplStM60yFNFjoZjeRxD82yESWdw5sLNNVI9vN2y0DVqyXoYOvXDCYfJ0-2mqt0d4Vl5mmX4gj8GXzM7dQcZvzloqOH2iO9M8E8_68E-7hS4fIJcbYuLUMpF0N=s72-w485-h273-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-4881779024011431385</id><published>2024-10-11T18:02:00.001+01:00</published><updated>2024-10-11T18:02:18.269+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Show the source code of a Python module (also in Jupyter)</title><content type='html'>&lt;h1 style=&quot;text-align: left;&quot;&gt;How to show the source code of Python module (also in Jupyter)&lt;/h1&gt;&lt;p&gt;- using the &lt;b&gt;inspect &lt;/b&gt;module&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Example: to show the source code for a &#39;utils&#39; module:&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;import utils&lt;br /&gt;import inspect&lt;br /&gt;&lt;br /&gt;lines = inspect.getsource(utils)&lt;br /&gt;print(lines)&lt;/p&gt;&lt;p&gt;# in Jupyter, use display:&lt;br /&gt;# display(lines)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/4881779024011431385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/10/show-source-code-of-python-module-also.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4881779024011431385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4881779024011431385'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/10/show-source-code-of-python-module-also.html' title='Show the source code of a Python module (also in Jupyter)'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-860290362902383310</id><published>2024-09-05T16:13:00.003+01:00</published><updated>2024-09-05T16:13:25.509+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><title type='text'>Articles about tests involving 3rd party services - End-to-end instead of Integration or Contract tests</title><content type='html'>&lt;p&gt;Integration tests for 3rd part APIs&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://axelhodler.medium.com/integration-tests-for-third-party-apis-dab67c52e352&quot;&gt;https://axelhodler.medium.com/integration-tests-for-third-party-apis-dab67c52e352&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Regression and Functional tests are meaningless&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://gerg.dev/2020/08/regression-and-functional-tests-are-meaningless/&quot;&gt;https://gerg.dev/2020/08/regression-and-functional-tests-are-meaningless/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Testing 3rd party services&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.reddit.com/r/ExperiencedDevs/comments/1aoh9v4/testing_3rd_party_services/&quot;&gt;https://www.reddit.com/r/ExperiencedDevs/comments/1aoh9v4/testing_3rd_party_services/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/860290362902383310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/09/articles-about-tests-involving-3rd.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/860290362902383310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/860290362902383310'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/09/articles-about-tests-involving-3rd.html' title='Articles about tests involving 3rd party services - End-to-end instead of Integration or Contract tests'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-4594614541237983456</id><published>2024-06-26T14:29:00.002+01:00</published><updated>2024-06-26T14:29:52.002+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Data analysis"/><category scheme="http://www.blogger.com/atom/ns#" term="Jupyter"/><title type='text'>Exporting a Jupyter notebook without the input code</title><content type='html'>&lt;p&gt;1. export to HTML&lt;/p&gt;&lt;p&gt;2. open in a browser (Edge or Chrome)&lt;/p&gt;&lt;p&gt;3. paste JavaScript code into the console, to remove the input fields:&lt;/p&gt;&lt;p&gt;document.querySelectorAll(&quot;div.jp-InputArea.jp-Cell-inputArea&quot;).forEach(function(a){a.remove()})&lt;/p&gt;&lt;p&gt;- see&amp;nbsp;&lt;a href=&quot;https://stackoverflow.com/questions/34818723/export-notebook-to-pdf-without-code&quot;&gt;https://stackoverflow.com/questions/34818723/export-notebook-to-pdf-without-code&lt;/a&gt;&lt;/p&gt;&lt;p&gt;4. save as HTML, or print to PDF&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/4594614541237983456/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/06/exporting-jupyter-notebook-without.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4594614541237983456'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4594614541237983456'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/06/exporting-jupyter-notebook-without.html' title='Exporting a Jupyter notebook without the input code'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-2985603078836695104</id><published>2024-06-21T15:33:00.004+01:00</published><updated>2024-06-21T15:40:36.046+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Data Visualization"/><category scheme="http://www.blogger.com/atom/ns#" term="Maps"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>World maps in Python - free map resources</title><content type='html'>&lt;p&gt;Map files (ZIP):&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://www.naturalearthdata.com/&quot;&gt;Natural Earth - Free vector and raster map data at 1:10m, 1:50m, and 1:110m scales (naturalearthdata.com)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The code below uses &quot;Admin 0 – Countries&quot; although other map files should also work, if they have countries in their &#39;NAME&#39; column.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Python:&lt;/p&gt;&lt;p&gt;Installing packages [&lt;a href=&quot;https://pypi.org/project/geopandas/&quot; target=&quot;_blank&quot;&gt;geopandas&lt;/a&gt;] [&lt;a href=&quot;https://pypi.org/project/seaborn/&quot; target=&quot;_blank&quot;&gt;seaborn&lt;/a&gt;]:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;pip install geopandas seaborn&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Loading the world map:&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;import geopandas as gpd&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# load the low resolution world map&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;world = gpd.read_file(&quot;./resources/ne_110m_admin_0_countries.zip&quot;) # ref https://www.naturalearthdata.com/downloads/110m-cultural-vectors/&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;all_countries = world[&#39;NAME&#39;]&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;def prepare_world_map_countries(country_names_to_highlight):&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; countries_joined = &#39;|&#39;.join(country_names_to_highlight))&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; countries_joined&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; countries = world[world[&#39;NAME&#39;].str.contains(countries_joined) == True]&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; countries = list(countries[&#39;NAME&#39;])&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; return countries&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Plotting the world map:&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;import matplotlib.patches as mpatches&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;import seaborn as sns&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;def plot_world_map(countries, title):&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; # initialize a new figure&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; fig = plt.figure(figsize=(20, 10))&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ax = fig.add_subplot()&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; colors = sns.color_palette(&quot;husl&quot;, len(all_countries))&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; patches = []&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; # loop over the continent names and corresponding colors&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; for (country_name, color) in list(zip(all_countries, colors)):&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # grab all countries that belong to the continent, then plot each of the&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # continents, giving each a unique color&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continent = world[world[&quot;NAME&quot;] == country_name]&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; is_active_country = country_name in countries&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; actual_color = color if is_active_country else &#39;white&#39;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continent.plot(ax=ax, color=actual_color, edgecolor=&quot;black&quot;, alpha=0.5)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # generate a patch for the current continent&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; patch = mpatches.Patch(label=country_name, color=color)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if is_active_country:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; patches.append(patch)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; # add the patches to the map&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ax.legend(handles=patches, loc=&quot;lower left&quot;, ncol=4)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; # turn off axis ticks&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ax.set_xticks([])&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ax.set_yticks([])&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; # set the plot title&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; plt.title(title)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; plt.show()&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Example execution:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;country_names_to_highlight = [&#39;United States of America&#39;,&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp;&#39;South Africa&#39;,&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp;&#39;Brazil&#39;,&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&#39;China&#39;,&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&#39;Australia&#39;,&amp;nbsp;&lt;/span&gt;&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp;&#39;Colombia&#39;,&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp;&#39;France&#39;]&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;plot_world_map(country_names_to_highlight, &quot;Countries Visited&quot;)&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;Resulting map:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgIJuiPJuVDyBti51wvCEYCD6GgFW7WseR3u_HSHr9bqTHfTN1CeiWH4m05CTlxtf8HAvzex9FGvzPPAvMnKlug_toUBOmruLYbfqe2PrI2fsOj6_4K60Hhr4MGsE5Uskz3h7m5J5VNn5EhLpr6AK_Hq_5EgVwZoiSIbaGeCz3iwggbnE021Rgrwxqsfc9e&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;797&quot; data-original-width=&quot;1570&quot; height=&quot;284&quot; src=&quot;https://blogger.googleusercontent.com/img/a/AVvXsEgIJuiPJuVDyBti51wvCEYCD6GgFW7WseR3u_HSHr9bqTHfTN1CeiWH4m05CTlxtf8HAvzex9FGvzPPAvMnKlug_toUBOmruLYbfqe2PrI2fsOj6_4K60Hhr4MGsE5Uskz3h7m5J5VNn5EhLpr6AK_Hq_5EgVwZoiSIbaGeCz3iwggbnE021Rgrwxqsfc9e=w562-h284&quot; width=&quot;562&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/2985603078836695104/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/06/world-maps-in-python-free.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/2985603078836695104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/2985603078836695104'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/06/world-maps-in-python-free.html' title='World maps in Python - free map resources'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/a/AVvXsEgIJuiPJuVDyBti51wvCEYCD6GgFW7WseR3u_HSHr9bqTHfTN1CeiWH4m05CTlxtf8HAvzex9FGvzPPAvMnKlug_toUBOmruLYbfqe2PrI2fsOj6_4K60Hhr4MGsE5Uskz3h7m5J5VNn5EhLpr6AK_Hq_5EgVwZoiSIbaGeCz3iwggbnE021Rgrwxqsfc9e=s72-w562-h284-c" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-6882536220206606885</id><published>2024-06-10T11:11:00.005+01:00</published><updated>2024-06-21T14:35:49.666+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Pandas"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Avoiding SettingsWithCopyWarning from pandas when adding a column as function of other columns</title><content type='html'>&lt;div&gt;Adding a new column as a function of other columns can hit performance issues, and more seriously can be unreliable if implemented incorrectly.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For simple cases, a vector based filter can efficiently add the values of the new column, via loc():&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;df.loc[df[&#39;eri_white&#39;]==1,&#39;race_label&#39;] = &#39;White&#39;&lt;/span&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However more complicated cases can require a function that checks each cell value.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Example:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;def get_label(text):&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; if is_css(text):&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; return &#39;css&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; if is_json(text):&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; return &#39;json&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; return &#39;other&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Applying this function via &#39;apply&#39; and then using that result to assign to a new column, triggers the SettingWithCopyWarning&amp;nbsp;warning from pandas:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;dfSourceLanguages[&#39;label&#39;] = dfSourceLanguages.apply(lambda r: get_label(r[&#39;text&#39;]), axis=1)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The SettingWithCopyWarning of pandas catches this and other cases where the code is not efficient and might not be reliable:&lt;/div&gt;&lt;br /&gt;&lt;i&gt;&lt;span style=&quot;font-family: courier;&quot;&gt; SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: &lt;a href=&quot;https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy&quot;&gt;https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy&lt;/a&gt; dfSourceLanguages[&#39;label&#39;] = dfSourceLanguages.apply(lambda r: get_label(r[&#39;text&#39;]), axis=1)&lt;/span&gt;&lt;/i&gt;&lt;div&gt;&lt;i&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This warning also occurs when using map():&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;dfSourceLanguages[&#39;label&#39;] = dfSourceLanguages[&#39;text&#39;].map(get_label)&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;---&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Another approach: use df.assign()&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# Assigns a new column &#39;label&#39; via the lambda function&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# - applies _get_label() to the series &#39;row.text&#39;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;df = df.assign(&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; label = lambda row: row.text.apply(_get_label)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/6882536220206606885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/06/avoiding-settingswithcopywarning-from.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/6882536220206606885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/6882536220206606885'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/06/avoiding-settingswithcopywarning-from.html' title='Avoiding SettingsWithCopyWarning from pandas when adding a column as function of other columns'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-329833558069849416</id><published>2024-06-10T08:51:00.004+01:00</published><updated>2025-03-25T08:27:20.549+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Data analysis"/><category scheme="http://www.blogger.com/atom/ns#" term="Jupyter"/><category scheme="http://www.blogger.com/atom/ns#" term="Pandas"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Expanding columns and rows in pandas results in Jupyter notebook</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;Expanding column widths&lt;/h2&gt;&lt;p&gt;By default, when executed in a Jupyter notebook, pandas results have their columns truncated to about 200px.&lt;/p&gt;&lt;p&gt;This sometimes obscures interesting parts of the results&lt;/p&gt;&lt;p&gt;One way to expand the column widths is to increase the max-width:&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;from&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;pandas&lt;/span&gt; &lt;span style=&quot;color: #c586c0;&quot;&gt;import&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;option_context&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #c586c0;&quot;&gt;with&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;option_context&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;display.max_colwidth&#39;&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;400&lt;/span&gt;):&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;display&lt;/span&gt;(&lt;span style=&quot;color: #9cdcfe;&quot;&gt;df&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;head&lt;/span&gt;())&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;This example expands columns that have long values, up to 400px.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;Alternatively, select a small number of rows (for example via head()) and print the transpose:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: #1f1f1f; color: #dcdcaa; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; white-space: pre;&quot;&gt;display&lt;/span&gt;&lt;span style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; white-space: pre;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background-color: #1f1f1f; color: #9cdcfe; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; white-space: pre;&quot;&gt;df&lt;/span&gt;&lt;span style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; white-space: pre;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;background-color: #1f1f1f; color: #dcdcaa; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; white-space: pre;&quot;&gt;head&lt;/span&gt;&lt;span style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; white-space: pre;&quot;&gt;().T)&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Expanding row counts&lt;/h2&gt;&lt;p&gt;similarly, more rows can be displayed via this setting:&lt;/p&gt;&lt;div style=&quot;background-color: #1f1f1f; color: #cccccc; font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 14px; line-height: 19px; white-space: pre;&quot;&gt;&lt;span style=&quot;color: #4ec9b0;&quot;&gt;pd&lt;/span&gt;.&lt;span style=&quot;color: #dcdcaa;&quot;&gt;set_option&lt;/span&gt;(&lt;span style=&quot;color: #ce9178;&quot;&gt;&#39;display.max_rows&#39;&lt;/span&gt;, &lt;span style=&quot;color: #b5cea8;&quot;&gt;500&lt;/span&gt;) &lt;/div&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/329833558069849416/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/06/expanding-columns-in-pandas-results-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/329833558069849416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/329833558069849416'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/06/expanding-columns-in-pandas-results-in.html' title='Expanding columns and rows in pandas results in Jupyter notebook'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-3998685950979443905</id><published>2024-06-09T11:51:00.009+01:00</published><updated>2025-04-20T11:54:41.825+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="data"/><category scheme="http://www.blogger.com/atom/ns#" term="Pandas"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Converting a Python array to a pandas dataframe [multiplying data]</title><content type='html'>&lt;p&gt;Sometimes a Python array is simpler to generate or manipulate - but then we need to convert it to a Pandas dataframe for further processing:&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;pre class=&quot;graf graf--pre graf--preV2&quot; data-code-block-lang=&quot;java&quot; data-code-block-mode=&quot;1&quot; name=&quot;1001&quot; spellcheck=&quot;false&quot;&gt;&lt;span class=&quot;pre--content&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;import&lt;/span&gt; numpy as &lt;span class=&quot;hljs-type&quot;&gt;np&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre graf--preV2&quot; data-code-block-lang=&quot;java&quot; data-code-block-mode=&quot;1&quot; name=&quot;1001&quot; spellcheck=&quot;false&quot;&gt;&lt;span class=&quot;pre--content&quot;&gt;&lt;span class=&quot;hljs-type&quot;&gt;import pandas as &lt;/span&gt;&lt;/span&gt;pd&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre&quot;&gt;def convert_array_of_rows_to_dataframe(array_of_rows, columns):&lt;br /&gt;  np_array = np.array(array_of_rows)&lt;br /&gt;  dfOut = pd.DataFrame.from_records(np_array)&lt;br /&gt;  dfOut.columns = columns&lt;br /&gt;  return dfOut&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre&quot;&gt;&lt;br /&gt;&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre&quot;&gt;Example call:&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre&quot;&gt;my_array = [ [&#39;This is great&#39;, &#39;positive&#39;],&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre&quot;&gt;[&#39;This is terrible&#39;, &#39;negative&#39;]&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre&quot;&gt;]&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre&quot;&gt;df = convert_array_of_rows_to_dataframe(my_array, [&#39;text&#39;, &#39;label&#39;])&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre&quot;&gt;&lt;br /&gt;&lt;/pre&gt;A more complicated example is using Python code to &#39;multiply&#39; data from CSV, and then convert that to a dataframe:&lt;br /&gt;&lt;br /&gt;&lt;pre class=&quot;graf graf--pre&quot;&gt;&lt;pre class=&quot;graf graf--pre graf--preV2&quot; data-code-block-lang=&quot;java&quot; data-code-block-mode=&quot;1&quot; name=&quot;1001&quot; spellcheck=&quot;false&quot;&gt;&lt;span class=&quot;pre--content&quot;&gt;&lt;br /&gt;&lt;span class=&quot;hljs-variable&quot;&gt;dfIn&lt;/span&gt; &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; pd.read_csv(&lt;span class=&quot;hljs-string&quot;&gt;&quot;../data/nouns.csv&quot;&lt;/span&gt;)&lt;br /&gt;multiplied_rows = []&lt;br /&gt;dfIn.reset_index()&lt;br /&gt;&lt;br /&gt;phrases = [&lt;/span&gt;&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre graf--preV2&quot; data-code-block-lang=&quot;java&quot; data-code-block-mode=&quot;1&quot; name=&quot;1001&quot; spellcheck=&quot;false&quot;&gt;&quot;You are a NOUN&quot;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;What a NOUN&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;Don&#39;t be such a NOUN&quot;&lt;/span&gt;,
&quot;This waiter is a NOUN.&quot;,
&quot;She was a NOUN today.&quot;,
&quot;The company here are NOUNs.&quot;,
&quot;That director was a NOUN.&quot;
]&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre graf--preV2&quot; data-code-block-lang=&quot;java&quot; data-code-block-mode=&quot;1&quot; name=&quot;1001&quot; spellcheck=&quot;false&quot;&gt;&lt;span class=&quot;pre--content&quot;&gt;&lt;br /&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; _, row in dfIn.iterrows():&lt;br /&gt;  &lt;span class=&quot;hljs-keyword&quot;&gt;for&lt;/span&gt; template in phrases:&lt;br /&gt;    multiplied_rows.append([template.replace(&lt;span class=&quot;hljs-string&quot;&gt;&quot;NOUN&quot;&lt;/span&gt;, row[&lt;span class=&quot;hljs-string&quot;&gt;&#39;text&#39;&lt;/span&gt;].lower())])&lt;br /&gt;&lt;br /&gt;dfMultiplied &lt;span class=&quot;hljs-operator&quot;&gt;=&lt;/span&gt; convert_array_of_rows_to_dataframe(offensive_multiplied_rows, [&lt;span class=&quot;hljs-string&quot;&gt;&#39;text&#39;&lt;/span&gt;])&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre graf--preV2&quot; data-code-block-lang=&quot;java&quot; data-code-block-mode=&quot;1&quot; name=&quot;1001&quot; spellcheck=&quot;false&quot;&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class=&quot;pre--content&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;Here are some other articles about Pandas:&lt;/span&gt;&lt;/p&gt;&lt;pre class=&quot;graf graf--pre graf--preV2&quot; data-code-block-lang=&quot;java&quot; data-code-block-mode=&quot;1&quot; name=&quot;1001&quot; spellcheck=&quot;false&quot;&gt;&lt;span class=&quot;pre--content&quot;&gt;- &lt;a href=&quot;https://www.kdnuggets.com/10-pandas-one-liners-for-exploratory-data-analysis&quot;&gt;https://www.kdnuggets.com/10-pandas-one-liners-for-exploratory-data-analysis&lt;/a&gt;&lt;/span&gt;&lt;/pre&gt;&lt;pre class=&quot;graf graf--pre graf--preV2&quot; data-code-block-lang=&quot;java&quot; data-code-block-mode=&quot;1&quot; name=&quot;1001&quot; spellcheck=&quot;false&quot;&gt;&lt;span class=&quot;pre--content&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/3998685950979443905/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/06/converting-python-array-to-pandas.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/3998685950979443905'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/3998685950979443905'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/06/converting-python-array-to-pandas.html' title='Converting a Python array to a pandas dataframe [multiplying data]'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-4560442307240383380</id><published>2024-05-22T12:59:00.004+01:00</published><updated>2024-06-09T11:53:51.591+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu"/><title type='text'>Ubuntu apt (and apt-get) tips</title><content type='html'>&lt;p&gt;
Possibly apt is generally more suitable as a higher-level tool than apt-get:
&lt;/p&gt;
&lt;div class=&quot;g&quot; style=&quot;-webkit-text-stroke-width: 0px; background-color: #1f1f1f; clear: both; color: #e8e8e8; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; line-height: 1.58; margin: 0px; orphans: 2; padding-bottom: 0px; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; width: 600px; word-spacing: 0px;&quot;&gt;&lt;div data-hveid=&quot;CBMQAA&quot; data-ved=&quot;2ahUKEwisz4-arc6GAxX4hv0HHTlqBV8QFSgAegQIExAA&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;tF2Cxc&quot; style=&quot;clear: both; padding-bottom: 0px; position: relative;&quot;&gt;&lt;div class=&quot;yuRUbf&quot; style=&quot;font-size: small; font-weight: normal; line-height: 1.58;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div class=&quot;wDYxhc&quot; data-md=&quot;61&quot; lang=&quot;en-NL&quot; style=&quot;-webkit-text-stroke-width: 0px; background-color: #1f1f1f; border-radius: 8px; clear: none; color: #e8e8e8; font-family: arial, sans-serif; font-size: 14px; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;&quot;&gt;&lt;div aria-level=&quot;3&quot; class=&quot;LGOjhe&quot; data-attrid=&quot;wa:/description&quot; data-hveid=&quot;CBoQAA&quot; role=&quot;heading&quot; style=&quot;overflow: hidden; padding-bottom: 20px;&quot;&gt;&lt;span style=&quot;color: var(--YLNNHc); font-family: &amp;quot;Google Sans&amp;quot;, arial, sans-serif; font-size: 20px;&quot;&gt;The apt command line tool provides a higher-level user interface for end users with intuitive commands, resulting behaviors, and security features. In contrast, the command apt-get is a low-level interface that communicates more closely with core Linux processes.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;apt package installer has a &#39;fix broken install&#39; option that could be worth trying:&lt;/p&gt;&lt;p&gt;&lt;span face=&quot;ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, &amp;quot;Liberation Mono&amp;quot;, &amp;quot;Courier New&amp;quot;, monospace&quot; style=&quot;background-color: #f3f4f6; color: #111827; font-size: 16px;&quot;&gt;sudo apt --fix-broken install&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/4560442307240383380/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/05/ubuntu-apt-tips.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4560442307240383380'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/4560442307240383380'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/05/ubuntu-apt-tips.html' title='Ubuntu apt (and apt-get) tips'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-7451100166156145184</id><published>2024-04-14T09:24:00.008+01:00</published><updated>2024-04-14T09:35:21.643+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="Cloud"/><title type='text'>Comparing Costs of Cloud Providers - vantage.sh</title><content type='html'>&lt;p&gt;&lt;a href=&quot;http://vantage.sh&quot;&gt;vantage.sh&lt;/a&gt; is a free site that helps compare the costs of similar services on the main cloud providers.&lt;/p&gt;&lt;p&gt;&lt;span face=&quot;Roboto, Arial, sans-serif&quot; style=&quot;background-color: white; color: #3c4043; font-size: 14px; letter-spacing: 0.2px; white-space-collapse: preserve;&quot;&gt;Comparing Amazon AWS instances: &lt;/span&gt;&lt;a href=&quot;https://www.google.com/url?q=https://instances.vantage.sh/&amp;amp;sa=D&amp;amp;source=calendar&amp;amp;usd=2&amp;amp;usg=AOvVaw0vBtKA66GazWxo2HB3DBH8&quot; style=&quot;background-color: white; color: #1a73e8; font-family: Roboto, Arial, sans-serif; font-size: 14px; letter-spacing: 0.2px; white-space-collapse: preserve;&quot; target=&quot;_blank&quot;&gt;https://instances.vantage.sh/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;AWS RDS instances - &lt;a href=&quot;https://instances.vantage.sh/rds/&quot;&gt;https://instances.vantage.sh/rds/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;AWS ElastiCache instances - &lt;a href=&quot;https://instances.vantage.sh/cache/&quot;&gt;https://instances.vantage.sh/cache/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;AWS Redshift instances - &lt;a href=&quot;https://instances.vantage.sh/redshift/&quot;&gt;https://instances.vantage.sh/redshift/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;AWS OpenSearch instances - &lt;a href=&quot;https://instances.vantage.sh/opensearch/&quot;&gt;https://instances.vantage.sh/opensearch/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;vantage.sh also provides a cost monitoring service, where you can integrate vantage.sh with your cloud environment - this is possible with many cloud providers (AWS, Azure...) -&amp;nbsp;&lt;a href=&quot;https://www.vantage.sh/&quot;&gt;https://www.vantage.sh/&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;i&gt;- note: the author has no affiliation with vantage.sh&lt;/i&gt;&lt;/div&gt;&lt;div&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/7451100166156145184/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/04/comparing-costs-of-cloud-providers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/7451100166156145184'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/7451100166156145184'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/04/comparing-costs-of-cloud-providers.html' title='Comparing Costs of Cloud Providers - vantage.sh'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-5860432121605905121</id><published>2024-04-14T09:19:00.004+01:00</published><updated>2024-04-14T09:19:56.741+01:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C#"/><category scheme="http://www.blogger.com/atom/ns#" term="Logging"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Structured Logging (Semantic Logging) in Python and C#</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;Why Structured logging:&lt;/h2&gt;&lt;p&gt;&lt;b&gt;1. machine parseable logs:&lt;/b&gt;&lt;/p&gt;&lt;p&gt;When a log is automatically parseable, this enables viewing, searching and filtering.&lt;/p&gt;&lt;p&gt;A parseable log can also enable further processing or display (for example: command line tools that output parseable logs are easier to automate via another tool such as a desktop app with graphical user interface).&lt;/p&gt;&lt;p&gt;&lt;b&gt;2. logged events have context&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Adding more context to each log event helps later debugging. Why: when programming, it can be difficult to know what info to add that would help future debugging.&lt;/p&gt;&lt;p&gt;Also see: &lt;a href=&quot;https://www.structlog.org/en/24.1.0/why.html#why&quot; target=&quot;_blank&quot;&gt;the &#39;why&#39; of Python&#39;s structlog&lt;/a&gt;.&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Structured logging in C#:&lt;/h2&gt;&lt;p&gt;&lt;a href=&quot;https://serilog.net/&quot; target=&quot;_blank&quot;&gt;serilog&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/serilog/serilog&quot; target=&quot;_blank&quot;&gt;serilog on github&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Further reading - C#&lt;/h3&gt;&lt;p&gt;- &lt;a href=&quot;https://learn.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-8.0&quot; target=&quot;_blank&quot;&gt;Logging in .NET Core and ASP.NET Core&lt;/a&gt;&lt;/p&gt;-&amp;nbsp;&lt;a href=&quot;https://medium.com/@stavsofer/structured-logging-and-logs-management-asp-net-core-serilog-seq-61109f740696&quot; target=&quot;_blank&quot;&gt;Structured Logging and Logs Management. A case study using ASP.NET Core, Serilog &amp;amp; Seq&lt;/a&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Structured logging in Python:&lt;/h2&gt;&lt;div&gt;&lt;a href=&quot;https://github.com/hynek/structlog&quot; target=&quot;_blank&quot;&gt;structlog&lt;/a&gt; - Structured Logging for Python&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;Further reading - Python&lt;/h3&gt;&lt;p&gt;- &lt;a href=&quot;https://stackoverflow.com/questions/48170682/can-structured-logging-be-done-with-pythons-standard-library&quot; target=&quot;_blank&quot;&gt;Can structured logging be done with Pythons standard library&lt;/a&gt;&lt;/p&gt;&lt;p&gt;-&amp;nbsp;&lt;a href=&quot;https://docs.python.org/3/howto/logging-cookbook.html&quot; target=&quot;_blank&quot;&gt;Logging Cookbook&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/5860432121605905121/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/04/structured-logging-semantic-logging-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/5860432121605905121'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/5860432121605905121'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/04/structured-logging-semantic-logging-in.html' title='Structured Logging (Semantic Logging) in Python and C#'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-8498870972780906820</id><published>2024-02-21T21:14:00.008+00:00</published><updated>2024-02-21T21:14:50.654+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Clean Code"/><category scheme="http://www.blogger.com/atom/ns#" term="Code analysis"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="Tools"/><title type='text'>Scanning Python code for security issues via Snyk: the ‘industrial strength’ option</title><content type='html'>&lt;h1 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; white-space-collapse: preserve;&quot;&gt;Scanning Python code for security issues via Snyk: the ‘industrial strength’ option&lt;/span&gt;&lt;/h1&gt;&lt;span id=&quot;docs-internal-guid-85f59b69-7fff-f288-7638-69857f231842&quot;&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;i&gt;note: I am not at all affiliated to Snyk - just a fan of its quality features.&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Snyk is a code scanning tool capable of detecting &lt;/span&gt;&lt;a href=&quot;https://owasp.org/www-project-top-ten/&quot; style=&quot;text-decoration-line: none;&quot;&gt;&lt;span style=&quot;color: #1155cc; font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;OWASP issues&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt; (Open Worldwide Application Security Project), following the CWE-NN standard (&lt;/span&gt;&lt;a href=&quot;https://cwe.mitre.org/&quot; style=&quot;text-decoration-line: none;&quot;&gt;&lt;span style=&quot;color: #1155cc; font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Common Weakness Enumeration&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;) for identifying code security issues.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;At time of writing, there is a free plan for individuals and small teams: &lt;/span&gt;&lt;a href=&quot;https://snyk.io/plans/&quot; style=&quot;text-decoration-line: none;&quot;&gt;&lt;span style=&quot;color: #1155cc; font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;https://snyk.io/plans/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Snyk supports many languages - here is the section for Python:&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 0; margin-top: 0; padding-inline-start: 48px;&quot;&gt;&lt;li aria-level=&quot;1&quot; dir=&quot;ltr&quot; style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; list-style-type: disc; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;p dir=&quot;ltr&quot; role=&quot;presentation&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;a href=&quot;https://snyk.io/platform/snyk-python-security/&quot; style=&quot;text-decoration-line: none;&quot;&gt;&lt;span style=&quot;color: #1155cc; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-decoration-line: underline; text-decoration-skip-ink: none; text-wrap: wrap; vertical-align: baseline;&quot;&gt;https://snyk.io/platform/snyk-python-security/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;To add a Python repository to Snyk for scanning:&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;ul style=&quot;margin-bottom: 0; margin-top: 0; padding-inline-start: 48px;&quot;&gt;&lt;li aria-level=&quot;1&quot; dir=&quot;ltr&quot; style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; list-style-type: disc; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;p dir=&quot;ltr&quot; role=&quot;presentation&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-wrap: wrap; vertical-align: baseline;&quot;&gt;The project must have a setup.py and setup.cfg file, describing the project and its dependencies.&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;
Note: normally setup.py and setup.cfg files are a modern way to describe how your code would be released as a Python package (for example to publish on pypi.org). However, even if you do not intend to publish your code as a package, I found it necessary to add these files.&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Otherwise, I found Snyk does not recognise the project as a Python project.&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;A minimal setup.cfg file:&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 14.6667px; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;[egg_info]
egg_base = .

[tool:pytest]
testpaths = .&lt;/span&gt;&lt;span style=&quot;font-family: Arial, sans-serif;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; white-space-collapse: preserve;&quot;&gt;note:&lt;/span&gt;&lt;/p&gt;&lt;ul style=&quot;margin-bottom: 0; margin-top: 0; padding-inline-start: 48px;&quot;&gt;&lt;li aria-level=&quot;1&quot; dir=&quot;ltr&quot; style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; list-style-type: disc; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;p dir=&quot;ltr&quot; role=&quot;presentation&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-wrap: wrap; vertical-align: baseline;&quot;&gt;the [egg_info] section is used to specify the location of ‘egg package’ details on build&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li aria-level=&quot;1&quot; dir=&quot;ltr&quot; style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; list-style-type: disc; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;p dir=&quot;ltr&quot; role=&quot;presentation&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-wrap: wrap; vertical-align: baseline;&quot;&gt;the [tool:pytest] section specifies where to look for unit tests&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;A minimal setup.py file, including the dependencies of the project:&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 14.6667px; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;import io

from setuptools import find_packages
from setuptools import setup

with io.open(&quot;README.md&quot;, &quot;rt&quot;, encoding=&quot;utf8&quot;) as f:
    readme = f.read()

setup(
    name=&quot;my-app&quot;,
    description=&quot;My wonderful Python project.&quot;,
    long_description=readme,
    packages=find_packages(),
    include_package_data=True,
    zip_safe=False,
    install_requires=[],
    extras_require={&quot;dev&quot;: [&quot;flake8==6.1.0&quot;, &quot;pyvan==1.2.2&quot;]}
)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; white-space-collapse: preserve;&quot;&gt;Further reading about setup.py and setup.cfg files:&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;a href=&quot;https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/&quot; style=&quot;text-decoration-line: none;&quot;&gt;&lt;span style=&quot;color: #1155cc; font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;Good luck with your scanning!&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-family: Arial, sans-serif; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline; white-space-collapse: preserve;&quot;&gt;&lt;h2 style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline;&quot;&gt;Alternatives to Snyk&lt;/span&gt;&lt;/h2&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline;&quot;&gt;VeraCode: &lt;/span&gt;&lt;a href=&quot;https://docs.veracode.com/r/Python_Scan_Directives?gad_source=1&amp;amp;gclid=CjwKCAiA29auBhBxEiwAnKcSqicM0d3L55z3LpysWl714-zWC_6ymqCxIXdrZDE1Q9kjxCMB5yv-TxoCkBIQAvD_BwE&quot; style=&quot;text-decoration-line: none;&quot;&gt;&lt;span style=&quot;color: #1155cc; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline;&quot;&gt;https://docs.veracode.com/r/Python_Scan_Directives?gad_source=1&amp;amp;gclid=CjwKCAiA29auBhBxEiwAnKcSqicM0d3L55z3LpysWl714-zWC_6ymqCxIXdrZDE1Q9kjxCMB5yv-TxoCkBIQAvD_BwE&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;p dir=&quot;ltr&quot; style=&quot;line-height: 1.38; margin-bottom: 0pt; margin-top: 0pt;&quot;&gt;&lt;span style=&quot;font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; vertical-align: baseline;&quot;&gt;SonarQube: &lt;/span&gt;&lt;a href=&quot;https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/languages/python/&quot; style=&quot;text-decoration-line: none;&quot;&gt;&lt;span style=&quot;color: #1155cc; font-size: 11pt; font-variant-alternates: normal; font-variant-east-asian: normal; font-variant-numeric: normal; font-variant-position: normal; text-decoration-line: underline; text-decoration-skip-ink: none; vertical-align: baseline;&quot;&gt;https://docs.sonarsource.com/sonarqube/latest/analyzing-source-code/languages/python/&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/8498870972780906820/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/02/scanning-python-code-for-security.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/8498870972780906820'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/8498870972780906820'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/02/scanning-python-code-for-security.html' title='Scanning Python code for security issues via Snyk: the ‘industrial strength’ option'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-5447314198668995485</id><published>2024-02-14T16:25:00.004+00:00</published><updated>2024-02-14T16:25:46.592+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="AI"/><category scheme="http://www.blogger.com/atom/ns#" term="AWS"/><category scheme="http://www.blogger.com/atom/ns#" term="scripting"/><category scheme="http://www.blogger.com/atom/ns#" term="windows-scripting"/><title type='text'>AWS Translate via the AWS CLI command line - error: &#39;charmap&#39; codec can&#39;t encode characters</title><content type='html'>&lt;p&gt;With the AWS CLI tool, it is possible to perform machine translation on the command line:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;aws translate translate-text --region &quot;eu-west-1&quot; --source-language-code &quot;en&quot; --target-language-code &quot;es&quot; --text &quot;hello, world&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;OUTPUT:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;{&lt;br /&gt;&amp;nbsp; &amp;nbsp; &quot;TranslatedText&quot;: &quot;hola, mundo&quot;,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &quot;SourceLanguageCode&quot;: &quot;en&quot;,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &quot;TargetLanguageCode&quot;: &quot;es&quot;&lt;br /&gt;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;notes:&lt;/p&gt;&lt;p&gt;1. Multiple AWS accounts via &#39;--profile&#39; option&lt;/p&gt;&lt;p&gt;- if you have multiple AWS accounts, you can add multiple credentials in your .aws/config file:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;[default]&lt;br /&gt;region = eu-west-1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;[profile my-aws-1]&lt;br /&gt;aws_access_key_id = xxx-1&lt;br /&gt;aws_secret_access_key = yyy-1&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;[profile my-aws-2]&lt;br /&gt;aws_access_key_id = xxx-2&lt;br /&gt;aws_secret_access_key = yyy-2&lt;/span&gt;&lt;/p&gt;&lt;p&gt;- then, to use a particular AWS account, add the --profile option to AWS CLI tool:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;aws translate translate-text &lt;span style=&quot;color: #ff00fe;&quot;&gt;--profile my-aws-1&lt;/span&gt; --region &quot;eu-west-1&quot; --source-language-code &quot;en&quot; --target-language-code &quot;es&quot; --text &quot;hello, world&quot;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;2. If you receive a character set error like this (especially if translating to a non-latin charachter set language like Spanish or Russian)&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;background-color: rgba(232, 232, 232, 0.04); font-family: Monaco, Menlo, Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-size: 12px; font-variant-ligatures: none; white-space-collapse: preserve;&quot;&gt;&lt;span style=&quot;color: red;&quot;&gt;{
    &quot;TranslatedText&quot;:
&#39;charmap&#39; codec can&#39;t encode characters in position 1-6: character maps to &amp;lt;undefined&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Then, you need to set some environment variables to tell Python to use Unicode (the AWS CLI tool is written in Python):&lt;/p&gt;&lt;p&gt;On Windows:&lt;/p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;set PYTHONIOENCODING=UTF-8&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;set PYTHONUTF8=1&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;3. It&#39;s also worth upgrading AWS CLI to the most recent version.&amp;nbsp;&lt;/div&gt;&lt;div&gt;The installers are at:&amp;nbsp;&lt;a href=&quot;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&quot;&gt;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/5447314198668995485/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/02/aws-translate-via-aws-cli-command-line.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/5447314198668995485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/5447314198668995485'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/02/aws-translate-via-aws-cli-command-line.html' title='AWS Translate via the AWS CLI command line - error: &#39;charmap&#39; codec can&#39;t encode characters'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-8487888442028396325</id><published>2024-01-27T09:47:00.005+00:00</published><updated>2024-03-25T09:55:55.337+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="PDF"/><category scheme="http://www.blogger.com/atom/ns#" term="scripting"/><title type='text'>Generate PDF from markdown via pandoc</title><content type='html'>&lt;p&gt;One option to generate PDF from a markdown file like README.md, is to use pandoc.&lt;/p&gt;&lt;br /&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Installation&lt;/h3&gt;&lt;br /&gt;You need to install both:&lt;br /&gt;&lt;br /&gt;- [Pandoc](&lt;a href=&quot;https://www.google.com/url?q=https://pandoc.org/installing.html)&amp;amp;sa=D&amp;amp;source=calendar&amp;amp;usd=2&amp;amp;usg=AOvVaw0R2wMVUaUAJNN1GdM9iQ5Z&quot;&gt;https://pandoc.org/installing.html)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;- [MiKTeX](&lt;a href=&quot;https://www.google.com/url?q=https://miktex.org/download)&amp;amp;sa=D&amp;amp;source=calendar&amp;amp;usd=2&amp;amp;usg=AOvVaw0CJRHEBRn4T4JjAYVwanFG&quot;&gt;https://miktex.org/download)&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Then, restart any terminal windows where you will run the command to generate PDF.&lt;br /&gt;&lt;br /&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Execution - basic command&lt;/h3&gt;&lt;div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;pandoc -o ./README.pdf ./README.md&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;h3&gt;Execution - command with margins and figures&lt;/h3&gt;&lt;/div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;pandoc -V geometry:&quot;top=2cm, bottom=1.5cm, left=2cm, right=2cm&quot; -f markdown-implicit_figures -o ./README.pdf ./README.md&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;h3&gt;Execution - command with margins and figures and colored links&lt;/h3&gt;&lt;/div&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;pandoc&amp;nbsp;&lt;span style=&quot;font-size: 14px; white-space: pre;&quot;&gt;-V &lt;/span&gt;&lt;span style=&quot;font-size: 14px; white-space: pre;&quot;&gt;linkcolor:blue &lt;/span&gt;&lt;span style=&quot;font-size: 14px; white-space: pre;&quot;&gt;-V &lt;/span&gt;&lt;span style=&quot;font-size: 14px; white-space: pre;&quot;&gt;urlcolor:blue&lt;/span&gt;&amp;nbsp;-V geometry:&quot;top=2cm, bottom=1.5cm, left=2cm, right=2cm&quot; -f markdown-implicit_figures+autolink_bare_uris -o ./README.pdf ./README.md&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;note: &quot;autolink_bare_uris&quot; is needed to color in the links (at least with pandoc 3.1.11.1 on Windows).&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;For more details and examples, see this excellent Medium article at &lt;a href=&quot;https://www.google.com/url?q=https://pavolkutaj.medium.com/markdown-to-pdf-with-pandoc-and-miktex-58b578cedf4b&amp;amp;sa=D&amp;amp;source=calendar&amp;amp;usd=2&amp;amp;usg=AOvVaw3lpkDcWhA6kZLf-8caMtbE&quot;&gt;https://pavolkutaj.medium.com/markdown-to-pdf-with-pandoc-and-miktex-58b578cedf4b&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/8487888442028396325/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/01/generate-pdf-from-markdown-via-pandoc.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/8487888442028396325'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/8487888442028396325'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/01/generate-pdf-from-markdown-via-pandoc.html' title='Generate PDF from markdown via pandoc'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-3796465133197250753</id><published>2024-01-19T15:28:00.006+00:00</published><updated>2024-03-23T20:41:04.709+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Clean Code"/><category scheme="http://www.blogger.com/atom/ns#" term="Code analysis"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="Tools"/><title type='text'>Linting Python code using ruff or flake8: simple, fast, free and no false positives</title><content type='html'>&lt;h2 style=&quot;text-align: left;&quot;&gt;Linting Python code using ruff or flake8: fast, free and no false positives&lt;/h2&gt;&lt;p&gt;Static code analysis can help automatically find minor coding issues and style deviations. This helps especially if several people are collaborating on the same code.&lt;/p&gt;&lt;p&gt;With a dynamically typed language such as Python, since there is no build step, it can be helpful to have some static code analysis in place, to for example catch silly mistakes with indentation, or more serious mistakes such as incorrect exception handling.&lt;/p&gt;&lt;p&gt;Linting can be though of as a kind of lightweight form of static code analysis, looking for code style and layout issues. Because Python uses indenting to communicate control flow and scope (rather than the brackets used by many C++ or C# styled languages including Java), then automatically detecting such spacing issues can be critical.&lt;/p&gt;&lt;p&gt;When selecting a Python linter, there are many options to chose from. I like to use flake8 as it is simple, reliable, fast and has very low rate of false positives. It can still detect more complex issues such as incorrect exception handling.&lt;/p&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;ruff - linter and formatter&lt;/h3&gt;&lt;div&gt;A new and even faster option:&amp;nbsp;&lt;a href=&quot;https://github.com/astral-sh/ruff?tab=readme-ov-file&quot; target=&quot;_blank&quot;&gt;ruff&lt;/a&gt;&amp;nbsp;- very fast and also formats the code, and its default settings seem to be more practical than flake8.&lt;/div&gt;&lt;div&gt;&lt;h3&gt;Installation&lt;/h3&gt;&lt;p&gt;To install ruff (via pip):&lt;/p&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px;&quot;&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;python -m pip install ruff --quiet&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3&gt;Execution&lt;/h3&gt;&lt;p&gt;To lint:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ruff check src&lt;/span&gt;&lt;/p&gt;&lt;p&gt;To format:&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&amp;nbsp; &amp;nbsp; ruff format src&lt;/span&gt;&lt;/p&gt;&lt;/div&gt;&lt;div&gt;To configure:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Either add sections to pyproject.toml if you have one, OR add a file ruff.toml.&lt;/div&gt;&lt;div&gt;See the &lt;a href=&quot;https://docs.astral.sh/ruff/configuration/&quot; target=&quot;_blank&quot;&gt;ruff docs&lt;/a&gt; for details.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;span&gt;&lt;!--more--&gt;&lt;/span&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;flake8 - simple linter&lt;/h3&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Installation&lt;/h3&gt;&lt;p&gt;To install flake8 (via pip):&lt;/p&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px;&quot;&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;python -m pip install flake8 --quiet&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Execution&lt;/h3&gt;&lt;p&gt;To run, assuming that source code is under &#39;src&#39; folder, use a command like:&lt;/p&gt;&lt;blockquote style=&quot;border: none; margin: 0px 0px 0px 40px; padding: 0px;&quot;&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;python -m flake8 ./src&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;For a more complete example with some disabled rules, see the following bash script:&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# so future errors halt the script.&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;set -e&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;echo Linting ...&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# Disable less useful errors&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# - ref https://www.flake8rules.com/&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;#&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# E302 Expected 2 blank lines&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# E305 Expected 2 blank lines after end of function or class&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;# E501 Line too long (82 &amp;gt; 79 characters)&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;FLAKE8_TO_IGNORE=E302,E305,E501&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;python -m flake8 --extend-ignore $FLAKE8_TO_IGNORE ./src&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;echo [done]&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;The same code is also available as a &lt;a href=&quot;https://gist.github.com/mrseanryan/a7d8ed4bfda2f3f6e495bfe719e8d35c&quot; target=&quot;_blank&quot;&gt;gist&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;For more details about flake8, see:&lt;/p&gt;&lt;p&gt;- quickstart: &lt;a href=&quot;https://flake8.pycqa.org/en/latest/index.html#quickstart&quot;&gt;https://flake8.pycqa.org/en/latest/index.html#quickstart&lt;/a&gt;&lt;/p&gt;&lt;p&gt;- rules: &lt;a href=&quot;https://www.flake8rules.com/&quot;&gt;https://www.flake8rules.com/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;h3 style=&quot;text-align: left;&quot;&gt;Alternatives to flake8 or ruff&lt;/h3&gt;&lt;div&gt;For other options to lint Python code (including code style) see the following articles:&lt;/div&gt;&lt;p&gt;&amp;nbsp; - &lt;a href=&quot;https://codilime.com/blog/python-code-quality-linters/&quot;&gt;https://codilime.com/blog/python-code-quality-linters/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; - &lt;a href=&quot;https://inventwithpython.com/blog/2022/11/19/python-linter-comparison-2022-pylint-vs-pyflakes-vs-flake8-vs-autopep8-vs-bandit-vs-prospector-vs-pylama-vs-pyroma-vs-black-vs-mypy-vs-radon-vs-mccabe/&quot;&gt;https://inventwithpython.com/blog/2022/11/19/python-linter-comparison-2022-pylint-vs-pyflakes-vs-flake8-vs-autopep8-vs-bandit-vs-prospector-vs-pylama-vs-pyroma-vs-black-vs-mypy-vs-radon-vs-mccabe/&lt;/a&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/3796465133197250753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/01/linting-python-code-using-flake8-simple.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/3796465133197250753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/3796465133197250753'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/01/linting-python-code-using-flake8-simple.html' title='Linting Python code using ruff or flake8: simple, fast, free and no false positives'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-75530295240941661</id><published>2024-01-19T15:02:00.003+00:00</published><updated>2024-01-19T15:02:15.611+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Automation"/><category scheme="http://www.blogger.com/atom/ns#" term="image-processing"/><category scheme="http://www.blogger.com/atom/ns#" term="Node.js"/><title type='text'>Self-host your photos on Amazon CloudFront and S3: Cheap, fast and simple [OSS noobgallery]</title><content type='html'>&lt;p&gt;&lt;b&gt;noobgallery &lt;/b&gt;is an open source tool at&amp;nbsp;&lt;a href=&quot;https://github.com/brendannee/noobgallery&quot;&gt;https://github.com/brendannee/noobgallery&lt;/a&gt;&amp;nbsp;which I started using after looking at other options that were either too complicated, or just did not create the kind of photo-first experience I desired.&lt;/p&gt;&lt;p&gt;I&#39;ve used noobgallery&amp;nbsp;to &lt;b&gt;completely rebuild my WordPress based site&lt;/b&gt; that was heavy, slow, hard to back up, and also becoming expensive.&lt;/p&gt;noobgallery is a Node.js based project to generate a static photo gallery powered by &lt;a href=&quot;https://sachinchoolur.github.io/lightgallery.js/&quot;&gt;lightgallery.js&lt;/a&gt;. The generated site is automatically deployed to Amazon S3, which allows for a huge amount of cheap storage (around $0.02/GB per month).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Features include:&lt;/div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;simple photo gallery creation: just create a folder for each gallery, and copy your photos. noobgallery takes care of the rest.&lt;/li&gt;&lt;li&gt;responsive layout, supports mobile and desktop&lt;/li&gt;&lt;li&gt;slideshow and zoom in/out&lt;/li&gt;&lt;li&gt;gallery summary &amp;amp; tags (via optional gallery.json for each gallery)&lt;/li&gt;&lt;li&gt;bread crumbs to navigate multple gallery levels&lt;/li&gt;&lt;li&gt;about page&lt;/li&gt;&lt;li&gt;error page&lt;/li&gt;&lt;li&gt;does not upload original images&lt;/li&gt;&lt;li&gt;add optional copyright watermark&lt;/li&gt;&lt;li&gt;add optional fotomoto store links&lt;/li&gt;&lt;li&gt;Adding CloudFront is quite trivial, and with Route 53 you get a free HTTPS certificate.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;The CloudFront CDN (Content Delivery Network) and the elegant HTML and JavaScript output of &lt;b&gt;noobgallery &lt;/b&gt;produce a photo site that is cross-device and is ridiculously fast to load, world wide.&lt;br /&gt;&lt;br /&gt;So if you are looking for a cheap and simple way to host your own photo site, do consider &lt;a href=&quot;https://github.com/brendannee/noobgallery&quot;&gt;noobgallery&lt;/a&gt;.&lt;br /&gt;&lt;p&gt;As a shameless plug, here is my own photo website, automatically generated via &lt;b&gt;noobgallery&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&lt;a href=&quot;https://everydayphotos.net/&quot;&gt;https://everydayphotos.net/&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;i&gt;disclosure: I did not create noobgallery, but I did contribute a couple of features.&lt;/i&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/75530295240941661/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/01/self-host-your-photos-on-amazon.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/75530295240941661'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/75530295240941661'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/01/self-host-your-photos-on-amazon.html' title='Self-host your photos on Amazon CloudFront and S3: Cheap, fast and simple [OSS noobgallery]'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3430885654094366683.post-3973857622719527556</id><published>2024-01-19T14:48:00.005+00:00</published><updated>2024-01-19T14:48:48.919+00:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type='text'>Sharing Python code via pypi packages - example: common Python utils bundled as &#39;cornsnake&#39;</title><content type='html'>&lt;p&gt;To avoid copy-paste hell, (duplicate code is generally regarded to be correlated with bugs) - Python code can be shared via packages.&lt;/p&gt;&lt;p&gt;There is a really nice tutorial here, with just enough detail to walk you through building and publishing your own package:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://realpython.com/pypi-publish-python-package/&quot;&gt;https://realpython.com/pypi-publish-python-package/&lt;/a&gt;&lt;/p&gt;&lt;span&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;/span&gt;&lt;p&gt;For an example with scripts to automatically bump versions and re-deploy, see:&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/mrseanryan/cornsnake&quot;&gt;https://github.com/mrseanryan/cornsnake&lt;/a&gt;&lt;/p&gt;&lt;p&gt;cornsnake is a small Python package published via pypi - it contains higher-level wrappers for common Python tasks:&lt;br /&gt;&lt;br /&gt;- for working with files, git, ZIP, lists, processes, dates and times.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://antipatterns.blogspot.com/feeds/3973857622719527556/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://antipatterns.blogspot.com/2024/01/sharing-python-code-via-pypi-packages.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/3973857622719527556'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3430885654094366683/posts/default/3973857622719527556'/><link rel='alternate' type='text/html' href='http://antipatterns.blogspot.com/2024/01/sharing-python-code-via-pypi-packages.html' title='Sharing Python code via pypi packages - example: common Python utils bundled as &#39;cornsnake&#39;'/><author><name>Sean Ryan</name><uri>http://www.blogger.com/profile/14086044408171743516</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEibSar0WX6BB8cYzGLfzZVu8zRRXdFpZK6MxS3g7u4fMedDkPtHCii-oO0d1z7nbCKsp6HpUl4NUNeOxz4-hWFtZKxRRUvuHi-GM4RudL04PZ8jwTvWd2JQMLL2sbIvLw/s113/sean_portrait_india.jpg'/></author><thr:total>0</thr:total></entry></feed>