<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jay Miller</title>
    <description>The latest articles on Forem by Jay Miller (@kjaymiller).</description>
    <link>https://forem.com/kjaymiller</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1781%2Fb7455835-34c4-4aaa-a90b-3023e0247a70.jpg</url>
      <title>Forem: Jay Miller</title>
      <link>https://forem.com/kjaymiller</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/kjaymiller"/>
    <language>en</language>
    <item>
      <title>Using Azure Storage Queues and Python to Automate Sending Tweets</title>
      <dc:creator>Jay Miller</dc:creator>
      <pubDate>Thu, 03 Nov 2022 07:00:00 +0000</pubDate>
      <link>https://forem.com/azure/using-azure-storage-queues-and-python-to-automate-sending-tweets-5306</link>
      <guid>https://forem.com/azure/using-azure-storage-queues-and-python-to-automate-sending-tweets-5306</guid>
      <description>&lt;p&gt;October was ADHD Awareness Month and this year for October, I wanted to do something to bring awareness and encouragement to folks with ADHD and other neurodiversities.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Jump To&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intro&lt;/li&gt;
&lt;li&gt;Storage Queues&lt;/li&gt;
&lt;li&gt;Creating Images&lt;/li&gt;
&lt;li&gt;Twitter Access&lt;/li&gt;
&lt;li&gt;Improving the Process&lt;/li&gt;
&lt;li&gt;Running the Script&lt;/li&gt;
&lt;li&gt;Was It Worth It&lt;/li&gt;
&lt;li&gt;Check it Out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aside from speaking at &lt;a href="https://www.youtube.com/watch?v=daOy79k9OhI" rel="noopener noreferrer"&gt;Refactr.Tech&lt;/a&gt; and appearing and &lt;a href="https://www.youtube.com/watch?v=cZSwhRCgFLA&amp;amp;t=36s" rel="noopener noreferrer"&gt;a few podcasts&lt;/a&gt;, I wanted to create something that:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. Would have a wider reach. 
2. Would let me play with Python and Azure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;If I look at where I have the largest reach, that's &lt;em&gt;Twitter&lt;/em&gt;. So I decided to create an automated Twitter Campaign.&lt;/p&gt;

&lt;p&gt;If I want to play with Python - Then I can send tweets &lt;em&gt;programatically&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;If I want to play with Azure... I can schedule the tweets with &lt;em&gt;Azure Functions&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can see the results in &lt;a href="https://dev.to/kjaymiller/results-of-31daysofneurodivergence-kk8"&gt;Part 3&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Content
&lt;/h2&gt;

&lt;p&gt;If you haven't seen the other parts in this series the TLDR was I asked for folks with neurodiversities (ADHD, Bipolar, Dyslexia, etc) to fill out a short-survey with the last part requesting the participant to send an anonymous message to folks that may have recently been diagnosed or are considering seeking a diagnosis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage Queues
&lt;/h2&gt;

&lt;p&gt;I needed a way to store the message so that they could be called.&lt;/p&gt;

&lt;p&gt;Originally I was thinking to use a NoSQL Database like &lt;a href="https://learn.microsoft.com/en-us/azure/cosmos-db/introduction" rel="noopener noreferrer"&gt;Cosmos DB&lt;/a&gt;. I could have added the &lt;code&gt;schedule day&lt;/code&gt; and then have the script pull the message for the current day.&lt;/p&gt;

&lt;p&gt;This would work but it felt like a lot to spin up a Database to store 30 documents.&lt;/p&gt;

&lt;p&gt;My next thought was to do something lighter (like SQLite) and then I remembered &lt;a href="https://www.youtube.com/watch?v=ICjFGTaxaZc&amp;amp;list=PL0MRiRrXAvRhuVf-g4o3IO0jmpLQgubZK&amp;amp;index=7" rel="noopener noreferrer"&gt;a talk from PyTexas&lt;/a&gt; about using &lt;a href="https://docs.python.org/3/library/queue.html" rel="noopener noreferrer"&gt;queues&lt;/a&gt; in Python.  While I didn't want a script running for that long I started thinking about storing the text in a queue. This is when I remember there being &lt;a href="https://learn.microsoft.com/en-us/azure/storage/queues/storage-queues-introduction" rel="noopener noreferrer"&gt;Azure Storage Queues&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F71q6amuqjkt3fokuhd5n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F71q6amuqjkt3fokuhd5n.jpg" alt="my messages in azure storage queues"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In short, a storage queue allows you to store millions of messages (either bytes or unicode). Its primary function is to pull data off the top of the queue and either delete the message or push it to the bottom. &lt;/p&gt;

&lt;p&gt;This was perfect because I already had a list of messages. I just needed to add them to the queue. Then my azure function would just call from the queue processing the message. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;azure.storage.queues&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;QueueClient&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;QueueClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_connection_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;conn_str&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CONNECTION_STRING&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;queue_name&lt;/span&gt;&lt;span class="o"&gt;=&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;QUEUE_NAME&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_message&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;index&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;idx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# to receive the message
&lt;/span&gt;
&lt;span class="n"&gt;_msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;receive_message&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Creating Images
&lt;/h2&gt;

