Planet Python

Subscribe to Planet Python feed
Planet Python - http://planetpython.org/
Updated: 1 hour 13 min ago

Talk Python to Me: #476: Unified Python packaging with uv

Wed, 2024-09-04 04:00
A couple of weeks ago, Charlie Marsh and the folks at Astral made another big splash with a major release of uv called "uv: Unified Python packaging" which has many far reaching features. We had to have Charlie on the show to give us the inside look into this development. Let's get to it.<br/> <br/> <strong>Episode sponsors</strong><br/> <br/> <a href='https://talkpython.fm/posit'>Posit</a><br> <a href='https://talkpython.fm/training'>Talk Python Courses</a><br/> <br/> <strong>Links from the show</strong><br/> <br/> <div><b>Charlie Marsh on Twitter</b>: <a href="https://twitter.com/charliermarsh?featured_on=talkpython" target="_blank" >@charliermarsh</a><br/> <b>Charlie Marsh on Mastodon</b>: <a href="https://hachyderm.io/@charliermarsh?featured_on=talkpython" target="_blank" >@charliermarsh</a><br/> <br/> <b>uv: Unified Python packaging</b>: <a href="https://astral.sh/blog/uv-unified-python-packaging?featured_on=talkpython" target="_blank" >astral.sh</a><br/> <b>Python executable management</b>: <a href="https://docs.astral.sh/uv/concepts/python-versions/?featured_on=talkpython" target="_blank" >astral.sh</a><br/> <b>Projects</b>: <a href="https://docs.astral.sh/uv/concepts/projects/?featured_on=talkpython" target="_blank" >astral.sh</a><br/> <b>Tools</b>: <a href="https://docs.astral.sh/uv/concepts/tools/?featured_on=talkpython" target="_blank" >astral.sh</a><br/> <b>Scripts</b>: <a href="https://docs.astral.sh/uv/guides/scripts/?featured_on=talkpython" target="_blank" >astral.sh</a><br/> <b>Rye and uv: August is Harvest Season for Python Packaging</b>: <a href="https://lucumr.pocoo.org/2024/8/21/harvest-season/?featured_on=talkpython" target="_blank" >lucumr.pocoo.org</a><br/> <b>Python Build Standalone releases</b>: <a href="https://github.com/indygreg/python-build-standalone/releases?featured_on=talkpython" target="_blank" >github.com</a><br/> <b>Rules</b>: <a href="https://docs.astral.sh/ruff/rules/?featured_on=talkpython" target="_blank" >astral.sh</a><br/> <b>Watch this episode on YouTube</b>: <a href="https://www.youtube.com/watch?v=oj8yk0Y-Ky0" target="_blank" >youtube.com</a><br/> <b>Episode transcripts</b>: <a href="https://talkpython.fm/episodes/transcript/476/unified-python-packaging-with-uv" target="_blank" >talkpython.fm</a><br/> <br/> <b>--- Stay in touch with us ---</b><br/> <b>Subscribe to us on YouTube</b>: <a href="https://talkpython.fm/youtube" target="_blank" >youtube.com</a><br/> <b>Follow Talk Python on Mastodon</b>: <a href="https://fosstodon.org/web/@talkpython" target="_blank" ><i class="fa-brands fa-mastodon"></i>talkpython</a><br/> <b>Follow Michael on Mastodon</b>: <a href="https://fosstodon.org/web/@mkennedy" target="_blank" ><i class="fa-brands fa-mastodon"></i>mkennedy</a><br/></div>
Categories: FLOSS Project Planets

PyCoder’s Weekly: Issue #645 (Sept. 3, 2024)

Tue, 2024-09-03 15:30

#645 – SEPTEMBER 3, 2024
View in Browser »

Using Astropy for Astronomy With Python

This course covers two problems from introductory astronomy to help you play with some Python libraries. You’ll use NumPy, Matplotlib, and pandas to find planet conjunctions, and graph the best viewing times for a star.
REAL PYTHON course

Python Language Summit 2024

Talk Python to Me interviews Seth Michael Larson and they talk about this year’s Python Language Summit. Learn all about what happened at the closed door session for core developers inside PyCon.
KENNEDY & LARSON podcast

Instant PEP 8 Compliance Checks & Fixes With Top AI Code Reviewer

With CodeRabbit, solve your indentation issues and security concerns. CodeRabbit doesn’t just point out issues; it suggests fixes and explains the reasoning behind the suggestion. Elevate code quality with AI-powered, context-aware reviews and 1-click fixes. Sign up for free today →
CODERABBIT sponsor

Layman’s Guide to Python Built-in Functions

This is a plain language guide to every built-in function in Python, paired with a simple example that shows each function in action.
MATT LAYMAN

DjangoCon Europe 2026 Call for Organizers

DJANGO SOFTWARE FOUNDATION

PyPy v7.3.17 Release

PYPY.ORG

Quiz: Python Strings and Character Data

REAL PYTHON

Quiz: Python String Formatting

REAL PYTHON

Articles & Tutorials Sorting Dictionaries in Python: Keys, Values, and More

In this video course, you’ll learn how to sort Python dictionaries. By the end, you’ll be able to sort by key, value, or even nested attributes. But you won’t stop there—you’ll also measure the performance of variations when sorting and compare different key-value data structures.
REAL PYTHON course

Understanding the Template Method Pattern in Python

The Template Method Pattern is when a base class is used to implement a series of steps, and subclasses can override one or more of those steps to customize the process. This article shows an example usage in Python and why you might want to implement it.
LANCE GOYKE

Accelerate Edge Devices With High-Performance AI Power

Experience the power of Edge AI—delivering lightning-fast, real-time processing where it matters. Optimize your applications with low latency, high efficiency, and unparalleled accuracy. Push performance beyond limits with Intel’s OpenVINO toolkit.
INTEL CORPORATION sponsor

Asyncio gather() Limit Concurrency

The asyncio.gather() function allows you to run multiple co-routines concurrently. There are times when you want to control just how much concurrency you have though and this post shows you how to use a semaphore to do just that.
JASON BROWNLEE

Adventures Building a Spreadsheet Engine in Python

Spreadsheets are a fascinating tool: you can both store and structure data, and include formulas that run computations on the contents of a sheet. James has written a spreadsheet engine, and this post talks about how it is done.
JAMES G

What’s New in pip 24.2

