<?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>DEV Community: Bruno Rocha</title>
    <description>The latest articles on DEV Community by Bruno Rocha (@rochacbruno).</description>
    <link>https://dev.to/rochacbruno</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%2F131111%2F59e2695f-e03c-4345-9281-5b11fc3e9cbc.png</url>
      <title>DEV Community: Bruno Rocha</title>
      <link>https://dev.to/rochacbruno</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rochacbruno"/>
    <language>en</language>
    <item>
      <title>Hello Dev.to</title>
      <dc:creator>Bruno Rocha</dc:creator>
      <pubDate>Tue, 09 Apr 2024 10:56:45 +0000</pubDate>
      <link>https://dev.to/codeshow/hello-devto-3h3l</link>
      <guid>https://dev.to/codeshow/hello-devto-3h3l</guid>
      <description>&lt;p&gt;Olá, estamos chegando!&lt;/p&gt;

&lt;p&gt;O CodeShow é um canal colaborativo com pessoas que criam conteúdo de programação e falamos sobre Python, Java, Rust, Go, SQL, Javascript e muito mais!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Python Protocol Oriented Programming</title>
      <dc:creator>Bruno Rocha</dc:creator>
      <pubDate>Fri, 05 Nov 2021 21:20:00 +0000</pubDate>
      <link>https://dev.to/rochacbruno/python-protocol-oriented-programming-1m0g</link>
      <guid>https://dev.to/rochacbruno/python-protocol-oriented-programming-1m0g</guid>
      <description>&lt;h2&gt;
  
  
  Python Objects 🐍
&lt;/h2&gt;

&lt;p&gt;In Python everything is an &lt;code&gt;object&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An object is formed by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;memory location&lt;/strong&gt; identified internally by an &lt;code&gt;id&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;type (class)&lt;/strong&gt; that determines the protocols of the object.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;value&lt;/strong&gt; (or a set of values) that the object holds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&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="c1"&gt;# Given an object identified by the variable name `a`
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# We can access its memory location `id`
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;1407854654624&lt;/span&gt;

&lt;span class="c1"&gt;# We can access its type
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&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;class &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;# We can access its value
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;

&lt;span class="c1"&gt;# We can use the behavior defined on its protocol
&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hex&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0x1&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above will be similar for &lt;strong&gt;every&lt;/strong&gt; object in Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types 🔠
&lt;/h2&gt;

&lt;p&gt;Every object is based on a type, a type is a &lt;code&gt;class&lt;/code&gt; definition.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;print&lt;/code&gt; &amp;lt;- is &lt;code&gt;function&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"Hello"&lt;/code&gt; &amp;lt;- is &lt;code&gt;str&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;0&lt;/code&gt; &amp;lt;- is &lt;code&gt;int&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[0:5]&lt;/code&gt; &amp;lt;- is a &lt;code&gt;slice&lt;/code&gt; type&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;str.upper&lt;/code&gt; &amp;lt;- is a &lt;code&gt;method_descriptor&lt;/code&gt; type
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt; &lt;span class="n"&gt;Function&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;Integer&lt;/span&gt;       &lt;span class="n"&gt;Slice&lt;/span&gt;
    &lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;  &lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;         &lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&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="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;World!&lt;/span&gt;&lt;span class="sh"&gt;"&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                  &lt;span class="n"&gt;___&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;&lt;span class="n"&gt;___&lt;/span&gt;            &lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;&lt;span class="n"&gt;___&lt;/span&gt;
                   &lt;span class="n"&gt;Symbol&lt;/span&gt;            &lt;span class="n"&gt;Method&lt;/span&gt; &lt;span class="n"&gt;Descriptor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Protocols 📝
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Python is a &lt;strong&gt;POP&lt;/strong&gt; Language (Protocol Oriented Programming)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;strong&gt;type&lt;/strong&gt; of the object determines its implementation, which exposes the behavior, the behavior are the things that the object &lt;strong&gt;can do&lt;/strong&gt; or &lt;strong&gt;things that can be done&lt;/strong&gt; with the object.&lt;/p&gt;

&lt;p&gt;There are languages that calls it &lt;strong&gt;Traits&lt;/strong&gt; of an object.&lt;/p&gt;

&lt;p&gt;Each set of those abilities is what we call a &lt;strong&gt;Protocol&lt;/strong&gt;, protocols are useful for &lt;strong&gt;setting contracts&lt;/strong&gt; 🤝 between objects.&lt;/p&gt;

&lt;p&gt;Identifying protocols on the &lt;strong&gt;Hello World&lt;/strong&gt; program:&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;Callable&lt;/span&gt;  &lt;span class="n"&gt;Subscriptable&lt;/span&gt;   &lt;span class="n"&gt;Sliceable&lt;/span&gt;
    &lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;  &lt;span class="n"&gt;______&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;    &lt;span class="n"&gt;__________&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&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="o"&gt;+&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;World!&lt;/span&gt;&lt;span class="sh"&gt;"&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="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;upper&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
             &lt;span class="n"&gt;________&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;&lt;span class="n"&gt;________&lt;/span&gt;      &lt;span class="n"&gt;__&lt;/span&gt;&lt;span class="err"&gt;⬆️&lt;/span&gt;&lt;span class="n"&gt;__&lt;/span&gt;
                  &lt;span class="n"&gt;Summable&lt;/span&gt;         &lt;span class="n"&gt;Callable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Callable&lt;/strong&gt; 🗣️ Can be invoked using ()&lt;br&gt;
