Planet Python

Subscribe to Planet Python feed
Planet Python - http://planetpython.org/
Updated: 17 hours 16 min ago

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

PyCharm: PyCharm 2024.2.1: What’s New!

Thu, 2024-08-29 12:15

PyCharm 2024.2.1 is here! This release’s key features include initial support for Python 3.13, improvements to the Data View tool window, and enhanced code assistance for Django.

Don’t forget to visit our What’s New page to get all the new updates. Download the latest version from our website, or update your current version through our free Toolbox App.

Download PyCharm 2024.2.1 PyCharm 2024.2.1 key features Data View PRO

PyCharm now provides two color-scheme options for the table heatmaps in the Data View tool window: the Diverging and Sequential color schemes.

The Diverging color scheme emphasizes variation relative to a norm. It consists of two contrasting colors that deviate from a central value in two opposite directions.

The Sequential color scheme consists of a single color or a range of closely related colors that vary in intensity.

You can apply the heatmap color schemes to the whole table or to each column separately, or you can use coloring only for Boolean values.

Python 3.13

PyCharm now recognizes TypeIs syntax, providing proper type inference and code completion for user-defined narrowed functions. As part of Python 3.13 support, the IDE is now also aware of ReadOnly keys in TypedDict and warns you if something is assigned to a ReadOnly member.

Read more Django: Completion for ModelAdmin fields, and more PRO

Get intelligent code completion, refactoring, and navigation for the fields in ModelAdmin classes. Other productivity enhancements include a warning about newly created apps that have not been added to the INSTALLED_APPS declaration, and the ability to insert an app’s tag into the manage.py console automatically when migrations are made from the Django Structure tool window.

Read our release notes for the full breakdown and more details on all of the features in 2024.2.1. If you encounter any problems, please report them in our issue tracker so we can address them promptly. 

Connect with us on X (formerly Twitter) to share your thoughts on PyCharm 2024.2.1. We’re looking forward to hearing them!

Categories: FLOSS Project Planets

Python Software Foundation: Python Developers Survey 2023 Results

Thu, 2024-08-29 05:46

We are excited to share the results of the seventh official annual Python Developers Survey. This survey is done yearly as a collaborative effort between the Python Software Foundation and JetBrains. Responses were collected from November 2023 through February 2024. This year, we kept the response period open longer to facilitate as much global representation as possible. More than 25,000 Python developers and enthusiasts from almost 200 countries and regions participated in the survey to reveal the current state of the language and the ecosystem around it.

Check out the survey results!

The survey aims to map the Python landscape and covers the following topics:

  • General Python usage
  • Purpose for using Python
  • Python versions
  • Frameworks and Libraries
  • Cloud Platforms
  • Data science
  • Development tools
  • Python packaging
  • Demographics

We encourage you to check out the methodology and the raw data for this year's Python Developers Survey, as well as those from past years (2022, 2021, 2020, 2019, 2018, and 2017). We would love to hear about what you learn by digging into the numbers! Share your results and comments with us on social media by mentioning JetBrains (LinkedIn, X) and the PSF (Mastodon, LinkedIn, X) using the #pythondevsurvey hashtag. Based on the feedback we received last year, we made adjustments to the 2023 survey- so we welcome suggestions and feedback that could help us improve again for next year!

Categories: FLOSS Project Planets

PyPy: Guest Post: How PortaOne uses PyPy for high-performance processing, connecting over 1B of phone calls every month

Thu, 2024-08-29 05:00

The PyPy project is always happy to hear about industrial use and deployments of PyPy. For the GC bug finding task earlier this year, we collaborated with PortaOne and we're super happy that Serhii Titov, head of the QA department at PortaOne, was up to writing this guest post to describe their use and experience with the project.

What does PortaOne do?

We at PortaOne Inc. allow telecom operators to launch new services (or provide existing services more efficiently) using our VoIP platform (PortaSIP) and our real-time charging system (PortaBilling), which provides additional features for cloud PBX, such as call transfer, queues, interactive voice response (IVR) and more. At this moment our support team manages several thousand servers with our software installed in 100 countries, through which over 500 telecommunication service providers connect millions of end users every day. The unique thing about PortaOne is that we supply the source code of our product to our customers - something unheard of in the telecom world! Thus we attract "telco innovators", who use our APIs to build around the system and the source code to create unique tweaks of functionality, which produces amazing products.

At the core of PortaSIP is the middle-ware component (the proper name for it is "B2BUA", but that probably does not say much to anyone outside of experts in VoIP), which implements the actual handling of SIP calls, messages, etc. and all added features (for instance, trying to send a call via telco operators through which the cost per minute is lower). It has to be fast (since even a small delay in establishing a call is noticed by a customer), reliable (everyone hates when a call drops or cannot be completed) and yet easily expandable with new functionality. This is why we decided to use Python as opposed to C/C++ or similar programming languages, which are often used in telecom equipment.

