<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: tinega</title>
    <description>The latest articles on Forem by tinega (@tinegagideon).</description>
    <link>https://forem.com/tinegagideon</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%2F388909%2Fa2b91fd1-271d-4df0-8789-505c692286a4.gif</url>
      <title>Forem: tinega</title>
      <link>https://forem.com/tinegagideon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/tinegagideon"/>
    <language>en</language>
    <item>
      <title>Dependency management in Python Using Poetry</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Fri, 31 May 2024 14:43:28 +0000</pubDate>
      <link>https://forem.com/tinegagideon/dependency-management-in-python-using-poetry-36h2</link>
      <guid>https://forem.com/tinegagideon/dependency-management-in-python-using-poetry-36h2</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Dependency management in Python is an important component of software development because it entails managing the libraries and packages required by a project. Proper dependency management ensures that the necessary dependencies are installed, conflicts are avoided, and the project is reproducible across different environments. &lt;/p&gt;

&lt;h1&gt;
  
  
  Concepts
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Dependencies&lt;br&gt;
Dependencies are external libraries or modules that a project relies on to function. These can range from standard libraries included with Python to third-party packages available on repositories like PyPI (Python Package Index).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dependency Management Tools&lt;br&gt;
Include tools such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pip: The default package installer for Python.Uses requirements.txt to list dependencies and their versions.&lt;/li&gt;
&lt;li&gt;virtualenv: Creates isolated Python environments to manage dependencies for different projects independently.&lt;/li&gt;
&lt;li&gt;venv: Provides similar functionality to virtualenv but is built into Python.&lt;/li&gt;
&lt;li&gt;conda: A package manager and environment management system that supports multiple languages.&lt;/li&gt;
&lt;li&gt;poetry: A modern tool for dependency management and packaging.Uses pyproject.toml to specify project configurations and dependencies.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Poetry
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://python-poetry.org/docs/#installing-with-the-official-installer" rel="noopener noreferrer"&gt;Poetry&lt;/a&gt; is a tool for dependency management and packaging in Python. It allows you to declare the libraries your project depends on and it will manage (install/update) them for you. Poetry offers a lockfile to ensure repeatable installs, and can build your project for distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pyproject.toml file
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;pyproject.toml&lt;/code&gt; is a configuration file used by packaging tools such as poetry.&lt;br&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;[tool.poetry]
name = "poetry-test"
version = "0.2.0"
description = ""
authors = ["None"]
readme = "README.md"

[tool.poetry.dependencies]
python = "^3.12"
requests = "^2.30.0"