A type is also callable when its protocol includes the &lt;code&gt;__call__&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Subscriptable&lt;/strong&gt;  ✍🏻 its elements can be accessed through a subscription. &lt;br&gt;
The subscription can be numeric ordinal &lt;code&gt;[0]&lt;/code&gt; or named key &lt;code&gt;['name']&lt;/code&gt;. A type is Subscriptable when its protocol includes the &lt;code&gt;__getitem__&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sliceable&lt;/strong&gt; 🔪 its collection of elements can be sliced in parts. &lt;br&gt;
A type is Sliceable when it is &lt;em&gt;Subscriptable&lt;/em&gt; and its &lt;code&gt;__getitem__&lt;/code&gt; method can accept a &lt;code&gt;slice&lt;/code&gt; in place of the &lt;code&gt;index&lt;/code&gt; or &lt;code&gt;name&lt;/code&gt;. A slice is the composition of &lt;code&gt;[start:stop:step]&lt;/code&gt; elements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Summable&lt;/strong&gt; ➕ Can be combined with other objects via &lt;code&gt;+&lt;/code&gt; operation.&lt;br&gt;
The product of this combination is always new object. On numeric types this is the ability to &lt;code&gt;sum&lt;/code&gt; two or more numbers in a set. On sequences it is the &lt;code&gt;concatenation&lt;/code&gt; of its fragments in to one. A type is Summable when its protocol includes the &lt;code&gt;__add__&lt;/code&gt; or &lt;code&gt;__radd__&lt;/code&gt; method.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Printable&lt;/strong&gt; 🖨️ Can be printed using &lt;code&gt;print&lt;/code&gt;&lt;br&gt;
All the Python objects are printable, &lt;code&gt;print&lt;/code&gt; will look either for a &lt;code&gt;__repr__&lt;/code&gt; or a &lt;code&gt;__str__&lt;/code&gt; method for printing the object.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ There are many more and in fact, you can define custom protocols, Protocols are very generic and there is no official list of protocols although there are some pre-defined protocols in the typing module.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&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;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Iterator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Iterable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Awaitable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Generic&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Complete list of protocols and sub typing is available on &lt;a href="https://mypy.readthedocs.io/en/stable/protocols.html"&gt;https://mypy.readthedocs.io/en/stable/protocols.html&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🦆 Protocols empowers an approach called &lt;strong&gt;Duck Typing&lt;/strong&gt; which is the fact that in &lt;strong&gt;Python&lt;/strong&gt; if an object looks like, behaves like, and has the behavior of a &lt;strong&gt;Duck&lt;/strong&gt;, it is said to be a &lt;strong&gt;Duck&lt;/strong&gt;, regardless if this is the case of a &lt;strong&gt;Dog&lt;/strong&gt; that learned to say &lt;strong&gt;quack&lt;/strong&gt; immitating a &lt;strong&gt;Duck&lt;/strong&gt; 🐶.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Typing and Protocol Checking
&lt;/h2&gt;

&lt;p&gt;Some protocols can be checked using built-in functions&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="nf"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="nf"&gt;callable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some protocols must be checked against its &lt;strong&gt;type class&lt;/strong&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="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="nf"&gt;isinstance&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="nb"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are cases where the only way to verify protocols&lt;br&gt;
is checking for its attributes.&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="nf"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&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;__add__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;  &lt;span class="c1"&gt;# Summable, we can use `+` operator.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Others where we need to use the &lt;strong&gt;EAFP&lt;/strong&gt; pattern.&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;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; 
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c1"&gt;# Strong type checking
&lt;/span&gt;    &lt;span class="c1"&gt;# we cannot `__add__` an `str` to an `int`
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Typing Protocols
&lt;/h2&gt;

&lt;p&gt;Python3 offers a way to define custom protocols&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runtime_checkable&lt;/span&gt;

&lt;span class="nd"&gt;@runtime_checkable&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CallableSummableSubscriptable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__call__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
        &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__add__&lt;/span&gt;&lt;span class="p"&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;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
        &lt;span class="bp"&gt;...&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__getitem__&lt;/span&gt;&lt;span class="p"&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;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;T&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;blockquote&gt;
&lt;p&gt;ℹ️ Protocol methods are just signatures with empty bodies, stated by the &lt;code&gt;...&lt;/code&gt;. &lt;code&gt;T&lt;/code&gt; is usually a type alias indicating a generic type.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Protocols are useful to define contracts, bounds on function signatures for example defining a function that accepts an argument only if the type has the specified protocol.&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;awesome_function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;thing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;CallableSummableSubscriptable&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# accepts only objects that implements that ⬆️ protocol.
&lt;/span&gt;    &lt;span class="c1"&gt;# Protocols can be checked at runtime @runtime_checkable
&lt;/span&gt;    &lt;span class="c1"&gt;# Or checked using static analysers e.g: mypy
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Is there the Traditional OOP in Python?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;OOP&lt;/strong&gt; Python is actually &lt;strong&gt;POP&lt;/strong&gt; (Protocol Oriented Programming)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;More&lt;/strong&gt; about &lt;strong&gt;Protocols&lt;/strong&gt; and &lt;strong&gt;Behavior&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Less&lt;/strong&gt; about tradicional OOP concepts.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All the traditional concepts and patterns are also available, but some are intrinsic to objects and protocols that in the end of the day the programmers doesn't have to take care of it at all in the same way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inheritance
&lt;/h3&gt;

&lt;p&gt;The ability to &lt;strong&gt;inherit&lt;/strong&gt; from another base type and take all its behavior and the ability to &lt;strong&gt;override&lt;/strong&gt; with custom implementation.&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;class&lt;/span&gt; &lt;span class="nc"&gt;MyString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__str__&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;upper&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="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MyString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bruno&lt;/span&gt;&lt;span class="sh"&gt;"&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BRUNO&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Encapsulation
&lt;/h3&gt;