&lt;p&gt;Sending text to twitter didn't seem like the greatest option. There is a character limit and studies show &lt;a href="https://blog.twitter.com/en_us/a/2014/what-fuels-a-tweets-engagement" rel="noopener noreferrer"&gt;tweets are more engaging when you add images&lt;/a&gt;. This gave me the idea of creating a base image and overlaying the text on the image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foabbj64h11iag4tj3f5x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foabbj64h11iag4tj3f5x.png" alt="Base Image from Canva"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was able to build a simple base image using Canva. Then, I overlayed the text using &lt;a href="https://python-pillow.org" rel="noopener noreferrer"&gt;Pillow&lt;/a&gt;. Working with text on images is somwhat complicated to get perfect so I opted to create 4 categories and a ratio for each one.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;md&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.010&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.012&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;xl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.014&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2xl&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.020&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then I used that ratio to autoscale the text until the bounding box was the desired size.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;draw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageDraw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;font_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;font&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageFont&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;truetype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assets/Lato-BoldItalic.ttf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;font_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="n"&gt;font&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getbbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;image_size_ratio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="n"&gt;font_size&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
   &lt;span class="n"&gt;font&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageFont&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;truetype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assets/Lato-BoldItalic.ttf&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;font_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It wasn't perfect, but it was good_enough. Then I added that index and a hashtag onto the image, and I was ready to go.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxba091kvpt6fi82182bz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxba091kvpt6fi82182bz.png" alt="Example Image from the Queue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Twitter Access
&lt;/h2&gt;

&lt;p&gt;The next step was sending the tweet. Twitter has an &lt;a href="https://developer.twitter.com/en/docs/twitter-api" rel="noopener noreferrer"&gt;API&lt;/a&gt; in which you can use to interact with the application. The most basic access is free. But in order to tweet images, I needed to request elevated access. Instead of using the API directly, I opted to use the python package &lt;a href="https://docs.tweepy.org/en/stable/" rel="noopener noreferrer"&gt;Tweepy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First connect your twitter account using your CLIENT AND ACCESS KEYS AND SECRETS. Then you'll need to store the image as an object using the v1 API or (&lt;code&gt;API&lt;/code&gt;).&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;BytesIO&lt;/span&gt; &lt;span class="c1"&gt;#This (lets you save the image in memory and not to a file)
&lt;/span&gt;
&lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OAuth1UserHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;consumer_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;consumer_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;consumer_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;consumer_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;access_token_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;access_token_secret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;BytesIO&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PNG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tweepy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;API&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;media&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;media_upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;my_file.png&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Then  you use the v2 API (&lt;code&gt;Client&lt;/code&gt;) to send the message embedding the media.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="c1"&gt;# with the message queued message as _msg
&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;twitterv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_tweet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;index&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; #31DaysOfNeurodivergence&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;media&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;filename&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;_msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;index&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}{&lt;/span&gt;&lt;span class="n"&gt;_msg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Improving the Process
&lt;/h2&gt;

&lt;p&gt;There were some challenges in figuring out this process. My teammate &lt;a href="https://twitter.com/pamelafox" rel="noopener noreferrer"&gt;Pamela Fox&lt;/a&gt; and I put together a little module called &lt;a href="https://pypi.org/project/azqueuetweeter/" rel="noopener noreferrer"&gt;AZ Queue Tweeter&lt;/a&gt; that expanded on this process, allowing you to not only send tweets with images to storage queues, but also supports the full range of a personal account on twitter. Here is an example of Pamela sending a Twitter poll.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;queue_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Whats your fav Python web framework?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;poll_options&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Flask&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Django&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FastAPI&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;All of em!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;poll_duration_minutes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;qt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_next_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message_transformer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4w93yguf2uv28fumdhr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv4w93yguf2uv28fumdhr.png" alt="Pamela's Resulting Twitter Poll"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This also introduced the ability to manipulate the text prior to sending it. In my script, I use &lt;a href="https://spacy.io/api/sentencizer" rel="noopener noreferrer"&gt;spacy&lt;/a&gt; to segment the messages into sentences keeping the text to 280 characters.&lt;/p&gt;

&lt;h2&gt;
  
  
   Running the Script
&lt;/h2&gt;

&lt;p&gt;So we've walked through how to make the tweet. How do we ensure that the tweets run everyday? This is where Azure functions come to play. I was able to create a simple timer function that runs once a day for the month of October.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scriptFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"__init__.py"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bindings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mytimer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"timerTrigger"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"in"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"schedule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0 0 12 * 10 *"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You can use the &lt;a href="https://learn.microsoft.com/en-us/azure/azure-functions/functions-run-local?tabs=v4%2Cmacos%2Cpython%2Cportal%2Cbash#create-func" rel="noopener noreferrer"&gt;CLI&lt;/a&gt; or &lt;a href="https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs-code?tabs=python" rel="noopener noreferrer"&gt;VS Code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F02h84khipjhxwqwfcscw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F02h84khipjhxwqwfcscw.jpg" alt="The Function Section in VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then pass a function that retrieves a message, creates the image, and sends the tweet.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;p&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mytimer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimerRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;QueueTweeter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;storage_auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;sa&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;twitter_auth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;br&gt;
    &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send_next_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;br&gt;
        &lt;span class="n"&gt;message_transformer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;load_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;preview_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;delete_after&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;br&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;span class="c1"&amp;gt;# Message is in format "Index - Text"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; triggered at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/p&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Was this worth the effort&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;When I think about the problem that I had (a lot of tweets getting sent over a large period of time) I don't think I had a lot of options that were "fully automated".&lt;/p&gt;

&lt;p&gt;I did learn some new tools and some interesting solves (looking at you PILLOW), also my overall cost for the month was less than $0.10.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fln4xhvmdvtwkbi1ftun6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fln4xhvmdvtwkbi1ftun6.jpg" alt="Monthly Cost to run"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Solving the problem was actually incredibly valuable as I now intend to use the same tooling to automate some of my podcasts and other content. I can also quickly modify this to use Azure queues to send message to other channels (like Discord or Teams).&lt;/p&gt;

