Feeds
Scarlett Gately Moore: KDE: Post Akademy Snap Wrap Up and Future
It has been a very busy couple of weeks in the KDE snap world! Here is a rundown of what has been done:
- Solved issues with an updated mesa in Jammy causing some apps to seg fault by rebuilding our content pack. Please do a snap refresh if this happens to you.
- Resolved our scanner apps not finding any scanners. Skanlite and Skanpage now work as expected and find your scanners, even network scanners!
- Fixed an issue with neochat/ruqola that relaunching the application just hangs https://forum.snapcraft.io/t/neochat-autoconnect-requests/36331 and https://bugs.kde.org/show_bug.cgi?id=473003 by allowing access to system password manager. Still working out online accounts ( specifically ubuntu-sso )
- Fixed issues with QML and styles not being found or set in many snaps.
- Helped FreeCAD update their snap to core22 ( while not KDE, they do use the kde-neon ext ) https://github.com/FreeCAD/FreeCAD-snap/pull/92
- New applications completed – Skrooge – Qrca – massif-visualizer
- Updating applications to 23.04.3 – half way through – unfortunately our priority for launchpad builders is last so it is a bottleneck until I sort out how to get them to bump that up.
- Updated our content pack to latest in snapcraft upstream for the kde-neon extension.
- Various fixes to ease updating our snapcraft files with new releases ( to ease CI automated releases )
An update to the “Very exciting news coming soon”: While everything went well, it is not (yet!) happening. I do not have the management experience the stakeholders are looking for to run the project. I understand completely! I have the passion and project experience, just not management in this type of project. So with that said, are you a KDE/C++ developer with a management background and have a history of bringing projects to the finishline? Are you interested in an exciting new project with new technologies? Talk to me! I can be reached via sgmoore on the various chat channels, sgmoore at kde dot org, or connect via linkedin and message: https://www.linkedin.com/in/scarlettgatelymoore If you know anyone that might be interested, please point them here!
As this project gets further delayed, it leaves me without an income still. If you or someone you know has any short term contract work let me know. Pesky bills and life expenses don’t pay themselves If you can spare some change ( anything helps ) please consider a donation. https://gofund.me/5d0691bc
A big thank you to the community for making my work possible thus far!
FSF News: Happening now: The second round of FSF board candidate discussions
PyBites: When to refactor your code?
How to make refactoring part of your Definition of Done
Photo by rtisanyb on UnsplashWriting code is an iterative process. The first iteration is usually not the best result. Grooming and polishing are needed before the code is ready to share with the world (and your future self).
There is a saying in software development that illustrates the importance of polishing code:
- Make it work
- Make it pretty
- Make it fast
The first step is clear: your code should solve a particular problem.
But what if your program’s input is huge and requires clever code optimizations to reach the required performance?
Maybe you would be tempted to skip step two and jump immediately to step three. If you do so, you’ll find out that trying to improve the performance of unpolished, difficult-to-read spaghetti code, is much harder to do than improving the performance of polished, neatly organized, and readable code.
But what is polished and readable code? How much polishing is enough? And how do you prevent spending too much time on polishing, leaving too little time for solving real problems?
Keep reading to find an answer to these questions!
How functions growAll software that is useful grows. In fact, the more useful a piece of software is, the faster it grows. There is not much developers can do about this growth but they can influence the way in which a codebase grows.
To see how software grows, and in which way it grows, let’s look how a single Python function grows.
The function we’re going to look at measures the volume of a Python codebase. For example, say you want to know the size of a very popular Python repository on GitHub: FastAPI. The function below (count_lines) takes a path as an argument and counts all .py files and the total number of lines of these files:
def count_lines(path): file_count = 0 line_count = 0 for root, dirs, files in os.walk(path): for file in files: if file.lower().endswith('.py'): file_count += 1 with open(os.path.join(root, file), 'r') as codefile: line_count += len(codefile.readlines()) print(f'Found {line_count} lines in {file_count} files.')The function above is only 10 lines of code and is not too difficult to understand. If you run it over the FastAPI repository it will print:
Found 94291 lines in 1167 files.Wow, that’s a lot of code in a lot of files.
Of course not every line in a Python file is a code line, some lines are whitespace or comment lines.
Let’s improve our function to only count lines with code:
def count_lines(path): file_count = 0 line_count = 0 for root, dirs, files in os.walk(path): for file in files: if file.lower().endswith('.py'): file_count += 1 with open(os.path.join(root, file), 'r') as codefile: lines = codefile.readlines() file_line_count = 0 for line in lines: stripped_line = line.strip() if stripped_line == '' or stripped_line[0] == '#': continue file_line_count += 1 line_count += file_line_count print(f'Found {line_count} lines in {file_count} files.')The count_lines function is now 17 lines of code, and the output is:
Found 81673 lines of code in 1167 files.OK, fewer lines but still a pretty large codebase.
Looking at the FastAPI repository we can see that it contains directories with Python files for documentation examples (docs_src), and a large amount of test code appears to be generated.
Let’s add a parameter to our function that can be used to exclude these directories:
Our function has now doubled in size (from 10 to 20 lines of code), but the output is a lot better:
Found 8321 lines of code in 49 files.Besides the total size of a codebase, it’s always interesting to know what the larger files in a codebase are. Let’s extend the reporting part of our function:
def count_lines(path, exclude_dirs): measurements = [] for root, dirs, files in os.walk(path): rel_path = os.path.relpath(root, path) if rel_path.startswith(tuple(exclude_dirs)): continue print(rel_path) for file in files: if file.lower().endswith('.py'): with open(os.path.join(root, file), 'r') as codefile: lines = codefile.readlines() line_count = 0 for line in lines: stripped_line = line.strip() if stripped_line == '' or stripped_line[0] == '#': continue line_count += 1 measurements.append((line_count, os.path.join(rel_path, file))) total_lines = sum([m[0] for m in measurements]) print(f'Found {total_lines} lines of code in {len(measurements)} files.') measurements.sort(reverse=True) for m in measurements[:10]: print(str(m[0]).rjust(4) + ' ' + m[1])This version of the count_lines function has 23 lines of code and outputs the following:
Found 8321 lines of code in 49 files. 1283 fastapi/routing.py 875 fastapi/applications.py 726 fastapi/dependencies/utils.py 708 fastapi/params.py 584 .github/actions/people/app/main.py 530 fastapi/param_functions.py 514 fastapi/_compat.py 480 fastapi/openapi/utils.py 426 fastapi/openapi/models.py 332 .github/actions/notify-translations/app/main.pyApparently fastapi/routing.py is one of the most important code files in the FastAPI repository.
Legacy code and maintainabilityThe example above illustrates how a piece of code grows (from 10, to 17, to 20, to 23 lines of code) through small improvements and new functionalities.
Larger functions, and more code in general, become a bigger and bigger problem as time passes by. Code is read much more often than it is written. Every time an improvement or feature request comes in, a developer (you?) must find his or her way in the codebase to find the location where a change is needed, understand how the existing code works, make the change, and test the change afterward. This is the maintainability problem. In extreme cases, your codebase can become a “legacy” codebase: extremely costly and extremely frustrating to change.
FastAPI is very popular (over 61k stars on GitHub) and a very actively developed codebase. It is not a legacy codebase. However, it also contains a fair share of functions that grew out of hand, like the 177 lines of code get_openapi_pathfunction.
The joy of refactoringRefactoring is fun. When our code works, it’s time to make it pretty.
Pure refactoring techniques — that only change the code structure, not its behavior — go a long way and modern IDEs have great built-in support for them.
Let’s polish our 23 lines of code function by applying a straightforward extract method refactoring and breaking it down into 3 shorter functions:
- measure: 11 lines of code
- count_lines_of_code: 8 lines of code
- generate_report: 8 lines of code
Notice how the refactoring not only improves the naming of our functions but also makes it easier to unit-test the functions in isolation.
The refactored code is listed below:
def measure(path, exclude_dirs): measurements = [] for root, dirs, files in os.walk(path): rel_path = os.path.relpath(root, path) if rel_path.startswith(tuple(exclude_dirs)): continue for file in files: if file.lower().endswith('.py'): with open(os.path.join(root, file), 'r') as codefile: loc = count_lines_of_code(codefile.readlines()) measurements.append((loc, os.path.join(rel_path, file))) print(generate_report(measurements)) def count_lines_of_code(lines): result = 0 for line in lines: stripped_line = line.strip() if stripped_line == '' or stripped_line[0] == '#': continue result += 1 return result def generate_report(measurements): result = '' total_lines = sum([m[0] for m in measurements]) print(f'Found {total_lines} lines of code in {len(measurements)} files.') measurements.sort(reverse=True) for m in measurements[:10]: result += str(m[0]).rjust(4) + ' ' + m[1] + '\n' return result Your Definition of Done: When to Refactor?A Definition of Done provides developers with a clear set of guidelines that define when a piece of code they’ve been working on is “Done” (i.e. ready for inclusion in the mainline of the product). Especially in developer teams a Definition of Done is used to set the bar for new code entering the codebase.
Examples of items on the Definition of Done list are:
- Code is peer-reviewed
- Code-style checks pass
- Unit-tests pass
- Unit-test coverage is higher than 80%
Adding “Code is refactored” to this list prevents the codebase from becoming a legacy codebase. But what is enough refactoring?
In the example above, making a small function slightly bigger does not mean it should be immediately refactored. Premature refactoring (making it pretty) can stand in the way of getting things done (making it work). But at some point, the size of the function becomes a risk to the correctness and future maintenance of the code. This risk can actually be estimated:
- Functions with 1–15 lines of code: no risk (easy code)
- Functions with 16–30 lines of code: low risk (verbose code)
- Functions with 31–60 lines of code: medium risk (hard-to-maintain code)
- Functions with more than 60 lines of code: high risk (unmaintainable code)
Based on the list above you might be tempted to put the limit for functions on 15 lines of code and demand all new code to be refactored until it satisfies this guideline. Unfortunately, perfect can be the enemy of good, like with so many other engineering guidelines. Just as a 100% unit-test coverage is impractical, a hard limit on function size might put developers in a “writers-block” and eventually leads to a rejection of the guideline.
So the question remains: when to refactor?
Software that tells you when to refactor: CodeLimitCodeLimit is a tool for developers with one goal: it tells the developer when it’s time to refactor.
You can compare the concept of Code Limit with a Speed Limit, or really any kind of limit, where the risk increases proportionate to the measurement. These limits keep things safe for yourself and others.
CodeLimit measures the lines of code for each function in your codebase and assigns each function to a category:
- Functions 1–15 lines of code, easy code
- Functions 16–30 lines of code, verbose code
- Functions 31–60 lines of code, hard-to-maintain code
- Functions with more than 60 lines of code, unmaintainable code
A color coding from green to red is used for each category.
Below is a screenshot of CodeLimit with the measurements for FastAPI:
As you can see above FastAPI has 4 functions in the unmaintainable category.
CodeLimit also tells you when refactoring is not needed:
CodeLimit showing measurements for CodeLimit How to run CodeLimitCodeLimit is easy to run on your development environment and requires no configuration if you have a typical Python project setup. Currently, CodeLimit only supports Python, but wider language support will follow soon.
The best way to run CodeLimit is as a pre-commit hook so it alarms you during development when it’s time to refactor:
- repo: https://github.com/getcodelimit/codelimit rev: v0.3.0 hooks: - id: codelimitCodeLimit is intended to be used alongside formatting, linters, and other hooks that improve the consistency and quality of your code, such as Black, Ruff, and MyPy. As an example see the pre-commit-config.yaml from CodeLimit itself.
If you want to explore how function length looks for your codebase, CodeLimit also provides a standalone TUI (Text-based User Interface) that works in any terminal on any platform. To install the standalone version of CodeLimit for your default Python installation run:
python -m pip install codelimit Answering the question: When to Refactor?To quote Martin Fowler: “Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”
Refactoring is a technique that improves the maintainability of your code, not only for others but also for your future self.
Knowing when to refactor and when refactoring is not needed is difficult. Time pressure can cause code to be shipped too early, slowly turning the codebase into a legacy codebase.
Focussing too much on code polishing can lead to frustrating code reviews.
CodeLimit encourages and challenges developers to apply just the right amount of refactoring. It will nudge you when it’s time to refactor and can be part of the team’s Definition of Done. CodeLimit is unlike many of the existing code quality tools, that measure a plethora of things. Instead, CodeLimit does one thing: tell you when it’s time to refactor.
Get started today with CodeLimit: https://github.com/getcodelimit/codelimit
EuroPython Society: EuroPython 2023 Code of Conduct Transparency Report
The 2023 version of the EuroPython conference took place both online and in person in July 2023. This was the first conference under our new Code of Conduct (CoC), and we had Code of Conduct working group members continuously available both online and in person.
ReportsWe received three reports, only one of which was actionable:
- An in person attendee pointed out that the original wifi password for the venue had “derogatory, sexist and potentially misogynistic” connotations in some variants of English slang, which the creators of that password were unaware of. Once this was pointed out, the password was changed to a more neutral one which took effect at the beginning of the next day.
- There were various reports of attendees being rude to conference volunteers when they were not allowed to enter conference rooms that were at capacity. No specific individuals were identified or reported, so the response at the recommendation of the CoC WG was a forceful reminder at the start of each day that all attendees be mindful of the CoC and respectful of the volunteers.
- There were reports catering staff being overheard to be rude to attendees asking about vegetarian/vegan food options. The response from the conference staff, with the support of the CoC WG, was to speak to the catering management to prevent re-occurrence.
Parabola GNU/Linux-libre: [From Arch]: budgie-desktop >= 10.7.2-6 update requires manual intervention
When upgrading from budgie-desktop 10.7.2-5 to 10.7.2-6, the package mutter43 must be replaced with magpie-wm, which currently depends on mutter. As mutter43 conflicts with mutter, manual intervention is required to complete the upgrade.
First remove mutter43, then immediately perform the upgrade. Do not relog or reboot between these steps.
pacman -Rdd mutter43
pacman -Syu
Web Review, Week 2023-32
Let’s go for my web review for the week 2023-32.
The Legacy of Bram Moolenaar - Jan van den BergTags: tech, vim
Nice words about Bram Moolenaar maintainer of vim who passed away recently.
https://j11g.com/2023/08/07/the-legacy-of-bram-moolenaar/
Tags: tech, unix, linux, redhat, history
Don’t be fooled of the title. Yes, it concludes about an opinion piece about the latest changes in policy around RHEL. Still, it starts with a very nice retelling of the history around UNIX and computing since the 70s. This is an invaluable resource.
https://www.lpi.org/blog/2023/07/30/ibm-red-hat-and-free-software-an-old-maddogs-view/
Tags: tech, google, browser, surveillance, attention-economy
Excellent piece against the Web Environment Integrity proposal from Google.
https://www.eff.org/deeplinks/2023/08/your-computer-should-say-what-you-tell-it-say-1
Tags: tech, cloudflare, google, surveillance, attention-economy
This is based on fingerprinting and sometimes fail. If Web Environment Integrity gets through it’ll be just worse.
https://jrhawley.ca/2023/08/07/blocked-by-cloudflare
Tags: tech, foss, politics, criticism
Definitely this. There’s still so much to achieve through FOSS, lots of missed opportunities. The mentioned factors clearly played a huge part in the current situation.
https://idiomdrottning.org/foss-dystopia
Tags: tech, browser, web
Indeed, too many websites or apps break or hijack basic features of the browser. To me it also shows the tension between trying to have a document browser and an application provider shoved in the same GUI.
https://heather-buchel.com/blog/2023/07/just-normal-web-things/
Tags: tech, programming, python
Definitely a clever combination of two Python constructs.
https://www.bitecode.dev/p/python-cocktail-mix-a-context-manager
Tags: tech, 3d, floats
Good explanations of why you might want to revert the Z axis on your projection matrices. Of course it boils down to how float precision works.
https://tomhultonharrop.com/mathematics/graphics/2023/08/06/reverse-z.html
Tags: tech, remote-working, management, communication
Kind of overlooking the cost of producing videos in my opinion. That being said, if you keep videos out of the picture this little article is spot on. Remote work is about more asynchronous and longer form communication first.
https://ben.balter.com/2023/08/04/remote-work-communicate-more-with-less/
I’m taking another short break, so no web review next week!
Bye for now!
Real Python: The Real Python Podcast – Episode #168: Common Python Stumbling Blocks & Quirky Behaviors
Have you ever encountered strange behavior when trying something new in Python? What are common quirks hiding within the language? This week on the show, Christopher Trudeau is here, bringing another batch of PyCoder's Weekly articles and projects.
[ 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 ]
LN Webworks: Step-by-Step Guide: Adding Google Directions Module to Drupal
Drupal, with its robust API-first approach, opens up a world of possibilities for seamless communication with various Google services. Amongst all, the Google Directions API stands out as a powerful tool for providing accurate navigation and route planning services. Leveraging Drupal's capabilities, integrating the Google Directions API becomes even more accessible and efficient.
Before we delve into the Google Directions Module for Drupal development and learn how to implement it, let’s understand Google Direction Module and the crucial prerequisites that would get you prepared.
Birger Schacht: Another round of rust
A couple of weeks ago I had to undergo surgery, because one of my kidneys malfunctioned. Everything went well and I’m on my way to recovery. Luckily the most recent local heat wave was over just shortly after I got home, which made being stuck at home a little easier (not sure yet when I’ll be allowed to do sports again, I miss my climbing gym…).
At first I did not have that much energy to do computer stuff, but after a week or so I was able to sit in front of the screen for short amounts of time and I started to get into writing Rust code again.
carlThe first thing I did was updating carl. I updated all the dependencies and switched the dependency that does coloring from ansi_term, which is unmaintained, to nu-ansi-term. When I then updated the clap dependency to version 4 I realized that clap now depends on the anstyle crate for text styling - so I updated carls coloring code once again so it now uses anstyle, which led to less dependencies overall. Implementing this change I also did some refactoring of the code.
carl how also has its own website as well as a subdomain1.
I also added a couple of new date properties to carl, namely all weekdays as well as odd and even - this means it is now possible choose a separate color for every weekday and have a rainbow calendar:
This is included in version 0.1.0 of carl, which I published on crates.io.
typelerateThen I started writing my first game - typelerate. It is a copy of the great typespeed, without the multiplayer support.
To describe the idea behind the game, I quote the typespeed website:
Typespeed’s idea is ripped from ztspeed (a DOS game made by Zorlim). The Idea behind the game is rather easy: type words that are flying by from left to right as fast as you can. If you miss 10 or more words, game is over.
Instead of the multiplayer support, typelerate works with UTF-8 strings and it also has another game mode: in typespeed you only type whats scrolling via the screen. In typelerate I added the option to have one or more answer strings. One of those has to be typed instead of the word flying across the screen. This lets you implement kind of an question/answer game. To be backwards compatible with the existing wordfiles from typespeed2, the wordfiles for the question/answer games contain comma separated values. The typelerate repository contains wordfiles with Python and Rust keywords as well as wordfiles where you are shown an Emoji and you have to type the corresponding Github shortcode. I’m happy to add additional wordfiles (there could be for example math questions…).
marsroverAnother commandline game I really like, because I am fascinated by the animated ASCII graphics, is the venerable moon-buggy. In this game you have to drive a vehicle across the moon’s surface and deal with obstacles like craters or aliens.
I reimplemented the game in rust and called it marsrover:
I published it on crates.io, you can find the repository on github. The game uses a configuration file in $XDG_CONFIG_HOME/marsrover/config.toml - you can configure the colors of the elements as well as the levels. The game comes with four levels predefined, but you can use the configuration file to override that list of levels with levels with your own properties. The level properties define the probabilities of obstacles occuring on your way on the mars surface and a points setting that defines how many points the user can get in that level (=the game switches to the next level if the user reaches the points).
[[levels]] prob_ditch_one = 0.2 prob_ditch_two = 0.0 prob_ditch_three = 0.0 prob_alien = 0.5 points = 100After the last level, the game generates new ones on the fly.
-
thanks to the service from https://cli.rs. ↩︎
-
actually, typelerate is not backwards compatible with the typespeed wordfiles, because those are not UTF-8 encoded ↩︎