In version 24.2, pip learns to use system certificates by default, receives a handful of optimizations, and deprecates legacy (setup.py develop) editable installations. This article covers the changes and why they’ve been made.
RICHARD SI

CPython Compiler Hardening

Nate has been working on the CPython compiler, applying memory hardening guidelines recommended by OpenSSF’s Memory Safety Special Interest Group. This blog post talks about what was applied and how it should improve CPython.
NATE OHLSON

A Comparison of Providers for Python Serverless Functions

This is a comparison chart of the most common host providers that support Python serverless functions. It compares what features are supported, pricing, runtime limits, and more.
HAROLD MARTIN

There Can’t Be Only One

A weird historical first in baseball recently reminded James about how often as programmers we map our data assuming a one-to-one relationship, and how often that’s a bad choice.
JAMES BENNETT

Safety & Security Engineer: First Year in Review

It has been a year since Mike joined the PSF as the Safety & Security Engineer for PyPI. This blog post talks about all the things he’s been involved with.
MIKE FIELDER

Python Developers Survey 2023 Results

Official Python Developers Survey 2023 Results by Python Software Foundation and JetBrains: more than 25k responses from almost 200 countries.
JETBRAINS.COM

Lesser Known Parts of Python Standard Library

This article covers some of the lesser used parts of the Python standard library, including Deque, defaultdict, UserDict, and more.
TRICKSTER DEV

Projects & Code AlgoTree: A Package for Working With Tree Structures

PYPI.ORG • Shared by Alex Towell

anacondacode: Execute Python Directly From Excel

PYPI.ORG

pare: Deploy Python Lambdas Alongside Your Web App

GITHUB.COM/GAUGE-SH

django-admin-action-forms: Forms for Django Admin

GITHUB.COM/MICHALPOKUSA

PromptMage Simplifies Managing LLM Workflows

PROMPTMAGE.IO • Shared by Tobias Sterbak

Events EARL 2024

September 4 to September 6, 2024
DATACOVE.CO.UK

Weekly Real Python Office Hours Q&A (Virtual)

September 4, 2024
REALPYTHON.COM

PyCon Estonia 2024

September 5 to September 7, 2024
PYCON.EE

Canberra Python Meetup

September 5, 2024
MEETUP.COM

Sydney Python User Group (SyPy)

September 5, 2024
SYPY.ORG

PyDelhi User Group Meetup

September 7, 2024
MEETUP.COM

Happy Pythoning!
This was PyCoder’s Weekly Issue #645.
View in Browser »

[ Subscribe to 🐍 PyCoder’s Weekly 💌 – Get the best Python news, articles, and tutorials delivered to your inbox once a week >> Click here to learn more ]

Categories: FLOSS Project Planets

Mike Driscoll: ANN: JupyterLab 101 Kickstarter

Tue, 2024-09-03 10:08

My latest Python book is now available for pre-order on Kickstarter.

JupyterLab 101 mockup

JupyterLab, the latest iteration of the Jupyter Notebook, is a versatile tool for sharing code in an easily understandable format.

Hundreds of thousands of people around the world use Jupyter Notebooks or variations of the Notebook architecture for any or all of the following:

  • teaching
  • presentations
  • learning a computer language
  • numerical simulations
  • statistical modeling
  • data visualization
  • machine learning
  • and much more!

Jupyter Notebooks can be emailed, put on GitHub, or run online. You may also add HTML, images, Markdown, videos, LaTeX, and custom MIME types to your Notebooks. Finally, Jupyter Notebooks support big data integration.

JupyterLab 101 will get you up to speed on the newest user interface for Jupyter Notebooks and the other tools that JupyterLab supports. You now have a tabbed interface that you can use to edit multiple Notebooks, open terminals in your browser, create a Python REPL, and more. JupyterLab also includes a debugger utility to help you figure out your coding issues.

Rest assured, JupyterLab supports all the same programming languages as Jupyter Notebook. The main difference lies in the user interface, which this guide will help you navigate effectively and efficiently.

After reading JupyterLab 101, you will be an expert in JupyterLab and produce quality Notebooks quickly!

What You’ll Learn

In this book, you will learn how about the following:

  • Installation and setup of JupyterLab
  • The JupyterLab user interface
  • Creating a Notebook
  • Markdown in Notebooks
  • Menus in JupyterLab
  • Launching Other Applications (console, terminal, text files, etc)
  • Distributing and Exporting Notebooks
  • Debugging in JupyterLab
  • Testing your notebooks
Rewards to Choose From

As a backer of this Kickstarter, you have some choices to make. You can receive one or more of the following, depending on which level you choose when backing the project:

  • An early copy of JupyterLab 101 + all updates including the final version (ALL BACKERS)
  • A signed paperback copy (If you choose the appropriate perk)
  • Get all by Python courses hosted on Teach Me Python or another site  (If you choose the appropriate perk)
  • T-shirt with the book cover  (If you choose the appropriate perk)

Get the book on Kickstarter today!

The post ANN: JupyterLab 101 Kickstarter appeared first on Mouse Vs Python.

Categories: FLOSS Project Planets

Real Python: Using Pydantic to Simplify Python Data Validation

Tue, 2024-09-03 10:00

Pydantic is a powerful data validation and settings management library for Python, engineered to enhance the robustness and reliability of your codebase. From basic tasks, such as checking whether a variable is an integer, to more complex tasks, like ensuring highly-nested dictionary keys and values have the correct data types, Pydantic can handle just about any data validation scenario with minimal boilerplate code.

In this video course, you’ll learn how to:

  • Work with data schemas with Pydantic’s BaseModel
  • Write custom validators for complex use cases
  • Validate function arguments with Pydantic’s @validate_call
  • Manage settings and configure applications with pydantic-settings