&lt;p&gt;The ability to &lt;strong&gt;hide&lt;/strong&gt; object attributes and methods and expose only a selected set of them or to &lt;strong&gt;expose&lt;/strong&gt; them in a more controlled way.&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="c1"&gt;# Descriptor is a protocol for getter/setter like approach.
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__get__&lt;/span&gt;&lt;span class="p"&gt;(...):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__set__&lt;/span&gt;&lt;span class="p"&gt;(...):&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Thing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Double underline means that the field is private
&lt;/span&gt;    &lt;span class="c1"&gt;# but actually it is only a naming mangling convention.
&lt;/span&gt;    &lt;span class="n"&gt;__protected_attr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Properties can also be used to define getter/setter
&lt;/span&gt;    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; 
        &lt;span class="k"&gt;return&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;__protected_attr&lt;/span&gt;
    &lt;span class="nd"&gt;@foo.setter&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_foo&lt;/span&gt;&lt;span class="p"&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;value&lt;/span&gt;&lt;span class="p"&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;__protected_attr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Polymorfism
&lt;/h3&gt;

&lt;p&gt;The ability for objects to behave differently regardless of its base type and for procedures to take different types of objects as arguments.&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bruno&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;len&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;key&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;other&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&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;Hello&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;World&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;ℹ️ In traditional OOP literature &lt;strong&gt;polymorphism&lt;/strong&gt; is often used to define only the ability to have methods reusing the same name but different implementation, but in fact it goes deeper than this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;🧑‍🍳 A Chef when selecting ingredients for a recipe, will look for the &lt;strong&gt;protocols&lt;/strong&gt; defined on each ingredient, the Chef can go to the supermarket and see a set of different types of onions 🧅, even if the recipe only says &lt;strong&gt;onion&lt;/strong&gt; the Chef knows based on the desired behavior that wants a specific &lt;strong&gt;type&lt;/strong&gt; of onion, white onions are swetter, better for cooked recipes, the purple onions are more acid so better for salads and raw recipes. (but that also depends a bit on taste)&lt;/p&gt;

&lt;p&gt;🧑‍💻 The Software Engineer when choosing the data structures to use in an algorithm 🤖 must look to the protocols defined and how the objects behaves even if the requirements says it is a collection of texts for example, the engineer must analyse the program to choose wisely between a &lt;strong&gt;tuple&lt;/strong&gt;, a &lt;strong&gt;list&lt;/strong&gt; or even a &lt;strong&gt;set&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The protocols are often more important than the types.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: Credits to @mathsppblog to have inspired the first paragraph of this post &lt;a href="https://twitter.com/mathsppblog/status/1445148609977126914"&gt;https://twitter.com/mathsppblog/status/1445148609977126914&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>oop</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>[EN] I am Learning Rust - Exercism Space Age</title>
      <dc:creator>Bruno Rocha</dc:creator>
      <pubDate>Mon, 30 Mar 2020 03:03:10 +0000</pubDate>
      <link>https://dev.to/rochacbruno/en-i-am-learning-rust-exercism-space-age-2kaj</link>
      <guid>https://dev.to/rochacbruno/en-i-am-learning-rust-exercism-space-age-2kaj</guid>
      <description>&lt;p&gt;Resolving Space Age Exercism in Rust language&lt;/p&gt;

&lt;p&gt;Used Traits and Macros.&lt;/p&gt;

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

</description>
      <category>rust</category>
      <category>exercism</category>
      <category>codeshow</category>
    </item>
    <item>
      <title>Never do this in Python</title>
      <dc:creator>Bruno Rocha</dc:creator>
      <pubDate>Thu, 06 Feb 2020 02:01:07 +0000</pubDate>
      <link>https://dev.to/rochacbruno/never-do-this-in-python-357e</link>
      <guid>https://dev.to/rochacbruno/never-do-this-in-python-357e</guid>
      <description>&lt;p&gt;This video is published in 2 languages.&lt;/p&gt;

&lt;p&gt;In English:&lt;/p&gt;

&lt;p&gt;In this video I share some things you should avoid doing in when #programming in #python, so called Python #antipatterns and I also show you examples of how to achieve the same result in a better way.&lt;/p&gt;

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

&lt;p&gt;In Portuguese:&lt;/p&gt;

&lt;p&gt;Neste video eu falo sobre algumas coisas que não devemos fazer ao programar em #python, algumas práticas que são caracterizadas como #antipatterns e que podem trazer problemas para o seu #software.&lt;/p&gt;

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

</description>
      <category>python</category>
    </item>
    <item>
      <title>Criando seu blog com Zola e hospedando de graça na Netlify</title>
      <dc:creator>Bruno Rocha</dc:creator>
      <pubDate>Mon, 18 Nov 2019 19:56:07 +0000</pubDate>
      <link>https://dev.to/rochacbruno/criando-seu-blog-com-zola-e-hospedando-de-graca-na-netlify-225c</link>
      <guid>https://dev.to/rochacbruno/criando-seu-blog-com-zola-e-hospedando-de-graca-na-netlify-225c</guid>
      <description>&lt;h1&gt;
  
  
  Criando seu blog com Zola e hospedando de graça na Netlify
&lt;/h1&gt;

&lt;p&gt;A forma mais prática para publicar blogs, especialmente se o blog for de uma pessoa desenvolvedora é a utilização de sites estáticos, são inúmeras as vantagens dessa abordagem.&lt;/p&gt;

&lt;p&gt;Os motivos que nos levam a escolher sites estáticos ao invés de um &lt;strong&gt;CMS&lt;/strong&gt; completo incluem a simplicidade da linguagem &lt;strong&gt;Markdown&lt;/strong&gt;, a possibilidade de armazenar o conteúdo gratuitamente em um repositório do &lt;strong&gt;Github&lt;/strong&gt; ou &lt;strong&gt;Gitlab&lt;/strong&gt;, a rapidez na renderização do conteúdo, a facilidade na migração caso precise mudar de servidor, a hospedagem gratuita em serviços como &lt;a href="http://netlify.com"&gt;Netlify&lt;/a&gt; ou Github Pages e é claro não ter que manter bancos de dados e servidores web.&lt;/p&gt;

