Planet Python

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

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

Pages