[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Poetry requires Python 3.8+&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Linux,macOS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;curl -sSL https://install.python-poetry.org | python3 -&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows(Poweshell)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;(Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py -&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add Poetry to your PATH(Environment Variables) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add the following paths to PATH variable depending on your system.&lt;br&gt;
&lt;code&gt;$HOME/.local/bin&lt;/code&gt; on Unix.&lt;br&gt;
&lt;code&gt;%APPDATA%\Python\Scripts&lt;/code&gt; on Windows.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;poetry --version&lt;/code&gt;: verify that poetry is installed correctly and added to $PATH.&lt;/p&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;poetry new &amp;lt;package name&amp;gt;&lt;/code&gt;: starts a new Python project by creating a new directory with a standard Python project structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new-package
  new-package
      __init__.py
  tests
      __init__.py
  pyproject.toml
  README.md   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;poetry init&lt;/code&gt;: Initializes a directory by prompting you to provide details about your project and its dependencies interactively. &lt;br&gt;
&lt;code&gt;poetry config virtualenvs.in-project true&lt;/code&gt;: create virtual environments inside the project's directory.&lt;strong&gt;Poetry by default will create a virtual environment under {cache-dir}/virtualenvs.&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;poetry shell&lt;/code&gt; : activate the virtual environment created.&lt;br&gt;
&lt;code&gt;poetry add &amp;lt;django&amp;gt;&lt;/code&gt;: adds a dependency to your project.This will add django to your pyproject.toml file and install django.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Allow &amp;gt;=2.0.0, &amp;lt;3.0.0 versions i.e minor version
poetry add requests^2.0.0

# Allow &amp;gt;=2.0.0, &amp;lt;2.1.0 versions i.e patch versions
poetry add requests~2.0.0

# Allow only a specific version
poetry add requests==2.0.0 | poetry add requests@2.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;poetry add --dev &amp;lt;pytest&amp;gt;&lt;/code&gt;: add dependencies only needed in development.Pytest will be added as a development dependency.&lt;br&gt;
&lt;code&gt;poetry remove &amp;lt;package name&amp;gt;&lt;/code&gt;: removes a package from the current list of installed packages.&lt;br&gt;
&lt;code&gt;poetry show&lt;/code&gt;: list all the available packages.&lt;br&gt;
&lt;code&gt;poetry show &amp;lt;package name&amp;gt;&lt;/code&gt;: list details about a specific package.&lt;br&gt;
&lt;code&gt;poetry version&lt;/code&gt;: shows the current version of the project.&lt;br&gt;
&lt;code&gt;poetry version &amp;lt;patch|minor|major&amp;gt;&lt;/code&gt;:  bumps the version of the project and writes to pyproject.toml.&lt;br&gt;
&lt;code&gt;poetry list&lt;/code&gt;: displays all the available Poetry commands.&lt;br&gt;
&lt;code&gt;poetry install&lt;/code&gt;: reads the pyproject.toml file from the current project, resolves the dependencies, and installs them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://python-poetry.org/docs/cli/" rel="noopener noreferrer"&gt;Commands&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/62764148/how-to-import-an-existing-requirements-txt-into-a-poetry-project" rel="noopener noreferrer"&gt;Importing existing requirements.txt file to poetry&lt;/a&gt;&lt;br&gt;
&lt;a href="https://packaging.python.org/en/latest/guides/writing-pyproject-toml/" rel="noopener noreferrer"&gt;pyproject file&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>A Docker Compose Example (FlaskAPP + PostgreSQL + Traefik).</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Tue, 06 Feb 2024 13:27:49 +0000</pubDate>
      <link>https://forem.com/tinegagideon/a-docker-compose-example-flaskapp-postgresql-traefik-2k0k</link>
      <guid>https://forem.com/tinegagideon/a-docker-compose-example-flaskapp-postgresql-traefik-2k0k</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt; is a tool used for defining and running multi-container Docker applications. It allows developers to describe all the services that make up an application in a single YAML file, defining the relationships and configurations between them. Docker Compose then uses this YAML configuration to deploy and manage the application's containers as a single unit. Docker Compose is particularly useful for development environments, testing, and deploying multi-container applications in a consistent and reproducible manner. It simplifies the process of managing complex application architectures by providing a declarative configuration file and a set of commands for common operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Components of Docker compose
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;compose file &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A YAML file is used to define the configuration of the entire application stack, including services, networks, and volumes. It specifies details such as the Docker images to use, container dependencies, environment variables etc.&lt;/p&gt;

&lt;p&gt;The default path for a Compose file is compose.yaml or compose.yml. docker-compose.yml/docker-compose.yaml also supported for backwards compatibility.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Services&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each service in a Docker Compose file represents a containerized application component. Services can be built from a specified Dockerfile or use pre-built images from a registry. You can define the relationships and dependencies between services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Volumes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Volumes can be defined to persist data outside the containers. This is crucial for storing data that needs to survive container restarts or updates.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Environment Variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker Compose allows you to set environment variables for services.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Networks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker Compose allows you to define custom networks to connect containers and control communication between them. Services can be attached to specific networks to isolate or expose their communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Sample compose file
&lt;/h2&gt;

&lt;p&gt;The Docker Compose file below defines a set of services that work together to run a Flask-based todo application along with a PostgreSQL database and Traefik as a reverse proxy/load balancer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;todo&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tinegagideon/flask-todo&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5000:5000"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DATABASE_URL=postgresql+psycopg2://postgres:postgres@todo-db:5432/postgres&lt;/span&gt;
    &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="c1"&gt;# Explicitly tell Traefik to expose this container&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.enable=true"&lt;/span&gt;
      &lt;span class="c1"&gt;# The domain the service will respond to&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;traefik.http.routers.todo.rule=Host(`localhost`)"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;todo-db&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;traefik&lt;/span&gt;

  &lt;span class="na"&gt;todo-db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:14&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432:5432"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=postgres&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pgdata:/var/lib/postgresql/data&lt;/span&gt;

  &lt;span class="na"&gt;traefik&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;traefik:v3.0&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--api.insecure=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--providers.docker=true"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--providers.docker.exposedbydefault=false"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--entrypoints.web.address=:80"&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:8080"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock:ro"&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pgdata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Compose file breakdown
&lt;/h3&gt;

&lt;p&gt;The compose file is divided into two sections: services and volume, with three services.&lt;/p&gt;

&lt;h4&gt;
  
  
  Services Section
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;todo Service&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It uses an image named tinegagideon/flask-todo for the Flask todo application.&lt;/li&gt;
&lt;li&gt;Exposes port 5000 of the container to port 5000 of the host machine.&lt;/li&gt;
&lt;li&gt;Sets environment variables for the Flask application, including the database URL.&lt;/li&gt;
&lt;li&gt;Uses labels to configure Traefik to expose this service and defines the routing rule.&lt;/li&gt;
&lt;li&gt;Depends on the todo-db service and the traefik service.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;todo-db Service&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses the official PostgreSQL image with version 14.&lt;/li&gt;
&lt;li&gt;Exposes port 5432 of the container to port 5432 of the host machine.&lt;/li&gt;
&lt;li&gt;Sets environment variables for the PostgreSQL database i.e the password, username, and database name.&lt;/li&gt;
&lt;li&gt;Mounts a volume named pgdata to persist PostgreSQL data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;traefik Service&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses the Traefik image with version 3.0.&lt;/li&gt;
&lt;li&gt;Specifies command-line arguments for Traefik:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;--api.insecure=true&lt;/code&gt; &lt;br&gt;
enables insecure access to the Traefik API.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--providers.docker=true&lt;/code&gt; &lt;br&gt;
enables Docker as a provider.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--providers.docker.exposedbydefault=false&lt;/code&gt; &lt;br&gt;
specifies that services must be explicitly exposed.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--entrypoints.web.address=:80&lt;/code&gt;&lt;br&gt;
 defines the entry point for HTTP traffic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exposes port 80 and port 8080 of the container to the corresponding ports on the host machine.&lt;/li&gt;
&lt;li&gt;Mounts the Docker socket to interact with Docker daemon inside the Traefik container.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Volumes Section
&lt;/h4&gt;

&lt;p&gt;Defines a named volume named pgdata that is used by the todo-db service to persist PostgreSQL data.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Crafting a Docker Image for Your Flask Web App</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Fri, 12 Jan 2024 19:20:28 +0000</pubDate>
      <link>https://forem.com/tinegagideon/crafting-a-docker-image-for-your-flask-web-app-2l8g</link>
      <guid>https://forem.com/tinegagideon/crafting-a-docker-image-for-your-flask-web-app-2l8g</guid>
      <description>&lt;h2&gt;
  
  
  Introduction🐋
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; is a revolutionary containerization platform that streamlines software development and deployment. It encapsulates applications and their dependencies, ensuring consistency across different environments. Docker eliminates the "it works on my machine" problem, promoting collaboration and scalability. Its efficient resource utilization and isolation capabilities make it a vital tool for modern software development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites 🗒
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Flask Application.&lt;/li&gt;
&lt;li&gt;Docker &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;Follow these steps to install docker to your computer&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Docker Hub Account &lt;a href="https://hub.docker.com/signup/" rel="noopener noreferrer"&gt;create a free account&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;I will assume that you have a basic understanding of python, especially the Flask framework and an understanding of networking ports&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample project 🏗️
&lt;/h2&gt;

&lt;p&gt;Project Directory Structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hello-flask/
├── app/
│   ├── __init__.py
│   └── app.py
├── requirements.txt
└── Dockerfile

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

&lt;/div&gt;



&lt;p&gt;Sample code in app.py file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;from flask import Flask

app = Flask(__name__) # create an instance of our imported Flask class.


@app.route("/")
def home():
    return 'hello flask'

# allows the code to be executed directly as a script
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://flask.palletsprojects.com/en/3.0.x/quickstart/" rel="noopener noreferrer"&gt;Official Flask Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dockerfile 📝
&lt;/h2&gt;

&lt;p&gt;Docker automates image creation by interpreting instructions from a &lt;a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/#:~:text=What%20is%20a%20Dockerfile%3F,to%20build%20a%20given%20image." rel="noopener noreferrer"&gt;Dockerfile&lt;/a&gt;, a text file containing sequential commands required to build a specific image. A Docker image comprises immutable layers, each representing an instruction from the Dockerfile. These layers are arranged in a stack, with each one capturing the incremental changes made compared to the previous layer.&lt;br&gt;
create a Dockerfile with the following instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM python:alpine

RUN apk update 
RUN apk add -y python-pip; pip install --no-cache-dir --upgrade pip
WORKDIR /hello-flask
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY /app .
ENTRYPOINT [ "python" ]
CMD [ "app.py" ]

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Each instruction break down
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;FROM python:alpine&lt;/code&gt;&lt;br&gt;
It specifies the base image to use, in this case, python:alpine. This image is based on the Alpine Linux distribution and includes Python.&lt;/p&gt;

&lt;p&gt;Note that while it's possible to use a Debian-based distro as the base image, it would require manual installation of Python within the image.  A python image based on alpine is smaller size compared to other distributions, therefore contributing to a more lightweight and efficient container. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;RUN apk update&lt;/code&gt;&lt;br&gt;
This updates the package index on the Alpine system using the apk package manager.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RUN apk add -y python-pip; pip install --no-cache-dir --upgrade pip&lt;/code&gt;&lt;br&gt;
This installs python-pip using apk and then upgrades pip to the latest version. The -y flag is used to automatically confirm the installation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;WORKDIR /hello-flask&lt;/code&gt;&lt;br&gt;
Sets the working directory inside the container to /hello-flask.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;COPY requirements.txt .&lt;/code&gt;&lt;br&gt;
Copies the requirements.txt file from the build context (where the Dockerfile is located) into the /hello-flask directory in the container.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RUN pip install -r requirements.txt&lt;/code&gt;&lt;br&gt;
Installs the Python packages listed in requirements.txt using pip. This is typically done in a separate step to take advantage of Docker layer caching.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;COPY /app .&lt;/code&gt;&lt;br&gt;
Copies the contents of the /app directory from the build context into the current working directory &lt;code&gt;/hello-flask&lt;/code&gt; in the container.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ENTRYPOINT [ "python" ]&lt;/code&gt;&lt;br&gt;
Specifies the default executable when the container starts. In this case, it sets the default executable to Python.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CMD [ "app.py" ]&lt;/code&gt;&lt;br&gt;
Provides default arguments for the ENTRYPOINT. When the container is run, it will execute python app.py by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building your docker image 🔨
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.docker.com/engine/reference/commandline/build/" rel="noopener noreferrer"&gt;docker build&lt;/a&gt; command builds Docker images from a Dockerfile and a context.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker image build -t myrepo/hello-flask .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will build an image with the repository name as &lt;code&gt;myrepo/hello-flask&lt;/code&gt; and a tag of latest is applied by default. &lt;br&gt;
The &lt;code&gt;-t&lt;/code&gt; option allows you to tag your Docker image with a specific name and optionally a tag.&lt;br&gt;
Tags are typically appended to the image name by specifying them following a colon.&lt;/p&gt;

&lt;p&gt;The dot at the end of the command specifies the build context. The build context is the path to the directory containing the Dockerfile and any files needed for the build process. In this case, it's set to the current directory&lt;/p&gt;

&lt;h2&gt;
  
  
  Running a container from your image 📦
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://docs.docker.com/engine/reference/commandline/run/" rel="noopener noreferrer"&gt;docker container run&lt;/a&gt; command runs a command in a new container, pulling the image if needed and starting the container.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker container run --rm -p 5000:5000  myrepo/hello-flask&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;replace &lt;code&gt;myrepo&lt;/code&gt; with your docker hub username or if you don't intend to upload to image just use  name of the image.e.g &lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker container run --rm -p 5000:5000 hello-flask&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--rm&lt;/code&gt;&lt;br&gt;
This flag removes the container automatically after it stops running. It helps to keep the system clean by avoiding the accumulation of unused containers.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;-p 5000:5000&lt;/code&gt;&lt;br&gt;
This flag maps the port 5000 from the host to the port 5000 on the container. It allows communication between the host machine and the running container through this specified port.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;myrepo/hello-flask&lt;/code&gt; &lt;br&gt;
This is the name of the Docker image used to create the container. It's assumed that you have an image named hello-flask in the myrepo repository.&lt;/p&gt;

&lt;p&gt;another useful OPTION to add to the docker container run command is:&lt;br&gt;
&lt;code&gt;--detach&lt;/code&gt; or &lt;code&gt;-d&lt;/code&gt; this runs the container in the background and prints its ID.&lt;/p&gt;

&lt;p&gt;You should be able to view a webpage by visiting &lt;a href="http://localhost:5000" rel="noopener noreferrer"&gt;http://localhost:5000&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Pushing your image to docker hub 🚀
&lt;/h2&gt;

&lt;p&gt;Before trying to push your image make sure to login in the docker CLI using &lt;code&gt;docker login&lt;/code&gt; with your docker hub credentials.&lt;/p&gt;

&lt;p&gt;Use &lt;a href="https://docs.docker.com/engine/reference/commandline/push/" rel="noopener noreferrer"&gt;docker image push&lt;/a&gt; to upload your images to the Docker Hub registry or to a self-hosted one.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker image push myrepo/hello-flask&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Commands
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;docker image tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]&lt;/code&gt; -- create an image tag&lt;br&gt;
&lt;code&gt;docker image ls&lt;/code&gt; -- lists images in your local machine.&lt;br&gt;
&lt;code&gt;docker container ls&lt;/code&gt; or &lt;code&gt;docker ps [OPTIONS]&lt;/code&gt; -- lists containers.&lt;br&gt;
&lt;code&gt;docker container stop [container id | container name]&lt;/code&gt; -- stop a running container&lt;br&gt;
&lt;code&gt;docker container rm [container id | container name]&lt;/code&gt; -- remove container&lt;br&gt;
&lt;code&gt;docker image prune [OPTIONS]&lt;/code&gt; -- remove unused images.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/engine/reference/commandline/cli/" rel="noopener noreferrer"&gt;More Commands - Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Images Vs Containers
&lt;/h2&gt;