&lt;p&gt;Eu mesmo já tentei criar meu próprio CMS algumas vezes (&lt;a href="http://github.com/opps"&gt;1&lt;/a&gt;, &lt;a href="http://github.com/rochacbruno-archive/quokka"&gt;2&lt;/a&gt;) e no final das contas percebi que eu não preciso de um &lt;strong&gt;CMS&lt;/strong&gt; complexo e você provavelmente também não.&lt;/p&gt;

&lt;h2&gt;
  
  
  Componentes
&lt;/h2&gt;

&lt;p&gt;Estes são os componentes que usaremos nesta solução.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.markdownguide.org/cheat-sheet/"&gt;Markdown&lt;/a&gt; - Linguagem de marcação para o conteúdo.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://git-scm.com/"&gt;Git&lt;/a&gt; (github/gitlab) - Repositório onde o conteúdo será armazenado.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getzola.org"&gt;Zola&lt;/a&gt; - Ferramenta que irá gerar o site estatico a partir dos arquivos markdown.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://help.github.com/en/github/writing-on-github/about-writing-and-formatting-on-github"&gt;Github UI&lt;/a&gt; ou seu editor favorito - Local onde escreveremos novos posts no blog.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://netlify.com"&gt;Netlify&lt;/a&gt; - Serviço de hospedagem que fará os deploys automaticamente do blog.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Zola
&lt;/h2&gt;

&lt;p&gt;O &lt;a href="http://getzola.org"&gt;Zola&lt;/a&gt; é um programa escrito em &lt;a href="http://rustlang.org"&gt;Rust&lt;/a&gt; para a geração de sites estáticos, com ele é possivel criar sites, single page apps e também blogs.&lt;/p&gt;

&lt;p&gt;Eu estava a procura de um gerador de sites estáticos para construir este blog e como estou&lt;br&gt;
bastante interessado em praticar com &lt;strong&gt;Rust&lt;/strong&gt; eu fui ao &lt;a href="https://github.com/awesome-rust-com/awesome-rust"&gt;AwesomeRust&lt;/a&gt; e fiz uma busca por &lt;strong&gt;static-site&lt;/strong&gt; e nesta lista estava o &lt;strong&gt;Zola&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Dei uma rápida olhada em seu &lt;a href="https://github.com/getzola/zola"&gt;código fonte&lt;/a&gt; para saber se eu teria condições de contribuir para o projeto caso viesse a adotar.&lt;/p&gt;

&lt;p&gt;Algumas coisas me fizeram escolher o &lt;strong&gt;Zola&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Escrito em &lt;strong&gt;Rust&lt;/strong&gt; (Rápido e Seguro)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;# Markdown é **amor**&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Binário único &lt;code&gt;$ zola&lt;/code&gt;, apenas &lt;code&gt;20MB&lt;/code&gt; com tudo incluido para gerar o blog.&lt;/li&gt;
&lt;li&gt;Templates &lt;a href="https://tera.netlify.com/"&gt;Tera&lt;/a&gt; que tem a &lt;code&gt;{{ sintaxe }}&lt;/code&gt; bem parecida com o &lt;a href="https://jinja.palletsprojects.com/"&gt;Jinja&lt;/a&gt; do &lt;strong&gt;Python&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Syntax Highlight.&lt;/li&gt;
&lt;li&gt;Shortcodes (diretivas Markdown customizáveis).&lt;/li&gt;
&lt;li&gt;Processamento de imagens.&lt;/li&gt;
&lt;li&gt;Muitos &lt;a href="https://www.getzola.org/themes/"&gt;Temas&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Deploy simples na Netlify e Github Pages.&lt;/li&gt;
&lt;li&gt;Todas as features de um gerador de sites estáticos.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Instalação
&lt;/h2&gt;

&lt;p&gt;Na verdade não há instalação, o &lt;strong&gt;Zola&lt;/strong&gt; é distribuído já compilado e é um único binário que você pode baixar na página de &lt;a href="https://github.com/getzola/zola/releases"&gt;releases&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A versão mais atual no momento desta postagem é a &lt;code&gt;0.9.0&lt;/code&gt; e para iniciar o seu &lt;strong&gt;Blog&lt;/strong&gt; você pode seguir estes passos.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Considerando um sistema Linux, porém se você estiver no &lt;a href="https://github.com/getzola/zola/releases/download/v0.9.0/zola-v0.9.0-x86_64-pc-windows-msvc.zip"&gt;Windows&lt;/a&gt; ou &lt;a href="https://github.com/getzola/zola/releases/download/v0.9.0/zola-v0.9.0-x86_64-apple-darwin.tar.gz"&gt;Mac&lt;/a&gt; veja os links na página de &lt;a href="https://github.com/getzola/zola/releases"&gt;releases&lt;/a&gt; e adapte para o seu O.S.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Baixando o Zola (linux)&lt;/span&gt;
wget https://github.com/getzola/zola/releases/download/v0.9.0/zola-v0.9.0-x86_64-unknown-linux-gnu.tar.gz

&lt;span class="c"&gt;# Descompactando&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xvzf&lt;/span&gt; zola-v0.9.0-x86_64-unknown-linux-gnu.tar.gz
&lt;span class="nb"&gt;rm &lt;/span&gt;zola-v0.9.0-x86_64-unknown-linux-gnu.tar.gz

&lt;span class="c"&gt;# Executando&lt;/span&gt;
./zola &lt;span class="nt"&gt;--help&lt;/span&gt;

&lt;span class="c"&gt;# Saída&lt;/span&gt;
SUBCOMMANDS:
    build    Deletes the output directory &lt;span class="k"&gt;if &lt;/span&gt;there is one and builds the site
    check    Try building the project without rendering it. Checks links
    init     Create a new Zola project
    serve    Serve the site. Rebuild and reload on change automatically
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Se tudo funcionou bem até aqui é hora de iniciar um projeto e começar a escrever o conteúdo para o blog.&lt;/p&gt;