The B2BUA component is a batch of similar Python processes that are looped inside a asyncore.dispatcher wrapper. The load balancing between these Python processes is done by our stateless SIP proxy server written in C++. All our sockets are served by this B2BUA. We have our custom client-wrappers around pymysql, redis, cassandra-driver and requests to communicate with external services. Some of the Python processes use cffi wrappers around C-code to improve their performance (examples: an Oracle DB driver, a client to a radius server, a custom C logger).

The I/O operations that block the main thread of the Python processes are processed in sub-threads. We have custom wrappers around threading.Thread and also asyncore.dispatcher. The results of such operations are returned to the main thread.

Improving our performance with PyPy

We started with CPython and then in 2014 switched to PyPy because it was faster. Here's an exact quote from our first testing notes: "PyPy gives significant performance boost, ~50%". Nowadays, after years of changes in all the software involved, PyPy still gives us +50% boost compared to CPython.

Taking care of real time traffic for so many people around the globe is something we're really proud of. I hope the PyPy team can be proud of it as well, as the PyPy product is a part of this solution.

Finding a garbage collector bug: stage 1, the GC hooks

However our path with PyPy wasn't perfectly smooth. There were very rare cases of crashes on PyPy that we weren't able to catch. That's because to make coredump useful we needed to switch to PyPy with debug, but we cannot let it run in that mode on a production system for an extended period of time, and we did not have any STR (steps-to-reproduce) to make PyPy crash again in our lab. That's why we kept (and still keep) both interpreters installed just in case, and we would switch to CPython if we noticed it happening.

At the time of updating PyPy from 3.5 to 3.6 our QA started noticing those crashes more often, but we still had no luck with STR or collecting proper coredumps with debug symbols. Then it became even worse after our development played with the Garbage Collector's options to increase performance of our middleware component. The crashes started to affect our regular performance testing (controlled by QA manager Yevhenii Bovda). At that point it was decided that we can no longer live like that and so we started an intense investigation.

During the first stage of our investigation (following the best practice of troubleshooting) we narrowed down the issue as much as we could. So, it was not our code, it was definitely somewhere in PyPy. Eventually our SIP software engineer Yevhenii Yatchenko found out that this bug is connected with the use of our custom hooks in the GC. Yevhenii created ticket #4899 and within 2-3 days we got a fix from a member of the PyPy team, in true open-source fashion.

Finding a garbage collector bug: stage 2, the real bug

Then came stage 2. In parallel with the previous ticket, Yevhenii created #4900 that we still see failing with coredumps quite often, and they are not connected to GC custom hooks. In a nutshell, it took us dozens of back and forward emails, three Zoom sessions and four versions of a patch to solve the issue. During the last iteration we got a new set of options to try and a new version of the patch. Surprisingly, that helped! What a relief! So, the next logical step was to remove all debug options and run PyPy only with the patch. Unfortunately, it started to fail again and we came to the obvious conclusion that what will help us is not a patch, but one of options we were testing out. At that point we found out that PYPY_GC_MAX_PINNED=0 is a necessary and sufficient condition to solve our issue. This points to another bug in the garbage collector, somehow related to object pinning.

Here's our current state: we have to add PYPY_GC_MAX_PINNED=0, but we do not face the crashes anymore.

Conclusion and next steps

Gratitude is extended to Carl for his invaluable assistance in resolving the nasty bugss, because it seems we're the only ones who suffered from the last one and we really did not want to fall back to CPython due to its performance disadvantage.

Serhii Titov, head of the QA department at PortaOne Inc.

P.S. If you are a perfectionist and at this point you have mixed feelings and you are still bothered by the question "But there might still be a bug in the GC, what about that?" - Carl has some ideas about it and he will sort it out (we will help with the testing/verification part).

Categories: FLOSS Project Planets

Matt Layman: No Frills, Just Go: Standard Library Only Web Apps

Wed, 2024-08-28 20:00
How much can you build in Go with zero extra packages? What is possible using nothing more than Go’s standard library? In this talk, you’re going to find out!
Categories: FLOSS Project Planets

Python Morsels: Arithmetic in Python

Wed, 2024-08-28 17:10

An explanation of Python's two number types (integers and floating point numbers), supported arithmetic operations, and an explanation of operator precedence.

Table of contents

  1. Integers
  2. Floating point numbers
  3. Mixing integers and floating point numbers
  4. Arithmetic operations
  5. Operator precedence in Python
  6. Arithmetic in Python is similar to in math