&lt;p&gt;An image represents the application we intend to execute, while a container is an instance of that image running as a process.&lt;/p&gt;

&lt;p&gt;Think of a Docker image as a recipe or a blueprint for creating a specific environment, and a Docker container as a ready-made dish prepared using the recipe (image).&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>python</category>
      <category>docker</category>
      <category>devops</category>
    </item>
    <item>
      <title>Elevating PRs with the Magic of an AI-Agent for a Seamless Experience: PR-Agent Vs Copilot For PRs</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Thu, 07 Dec 2023 10:14:29 +0000</pubDate>
      <link>https://forem.com/tinegagideon/elevating-prs-with-the-magic-of-an-ai-agent-for-a-seamless-experience-pr-agent-vs-copilot-for-prs-3pm1</link>
      <guid>https://forem.com/tinegagideon/elevating-prs-with-the-magic-of-an-ai-agent-for-a-seamless-experience-pr-agent-vs-copilot-for-prs-3pm1</guid>
      <description>&lt;h2&gt;
  
  
  Pull Request
&lt;/h2&gt;

&lt;p&gt;A pull request (PR) is a fundamental concept in version control systems, particularly in distributed version control systems like Git. It is a mechanism used to propose changes to a codebase in a collaborative software development environment. &lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of a pull request workflow
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Isolation of Changes: Each pull request is associated with a specific branch, allowing changes to be isolated until they are thoroughly reviewed and tested.&lt;/li&gt;
&lt;li&gt;Collaborative Code Review: They facilitate collaborative code reviews, allowing multiple team members to review and discuss proposed changes before merging.&lt;/li&gt;
&lt;li&gt;Continuous Integration: Integration with CI tools ensures that changes do not break existing functionality and meet project standards before being merged.&lt;/li&gt;
&lt;li&gt;Improve code quality and performance: When creating a pull request, you're inviting a colleague to review your code, seeking constructive feedback. This collaborative process aims to enhance code quality through the insights and suggestions provided by the reviewer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pull requests play a pivotal role in version control systems. Tools like Copilot for PRs and CodiumAI PR-Agent serve the purpose of enhancing PR descriptions and facilitating faster review and merging processes, thereby contributing to improved collaboration within your team.&lt;/p&gt;