[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

Categories: FLOSS Project Planets

Django Weblog: Django security releases issued: 5.1.1, 5.0.9, and 4.2.16

Tue, 2024-09-03 07:00

In accordance with our security release policy, the Django team is issuing releases for Django 5.1.1, Django 5.0.9, and Django 4.2.16. These releases address the security issues detailed below. We encourage all users of Django to upgrade as soon as possible.

CVE-2024-45230: Potential denial-of-service vulnerability in django.utils.html.urlize()

urlize and urlizetrunc were subject to a potential denial-of-service attack via very large inputs with a specific sequence of characters.

Thanks to MProgrammer for the report.

This issue has severity "moderate" according to the Django security policy.

CVE-2024-45231: Potential user email enumeration via response status on password reset

Due to unhandled email sending failures, the django.contrib.auth.forms.PasswordResetForm class allowed remote attackers to enumerate user emails by issuing password reset requests and observing the outcomes.

To mitigate this risk, exceptions occurring during password reset email sending are now handled and logged using the django.contrib.auth logger.

Thanks to Thibaut Spriet for the report.

This issue has severity "low" according to the Django security policy.

Affected supported versions
  • Django main branch
  • Django 5.1
  • Django 5.0
  • Django 4.2
Resolution

Patches to resolve the issue have been applied to Django's main, 5.1, 5.0, and 4.2 branches. The patches may be obtained from the following changesets.

CVE-2024-45230: Potential denial-of-service vulnerability in django.utils.html.urlize() CVE-2024-45231: Potential user email enumeration via response status on password reset The following releases have been issued

The PGP key ID used for this release is Natalia Bidart: 2EE82A8D9470983E

General notes regarding security reporting

As always, we ask that potential security issues be reported via private email to security@djangoproject.com, and not via Django's Trac instance, nor via the Django Forum, nor via the django-developers list. Please see our security policies for further information.

Categories: FLOSS Project Planets

Python Bytes: #399 C will watch you in silence

Tue, 2024-09-03 04:00
<strong>Topics covered in this episode:</strong><br> <ul> <li><strong><a href="https://hynek.me/articles/docker-virtualenv/?featured_on=pythonbytes">Why I Still Use Python Virtual Environments in Docker</a></strong></li> <li><a href="https://lp.jetbrains.com/python-developers-survey-2023/?featured_on=pythonbytes"><strong>Python Developer Survey Results</strong></a></li> <li><strong><a href="https://www.anaconda.com/blog/introducing-anaconda-code-add-in-for-microsoft-excel?featured_on=pythonbytes">Anaconda Code add-in for Microsoft Excel</a></strong></li> <li><a href="https://davidism.com/disabling-scheduled-dependency-updates/?featured_on=pythonbytes"><strong>Disabling Scheduled Dependency Updates</strong></a></li> <li><strong>Extras</strong></li> <li><strong>Joke</strong></li> </ul><a href='https://www.youtube.com/watch?v=dpAPT-T5m2g' style='font-weight: bold;'data-umami-event="Livestream-Past" data-umami-event-episode="399">Watch on YouTube</a><br> <p><strong>About the show</strong></p> <p>Sponsored by us! Support our work through</p> <ul> <li>Our <a href="https://training.talkpython.fm/?featured_on=pythonbytes"><strong>courses at Talk Python Training</strong></a></li> <li><a href="https://courses.pythontest.com/?featured_on=pythonbytes"><strong>Hello, pytest! Course</strong></a></li> <li><a href="https://www.patreon.com/pythonbytes"><strong>Patreon Supporters</strong></a></li> </ul> <p><strong>Connect with the hosts</strong></p> <ul> <li>Michael: <a href="https://fosstodon.org/@mkennedy"><strong>@mkennedy@fosstodon.org</strong></a></li> <li>Brian: <a href="https://fosstodon.org/@brianokken"><strong>@brianokken@fosstodon.org</strong></a></li> <li>Show: <a href="https://fosstodon.org/@pythonbytes"><strong>@pythonbytes@fosstodon.org</strong></a></li> </ul> <p>Join us on YouTube at <a href="https://pythonbytes.fm/stream/live"><strong>pythonbytes.fm/live</strong></a> to be part of the audience. Usually <strong>Monday</strong> at 10am PT. Older video versions available there too.</p> <p>Finally, if you want an artisanal, hand-crafted digest of every week of the show notes in email form? Add your name and email to <a href="https://pythonbytes.fm/friends-of-the-show">our friends of the show list</a>, we'll never share it.</p> <p><strong>Michael #1:</strong> <a href="https://hynek.me/articles/docker-virtualenv/?featured_on=pythonbytes">Why I Still Use Python Virtual Environments in Docker</a></p> <ul> <li>by Hynek Schlawack</li> <li>I was going to cover <a href="https://hynek.me/articles/docker-uv/?featured_on=pythonbytes">Production-ready Docker Containers with uv</a> but decided to take this diversion instead.</li> <li>Spend a lot of time thinking about the secondary effects of what you do.</li> <li>venvs are well known and well documented. Let’s use them.</li> </ul> <p><strong>Brian #2:</strong> <a href="https://lp.jetbrains.com/python-developers-survey-2023/?featured_on=pythonbytes"><strong>Python Developer Survey Results</strong></a></p> <ul> <li>“… official Python Developers Survey, conducted as a collaborative effort between the Python Software Foundation and JetBrains.”</li> <li>Python w/ Rust rising, but still only 7%</li> <li>““The drop in HTML/CSS/JS might show that data science is increasing its share of Python.” - Paul Everitt</li> <li>37% contribute to open source. Awesome.</li> <li>Favorite Resources: Podcasts <ul> <li>Lots of familiar faces there. Awesome. <ul> <li>Perhaps I shouldn’t have decided to move “Python Test” back to <a href="https://testandcode.com?featured_on=pythonbytes">Test &amp; Code</a></li> </ul></li> </ul></li> <li>Usage <ul> <li>“Data analysis” down, but I think that’s because “data engineering” is added.</li> <li>Data, Web dev, ML, devops, academic, </li> <li>Testing is down <img src="https://paper.dropboxstatic.com/static/img/ace/emoji/1f61e.png?version=8.0.0" alt="disappointed face" /> 23%</li> </ul></li> <li>Python Versions <ul> <li>Still some 2 out there</li> <li>Most folks on 3.10-3.12</li> </ul></li> <li>Install from: mostly python.org</li> <li>Frameworks <ul> <li>web: Flask, Django, Requests, FastAPI …</li> <li>testing: pytest, unittest, mock, doctest, tox, hypothesis, nose (2% might be the Python 2 people)</li> </ul></li> <li>Data science <ul> <li>77% use pandas, 72% NumPy</li> </ul></li> <li>OS: Windows still at 55% </li> <li>Packaging: <ul> <li>venv up to 55%</li> <li>I imaging uv will be on the list next year</li> <li>requirements.txt 63%, pyproject.toml 32%</li> </ul></li> <li>virtual env in containers? 47% say no</li> </ul> <p><strong>Michael #3:</strong> <a href="https://www.anaconda.com/blog/introducing-anaconda-code-add-in-for-microsoft-excel?featured_on=pythonbytes">Anaconda Code add-in for Microsoft Excel</a></p> <ul> <li>Run their Python-powered projects in Excel locally with the Anaconda Code add-in</li> <li>Powered by PyScript, an Anaconda supported open source project that runs Python locally without install and setup</li> <li>Features <ul> <li>Cells Run Independently</li> <li>Range to Multiple Types</li> <li>init.py file is static and cannot be edited, with Anaconda Code, users have the ability to access and edit imports and definitions, allowing you to write top-level functions and classes and reuse them wherever you need. </li> <li>A Customizable Environment </li> </ul></li> </ul> <p><strong>Brian #4:</strong> <a href="https://davidism.com/disabling-scheduled-dependency-updates/?featured_on=pythonbytes"><strong>Disabling Scheduled Dependency Updates</strong></a></p> <ul> <li>David Lord</li> <li>Interesting discussion of as they happen or batching of upsates to dependencies</li> <li>dependencies come in <ul> <li>requirements files</li> <li>GH Actions in CI workflows</li> <li>pre-commit hooks</li> </ul></li> <li>David was seeing 60 PRs per month when set up on monthly updates (3 ecosystems * 20 projects)</li> <li>new tool for updating GH actions: <a href="https://gha-update.readthedocs.io/en/latest/?featured_on=pythonbytes">gha-update</a>, allows for local updating of GH dependencies</li> <li>New process <ul> <li>Run pip-compile, gha-update, and pre-commit locally.</li> <li>Update a project’s dependencies when actively working on the project, not just whenever a dependency updates.</li> <li>Note that this works fine for dev dependencies, less so for security updates from run time dependencies. But for libraries, runtime dependencies are usually not pinned.</li> </ul></li> </ul> <p><strong>Extras</strong> </p> <p>Brian:</p> <ul> <li><a href="https://testandcode.com?featured_on=pythonbytes">Test &amp; Code</a> coming back this week</li> </ul> <p>Michael:</p> <ul> <li><a href="https://www.codeinacastle.com/python-zero-to-hero-2024?featured_on=pythonbytes">Code in a Castle event</a></li> <li><a href="https://github.com/basnijholt/unidep/pull/191#issuecomment-2322392833">Python Bytes badge spotting</a></li> <li><a href="https://news.ycombinator.com/item?id=41385546&featured_on=pythonbytes">Guido’s post removed for moderation</a></li> </ul> <p><strong>Joke:</strong> <a href="https://devhumor.com/media/c-will-watch-in-silence?featured_on=pythonbytes">C will watch in silence</a></p>
Categories: FLOSS Project Planets

Armin Ronacher: Progress

Mon, 2024-09-02 20:00

As I'm getting older a lot of my social circles are becoming ever more conservative. The focus shifts from building with ambition to fiercly protecting what one has achieved. Shifting the mind on protectionism makes one consider all that can cause damage. It puts the focus on the negative, it makes those negative thoughts feel much more significant than they are and one dwells on the past, instead of envisioning of what opportunity might lie ahead.

Yet, when we look back at history, it becomes clear that progress and fresh ideas tend to prevail over time. Not every new idea will succeed, but the overall trend is undeniable.

I believe that every day presents us with a choice: to step forward with courage and optimism or to cling to the status quo, even as it becomes increasingly untenable. Embracing new ideas carries inherent risks, but so does the refusal to explore them.

Right now we find ourselves slowly sliding down from our local maximum and some people try to pull you back up to where we were standing. On the other hand if you dare to run you will find a bigger and more impressive hill to scale. One that offers a better vantage point and when water rises undoubtedly the better place to be.

In today's political environment, the rhetoric is dominated by a yearning for the past. Some politicians will promote a return to fossil fuels and conservative social norms. They play into your fears of others and promote individualism at cost of the collective. The will uphold every bad news as a reason to fortify borders and strengthen nation-states.

But as time marches on, future generations will likely look back at these regressive inclinations and wonder how we could have been so short-sighted.

Categories: FLOSS Project Planets

Hynek Schlawack: How to Ditch Codecov for Python Projects

Mon, 2024-09-02 20:00

Codecov’s unreliability breaking CI on my open source projects has been a constant source of frustration for me for years. I have found a way to enforce coverage over a whole GitHub Actions build matrix that doesn’t rely on third-party services.

Categories: FLOSS Project Planets

Real Python: Generate Images With DALL·E and the OpenAI API

Mon, 2024-09-02 10:00

Describe any image, then let a computer create it for you. What sounded futuristic only a few years ago has become reality with advances in neural networks and latent diffusion models (LDM). DALL·E by OpenAI has made a splash through the amazing generative art and realistic images that people create with it.

OpenAI allows access to DALL·E through their API, which means that you can incorporate its functionality into your Python applications.

In this tutorial, you’ll:

  • Get started using the OpenAI Python library
  • Explore API calls related to image generation
  • Create images from text prompts
  • Create variations of your generated image
  • Convert Base64 JSON responses to PNG image files

You’ll need some experience with Python, JSON, and file operations to breeze through this tutorial. You can also study up on these topics while you go along, as you’ll find relevant links throughout the text.

Get Your Code: Click here to download the free sample code that you’ll use to generate stunning images with DALL·E and the OpenAI API.

Take the Quiz: Test your knowledge with our interactive “Generate Images With DALL·E and the OpenAI API” quiz. You’ll receive a score upon completion to help you track your learning progress:

Interactive Quiz

Generate Images With DALL·E and the OpenAI API

In this quiz, you'll test your understanding of generating images with DALL·E by OpenAI using Python. You'll revisit concepts such as using the OpenAI Python library, making API calls for image generation, creating images from text prompts, and converting Base64 strings to PNG image files.

Complete the Setup Requirements

If you’ve seen what DALL·E can do and you’re eager to make its functionality part of your Python applications, then you’re in the right spot! In this first section, you’ll quickly walk through what you need to do to get started using DALL·E’s image creation capabilities in your own code.

Install the OpenAI Python Library

Confirm that you’re running Python version 3.7.1 or higher, create and activate a virtual environment, and install the OpenAI Python library:

Windows PowerShell PS> python --version Python 3.12.5 PS> python -m venv venv PS> .\venv\Scripts\activate (venv) PS> python -m pip install openai Copied! Shell $ python --version Python 3.12.5 $ python -m venv venv $ source venv/bin/activate (venv) $ python -m pip install openai Copied!

The openai package gives you access to the full OpenAI API. In this tutorial, you’ll focus on image generation, which lets you interact with DALL·E models to create and edit images from text prompts.

Get Your OpenAI API Key

You need an API key to make successful API calls. Sign up with OpenAI and create a new project API key by clicking on the Dashboard menu and then API keys on the bottom left of the navigation menu:

On this page, you can create and manage your API keys, which allow you to access the service that OpenAI offers through their API. You can create and delete secret keys.

Click on Create new secret key to create a new API key, and copy the value shown in the pop-up window.

Note: OpenAI assigns your API usage through unique key values, so make sure to keep your API key private. The company calculates the pricing of requests to generate images on a per-image basis that depends on the model you use and the resolution of the output image.

Keep in mind that OpenAI’s API services and pricing policies may change. Be sure to check their website for up-to-date information about pricing and offers.

Always keep this key secret! Copy the value of this key so you can later use it in your project. You’ll only see the key value once.

Save Your API Key as an Environment Variable

A quick way to save your API key and make it available to your Python scripts is to save it as an environment variable. Select your operating system to learn how:

Windows PowerShell (venv) PS> $ENV:OPENAI_API_KEY = "<your-key-value-here>" Copied! Shell (venv) $ export OPENAI_API_KEY="<your-key-value-here>" Copied! Read the full article at https://realpython.com/generate-images-with-dalle-openai-api/ »

[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

Categories: FLOSS Project Planets

Real Python: Quiz: How to Use Conditional Expressions With NumPy where()

Mon, 2024-09-02 08:00

In this quiz, you’ll test your understanding of How to Use Conditional Expressions With NumPy where().

By working through the questions, you’ll consolidate the knowledge you gained from the tutorial and take yourself beyond what you learned.

To answer some of the questions, you’ll need to do some research outside of the tutorial itself. Embrace this challenge because exploration can take you on a valuable learning journey.

[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

Categories: FLOSS Project Planets

Real Python: Quiz: Generate Images With DALL·E and the OpenAI API

Mon, 2024-09-02 08:00

In this quiz, you’ll test your understanding of generating images with DALL·E by OpenAI API using Python.

By working through this quiz, you’ll revisit how to use the OpenAI Python library, make API calls related to image generation, create images from text prompts, create variations of an image, and convert Base64 strings to PNG image files.

[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short & sweet Python Trick delivered to your inbox every couple of days. >> Click here to learn more and see examples ]

Categories: FLOSS Project Planets

Zato Blog: Airport integrations in Python

Mon, 2024-09-02 04:00
Airport integrations in Python 2024-09-02, by Dariusz Suchojad

Did you know you can use Python as an integration platform for your airport systems? It's Open Source too.

From AODB, transportation, business operations and partner networks, to IoT, cloud and hybrid deployments, you can now use Python to build flexible, scalable and future-proof architectures that integrate your airport systems and support your master plan.

Read here about what is possible and learn more why Python and Open Source are the right choice.

More blog posts
Categories: FLOSS Project Planets

Quansight Labs Blog: Towards Inclusive Documentation: the PyData Sphinx Theme, Before and After Accessibility Fixes

Sun, 2024-09-01 20:00
A small showcase of accessibility improvements made to the PyData Sphinx Theme, Fall 2023-Spring 2024
Categories: FLOSS Project Planets

Tryton News: Newsletter August 2024

Sun, 2024-09-01 02:00

In the last month we focused on fixing bugs, improving the behaviour of things, speeding-up performance issues - building on the changes from our last release. We also added some new features which we would like to introduce to you in this newsletter.

For an in depth overview of the Tryton issues please take a look at our issue tracker or see the issues and merge requests filtered by label.

Changes for the User Sales, Purchases and Projects

Now Tryton warns the user when submitting another complaint for the same origin.

Accounting, Invoicing and Payments

Now Tryton allows to copy account moves from closed periods. When copy a move from a closed period we now set the period of the duplicate to the current period and the date to the actual date, while informing the user about the changes.

Stock, Production and Shipments

Our sendcloud integration now adds package weight and warehouse as shipping method criteria.

User Interface

Now we add a searcher for summary fields, which searches the whole description.

We’ve now merged the HTML edit and translate buttons into a single button that asks for the language before opening, with the current language pre-selected.

System Data and Configuration

Now you can configure the license key for TinyMCE.

Now Tryton supports the UTR (United Kingdom Unique Taxpayer Reference) identifier.

New Documentation We've created or updated the following documentations: New Releases

We released bug fixes for the currently maintained long term support series
7.0 and 6.0, and for the penultimate series 7.2.

Authors: @dave @pokoli @udono

1 post - 1 participant

Read full topic

Categories: FLOSS Project Planets

Carl Trachte: Scalable Vector Graphics Followup

Sat, 2024-08-31 09:47

 A quick follow up to the last post:

1) I spelled scalable wrong in the title; hopefully it's fixed.

2) The svg partial logo that rendered in Blogger did not render on the Planet Python feed.

3) The logo svg is too big for Blogger. I need to find a way to make a smaller (file size) one.