&lt;h2&gt;
  
  
  Criando um novo site Zola
&lt;/h2&gt;

&lt;p&gt;Este processo é bem simples rodando o comando &lt;code&gt;$ zola..&lt;/code&gt; &lt;strong&gt;&lt;a href="https://codeshow.com.br/criando-seu-blog-com-zola-e-hospedando-de-graca-na-netlify/#criando-um-novo-site-zola"&gt;Clique aqui para continuar lendo...&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Este conteúdo também está disponível em áudio:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="100%" height="232px" src="https://open.spotify.com/embed/episode/7wc51XnCdHeOv70sxQr6OD%20"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>rust</category>
      <category>zola</category>
      <category>blog</category>
      <category>staticsite</category>
    </item>
    <item>
      <title>from dynaconf import settings</title>
      <dc:creator>Bruno Rocha</dc:creator>
      <pubDate>Fri, 12 Apr 2019 16:40:11 +0000</pubDate>
      <link>https://dev.to/rochacbruno/from-dynaconf-import-settings-2f8o</link>
      <guid>https://dev.to/rochacbruno/from-dynaconf-import-settings-2f8o</guid>
      <description>&lt;p&gt;Often when starting a new Python project we need to spend some time thinking about how to manage the settings, decide on which module the configuration manager will be written, decide which name to give to this module, create a class or function to store the configuration keys, create the conditions for multiple environments and still need to worry about where these keys will be stored and in which file format?&lt;/p&gt;