&lt;h2&gt;
  
  
  CodiumAI's PR-Agent
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.codium.ai/products/git-plugin/" rel="noopener noreferrer"&gt;CodiumAI's PR-Agent&lt;/a&gt; is an &lt;strong&gt;open source&lt;/strong&gt; AI agent tool designed to streamline and expedite the process of reviewing pull requests (PRs). This tool automatically analyzes both the commits and the PR itself, delivering various types of feedback to enhance the efficiency of the review process. CodiumAI's PR Agent features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PR Review&lt;/strong&gt;: Feedback about the PR main theme, type, relevant tests, security issues, focused PR, and various suggestions for the PR content. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-Description&lt;/strong&gt;: Automatically generating PR description - name, type, summary, and code walkthrough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Question Answering&lt;/strong&gt;: Answering free-text questions about the PR. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Suggestion&lt;/strong&gt;: Committable code suggestions for improving the PR.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Getting started with CodiumAI's PR-Agent
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;For public repositories&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just mention the name &lt;code&gt;@CodiumAI-Agent&lt;/code&gt; in your git provider environment and ask to &lt;strong&gt;/review&lt;/strong&gt;, &lt;strong&gt;/describe&lt;/strong&gt;, &lt;strong&gt;/improve&lt;/strong&gt;, or &lt;strong&gt;/ask&lt;/strong&gt; anything e.g. "Is my PR documented enough?", and the agent will perform these tasks for you.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For private repositories and open-source projects:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You will first need to install the app on you private repo. Just follow this detailed &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/INSTALL.md" rel="noopener noreferrer"&gt;step by step guide&lt;/a&gt;. Then summon your pull request helping agent easily, just write /review, /describe, /improve or /ask anything e.g. "is my PR documented enough?", and the agent will perform these tasks for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Try it it's Free
&lt;/h3&gt;

&lt;p&gt;In any PR comment on your public GitHub repository, mention &lt;code&gt;@CodiumAI-Agent&lt;/code&gt; with a desired command in any PR comment. The agent will generate a response based on your command.&lt;/p&gt;

&lt;h3&gt;
  
  
  PR-Agent Commands
&lt;/h3&gt;

&lt;p&gt;Explore the links for in-depth details and examples related to the commands.&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/REVIEW.md" rel="noopener noreferrer"&gt;/review&lt;/a&gt;: Scans the PR code changes, and automatically generates a PR review.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7lxglebdqlgv6d4vjsn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7lxglebdqlgv6d4vjsn.png" alt="review example" width="800" height="625"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/ASK.md" rel="noopener noreferrer"&gt;/ask "..."&lt;/a&gt;: Answers questions about the PR, based on the PR code changes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3x69obnkxtq02l4jpx9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc3x69obnkxtq02l4jpx9.png" alt="ask example" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/IMPROVE.md" rel="noopener noreferrer"&gt;/improve&lt;/a&gt;: Scans the PR code changes, and automatically generates committable suggestions for improving the PR code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjrlivxwgwpew0byqeqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhjrlivxwgwpew0byqeqe.png" alt="improve example" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md" rel="noopener noreferrer"&gt;/describe&lt;/a&gt;: Scans the PR code changes, and automatically generates PR description - title, type, summary, code walkthrough and labels.&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/ADD_DOCUMENTATION.md" rel="noopener noreferrer"&gt;/add_docs&lt;/a&gt;: Scans the PR code changes, and automatically suggests documentation for the undocumented code components (functions, classes, etc.).&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/SIMILAR_ISSUE.md" rel="noopener noreferrer"&gt;/similar_issue&lt;/a&gt;: Retrieves the most similar issues to the current issue.&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/UPDATE_CHANGELOG.md" rel="noopener noreferrer"&gt;/update_changelog&lt;/a&gt;: Automatically updates the CHANGELOG.md file with the PR changes.&lt;/p&gt;

&lt;p&gt;✅ &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/GENERATE_CUSTOM_LABELS.md" rel="noopener noreferrer"&gt;/generate_labels&lt;/a&gt;: Scans the PR code changes, and given a list of labels and their descriptions, it automatically suggests labels that match the PR code changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Copilot for PRs
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://githubnext.com/projects/copilot-for-pull-requests" rel="noopener noreferrer"&gt;Copilot for PRs&lt;/a&gt; brings the power of Copilot to the PR experience, to help you write better PR descriptions, and to help your team review and merge PRs faster. Copilot for PRs features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Suggestions for your pull request description&lt;/strong&gt; : allows developers to insert marker tags in their pull request description. When the description is saved, Copilot will expand the marker into a description of the changes in the pull request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered review responses&lt;/strong&gt;: auto-generate changes in response to requests to add documentation or even to add another test&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered PR repair&lt;/strong&gt;: Proposes a fix to forgotten documentation and unit test updates during the PR process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-powered PR completion&lt;/strong&gt;: Copilot's bot is being empowered with the capability to complete pull requests given a few indicative edits such as adding comments to all your functions, throughout all your code. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gentest&lt;/strong&gt;: Copilot's prototype uses AI to identify changes in your PR that may be lacking tests, and suggests tests for you to build on or use directly. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resolving issues with AI&lt;/strong&gt;: automatically describes how to solve an issue and even to automatically suggest the changes you need to make. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Getting started with Copilot for PRs
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Sign in with GitHub. This dashboard will be used to manage your Copilot for PRs settings.&lt;/li&gt;
&lt;li&gt;Install the GitHub App. You must have admin access to the repository or be an owner of the organization to install the GitHub App.&lt;/li&gt;
&lt;li&gt;Add your repos to the waitlist. Copilot for PRs is available as a technical preview in order to identify if it brings value to our users. We're limited on capacity, so you'll need to add your repositories to our waitlist.&lt;/li&gt;
&lt;li&gt;Include marker tags in your PR description. Copilot will automatically expand them for you.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Copilot for PRs Markers/commands
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;copilot:all&lt;/code&gt;: showcases all the different kinds of content in one go.&lt;br&gt;
&lt;code&gt;copilot:summary&lt;/code&gt;: expands to a one-paragraph summary of the changes in the pull request.&lt;br&gt;
&lt;code&gt;copilot:walkthrough&lt;/code&gt;: expands to a detailed list of changes, including links to the relevant pieces of code.&lt;br&gt;
&lt;code&gt;copilot:poem&lt;/code&gt;: expands to a poem about the changes in the pull request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Platforms 💻
&lt;/h3&gt;