&lt;p&gt;I've already converted this queue into a &lt;a href="https://jm-31days-of-nd-2022.azurewebsites.net" rel="noopener noreferrer"&gt;website&lt;/a&gt; using Flask + HTMX.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm5ij7icwlmfj396asw6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm5ij7icwlmfj396asw6.gif" alt="Flask Site Using the Queue"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Check it Out
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/kjaymiller/31DaysofNeurodivergenceTweets" rel="noopener noreferrer"&gt;Check out the repo&lt;/a&gt; to see how I was able to build this campaign. Finally check out &lt;a href="https://github.com/kjaymiller/Az-Queue-Tweeter" rel="noopener noreferrer"&gt;AZ Queue Tweeter&lt;/a&gt; to create your own campaigns!&lt;/p&gt;

</description>
      <category>mentalhealth</category>
      <category>azure</category>
      <category>python</category>
      <category>twitter</category>
    </item>
    <item>
      <title>Results of #31DaysofNeurodivergence</title>
      <dc:creator>Jay Miller</dc:creator>
      <pubDate>Thu, 03 Nov 2022 07:00:00 +0000</pubDate>
      <link>https://forem.com/kjaymiller/results-of-31daysofneurodivergence-kk8</link>
      <guid>https://forem.com/kjaymiller/results-of-31daysofneurodivergence-kk8</guid>
      <description>&lt;h1&gt;
  
  
  Wrapping Up 31DaysofNeuroDivergence
&lt;/h1&gt;

&lt;p&gt;A back in September I shared an &lt;a href="https://dev.to/kjaymiller/31daysofneurodivergence-4b3p"&gt;idea to encourage folks&lt;/a&gt; considering a neurodiversity diagnosing. This included a &lt;a href="https://dev.to/kjaymiller/31daysofneurodivergence-4b3p"&gt;twitter campaign&lt;/a&gt; for the month of October under the hashtag #31DaysofNeurodivergence.&lt;/p&gt;

&lt;p&gt;I was able to send a message on 31 messages using an automated tweet schedule I built using &lt;a href="https://dev.to/azure/using-azure-storage-queues-and-python-to-automate-sending-tweets-5306"&gt;Azure Storage Queues and Python&lt;/a&gt;. The project also inspired a &lt;a href="https://github.com/kjaymiller/Az-Queue-Tweeter"&gt;Python package&lt;/a&gt; that would make campaigns like this easier in the future!&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;The #31DaysofNeurodivergence tweets were seen a total of  10,186 times. They received 189 likes and were retweeted 20 times.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D26-L8ZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aqx3x9h9zaul60tg50q5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D26-L8ZS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aqx3x9h9zaul60tg50q5.png" alt="Impressions" width="722" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't have much of a perspective on how good/bad this is. To a marketer, this may not be anything special. And there were a lot of things that I could have spent more time focusing on (like when I tweeted, a better design or color scheme). That said I'm perfectly fine with this result and here is why.&lt;/p&gt;

&lt;h3&gt;
  
  
  People saw it.
&lt;/h3&gt;

&lt;p&gt;Let's rephrase what this data means. There were 10,186 times that someone had the opportunity to hear someone with a Neurodivergency share their story. 189 times someone resonated with the messages of a stranger and 20 times someone thought "This information is valuable and should be shared with people in my community".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZRYDoYpP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0cnc05mkizgkclhf7orl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZRYDoYpP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0cnc05mkizgkclhf7orl.png" alt="Likes and Retweets" width="722" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My goal for this was to share a message of encouragement and I certainly did that.&lt;/p&gt;

</description>
      <category>twitter</category>
      <category>mentalhealth</category>
      <category>analytics</category>
    </item>
    <item>
      <title>#31DaysofNeurodivergence</title>
      <dc:creator>Jay Miller</dc:creator>
      <pubDate>Sat, 01 Oct 2022 18:53:48 +0000</pubDate>
      <link>https://forem.com/kjaymiller/31daysofneurodivergence-4b3p</link>
      <guid>https://forem.com/kjaymiller/31daysofneurodivergence-4b3p</guid>
      <description>&lt;p&gt;It's October and that means it's #ADHDAwarenessMonth! As I've been mentioning I collected messages of support from folks with a Neurodivergency to give you a message of support if you're newly diagnosed or have been considering seeking a diagnosis.&lt;/p&gt;

&lt;p&gt;These messages were collected anonymously. I'll be sending one tweet a day with the following image card and the hashtag #31daysofNeurodivergence.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cUXDH0EG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ccs3cl0hkn464ry3bj7l.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cUXDH0EG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ccs3cl0hkn464ry3bj7l.jpg" alt="orange twitter image card" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whether it's ADHD, ASD, Dislexia, Bipolar, or PTSD, or any other Neurodivergence, I hope these messages will be a voice of encouragement for you this month to speak with someone.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the folks who participated in this.
&lt;/h2&gt;

&lt;p&gt;Folks were asked a bit about their journey with mental health. While this isn't a comprehensive study. It definitely matches that of the experiences I heard from others.&lt;/p&gt;