&lt;p&gt;No more! now you have &lt;a href="http://github.com/rochacbruno/dynaconf" rel="noopener noreferrer"&gt;Dynaconf&lt;/a&gt;!&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&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%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/rochacbruno" rel="noopener noreferrer"&gt;
        rochacbruno
      &lt;/a&gt; / &lt;a href="https://github.com/rochacbruno/dynaconf-mirror" rel="noopener noreferrer"&gt;
        dynaconf-mirror
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      dynaconf mirror (mainly for stats)- ORIGINAL REPO ON - https://github.com/dynaconf/dynaconf
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/rochacbruno/dynaconf-mirror/art/header.png?v2"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Frochacbruno%2Fdynaconf-mirror%2Fart%2Fheader.png%3Fv2" alt="dynaconf. new logo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;dynaconf&lt;/strong&gt; - Configuration Management for Python.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/rochacbruno/dynaconf-mirror/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1c4728225f85d1d04552d844137d2689ca3fdba22d7db01d13ed8019041f3da6/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d3030374543372e7376673f7374796c653d666c61742d737175617265" alt="MIT License"&gt;&lt;/a&gt; &lt;a href="https://pypi.python.org/pypi/dynaconf" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/262b1307615052a5d54e5a3b4493fb61f01ba132f4d5992afb67f0196df62503/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f64796e61636f6e662e737667" alt="PyPI"&gt;&lt;/a&gt; &lt;a href="https://github.com/rochacbruno/dynaconf-mirror" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/f151bb2a1d4574fb4c9252f654270914c4e9c4a99c42eb92bfa6106d3d661ccc/68747470733a2f2f696d672e736869656c64732e696f2f707970692f707976657273696f6e732f64796e61636f6e662e737667" alt="PyPI"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/96ec97df987eb8576ff8e55c2817caa5eaefe88ffb42fe41dd62ab856e162e47/68747470733a2f2f696d672e736869656c64732e696f2f707970692f646d2f64796e61636f6e662e7376673f6c6162656c3d706970253230696e7374616c6c73266c6f676f3d707974686f6e"&gt;&lt;img src="https://camo.githubusercontent.com/96ec97df987eb8576ff8e55c2817caa5eaefe88ffb42fe41dd62ab856e162e47/68747470733a2f2f696d672e736869656c64732e696f2f707970692f646d2f64796e61636f6e662e7376673f6c6162656c3d706970253230696e7374616c6c73266c6f676f3d707974686f6e" alt="PyPI - Downloads"&gt;&lt;/a&gt; &lt;a href="https://github.com/dynaconf/dynaconf/actions/workflows/main.yml" rel="noopener noreferrer"&gt;&lt;img src="https://github.com/dynaconf/dynaconf/actions/workflows/main.yml/badge.svg" alt="CI"&gt;&lt;/a&gt; &lt;a href="https://codecov.io/gh/dynaconf/dynaconf" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/0241dd2a522e7f6103b0cba512237f7e0c548a673102d779ca28b33453af01f4/68747470733a2f2f636f6465636f762e696f2f67682f64796e61636f6e662f64796e61636f6e662f6272616e63682f6d61737465722f67726170682f62616467652e737667" alt="codecov"&gt;&lt;/a&gt; &lt;a href="https://www.codacy.com/gh/dynaconf/dynaconf/dashboard?utm_source=github.com&amp;amp;utm_medium=referral&amp;amp;utm_content=dynaconf/dynaconf&amp;amp;utm_campaign=Badge_Grade" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/bdf7c95e2e264fc461a97ecd9e761bf68aaa52b09f770006d43723ae4647be61/68747470733a2f2f6170702e636f646163792e636f6d2f70726f6a6563742f62616467652f47726164652f3366623264653938343634343432663939613736363331383138303362343030" alt="Codacy Badge"&gt;&lt;/a&gt;  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/61c90eddb29c58806a87f4b1d2fa5b7eb7b19ea3c4509d6d04325e6f625d496d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f64796e61636f6e662f64796e61636f6e662e737667"&gt;&lt;img src="https://camo.githubusercontent.com/61c90eddb29c58806a87f4b1d2fa5b7eb7b19ea3c4509d6d04325e6f625d496d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f64796e61636f6e662f64796e61636f6e662e737667" alt="GitHub stars"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/668f3b141ad780af773837b36e856f4c60cbabac25b5186040a0675441033e4c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652d646174652f64796e61636f6e662f64796e61636f6e662e737667"&gt;&lt;img src="https://camo.githubusercontent.com/668f3b141ad780af773837b36e856f4c60cbabac25b5186040a0675441033e4c/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652d646174652f64796e61636f6e662f64796e61636f6e662e737667" alt="GitHub Release Date"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/cd4ddc582c79ac0ec85f58ce3c4391ceb5bd6940c3e82d832b09af7551ab7a33/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6d6d6974732d73696e63652f64796e61636f6e662f64796e61636f6e662f6c61746573742e737667"&gt;&lt;img src="https://camo.githubusercontent.com/cd4ddc582c79ac0ec85f58ce3c4391ceb5bd6940c3e82d832b09af7551ab7a33/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f636f6d6d6974732d73696e63652f64796e61636f6e662f64796e61636f6e662f6c61746573742e737667" alt="GitHub commits since latest release"&gt;&lt;/a&gt; &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/ed2b3b78b59fd4ed16914e388c2da61f0bc714fa352c3478fff99b7f276f2a3b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f64796e61636f6e662f64796e61636f6e662e737667"&gt;&lt;img src="https://camo.githubusercontent.com/ed2b3b78b59fd4ed16914e388c2da61f0bc714fa352c3478fff99b7f276f2a3b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6173742d636f6d6d69742f64796e61636f6e662f64796e61636f6e662e737667" alt="GitHub last commit"&gt;&lt;/a&gt; &lt;a href="https://github.com/ambv/black/" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5bf9e9fa18966df7cb5fac7715bef6b72df15e01a6efa9d616c83f9fcb527fe2/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f636f64652532307374796c652d626c61636b2d3030303030302e737667" alt="Code Style Black"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/f66e8a92b0fa2ee9ef0983f7dba5a7dea6c82b0683ceb310465b2f14634b9fdc/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f64796e61636f6e662f64796e61636f6e662e737667"&gt;&lt;img src="https://camo.githubusercontent.com/f66e8a92b0fa2ee9ef0983f7dba5a7dea6c82b0683ceb310465b2f14634b9fdc/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f64796e61636f6e662f64796e61636f6e662e737667" alt="GitHub issues"&gt;&lt;/a&gt; &lt;a href="https://github.com/dynaconf/dynaconf/discussions" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/1ab5ff6c900ec11598007e4313614e71a2f44e2f4ce6b1f7009b0c1c40d870ce/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f75736572732d666f72756d2d626c75652e7376673f6c6f676f3d676f6f676c6563686174" alt="User Forum"&gt;&lt;/a&gt; &lt;a href="https://gitter.im/dynaconf/dev?utm_source=badge&amp;amp;utm_medium=badge&amp;amp;utm_campaign=pr-badge&amp;amp;utm_content=badge" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5c9cfd91abb5d92cd9bb73fb08d02c55612ef4eff16dfeae56aece432c963609/68747470733a2f2f6261646765732e6769747465722e696d2f64796e61636f6e662f6465762e737667" alt="Join the chat at https://gitter.im/dynaconf/dev"&gt;&lt;/a&gt; &lt;a href="https://matrix.to/#/#dynaconf:matrix.org" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/e02e0b61005118d0f7f3acf0116d56770d322aef7342e99991d856288e301856/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6465762d726f6f6d2d626c75652e7376673f6c6f676f3d6d6174726978" alt=" Matrix"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Inspired by the &lt;a href="https://12factor.net/config" rel="nofollow noopener noreferrer"&gt;12-factor application guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Settings management (default values, validation, parsing, templating)&lt;/li&gt;
&lt;li&gt;Protection of sensitive information (passwords/tokens)&lt;/li&gt;
&lt;li&gt;Multiple file formats &lt;code&gt;toml|yaml|json|ini|py&lt;/code&gt; and also customizable loaders.&lt;/li&gt;
&lt;li&gt;Full support for environment variables to override existing settings (dotenv support included).&lt;/li&gt;
&lt;li&gt;Optional layered system for multi environments &lt;code&gt;[default, development, testing, production]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Built-in support for Hashicorp Vault and Redis as settings and secrets storage.&lt;/li&gt;
&lt;li&gt;Built-in extensions for &lt;strong&gt;Django&lt;/strong&gt; and &lt;strong&gt;Flask&lt;/strong&gt; web frameworks.&lt;/li&gt;
&lt;li&gt;CLI for common operations such as &lt;code&gt;init, list, write, validate, export&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;full docs on &lt;a href="https://dynaconf.com" rel="nofollow noopener noreferrer"&gt;https://dynaconf.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Install&lt;/h3&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;$ pip install dynaconf&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;Initialize Dynaconf on project root directory&lt;/h4&gt;
&lt;/div&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;$ cd path/to/your/project/
$ dynaconf init -f toml

⚙️  Configuring your Dynaconf environment
------------------------------------------
🐍 The file `config.py` was generated.

🎛️  settings.toml created to hold your settings.

🔑 .secrets.toml created to hold your secrets.

🙈 the .secrets.* is also included in `.gitignore`
  beware to not push your secrets&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/rochacbruno/dynaconf-mirror" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Spend your precious time developing your application, run &lt;code&gt;pip install dynaconf&lt;/code&gt; and let Dynaconf take care of your settings.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick start.
&lt;/h2&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;dynaconf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! &lt;/p&gt;

&lt;p&gt;That is the only line of code you need, no complicated boilerplate, no &lt;a href="https://i.imgur.com/rxxTUoe.jpg" rel="noopener noreferrer"&gt;hadouken-ifs&lt;/a&gt;, no need to maintain config classes.&lt;/p&gt;