&lt;p&gt;CodiumAI's PR-Agent offers extensive compatibility with various Git providers such as GitHub, GitLab, Bitbucket, and CodeCommit. Its versatility is showcased through multiple usage options including CLI, GitHub Action, GitHub App, Docker, among others. While Copilot for PRs currently caters exclusively to GitHub, this platform-specific support seamlessly integrates with GitHub workflows. Additionally, PR-Agent provides users with the flexibility to choose from a diverse range of models, including GPT-4, GPT-3.5, Anthropic, Cohere, and Llama2, allowing for a customized experience based on specific project requirements or user preferences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source code 📜
&lt;/h3&gt;

&lt;p&gt;CodiumAI's PR-Agent operates on an open-source basis, actively encouraging contributions from the community. In contrast, GitHub Copilot is not open source; it is a proprietary product developed by GitHub, a subsidiary of Microsoft. While GitHub Copilot utilizes OpenAI's Codex model as its underlying technology, the specific implementation and integration with GitHub remain proprietary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ease of Use 👍
&lt;/h3&gt;

&lt;p&gt;When it comes to installation and use case scenarios, CodiumAi provides excellent documentation and clear, easy-to-follow explanations. As of right now, Copilot for PRs documentation is not as informative. In addition PR-Agent commands are concise and provide detailed feedback.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data Privacy 🕵️‍♀️
&lt;/h3&gt;

&lt;p&gt;CodiumAI empowers developers who prioritize privacy to independently host their PR-Agent instances, with a steadfast commitment: no user data is stored or used for training purposes. In contrast, GitHub Copilot Business gathers personal data across three categories: User Engagement Data, Prompts, and Suggestions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pricing 💰
&lt;/h3&gt;

&lt;p&gt;CodiumAI's PR-Agent is available for free, in contrast to GitHub Copilot, which comes with a price tag of $10 USD per month or $100 USD per year. Nonetheless, GitHub Copilot does offer a complimentary tier for students and educators.&lt;/p&gt;

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

&lt;p&gt;By automatically generating detailed pull request descriptions, providing intelligent code suggestions, and ensuring documentation accuracy, CodiumAI sets itself apart with unparalleled depth and customization. Unlike settling for less, users embrace a tool that evolves with them, thanks to its open-source nature. CodiumAI serves as a community-driven platform, incorporating diverse expertise to cater to the ever-changing needs of developers. Acting as a coding companion, it supports users in tasks ranging from intricate code reviews to generating test cases, answering queries, and streamlining changelog updates.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>opensource</category>
      <category>git</category>
    </item>
    <item>
      <title>Python One Liners</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Mon, 27 Nov 2023 08:32:01 +0000</pubDate>
      <link>https://forem.com/tinegagideon/python-one-liners-1klg</link>
      <guid>https://forem.com/tinegagideon/python-one-liners-1klg</guid>
      <description>&lt;p&gt;In Python, a "one-liner" is a concise and frequently ingenious solution to a problem that can be stated in only one line of code. For readability and maintainability in bigger codebases, they are not always advised, despite their sometimes-elegant and potent nature. They are, nevertheless, frequently employed in scripting, where conciseness is valued. Here are a few sample lines of code for one-liner solutions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple variable assignments
&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;occupation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keisha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cook&lt;/span&gt;&lt;span class="sh"&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;occupation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# keisha 30 cook
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;HTTP server
&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;python&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;server&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Swap variables
&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;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;b&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&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;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# b a
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ternary operator
&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;yob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1997&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;hey kid(gen alpha)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;yob&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;2013&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wassup gen z&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;yob&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1995&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello millennials&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;yob&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1980&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hey gen x&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;yob&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;1965&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello baby boomer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# wassup gen z
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Variable unpacking
&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;users&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;kalama&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;kairetu&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;munga&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;mwanaisha&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#kalama kairetu munga mwanaisha
&lt;/span&gt;
&lt;span class="n"&gt;user1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user2&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;other_users&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;users&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;other_users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#['munga', 'mwanaisha']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Reverse a list
&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;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;40&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;z&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;#[40, 30, 20, 10]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Sort a list
&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;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;999999999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1000000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;123456789&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="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# [-1000000000, -500000, 1000000, 123456789, 999999999]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Sort a list - reversed
&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;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;500000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;999999999&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1000000000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;123456789&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="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;reverse&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;#[999999999, 123456789, 1000000, -500000, -1000000000]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Filter from a list
&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;numbers&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;4&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="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;odd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;!=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;numbers&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;odd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#[1, 3, 5, 7, 9]
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://dev.to/tinegagideon/list-dictionary-comprehension-in-python-53m8"&gt;List comprehension&lt;/a&gt;
&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;names&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;lizzy&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;bruce&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;wafula&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="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="c1"&gt;#['Lizzy', 'Bruce', 'Wafula']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Remove duplicates from a list
&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;num&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&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="mi"&gt;5&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;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="c1"&gt;# [1, 2, 3, 4, 5, 8, 9]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Combine two lists to a dictionary
&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;letters&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;a&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;b&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;c&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;d&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;4&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="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;letters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="c1"&gt;# {'a': 1, 'b': 2, 'c': 3, 'd': 4}
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Unpacking using * operator and zip
&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;pair&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;jack&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;inaam&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Anna &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;John&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;marks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pair&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;names&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;marks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;#('jack', 'inaam', 'Anna ', 'John')
#(50, 80, 70, 35)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Type conversion of items in an iterable using map function
&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;strings&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;1&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;2&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;3&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;4&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;5&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;6&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;7&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;8&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="nf"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;strings&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="c1"&gt;# (1, 2, 3, 4, 5, 6, 7, 8)
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Alternative value for input statements
&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;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Name: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;#using ternary operator
&lt;/span&gt;
&lt;span class="n"&gt;name_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Name: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name_input&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name_input&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;N/A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Creating a &lt;a href="https://docs.python.org/3/library/copy.html" rel="noopener noreferrer"&gt;shadow copy&lt;/a&gt; of a list
&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;mylist&lt;/span&gt; &lt;span class="o"&gt;=&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="mi"&gt;4&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="n"&gt;copy_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mylist&lt;/span&gt;&lt;span class="p"&gt;[:]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>beginners</category>
      <category>python</category>
    </item>
    <item>
      <title>Web Scraping using Selenium: A Guide for Beginners</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Mon, 09 Oct 2023 13:07:48 +0000</pubDate>
      <link>https://forem.com/tinegagideon/web-scraping-using-selenium-a-guide-for-beginners-3ke6</link>
      <guid>https://forem.com/tinegagideon/web-scraping-using-selenium-a-guide-for-beginners-3ke6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.selenium.dev/" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt; is a framework that many developers use to automate web browsers. It's an open source tool that offers compatibility, with web browsers and supports programming languages. While its commonly used for testing web applications it's also handy for tasks like web scraping and automating browser actions. WebDriver, which is a part of Selenium allows developers to control web browsers programmatically. &lt;/p&gt;