&lt;p&gt;Many of the folks in that filled this out belonged to one or more underrepresented group in their career. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z9ueF6Kw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n121q2hac1e7ro8lp2p6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z9ueF6Kw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n121q2hac1e7ro8lp2p6.png" alt="survey results for underrepresented groups" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These folks were mostly also diagnosed later in life.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7BkQJmA_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ugkbowihnw1sx0xinwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7BkQJmA_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0ugkbowihnw1sx0xinwa.png" alt="survey results for diagnosis" width="880" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The majority of folks also didn't speak openly about mental health and a large group of folks were often discouraged from seeking professional help by their culture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EDDZbshu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xn2dz62v5j8726bpsd8m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EDDZbshu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xn2dz62v5j8726bpsd8m.png" alt="survey results for mental health and family" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to want to receive these messages, be sure to follow &lt;a href="https://twitter.com/kjaymiller"&gt;me on Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, a majority of these folks were encouraged after hearing about others with neurodivergencies. That is why we're sharing this information in hopes that we can encourage others.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IYHgAPdS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nwazrtr46hppoofpon78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IYHgAPdS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nwazrtr46hppoofpon78.png" alt="survey about hearing about mental health from others" width="880" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>Add Code of Conduct Extension Now Comes with Options!</title>
      <dc:creator>Jay Miller</dc:creator>
      <pubDate>Fri, 19 Aug 2022 19:21:00 +0000</pubDate>
      <link>https://forem.com/kjaymiller/add-code-of-conduct-extension-now-comes-with-options-436p</link>
      <guid>https://forem.com/kjaymiller/add-code-of-conduct-extension-now-comes-with-options-436p</guid>
      <description>&lt;p&gt;The first update to my VS Code extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=kjaymiller.vscode-add-code-of-conduct"&gt;Add Code of Conduct&lt;/a&gt; is now available!&lt;/p&gt;

&lt;p&gt;In this update, we added the ability to choose between two commonly used Codes of Conduct:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://contributor-covenant.org/"&gt;Contributor Covenant&lt;/a&gt; (The existing Option) &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md"&gt;Citizen Code of Conduct&lt;/a&gt; (The new Option)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2Q1GjLZy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://kjaymiller.azureedge.net/media/add_covenant-2022-8-2.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2Q1GjLZy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://kjaymiller.azureedge.net/media/add_covenant-2022-8-2.gif" alt="gif of the step through process adding a CoC" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This opens the door to adding several options.&lt;/p&gt;

&lt;p&gt;This also begins the conversation around what other files should be added by default and how to add them. Speaking with my wonderful colleage, &lt;a href="https://twitter.com/crazy4pi314"&gt;Sarah&lt;/a&gt;, I feel the right thing to do is to replicat this process for all of the files I think should be a standard in &lt;a href="https://contributionswelcome.org"&gt;making open source accessible to everyone&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That said, this extension will only handle code of conducts but there is still much to be done, like adding more options and providing a way to add defaults.&lt;/p&gt;

&lt;p&gt;I give a few shoutouts on the &lt;a href="https://marketplace.visualstudio.com/items/kjaymiller.vscode-add-code-of-conduct/changelog"&gt;changelog&lt;/a&gt; so check that out.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>opensource</category>
      <category>news</category>
      <category>community</category>
    </item>
    <item>
      <title>New Project 31 Tweets of Neurodiverse Encouragement</title>
      <dc:creator>Jay Miller</dc:creator>
      <pubDate>Wed, 17 Aug 2022 19:10:23 +0000</pubDate>
      <link>https://forem.com/kjaymiller/new-project-31-tweets-of-neurodiverse-encouragement-1e6m</link>
      <guid>https://forem.com/kjaymiller/new-project-31-tweets-of-neurodiverse-encouragement-1e6m</guid>
      <description>&lt;p&gt;We've all seen motivational posts on social media designed to &lt;del&gt;get follows&lt;/del&gt; brighten our days.&lt;/p&gt;

&lt;p&gt;I've looked at these posts wondering do they actually help. I believe they initially did. But overtime, the desire for people to find a solution was only matched with peoples desire for influence. &lt;/p&gt;

&lt;p&gt;My development philosophy is "Helpful or Fun, and in the best cases BOTH". When I create projects, my hope is that I can make things that are helpful to others. This definitely fits in the "both" category.&lt;/p&gt;

&lt;p&gt;I've  been public about getting diagnosed with ADHD  as an adult. I, like others, viewed neurodivergence (ND) as a negative personality trait. This changed only after I had wonderful neurodivergent people show me that a diagnosis didn't have to come at the sacrifice of success.&lt;/p&gt;

&lt;p&gt;All that to say, I wanted to improve how neurodivergent folks can provide encouragement one another. &lt;/p&gt;

&lt;p&gt;I've created a &lt;a href="https://aka.ms/jm-ndform-2022"&gt;form&lt;/a&gt; that ND folks can fill out. It's anonymous, it doesn't try to over-classify based on individual traits. It serves a few purposes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It provides a little insight and understanding of where folks are coming from.&lt;/li&gt;
&lt;li&gt;It allows people to openly share to their comfort. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The goal is to send a &lt;em&gt;motivational&lt;/em&gt; message on Twitter (hopefully from an account not my own) each day. The goal is to share real messages of encouragement for folks who have been recently diagnosed or are considering seeking diagnosis or treatment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Is This on a Developer Blog
&lt;/h2&gt;

&lt;p&gt;First of all, developers are people, and mental health is one of the biggest reasons people exit tech.&lt;/p&gt;

&lt;p&gt;I've learned that many folks (including myself) got into tech without knowing they were neurodivergent. This isn't a blanket statement or me trying to match successful tech folks to mental health diagnoses. It's an observation. As I speak about my diagnoses, people reach out to me sharing they were also recently diagnosed or have been considering getting diagnosed. Neurotypical folks &lt;/p&gt;