&lt;p&gt;You must be wondering - &lt;strong&gt;"What magic is this? Where does the setting values come from?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, there is no magic, and the values can come from wherever you want, by default and following the recommendations of the &lt;a href=""&gt;12 factor apps&lt;/a&gt; Dynaconf has preference for environment variables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# optionally you can save it in .env file&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DYNACONF_DEBUG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
export &lt;/span&gt;&lt;span class="nv"&gt;DYNACONF_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Bruno
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dynaconf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python3 app.py
Bruno
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;And the environment variables for Dynaconf are typed using the &lt;code&gt;toml&lt;/code&gt; format so&lt;code&gt;true&lt;/code&gt; has been evaluated to boolean &lt;code&gt;True&lt;/code&gt; and this makes it possible to export lists, dictionaries, floats, booleans, and so on.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://dynaconf.readthedocs.io/en/latest/guides/environment_variables.html" rel="noopener noreferrer"&gt;Read more about envvars&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  More than environment variables
&lt;/h2&gt;

&lt;p&gt;Well, that's cool, but your project will not have settings coming from just the environment variables, I'm sure you want to have a settings file where you can set  default values.&lt;/p&gt;

&lt;p&gt;Dynaconf can read multiple file formats, out of the box it supports &lt;code&gt;.py&lt;/code&gt;, &lt;code&gt;.toml&lt;/code&gt;, &lt;code&gt;.ini&lt;/code&gt; and &lt;code&gt;.json&lt;/code&gt;. If &lt;code&gt;PyYAML&lt;/code&gt; is installed then it will also support &lt;code&gt;.yaml&lt;/code&gt; and you don't have to take care of finding and opening the files. The preferred format is &lt;code&gt;.toml&lt;/code&gt; because it is currently the best configuration format, widely addopted, and you can use whatever file format you want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="c"&gt;# settings.toml&lt;/span&gt;
&lt;span class="nn"&gt;[default]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bruno"&lt;/span&gt;

&lt;span class="nn"&gt;[development]&lt;/span&gt;
&lt;span class="py"&gt;debug&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="nn"&gt;[production]&lt;/span&gt;
&lt;span class="py"&gt;debug&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dynaconf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DEBUG&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NAME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;python3 app.py
Bruno
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And as you can see now using &lt;code&gt;settings.&lt;/code&gt; file we can have separate &lt;code&gt;[environments]&lt;/code&gt; by default dynaconf will always work on &lt;code&gt;[development]&lt;/code&gt; which means only &lt;code&gt;[default]&lt;/code&gt; and &lt;code&gt;[development]&lt;/code&gt; variables will be loaded. At any time you can do &lt;code&gt;export ENV_FOR_DYNACONF=production&lt;/code&gt; and then it starts using the values from &lt;code&gt;[production]&lt;/code&gt; environment.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you don't want to have that separation by environment, you can simply put everything under &lt;code&gt;[default]&lt;/code&gt; section.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Read more about &lt;a href="https://dynaconf.readthedocs.io/en/latest/guides/usage.html#working-environments" rel="noopener noreferrer"&gt;environments and settings file&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Some values are secrets
&lt;/h2&gt;

&lt;p&gt;A good practice is to not store your &lt;strong&gt;secrets&lt;/strong&gt; like &lt;strong&gt;passwords&lt;/strong&gt; and &lt;strong&gt;tokens&lt;/strong&gt; directly on settings files, because you can make a mistake and commit that to a public git repository, so there are some alternatives to store &lt;strong&gt;secrets&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment Variables
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Not recommended&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are some people who &lt;a href="https://diogomonica.com/2017/03/27/why-you-shouldnt-use-env-variables-for-secret-data/" rel="noopener noreferrer"&gt;disagrees&lt;/a&gt; and it is really a point of security failure. However, if you are sure that your machine is protected, you can leave the secrets in the variables, at your own risk, Dynaconf can read it normally.&lt;/p&gt;

&lt;h3&gt;
  
  
  Secret files
&lt;/h3&gt;

&lt;p&gt;This is a simple level of security for keeping secrets, and it is specially useful to keep &lt;code&gt;development&lt;/code&gt; secrets. That &lt;strong&gt;token&lt;/strong&gt; you use to access the development API etc.&lt;/p&gt;

&lt;p&gt;It is very simple, together with your normal &lt;code&gt;settings.toml&lt;/code&gt; you put a new file called &lt;code&gt;.secrets.toml&lt;/code&gt; and store your sensitive data there. Dynaconf will read it after the read of the &lt;code&gt;settings.toml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Wait.. how does it solve my security problem?&lt;/p&gt;

&lt;p&gt;Well it does not (yet) but it make your life easier in 2 ways.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Put &lt;code&gt;.secrets.*&lt;/code&gt; in your &lt;code&gt;~/.gitignore&lt;/code&gt; so you will never commit the mistake of sending that data to a public git repository.&lt;/li&gt;
&lt;li&gt;Dynaconf can output debug information when &lt;code&gt;DEBUG_LEVEL_FOR_DYNACON=DEBUG&lt;/code&gt; is exported, all loaded values are printed but if the values comes from a &lt;code&gt;.secrets.*&lt;/code&gt; file, then only the key is printed and the value is masked. It is useful to use on public CI.&lt;/li&gt;
&lt;li&gt;You can setup a step on your Ansible deployment playbook that will safely copy or generate the secrets file to store there on your production environment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can also tell Dynaconf to load that file from somewhere else &lt;code&gt;export SECRETS_FOR_DYNACONF=/path/to/secrets/location/.secrets.yaml&lt;/code&gt; (very useful for CI like Jenkins)&lt;/p&gt;