&lt;h2&gt;
  
  
  Using Selenium to scrape data
&lt;/h2&gt;

&lt;p&gt;Task: Scraping the latest news posts from a popular blog post&lt;br&gt;
&lt;strong&gt;Please note that to follow along you must have an understanding of basic HTML elements and CSS classes and id selectors as well as python&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To use selenium we first need to install the package using &lt;a href="https://pypi.org/project/selenium/" rel="noopener noreferrer"&gt;pip&lt;/a&gt;.&lt;br&gt;
&lt;code&gt;pip install selenium&lt;/code&gt;&lt;br&gt;
Using a code editor of your choice create a .py file and import selenium.webdriver module which provides all the WebDriver implementations.&lt;/p&gt;

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

from selenium import webdriver

driver = webdriver.Chrome()
driver.get('https://www.google.com')


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

&lt;/div&gt;

&lt;p&gt;To test if everything is working so far we need to instruct the Selenium WebDriver to navigate a given URL.&lt;br&gt;
Running the .py file should launch a browser instance and close immediately the website loads.&lt;/p&gt;

&lt;p&gt;Chrome() class also provides implementation for chromium based browsers e.g brave and not just the chrome.&lt;/p&gt;

&lt;p&gt;To use Brave, a Chromium-based browser, with Selenium WebDriver in Python, you can set the binary location using the webdriver.ChromeOptions() class and then pass these options as a parameter when creating the WebDriver instance. Here's how you can do it:&lt;/p&gt;

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

from selenium import webdriver

BROWSER_PATH = r"C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe"
OPTIONS = webdriver.ChromeOptions()
OPTIONS.binary_location = BROWSER_PATH

driver = webdriver.Chrome(options=OPTIONS)
driver.get('https://www.google.com')


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

&lt;/div&gt;

&lt;p&gt;To prevent the browser instance from closing, add the following property with name 'detach' and set its value to 'True'&lt;br&gt;
&lt;code&gt;OPTIONS.add_experimental_option("detach", True)&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Scraping the data
&lt;/h2&gt;

&lt;p&gt;I will demonstrate using pulselive website. The following code should load the website on a browser instance.&lt;/p&gt;

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

from selenium import webdriver

BROWSER_PATH = r"C:\Program Files\BraveSoftware\Brave-Browser\Application\brave.exe"
OPTIONS = webdriver.ChromeOptions()
OPTIONS.binary_location = BROWSER_PATH
OPTIONS.add_experimental_option("detach", True)

URL = 'https://www.pulselive.co.ke/news'

driver = webdriver.Chrome(options=OPTIONS)
driver.get(URL)



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

&lt;/div&gt;

&lt;p&gt;We now need find the HTML elements that may be of use to us.&lt;br&gt;
To interact with web pages and find HTML elements using Developer Tools, you can follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open Brave browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate to the web page you want to inspect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To open Developer Tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On Windows/Linux: Press &lt;code&gt;Ctrl + Shift + I&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;On macOS: Press &lt;code&gt;Option + ⌘ + I&lt;/code&gt; or right-click anywhere on the page and select "Inspect" from the context menu.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the Developer Tools panel that opens, you will see various tabs such as "Elements," "Console," "Network," etc. You are interested in the "Elements" tab, which shows the HTML structure of the web page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In the "Elements" tab, you can expand and collapse elements to explore the page's structure. Look for the &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; element with a class name of "article-list-items." It should be under the &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; (unordered list) element, and each list item &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; should contain an &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag for the article link and an &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt; tag for the article title.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;h3&gt;
  
  
  Locating elements using By
&lt;/h3&gt;

&lt;p&gt;This is done by first importing By from from selenium.webdriver.common.by&lt;br&gt;
&lt;code&gt;from selenium.webdriver.common.by import By&lt;/code&gt;&lt;br&gt;
next we instruct the webdriver instance using find_element method i.e&lt;code&gt;driver.find_element(By.CLASS_NAME, value='article-list-items')&lt;/code&gt; then assign this to a variable(i named mine articles)&lt;br&gt;
&lt;strong&gt;Note: div(class='article-list-items') is the parent element of the articles.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63zgifjh2ibbgenlcgqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F63zgifjh2ibbgenlcgqa.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
Executing this code returns a selenium webElement, To access the relevant text and links, we need to narrow down using css selectors to the specific element that we are targeting i.e getting all the links contained in the div element with a class name &lt;strong&gt;article-list-items&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Remember the div with a class name &lt;strong&gt;article-list-items&lt;/strong&gt;,it is an unordered list element containing list elements(the list elements also contain other divs and anchor tags)&lt;br&gt;
&lt;code&gt;find_elements(By.CSS_SELECTOR)&lt;/code&gt; value='li a' helps narrow down to the target element in our case, links in the anchor tags.&lt;br&gt;
Since &lt;code&gt;find_elements&lt;/code&gt; does not return a single element but all the elements matching our value, assign a variable to point to the results and iterate to get a hold of each item.&lt;br&gt;
Finally for each item call the &lt;code&gt;get_attribute&lt;/code&gt; method with attribute name 'href' to return the url contained in each anchor tag.&lt;/p&gt;

&lt;p&gt;For the article titles the approach is similar.&lt;/p&gt;

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

&lt;p&gt;To get the title contained in h2 tags use find elements by css selector value='li h2' and because h2 tags do not have attributes but instead contain texts in between. The text can be retrieved by using the property &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwh1a0shonmhwy7ml4f78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwh1a0shonmhwy7ml4f78.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
The above code prints the articles with article titles and links separated by a semi-colon. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final tips&lt;/strong&gt;&lt;br&gt;
Have you noticed how every time we ran the code a new browser application window is launched.using this option &lt;code&gt;OPTIONS.add_argument("--headless=new")&lt;/code&gt; runs everything in the background.&lt;br&gt;
To automatically shut down the chromiumdriver executable instance i.e browser instance add &lt;code&gt;driver.quit()&lt;/code&gt; at the end of your code.&lt;/p&gt;

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

&lt;p&gt;This is just a simple example use case on how automation can be used to simplify the process of acquiring information. The amount of applications is vast and i hope this demonstration provides you will a few insights and tips on how to get started with web scraping automation.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://selenium-python.readthedocs.io/" rel="noopener noreferrer"&gt;Unofficial documentation&lt;/a&gt; here.&lt;/p&gt;