&lt;p&gt;Also there will be some technical details in how this will be implemented. That said, the project won't work without contributions.&lt;/p&gt;

&lt;h2&gt;
  
  
  How You Can Help
&lt;/h2&gt;

&lt;p&gt;If you are neurodivergent, please fill out the form at &lt;a href="https://aka.ms/jm-ndform-2022"&gt;https://aka.ms/jm-ndform-2022&lt;/a&gt;. No personal identifiable information will be collected. There are a few question s I hope to share some collective results, but also the last question is a personal message that once reviewed (again no PII or hatred) will be sent out.&lt;/p&gt;

&lt;p&gt;My goal is that enough people can share their story that we can get a full year of encouragement.&lt;/p&gt;

&lt;p&gt;Again the form is at &lt;a href="https://aka.ms/jm-ndform-2022"&gt;https://aka.ms/jm-ndform-2022&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mentalhealth</category>
    </item>
    <item>
      <title>Deploy Azure Static Web Apps using Python</title>
      <dc:creator>Jay Miller</dc:creator>
      <pubDate>Wed, 03 Aug 2022 14:44:52 +0000</pubDate>
      <link>https://forem.com/azure/deploy-azure-static-web-apps-using-python-1hn7</link>
      <guid>https://forem.com/azure/deploy-azure-static-web-apps-using-python-1hn7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;TLDR: Connect your repo to Azure Static Web Apps and use GitHub Actions to build your site via Python.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Modern Static Sites (popularly referred to as &lt;a href="https://jamstack.org" rel="noopener noreferrer"&gt;JAMstack Apps&lt;/a&gt;) provide a custom web experience for little to no cost.&lt;/p&gt;

&lt;p&gt;I've been working on &lt;a href="https://render-engine.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;my own static site generator&lt;/a&gt; for going on 5 years now. It's developed a lot over time, but one thing is consistent. It's modern python!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2Frender-engine-output.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2Frender-engine-output.png" alt="output of my static site generator building files"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many folks have used tools like &lt;a href="https://pages.github.com" rel="noopener noreferrer"&gt;github pages&lt;/a&gt;, &lt;a href="https://netlify.com" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; or &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt;, since joining Microsoft, I wanted to learn more about how to make both static and dynamic sites using Python and &lt;a href="https://azure.microsoft.com/en-us/" rel="noopener noreferrer"&gt;Azure&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I first learned about Static Web Apps (SWA) in my first week when the team was &lt;a href="https://techcommunity.microsoft.com/t5/apps-on-azure-blog/learn-azure-static-web-apps-in-30daysofswa/ba-p/3354021" rel="noopener noreferrer"&gt;celebrating one year&lt;/a&gt; of the product. By design, the plan was to serve web applications by mixing HTML and optionally dynamic content via Azure functions.&lt;/p&gt;

&lt;p&gt;Python has fallen out of favor for building static web apps, but it is still possible to deploy a static web app. Sadly, you do have to do a little more than if you were going to use Javascript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup Azure Static Web Apps (The VS Code way)
&lt;/h2&gt;

&lt;p&gt;You can setup Azure Static Web Apps with VS Code using the &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/getting-started?tabs=vanilla-javascript#install-azure-static-web-apps-extension" rel="noopener noreferrer"&gt;Azure Static Web Apps Getting Started&lt;/a&gt;. There provides a few options for web frameworks and the closest for you will be the vanilla JS route. We'll skip the first couple steps since we're not using the demo repo (or Javascript). I don't want to re-hash the tutorial; here is a quick recap:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your project's repo in VS Code&lt;/li&gt;
&lt;li&gt;Install the Azure Extension and log in to your Azure account&lt;/li&gt;
&lt;li&gt;Select the Azure Side bar menu in the &lt;em&gt;RESOURCES&lt;/em&gt; tab &lt;/li&gt;
&lt;li&gt;Select the create icon (plus sign)&lt;/li&gt;
&lt;li&gt;In the prompt, choose &lt;em&gt;Create Static Web App&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Run through the wizard

&lt;ol&gt;
&lt;li&gt;connecting your GitHub account&lt;/li&gt;
&lt;li&gt;creating a name for your project&lt;/li&gt;
&lt;li&gt;choose your preffered region&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;The next step is where things begin to differ.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;IMPORTANT&lt;/strong&gt; Selecting &lt;strong&gt;CUSTOM&lt;/strong&gt; as the Deployment Method.
&lt;/li&gt;
&lt;li&gt;Set your app location to "/" path of your project or wherever your Python code lives.&lt;/li&gt;
&lt;li&gt;Set the output path to the location where your code will create HTML.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2FNewSWAApp.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2FNewSWAApp.gif" alt="gif of building out the steps in VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting your site up and running
&lt;/h2&gt;

&lt;p&gt;Sadly, Azure Static Web Apps don't support running python based build commands easily, but according to the docs, we just need &lt;strong&gt;ONE HTML&lt;/strong&gt; file in a folder to build a site. we can give it that file in a few different ways. Where you build your HTML will be up to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build in the image
&lt;/h2&gt;

