<?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: Sharon Batiste</title>
    <description>The latest articles on DEV Community by Sharon Batiste (@2320sharon).</description>
    <link>https://dev.to/2320sharon</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%2F704062%2F75d3894a-1664-45d8-8ce7-b33b7a986a61.jpeg</url>
      <title>DEV Community: Sharon Batiste</title>
      <link>https://dev.to/2320sharon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/2320sharon"/>
    <language>en</language>
    <item>
      <title>Making Sense of pyproject.toml, setup.cfg, and setup.py</title>
      <dc:creator>Sharon Batiste</dc:creator>
      <pubDate>Thu, 22 Sep 2022 15:54:00 +0000</pubDate>
      <link>https://dev.to/2320sharon/making-sense-of-pyprojecttoml-setupcfg-and-setuppy-2o6m</link>
      <guid>https://dev.to/2320sharon/making-sense-of-pyprojecttoml-setupcfg-and-setuppy-2o6m</guid>
      <description>&lt;p&gt;So you decided you want to make a python package thats awesome! But after reading through the documentation and numerous blog posts you might be feeling utterly confused as to what exactly you need to make a pypi package. I'm here to explain the connections between &lt;code&gt;pyproject.toml&lt;/code&gt;, &lt;code&gt;setup.cfg&lt;/code&gt; and&lt;code&gt;setup.py&lt;/code&gt; .I'll show you how you can make sure your project will be future proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  TLDR
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;pyproject.toml&lt;/code&gt;: use to declare your package's metadata and specify what build tools(like setuptools or poetry) to use to build your package. Use the command &lt;code&gt;python -m build&lt;/code&gt; to build your package wheel and sdist.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setup.cfg&lt;/code&gt;:  use to declare your package's metadata (if you didn't already use pyproject.toml to declare your metadata).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;setup.py&lt;/code&gt; (deprecated) : used to declare your package's metadata and configuration options. Use the command &lt;code&gt;setup.py sdist setup.py bdist_wheel&lt;/code&gt; to build your package wheel and sdist.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is a pyproject.toml?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pyproject.toml&lt;/code&gt; tells pip what build tools it needs to build sdist and wheels. Before pyproject.toml was introduced pip had no way of knowing what build tools (tools like peotry, setuptools, etc.) it needed to use to build the wheel for your project. With &lt;code&gt;pyproject.toml&lt;/code&gt; you can specify exactly what version of the build tool you need to correctly build your pip package in your virtual environment. For example, the following &lt;code&gt;pyproject.toml&lt;/code&gt; tells pip the build tool it needs to build your package with &lt;code&gt;setuptools&lt;/code&gt;, specifically a version greater than or equal to 61.0.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[build-system]
requires = ["setuptools&amp;gt;=61.0"]
build-backend = ["setuptools.build_meta"]

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

&lt;/div&gt;



&lt;p&gt;You can read more about how pyproject.toml works &lt;a href="https://snarky.ca/what-the-heck-is-pyproject-toml/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why do I need &lt;code&gt;pyproject.toml&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;You need it because it tells pip what build tools pip needs to use build your package in your virtual environment. Not to mention &lt;code&gt;setup.py&lt;/code&gt; is (deprecated)[&lt;a href="https://setuptools.pypa.io/en/latest/deprecated/commands.html" rel="noopener noreferrer"&gt;https://setuptools.pypa.io/en/latest/deprecated/commands.html&lt;/a&gt;] so you should declare you package's metadata in your &lt;code&gt;pyproject.toml&lt;/code&gt; file too. Of course you  can also specify the project's metadata in your &lt;code&gt;setup.cfg&lt;/code&gt; if you'd like too, but I prefer to keep it all in &lt;code&gt;pyproject.toml&lt;/code&gt;.&lt;br&gt;
Additionally, certain tools like &lt;code&gt;poetry&lt;/code&gt; and &lt;code&gt;flit&lt;/code&gt; use this file to specify how to build you package, its dependencies, etc. &lt;a href="https://www.python-engineer.com/posts/python-poetry-tutorial/#:~:text=By%20default%2C%20poetry%20creates%20a,is%20not%20stored%20in%20pyproject." rel="noopener noreferrer"&gt;This article&lt;/a&gt; explains more in detail how &lt;code&gt;poetry&lt;/code&gt; uses the &lt;code&gt;pyproject.toml&lt;/code&gt;. If you want to know how to structure your pyproject.toml file check out the &lt;a href="https://dev.to/2320sharon/how-to-build-a-pyprojecttoml-file-4mk8"&gt;guide&lt;/a&gt; I wrote.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In case you're curious, you must name your package's &lt;code&gt;.toml&lt;/code&gt; file &lt;code&gt;pyproject.toml&lt;/code&gt; otherwise you package won't build correctly.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  What is a &lt;code&gt;setup.py&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;setup.py&lt;/code&gt; is a script that can executed on the command line that is used to build a source distribution and wheel for your package with the command &lt;code&gt;setup.py sdist setup.py bdist_wheel&lt;/code&gt; . You can also declare metadata and package options in your &lt;code&gt;setup.py&lt;/code&gt;. However, I do not recommend you use &lt;code&gt;setup.py&lt;/code&gt; as &lt;a href="https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html" rel="noopener noreferrer"&gt;it is being deprecated&lt;/a&gt;. Instead you should use &lt;code&gt;pyproject.toml&lt;/code&gt; to declare your package's metadata and build dependencies.&lt;/p&gt;
&lt;h3&gt;
  
  
  Do I need &lt;code&gt;setup.py&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;You shouldn't use &lt;code&gt;setup.py&lt;/code&gt; because its deprecated instead you should use &lt;code&gt;pyproject.toml&lt;/code&gt; to declare the build tools and metadata for your package. You shouldn't invoke &lt;code&gt;setup.py&lt;/code&gt; directly to perform tasks like uploading to pypi or building you package. The following table shows what commands to use instead of the deprecated &lt;code&gt;setup.py&lt;/code&gt; commands: &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;setup.py command&lt;/th&gt;
&lt;th&gt;New Command&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;setup.py sdist setup.py bdist_wheel&lt;/td&gt;
&lt;td&gt;python -m build (with build)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setup.py test&lt;/td&gt;
&lt;td&gt;pytest (usually via tox or nox)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setup.py install&lt;/td&gt;
&lt;td&gt;pip install&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setup.py develop&lt;/td&gt;
&lt;td&gt;pip install -e&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setup.py upload&lt;/td&gt;
&lt;td&gt;twine upload (with twine)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setup.py check&lt;/td&gt;
&lt;td&gt;twine check (this doesn't do all the same checks but it's a start)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This table I got from &lt;a href="https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html#:~:text=You%20may%20still%20find%20advice,CLI%20tools%20like%20pip%2C%20build" rel="noopener noreferrer"&gt;Why you should not invoke setup.py directly&lt;/a&gt;. It explains why setup.py shouldn't be used as well as why there is so much confusion around why setup.py shouldn't be used. I highly recommend reading it if you are wondering why &lt;code&gt;setup.py&lt;/code&gt; is being deprecated.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is a &lt;code&gt;setup.cfg&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;A &lt;code&gt;setup.cfg&lt;/code&gt; is a configuration file used to declare the metadata for your package. Metadata is information that describes your package such as package's name, version, description, etc. All this information can be included in your &lt;code&gt;setup.cfg&lt;/code&gt; or your &lt;code&gt;pyproject.toml&lt;/code&gt;. If you want more details on how to use &lt;code&gt;setup.cfg&lt;/code&gt; check out &lt;a href="https://setuptools.pypa.io/en/latest/userguide/declarative_config.html" rel="noopener noreferrer"&gt;setuptools page&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to use &lt;code&gt;setup.cfg&lt;/code&gt; to declare your package's metadata and want to use &lt;code&gt;setup.py&lt;/code&gt; still here is what your &lt;code&gt;setup.py&lt;/code&gt; should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from setuptools import setup
if __name__ == '__main__':
    setup()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using &lt;code&gt;setup.cfg&lt;/code&gt; and &lt;code&gt;setup.py&lt;/code&gt; together will cause &lt;code&gt;setup.py&lt;/code&gt; to use &lt;code&gt;setup.cfg&lt;/code&gt;'s metadata to create the python package so you don't have to declare the metadata directly in the &lt;code&gt;setup.py&lt;/code&gt; file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do I need &lt;code&gt;setup.cfg&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;If you only used your &lt;code&gt;pyproject.toml&lt;/code&gt; file to declare your build tools then you can use &lt;code&gt;setup.cfg&lt;/code&gt; to declare all your metadata like your package's name, version number and so forth.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pyproject.toml&lt;/code&gt; could declare build dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[build-system]
requires = ["setuptools&amp;gt;=61.0"]
build-backend = ["setuptools.build_meta"]

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;setup.cfg&lt;/code&gt; could contain all your package's metadata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[metadata]
name = sample_pkg
version = 1.0.0
author = Sharon Fitzpatrick
description = this is the smallest description
long_description = This is a longest description
url = https://github.com/pypa/packaging.python.org
keywords = python,example
[options]
python_requires = &amp;gt;=3.8, &amp;lt;4
install_requires = 
    numpy
    matplotlib
[options.extras_require]
test = 
    pytest
    coverage
[options.package_data]
sample = 
    sample_data.csv'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What's Metadata?
&lt;/h3&gt;

&lt;p&gt;Metadata is information that describes your package. Metadata is information like the package's name, version, and description.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Build a pyproject.toml File</title>
      <dc:creator>Sharon Batiste</dc:creator>
      <pubDate>Thu, 22 Sep 2022 15:21:14 +0000</pubDate>
      <link>https://dev.to/2320sharon/how-to-build-a-pyprojecttoml-file-4mk8</link>
      <guid>https://dev.to/2320sharon/how-to-build-a-pyprojecttoml-file-4mk8</guid>
      <description>&lt;p&gt;In this tutorial I'll be walking you through how to build a simple &lt;code&gt;pyproject.toml&lt;/code&gt; file. I'll be including a sample &lt;code&gt;pyproject.toml&lt;/code&gt; as well as include links to some resources I found very helpful when learning how to construct my own &lt;code&gt;pyproject.toml&lt;/code&gt;. First, I'll be showing you the full &lt;code&gt;pyproject.toml&lt;/code&gt; then I'll break down the purpose of each section of the file. &lt;code&gt;Setuptools&lt;/code&gt; has a &lt;a href="https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html" rel="noopener noreferrer"&gt;fantastic page&lt;/a&gt; that explains more about &lt;code&gt;pyproject.toml&lt;/code&gt; and how it can be used with &lt;code&gt;setuptools&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample &lt;code&gt;pyproject.toml&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# tells pip what build tool to use to build your package
[build-system]
requires = ["setuptools&amp;gt;=61.0"]
build-backend = "setuptools.build_meta"

# tells pip how to build your pypi webpage &amp;amp; what dependencies to install
[project]
name = "sample_pkg"
dynamic = ["readme"]
version = "0.0.30"
authors = [
  { name="Sharon Fitzpatrick", email="sharon.fitzpatrick23@gmail.com" }]
description = "A tool that performs xyz"
dependencies = ["matplotlib",
  "numpy&amp;lt;1.23.0"]
license = { file="LICENSE" }
requires-python = "&amp;gt;=3.8"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: OS Independent",
]