One more try with svg in Blogger. The png DAG Hamilton logo first:



And one more attempt:




Categories: FLOSS Project Planets

Carl Trachte: Scaleable Vector Graphics (svg) - Decomposing and Scaling Elements for Blogger

Sat, 2024-08-31 02:35

Last post I lamented the failure of any the svg graphs I had for DAG Hamilton workflows to render in Blogger. I set out to rectify this and have had some initial success.

My first attempt to get svg to show up in Blogger has the DAG Hamilton logo as its subject. My approach was to bring the svg elements down to the most basic primitives I could manage, then scale and translate their individual coordinates to bring them into the view.

Fortunately, I was able to find an example from someone who had successfully rendered svg in Blogger. The subject blog post is eleven years old. It appears svg never totally caught on for some platforms. Nonetheless, I used this as a template, and, after some initial success, managed to render the Hamilton logo.

The post will step through the individual path components of the Hamilton logo (7) and show the code used to transform the coordinates to make the svg elements render at an appropriate location and size. The individual path elements that make up the logo are a large number of 3 coordinate bezier curves. The manner in which the curves listed is very format specific to the platform that created them. Unfortunately, I cannot recall which online png to svg converter I used to create the svg. Portable Inkscape kept crashing on the large png file, so I brute forced the issue by using an online converter.