&lt;p&gt;Azure uses a system called &lt;a href="https://github.com/Microsoft/Oryx" rel="noopener noreferrer"&gt;Oryx&lt;/a&gt;. You don't need to know too much about how it works but it looks for specific files and chooses build specs based on them. If you have a &lt;code&gt;requirements.txt&lt;/code&gt;, Oryx will know to use Python. &lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Using Oryx comes with a few compromises. Oryx uses a Python 3.8 build by default. You can update up to Python 3.9.7 by adding &lt;code&gt;PYTHON_VERSION: "3.9.7"&lt;/code&gt; to the yaml file. Also, you will need to add your build steps to the  &lt;code&gt;PRE_BUILD_COMMAND&lt;/code&gt;&lt;sup id="fnref2"&gt;2&lt;/sup&gt;. You can create shell script or add the steps seperated with &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build And Deploy&lt;/span&gt;
        &lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;builddeploy&lt;/span&gt;
        &lt;span class="s"&gt;uses&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Azure/static-web-apps-deploy@v1&lt;/span&gt;
        &lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;azure_static_web_apps_api_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_MY_PROJECT }}&lt;/span&gt;
          &lt;span class="na"&gt;repo_token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt; &lt;span class="c1"&gt;# Used for Github integrations (i.e. PR comments)&lt;/span&gt;
          &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;upload"&lt;/span&gt;
          &lt;span class="c1"&gt;###### Repository/Build Configurations - These values can be configured to match your app requirements. ######&lt;/span&gt;
          &lt;span class="c1"&gt;# For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig&lt;/span&gt;
          &lt;span class="na"&gt;app_location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/"&lt;/span&gt; &lt;span class="c1"&gt;# App source code path&lt;/span&gt;
          &lt;span class="na"&gt;output_location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OUTPUT_PATH"&lt;/span&gt; &lt;span class="c1"&gt;# Built app content directory - optional&lt;/span&gt;
  &lt;span class="err"&gt;      &lt;/span&gt;&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;PYTHON_VERSION&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.9.7&lt;/span&gt;
          &lt;span class="na"&gt;PRE_BUILD_COMMAND&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;pip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;--upgrade&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;pip&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;install&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-r&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;requirements.txt&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;python&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;routes.py'&lt;/span&gt; &lt;span class="c1"&gt;# This can be a shell script as well&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build Before the Image
&lt;/h3&gt;

&lt;p&gt;You can separate your build steps from the Azure image deployed, building it in Github Actions. &lt;/p&gt;

&lt;p&gt;To build your environment in GH Actions you'll need to add a block to your yaml file &lt;strong&gt;BEFORE&lt;/strong&gt; the Azure &lt;code&gt;Build and Deploy&lt;/code&gt; section. You'll need to include the &lt;code&gt;setup-python&lt;/code&gt; action and specify the python version you would like to use. Use the major version of your python version so &lt;code&gt;3.10&lt;/code&gt; and NOT &lt;code&gt;3.10.5&lt;/code&gt;. For more information and options on this you can check out the &lt;a href="https://github.com/actions/setup-python" rel="noopener noreferrer"&gt;Setup-Python GH actions repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next you'll need to add the run steps. Give this section a new name and enter the commands to run.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;az_build.sh&lt;/span&gt; &lt;span class="c1"&gt;# My run script is routes.py&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For more than one command, use &lt;code&gt;|-&lt;/code&gt; at the beginning which each command being on its own line.&lt;/p&gt;

&lt;p&gt;I don't think there is much of a difference performance-wise. You're code is doing the same thing, just in a different place. Use this method to bypass Python version limits of Oryx (or separate concerns in your build).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2FBuild%2520in%2520github%2520actions.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2FBuild%2520in%2520github%2520actions.png" alt="The build in GH Actions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Build Before Pushing to Github
&lt;/h3&gt;

&lt;p&gt;There is another way. Build your site locally and push its contents to GithHub.&lt;/p&gt;

&lt;p&gt;You will need to manually run your build steps. The biggest advantages is complete control and you don't have to modify your yaml file.&lt;/p&gt;

&lt;p&gt;The advantage of doing this is if you do granular changes, you don't have to rebuild the entire site.&lt;/p&gt;

&lt;h2&gt;
  
  
  Viewing your Site
&lt;/h2&gt;

&lt;p&gt;After you push your code to GitHub. You'll be able to see your site live. If you aren't sure of the URL, check the GitHub Actions Build and it will tell you in the build steps. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2Faz%2520deployment%2520build.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2Faz%2520deployment%2520build.png" alt="The Successful build with url"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also refresh the Azure Section of VS Code and it should be visible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2Fswa-output-vs-code.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkjaymiller.azureedge.net%2Fmedia%2Fswa-output-vs-code.png" alt="The new SWA in VS Code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once it's running you can &lt;a href="https://docs.microsoft.com/en-us/azure/static-web-apps/custom-domain" rel="noopener noreferrer"&gt;add a custom domain&lt;/a&gt; in the Azure Portal. &lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Sadly I don't think this works in Azure Static Web Apps using Pipenv or Poetry. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;You can add also add those steps to the &lt;code&gt;POST_BUILD_COMMAND&lt;/code&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>python</category>
      <category>staticwebapps</category>
      <category>azure</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Make Inlay Type Hints in Python Appear/Disappear</title>
      <dc:creator>Jay Miller</dc:creator>
      <pubDate>Wed, 27 Jul 2022 21:46:57 +0000</pubDate>
      <link>https://forem.com/kjaymiller/make-inlay-type-hints-in-python-appeardisappear-njk</link>
      <guid>https://forem.com/kjaymiller/make-inlay-type-hints-in-python-appeardisappear-njk</guid>
      <description>&lt;h2&gt;
  
  
  A Type Hinting Tip for Those Not Completely Onboard
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;TLDR: You can set &lt;code&gt;Inlay Hints: Enabled&lt;/code&gt; to &lt;code&gt;On/OffUnless pressed&lt;/code&gt; in the settings to show/hide inlay type hints in Python code. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In July the VS Code Python Team released an &lt;a href="https://devblogs.microsoft.com/python/python-in-visual-studio-code-july-2022-release/" rel="noopener noreferrer"&gt;update for VS Code&lt;/a&gt; that announced inlay Type Hint Support.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/hHBp0r4w86g"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Adding type hint inferences next to your code is very nice. The more I started playing with it, I noticed that sometimes the type hints didn't feel helpful and made my code look cluttered.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Ftype_literals.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Ftype_literals.png" alt="type literals don't help that much when writing code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't get me wrong, I like type hints. They are a massive help with troubleshooting and documentation. They are even used in &lt;a href="https://docs.python.org/3/library/dataclasses.html" rel="noopener noreferrer"&gt;dataclasses&lt;/a&gt;, one of my favorite standard library tools. But as I tell my child, there is a time and place for everything. When it comes to type hints, &lt;em&gt;All the Time!&lt;/em&gt;, is not the answer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's take the following example.
&lt;/h3&gt;