</description>
      <category>python</category>
      <category>selenium</category>
      <category>web</category>
      <category>automation</category>
    </item>
    <item>
      <title>List &amp; Dictionary Comprehension in Python</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Fri, 08 Sep 2023 10:12:42 +0000</pubDate>
      <link>https://forem.com/tinegagideon/list-dictionary-comprehension-in-python-53m8</link>
      <guid>https://forem.com/tinegagideon/list-dictionary-comprehension-in-python-53m8</guid>
      <description>&lt;h2&gt;
  
  
  List Comprehension
&lt;/h2&gt;

&lt;p&gt;Python lists are a fundamental data structure for storing and managing data collections. Lists are adaptable, flexible, and may store a variety of data kinds, including integers, strings, and even other lists.&lt;br&gt;
List comprehension lets you make a new list by applying an expression to each item in an existing iterable (such as a list, tuple, or range) and optionally filtering the items depending on a condition. List comprehensions are a more compact and readable means of creating lists than typical for loops.&lt;br&gt;
As an example, suppose we want to create a new list of even numbers from a list of random numbers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;numbers = [84, 77, 50, 89, 33, 36, 59, 31, 76, 1, 20, 58, 59, 93, 70, 28, 51, 7, 48, 74]

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

&lt;/div&gt;



&lt;p&gt;Using a for loop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;even_numbers = []