The first element of the logo is basically a purple background for the whole logo. A gap or divit can be seen just left of center on the upper part. I'll cover the manual "fixing" of this further on.



Second path (orange)



Third path (deep purple)





Fourth path (yellow top point)

                                        

Fifth path (light orangey left leg were the star to face out from the screen)

                                      

Sixth path (medium purple little triangle in the center)

                                      

Seventh path (light orangey little triangle to the right of center)

                                   


Fixing that niggling divit on the top half of the logo (the thin subvertical line).


                                     


Final product. This is the one svg inline drawing I was able to show (content size limitations of Blogger?)


The full logo refuses to render (although I swear it did before). Well, at least there is an svg element showing up on the page (a purple star). <sigh> Another png . . .

                                   


The code. I'm not strong on HTML, but it was necessary to edit this post inline. As part of that exercise, I included the post outline generation as part of the script.



# python 3.12


# blog_post_make_outline.py


"""

Attempt to scale, translate, and inline svg

elements for display in Blogger.

"""


import re


import pprint


import sys


import copy


import xml.etree.ElementTree as ET


# REGEX patterns.


PATHPAT = r'[<]path[ ]d[=]["]'


MPAT = r'M([-]*[0-9]+[.]*[0-9]*)[ ]([-]*[0-9]+[.]*[0-9]*)[ ]'


          # first bezier curve coord