&lt;h3&gt;
  
  
  Vault Project from Hashicorp
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Recommended!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we are really talking about &lt;strong&gt;true security&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Using &lt;strong&gt;Vault&lt;/strong&gt; is the better way to protect your secrets dynaconf has built-in support:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VAULT_ENABLED_FOR_DYNACONF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
export &lt;/span&gt;&lt;span class="nv"&gt;VAULT_URL_FOR_DYNACONF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;https://..../
&lt;span class="nb"&gt;export &lt;/span&gt;OTHER_VAULT_CONFIGS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then if have for example the &lt;code&gt;TOKEN&lt;/code&gt; stores on your vault server you can simply do:&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dynaconf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="nf"&gt;perform_your_authentication&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TOKEN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vault has lots of features like leases and sealed vaults.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dynaconf.readthedocs.io/en/latest/guides/sensitive_secrets.html" rel="noopener noreferrer"&gt;Read More&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Are you using Django or Flask?
&lt;/h2&gt;

&lt;p&gt;Dynaconf provides extensions for those 2 frameworks, with 2 lines of code you enable it and then your framework will start reading settings from Dynaconf.&lt;/p&gt;

&lt;h3&gt;
  
  
  Django
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# settings.py
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dynaconf&lt;/span&gt;  &lt;span class="c1"&gt;# noqa
&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dynaconf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DjangoDynaconf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you if you do &lt;code&gt;export DJANGO_FOO=BAR&lt;/code&gt; you can access inside your app via &lt;code&gt;django.conf.settings.FOO&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dynaconf.readthedocs.io/en/latest/guides/django.html" rel="noopener noreferrer"&gt;read more&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Flask
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app.py
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dynaconf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FlaskDynaconf&lt;/span&gt;
&lt;span class="nc"&gt;FlaskDynaconf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you if you do &lt;code&gt;export FLASK_FOO=BAR&lt;/code&gt; you can access inside your app via &lt;code&gt;app.config['FOO']&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dynaconf.readthedocs.io/en/latest/guides/flask.html" rel="noopener noreferrer"&gt;read more&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What if you are using a different settings file format? a different framework and a different external storage?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;You can extend Dynaconf adding new loaders!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dynaconf already provides loaders for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.py&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.json&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yaml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.toml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.ini&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Redis Server&lt;/li&gt;
&lt;li&gt;Vault Server&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.env&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But if this is not a fit for your project you can still &lt;a href="https://dynaconf.readthedocs.io/en/latest/guides/extend.html" rel="noopener noreferrer"&gt;create your own loader&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Dynaconf is the only thing you need to manage your settings!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Well tested&lt;/li&gt;
&lt;li&gt;Trusted by companies like Red Hat, Seek, Catho and others&lt;/li&gt;
&lt;li&gt;Well tested both on Linux and Windows environment&lt;/li&gt;
&lt;li&gt;Strict separation of settings from code (following &lt;a href="https://12factor.net/config" rel="noopener noreferrer"&gt;12-factor applications&lt;/a&gt; Guide).&lt;/li&gt;
&lt;li&gt;Define comprehensive default values.&lt;/li&gt;
&lt;li&gt;Store parameters in multiple file formats (&lt;strong&gt;.toml&lt;/strong&gt;, .json, .yaml, .ini and .py).&lt;/li&gt;
&lt;li&gt;Sensitive &lt;strong&gt;secrets&lt;/strong&gt; like tokens and passwords can be stored in safe places like &lt;code&gt;.secrets&lt;/code&gt; file or &lt;code&gt;vault server&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Parameters can optionally be stored in external services like Redis server.&lt;/li&gt;
&lt;li&gt;Simple &lt;strong&gt;feature flag&lt;/strong&gt; system.&lt;/li&gt;
&lt;li&gt;Layered &lt;strong&gt;[environment]&lt;/strong&gt; system.&lt;/li&gt;
&lt;li&gt;Environment variables can be used to override parameters.&lt;/li&gt;
&lt;li&gt;Support for &lt;code&gt;.env&lt;/code&gt; files to automate the export of environment variables.&lt;/li&gt;
&lt;li&gt;Correct data types (even for environment variables).&lt;/li&gt;
&lt;li&gt;Have &lt;strong&gt;only one&lt;/strong&gt; canonical settings module to rule all your instances.&lt;/li&gt;
&lt;li&gt;Drop in extension for &lt;strong&gt;Flask&lt;/strong&gt; &lt;code&gt;app.config&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;Drop in extension for &lt;strong&gt;Django&lt;/strong&gt; &lt;code&gt;conf.settings&lt;/code&gt; object.&lt;/li&gt;
&lt;li&gt;Powerful &lt;strong&gt;$ dynaconf&lt;/strong&gt; CLI to help you manage your settings via console.&lt;/li&gt;
&lt;li&gt;Customizable &lt;strong&gt;Validation&lt;/strong&gt; System to ensure correct config parameters.&lt;/li&gt;
&lt;li&gt;Allow the change of &lt;strong&gt;dyna&lt;/strong&gt;mic parameters on the fly without the need to redeploy your application.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Read the docs
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Settings are simple but Dynaconf provides even more features like &lt;strong&gt;Feature Flags&lt;/strong&gt;, &lt;strong&gt;Settings Context Managers&lt;/strong&gt;, &lt;strong&gt;Plugin Settings&lt;/strong&gt; etc..&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href="http://dynaconf.readthedocs.io/" rel="noopener noreferrer"&gt;http://dynaconf.readthedocs.io/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dynaconf is waiting for your &lt;a href="https://github.com/rochacbruno/dynaconf/issues/155" rel="noopener noreferrer"&gt;feedback&lt;/a&gt; and &lt;a href="https://github.com/rochacbruno/dynaconf/issues" rel="noopener noreferrer"&gt;Contribution&lt;/a&gt;&lt;/p&gt;

&lt;p&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="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dynaconf&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt;
&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;THANKS_FOR_READING&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>django</category>
      <category>flask</category>
      <category>12factorapp</category>
    </item>
  </channel>
</rss>