# (BETA) tells setuptools you will be using a readme file for the long description field for your pypi profile.
[tool.setuptools.dynamic]
readme = {file = ["README.md"]}

# (OPTIONAL) tells pypi that these urls are where your project's source code and issue tracker reside
[project.urls]
"Homepage" = "https://github.com/pypa/packaging.python.org"
"Bug Tracker" = "https://github.com/pypa/packaging.python.org/issues"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  [build-system]
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Tells pip what build tool to use to build your pip package. You can choose build tools like &lt;code&gt;poetry&lt;/code&gt;,&lt;code&gt;hatchling&lt;/code&gt;,&lt;code&gt;setuptools&lt;/code&gt;, etc. to build your package. Without the &lt;code&gt;build-system&lt;/code&gt; pip would have to guess what tools you used to create your package.
If you want to learn more about the &lt;code&gt;pyproject.toml&lt;/code&gt; file check &lt;a href="https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml/" rel="noopener noreferrer"&gt;pip's documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;requires = ["setuptools&amp;gt;=61.0"]&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;tells pip exactly what versions of &lt;code&gt;setuptools&lt;/code&gt; are compatible to build the package&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;build-backend = "setuptools.build_meta"&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;tells pip that you will be using &lt;code&gt;setuptools&lt;/code&gt; to build your package&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  [project]
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This section tells pip the metadata for your package. The metadata for your package is information that describes your package like your package's name, version number, and dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;name = "sample_pkg"&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tells pip the name of your package. This must be a unique name on pypi.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;dynamic = ["readme"]&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tells setuptools that you will be creating the &lt;code&gt;long description&lt;/code&gt; dynamically from the readme file. The &lt;code&gt;long description&lt;/code&gt; is what is displayed on your pypi's project page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;version = "0.0.30"&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tells pip is the current version of the package&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;authors = [{ name="Sharon Fitzpatrick",email="sharon.fitzpatrick23@gmail.com" }]&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tells pip is the author of the package&lt;/li&gt;
&lt;li&gt;You must include both the authors name and email for this to work properly&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;description = "A tool that performs xyz"&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tells pip a short description which will be displayed on your package's pypi page.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;dependencies = ["matplotlib","numpy&amp;lt;1.23.0"]&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tells pip what dependencies your package needs to run&lt;/li&gt;
&lt;li&gt;You can even specify the version of packages that are compatible with your package&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;license = { file="LICENSE" }&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tells pip you will be using the file named LICENSE in your repository as your license&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;requires-python = "&amp;gt;=3.8"&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tells pip what python version your package requires&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;classifiers = ["Programming Language :: Python :: 3","License :: OSI Approved :: MIT License","Operating System :: OS Independent",]&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Used by PyPi categorize each package's release, it describes who the package is for and what systems it can run on, and how mature package is. &lt;/li&gt;
&lt;li&gt;You can find the &lt;a href="https://pypi.org/classifiers/" rel="noopener noreferrer"&gt;full list of classifiers from pypi&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  [tool.setuptools.dynamic]
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This section is specific to &lt;code&gt;setuptools&lt;/code&gt; and still in beta. &lt;a href="https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html#:~:text=%22my_package%22%5D-,Dynamic%20Metadata,-%23" rel="noopener noreferrer"&gt;Read more here.&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;It tells &lt;code&gt;setuptools&lt;/code&gt; that the following fields will be populated dynamically by files included into the repository&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;readme = {file = ["README.md"]}&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Tells &lt;code&gt;setuptools&lt;/code&gt; you will be using a readme file for the long description field for your pypi profile.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; your README file must be named exactly README. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NOTE:&lt;/strong&gt; a GitHub styled &lt;code&gt;README.md&lt;/code&gt; may not render correctly on &lt;code&gt;pypi&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  [project.urls]
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This is an optional section that tells pypi the urls associated  with your package
###  "Homepage" = "&lt;a href="https://github.com/pypa/packaging.python.org" rel="noopener noreferrer"&gt;https://github.com/pypa/packaging.python.org&lt;/a&gt;"&lt;/li&gt;
&lt;li&gt;This tells pypi where your package is from  (optional)
###  "Bug Tracker" = "&lt;a href="https://github.com/pypa/packaging.python.org/issues" rel="noopener noreferrer"&gt;https://github.com/pypa/packaging.python.org/issues&lt;/a&gt;"&lt;/li&gt;
&lt;li&gt; This tells pypi where issues and bugs for your project are being tracked (optional)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ready to upload to PyPi?
&lt;/h2&gt;