Integers

Integers are used for representing whole numbers.

>>> 5 5 >>> 0 0 >>> 999999999999 999999999999 >>> -10 -10

Any number that doesn't have a decimal point in it is an integer.

Floating point numbers

Floating point numbers are used …

Read the full article: https://www.pythonmorsels.com/arithmetic-in-python/
Categories: FLOSS Project Planets

Real Python: Web Scraping With Scrapy and MongoDB

Wed, 2024-08-28 10:00

Scrapy is a robust Python web scraping framework that can manage requests asynchronously, follow links, and parse site content. To store scraped data, you can use MongoDB, a scalable NoSQL database, that stores data in a JSON-like format. Combining Scrapy with MongoDB offers a powerful solution for web scraping projects, leveraging Scrapy’s efficiency and MongoDB’s flexible data storage.

In this tutorial, you’ll learn how to:

  • Set up and configure a Scrapy project
  • Build a functional web scraper with Scrapy
  • Extract data from websites using selectors
  • Store scraped data in a MongoDB database
  • Test and debug your Scrapy web scraper

If you’re new to web scraping and you’re looking for flexible and scalable tooling, then this is the right tutorial for you. You’ll also benefit from learning this tool kit if you’ve scraped sites before, but the complexity of your project has outgrown using Beautiful Soup and Requests.

To get the most out of this tutorial, you should have basic Python programming knowledge, understand object-oriented programming, comfortably work with third-party packages, and be familiar with HTML and CSS.

By the end, you’ll know how to get, parse, and store static data from the Internet, and you’ll be familiar with several useful tools that allow you to go much deeper.

Get Your Code: Click here to download the free code that shows you how to gather Web data with Scrapy and MongoDB.

Take the Quiz: Test your knowledge with our interactive “Web Scraping With Scrapy and MongoDB” quiz. You’ll receive a score upon completion to help you track your learning progress:

Interactive Quiz

Web Scraping With Scrapy and MongoDB

In this quiz, you'll test your understanding of web scraping with Scrapy and MongoDB. You'll revisit how to set up a Scrapy project, build a functional web scraper, extract data from websites, store scraped data in MongoDB, and test and debug your Scrapy web scraper.

Prepare the Scraper Scaffolding

You’ll start by setting up the necessary tools and creating a basic project structure that will serve as the backbone for your scraping tasks.

While working through the tutorial, you’ll build a complete web scraping project, approaching it as an ETL (Extract, Transform, Load) process:

  • Extract data from the website using a Scrapy spider as your web crawler.
  • Transform this data, for example by cleaning or validating it, using an item pipeline.
  • Load the transformed data into a storage system like MongoDB with an item pipeline.

Scrapy provides scaffolding for all of these processes, and you’ll tap into that scaffolding to learn web scraping following the robust structure that Scrapy provides and that numerous enterprise-scale web scraping projects rely on.

Note: In a Scrapy web scraping project, a spider is a Python class that defines how to crawl a specific website or a group of websites. It contains the logic for making requests, parsing responses, and extracting the desired data.

First, you’ll install Scrapy and create a new Scrapy project, then explore the auto-generated project structure to ensure that you’re well-equipped to proceed with building a performant web scraper.

Install the Scrapy Package

To get started with Scrapy, you first need to install it using pip. Create and activate a virtual environment to keep the installation separate from your global Python installation. Then, you can install Scrapy:

Shell (venv) $ python -m pip install scrapy Copied!

After the installation is complete, you can verify it by running the scrapy command and viewing the output:

Shell (venv) $ scrapy Scrapy 2.11.2 - no active project Usage: scrapy <command> [options] [args] Available commands: bench Run quick benchmark test fetch Fetch a URL using the Scrapy downloader genspider Generate new spider using pre-defined templates runspider Run a self-contained spider (without creating a project) settings Get settings values shell Interactive scraping console startproject Create new project version Print Scrapy version view Open URL in browser, as seen by Scrapy [ more ] More commands available when run from project directory Use "scrapy <command> -h" to see more info about a command Copied!

The command-line (CLI) program should display the help text of Scrapy. This confirms that you installed the package correctly. You’ll next run the highlighted startproject command to create a project.

Create a Scrapy Project

Scrapy is built around projects. Generally, you’ll create a new project for each web scraping project that you’re working on. In this tutorial, you’ll work on scraping a website called Books to Scrape, so you can call your project books.

As you may have already identified in the help text, the framework provides a command to create a new project:

Shell (venv) $ scrapy startproject books Copied! Read the full article at https://realpython.com/web-scraping-with-scrapy-and-mongodb/ »

[ 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

Pages