BEZPAT = (r'C([-]*[0-9]+[.]*[0-9]*)[ ]([-]*[0-9]+[.]*[0-9]*)[ ]'

          # second bezier curve coord

          r'([-]*[0-9]+[.]*[0-9]*)[ ]([-]*[0-9]+[.]*[0-9]*)[ ]'

          # third bezier curve coord

          r'([-]*[0-9]+[.]*[0-9]*)[ ]([-]*[0-9]+[.]*[0-9]*)[ ]')


ZPAT = r'Z[ ]'


FILLPAT = (r'["] fill[=]["]([#][A-F0-9][A-F0-9][A-F0-9]'

           r'[A-F0-9][A-F0-9][A-F0-9])["][ ]')


#                 transform="translate(4756.96875,109.12890625)" 

#                 transform="translate(5619,4112)"/>

TRANSFORMPAT = (r'transform[=]["]translate[(]'

                r'([-]*[0-9]+[.]*[0-9]*)[,]([-]*[0-9]+[.]*[0-9]*)[)]["]')


# Output formats/constants.


BEZFMT = ('C{0:.7f} {1:.7f} '

          '{2:.7f} {3:.7f} '

          '{4:.7f} {5:.7f} ')


PATHFMT_OPEN = '<path d="'


PATHFMT_1 = 'M{mstartx:.5f} {mstarty:.5f} {path:s} Z '


PATHFMT_2 = '" fill="{fill:s}" transform="translate({translatex:.7f},{translatey:.7f})"'


PATHFMT_CLOSE = ' />'


SVG_TAG_OPEN = ('<svg xmlns="http://www.w3.org/2000/svg" '

                'xmlns:xlink="http://www.w3.org/1999/xlink" '

                "width='500px' height='500px'>")


SVG_TAG_CLOSE = '</svg>'


def parse_path(pathstring):

    """

    Capture path elements in a dictionary.


    pathstring is the svg string for the path (one line).


    For a path comprised entirely of bezier curves

    in the format (all one line):


    <ns0:path d="M0 0 C2.54601018 1.57157072 5.09846344 3.13131386 7.65625 4.68359375 C39.179 . . .  0 0 Z M-690.96875 4007.87109375 C-707.702 . . .  Z " fill="#C3368C" transform="translate(4756.96875,109.12890625)" />


    Returns dictionary.

    """

    retval = {}

    patpath = re.compile(PATHPAT)

    match = patpath.match(pathstring)

    startindex = match.span()[1]

    mpat = re.compile(MPAT)

    # MPAT

    match = mpat.match(pathstring[startindex:])

    mpatgroups = match.groups()

    retval['mpatgroups'] = []

    retval['mpatgroups'].append(mpatgroups)

    startindex += match.span()[1]

    bezpat = re.compile(BEZPAT)

    zpat = re.compile(ZPAT)

    retval['paths'] = []

    while match:

        pathpoints = []

        # BEZPAT

        match = bezpat.match(pathstring[startindex:])

        while match:

            # Sentinel.

            if not match:

                continue

            pathpoints.append(match.groups())

            startindex += match.span()[1]

            match = bezpat.match(pathstring[startindex:])

        retval['paths'].append(pathpoints)

        # ZPAT

        match = zpat.match(pathstring[startindex:])

        startindex += match.span()[1]

        # Then look for MPAT

        # MPAT

        match = mpat.match(pathstring[startindex:])

        # If MPAT not there, work on color and transform.

        if not match:

            continue

        startindex += match.span()[1]

        retval['mpatgroups'].append(mpatgroups)

    fillpat = re.compile(FILLPAT)

    match = fillpat.match(pathstring[startindex:])

    startindex += match.span()[1]

    print('adding fill . . .')

    fill = match.groups()[0]

    retval['fill'] = fill

    transformpat = re.compile(TRANSFORMPAT)

    match = transformpat.match(pathstring[startindex:])

    transform = match.groups()

    print('adding transform . . .')

    retval['transform'] = transform

    return retval


def parse_all_paths(svgfilepath):

    """

    Finds and parses all svg paths

    within an svg file (very format

    specific - bezier curves only).


    Returns list of dictionaries, one

    for each path line of the svg file.

    """

    # Do all paths in Hamilton logo.

    # Make list of dictionaries.

    patpath = re.compile(PATHPAT)

    with open(svgfilepath, 'r') as f:

        paths = []

        # Line one.

        next(f)

        # Line two.

        next(f)

        for linex in f:

            print(PATHPAT)

            print(linex[:30])

            match = patpath.match(linex)

            if not match:

                break

            paths.append(parse_path(linex))

    return paths