&lt;p&gt;Now that you know how to build your &lt;code&gt;pyproject.toml&lt;/code&gt; file are you ready to upload your package to PyPi? I created a guide to show you how to &lt;a href="https://dev.to/2320sharon/the-modern-way-of-uploading-a-pypi-package-2gpd"&gt;upload to PyPi the modern way&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>pyproject</category>
      <category>pypi</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>The Modern Way of Uploading a PyPi Package</title>
      <dc:creator>Sharon Batiste</dc:creator>
      <pubDate>Thu, 22 Sep 2022 15:00:32 +0000</pubDate>
      <link>https://dev.to/2320sharon/the-modern-way-of-uploading-a-pypi-package-2gpd</link>
      <guid>https://dev.to/2320sharon/the-modern-way-of-uploading-a-pypi-package-2gpd</guid>
      <description>&lt;p&gt;There are a lot of conflicting guides when it comes to uploading your first package onto PyPi. This guide will show you the modern way to upload your python package onto PyPi as well as some common pitfalls to avoid.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You Begin
&lt;/h2&gt;

&lt;p&gt;Make sure you have &lt;code&gt;setuptools&lt;/code&gt; and the command line tool &lt;code&gt;build&lt;/code&gt; installed in the virtual environment you have created your package's code in. To install build run &lt;code&gt;pip install --upgrade build&lt;/code&gt;. You will also need to install &lt;code&gt;twine&lt;/code&gt; in order to upload the package to pypi. Use the command &lt;code&gt;pip install twine&lt;/code&gt; to install twine in your virtual environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install setuptools twine
pip install --upgrade build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1. Build your wheel and dist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Command:&lt;/strong&gt; &lt;code&gt;python -m build&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This creates the &lt;code&gt;wheel&lt;/code&gt; and &lt;code&gt;dist&lt;/code&gt;(short for source distribution) for your project. It the recommended way to build your python package ever since &lt;a href="https://setuptools.pypa.io/en/latest/deprecated/commands.html" rel="noopener noreferrer"&gt;&lt;code&gt;setup.py&lt;/code&gt; was deprecated&lt;/a&gt;. This command works just like the deprecated &lt;code&gt;python setup.py sdist/*&lt;/code&gt; way of creating a source distribution. It works great with a &lt;code&gt;pyproject.toml&lt;/code&gt; to build you sdist and wheel.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;python -m build&lt;/code&gt; with the same version number  in your &lt;code&gt;pyproject.toml&lt;/code&gt; or &lt;code&gt;setup.cfg&lt;/code&gt; it will replace that version of &lt;code&gt;wheel&lt;/code&gt; and &lt;code&gt;sdist&lt;/code&gt;. For example if you already ran &lt;code&gt;python -m build&lt;/code&gt; when your &lt;code&gt;pyproject.toml&lt;/code&gt; had &lt;code&gt;version = 0.0.03&lt;/code&gt; and then modified your code you could run &lt;code&gt;python -m build&lt;/code&gt; to replace the &lt;code&gt;version = 0.0.03&lt;/code&gt; of sdist and wheel you built previously. This will only work if you haven't already uploaded that version number to PyPi.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Check your package's before upload
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Command:&lt;/strong&gt; &lt;code&gt;twine check dist/*&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Check specific version:&lt;/strong&gt; &lt;code&gt;twine check dist/*0.0.1*&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;twine check&lt;/code&gt; checks your long description (or readme) to see if it will render correctly on PyPi.&lt;/p&gt;

&lt;p&gt;⚠️&lt;strong&gt;WARNING&lt;/strong&gt;⚠️&lt;br&gt;
If you use the dynamic readme option in your &lt;code&gt;pyproject.toml&lt;/code&gt; and your README file is not named exactly &lt;code&gt;README&lt;/code&gt; the &lt;code&gt;twine check&lt;/code&gt; will fail and return the error message. However the package can still up successfully uploaded to PyPi even when the check fails. It just means the readme might not render correctly on PyPi.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Upload to Test PyPi (Optional)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Command:&lt;/strong&gt;&lt;code&gt;twine upload --repository testpypi dist&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Pypi has a test version where you can upload packages without impacting the real PyPi index. This is a great place to get familiar with uploading to PyPi without the stress of impacting the PyPi index.&lt;/p&gt;

&lt;p&gt;⚠️&lt;strong&gt;WARNING!&lt;/strong&gt;⚠️&lt;br&gt;
Don't upload any packages with dependencies to Test Pypi because the dependencies are not guaranteed to be uploaded on Test Pypi. This may cause your installations from Test PyPi may randomly fail because pip will try to find your dependencies on Test PyPi where they don't exist.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Upload to PyPi with Twine
&lt;/h2&gt;

&lt;p&gt;🚀&lt;strong&gt;Command:&lt;/strong&gt;&lt;code&gt;twine upload dist/*&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This command uses a pip package called Twine to upload your package to PyPi.&lt;/p&gt;

&lt;p&gt;When you run this command you will be prompted to enter your password unless you have configured a tool like &lt;a href="https://pypi.org/project/keyring/" rel="noopener noreferrer"&gt;keyring&lt;/a&gt; to automatically enter your credentials.&lt;/p&gt;
&lt;h3&gt;
  
  
  Configure KeyRing to Automatically Enter PyPi Credentials
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install keyring in your virtual environment &lt;code&gt;pip install keyring&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Save your username and password with keyring. In your virtual environment's command prompt enter: 

&lt;ul&gt;
&lt;li&gt;Make sure to put a space between the link and YOUR_USERNAME
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keyring set https://upload.pypi.org/legacy/ &amp;lt;YOUR USERNAME&amp;gt;
Enter your password when prompted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keyring set https://upload.pypi.org/legacy/ ms_username
&amp;lt;click enter&amp;gt;
my_fake_password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you're a Windows user and don't see your password being entered in the window don't worry that's normal!&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Want to upload a specific version of your package?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Command:&lt;/strong&gt; &lt;code&gt;twine upload dist/*&amp;lt;version_number&amp;gt;*&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you want to upload a specific version of your package here is a shortcut&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example:&lt;/strong&gt; &lt;code&gt;twine upload dist/*0.0.6*&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;This will upload all the dist files (wheel and tar) with version number = 0.0.6.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  What is Twine?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Twine is a super easy to use package that lets you upload to PyPi or Test PyPi with a single command.&lt;/li&gt;
&lt;li&gt;You can install it with pip using the command &lt;code&gt;pip install twine&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>packaging</category>
      <category>tutorial</category>
      <category>pypi</category>
    </item>
    <item>
      <title>How to Start Practicing Coding Interview Questions</title>
      <dc:creator>Sharon Batiste</dc:creator>
      <pubDate>Wed, 11 May 2022 15:17:46 +0000</pubDate>
      <link>https://dev.to/2320sharon/how-to-start-practicing-coding-interview-questions-3dna</link>
      <guid>https://dev.to/2320sharon/how-to-start-practicing-coding-interview-questions-3dna</guid>
      <description>&lt;p&gt;Okay so I have a confession to make I've been dodging practicing for coding interview for months. I've conveniently always had a side project to work on or was too tired from programming all day at work to start them. But the truth is I was scared to start them because they made me feel stupid. &lt;/p&gt;

&lt;p&gt;I wanted to share some steps I took that are helping me overcome my fear of interview questions, so that hopefully they can help you too. Feel free to share more things that personally helped you out in the comments below!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Make Your Motivation to be More than Getting a Job 🐺
&lt;/h2&gt;

&lt;p&gt;Having multiple motivations to practice coding interview questions will make it easier to start and continue the routine. For instance, you may want to learn more programming shortcuts that increase your speed. This is a great motivation because it will have you digging through the solutions to find ways you can better your code. My motivation is practice explaining my problem solving out loud so that I can improve my speaking skills. This makes me more excited to start than just plain "I need to do this for the job" 😩.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Make a Schedule &amp;amp; Stick to it 🗓️
&lt;/h2&gt;

&lt;p&gt;I have found they key to making progress on interview questions is to practice in little chunks at a time 3 or 4 times a week. Spend 30 minutes to an hour 3 or 4 days a week practicing interview questions. This will lead you to developing a habit of studying them and make it easier to continue practicing long term. Also don't beat yourself up or increase the time you study the next day if you miss a day. When you increase the barrier to starting by punishing yourself you make it not only harder to begin a practice session but also turn practicing into a punishment. Think of practicing interview questions as time of exploration 🚀 and learning. Find a way to frame it as a fun experience.😄 &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Study the Algorithms &amp;amp; Structures in the Solutions ⛰️
&lt;/h2&gt;

&lt;p&gt;When you encounter a data structure or algorithm you don't know in the problem or solutions spend some time studying it and practicing it before getting back to the problem. This will help you learn these structures in an organic way. Furthermore, since you are practicing them before you apply them to the problem you will know when and how to apply them. ✨ This &lt;a href="https://leetcode.com/discuss/study-guide/1965086/how-to-practice-for-2200-rating-in-lc" rel="noopener noreferrer"&gt;LeetCode Discussion&lt;/a&gt; explains this idea more in depth&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Practice Writing out the Steps 📝
&lt;/h2&gt;

&lt;p&gt;Write out the steps (not code) you need to do to solve the problem first. This will let you fully understand the problem so you don't start coding then realize your approach was all wrong. (admittedly this still happens to me sometimes 😅). Then reread the question to make sure your steps would produce the output the question is asking for. This also helps you practice explaining the way you would solve the problem to an interviewer.&lt;/p&gt;

&lt;p&gt;Write out the high level steps like: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set the maximum value to the first value of the array&lt;/li&gt;
&lt;li&gt;Iterate through all elements of the array&lt;/li&gt;
&lt;li&gt;Compare each value in the array to the maximum value&lt;/li&gt;
&lt;li&gt;If this value if greater than the maximum value  make this value the new maximum value&lt;/li&gt;
&lt;li&gt;Return the maximum value&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 5: Remember You're Not Stupid these are Hard
&lt;/h2&gt;

&lt;p&gt;As &lt;a href="https://leetcode.com/discuss/general-discussion/353876/Leetcode-NOOB-(Struggling-with-easy)" rel="noopener noreferrer"&gt;this post&lt;/a&gt; on Leetcode shows these problems are challenging (not impossible), so expect yourself to get stuck on a lot of problems. Never call yourself names like "stupid" or say "I'm just not that smart" the way you speak to yourself impacts how you view yourself. Its going to cause you to lose motivation, not solve problems you were capable of solving, and feel so much worse about yourself. Instead remember that these problems are meant to be challenging and that no one knows how to do them right out of the womb 👶. A friend once told me that when you do something for the first time its going to be bad, but when you do it for the 100th 💯 time its going to be great!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Reward Yourself 🍰
&lt;/h2&gt;

&lt;p&gt;Let's face it is programming is hard work and you should reward yourself each week after you finish all your practice sessions. This will incentivize you to keep making progress. Also occasionally take a look back at your old solutions to see how much you have improved. This should be a confidence boost ⏫ because your can see how much better you understand the solution and even how you can do it better now! &lt;/p&gt;

&lt;p&gt;I hope these tips help you and please let me know in the comments what strategies you use when you practice interview questions. I'm still learning and would love to hear your secret tricks. &lt;/p&gt;

</description>
      <category>career</category>
      <category>interview</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Secrets of Python's Glob</title>
      <dc:creator>Sharon Batiste</dc:creator>
      <pubDate>Wed, 20 Apr 2022 15:03:37 +0000</pubDate>
      <link>https://dev.to/2320sharon/the-secrets-of-glob-31a7</link>
      <guid>https://dev.to/2320sharon/the-secrets-of-glob-31a7</guid>
      <description>&lt;h2&gt;
  
  
  Table of Common Glob Strings
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Glob&lt;/th&gt;
&lt;th&gt;Definition&lt;/th&gt;
&lt;th&gt;Example Glob&lt;/th&gt;
&lt;th&gt;Valid Files&lt;/th&gt;
&lt;th&gt;Not Valid&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;matches 0 or more characters&lt;/td&gt;
&lt;td&gt;*.jpg&lt;/td&gt;
&lt;td&gt;[im1.jpg,cat.jpg]&lt;/td&gt;
&lt;td&gt;cat.JPG, dog.png&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;?&lt;/td&gt;
&lt;td&gt;matches EXACTLY 1 character&lt;/td&gt;
&lt;td&gt;?_at.jpg&lt;/td&gt;
&lt;td&gt;bat.jpg,cat.jpg&lt;/td&gt;
&lt;td&gt;hhat.jpg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;**&lt;/td&gt;
&lt;td&gt;recursive search&lt;/td&gt;
&lt;td&gt;/*&lt;em&gt;/&lt;/em&gt;.jpg&lt;/td&gt;
&lt;td&gt;[home/imgs/1.jpg,imgs/im.jpg]&lt;/td&gt;
&lt;td&gt;file.jpg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!()&lt;/td&gt;
&lt;td&gt;does not match characters in ()&lt;/td&gt;
&lt;td&gt;&lt;em&gt;!(a)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;[rock.jpg,shell.txt]&lt;/td&gt;
&lt;td&gt;cat.txt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[]&lt;/td&gt;
&lt;td&gt;matches range of character in []&lt;/td&gt;
&lt;td&gt;[ad]-img/*.txt&lt;/td&gt;
&lt;td&gt;[a-img.txt,d-img.txt]&lt;/td&gt;
&lt;td&gt;c-file.txt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*()&lt;/td&gt;
&lt;td&gt;matches 0 or more characters within the ()&lt;/td&gt;
&lt;td&gt;"*(.jpg)"&lt;/td&gt;
&lt;td&gt;[file.jpg,blob.jpg,k.jpg]&lt;/td&gt;
&lt;td&gt;file.png&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Interactive tool to test your glob
&lt;/h2&gt;

&lt;p&gt;I discovered &lt;a href="https://www.digitalocean.com/community/tools/glob?comments=true&amp;amp;glob=%2F%2A%2Ajpg_files%2F%2A.txt&amp;amp;matches=false&amp;amp;tests=%2F%2F%20This%20will%20match%20as%20it%20ends%20with%20%27.js%27&amp;amp;tests=%2Fjpg_files%2Fworld.txt&amp;amp;tests=%2F%2F%20This%20won%27t%20match%21&amp;amp;tests=%2Ftest%2Fsome%2Fglobs" rel="noopener noreferrer"&gt;Glob Tool&lt;/a&gt; that lets you test out your glob strings with sample file paths. You type in the string glob you think would find the files you want then type the file path in the &lt;code&gt;Test Strings&lt;/code&gt; box and it will show you if your file will be found. This is a great way to learn glob and saves your time from testing it on your computer.&lt;br&gt;
&lt;a href="https://media2.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%2Fzd0t4ssmwpc2qdzibew0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzd0t4ssmwpc2qdzibew0.jpg" alt="Glob Tool Screenshot" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Get the full path of all the jpegs in a folder
&lt;/h1&gt;

&lt;p&gt;Get the full path of all the jpgs in a folder with glob.&lt;/p&gt;

&lt;h4&gt;
  
  
  TDLR
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Windows paths use \ so use \\ instead
&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;images&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Returns 
#["C:\\Python\\images\\img.jpg","C:\\Python\\images\\img2.jpg"]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Full Code
&lt;/h4&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;glob&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt; 
&lt;span class="n"&gt;images_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sep&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;images&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# C:\\Python\\images\\
&lt;/span&gt;&lt;span class="n"&gt;glob_str&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;images_path&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# C:\\Python\\images\\*jpg
&lt;/span&gt;&lt;span class="n"&gt;full_images_paths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;glob_str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# On Windows Returns 
#["C:\\Python\\images\\img.jpg","C:\\Python\\images\\img2.jpg"]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Get just the filenames in a folder
&lt;/h1&gt;

&lt;p&gt;Get the just the names of all the jpgs in a folder with &lt;a href="https://thomas-cokelaer.info/tutorials/python/module_glob.html#:~:text=5.3.%20methods,a%20pattern.%20So%3A" rel="noopener noreferrer"&gt;glob1&lt;/a&gt;. &lt;code&gt;glob1&lt;/code&gt; takes two arguments the file path you want to search and the glob string you pass in.&lt;br&gt;
&lt;code&gt;glob.glob1("file_path_to_search","pattern")&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  TDLR
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Windows paths use \ so use \\ instead
&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;images&lt;/span&gt;&lt;span class="se"&gt;\\&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;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# This also works:
&lt;/span&gt;&lt;span class="n"&gt;images&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;C:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s"&gt;images&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;*.jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Returns 
#["img.jpg","img2.jpg"]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Full Code
&lt;/h4&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;glob&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt; 
&lt;span class="n"&gt;images_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getcwd&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sep&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;images&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# C:\\Python\\images\\
&lt;/span&gt;&lt;span class="n"&gt;full_images_paths&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;images_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*jpg&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# On Windows Returns 
#["img.jpg","img2.jpg"]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In Depth Glob Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Glob&lt;/th&gt;
&lt;th&gt;Definition&lt;/th&gt;
&lt;th&gt;Example Glob&lt;/th&gt;
&lt;th&gt;Valid Files&lt;/th&gt;
&lt;th&gt;Not Valid&lt;/th&gt;
&lt;th&gt;Explaination&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;*&lt;/td&gt;
&lt;td&gt;matches 0 or more characters CASE SENSITIVE&lt;/td&gt;
&lt;td&gt;*.jpg&lt;/td&gt;
&lt;td&gt;[im1.jpg,cat.jpg]&lt;/td&gt;
&lt;td&gt;cat.JPG, dog.png&lt;/td&gt;
&lt;td&gt;The rest of the  string must match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;?&lt;/td&gt;
&lt;td&gt;matches EXACTLY 1 character&lt;/td&gt;
&lt;td&gt;?_at.jpg&lt;/td&gt;
&lt;td&gt;bat.jpg,cat.jpg&lt;/td&gt;
&lt;td&gt;hhat.jpg&lt;/td&gt;
&lt;td&gt;Only 1 character before the _at&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;**&lt;/td&gt;
&lt;td&gt;recursive search&lt;/td&gt;
&lt;td&gt;/*&lt;em&gt;/&lt;/em&gt;.jpg&lt;/td&gt;
&lt;td&gt;[home/folders/img.jpg,folders/im.jpg]&lt;/td&gt;
&lt;td&gt;file.jpg&lt;/td&gt;
&lt;td&gt;Cannot be without a parent directory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;!()&lt;/td&gt;
&lt;td&gt;does not match characters in ()&lt;/td&gt;
&lt;td&gt;&lt;em&gt;!(a)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;[rock.jpg,shell.txt]&lt;/td&gt;
&lt;td&gt;cat.txt&lt;/td&gt;
&lt;td&gt;A cannot be in the string&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[]&lt;/td&gt;
&lt;td&gt;matches range of character in [] CASE SENSITIVE&lt;/td&gt;
&lt;td&gt;[ad]-file/*.txt&lt;/td&gt;
&lt;td&gt;[a-file.txt,d-file.txt]&lt;/td&gt;
&lt;td&gt;c-file.txt&lt;/td&gt;
&lt;td&gt;c is not in the [ad] so its not a match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;*()&lt;/td&gt;
&lt;td&gt;matches 0 or more characters within the ()&lt;/td&gt;
&lt;td&gt;"*(.jpg)"&lt;/td&gt;
&lt;td&gt;[file.jpg,blob.jpg,k.jpg]&lt;/td&gt;
&lt;td&gt;file.png&lt;/td&gt;
&lt;td&gt;Files with any name as long as they end in .jpg&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>glob</category>
    </item>
    <item>
      <title>Creating The Ideal Coding Environment</title>
      <dc:creator>Sharon Batiste</dc:creator>
      <pubDate>Fri, 15 Apr 2022 17:07:08 +0000</pubDate>
      <link>https://dev.to/2320sharon/creating-the-ideal-coding-environment-3hpk</link>
      <guid>https://dev.to/2320sharon/creating-the-ideal-coding-environment-3hpk</guid>
      <description>&lt;h2&gt;
  
  
  1. Get a comfortable chair
&lt;/h2&gt;

&lt;p&gt;Get a good chair that forces you to sit up straight. Fighting back pain while you're coding makes you less effective and makes you miserable. I didn't want to spend over $600 on a fancy chair so I use a pillow to better prop up my back. Its cheap and easy!&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Align your Monitor at Eye Level
&lt;/h2&gt;

&lt;p&gt;Position your monitor so that you don't have to move your head or your back to see what is on screen. As a rule of thumb ergonomics experts recommend that your monitor should be at arms length away from you at most. This will prevent your from hunching over to see what's on screen and will decrease your risk of eye strain.&lt;/p&gt;

&lt;p&gt;I made my desktop stand out of wood and it was super easy to to make. You can also use some old textbooks or shoe boxes if you want to make your own stand.&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=F8_ME4VwTiw&amp;amp;ab_channel=WallStreetJournal" rel="noopener noreferrer"&gt;Ergonomics Expert Explains How to Set Up Your Desk&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2F2320sharon%2FDEV_Blogs_Repository%2Fmaster%2Fbrightened.jpg%3Ftoken%3DGHSAT0AAAAAABSQCTPACP54CSN5LF7XDOA4YSZWJWQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2F2320sharon%2FDEV_Blogs_Repository%2Fmaster%2Fbrightened.jpg%3Ftoken%3DGHSAT0AAAAAABSQCTPACP54CSN5LF7XDOA4YSZWJWQ" alt="My Desktop SetUp" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Write Code at Your Best Times
&lt;/h2&gt;

&lt;p&gt;If you program best in the morning when you can hear the birds chirping then program in the morning. If you program best at midnight when no one is awake then program at midnight. The quality of your code will dramatically increase when you're in the zone and you will write code even faster than usual. I write my best code in the early morning after a cup of coffee and writing my goals for the day.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Have Minimal Background Noise
&lt;/h2&gt;

&lt;p&gt;Having some level of background noise helps stimulate your brain to focus as long as that background noise isn't distracting. I find that listening to Lofi, game soundtracks, or nature ambience helps me stay in the zone longer and keeps me from getting bored. Somedays when I didn't get enough sleep or want some company  coding in a coffee shop provides me with energy to code. That being said I usually lose my ability to focus after 3 or more hours at which point I head back to my quiet home office.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Chill Out Don't Overstress
&lt;/h2&gt;

&lt;p&gt;Being overly stressed diminishes your brain's ability to execute flexible problem solving. I notice that when I get too stressed I can't visualize solutions and get locked into a single solution. Taking some time to relax and get my mind off the problem allows me to come back with a fresh perspective. That being said a little stress is good to motivate you because it adds some stakes to your programming. You don't want to disappoint your co-workers with bad code so that stress will motivate you to write better code.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Have a Sheet of Paper
&lt;/h2&gt;

&lt;p&gt;A sheet of paper is great place to offload ideas, visualize programming problems, and break large tasks into subtasks. I find that having a notepad where I can write anything without worrying about organization takes the pressure off myself to write perfect. You should use the paper/notepad as a place to quickly offload thoughts and ideas. It doesn't need to be  organized it's just temporary storage for your thought process.&lt;br&gt;
&lt;a href="https://media2.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%2Fzgvp0sx22geyciary1h4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzgvp0sx22geyciary1h4.jpg" alt="Legal Notepad" width="275" height="183"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>programming</category>
      <category>workstations</category>
    </item>
    <item>
      <title>Lessons from a Computer Science College Grad</title>
      <dc:creator>Sharon Batiste</dc:creator>
      <pubDate>Sat, 19 Mar 2022 03:24:25 +0000</pubDate>
      <link>https://dev.to/2320sharon/lessons-from-a-computer-science-college-grad-2j7i</link>
      <guid>https://dev.to/2320sharon/lessons-from-a-computer-science-college-grad-2j7i</guid>
      <description>&lt;p&gt;In December of 2021 I graduated with a degree in Computer Science. I've been working as a programming contractor for the USGS where I build python applications for them. I wanted to share some of the lessons I learned being in the workforce that aren't taught in school for other new programmers.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Don't Overcomplicate Your Code
&lt;/h2&gt;

&lt;p&gt;If you can barely understand how your code works then how do you honestly expect others to? If your code is open source and going to be used by developers with a variety of skill levels make it easy to understand. Making your code will make it easier to maintain by decreasing the amount of time it takes to read your code. &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Write Down Your Problem Solving Process
&lt;/h2&gt;

&lt;p&gt;"The mind is messy, but paper is clean". When you're struggling to solve a complex problem writing it down takes the pressure of your brain by allowing you to offload your thoughts to the paper. This lets you clearly see the entire problem on one sheet of paper instead of a cluster of messy thoughts. It also makes the problem less intimidating by simplifying it to simple steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Take Notes on How to Set Up Your Dev Environment
&lt;/h2&gt;

&lt;p&gt;You will forget how you set up your complex dev environment at some point. Use a tool like Notion to create a wiki where you can write down the steps you took to build your dev environment and never forget again.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Talk to Other Developers about Your Problems
&lt;/h2&gt;

&lt;p&gt;Whether you are stuck on a problem or just need some inspiration talking with other developers lets you consider solutions and perspectives you would have never thought of. It helps you see the simplest and most effective solution because they aren't biased to the same solutions and mindset you are. Plus its fun!&lt;/p&gt;

&lt;h3&gt;
  
  
  Check me out on GitHub
&lt;/h3&gt;

&lt;p&gt;I work on open source projects and I'd love to work with you.&lt;br&gt;
&lt;a href="https://github.com/2320sharon" rel="noopener noreferrer"&gt;https://github.com/2320sharon&lt;/a&gt;&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>python</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Reducing Docker Container Size</title>
      <dc:creator>Sharon Batiste</dc:creator>
      <pubDate>Sun, 12 Sep 2021 03:42:21 +0000</pubDate>
      <link>https://dev.to/2320sharon/reducing-docker-container-size-17fl</link>
      <guid>https://dev.to/2320sharon/reducing-docker-container-size-17fl</guid>
      <description>&lt;h3&gt;
  
  
  Two Ways to reduce the size of a docker container
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Reduce the size of the layer&lt;/li&gt;
&lt;li&gt;Reduce the number of layers&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  But what is a layer?
&lt;/h3&gt;

&lt;p&gt;A layer is a change applied to an image. Every command you specify &lt;strong&gt;( FROM , RUN , COPY , etc.)&lt;/strong&gt; in your Dockerfile causes the previous image to change, thus creating a new layer. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F31mzennx0l6sj5jubq3e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F31mzennx0l6sj5jubq3e.jpg" alt="Alt Text" width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
Fig.1 - Dockerfile Layer credit: Agent of Change's YouTube
&lt;/p&gt;

&lt;h2&gt;
  
  
  Multistage Builds
&lt;/h2&gt;

&lt;p&gt;The best way to reduce the number of layers is to use a Multistage build. This turns our Docker build into 2 stages. The first stage to be built will be the exe file and the second stage will be an image using that exe file.&lt;/p&gt;

&lt;p&gt;The following code shows how to make a multistage Docker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F22elgvwvg4cxn3ob2qz2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F22elgvwvg4cxn3ob2qz2.jpg" alt="Alt Text" width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;
Fig.2 - Dockerfile Multistage Code Example: Agent of Change's YouTube
&lt;/p&gt;

&lt;p&gt;Each &lt;strong&gt;FROM&lt;/strong&gt; creates a new stage. The first stage is tagged as ''builder" by the code&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;FROM golang 1.7.3 AS builder&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
  command. The code afterwards complies the code and all its dependencies together with the &lt;strong&gt;RUN&lt;/strong&gt; command.&lt;/p&gt;

&lt;p&gt;The second &lt;strong&gt;FROM&lt;/strong&gt; creates a new stage from the lightweight alpine container and then copies the complied code from the "builder" stage we created previously. The container will be much smaller because the second stage doesn't have to create the complied code; instead it can use the code from the first stage.&lt;/p&gt;

&lt;p&gt;Credit for all screenshots posted here are from the amazing YouTube channel &lt;strong&gt;Agent of Change&lt;/strong&gt;. This post is just meant to summarize information taken from his video. Please go check it out and it is linked under Resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=1tHCVIO8Q04&amp;amp;ab_channel=AgentofChange" rel="noopener noreferrer"&gt;Agent of Change's video on Docker Layers and Multistage Builds&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=2KzDMD5Qk2k&amp;amp;ab_channel=DevOpsDirective" rel="noopener noreferrer"&gt;DevOps Directive's video on Docker Multistage Builds&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