&lt;p&gt;Let's say we have some dictionary objects that are brought into our code from multiple systems. Sometimes the &lt;code&gt;employee_id&lt;/code&gt; will be a numerical id and other times it will be a unique string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="n"&gt;jay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Jay&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;employee_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;abcd1234&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;# some records could be integers depending on the schema
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we don't define types, PyLance will assume that the contact &lt;code&gt;jay&lt;/code&gt; is the type &lt;code&gt;dict[str, str]&lt;/code&gt; because all the values in the dictionary are &lt;code&gt;str&lt;/code&gt;. What happens if we have a different record like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;kevin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Kevin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;employee_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;12345678&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The variable of &lt;code&gt;kevin&lt;/code&gt; would be typed &lt;code&gt;dict[str, Any]&lt;/code&gt; because the type of the &lt;code&gt;employee_id&lt;/code&gt; differs from the &lt;code&gt;name&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;If we build a function that gets the employee id of multiple entries and sorts by &lt;code&gt;employee_id&lt;/code&gt;, We'll get a &lt;code&gt;TypeError&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_employee_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;retrieve employee id from contact&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;contact&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;employee_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;sorted_employees&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;jay&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kevin&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;get_employee_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Traceback &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;stdin&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;supported&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;instances&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;int&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;str&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The solution is to return the contact variable as a str.  Type Hints would have told us that the contact would have been &lt;code&gt;Any&lt;/code&gt; type (like &lt;code&gt;kevin&lt;/code&gt;). And this would have been a hint we need to make types consistent. &lt;/p&gt;

&lt;p&gt;We could even create a custom named type as Łukasz Langa mentions in his &lt;a href="https://youtu.be/wbohVjhqg7c?t=753" rel="noopener noreferrer"&gt;PyCon US 2022 Keynote&lt;/a&gt;. This would provide helpful hints as we're writing the code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Fcustom_type_contact.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Fcustom_type_contact.png" alt="custom type hint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The July 2022 Update
&lt;/h2&gt;

&lt;p&gt;The aforementioned VS Code Python update made it so that types could be inlayed next to your code. This makes adding type hints much simpler because hints (which are not added to your code) are valid Python code and can be added by the author.&lt;/p&gt;

&lt;p&gt;In this case the hints would have been helpful but I don't want them always be present. There is an existing feature that may be new to Python developers using VS Code that will make showing your type hints only when you want to see them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turning On Inlay Hints
&lt;/h2&gt;

&lt;p&gt;For this to work you must first turn on Inlay Hints for python. Make sure the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-python.python" rel="noopener noreferrer"&gt;Python Extension&lt;/a&gt; is installed in VS Code and search "Python Inlay Hints" in settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Fset_python_inlay_hints.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Fset_python_inlay_hints.gif" alt="python inlay type hints"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first value to turn on is &lt;code&gt;Python › Analysis › Inlay Hints: Function Return Types&lt;/code&gt;. This gives typing for what a function or method is returning.&lt;/p&gt;

&lt;p&gt;The second is &lt;code&gt;Python › Analysis › Inlay Hints: Variable Types&lt;/code&gt;. This inlays hints on variables that are written (like the ones above).&lt;/p&gt;

&lt;h2&gt;
  
  
  Customizing How Inlay Hints Present in Your Editor
&lt;/h2&gt;

&lt;p&gt;Next in settings just search for "Inlay".  You should find &lt;code&gt;Editor › Inlay Hints: Enabled&lt;/code&gt;.  The value is set to &lt;code&gt;on&lt;/code&gt; by default, but it has a few options, including &lt;code&gt;OnUnlessPressed&lt;/code&gt; and &lt;code&gt;OffUnlessPressed&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Fset_inlay_hints.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Fset_inlay_hints.gif" alt="Set Inlay Hints Enabled"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you change the value to &lt;code&gt;OffUnlessPressed&lt;/code&gt;, you will no longer see inlayed hints until you enter &lt;em&gt;Ctrl + Alt&lt;/em&gt; (&lt;em&gt;⌃ + ⌥&lt;/em&gt; on MacOS)&lt;/strong&gt;. When you need a hint, press the keys and the type hints will reappear. Release the keys and they disappear again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Ftoggle_inlay_hints.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjmblogstorrage.blob.core.windows.net%2Fmedia%2Ftoggle_inlay_hints.gif" alt="Toggle Inlay Hints"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also set &lt;code&gt;OnUnlessPressed&lt;/code&gt;. This does the opposite, only showing the code that exists in the file. This entry in settings is also next to other Inlay hint stylings that may help you differentiate your code from hints. &lt;/p&gt;

