Feeds
Consensus Enterprises: Aegir5 + Pitch-burgh
Russell Coker: Links May 2023
Petter Reinholdtsen wrote an interesting blog post about their work on packaging speech to text for Debian [1]. The work of the Debian Deep Learning Team seems really interesting and I look forward to playing with this sort of thing after the release of Bookworm (the packages in question will NOT go in Bookworm but I’ll run at least one system on Testing after Bookworm). It would be nice to get more information on the hardware used for running such programs, the minimum hardware needed for real-time speech to text would be interesting to know.
Brian Krebs wrote an informative article about attacks involving supply chain compromise and fake LinkedIn profiles [2]. The attacks targetted Linux as well as Windows.
Interesting video about the Illium cameras, a bit harsh though, they criticise Illium devices for being too low resolution, too expensive, and taking too much CPU time to process [3]. The Illium cameras still sell for decent prices on eBay, I wonder if it’s because of curious people like me who would like to play with them and have money to spare or whether some other interesting things are being done. I wonder how a 4*4 array of the rectangular cameras secured together with duct tape would go. The ideas of Illium should work better if implemented for multi-core CPUs or GPUs.
Wired has an interesting article about the way DJI drones transmit the location of the drone operator without encryption – by design [5]. Apparently this has been used for targetting attacks on drone operators in Ukraine.
This video about robot “mice” navigating mazes is interesting [6]. But I think it became less interesting when they got to the stage of milliseconds counting for the win, it’s very optimised for one case just like F1. I think it would be interesting if they had a rally contest where they go across grass or sand, 3D mazes both in air and water, and contests where Tungsten weights have to be transported. They should push some of the other limits of engineering as completing a maze quickly has been solved.
The Guardian has an interesting article about a blood test for sleepy driving [7]. Once they have an objective test they can punish people for it.
This github repository listing public APIs is interesting [8]. Lots of fun ideas for phone apps there.
Simon Josefsson wrote an insightful blog post about the threat model of security devices [9]. Unfortunately the security of most people is way below the level where this is an issue. But it’s good to think about future steps needed for good security.
Cory Doctorow wrote an interesting article “The Swivel Eyed Loons have a Point” [10] about the fact that some of the nuttiest people are protesting about real issues, just in the wrong way.
- [1] https://tinyurl.com/2gz5ftr4
- [2] https://tinyurl.com/2ykf6lvk
- [3] https://www.youtube.com/watch?v=Zo4u578ZqrU
- [4] https://tinyurl.com/27mq65e2
- [5] https://www.wired.com/story/dji-droneid-operator-location-hacker-tool/
- [6] https://www.youtube.com/watch?v=ZMQbHMgK2rw
- [7] https://tinyurl.com/2zfgkpb9
- [8] https://github.com/public-apis/public-apis
- [9] https://tinyurl.com/2lqo632w
- [10] https://tinyurl.com/2nvh3tdu
Related posts:
- Links April 2023 Cory Doctorow has an insightful article Gig Work is the...
- Links January 2023 The Intercept has an amusing and interesting article about senior...
- Links March 2023 Interesting paper about a plan for eugenics in dogs with...
Russell Coker: Genesis GV60
I recently test drove a Genesis GV70, but the GV60 [1] which I didn’t test drive is a nicer car.
The GV70 and GV60 are all electric so they are quiet and perform well. The GV70 has a sun-roof that opens, it was the first car I’ve driven like that and I decided I don’t like it. Having the shade open so I can see the sky while stuck in a traffic jam is nice though. The GV60 has a non-opening sun-roof with a shade that can be retracted, this is a feature I’d really like to have in my next car.
Electric cars as a general rule have good acceleration and are quiet, the GV70 performed as expected in that regard. It has a head-up display projected on the windscreen for the speed and the speed limit on the road in question which is handy. When driving in a car park it showed images from all sides which is really handy, I wish I had explored that feature more.
The console is all electronic with a TFT display instead of mechanical instruments but the only significant difference this makes in driving is that when a turn indicator is used the console display shows a video feed for the blind-spot that matches the lane change direction. This is a significant safety feature and will reduce the incidence of collisions. But the capabilities of the hardware seem under utilised, hopefully they will release a software update at some future time to do more with it.
The most significant benefit of the GV60 over the GV70 is that it has cameras instead of mirrors at the sides of the car. This reduces drag and also removes the need to adjust mirrors to match the height of the driver. Also for driver instruction the instructor and learner get to see the same view. A logical development of such cars is an expansion pack for instruction that has displays in the passenger seat to show the instructor the same instrument view as the driver sees.
The minimum list driveaway price for the GV60 is $117,171.50 and for the GV70 it is $138,119.89 – both of which are more than I’m prepared to pay for a car. The GV60 apparently can be started by fingerprint which seems like a bad idea given the poor security of fingerprint sensors, but as regular car keys tend not to be too difficult to work around it probably doesn’t matter. The Genesis web site makes it difficult to find the ranges of electric cars which is surprising. A Google search suggests that the GV60 can do 466Km and the GV70 can do 410Km which are both reasonable numbers and nothing to be ashamed of.
The GV70 was a fun car to drive and the GV60 looks like it would be even better. I recommend that everyone who likes technology take one for a test drive, but for my own use I’m looking for something that costs less than half as much.
Related posts:
- hybrid Lexus is best luxury car The Lexus GS 450 hybrid petrol/electric car has been given...
- Mercedes S class and car safety The S Class Mercedes has some really interesting safety features,...
- Video Mode and KVM I recently changed my KVM servers to use the kernel...
Golems GABB: Best Practices for Cross-Platform Development in 2023
Cross-platform mobile application development continues to gain popularity. This is due to the sharp rise in the creation of native software products that do not always bring the expected results. For instance, a cross-platform application can run on multiple operating systems, including Windows, Linux, and Mac OS X. Below, we will discuss cross-platform development and the tools to create multi-platform applications.
It is worth considering that creating a high-quality cross-platform application without high-level programming languages is impossible. Choosing the right development environment that supports conditional compilation is also crucial. The principle of multi-platform development is based on using a single code base, ensuring compatibility with different platforms. Stability is achieved by timely and correct translation of the application code under a certain operating procedure.
PyBites: What’s enough as a developer and in life?
Welcome back to the Pybites podcast!
Watch here:
Listen here:
Welcome back to the Pybites podcast! Today we hone in on the concept of “Enough”, which we read about in the book “Psychology of Money” – chapter 3, titled “Never Enough”.
We discuss what this means and relate it back to the Python developer journey and life in general, giving tips how to find the balance (which can be challenging).
As usual we also share Pybites wins + books we are reading.
Enjoy and reach out if you have feedback or want to hear us talk about any topic specifically.
Chapters:
00:00 Intro
01:16 The compound effect / podcast backstory
02:24 Wins
06:47 What’s enough? (Psychology of Money book)
09:12 Is it a moving target?
10:55 Quotes from the book
12:53 Don’t compare yourself to others
13:50 Focus on internals / “enough” in fitness
14:50 Linking it to the developer journey / wins file
15:30 Give yourself space to make decisions
15:50 How does this rhyme with our “what’s next?”
17:40 Extra Fabulous Comics (linked)
18:19 Books
22:50 Share your reading on our Slack or Pybites Books
23:16 Teasers upcoming episodes
23:50 Thank you!
24:09 Outro
Extra Fabulous Comics regarding “enough” in fitness / bodybuilding (this sums it up pretty well lol)
Thank for listening!
Surprise New Video by Ramon: Gradient Brushes
Because you asked for it, here a surprise video by Ramon Miranda introducing gradient brushes:
The post Surprise New Video by Ramon: Gradient Brushes appeared first on Krita.
The Drop Times: Drupal Presented the Ideal Platform for Me to Work with; Renato Gonçalves | DC Pittsburgh 23
The Python Coding Blog: From Classes to Turtles via Functools and more | May in Review
I kept myself quite busy May. Not only did I finish running the first The Python Coding Programme cohort and starting running the second. I published seven new articles on The Python Coding Stack. Here’s a roundup:
- The second and third Years at Hogwarts School of Codecraft and Algorithmancy are now out. Year 2 deals with defining classes and data attributes and was published on the 2nd of May: Let The Real Magic Begin • Creating Classes in Python. Year 3 focuses on creating methods within those classes and was published on the 17th of May: There’s A Method To The Madness • Defining Methods In Python Classes
- The other ongoing series on The Stack at the moment is about data structure categories. The third instalment in the series was published on the 11th of May and dealt with mappings: Finding Your Way To The Right Value • Python’s Mappings (Data Structure Categories #3)
- Mappings also featured in another article on the 24th of May. This visualised mappings in the context of a real world scenario: The One About The Taxi Driver, Mappings, and Sequences • A Short Trip to 42 Python Street
- On the 7th of May I published a deep dive into the partial() and partialmethod() functions you’ll find in the functools module: Python’s functools.partial() Lets You Pre-Fill A Function
- Most articles on The Python Coding Stack are available for free. However, I occasionally publish articles exclusively for the paid subscribers on the stack. I talked about Deconstructing Ideas And Constructing Code • Using the Store-Repeat-Decide-Reuse Concept on the 20th of May
- And finally, on the 28th of May, I published a step-by-step tutorial using turtle. Those who follow my writing long enough know that I love the turtle module and will return to it from time to time: Zen and The Art of Python `turtle` Animations • A Step-by-Step Guide
Here’s what the animation looks like:
Coming in June: further instalments in both the object-oriented programming series and the data structure categories, and more…
I’m also working on the video courses and I hope to publish the first set of courses very soon.
Subscribe to The Python Coding StackRegular articles for the intermediate Python programmer or a beginner who wants to “read ahead”
SubscribeThe post From Classes to Turtles via Functools and more | May in Review appeared first on The Python Coding Book.
Python GUIs: Your First Steps With the Kivy Library for GUI Development
Kivy is an open-source Python software library for developing graphical user interfaces. It supports cross-platform development for the desktop as well as the creation of multi-touch apps for mobile devices.
Kivy apps can run across several platforms, including Windows, Linux, macOS, Android, and IOS. One place where Kivy particularly shines is in game development. By combining Kivy's 2D physics capabilities with a simple physics engine, you can create impressive 2D simulations and games.
In this article, you'll learn about using Kivy to develop Python apps. We will go through an introduction to Kivy and what it can do. You'll learn how to create a simple Kivy app in Python and learn the basics of Kivy's styling language, known as Kv. Finally, you'll use Kivy's graphics module to draw 2D shapes on the Kivy canvas.
To get the most out of this tutorial, you should have basic knowledge of Python. Previous knowledge of general concepts of GUI programming, such as event loops, widgets, layouts, and forms, is also a plus.
Table of Contents- Installing Kivy
- Writing Your First Kivy GUI App in Python
- Exploring Widgets and Layouts
- Using Widgets and Layouts: A Practical Example
- Drawing Shapes in Kivy: The canvas Property
- Styling Your GUIs With the Kivy Language
- More Resources
- Conclusion
There are many different Python GUI libraries available, and choosing one for your project can be a really tough and confusing decision to make. For advice see our guide to Python GUI libraries.
Let's get started. We'll first take a few moments to install and set up Kivy on your computer.
Installing KivyBefore using a third-party library like Kivy, we must install it in our working environment. Installing Kivy is as quick as running the python -m pip install kivy command on your terminal or command line. This command will install the library from the Python package index (PyPI).
Note that as of the time of writing this tutorial, Kivy only officially supports Python versions up to 3.10. For detailed information about installing Kivy, visit the official installation guide.
However, when working with third-party libraries, it's good practice to create a Python virtual environment, which is a self-contained Python installation for a particular version of Python that you can use to isolate the dependencies of a given project.
To create a virtual environment, you'll typically use Python's venv module from the standard library. Fire up a command-line window and type in the following command in your working directory.
sh $ python -m venv kivy_envThis command will create a folder called kivy_env containing a Python virtual environment. The Python version in this environment is the same as you get when you run python --version on your command line.
Next, we need to activate the virtual environment. Use the appropriate command, depending on whether you're on Windows, macOS, or Linux:
- Windows
- macOS
- Linux
Once that's confirmed to be working, you can then install Kivy within the virtual environment you just created by running the following:
sh (kivy_env) $ python -m pip install kivyWith this command, you'll install Kivy in your active Python virtual environment, so you're now ready to go.
You can also install Kivy by downloading its source code directly from GitHub and doing a manual installation on the command line. For more information on following this installation path, check out the section about installing Kivy from source in the documentation.
Writing Your First Kivy GUI App in PythonWithout further ado, let's get right into creating our first app with Kivy and Python. For this app, we will use a Label object to display the traditional "Hello, World!" message on our screen. To write a minimal Kivy GUI app, we need to run a few steps:
- Subclassing the App class
- Implementing its build() method, which returns a Widget instance
- Instantiating this class and calling its run() method
Let's start by importing the required classes. For our example, we only need the App and Label classes. Create a Python file called app.py and add the following imports:
python from kivy.app import App from kivy.uix.label import LabelThe App class provides the base functionality required to create GUI apps with Kivy, such as managing the event loop. Meanwhile, the Label class will work as the root visual element or widget for our GUI.
Next, we can create our subclass of App. We have called it MainApp here. However, you can call it whatever you like:
python from kivy.app import App from kivy.uix.label import Label class MainApp(App): def build(self): return Label(text="Hello, World!")This subclass uses the concept of inheritance in object-oriented programming (OOP) in Python. All the attributes and methods defined in the superclass, App, are automatically inherited by the subclass, MainApp.
In order for our app to create a UI, we need to define a build() method. In build(), we create and return either a widget or layout, which will be the root object in our UI structure.
The build() method is the entry point to whatever will be drawn on the screen. In our example, it creates and returns a label with the "Hello, World!" text on it.
Finally, we need to create an instance of MainApp and call its run() method:
python from kivy.app import App from kivy.uix.label import Label class MainApp(App): def build(self): return Label(text="Hello, World!") MainApp().run()In the final line, we create an instance of MainApp and call its run() method. This method launches the application and runs its main loop. That's it! We're ready to run our first Kivy app. Open your command line and run the following command:
sh $ python app.pyYou'll see the following window on your screen:
First Kivy GUI Application
Great! You've just written your first Kivy GUI app using Python. It shows a black window with the message "Hello, World!" In its center. Note that the window's title bar shows the title Main, which comes from the name of your App subclass.
The next step is to explore some other essential features of Kivy that will allow you to write fully-functional GUI apps with this library.
Exploring Widgets and LayoutsIn the previous section, we mentioned widgets and layouts a few times -- you may be wondering what they are! A widget is an element of a GUI that displays information or provides a specific function. They allow your users to interact with your app's GUI.
A layout, on the other hand, provides a way of arranging widgets into a particular structure in your application's windows. A layout can also give certain behaviors to widgets that belong to it, like the ScatterLayout, which enables multi-touch resizing of a child widget.
In Kivy, you'll find widget and layout classes in their corresponding module under the kivy.uix module. For example, to import the Button class, we can use:
python from kivy.uix.button import ButtonIn Kivy, widgets and layout classes are usually located in modules named after the class itself. However, the class uses CamelCase, and the containing module uses lower casing.
For example, take the following imports:
python # Widgets from kivy.uix.label import Label from kivy.uix.image import Image # Layouts from kivy.uix.boxlayout import BoxLayout from kivy.uix.floatlayout import FloatLayoutYou'll find some exceptions to this naming convention. For example:
python from kivy.uix.image import AsyncImage from kivy.uix.screenmanager import FadeTransitionThis commonly happens with modules that define multiple and closely related classes, such as Image and AsyncImage.
WidgetsWidgets are the building blocks of Kivy-based GUIs. Some of the most commonly used GUI widgets in Kivy apps include the following:
- Widget is the base class required for creating widgets.
- Label is used for rendering text on windows and dialogs.
- TextInput provides a box for editable plain text.
- Button triggers actions when the user presses it.
- CheckBox provides a two-state button that can be either checked or unchecked.
- Image is used to display an image on your GUIs.
- ProgressBar visualizes the progress of some tasks.
- DropDown provides a versatile drop-down list that can list different widgets.
With these widgets and some others that Kivy provides, you can build complex and user-friendly interfaces for your applications.
LayoutsKivy also has a rich set of layout classes that allows you to arrange your widgets coherently and functionally to build up GUIs. Some examples of common layouts include:
- BoxLayout arranges widgets sequentially in either a vertical or horizontal fashion.
- FloatLayout arranges widgets in a specific position on the containing window.
- RelativeLayout arranges child widgets according to relative positions.
- GridLayout arranges widgets in a grid defined by the rows and columns.
- PageLayout creates multi-page layouts in a way that allows flipping from one page to another.
- ScatterLayout positions its child widgets similarly to a RelativeLayout.
- StackLayout stacks in a left-to-right and then top-to-bottom order, or top-to-bottom then left-to-right order.
You can combine and nest layouts together to build complex user interfaces.
Using Widgets and Layouts: A Practical ExampleAs an example of how to use widgets and layouts in Kivy, let's look at a commonly used layout class: the GridLayout. With this class, we can create a grid of rows and columns. Each cell of the grid has a unique pair of zero-based coordinates. Consider the following example:
python from kivy.app import App from kivy.uix.button import Button from kivy.uix.gridlayout import GridLayout ROWS = COLS = 3 class GridApp(App): def build(self): root = GridLayout(rows=ROWS, cols=COLS) for i in range(ROWS): for j in range(COLS): root.add_widget(Button(text=f"({i}, {j})")) return root GridApp().run()In the build() method, we instantiate the GridLayout with three rows and three columns. Then use a for loop to add button widgets to the layout using the add_widget() method.
When we run this app, we get the window that is shown below:
Grid Layout in Kivy
Each button on the grid shows its corresponding pair of coordinates. The first coordinate represents the row, while the second represents the column. Like the rest of the layout classes, GridLayout can take several arguments that you can use to fine-tune its behavior.
Drawing Shapes in Kivy: The canvas PropertyTo deeply customize a GUI or design a 2D video game, we may need to draw 2D shapes, such as a rectangle, circle, ellipse, or triangle. Doing this is straightforward in Kivy. The library provides a rich set of shape classes that you can find in the kivy.graphics package. Some of these classes include:
To draw a shape on the screen with Kivy, we need to use the canvas property of a Widget object. This property holds an instance of the Canvas class, which lives in the kivy.graphics package.
Let's see how this works with an example of a white square drawn on the screen:
python from kivy.app import App from kivy.core.window import Window from kivy.graphics import Rectangle from kivy.uix.widget import Widget class CanvasApp(App): def build(self): root = Widget() size = 200 width, height = Window.size pos_x = 1/2 * (width - size) pos_y = 1/2 * (height - size) with root.canvas: Rectangle(size=[size, size], pos=[pos_x, pos_y]) return root CanvasApp().run()Inside build(), we create the root widget and define the size of our shape. It'll be a square shape, so each side is equal.
Next, we compute the coordinates to center our shape on the window. The coordinates passed when creating the shape are for the top left corner of the window.
To calculate the correct values, we take the width and height of our main window, halving these values to get the center. We then subtract half of the width or height of our shape to position the center of our shape in the middle of the window. This can be simplified to 1/2 * (width - size) or 1/2 * (height - size). We store the resulting top left coordinates in pos_x and pos_y.
Next, we use the canvas property of our root window to draw the shape. This property supports the with statement, which provides the appropriate context for creating our shapes. Inside the with block, we define our Rectangle instance with the size and pos arguments.
Finally, we return the root widget as expected. The final line of code creates the app instance and calls its run() method. If you run this app from your command line, then you'll get the following window on the screen:
Drawing Shapes in Kivy With Canvas
Cool! You've drawn a square on your Kivy app. The computed coordinates place the square in the center of the window. The default color is white. However, we can change it:
python # ... from kivy.graphics import Color, Rectangle from kivy.uix.widget import Widget # ... class CanvasApp(App): def build(self): # ... with root.canvas: Color(1, 1, 0, 1) Rectangle(size=[side, side], pos=[pos_x, pos_y]) # ...In this code snippet, we have added an import for the Color class from the graphics package. The Color class accepts four numeric arguments between 0 and 1 representing the red, green, blue, and transparency components of our target color.
For example, the values (1, 0, 0, 1) represent an entirely red and fully opaque color. The value (0, 1, 0, 0.5) is fully green, half opaque, and half transparent. Consequently, the value (1, 1, 0, 1) gives a fully opaque yellow color. So, if you run the app, then you'll get the following output:
Drawing Shapes in Color With Kivy
We can experiment with different color values and also with different shape classes, which is cool.
Finally, note that to see the effect of the Color() on the drawn rectangle, the Color class must be instantiated before the Rectangle class. You can think of this as dipping your paintbrush on a palette before using it to paint on your canvas! Interestingly, any drawing that comes after the Color instance is painted accordingly so long as a different color has not been applied.
Using the with statement is pretty convenient and facilitates working with shapes. Alternatively, we can use the canvas.add() method:
python root.canvas.add(Color(1, 1, 0, 1)) root.canvas.add( Rectangle(size=[side, side], pos=[pos_x, pos_y]) )These statements are equivalent to the statements we have in the with block. Go ahead and give it a try yourself.
Styling Your GUIs With the Kivy LanguageKivy also provides a declarative language known as the Kv language, which aims at separating your application's GUI design and business logic. In this tutorial, we will not go deep into using the Kv language. However, we will highlight some of its main features and strengths.
With Kv language, you can declare and style the widgets and graphical components of your GUI apps. You will put your Kv code in files with the .kv extension. Then you can load the content of these files into your app to build the GUI. You'll have at least two ways to load the content of a .kv file:
- Relying on the automatic loading mechanism
- Using the Builder class for manual loading
In the following sections, you'll learn the basics of these two ways of using the Kv language to build the GUI of your Kivy apps.
Relying on the Automatic Widget LoadingAs stated earlier, the Kv language helps you separate business logic from GUI design. Let's illustrate this possibility with an updated version of our "Hello, World!" app:
python from kivy.app import App from kivy.uix.label import Label class CustomLabel(Label): pass class MainApp(App): def build(self): root = CustomLabel() return root MainApp().run()As you can see we have subclassed the Label class to create a new CustomLabel haven't made any modifications to the subclass, so it functions exactly like the Label class but with a different name. We add a pass statement, which is a Python placeholder statement which makes the code syntactically valid.
Next, create a file called main.kv alongside your app's file. Define a label using the following code:
kv <CustomLabel>: text: "Hello, World!"Note that your label must have the same name as your custom Python class in the app's file. Additionally, the .kv file must have the same name as your subclass of App, but without the App suffix and in lowercase. In this example, your subclass is named MainApp, so your .kv file must be main.kv.
Now you can run the app from your command line. You'll get the following window on your screen:
Kivy Application Using the Kv Language
The Kv language, also known as kivy language or just kvlang, allows us to create widget trees in a declarative way. It also lets you bind widget properties to each other or to callbacks.
Loading Widgets Through the Builder ClassWhen your Kivy project grows, your .kv file will grow as well. So, it is recommended that you split up the file into different files for readability. In such cases, you will end up with multiple .kv files, and the automatic loading mechanism will not be sufficient. You'll have to use the Builder class from kivy.lang.Builder.
To explore how to use Builder, let's build a sample GUI consisting of a label and button in a BoxLayout. The label will be provided in the labels.kv file, while the buttons will live in the buttons.kv file.
Here's the Python code for this app:
python from kivy.app import App from kivy.lang import Builder from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button from kivy.uix.label import Label Builder.load_file("labels.kv") Builder.load_file("buttons.kv") class CustomLabel(Label): pass class CustomButton(Button): pass class MainApp(App): def build(self): root = BoxLayout(orientation="vertical") root.add_widget(CustomLabel()) root.add_widget(CustomButton()) return root MainApp().run()After importing the required classes, we call the load_file() method. This method takes the filename of a .kv file as an argument and loads it into your app.
Next, you create the custom label and button following the pattern used in the previous section. Inside build(), you create a BoxLayout and add the two widgets to it. Now you need to provide the required .kv files.
Go ahead and create a labels.kv file with the following content:
kv <CustomLabel>: text: "This is a custom label!" font_size: 50 bold: TrueThis file provides a label with the text "This is a custom label!". Its font will have a size of 50 pixels and will be bold.
The buttons.kv will have the following code:
kv <CustomButton>: text: "Click me!"Your custom button will be quite minimal. It'll only have the text "Click me!" on it. Go ahead and run the app from your command line. You'll get the following window on your screen:
Kivy Application Using the Kv Language With Multiple kv Files
In addition to using the load_file() to build Kv language files, you can also parse and load Kv language directly in a multi-line string in your Python file:
python Builder.load_string(""" <CustomLabel>: text: "This is a custom label!" font_size: 50 bold: True """) Builder.load_string(""" <CustomButton>: text: "Click me!" """)These calls to load_string() are completely equivalent to the corresponding calls to load_file() in our original code example.
Let's take a look at a final example of using the Kv language. This time we'll use the language to draw shapes. Create a rectangle.py file with the following content:
python from kivy.app import App from kivy.uix.widget import Widget class CustomRectangle(Widget): pass class MainApp(App): def build(self): return CustomRectangle() MainApp().run()Now go ahead and create another file in the same directory and save it as main.kv. Then add the following content:
kv <CustomRectangle>: canvas: Color: rgba: 1, 1, 0, 1 Rectangle: size: 200, 200 pos: 0, 0If you run the rectangle.py file, then you will see a 200×200 pixels rectangle ---square in this case--- at the lower left corner of your window! For more guidelines on using Kv Language, check out its official documentation.
More ResourcesFor some more examples of what you can do with Kivy, take a look at the Kivy examples section in the documentation. Depending on your interest, you can also the other resources. For example:
- If you're interested in 3D, then the Kivy 3D demo gives a good demonstration of the framework's rendering abilities.
- If you're interested in using Kivy to develop for mobile, you can write functional Android apps (APKs) with Python and pack them using tools like Buildozer and Python-For-Android without learning Java.
- If you want a complete vision of where you can use Kivy, then check out the gallery of examples provided by the Kivy community.
What you've learned in this tutorial is just the tip of the Kivy iceberg. There's so much more to Kivy than what meets the eye. It's a powerful GUI library that provides a well-structured hierarchy of classes and objects that you can use to create modern and cross-platform GUIs for your applications.
Russ Allbery: Review: Night Watch
Review: Night Watch, by Terry Pratchett
Series: Discworld #29 Publisher: Harper Copyright: November 2002 Printing: August 2014 ISBN: 0-06-230740-1 Format: Mass market Pages: 451Night Watch is the 29th Discworld novel and the sixth Watch novel. I would really like to tell people they could start here if they wanted to, for reasons that I will get into in a moment, but I think I would be doing you a disservice. The emotional heft added by having read the previous Watch novels and followed Vimes's character evolution is significant.
It's the 25th of May. Vimes is about to become a father. He and several of the other members of the Watch are wearing sprigs of lilac for reasons that Sergeant Colon is quite vehemently uninterested in explaining. A serial killer named Carcer the Watch has been after for weeks has just murdered an off-duty sergeant. It's a tense and awkward sort of day and Vimes is feeling weird and wistful, remembering the days when he was a copper and not a manager who has to dress up in ceremonial armor and meet with committees.
That may be part of why, when the message comes over the clacks that the Watch have Carcer cornered on the roof of the New Hall of the Unseen University, Vimes responds in person. He's grappling with Carcer on the roof of the University Library in the middle of a magical storm when lightning strikes. When he wakes up, he's in the past, shortly after he joined the Watch and shortly before the events of the 25th of May that the older Watch members so vividly remember and don't talk about.
I have been saying recently in Discworld reviews that it felt like Pratchett was on the verge of a breakout book that's head and shoulders above Discworld prior to that point. This is it. This is that book.
The setup here is masterful: the sprigs of lilac that slowly tell the reader something is going on, the refusal of any of the older Watch members to talk about it, the scene in the graveyard to establish the stakes, the disconcerting fact that Vetinari is wearing a sprig of lilac as well, and the feeling of building tension that matches the growing electrical storm. And Pratchett never gives into the temptation to explain everything and tip his hand prematurely. We know the 25th is coming and something is going to happen, and the reader can put together hints from Vimes's thoughts, but Pratchett lets us guess and sometimes be right and sometimes be wrong. Vimes is trying to change history, which adds another layer of uncertainty and enjoyment as the reader tries to piece together both the true history and the changes. This is a masterful job at a "what if?" story.
And, beneath that, the commentary on policing and government and ethics is astonishingly good. In a review of an earlier Watch novel, I compared Pratchett to Dickens in the way that he focuses on a sort of common-sense morality rather than political theory. That is true here too, but oh that moral analysis is sharp enough to slide into you like a knife. This is not the Vimes that we first met in Guards! Guards!. He has has turned his cynical stubbornness into a working theory of policing, and it's subtle and complicated and full of nuance that he only barely knows how to explain. But he knows how to show it to people.
Keep the peace. That was the thing. People often failed to understand what that meant. You'd go to some life-threatening disturbance like a couple of neighbors scrapping in the street over who owned the hedge between their properties, and they'd both be bursting with aggrieved self-righteousness, both yelling, their wives would either be having a private scrap on the side or would have adjourned to a kitchen for a shared pot of tea and a chat, and they all expected you to sort it out.
And they could never understand that it wasn't your job. Sorting it out was a job for a good surveyor and a couple of lawyers, maybe. Your job was to quell the impulse to bang their stupid fat heads together, to ignore the affronted speeches of dodgy self-justification, to get them to stop shouting and to get them off the street. Once that had been achieved, your job was over. You weren't some walking god, dispensing finely tuned natural justice. Your job was simply to bring back peace.
When Vimes is thrown back in time, he has to pick up the role of his own mentor, the person who taught him what policing should be like. His younger self is right there, watching everything he does, and he's desperately afraid he'll screw it up and set a worse example. Make history worse when he's trying to make it better. It's a beautifully well-done bit of tension that uses time travel as the hook to show both how difficult mentorship is and also how irritating one's earlier naive self would be.
He wondered if it was at all possible to give this idiot some lessons in basic politics. That was always the dream, wasn't it? "I wish I'd known then what I know now"? But when you got older you found out that you now wasn't you then. You then was a twerp. You then was what you had to be to start out on the rocky road of becoming you now, and one of the rocky patches on that road was being a twerp.
The backdrop of this story, as advertised by the map at the front of the book, is a revolution of sorts. And the revolution does matter, but not in the obvious way. It creates space and circumstance for some other things to happen that are all about the abuse of policing as a tool of politics rather than Vimes's principle of keeping the peace. I mentioned when reviewing Men at Arms that it was an awkward book to read in the United States in 2020. This book tackles the ethics of policing head-on, in exactly the way that book didn't.
It's also a marvelous bit of competence porn. Somehow over the years, Vimes has become extremely good at what he does, and not just in the obvious cop-walking-a-beat sort of ways. He's become a leader. It's not something he thinks about, even when thrown back in time, but it's something Pratchett can show the reader directly, and have the other characters in the book comment on.
There is so much more that I'd like to say, but so much would be spoilers, and I think Night Watch is more effective when you have the suspense of slowly puzzling out what's going to happen. Pratchett's pacing is exquisite. It's also one of the rare Discworld novels where Pratchett fully commits to a point of view and lets Vimes tell the story. There are a few interludes with other people, but the only other significant protagonist is, quite fittingly, Vetinari. I won't say anything more about that except to note that the relationship between Vimes and Vetinari is one of the best bits of fascinating subtlety in all of Discworld.
I think it's also telling that nothing about Night Watch reads as parody. Sure, there is a nod to Back to the Future in the lightning storm, and it's impossible to write a book about police and street revolutions without making the reader think about Les Miserables, but nothing about this plot matches either of those stories. This is Pratchett telling his own story in his own world, unapologetically, and without trying to wedge it into parody shape, and it is so much the better book for it.
The one quibble I have with the book is that the bits with the Time Monks don't really work. Lu-Tze is annoying and flippant given the emotional stakes of this story, the interludes with him are frustrating and out of step with the rest of the book, and the time travel hand-waving doesn't add much. I see structurally why Pratchett put this in: it gives Vimes (and the reader) a time frame and a deadline, it establishes some of the ground rules and stakes, and it provides a couple of important opportunities for exposition so that the reader doesn't get lost. But it's not good story. The rest of the book is so amazingly good, though, that it doesn't matter (and the framing stories for "what if?" explorations almost never make much sense).
The other thing I have a bit of a quibble with is outside the book. Night Watch, as you may have guessed by now, is the origin of the May 25th Pratchett memes that you will be familiar with if you've spent much time around SFF fandom. But this book is dramatically different from what I was expecting based on the memes. You will, for example see a lot of people posting "Truth, Justice, Freedom, Reasonably Priced Love, And a Hard-Boiled Egg!", and before reading the book it sounds like a Pratchett-style humorous revolutionary slogan. And I guess it is, sort of, but, well... I have to quote the scene:
"You'd like Freedom, Truth, and Justice, wouldn't you, Comrade Sergeant?" said Reg encouragingly.
"I'd like a hard-boiled egg," said Vimes, shaking the match out.
There was some nervous laughter, but Reg looked offended.
"In the circumstances, Sergeant, I think we should set our sights a little higher—"
"Well, yes, we could," said Vimes, coming down the steps. He glanced at the sheets of papers in front of Reg. The man cared. He really did. And he was serious. He really was. "But...well, Reg, tomorrow the sun will come up again, and I'm pretty sure that whatever happens we won't have found Freedom, and there won't be a whole lot of Justice, and I'm damn sure we won't have found Truth. But it's just possible that I might get a hard-boiled egg."
I think I'm feeling defensive of the heart of this book because it's such an emotional gut punch and says such complicated and nuanced things about politics and ethics (and such deeply cynical things about revolution). But I think if I were to try to represent this story in a meme, it would be the "angels rise up" song, with all the layers of meaning that it gains in this story. I'm still at the point where the lilac sprigs remind me of Sergeant Colon becoming quietly furious at the overstep of someone who wasn't there.
There's one other thing I want to say about that scene: I'm not naturally on Vimes's side of this argument. I think it's important to note that Vimes's attitude throughout this book is profoundly, deeply conservative. The hard-boiled egg captures that perfectly: it's a bit of physical comfort, something you can buy or make, something that's part of the day-to-day wheels of the city that Vimes talks about elsewhere in Night Watch. It's a rejection of revolution, something that Vimes does elsewhere far more explicitly.
Vimes is a cop. He is in some profound sense a defender of the status quo. He doesn't believe things are going to fundamentally change, and it's not clear he would want them to if they did.
And yet. And yet, this is where Pratchett's Dickensian morality comes out. Vimes is a conservative at heart. He's grumpy and cynical and jaded and he doesn't like change. But if you put him in a situation where people are being hurt, he will break every rule and twist every principle to stop it.
He wanted to go home. He wanted it so much that he trembled at the thought. But if the price of that was selling good men to the night, if the price was filling those graves, if the price was not fighting with every trick he knew... then it was too high.
It wasn't a decision that he was making, he knew. It was happening far below the areas of the brain that made decisions. It was something built in. There was no universe, anywhere, where a Sam Vimes would give in on this, because if he did then he wouldn't be Sam Vimes any more.
This is truly exceptional stuff. It is the best Discworld novel I have read, by far. I feel like this was the Watch novel that Pratchett was always trying to write, and he had to write five other novels first to figure out how to write it. And maybe to prepare Discworld readers to read it.
There are a lot of Discworld novels that are great on their own merits, but also it is 100% worth reading all the Watch novels just so that you can read this book.
Followed in publication order by The Wee Free Men and later, thematically, by Thud!.
Rating: 10 out of 10
Community posts: Introducing the Updated Drupal Community Code of Conduct
The Drupal Community Working Group (CWG) is excited to announce the release of an updated Code of Conduct for the Drupal community. It will take effect on July 1, 2023.
This new version is designed to reflect the growth of the Drupal community since the original Code of Conduct was adopted in 2010 and to help foster a safer, more inclusive, and harassment-free environment for everyone. While it retains the same basic structure as the previous document, much of the text was rewritten to make it easier to read. It also includes new elements inspired by other widely-used open source codes of conduct.
Some of the highlights of the updated Code of Conduct include:
- Improved Readability: The new document has shorter sentences and paragraphs than the previous version, making it easier to read and comprehend. It is also written in a less formal tone.
- Increased Clarity: The updated version includes more detail about where the Code of Conduct applies and the consequences of violating it. It emphasizes the shared responsibility of maintaining a welcoming community.
- More Specificity: Examples of positive and unacceptable behaviors have been added to each section to help community members better understand the expectations and guidelines for their conduct within the Drupal community
- Inclusivity and Diversity: The updated Code of Conduct places a stronger emphasis on fostering an inclusive and diverse environment for people of all backgrounds and identities, and is more consistent with Drupal’s Values and Principles.
- More Actionable: Instructions for reporting Code of Conduct violations are now broken out in an alert box to make them easier for people to find.
The process of updating the Code of Conduct began in earnest in the summer of 2022, building upon community feedback gathered by the CWG since 2017. It was spearheaded by a subgroup of the CWG’s Community Health Team, who gathered feedback and shared drafts with a diverse group of stakeholders across our global community. A draft was then shared publicly with the community for additional feedback and revision. Finally, the document was reviewed and approved by the CWG’s Conflict Resolution Team and Review Panel. If you will be attending the Community Summit at DrupalCon Pittsburgh, members of the team will be sharing additional details at the “How We Updated the Drupal Code of Conduct” session.
We would like to express our gratitude to everyone who contributed to the development of the updated Code of Conduct. Your input and dedication have been invaluable in creating a more inclusive and welcoming environment for all community members.
We encourage all community members to read and familiarize themselves with the updated Code of Conduct. Drupal.org users will also be alerted to the new language when it goes into effect July 1.
If you have any questions or concerns, please do not hesitate to file an issue in the CWG’s issue queue. If you would prefer to reach out privately, you can also send an email to drupal-cwg@drupal.org. Your feedback is always welcome as we continue to improve and adapt our Code of Conduct to the evolving needs of our community.
Thank you for being a part of the Drupal community, and for your commitment to making it a welcoming and inclusive place for everyone.
Brett Cannon: In response to the Changelog #526
In episode 526 of the Changelog podcast entitled, "Git with your friends", they discussed various tools involving git (disclaimer: I have been on the podcast multiple times and had dinner with the hosts of the podcast the last time they were in Vancouver). Two the projects they discussed happened to be written in Python. That led Jerod to say:
The Python one gives me pause as well, just because I don’t know if it’s gonna go right.🤨
Jerod and Adam know I tend to run behind in listening to my podcasts, so they actually told me to listen to the podcast and let them know what I thought, hence this blog post (they also told me to write a blog post when I asked where they wanted "my rant/reply", so they literally asked for this 😉).
To start, Jerod said:
If it’s pip install for me, I just have anxiety… Even though it works most of the time. It’s the same way – and hey, old school Rubyist, but if I see your tool and I see it’s written in Ruby, I’m kind of like “Uhm, do I want to mess with this?” And that’s how I am with Python as well. Their stories are just fraught.To me, that&aposs a red flag that Jerod is installing stuff globally and not realizing that he should be using a virtual enivonrment to isolate his tools and their dependencies. Now, I consider asking non-Python developers to create virtual environments to be a lot, and instead I would recommend using pipx. That allows one to install a Python-based tool in a very straightforward manner using pipx install into their .local directory. I also expect pipx to be available from all the major OS package managers, so installing it (and implicitly Python) shouldn&apost be too difficult.
If you don&apost want the tool you are running to be installed "permanently", pipx run will create a virtual environment in a temp directory so your system can reclaim the space when it wants to. This also has a side-effect of grabbing a newer version of the tool on occasion as the files will occasionally be deleted.
Another option is if projects provide a .pyz file. When projects do that, they are giving users a zip file that is self-contained in terms of Python code, such that you can just pass that to your Python interpreter to run something (e.g. python tool.pyz). That avoids any installation overhead or concerns over what Python interpreter you have installed at any point since you point any Python interpreter at the .pyz file (compatibility permitting).
For the pipx scenario we probably need projects to take the lead to write their documentation about this as non-Python developers quite possibly don&apost know about either option. The .pyz solution involves the project itself to build something as part of its release process which is also a bigger ask.
Jerod did provide a little bit of clarification later about what his concerns were:
Yeah. I have no problem with Ruby-based things. But if you say gem-install this tool, I’m like “You know what? I don’t really trust my Ruby environment over the course of years on my Mac”, and I’m the same way with Python. Whereas with Go, and with Rust, it seems - and JavaScript had the same bad story for me, but Deno with TypeScript is showing some new opportunities to have universal binaries, which is cool… I’m just way more likely to say “If you can just grab a binary, drop it in your path and execute it, I will do that 100 times a day.” But if your tool says PIP install, or it says gem install, or says npm install, I’m kind of like “Do I want to mess with this?” That’s just my sense.So that does tie into the above guess that Jerod isn&apost using virtual environments. But you could stretch this out and say Jerod is even concerned that his Python interpreter will change or disappear, breaking any code he installed for that. In that instance, pipx run is rather handy as it will implicitly install Python if you got it from your OS package manager. You can also install Python explicitly instead of relying on it coming installed in the OS (which is now a Unix thing since macOS stopped shipping Python by default).
There is also the option of turning your Python tool into a standalone application. You can use things like Briefcase for GUI apps and PyApp for CLI apps. But this does make releasing harder as the project is now being asked to maintain builds for various operating systems instead of simply relegating that job to Python itself.
Now, Adam wanted even less work to do in order to get a tool:
if it’s on Linux, it should be in Apt, or whatever your [unintelligible 00:45:04.05] Yum, or pick your – it should be a package. Or you should have to update your registry with whatever package directory you want to use, and apt update, and get that, and install. That’s my feelings. I don’t like to PIP install anything if I don’t have to.The trick with this is that you, the tool developer, do not have direct control as to whether an OS package manager picks up your tool to be packaged. Since you don&apost control that distribution mechanism there is no guarantee that you can get your tool into the package manager you want (e.g., Homebrew can choose to reject your project for inclusion).
The other problematic part is there&aposs multiple OS package managers to get into, and that&aposs even if you restrict yourself to the "major" Linux distributions:
And that&aposs not covering the BSDs:
Windows:
or macOS:
And so supporting that installation flow of just installing from an OS package manager takes work as you&aposre now coordinating your tool with multiple OSs which all have their own metadata format, requirements for inclusion, ways to be told about updates, etc. It&aposs not a small lift to make happen if you want a large swath of coverage for your project.
Hopefully this has allievated some of Jerod&aposs concerns and shown Adam that his ask isn&apost small. 😉 But what&aposs the best approach for a Python tool project to take?
Unfortunately I don&apost know if there&aposs a simple answer here. For instance, if people were to use PyApp to build a self-contained binary, would people download it and actually use it, or would they be like Adam and just look for what&aposs available from their OS package manager? Where is the best cost:benefit ratio for each of the options suggested above where it warrants complicating your release process? I think documenting pipx and making a .pyz, if possible, available do make sense. But as to whether standalone binaries make sense or if it&aposs a better use of time to try and get into the package managers I honestly don&apost know.
PyCoder’s Weekly: Issue #579 (May 30, 2023)
#579 – MAY 30, 2023
View in Browser »
In this tutorial, you’ll learn what a callable is in Python and how to create callable instances using the .__call__() special method in your custom classes. You’ll also code several examples of practical use cases for callable instances in Python.
REAL PYTHON
“Typically, Django allows sorting a queryset by any attribute on the model or related to it in either ascending or descending order. However, what if you need to sort the queryset following a custom sequence of attribute values?”
REDOWAN DELOWAR
Semgrep is trusted by hundreds of thousands of developers at top companies, such as GitLab, Snowflake, Slack, and many more, to ensure the security of their code (SAST) and dependencies (SCA). Add your project in 1 minute and see for yourself →
SEMGREP sponsor
This article covers the importance and use of decorators in your code. It introduces you to both function and class decorators and helps you write your own.
TONIE VICTOR
In March and April 2023, PyPI received three subpoenas for user data from the US Department of Justice. This blog post covers what was requested and how the PyPI is working to clarify what they retain and can make available in the future. See the associated Hacker News discussion.
PYPI.ORG
This blog post from Jakub talks about how writing code in Rust has informed a more rigorous approach to his Python. He now uses types more frequently, absorbing the strictness of Rust in his Python coding style. Associated Hacker News conversation
JAKUB BERANEK
In this video course, you’ll learn how to create a Python package for your project and how to publish it to PyPI, the Python Package Repository. Quickly get up to speed on everything from naming your package to configuring it using setup.cfg.
REAL PYTHON course
Trusted by 2000+ developers from 120+ countries. Proxify provides software developers with an effortless, fast, and reliable way to find high-paying remote job opportunities. Join the most developer-friendly community today and start working on engagements with Top clients in the USA & EU →
PROXIFY sponsor
In this video course, you’ll learn all about the k-nearest neighbors (kNN) algorithm in Python, including how to implement kNN from scratch. Once you understand how kNN works, you’ll use scikit-learn to facilitate your coding process.
REAL PYTHON course
David expounds on why we should appreciate the features of other languages and how they enable the creativity of their developers, even if we don’t like those features ourselves.
DAVID HANSSON
Including a Golang package in Python using Gopy: A simple way to leverage the power of Golang packages in Python applications.
ARJUN MAHISHI • Shared by Prathamesh
CSV, JSON, Parquet — which data format should you use for your Pandas data? Itamar compares them and makes recommendations.
ITAMAR TURNER-TRAURING
In this article, you learn about bit manipulation and how to solve problems efficiently using it in Python.
ANURAG VERMA
GITHUB.COM/HAKANCELIKDEV • Shared by Hakan Çelik
ChatSQL: Convert Plain Text to SQL Through ChatGPTGITHUB.COM/ADEMAKDOGAN • Shared by Adem AKDOGAN
pyserde: Dataclass Based Serialization Library pyscan: Rust Based Python Dependency Vulnerability Scanner guidance: Language for Controlling Large Language Models Events DjangoCon Europe 2023 May 29 to June 3, 2023
DJANGOCON.EU
May 31, 2023
REALPYTHON.COM
June 1, 2023
MEETUP.COM
June 2 to June 5, 2023
PYDATA.ORG
June 3 to June 4, 2023
PYLAPAZ.ORG
Happy Pythoning!
This was PyCoder’s Weekly Issue #579.
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 ]
Four Kitchens: A more modern, sustainable approach to higher ed websites with YaleSites
Senior Engineer
As a tech lead, Jim works with clients through the full project cycle, translating their business requirements into actionable development work and working with them to find technical solutions to their challenges.
January 1, 1970
Running the digital experience is a large-scale operation for most higher ed institutions. Whether your architecture was established five or 15 years ago, the departments, offices, and entities you need to manage may add up to hundreds or even thousands of websites. And each new addition is increasingly challenging to maintain.
Some sites use shared modules, while others do not. If you want to make an update to one website, you have to cross your fingers and hope it doesn’t break something on 500 others. Every day, another stakeholder presents a new request in support of an upcoming project.
Facing all these compounding issues, the IT department at Yale understood that a lift-and-shift of their existing sites was impossible. Upgrading their digital platform presented an opportunity to reset their architecture and processes to start fresh.
In a preview of our upcoming presentation at DrupalCon 2023, here’s what happened next — and what your institution can learn from it.
Why reinvention makes sense for higher ed institutionsUniversities are facing significant challenges related to budgets, economic uncertainty, and reduced admissions applications. The pandemic introduced further uncertainty balanced with an increased need to sharpen digital presentations.
As one of the most prestigious institutions in the world, Yale needed to find a new, more sustainable way to manage its digital needs. The institution had stretched the limits of a very mature Drupal 7 site with more than a decade’s worth of modules, themes, and custom code.
It was difficult for the IT team to test with confidence, because they manage more than 1,100 sites that were all created in different ways. In addition, the more impressive a new site looked, the more other offices and departments wanted to emulate it.
The unintended consequences of an overtaxed website platformWith the university’s website system at critical mass, Yale’s teams lacked incentive to add new features to its legacy platform. Consequently, some larger departments found the platform inflexible, leading them to Wix and Squarespace for new projects. If the university didn’t find a workable platform solution, it ran the risk of increased site errors, design inconsistencies, and a diminished user experience.
Resetting Yale’s approach to digital required a sizable upfront capital investment. As the work comes to fruition, the organization is gaining a flexible, scalable platform that will benefit every department into the next decade — and beyond.
YaleSites: A transformational approach to higher ed websitesYaleSites is the product of years of examining the university’s needs. Through our previous work with the institution’s cybersecurity office and the Schwarzman Center, we developed a new platform that incorporated the following elements:
A unified brand identity and design systemYaleSites offers many departments the ability to create unique digital experiences that are aligned with the institution’s overall design. Instead of a conventional CMS, Yale’s team uses a customized drag-and-drop page builder drawn from a library of proven components powered by Emulsify.
The YaleSites Welcome page Inclusive and accessible development for all customers and devicesInstitutions like Yale need to offer an equitable digital experience for every audience. YaleSites upholds and prioritizes the university’s accessibility standards by making sure every content block follows best practices for usability and accessibility.
User-focused experience and designYaleSites prioritizes the needs of the organization’s audience and its end users. Across the organization, content authors of every skill level can access a full library of templates, starter kits, and media libraries to produce what they need.
Adding blocks in the YaleSites administrative interface. Standardized practices for developmentThe organization’s development process has been streamlined. Rather than asking “What do you need in a website?”, work begins with the question, “How can our tools help with your strategy?” Developers don’t have to reinvent the wheel for a new site. Instead, they have the support of a system that’s performant, on-brand, and secure.
Sustainable governanceWe implemented YaleSites with an eye toward thoughtful and sustainable growth. Universities often set digital priorities based on the loudest or most powerful voices in the organization. Now, Yale uses processes that enable them to focus on the organization’s most pressing needs. Plus, a core group meets regularly to collect feedback, respond to requests, and adjust priorities as needed.
Shifting from a project-based to a product-based perspectiveAfter launching YaleSites, the institution will enter the maintenance phase of protecting its system. The university’s new platform required a significant financial investment — now it must invest in the long-term work of governance.
The success of Yale’s platform hinges on a seismic internal shift. YaleSites isn’t a project that concludes with a specific end date. It’s a product that the organization must refine and support in perpetuity.
Since YaleSites is a product, its resources are finite. For example, if IT plans to add six new features in a quarter, any new request is a negotiation. Something may need to get bumped from the product roadmap. Rather than rushing a new feature into development for a short-term need, the organization follows a multiyear roadmap and measures the needs against all of the priorities in the queue.
Eliminate deadline pressure by focusing on constant improvementThinking long-term about your organization’s website removes the need to squeeze as many improvements as possible into a project’s deadline. Following the principles of Agile development frees your team from solving every use case before launch. Instead, you can launch a minimally functional feature like an events calendar, see how people use it, and refine how it works according to actionable feedback.
YaleSites allows the institution to implement site improvements with confidence. Rather than working on whatever makes sense in the moment, they see their work progress from ideation to development, testing, and release.
From the flexibility of its digital tools to a more managed, Agile-driven approach to website improvements, YaleSites marks a dramatic shift for the better. If this sounds like a shift that would benefit how your organization works, we should talk. We can help you view your site and its planning from a new perspective.
Megan Bygness Bradley and the Yale team contributed to this post.
The post A more modern, sustainable approach to higher ed websites with YaleSites appeared first on Four Kitchens.
Stack Abuse: How to Split String on Multiple Delimiters in Python
Among the plenty of string operations, splitting a string is a significant one, offering the capability to divide a large, composite text into smaller, manageable components. Typically, we use a single delimiter like a comma, space, or a special character for this purpose. But what if you need to split a string based on multiple delimiters?
Imagine a situation where you're dealing with text data punctuated with various separators, or you're parsing a complex file with inconsistent delimiters. This is where Python's ability to split strings on multiple delimiters truly shines.
In this article, we'll give you a comprehensive overview of the different techniques of multi-delimiter string splitting in Python. We'll explore core Python methods, regular expressions, and even external libraries like Pandas to achieve this.
The str.split() Method can Split Strings on Only One DelimiterThe str.split() method is Python's built-in approach to dividing a string into a list of substrings. By default, str.split() uses whitespace (spaces, tabs, and newlines) as the delimiter. However, you can specify any character or sequence of characters as the delimiter:
text = "Python is a powerful language" words = text.split() print(words)Running this code will result in:
['Python', 'is', 'a', 'powerful', 'language']In this case, we've split the string into words using the default delimiter - whitespace. But what if we want to use a different delimiter? We can pass it as an argument to split():
text = "Python,is,a,powerful,language" words = text.split(',') print(words)Which will give us:
['Python', 'is', 'a', 'powerful', 'language']While str.split() is highly useful for splitting strings with a single delimiter, it falls short when we need to split a string on multiple delimiters. For example, if we have a string with words separated by commas, semicolons, and/or spaces, str.split() cannot handle all these delimiters simultaneously.
Advice: Reading our guide "Python: Split String into List with split()" will help you gain a deeper understanding of the split() method in Python.
In the upcoming sections, we will explore more sophisticated techniques for splitting strings based on multiple delimiters in Python.
Using Regular Expressions - the re.split() MethodTo tackle the issue of splitting a string on multiple delimiters, Python provides us with the re (Regular Expressions) module. Specifically, the re.split() function is an effective tool that allows us to split a string using multiple delimiters.
Regular expressions (or regex) are sequences of characters that define a search pattern. These are highly versatile, making them excellent for complex text processing tasks.
Consider the following string:
text = "Python;is,a powerful:language"If you want to extract words from it, you must consider multiple delimiters. Let's take a look at how we can use re.split() to split a string based on multiple delimiters:
import re text = "Python;is,a powerful:language" words = re.split(';|,| ', text) print(words)This will give us:
['Python', 'is', 'a', 'powerful', 'language']We used the re.split() method to split the string at every occurrence of a semicolon (;), comma (,), or space ( ). The | symbol is used in regular expressions to mean "or", so ;|,| can be read as "semicolon or comma or space".
This function demonstrates far greater versatility and power than str.split(), allowing us to easily split a string on multiple delimiters.
Advice: You can find more about Python regular expressions in our "Introduction to Regular Expressions in Python".
In the next section, we'll take a look at another Pythonic way to split strings using multiple delimiters, leveraging the translate() and maketrans() methods.
Using translate() and maketrans() MethodsPython's str class provides two powerful methods for character mapping and replacement: maketrans() and translate(). When used in combination, they offer an efficient way to replace multiple delimiters with a single common one, allowing us to use str.split() effectively.
The maketrans() method returns a translation table that can be used with the translate() method to replace specific characters. So, let's take a look at how to utilize those two methods to fit our needs.
First of all, we need to create a translation table that maps semicolons (;) and colons (:) to commas (,):
text = "Python;is,a powerful:language" # Create a translation table mapping ';' and ':' to ',' table = text.maketrans(";:", ",,")Then we use the translate() method to apply this table to our text. This replaces all semicolons and colons with commas:
# Apply the translation table text = text.translate(table)Finally, we can use str.split(',') to split the text into words and print extracted words:
# Now we can split on the comma words = text.split(',') print(words)This will result in:
['Python', 'is', 'a powerful', 'language']Note: This approach is particularly useful when you want to standardize the delimiters in a string before splitting it.
In the next section, we'll explore how to utilize an external library, Pandas, for splitting strings on multiple delimiters.
Leveraging the Pandas LibraryPandas, a powerful data manipulation library in Python, can also be used for splitting strings on multiple delimiters. Its str.split() function is capable of handling regex, making it another effective tool for this task.
While the built-in string methods are efficient for smaller data, when you're working with large datasets (like a DataFrame), using Pandas for string splitting can be a better choice. The syntax is also quite intuitive.
Here's how you can use Pandas to split a string on multiple delimiters:
import pandas as pd # Create a DataFrame df = pd.DataFrame({'Text': ['Python;is,a powerful:language']}) # Use the str.split() function with a regex pattern df = df['Text'].str.split(';|,|:', expand=True) print(df)This will give us:
0 1 2 3 4 0 Python is a powerful languageWe first created a DataFrame with our text. We then used the str.split() function, passing in a regex pattern similar to what we used with re.split(). The expand=True argument makes the function return a DataFrame where each split string is a separate column.
Note: Although this method returns a DataFrame instead of a list, it can be highly useful when you're already working within the Pandas ecosystem.
Performance ComparisonWhen choosing a method to split strings on multiple delimiters, performance can be an important factor, especially when working with large datasets. Let's examine the performance of the methods we've discussed.
The built-in str.split() method is quite efficient for smaller data sets and a single delimiter, but its performance suffers when used with multiple delimiters and large datasets due to the necessary extra processing.
The re.split() method is versatile and relatively efficient, as it can handle multiple delimiters well. However, its performance might also degrade when dealing with huge amounts of data, because regular expressions can be computationally intensive.
Using translate() and maketrans() can be an efficient way to handle multiple delimiters, especially when you want to standardize the delimiters before splitting. However, it involves an extra step, which can affect performance with large datasets.
Finally, while the Pandas library offers a very efficient and flexible method to split strings on multiple delimiters, it might be overkill for simple, small tasks. The overhead of creating a DataFrame can affect performance when working with smaller data, but it excels in handling large datasets.
In conclusion, the best method to use depends on your specific use case. For small datasets and tasks, Python's built-in methods might be more suitable, while for larger, more complex data manipulation tasks, Pandas could be the way to go.
ConclusionString splitting, especially on multiple delimiters, is a common yet crucial operation in Python. It serves as the backbone in many text processing, data cleaning, and parsing tasks. As we've seen, Python provides a range of techniques for this task, each with its own strengths and weaknesses. From the built-in str.split(), to the versatile Regular Expressions, the character mapping translate() and maketrans() methods, and even the external Pandas library, Python offers solutions suitable for any complexity and size of data.
It's important to understand the different methods available and choose the one that best suits your specific requirements. Whether it's simplicity, versatility, or performance, Python's tools for string splitting can cater to various needs.
We hope this article helps you become more proficient in handling and manipulating strings in Python.
Chromatic: Drupal 7 End-of-Life Ep 08: Building a Bridge to Drupal 7 with Matt Glaman
The Three of Wands: Intro to cattrs 23.1.0
Instead of my usual Twitter and Fediverse threads, for this release of cattrs I figured I&aposd try something different. A blog post lets me describe the additions in more detail, provide context and usage examples, and produces a permanent record that can be linked to from the relevant places, like a GitHub release page and the cattrs changelog.
cattrs is a library for transforming Python data structures, the most obvious use case being de/serialization (to JSON, msgpack, YAML, and other formats).
Tagged Unionscattrs has supported unions of attrs classes for a long time through our default automatic disambiguation strategy. This is a very simple way of supporting unions using no extra configuration. The way it works is: we examine every class in the union, find unique, mandatory attribute names for each class, and generate a function using that information to do the actual structuring. (Other unions are supported via manually-written hooks.)
But what if one of your classes has no unique attributes, or you just want to be able to tell the union member from a glance at the payload? Now you can use the tagged unions strategy.
This strategy adds a field into the unstructured payload, defaulting to _type but configurable, which inserts a piece of data (by default the name of the class, but again configurable) to help with structuring.
This strategy isn&apost the default so you&aposll have to import it and configure it on a union-by-union basis.
from attrs import define from cattrs import Converter from cattrs.strategies import configure_tagged_union @define class A: a: int @define class B: a: str c = Converter() configure_tagged_union(A | B, c) c.unstructure(A(1), unstructure_as=A|B) # {"a": 1, "_type": "A"} c.structure({"a": 1, "_type": "A"}, A|B) # A(1)A useful feature of configure_tagged_union is that you can give it a default member class. This is a good way of evolving an API from a single class to a union in a backwards-compatible way.
from attrs import define @define class Request: @define class A: field: int payload: A c = Converter() c.structure({"payload": {"field": 1}}, Request) # Request(A(1)) # Next iteration: @define class Request: @define class A: field: int @define class B: field: int payload: A | B c = Converter() configure_tagged_union(A | B, c, default=A) # No type info means `A` c.structure({"payload": {"field": 1}}, Request) # Still Request(A(1))Improved Validation Errorscattrs has had a detailed validation mode for a few versions now, and it&aposs enabled by default. In this mode, structuring errors are gathered and propagated out as an ExceptionGroup subclass, essentially creating a tree of errors mirroring the desired data structure. This ExceptionGroup can then be printed out using normal Python tooling for printing exceptions.
Still, sometimes you need a more succinct representation of your errors; for example if you need to display it to a user or return it to a web frontend. So now we have a simple transformer function available:
from attrs import define from cattrs import structure, transform_error @define class Class: a_list: list[int] a_dict: dict[str, int] try: structure({"a_list": ["a"], "a_dict": {"str": "a"}}, Class) except Exception as exc: print(transform_error(exc)) [ &aposinvalid value for type, expected int @ $.a_list[0]&apos, "invalid value for type, expected int @ $.a_dict[&aposstr&apos]" ]As you see, we generate a list of readable(-ish) error messages, including a path to every field. This can be customized, or you can copy/paste the transform_error function and just alter it directly if you require absolute control. Learn more here.
Typed Dictscattrs now supports TypedDicts on all supported Python versions. Due to spotty TypedDict functionality in earlier Pythons, I recommend you use TypedDict from typing_extensions when running on 3.9 or earlier. This is the reason cattrs now depends on typing_extensions on those versions.
from typing import TypedDict from datetime import datetime from cattrs.preconf.json import make_converter converter = make_converter() class MyDict(TypedDict): my_datetime: datetime converter.structure({"my_datetime": "2023-05-01T00:00:00Z"}, MyDict) # {&aposmy_datetime&apos: datetime.datetime(2023, 5, 1, 0, 0, tzinfo=datetime.timezone.utc)}Generic TypedDicts are supported on 3.11+ (a language limitation), and totalities, Required and NotRequred are supported regardless.
The TypedDict implementation leverages the existing attrs/dataclasses base so it inherits most of the features. For example, structuring and unstructuring hooks can be customized to rename or omit keys. Here&aposs an example with the forbid_extra_keys functionality:
from typing import TypedDict from cattrs import Converter from cattrs.gen.typeddicts import make_dict_structure_fn class MyTypedDict(TypedDict): a: int c = Converter() c.register_structure_hook( MyTypedDict, make_dict_structure_fn(MyTypedDict, c, _cattrs_forbid_extra_keys=True) ) c.structure({"a": 1, "b": 2}, MyTypedDict) # Raises an exceptionNew Markdown DocsThe docs have been rewritten using Markdown and MyST! We can finally link like civilized people and not animals, so I&aposll be going through the docs and making them more interconnected. The theme has also been tweaked to be more airy and (in my opinion) better looking. The new docs are live at https://catt.rs now.
MiscThere are many more smaller changes in this release; I suggest inspecting the actual changelog. A quick shout out to the include_subclasses strategy by Matthieu Melot!
What&aposs NextSo I don&apost actually know exactly what&aposll end up in the next version of cattrs since I don&apost work via a strict roadmap and I can&apost predict what folks will contribute.
What I think will probably happen is the creation of some sort of OpenAPI/jsonschema and cattrs wrapper library. It&aposs something folks have expressed interest in, and I already have the bones of it in the uapi project.
I&aposll also continue work on fleshing out the cattrs.v validation subsystem. This will probably go hand-in-hand with efforts in attrs and Mypy making operations on class attributes type-safe.
I&aposll also almost certainly expand both our union strategies to additionally handle enums and literals automatically, enabling true sum type support by default.
Real Python: Getting the First Match From a Python List or Iterable
At some point in your Python journey, you may need to find the first item that matches a certain criterion in a Python iterable, such as a list or dictionary.
The simplest case is that you need to confirm that a particular item exists in the iterable. For example, you want to find a name in a list of names or a substring inside a string. In these cases, you’re best off using the in operator. However, there are many use cases when you may want to look for items with specific properties. For instance, you may need to:
- Find a non-zero value in a list of numbers
- Find a name of a particular length in a list of strings
- Find and modify a dictionary in a list of dictionaries based on a certain attribute
In this video course, you’ll explore how best to approach all three scenarios.
[ 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 ]
Tag1 Consulting: On 20 Years of Drupal: an interview with Matthew Saunders
In continuing our 20 years of Drupal series, Tag1 Consulting's, Managing Director Michael Meyers interviews leaders from the Drupal Community who have been instrumental in creating one of the largest open-source communities and one of the most popular Content Management Systems that powers over 3% of the Internet. In this installment, join us for our talk with prolific contributor Matthew Saunders. Currently at Pfizer, Matthew shares his journey into technology by way of the Arts, where he discovered his passion for technology after becoming a Webmaster for an experimental dance company back in 1995. With over 15 years of continuous involvement in the Drupal Community - former board member of the Drupal Association and long-time organizer of Drupalcamp Colorado, we hope you will enjoy this trip down memory lane. --- For a transcript of this video, see On 20 Years of Drupal with Matthew Saunders. --- Photo by Jason Hafso on Unsplash
Read more michaelemeyers Tue, 05/30/2023 - 06:15Matt Glaman: Factories and dependency injection
Last week I wrote about dependency injection anti-patterns in Drupal. These anti-patterns occur when your service's constructor has logic that interacts with the injected dependent services beyond assigning them to properties. These anti-patterns include creating a new object from a factory or retrieving an object from a stack. However, Symfony's service container supports defining services built from factories. This can streamline your code and follow best practices when using dependency injection. Drupal uses this factory service design pattern for cache bins, loggers, and the HTTP client service.