def work_paths(paths, fcn):

    """

    Apply an operation to all coordinates in

    the bezier curve paths represented in

    paths.


    Also covers translate and fill.


    paths is a list of dictionaries. Each

    dictionary represents one line of an

    svg file with a path made up of 

    bezier curves.

    """

    # Return value.

    newpaths = []

    # M - start of path segment.

    for pthx in paths:

        newmpatgroups = []

        for coordsx in pthx['mpatgroups']:

            newmpatgroups.append([fcn(x) for x in coordsx])

        newpaths.append({'mpatgroups':newmpatgroups})

    # to Z - end of path segment.

    # List of path dictionaries (paths).

    for pthx, newpath in zip(paths, newpaths):

        newpath['paths'] = []

        # Each M to Z path segment.

        for path in pthx['paths']:

            curvegroup = []

            for curve in path:

                newcurve = [fcn(x) for x in curve]

                curvegroup.append(newcurve)

            newpath['paths'].append(curvegroup)

    # transform and fill.

    for pthx, newpath in zip(paths, newpaths):

        newpath['transform'] = [fcn(x) for x in pthx['transform']]

        newpath['fill'] = pthx['fill']

    return newpaths


def translate_paths(paths, translation):

    """

    From a two tuple of x, y translation,

    adjust dictionary values for x, y 

    translation in each path in path

    list accordingly.


    Returns new dictionary

    """

    # TRANSLATE

    # ['mpatgroups', 'paths', 'fill', 'translate']

    translated_paths = copy.deepcopy(paths)

    for pathx in translated_paths:

        pathx['transform'][0] += translation[0]

        pathx['transform'][1] += translation[1]

    return translated_paths


def get_path_strings(paths):

    """

    From a list of path dictionaries, 

    builds one line strings for insertion

    into svg file.


    Returns list

    """

    pathdict_2 = {'fill':None,

                'translatex':None,

                'translatey':None}

    path_segment_dict = {'mstartx':None,

                         'mstarty':None,

                         'path':None}

    pathstrings = []

    for pathx in paths:

        # Copy and initialize fill/translate dictionary.

        fill_translate = copy.deepcopy(pathdict_2)

        fill_translate['fill'] = pathx['fill']

        fill_translate['translatex'] = pathx['transform'][0]

        fill_translate['translatey'] = pathx['transform'][1]

        # Zip together M and path segments.

        path_segs = zip(pathx['mpatgroups'], pathx['paths'])

        # For each path segment.

        path_strings = []

        for M, path_seg in path_segs:

            seg_dict = copy.deepcopy(path_segment_dict)

            seg_dict['mstartx'] = M[0]

            seg_dict['mstarty'] = M[1]

            # Build path segment string.

            path_seg_strings = [BEZFMT.format(*coords) for coords in path_seg]

            path = ''.join(path_seg_strings)

            seg_dict['path'] = path

            # Make final segment string with M (PATHFMT_1)

            path_with_M = PATHFMT_1.format(**seg_dict)

            path_strings.append(path_with_M)

        path_all_together = ''.join(path_strings)

        # Tack on fill/translate at end and beginning with d path flag.

        # Add to pathstrings.

        pathstrings.append(PATHFMT_OPEN  +

                           path_all_together +

                           PATHFMT_2.format(**fill_translate) +

                           PATHFMT_CLOSE)

    return pathstrings  


paths = parse_all_paths('hamilton_logo_large.svg')

print('len(paths) = {0:d}'.format(len(paths)))

pprint.pprint([x for x in paths[0]])


paths = work_paths(paths, float)


scale = 0.035

scaleit = lambda x: scale * x


paths = work_paths(paths, scaleit)


# pprint.pprint(paths[0]['paths'][0])


paths = translate_paths(paths, (125, 0))


pathstrings = get_path_strings(paths)


# with open('test_paths.txt', 'w') as f:

#     for pathx in pathstrings:

#         print(pathx, file=f)

#         print('\n\n', file=f)


GAP_FIX = "<polygon points='265 90.25, 245 143.75, 268 144.1, 295 90.25' style='fill: black;' />"

GAP_FIX_PROPER_COLOR = "<polygon points='265 90.25, 245 143.75, 268 144.1, 295 90.25' style='fill: #C3368C;' />"


TEXT = '<p>{0:s}</p>'


CODE = """

<p>&nbsp;</p><pre style="background: rgb(238, 238, 238); border-bottom-color: initial; border-bottom-style: initial; border-image: initial; border-left-color: initial; border-left-style: initial; border-radius: 10px; border-right-color: initial; border-right-style: initial; border-top-color: rgb(221, 221, 221); border-top-style: solid; border-width: 5px 0px 0px; color: #444444; font-family: &quot;Courier New&quot;, Courier, monospace; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: inherit; margin-bottom: 1.5em; margin-top: 0px; overflow-wrap: normal; overflow: auto; padding: 12px; vertical-align: baseline;"><span style="font-size: 13px;">{0:s}</span></pre>

"""


textlist = ['blah blah blah',

            'blah blah blah again',

            'blah blah blah a third time',

            'blah blah blah a fourth time',

            'blah blah blah a fifth time',

            'blah blah blah a sixth time',

            'blah blah blah a seventh time',

            'fix divit',

            'final product']


fixed_divit = copy.deepcopy(pathstrings)

fixed_divit.insert(1, GAP_FIX_PROPER_COLOR)


svglist = [pathstrings[0:1],

           pathstrings[0:2],

           pathstrings[0:3],

           pathstrings[0:4],

           pathstrings[0:5],

           pathstrings[0:6],

           pathstrings[0:],

           pathstrings[0:] + [GAP_FIX],

           fixed_divit]


with open('blogpost.html', 'w') as f:

    for blah, svgels in zip(textlist, svglist):

        print(TEXT.format(blah), file=f)

        print(SVG_TAG_OPEN, file=f)

        for svgelement in svgels:

            print(svgelement, file=f)

        print(SVG_TAG_CLOSE, file=f) 


    print(TEXT.format('More blah about code'), file=f)


    print(CODE.format('>>> import this'), file=f)


print('Done')

Notes:

1) I had had good intentions of including a code box (the CODE string constant in the Python code) and I hit a bit of a wall. Not only is my code a mixed bag (this blog was always intended as a learning experience and a place for trying things out), it doesn't look good. We deal.