</description>
      <category>python</category>
      <category>vscode</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Announcing DiversityOrgs.Tech (Beta 2)</title>
      <dc:creator>Jay Miller</dc:creator>
      <pubDate>Wed, 29 Jun 2022 17:08:58 +0000</pubDate>
      <link>https://forem.com/azure/announcing-diversityorgstech-beta-2-f22</link>
      <guid>https://forem.com/azure/announcing-diversityorgstech-beta-2-f22</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Oringally Posted on &lt;a href="https://kjaymiller.com/blog/diversityorgs-tech-beta-2"&gt;kjaymiller.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two years ago, I started working on &lt;a href="https://diversityorgs.tech"&gt;Diversityorgs.Tech&lt;/a&gt; as a project to learn new tools and create a resource for underrepresented folks in tech everywhere. Today I'm happy to announce some amazing new features thanks to the entire project being rebuilt using &lt;a href="https://djangoproject.org"&gt;Django 4&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s start with exploring some of the new features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Map Based Searching:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qOTUORZo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/826yyomi9eyg97yfu13r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qOTUORZo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/826yyomi9eyg97yfu13r.png" alt="Map showing locations for Black Girls Code" width="880" height="443"&gt;&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;It’s good to know what’s in your area. Not only are we indexing city-level locations of these orgs, but you can now find them on a map. Pages with organizations in different locations will present a map so you can view the results in that area. This is powered by Azure Maps for geocoding, and map display.&lt;/p&gt;

&lt;h2&gt;
  
  
  Focused Searching and Filtering
&lt;/h2&gt;

&lt;p&gt;We’ve all had the painful experience of looking for similar results and the service you’re using forces you to reapply all the previous settings manually. For Example, you are looking at PyLadies Atlanta and you want more groups focused on women. You select the women tag and the site will first return orgs in Atlanta with the same tag. On that page there is an option to expand to all orgs with that tag or that location.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PmH1HVRA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rn4h38pgg9cfuqggwsby.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PmH1HVRA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rn4h38pgg9cfuqggwsby.png" alt="Select a Diversity Focus will lead to more results with the same focus in the same location" width="880" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Better Organization Management
&lt;/h2&gt;

&lt;p&gt;One of the biggest barriers to further development previously was that it was very impractical to add/update content. I’ve added two new features to make organization management easier.&lt;/p&gt;

&lt;p&gt;First, organizers can create an account and request moderator rights to an org. Once reviewed and approved, they can make updates to their org’s location, links, logo and more.&lt;/p&gt;

&lt;p&gt;Second, anyone can suggest changes to an organization. These changes will be reviewed, and updates can be made by organizers or administrators&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oLQo_1YM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ak1u3mn1he2dm42iygg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oLQo_1YM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ak1u3mn1he2dm42iygg.png" alt="The Suggest Edit link allow for access to request updates to the view" width="880" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More Than Just a Name
&lt;/h2&gt;

&lt;p&gt;Joining an organization as a member is one of the first steps in getting more involved in the developer community. That said many of those foundational experiences can impact future decisions. This site highlights important things like having a publicly available code of conduct.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OfDiJxJH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eorzflksazk2ekxsrz7j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OfDiJxJH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eorzflksazk2ekxsrz7j.png" alt="An organization page will show if it has a public link to the code of conduct" width="880" height="115"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Speaking of good intentions, we’ve also added the ability to report any organization for removal by ANYONE. Each report is taken seriously and investigated.&lt;/p&gt;

&lt;h2&gt;
  
  
  The API
&lt;/h2&gt;

&lt;p&gt;The REST API is generally available in limited scope with more endpoints available with an API Key. The hope is organizations and municipalities can use the data collected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2QM3iY-K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1mmrccjup80frgauf8w1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2QM3iY-K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1mmrccjup80frgauf8w1.png" alt="API results of orgs in Atlanta" width="880" height="560"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Organizers can even manage the organizations they are responsible for providing easy updates and automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Information Freedom and Data Privacy
&lt;/h2&gt;

&lt;p&gt;This site aims to ensure that folks find helpful information to determine if an organization is right for them. All information for each organization is available for free with no need to create an account unless you are an organizer. The site doesn’t collect or sell personal identifying data nor share information with organizations.&lt;/p&gt;

&lt;p&gt;Simply put, your data is just that, &lt;strong&gt;YOURS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I’ll be working with my team at Microsoft to highlight some of the specifics of deploying and maintaining this app in the Azure ecosystem. You'll be able to see those posts in the future on the &lt;a href="https://dev.to/azure"&gt;Microsoft Azure Dev.To Channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This was a big undertaking that took much of the last few months to get to this point. There are likely bugs and some of the interfaces will undergo some changes. If you spot an issue, please let me know by submitting an issue over on the &lt;a href="https://github.com/kjaymiller/diversity-orgs-django/issues/new/choose"&gt;GitHub Repo&lt;/a&gt;. Lastly, this project is open-source project and accepting contributions from folks at all skill-levels.&lt;/p&gt;

&lt;p&gt;I hope that you'll enjoy using Diversityorgs.Tech and that you point underrepresented folks to this as a resource in their tech career at all stages.&lt;/p&gt;

</description>
      <category>django</category>
      <category>azure</category>
      <category>webdev</category>
      <category>career</category>
    </item>
  </channel>
</rss>