for number in numbers:
    if number % 2 == 0:
        even_numbers.append(number)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using list comprehension&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;even_numbers = [num for num in numbers if num % 2 == 0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;the syntax for list comprehension is :&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;list = [new_item for item in some_list if conditional_statement]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dictionary Comprehension
&lt;/h2&gt;

&lt;p&gt;Dictionaries in Python are a versatile data structure that may be used to store and manage collections of key-value pairs. &lt;br&gt;
Dictionary comprehension is a simple and effective method for creating dictionaries in Python. You can create dictionaries by specifying key-value pairs based on an expression and an iterable. Dictionary comprehensions are a logical extension of list comprehensions and a useful feature for easily generating dictionaries without the use of explicit loops.&lt;/p&gt;

&lt;p&gt;suppose we have a dictionary of cars and year of manufacture, and we want to create a dictionary of  recently manufactured ones&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;car_dictionary = {
    "Tesla Model 3": 2020,
    "Toyota Camry": 2022,
    "Ford Mustang": 2021,
    "Honda Civic": 2023,
    "Chevrolet Silverado": 2019
}

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

&lt;/div&gt;



&lt;p&gt;using a for loop&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;recently_manufactured = {}

for (car,year) in car_dictionary.items():
    if year &amp;gt; 2021:
        recently_manufactured[car] = year

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

&lt;/div&gt;



&lt;p&gt;using dictionary comprehension&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;recently_manufactured = {car:year for (car, year) in car_dictionary.items() if year &amp;gt; 2021}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;the syntax for dictionary comprehension is:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dictionary = {new_key:new_value for (key, value) in some_dict.items() if conditional_statement}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Manually add an appimage software shortcut to application menu in linux</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Tue, 23 Mar 2021 20:04:29 +0000</pubDate>
      <link>https://forem.com/tinegagideon/manually-add-an-appimage-software-shortcut-to-application-menu-in-linux-29ok</link>
      <guid>https://forem.com/tinegagideon/manually-add-an-appimage-software-shortcut-to-application-menu-in-linux-29ok</guid>
      <description>&lt;p&gt;I am going demonstrate how you can add an appimage application shortcut to linux desktop system's application menu and also how to customize its icon.But first lets get to understand what an appimage software is.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is an appimage application and what are its benefits
&lt;/h3&gt;

&lt;p&gt;For starters,there are many ways an application can be installed in a linux system i.e deb packages,snaps,flatpaks and appimages.Our focus today is appimages.&lt;br&gt;
An Appimage application is a single portable and executable software that can be run on linux without installation.&lt;/p&gt;

&lt;p&gt;Benefits of using appimages&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compatibility with most linux distributions.&lt;/li&gt;
&lt;li&gt;Simple to run i.e download,make it executable and run.since it is not installed no system libraries are altered.&lt;/li&gt;
&lt;li&gt;Download and use trusted software directly from the original author(s).&lt;/li&gt;
&lt;li&gt;Uninstalling is as simple as just deleting the file. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Running an app image
&lt;/h3&gt;

&lt;p&gt;Lets download the fluent reader software(it is a modern rss reader) as an example.&lt;br&gt;
&lt;a href="https://github.com/yang991178/fluent-reader/releases/" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvx6ky9gx0k4m67pxzrl7.png" alt="Alt Text"&gt; &lt;/a&gt;&lt;br&gt;
Once download is completed,navigate to the downloads folder and right-click on the downloaded appimage file,click on Properties thereafter,Click on the permissions tab and check the execute option.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1zzsddos3f1ybcf8epw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1zzsddos3f1ybcf8epw.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
The software should be running by now without any problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a shortcut with custom icon to the linux application menu
&lt;/h3&gt;

&lt;p&gt;Note: super user permission is required for this process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the terminal&lt;/li&gt;
&lt;li&gt;Navigare to the /usr/share/applications directory.&lt;/li&gt;
&lt;li&gt;Create a new file with a .desktop extension in the applications directory.&lt;/li&gt;
&lt;li&gt;Open the file with gedit
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiycr868yzpkluvmx2jmh.png" alt="Alt Text"&gt;
&lt;/li&gt;
&lt;li&gt;Add the following template text to your empty file and replace with the location of your exec(i.e appimage location) and icon of your choice.eg
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6rnf41qi9v2gewl2xvwu.png" alt="Alt Text"&gt;
&lt;/li&gt;
&lt;li&gt;Save your file and exit the terminal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should be able to see your software shortcut in the menu and it should run when clicked if you followed the steps above correctly.&lt;/p&gt;

&lt;p&gt;Thanks and have fun ☺️&lt;/p&gt;

</description>
      <category>linux</category>
      <category>ubuntu</category>
      <category>beginners</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Hosting Your App For Free</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Fri, 10 Jul 2020 11:31:25 +0000</pubDate>
      <link>https://forem.com/tinegagideon/hosting-your-app-for-free-1fk0</link>
      <guid>https://forem.com/tinegagideon/hosting-your-app-for-free-1fk0</guid>
      <description>&lt;p&gt;A weather application is always the first and easiest way for many developers to learn how to use APIs.Today we are going to go through the basics of creating and deploying your site build using Vue.js.&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting Started
&lt;/h1&gt;

&lt;p&gt;First we need to create a free &lt;a href="https://home.openweathermap.org/users/sign_up" rel="noopener noreferrer"&gt;open weather&lt;/a&gt; account to access their API.&lt;br&gt;
To use vueCLI, we need to download and install &lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flvmykcuig1hfwjut4ivz.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the installation is completed run the following commands in the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g @vue/cli
# OR
yarn global add @vue/cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  creating the project
&lt;/h2&gt;

&lt;p&gt;To create a project open your terminal and,run &lt;code&gt;vue create weather&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff8uqfngw44nuf763q733.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff8uqfngw44nuf763q733.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Navigate and select default using the arrow keys.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzwzi4rjesn1gw3706n44.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzwzi4rjesn1gw3706n44.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
When completed a folder will be created with git initialized.&lt;br&gt;
Open the folder using your code editor of choice.&lt;br&gt;
It should show something similar to this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faiwdr5hb4ety3fayc9if.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Faiwdr5hb4ety3fayc9if.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Coding
&lt;/h2&gt;

&lt;p&gt;Since it is a very small application we wont need the components folder and we are going to have to delete the boilerplate code already there in the App.vue file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvr3cpvv90mltjnbv81u1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvr3cpvv90mltjnbv81u1.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;inside the div tag type the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;header&amp;gt;
      &amp;lt;h1&amp;gt;WeatherApp&amp;lt;/h1&amp;gt;
      &amp;lt;input
        type="text"
        autocomplete="off"
        class="search-box"
        placeholder="Search for a city..."
        v-model="query"
        @keypress="fetchWeather"
      /&amp;gt;
    &amp;lt;/header&amp;gt;
    &amp;lt;main class="card" v-if="typeof weather.main != 'undefined'"&amp;gt;
      &amp;lt;div class="location"&amp;gt;{{weather.name}}, {{weather.sys.country}}&amp;lt;/div&amp;gt;
      &amp;lt;div class="temp"&amp;gt;{{ Math.round(weather.main.temp)}}°C&amp;lt;/div&amp;gt;
      &amp;lt;div class="weather"&amp;gt;{{weather.weather[0].main}}&amp;lt;/div&amp;gt;
    &amp;lt;/main&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;V-model&lt;/strong&gt; is a directive in vue.js that interacts with the DOM,we have bind the input to a variable data stored in query.&lt;br&gt;
&lt;strong&gt;@keypress&lt;/strong&gt;(which can also be expressed as v-on:keypress) is a directive that listens to DOM events and runs fetchWeather method when triggered.&lt;/p&gt;

&lt;p&gt;The following code goes inside the script tag&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default {
  name: "App",
  data() {
    return {
      api_key: "&amp;lt;your api key&amp;gt;",
      url_base: "https://api.openweathermap.org/data/2.5/",
      query: "",
      weather: {}
    };
  },
  methods: {
    fetchWeather(e) {
      if (e.key === "Enter") {
        fetch(
          `${this.url_base}weather?q=${this.query}&amp;amp;units=metric&amp;amp;APPID=${this.api_key}`
        )
          .then(res =&amp;gt; {
            return res.json();
          })
          .then(this.setResults);
      }
    },
    setResults(results) {
      this.weather = results;
    }
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Viewing the app in a local server open the terminal,run &lt;code&gt;npm run server&lt;/code&gt; then click at the localhost:8080 link.&lt;/p&gt;

&lt;h1&gt;
  
  
  Deployment
&lt;/h1&gt;

&lt;p&gt;There are various platforms from which we can deploy our app from.But we are going to focus on netlify for today.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fakgrf4xvp5fku9qonzo8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fakgrf4xvp5fku9qonzo8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
We will need to sign up for an account.i recommend signing up with github.&lt;/p&gt;

&lt;p&gt;Netlify allows you to drag and drop the files to be deployed but&lt;br&gt;
alternatively you can deploy directly from github.&lt;/p&gt;

&lt;p&gt;Using github makes it easy to update your site since changes are made as soon as they are pushed to your repository.To do so follow the steps below&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On the sites menu select new site from git.&lt;/li&gt;
&lt;li&gt;Connect to Git Provider&lt;/li&gt;
&lt;li&gt;Search for your repo/configure the netlify app on Github.&lt;/li&gt;
&lt;li&gt;Build and deploy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi3iay416xyxfjx2rzv9j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi3iay416xyxfjx2rzv9j.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Always ensure the build command is set to &lt;code&gt;npm run build&lt;/code&gt; and the publish directory set to &lt;code&gt;dist&lt;/code&gt;&lt;/p&gt;

</description>
      <category>hosting</category>
      <category>vue</category>
      <category>javascript</category>
      <category>netlify</category>
    </item>
    <item>
      <title>Stuck in choosing the right color for your website?</title>
      <dc:creator>tinega</dc:creator>
      <pubDate>Fri, 12 Jun 2020 06:42:03 +0000</pubDate>
      <link>https://forem.com/tinegagideon/stuck-in-choosing-the-right-color-for-your-website-8bd</link>
      <guid>https://forem.com/tinegagideon/stuck-in-choosing-the-right-color-for-your-website-8bd</guid>
      <description>&lt;p&gt;Choosing the right colors for your website can sometimes become exhausting,but with the help of certain tools the whole process can be simplified....&lt;br&gt;
Here are some of the tools i use:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://colorsinspo.com/" rel="noopener noreferrer"&gt;COLORSinspo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://colorsinspo.com/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GbfZ4Le_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/tinegadev/image/upload/v1591942347/dev.to/Screenshot_43_xtrahd.png" alt="colorsinspo home" width="800" height="405"&gt;&lt;/a&gt;&lt;br&gt;
A simple and easy interface,just click on an image and paste the code to your css.Includes hundreds of color palettes and gradient colors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.color-hex.com/" rel="noopener noreferrer"&gt;color-hex&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.color-hex.com/" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ruMaRM9C--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://res.cloudinary.com/tinegadev/image/upload/v1591942828/dev.to/Screenshot_44_pbeli1.png" alt="color-hex &amp;lt;br&amp;gt;
home" width="800" height="418"&gt;&lt;/a&gt;&lt;br&gt;
Color-hex gives information about colors including color models (RGB,HSL,HSV and CMYK), Triadic colors, monochromatic colors and analogous colors calculated in color page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://chrome.google.com/webstore/detail/colorpick-eyedropper/ohcpnigalekghcmgcdcenkpelffpdolg?hl=en/" rel="noopener noreferrer"&gt;ColorPick Eyedropper&lt;/a&gt;&lt;br&gt;
This is a chrome extension,color chooser that allows you to select colors from webpages.&lt;/p&gt;

&lt;h2&gt;In conclusion..&lt;/h2&gt;

&lt;p&gt;I hope you found this information useful.This is just a small list,feel free to share others in the comments below.&lt;/p&gt;

</description>
      <category>css</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>colors</category>
    </item>
  </channel>
</rss>