Which brings me to the point: you hear titles like front end developer, designer, website marketer etc. and think, "Well, it's kind of like art, kind of like coding . . . sort of creative." I now know, it's coding and it's thinking and it's grinding. All respect.

2) Steven Lott recently published a book that I bought (pdf). I have found it helpful. It's very pragmatic. I'm only about 15% of the way into it, but his treatment of regular expressions as just another tool not be scared of made me less tentative in my REGEX use (even if my REGEXes are far from elegant). Group capture with parens was really helpful for this exercise.

3) Our chief geology database administrator commented that the colors of the DAG Hamilton logo are those of the Spanish shawl nudibranch. There is a resemblance.

Photo courtesy of iNaturalist.



Thanks for stopping by.

Categories: FLOSS Project Planets

Python Morsels: Functions and Methods in Python

Fri, 2024-08-30 18:23

Methods are functions that live on objects.

Table of contents

  1. Operators
  2. Some functions included with Python
  3. Calling functions
  4. Function arguments
  5. Functions either return a value or perform an action
  6. Methods are a special type of functions
  7. Functions are everywhere in Python

Operators

Python includes operators, like the plus operator (+) and the minus operator (-):

>>> n = 9 >>> language = "Python" >>> language + " is fun" 'Python is fun' >>> n - 4 5 Some functions included with Python

But Python also includes many …

Read the full article: https://www.pythonmorsels.com/functions-and-methods/
Categories: FLOSS Project Planets

CodersLegacy: Understanding the Switch Case Statement in Python 3.10

Fri, 2024-08-30 16:50

Python is known for its simplicity and readability, but one feature it has historically lacked is a native switch case statement, commonly found in other programming languages like C, C++, and Java. Instead, Python developers often relied on a series of if-elif-else statements or dictionaries to emulate switch-case behavior.

However, with the release of Python 3.10, a new feature known as “Structural Pattern Matching” was introduced, which effectively brings a form of switch-case functionality to Python.

In this tutorial, we’ll explore how to use the switch case statement, Python’s new approach to handling multiple conditions in a more readable and efficient way.


Introduction to the match Statement

The match statement in Python 3.10 allows for pattern matching, which is more powerful and flexible than the traditional switch-case statements found in other languages. Pattern matching checks a given value against a series of patterns and executes the corresponding block of code when a match is found.

Here’s a basic structure of how a match statement works:

Pythondef example(value): match value: case pattern1: # Code block for pattern1 case pattern2: # Code block for pattern2 case _: # Default case (similar to 'default' in switch-case) Key Components:
  • match statement: The equivalent of the switch keyword in other languages.
  • case clauses: These represent the individual cases you want to check against, similar to case in switch-case.
  • Wildcard (_): Acts as the default case, covering any values that don’t match the specified patterns.


Example: Basic Pattern Matching

Let’s start with a simple example of using match to simulate a switch-case statement that handles different types of user inputs.

Pythondef process_command(command): match command: case "start": return "Starting the system..." case "stop": return "Stopping the system..." case "restart": return "Restarting the system..." case _: return "Unknown command." # Testing the function print(process_command("start")) # Output: Starting the system... print(process_command("pause")) # Output: Unknown command.

In this example:

  • The match statement checks the value of command.
  • Depending on the matched value, the corresponding message is returned.
  • The wildcard (_) case handles any input that doesn’t match the predefined commands, acting as a fallback or default case.


Advanced Pattern Matching

The match statement in Python 3.10 is not limited to simple value matching. It supports more complex patterns, including:

1. Matching Data Structures

You can use pattern matching with lists, tuples, and dictionaries.

Pythondef analyze_shape(shape): match shape: case ("circle", radius): return f"Circle with radius {radius}" case ("rectangle", width, height): return f"Rectangle with width {width} and height {height}" case ("square", side): return f"Square with side {side}" case _: return "Unknown shape" # Testing the function print(analyze_shape(("circle", 5))) # Output: Circle with radius 5 print(analyze_shape(("rectangle", 4, 6))) # Output: Rectangle with width 4 and height 6


2. Matching with Conditions (Guards)

You can add conditions to cases using if statements, known as “guards”.

Python 0: return "Negative number" case n if n == 0: return "Zero" case n if n > 0: return "Positive number" # Testing the function print(categorize_number(-5)) # Output: Negative number print(categorize_number(0)) # Output: Zero print(categorize_number(10)) # Output: Positive number" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button">def categorize_number(number): match number: case n if n < 0: return "Negative number" case n if n == 0: return "Zero" case n if n > 0: return "Positive number" # Testing the function print(categorize_number(-5)) # Output: Negative number print(categorize_number(0)) # Output: Zero print(categorize_number(10)) # Output: Positive number


3. Combining Patterns

You can also combine multiple patterns in a single case using the | (or) operator.

Pythondef get_day_type(day): match day: case "Saturday" | "Sunday": return "Weekend" case "Monday" | "Tuesday" | "Wednesday" | "Thursday" | "Friday": return "Weekday" case _: return "Invalid day" # Testing the function print(get_day_type("Sunday")) # Output: Weekend print(get_day_type("Monday")) # Output: Weekday print(get_day_type("Funday")) # Output: Invalid day


When to Use match Over if-elif-else

While you can still use if-elif-else statements, match provides a cleaner and more readable alternative when dealing with multiple conditions. It’s especially useful when:

  • You have a large number of conditions to check.
  • You want to match complex data structures.
  • You need to execute different code blocks based on the structure of data, not just its value.


By mastering this new feature, you can write cleaner, more maintainable code that can easily adapt to complex logic scenarios.

As you start integrating match into your code, you’ll likely find many situations where it simplifies your conditional logic, making your Python code not only more efficient but also more Pythonic.

The post Understanding the Switch Case Statement in Python 3.10 appeared first on CodersLegacy.

Categories: FLOSS Project Planets

Zero to Mastery: Python Monthly Newsletter 💻🐍

Fri, 2024-08-30 03:43
57th issue of Andrei Neagoie's must-read monthly Python Newsletter
Categories: FLOSS Project Planets

Matt Layman: Kamal - Building SaaS #200

Thu, 2024-08-29 20:00
In this episode, we pulled out a new tool. We spent the session using Kamal, a tool to deploy web apps directly to servers. Kamal offers a complete tool set to get apps running on bare metal or cloud machines. We played with the tool to see how far we go to get an app deployed to a new server.
Categories: FLOSS Project Planets

Pages