Feeds
Initial work on Keychain
A month ago, I started working on a new application to manage your passwords in Plasma. And while still at a PoC status, this weekend, it finally started to look like something almost usable, so it sounded like a good occassion to write a small blog post about it.
The current name is “Keychain” or “Plasma Keychain” but this is subject to change and suggestions are more than welcome.
My end goal is to provide a more future proof replacement to the ageing KWallet application. From a technical point of view, this is a fork of the internal of KeepassXC with a Kirigami GUI completely written from scratch. This means it uses the standardized Keepass format to store the passwords in the database which is implemented by many applications including on other platforms like Android and iOS (see the list of Keepass port). And while not yet exposed in the GUI, basing the work on top of KeepassXC enables a lot of interesting features not available in KWallet, like Yubikey and PassKey support, password sharing, export and import for various other password database formats, TOTP support and browser integration…
While also providing vital features for the desktop integration like the Freedesktop Secret Service protocol what we also have in KWallet.
Here are some screenshots of the current state.
This is the main view where viewing, adding, editing and removing entries already work.
This is the database generator page which unfortunately doesn’t work yet.
And this is the UI to open an existing database.
As you can see there is still a lot of work required, so if people are interested to help or to take a look at the current progress, the code is on KDE’s gitlab instance.
Mario Hernandez: Components variations in Storybook
One great way to extend your catalog of components is by creating components variations. Variations, in the context of component-driven development, refers to displaying your content in different ways. Variations of a component reduce the need of building new components as well as duplicate code.
In Storybook, variations are known as Stories. In this post I will be using variations and stories interchangeably.
The image below shows how different card stories or variations, can display the same content in many ways.
Fig. 1: Example of multiple variations of a Card component.
Principles of building componentsSometimes when building a new component, we can't anticipage how the website will evolve with time and therefore we build components the best way possible at the time of building them. As time goes by and requirements change, we realize that we could have done things differently had we known about the requirements changes. Variations of a component give you a chance to alter how something was built without having to change your entire environment of content architecture.
Some time ago I wrote about principles for building components. Rather than repeating myself, take a quick look at the article and comeback when you are done. You will find those principles not only apply to building new components, but also to building variations of components.
Building component variations in StorybookIn Storybook, all variations of a component are referred to as "Stories", hence the name Storybook. A story captures the rendered state of a UI component. Developers write multiple stories per component that describe all the “interesting” states/variations a component can support. Here's a visual that describes the official naming and hierarchy Storybook uses.
Fig. 2: Storybook's official naming convention and hierarchy.
The Card componentFirst off, I am going with the assumption that you already know how Storybook stories are created and that you have a Storybook instance running. If that's not the case, follow these instructions to get your Storybook environment up and running. You will need NodeJS 20+ and NVM installed on your system to follow along.
Next, let's look at the Card variations we will be creating in this post.
Fig. 3: Example of the different card variations we will build in this post.
The image above shows the Card stories or variations we will build. From top-left to right:
- Default or Stacked
- Light CTA
- Small
- No image
- Horizontal
In the interest of time, I have a repo that already includes the base of the Card component so you can focus only on building the variations.
-
Clone the repo which already contains a project to work with and the Card component.
If you already have a working Storybook environment, copy the components directory (src/components), from the newly cloned repo, into your project. -
Switch to the variations branch by running git checkout variations
-
Run the project as instructed in the README in the repo
In this tutorial, we will use two methods for creating variations in Storybook:
- Doing all the work directly in card.stories.jsx to change fields values or hide/show fields, depending on the story requirements.
- Using additional *.yml files to assist with the same fields updates above.
We will be using the first method above for all stories except the Card horizontal. The original Card component was built with Twig, but for the variations we will be working exclusively in card.stories.jsx. The current version of the card story looks like this:
import parse from 'html-react-parser'; import card from './card.twig'; import data from './card.yml'; import './card.css'; const component = { title: 'Molecules/Card', render: (args) => parse(card(args)), }; export const Card = { name: 'Card stacked', args: { ...data }, }; export default component;Let me explain the snippet above as this is the foundation for all the variations we will be creating.
-
First we do a series of imports to collect all the pieces needed to build components and stories:
- import parse: This is a react plugin which allows us to parse the HTML in our stories into React code Storybook can understand.
- import card: It imports all the code and logic inside our component's twig template.
- import data: Pulls in all the data from the component's .yml file so we can use it as React args.
- import './card.css': Imports all CSS styles so Storybook can displayed the styled components and stories. Inside card.css, we already have styles for each of the stories we will be building.
-
Next, we set a new configuration object called component, which will serve as the default instance of the card component. This is an arbitrary name and can be anything that makes sense to you.
Inside the component object we have two properties: title and render.- The title property's value determines the location and name of the component within Storybook's hierarchy. In this example the Card component will be located under the Molecules folder. See Fig.2 above for details about the hierarchy.
- The render property is what handles the rendering of the component by using the card and data objects we imported earlier, and combined together (Twig and YML), they render the full component.
-
Next, we create our first story by defining a new configuration object called Card, in which we pass a name (Card stacked), for the story and the data variable as args.
-
Finally, we export the component object as default, which is a React requirement.
If Storybook is running, you should see the new variation which will display the Card stacked. If you need to run Storybook for the first time, in your command line navigate to the storybook directory and run these commands:
IMPORTANT: You need NodeJS 20+ and NVM installed in your system. nvm install npm install npm run build npm run storybookIf all goes well, Storybook should be running showing the Card stacked story under the Molecules folder.
Preview of Card stackedFig. 4: Example of the Card stacked from which other variations will originate.
Card with light CTA- Inside card.stories.jsx, and directly after the closing of the Card object (around line 17), add the following object to create a new story:
Let's go over the snippet above:
- We start by creating and exporting a new object called CardLightCta. This is a new story. This name is arbitrary but it should be unique for each story.
- Next, we pass the default Card story (...Card), as a spread operator, so the new story inherits all attributes from the original card.
- The name property allows for each story to have a unique name which will appear directly under the component name in Storybook's sidebar (see Fig. 2 at the top for details).
- Finally, we open the args object where we will update some of the fields to achieve the desired variation:
- We pass the ...data object as a spread operator to individually update the fields that need updating.
- Since the only difference between this variation and the original card is that the CTA is light, we need to define the cta object and provide each of its properties with the appropriate values:
- First as a modifier class we pass button--light. This is a predefined modifier class which will turn the CTA white.
- Next, we type the text that will become the CTA's label, Try it now.
- And finally, we pass a URL to the CTA.
Fig. 5: Example of a Card component with a light CTA.
Card smallThis next story or variation is the small version of the card. The difference between this card and the original one is that this one has no CTA, and its size is ...well, small 🙂
Same as before, add the following snippet to card.stories.jsx directly after the closing of the card with light CTA story:
export const CardSmall = { ...Card, name: 'Card small', args: { ...data, modifier: 'card--small', cta: '', }, };This story is very similar to the previous one from the updates needed point of view. As you can see, the only thing we are doing is passing card--small as a modifier class to the entire component, and since we don't need a button or CTA, we are defining the cta object but its value is empty which will suppress it from printing on the page. If you notice in card.twig, we use a conditional that checks if the cta object exists, otherwise don't print any of the markup starting with the footer tag.
Preview of small cardFig. 6: Example of a small card.
Card with no image- You know the drill, inside card.stories.jsx, directly after the closing of the previous story, add the following snippet:
Even more similar to the previous story, this variation only varies from the original story as follows:
- We are passing a modifier class to the component, card--no-image.
- Since we want no image, we define the image object but leave its value empty.
Fig. 6: Example of a card without image.
Card horizontalThe final variation is the Card horizontal. For all previous variations we have done all the changes inside card.stories.jsx, but for this one, we will resource to using an alternative *.yml file. Why you may ask, well, this variation requires a bit more changes and making all those changes inside the stories.jsx file may look a little too busy and not as easy to read the code. That's pretty much the only reason for me to use this method, to keep the code in my stories clean and more readable.
You may have noticed in the project you cloned; inside the card directory we have a file called card-horizontal.yml. This file is almost identical to the original card.yml as far as the fields in it. The only difference is that some of the fields have unique content or no content at all. Let's look at the file before starting.
--- modifier: 'card--horizontal' image: <img src="/card-square.jpg" alt="Palm trees near city buildings" /> title: level: 2 modifier: 'card__title' text: 'Step outside to the outdoors' url: 'https://mariohernandez.io' teaser: 'With spring in full bloom, the weather could not be better to take a walk outside and enjoy the beauty of nature.' cta: ''- The modifier field has a specific CSS class we will pass: card--horizontal. This class will allow us to change the layout of the card to be in horizontal direction.
- The image field uses a different image altogether. The image has been cropped in square aspect ratio for better fitting of this variation.
- Finally, the cta field is empty, meaning we don't want to print a button on this variation.
Maybe I exaggerated when I said that this variation has too many changes, but my point is that in cases when your stories do require a lot of changes, using a different yml file may help you keep your stories.jsx file a lot neater and cleaner.
- The first step is one we haven't done before. Inside card.stories.jsx somewhere around line 5 (after the last import in the file), add the following import:
- Next, the way we've done before, inside card.stories.jsx add the following object directly after the closing of the last story:
- First we imported a new data file called card-horizontal.yml and assigned the object name of dataHorizontal. By doing this, any changes we make inside card-horizontal.yml will be reflected in Storybook.
- Lastly, we repeat the same process as the previous variations but this time, inside the args object, we pass the new object we created in the previous step (...dataHorizontal), rather than ...data.
- That's it. Our story file is nice and clean. Since we handled all the fields updates in card-horizontal.yml, the .jsx file is simply consuming its data to achieve the desired variations.
Fig. 6: Example of a card in horizontal layout.
Now that we have covered both methods for creating variations, know that neither method is better than the other. The decision to use one over the other boils down to personal preferences and sometimes which makes the most sense to simplify the process.
End resultAt the end of this process, your card.stories.jsx should look like this:
import parse from 'html-react-parser'; import card from './card.twig'; import data from './card.yml'; import dataHorizontal from './card-horizontal.yml'; import './card.css'; const component = { title: 'Molecules/Card', render: (args) => parse(card(args)), }; export const Card = { name: 'Card stacked', args: { ...data }, }; export const CardLightCta = { ...Card, name: 'Card light CTA', args: { ...data, cta: { modifier: 'button--light', text: 'Try it now', url: 'https://mariohernandez.io', } }, }; export const CardSmall = { ...Card, name: 'Card small', args: { ...data, modifier: 'card--small', cta: '', }, }; export const CardNoImage = { ...Card, name: 'Card no image', args: { ...data, modifier: 'card--no-image', image: '', }, }; export const CardHorizontal = { ...Card, name: 'Card horizontal', args: { ...dataHorizontal, }, }; export default component; In closingThis only touches the surface of creating stories, but it is refreshing to know that no matter how complex your components may be, when it comes to having Storybook parse them, the React code in your stories is very minimum. Certainly, there are exceptions, but as I complete the migration of our large Drupal project with many components, some of which are pretty large and complex, we still were surprised how little React code was required of us to write because all the heavy lifting is being done by Storybook, with its contrib extensions, as well as Twig itself.
poke @ Savannah: GNU poke 4.2 released
I am happy to announce a new release of GNU poke, version 4.2.
This is a bugfix release in the 4.x series.
See the file NEWS in the distribution tarball for a list of issues
fixed in this release.
The tarball poke-4.2.tar.gz is now available at
https://ftp.gnu.org/gnu/poke/poke-4.2.tar.gz.
> GNU poke (http://www.jemarch.net/poke) is an interactive, extensible
> editor for binary data. Not limited to editing basic entities such
> as bits and bytes, it provides a full-fledged procedural,
> interactive programming language designed to describe data
> structures and to operate on them.
Thanks to the people who contributed with code and/or documentation to
this release.
Happy poking!
Mohammad-Reza Nabipoor
TestDriven.io: Reusable Components in Django with Stimulus and Tailwind CSS - Part 1
Joachim Breitner: Do surprises get larger?
Imagine you are living on a riverbank. Every now and then, the river swells and you have high water. The first few times this may come as a surprise, but soon you learn that such floods are a recurring occurrence at that river, and you make suitable preparation. Let’s say you feel well-prepared against any flood that is no higher than the highest one observed so far. The more floods you have seen, the higher that mark is, and the better prepared you are. But of course, eventually a higher flood will occur that surprises you.
Of course such new record floods are happening rarer and rarer as you have seen more of them. I was wondering though: By how much do the new records exceed the previous high mark? Does this excess decrease or increase over time?
A priori both could be. When the high mark is already rather high, maybe new record floods will just barley pass that mark? Or maybe, simply because new records are so rare events, when they do occur, they can be surprisingly bad?
This post is a leisurely mathematical investigating of this question, which of course isn’t restricted to high waters; it could be anything that produces a measurement repeatedly and (mostly) independently – weather events, sport results, dice rolls.
The answer of course depends on the distribution of results: How likely is each possible results.
Dice are simpleWith dice rolls the answer is rather simple. Let our measurement be how often you can roll a die until it shows a 6. This simple game we can repeat many times, and keep track of our record. Let’s say the record happens to be 7 rolls. If in the next run we roll the die 7 times, and it still does not show a 6, then we know that we have broken the record, and every further roll increases by how much we beat the old record.
But note that how often we will now roll the die is completely independent of what happened before!
So for this game the answer is: The excess with which the record is broken is always the same.
Mathematically speaking this is because the distribution of “rolls until the die shows a 6” is memoryless. Such distributions are rather special, its essentially just the example we gave (a geometric distribution), or its continuous analogue (the exponential distributions, for example the time until a radioactive particle decays).
Mathematical formulationWith this out of the way, let us look at some other distributions, and for that, introduce some mathematical notations. Let X be a random variable with probability density function φ(x) and cumulative distribution function Φ(x), and a be the previous record. We are interested in the behavior of
Y(a) = X − a ∣ X > x
i.e. by how much X exceeds a under the condition that it did exceed a. How does Y change as a increases? In particular, how does the expected value of the excess e(a) = E(Y(a)) change?
Uniform distributionIf X is uniformly distributed between, say, 0 and 1, then a new record will appear uniformly distributed between a and 1, and as that range gets smaller, the excess must get smaller as well. More precisely,
e(a) = E(X − a ∣ X > a) = E(X ∣ X > a) − a = (1 − a)/2
This not very interesting linear line is plotted in blue in this diagram:
The expected record surpass for the uniform distributionThe orange line with the logarithmic scale on the right tries to convey how unlikely it is to surpass the record value a: it shows how many attempts we expect before the record is broken. This can be calculated by n(a) = 1/(1 − Φ(a)).
Normal distributionFor the normal distribution (with median 0 and standard derivation 1, to keep things simple), we can look up the expected value of the one-sided truncated normal distribution and obtain
e(a) = E(X ∣ X > a) − a = φ(a)/(1 − Φ(a)) − a
Now is this growing or shrinking? We can plot this an have a quick look:
The expected record surpass for the normal distributionIndeed it is, too, a decreasing function!
(As a sanity check we can see that e(0) = √(2/π), which is the expected value of the half-normal distribution, as it should.)
Could it be any different?This settles my question: It seems that each new surprisingly high water will tend to be less surprising than the previously – assuming high waters were uniformly or normally distributed, which is unlikely to be helpful.
This does raise the question, though, if there are probability distributions for which e(a) is be increasing?
I can try to construct one, and because it’s a bit easier, I’ll consider a discrete distribution on the positive natural numbers, and consider at g(0) = E(X) and g(1) = E(X − 1 ∣ X > 1). What does it take for g(1) > g(0)? Using E(X) = p + (1 − p)E(X ∣ X > 1) for p = P(X = 1) we find that in order to have g(1) > g(0), we need E(X) > 1/p.
This is plausible because we get equality when E(X) = 1/p, as it precisely the case for the geometric distribution. And it is also plausible that it helps if p is large (so that the next first record is likely just 1) and if, nevertheless, E(X) is large (so that if we do get an outcome other than 1, it’s much larger).
Starting with the geometric distribution, where P(X > n ∣ X ≥ n) = pn = p (the probability of again not rolling a six) is constant, it seems that these pn is increasing, we get the desired behavior. So let p1 < p2 < pn < … be an increasing sequence of probabilities, and define X so that P(X = n) = p1 ⋅ ⋯ ⋅ pn − 1 ⋅ (1 − pn) (imagine the die wears off and the more often you roll it, the less likely it shows a 6). Then for this variation of the game, every new record tends to exceed the previous more than previous records. As the p increase, we get a flatter long end in the probability distribution.
Gamma distributionTo get a nice plot, I’ll take the intuition from this and turn to continuous distributions. The Wikipedia page for the exponential distribution says it is a special case of the gamma distribution, which has an additional shape parameter α, and it seems that it could influence the shape of the distribution to be and make the probability distribution have a longer end. Let’s play around with β = 2 and α = 0.5, 1 and 1.5:
The expected record surpass for the gamma distributionFor α = 1 (dotted) this should just be the exponential distribution, and we see that e(a) is flat, as predicted earlier.
For larger α (dashed) the graph does not look much different from the one for the normal distribution – not a surprise, as for α → ∞, the gamma distribution turns into the normal distribution.
For smaller α (solid) we get the desired effect: e(a) is increasing. This means that new records tend to break records more impressively.
The orange line shows that this comes at a cost: for a given old record a, new records are harder to come by with smaller α.
ConclusionAs usual, it all depends on the distribution. Otherwise, not much, it’s late.
Sebastian Pölsterl: scikit-survival 0.23.0 released
I am pleased to announce the release of scikit-survival 0.23.0.
This release adds support for scikit-learn 1.4 and 1.5, which includes missing value support for RandomSurvivalForest. For more details on missing values support, see the section in the release announcement for 0.23.0.
Moreover, this release fixes critical bugs. When fitting SurvivalTree, the sample_weight is now correctly considered when computing the log-rank statistic for each split. This change also affects RandomSurvivalForest and ExtraSurvivalTrees which pass sample_weight to the individual trees in the ensemble. Therefore, the outputs produced by SurvivalTree, RandomSurvivalForest, and ExtraSurvivalTrees will differ from previous releases.
This release fixes a bug in ComponentwiseGradientBoostingSurvivalAnalysis and GradientBoostingSurvivalAnalysis when dropout is used. Previously, dropout was only applied starting with the third iteration, now dropout is applied in the second iteration too.
Finally, this release adds compatibility with numpy 2.0 and drops support for Python 3.8.
Installscikit-survival is available for Linux, macOS, and Windows and can be installed either
via pip:
pip install scikit-survivalor via conda
conda install -c conda-forge scikit-survivalPython GUIs: PyQt6, PySide6, PyQt5 and PySide2 Books -- updated for 2024! — Extended and updated with new examples, demos including Model View Controller architecture
Hello! Today I have released new digital updates to my PyQt5, PyQt6, PySide2 and PySide6 book Create GUI Applications with Python & Qt.
This update brings all versions up to date with the latest developments in Qt, As well as corrections and additions to existing chapters, there are new sections dealing with form layouts, built-in dialogs and developing Qt applications using a Model View Controller (MVC) architecture.
As always, if you've previously bought a copy of the book you get these updates for free! Just go to the downloads page and enter the email you used for the purchase.
You can buy the latest editions below --
- PyQt6 Book 5th Edition, Create GUI Applications with Python & Qt6
- PySide6 Book, 5th Edition, Create GUI Applications with Python & Qt6
- PyQt5 Book 5th Edition, Create GUI Applications with Python & Qt5
- PySide2 Book 5th Edition, Create GUI Applications with Python & Qt5
If you bought the book elsewhere (in paperback or digital) you can register to get these updates too. Email your receipt to register@pythonguis.com
Enjoy!
KDE participates in OSPP 2024
We are pleased to announce our participation in the Open Source Promotion Plan (OSPP) 2024. KDE will mentor a project within this program. OSPP is largely organized by The Institute of Software at the Chinese Academy of Sciences. Its goal is to encourage college students to engage in developing and maintaining open-source software.
This marks KDE Community's first year participate in OSPP, and we mentor a project.
Porting KDE Games to the Android PlatformKDE Games and educational games are integral parts of the KDE Gear suite. This year, under the guidance of Benson Muite, Hanyang Zhang will undertake work in this area. Hanyang Zhang will be responsible for porting one to two KDE Games to the Android platform.
Let's warmly welcome the new contributor and wish them a enjoyable summer within KDE!
My work in KDE for June 2024
Hello! I intentionally skipped last month because I was busy with other tasks, and I didn’t have much to discuss KDE-wise. Anyway, let’s get started:
AkademyI have booked my travel plans for Akademy 2024, and hopefully this time my travel will be uneventful. I’ll be attending QtCS 2024 in Würzburg too. At the time of writing, the program has not been announced yet - so I’m not sure if I’m giving a talk yet, but fingers crossed 🤞
Art on WaylandA common problem with artists inquiring about the KDE Wayland session is that a lot of information is passed down. Some of the information is clearly out of date, and it spreads like wildfire. On top of that, factual information is scattered across multiple wiki pages, forum posts, and chat messages. I wrote up a page (personally maintained by me, mind) hosted at https://artonwayland.redstrate.com/. (If all goes well, I hope to retire this page in a year or two.)
In terms of software, gsetwacom was recently released by Peter Hutterer. So, I created our own (intentionally a seperate tool), called ktabletconfig. I personally don’t have a use for this tool, but I wanted to create it anyway. I hope it serves someone well!
I do plan on expanding ktabletconfig’s features, as the Wayland session continues to mature.
PlasmaFeature I merged the tablet tester, finally! Thanks to Nate for pushing it past the finish line, as always. 6.2
A slightly out of date screenshot of the TesterFeature Clearly explain what left-handed mode does in the Tablet KCM, because even I didn’t know until I looked it up! 6.2
Feature Rebased and merged Aki Sakurai’s “Map to Workspace” (aka all monitors) feature for the Tablet KCM. 6.2
Bugfix I also fixed the wrong aspect ratio for the output preview in the Tablet KCM. Now mapping between 4:3 and 16:9 screens should make more sense in the UI. 6.1
Bugfix Went through the whole Tablet KCM and cleaned up the terms we use. It’s a small thing, but I hope it makes the features we have more understandable. 6.2
FrameworksFeature I have begun adding a way for Kirigami applications to save and restore window state like our QtWidget applications do. I have stalled on it because of something else, but this is something I want to finish soon. ???
Feature Added a generic “translate” icon for applications based on the crow-translate icon we already have. 6.4
TokodonFeature I finished up and merged quoted posts support! I’m also pretty happy with the implementation. 24.08
Quoted posts are now “supported” in Tokodon, at least with what we can do KritaBugfix Fixed the “DEV BUILD” badge going to a 404. 5.2.3
Bugfix Fix the lag in the tablet tester when using it with a S-Pen on Android. 5.2.3
Bugfix Multiple small improvements for the S-Pen on Android. 5.2.3
I changed up some of the text and mentioned S9 family support here now! NeoChatBugfix Prevented the location map showing up even though no locations were shared. That also fixes copyright link activation! 24.05
Bugfix Fixed the QR code not showing up on the account page. 24.05
Bugfix Added a focus border to the appearance page modes, which helps users who solely depend on the keyboard. (It was navigable before, but you would have no idea which one was selected.) 24.05
Bugfix Removed room members being highlighted on tap. This makes the member list appear slightly less buggy. 24.05
Feature Added basic keyboard navigation for the server selection popup. 24.05
Bugfix Fixed keyboard navigation in the space drawer. 24.05
Bugfix Fixed keyboard navigation on the room & user search pages. 24.05
OtherBugfix Fixed keyboard navigation for Kirigami Add-on’s FormComboBoxDelegate, which improves keyboard navigation in lots of Kirigami applications! 1.3.0
I updated the Plasma Desktop README in line with the other README things I did this year!
My work in KDE for April 2024 HomeZero to Mastery: Python Monthly Newsletter 💻🐍
Awesome Python Applications: aider
aider: Console-based LLM pair programming tool, to edit code in your local git repository.
Links:
Awesome Python Applications: napar
napar: A fast, interactive, multi-dimensional image viewer for annotation and analysis of large images.
Links:
Awesome Python Applications: Plane
Plane: Modern, self-hostable issue and product roadmap tracker. An alternative to JIRA, Linear, and Asana.
Links:
Russ Allbery: Review: Bitter Angels
Review: Bitter Angels, by C.L. Anderson
Publisher: Ballantine Books Copyright: 2009 ISBN: 0-553-59217-3 Format: Mass market Pages: 438Bitter Angels is a stand-alone science fiction novel. It won the Philip K. Dick award for best SF original paperback in 2010. C.L. Anderson is a pen name for Sarah Zettel.
Terese was a Guardian, one of the agents of the Pax Solaris who find ways to keep the peace in troubled systems and high-stress situations with the help of an implanted Companion, an assistant AI. Forty years ago, on one of those missions, she was captured and her Companion was forcibly removed. She was rescued by her friend and mentor and retired afterwards, starting a new life and a new family, trying to leave the memories behind.
Now, the woman who rescued her is dead. She was murdered on duty in the Erasmus system, a corporate hellhole that appears to be on the verge of exploding into a political hot spot. Bianca's last instructions asked for Terese to replace her. Terese's family is furious at her for even considering returning to the Guardians, but she can't say no. Duty, and Bianca's dying request, call too strongly.
Amerand is Security on Dazzle, one of the Erasmus stations. He is one of the refugees from Oblivion, the station that the First Bloods who rule the system let die. He keeps his head above water and tries to protect his father and find his mother without doing anything that the ever-present Clerks might find concerning. Keeping an eye on newly-arriving Solaris saints is a typical assignment, since the First Bloods don't trust the meddling do-gooders. But something is not quite right, and a cryptic warning from his Clerk makes him even more suspicious.
This is the second book by Sarah Zettel that I've read, and both of them have been tense, claustrophobic thrillers set in a world with harsh social inequality and little space for the characters to maneuver. In this case, the structure of her future universe reminded me a bit of Iain M. Banks's Culture, but with less advanced technology and only humans. The Pax Solaris has eliminated war within its borders and greatly extended lifespans. That peace is maintained by Guardians, who play a role similar to Special Circumstances but a bit more idealist and less lethal. They show up where there are problems and meddle, manipulating and pushing to try to defuse the problems before they reach the Pax Solaris.
Like a Culture novel, nearly all of the action takes place outside the Pax Solaris in the Erasmus system. Erasmus is a corporate colony that has turned into a cross between a hereditary dictatorship and the Corporate Rim from Martha Wells's Murderbot series. Debt slavery is ubiquitous, economic inequality is inconceivably vast, and the Clerks are everywhere. Erasmus natives like Amerand have very little leeway and even fewer options. Survival is a matter of not drawing the attention of the wrong people. Terese and her fellow Guardians are appalled, but also keenly aware that destabilizing the local politics may make the situation even worse and get a lot of people killed.
Bitter Angels is structured like a mystery: who killed Bianca, and what was her plan when she was killed? Unlike a lot of books of this type, the villains are not idiots and their plan is both satisfyingly complex and still depressingly relevant. I don't think I'm giving anything away by saying that I have read recent news articles about people with very similar plans, albeit involving less science-fiction technology. Anderson starts with a tense situation and increases the pressure relentlessly, leaving the heroes one step behind the villains for almost the entire novel. It is not happy or optimistic reading — at times, the book is quite dark — but it certainly was engrossing.
The one world-building quibble that I had is that the Erasmus system is portrayed partly as a hydraulic empire, and while this is arguably feasible given that spaceship travel is strictly controlled, it seemed like a weird choice given the prevalence of water on the nearby moons. Water smuggling plays a significant role in the plot, and I wasn't entirely convinced of the politics and logistics behind it. If this sort of thing bugs you, there are some pieces that may require suspension of disbelief.
Bitter Angels is the sort of tense thriller where catastrophe is barely avoided and the cost of victory is too high, so you will want to be in the mood for that before you dive in. But if that's what you're looking for, I thought Anderson delivered a complex and satisfying story.
Content warning: major character suicide.
Rating: 7 out of 10
Spinning Code: Knowing When to Ask for Help
One of the skills everyone needs to have is asking for help. Whether that’s in our work, our education, or our personal lives, we all need help from time to time. We are focused on work here, but this same basic rules apply in all aspects of our lives.
The right time to ask for help is, like so many things, a balancing act. Struggling through a complex issue can be a great way to learn something new. But often we can short cut that learning by simply asking the right questions at the right time.
On the flip side, if we ask too early not only do we risk missing a chance to build deep understanding, we also risk frustrating colleagues by asking them to do our job.
One short cut for when you need to ask for help is if another team member asks if you have already asked. Generally, I want to have called for support before my PM suggests it. By then they are frustrated that I haven’t already solved whatever the issue is solo.
Signs You Might Need HelpGiven my current role and skill set, I’m often the person who gets called when a project goes sideways. That means I see a lot of places where someone didn’t call for help until they were in crisis. While that’s going to happen to us all from time to time, it’s better to call for help when the problem is small. If you want until the project starts burning down around you, it’s way too late.
You might need help if:
- You have absolutely no idea what to do next.
- You are about to re-design a large portion of your project to get around a challenge.
- You have spent more than a day pounding on a problem without success.
- You are avoiding working on a task, because you don’t know how to get started.
- You are about to use a mode/tool/technique that everyone says is a bad idea.
- In Salesforce that can mean things like:
- loading data in serial mode
- setting batch size to 1
- using view all data in your tests.
- In Drupal that can mean things like:
- hacking a module
- loading data in the theme layer
- writing raw SQL queries
- In Salesforce that can mean things like:
As I said before, asking for help is a balance: you can wait too long, or you can ask too soon. The real trick is hitting the sweet spot.
There are several things you should always do before taking another person’s time.
- Google It! I kinda can’t believe I have to say that, but not everyone bothers.
- Make sure you can explain the question clearly. If you don’t know where you got stuck, how can I help you get unstuck? And thinking it through might make the answer obvious.
- Develop a theory. When asking for help, it can be useful to pose a theory about an approach. Even if you’re wrong it may help me understand your thinking.
- Try a few things. Experimenting with what’s going wrong can help you formulate your question, and may help me short cut my research if you have eliminated obvious issues.
- Explain the problem to your dog, cat, rabbit, stuff animal, etc. As someone who spends time being a human rubber duck, I can often tell when someone tried to explain it once already.
For me, the hardest part is knowing who to ask.
As a consultant I try to avoid asking questions in places clients may see it. Our clients pay for us to be experts, they do not want to see us asking questions in public – particularly if the question has a simple answer.
As a Salesforce MVP, one of my favorite perks is the MVP Slack channel, where we ask each other questions that run the full range of complexity. While access to a community that hard to access, and that advanced, is a privilege there are other ways to find similar groups like your local user group.
I love having a good internal network of people to ask for help. Most of the places I have worked at as a consultant have had some kind of information place to ask questions and help each other out. If you work in a consultancy find or create such a back channel.
If concerns about being seen by clients isn’t relevant to you, check out this list of 7 Salesforce Communities to Join recommended by Salesforce Ben.
Help Build a Helpful CommunityThe final thing to know about asking for help, is that it’s important to offer help as well. A good question can be valuable to someone else who has the same issue in the future. A good answer is helpful to both the person who asked the question and the person who looks again in the future.
But offering answers, even if not perfect answers, is a great way to learn and encourage others to seek help. Any time I post a question on Stack Exchange, I try to hunt around for one or two to answer as well. That both allows me to pay it forward, it also helps encourage the tone that people can be experts in one thing while still needing help in another.
Smart people need help, and should be comfortable asking for it.
The post Knowing When to Ask for Help appeared first on Spinning Code.
This week in KDE: everything, I think
We spent an enormous amount of time working on bug-fixing and polishing tasks for Plasma 6.1 this week. It was a big release, and there were some rough edges around the new edit mode. So we put quite a bit of time into making it integrate more seamlessly with the other existing modes, and generally polishing it up. Other areas of focus included panels and the system tray, especially when using non-default settings. We made a lot of big changes under the hood for Plasma 6.1 that had some negative consequences, so we’re working to fix things as quickly as we can.
As part of this initiative, we’ve driven the number of high priority Plasma bugs to a new record low: 29! This is the first time it’s ever dipped below 30, which I find very exciting! We’re really getting there.
After bug-fixing, we started working on user interface polish for Plasma 6.2. At this point new features are mostly still cooking, but a lot of subtle improvements have already started to land — complete with screenshots below!
New FeaturesPlasma now supports Enhanced Open (OWE) Wi-Fi security (Fabian Vogt, Plasma 6.2.0. Link)
In KWin’s new (off-by-default) “Hide Cursor” effect, you can now turn off hiding it after inactivity, and only hide it while typing (Vlad Zahorodnii, Plasma 6.2.0. Link)
UI ImprovementsOkular now provides you more information about the validity of a document’s cryptographic signatures (Sune Vuorela, Okular 24.08.0. Link)
When shaking the cursor to expand it, it’s now nice and crisp when using one of the default Breeze cursor themes. Note that It’ll still be pixelated when using a 3rd-party cursor theme until we can implement general support for SVG cursor theming and encourage 3rd-party theme artists to use it (Vlad Zahorodnii, Plasma 6.1.1. Link):
In KWin’s Overview effect, the labels showing windows’ titles are now more legible (Akseli Lahtinen, Plasma 6.1.2. Link):
The Ocean and Oxygen sound themes now include bell sounds, so our automatic “make the system bell not not make you want to commit homicide” transformer can get its sound from those themes, and not just the fallback FreeDesktop sound theme (me: Nate Graham and Guilherme Marçal Silva, Plasma 6.1.2. Link 1 and link 2)
We’ve given another go at the idea of using the same “Open With” UI everywhere — this time including the terminal and script options that were missing last time and caused us to revert it (Harald Sitter, Plasma 6.2.0. Link 1 and link 2):
Discover now shows you a clear error message when the PackageKit daemon is broken or crashy instead of an ambiguous-to-misleading message, and also gives you a handy button you can use to submit a bug report for your distro to gently nudge them to actually care about PackageKit support (Harald Sitter, Plasma 6.2.0. Link)
Plasma’s Lock/Logout widget now has a “Show logout screen” option, bringing back the capability to see a screen with all the options. And now it replaces the previous “shut down” action, restoring the default user experience it had in Plasma 6.0 and earlier: a lock button and a button to show all the session-ending options, with “Shut Down” pre-selected. You can still customize the widget to show whatever you want, of course (Thomas Carmichael, and me: Nate Graham, Plasma 6.2.0. Link 1 and link 2)
Clarified the UI option to confirm shutdown, reboot, and logout, and also changed the old ambiguous “Leave…” text to “Show Logout Screen”, which is clearer (me: Nate Graham, Plasma 6.2.0. Link 1 and link 2):
You can now set the key repeat rate to 200 characters per second, up from the old maximum value of 100 (Vladimir Brik, Plasma 6.2.0. Link)
On System Settings’ Search page, indexing status is now shown in a footer, so it doesn’t cause UI elements to jump around while indexing (me: Nate Graham Plasma 6.2.0. Link):
On System Settings’ Touchpad page, the “Disable while typing” effect now warns you that it might break video games while in use (me: Nate Graham, Plasma 6.2.0. Link)
Plasma’s Power and Battery widget now tells you when power profiles aren’t available because power saving is being handled by the alternative TLP utility (Bohdan Onofriichuk, Plasma 6.2.0. Link)
On System Settings’ Bluetooth page, blocked devices are now listed in their own section, and we also show a contextual help button to help you understand what “blocked” means in this context (Ivan Tkachenko, Plasma 6.2.0. Link 1 and link 2):
The crash reporter dialog now has a “Finish” button in the corner that activates once it’s all done, so it’s more obvious when and how you can get rid of it (Engin Karakurt, Plasma 6.2.0. Link)
When using a custom accent color, Breeze folder icons no longer turn all white or all black when selected in various contexts; instead their background colors will just be tinted a little bit (Marco Martin and Carl Schwan, Frameworks 6.4. Link):
Bug FixesFixed two regression in KCalc that would cause it to crash when hitting the backspace key and broke input chaining (Gabriel Barrantes, KCalc 24.05.2. Link 1 and link 2)
Fixed a regression that caused Plasma’s Icons-and-Text Task Manager widgets to not actually show text anymore on a thick vertical panel (Marco Martin, Plasma 6.1.1. Link)
Fixed a regression that could cause Plasma’s System Tray to temporarily disappear when you quit an app playing media while the System Tray’s Media Player widget was active (Marco Martin, Plasma 6.1.1. Link)
Fixed a visual regression in Plasma’s icons-and-text task manager’s multi-row mode (Ismael Asensio, Plasma 6.1.1. Link)
Fixed a regression that caused Plasma panels’ Adaptive opacity mode to not work properly with certain types of window resizing actions, panel orientations, and visibility states (Fushan Wen, Plasma 6.1.1. Link)
Fixed a KWin regression that broke multi-monitor support in the popular Polonium tiling script (Alik Aslanyan, Plasma 6.1.1. Link)
Fixed a regression that caused newly-created blank System Monitor widgets to be broken until Plasma was restarted once (Arjen Hiemstra, Plasma 6.1.1. Link)
Fixed an odd interaction in Plasma’s new edit mode that could cause it to undesirably exit when the widget explorer was closed (Niccolò Venerandi, Plasma 6.1.1. Link)
Fixed an issue that could sometimes cause the displayed brightness percentage to drift out of sync between the System tray widget and the OSD, and also make the slider kinda laggy (Jakob Petsovits, Plasma 6.1.1. Link 1 and link 2)
In case you’d noticed a tiny, barely detectable horizontal line in the top-left corner of Plasma widgets, it’s gone now (Niccolò Venerandi, Plasma 6.1.1. Link)
Fixed a case where KWin would crash when run on a system with very old (like, 15 years old) graphics hardware (Xaver Hugl, Plasma 6.1.2. Link)
Fixed a regression that broke the layout of Discover’s “Share” dialog (Aleix Pol Gonzalez, Plasma 6.1.2. Link)
Fixed a regression that could cause individual widgets’ hover popups in edit mode to get covered up by the panel settings dialog under certain circumstances (Niccolò Venerandi, Plasma 6.1.2. Link)
Fixed a regression that could, under certain circumstances, cause Plasma’s “Show Alternatives” popup get stuck in the open state open and not close (Niccolò Venerandi, Plasma 6.1.2. Link)
Fixed a regression that caused the “Add Widgets…” button that appears on empty panels is to be aligned incorrectly and located in the wrong place (Niccolò Venerandi, Plasma 6.1.2. Link)
Fixed a regression that caused undoing the deletion of a panel outside of global edit mode to make it get stuck in its own panel edit mode (Marco Martin, Plasma 6.1.2. Link)
Fixed an issue that could cause Plasma to freeze when a thick panel contained certain combinations of widgets with very specific popup sizes (Marco Martin, Plasma 6.1.2. Link)
When System Settings is already showing a page that lives in a sub-category, using another app to open open a different page that doesn’t live in a sub-category now correctly hides the sub-category column (Matthias Tillman, Plasma 6.1.2. Link)
On System Settings’ Accessibility page, the sidebar listing sub-pages now has correct hover and highlight effects (me: Nate Graham, Plasma 6.1.2. Link)
When using Qt 6.8, Plasma no longer quits when you drag an app from Kickoff to the desktop (Vlad Zahorodnii, Plasma 6.2.0. Link)
Discover no longer crashes when you try to update a Flatpak app that has been declared end-of-life without any replacement provided. Instead you’ll be asked if you’d like to uninstall it (Harald Sitter, Plasma 6.2.0. Link)
Dragging a widget from one Plasma panel to another one or the desktop while in edit mode no longer causes it to get lost in a limbo state (Niccolò Venerandi, Plasma 6.2.0. Link)
If you set a global shortcut to activate a System Tray widget, it now always works, rather than only working after the first time the System Tray was opened (Marco Martin, Plasma 6.2.0. Link)
The “Choose a device to send to:” text in share dialogs for KDE Connect is now always readable in every language (Ivan Tkachenko, Frameworks 6.4. Link)
Other bug information of note:
- 4 Very high priority Plasma bugs (down from 5 last week). Current list of bugs
- 29 15-minute Plasma bugs (down from 33 last week). Current list of bugs
- 137 KDE bugs of all kinds fixed over the last week. Full list of bugs
Fixed a case where KWin’s new triple buffering feature could actually make things worse with certain hardware (Xaver Hugl, Plasma 6.1.1. Link)
KWin now falls back to software rendering automatically when used on systems with very old (like, 15 years old) graphics hardware that supports only a limited number of OpenGL operations (Xaver Hugl, Plasma 6.1.1. Link)
Fixed a memory leak in Plasma caused by receiving notifications (Arjen Hiemstra, Plasma 6.1.2. Link)
Improved KWin’s robustness when using a very high refresh rate input device (like one of those blingy 127 billion hertz gamer mice), reducing the chance of apps freezing or quitting after the mouse is moved very very quickly (Vlad Zahorodnii, Plasma 6.2.0. Link)
In Plasma’s clipboard, the “Keep the selection and clipboard the same” setting now works independently of the “Text selection: Always save in history” setting (Fushan Wen, Plasma 6.2.0. Link)
Using a stylus on Wayland now allows you to drag windows around from empty areas, when so configured (Nicolas Fella, Qt 6.7.3. Link)
Automation & SystematizationAdded a test for adaptive panel opacity working properly (Fushan Wen, link)
…And Everything ElseThis blog only covers the tip of the iceberg! If you’re hungry for more, check out https://planet.kde.org, where you can find more news from other KDE contributors.
How You Can HelpYou probably noticed a lot of regressions got fixed! How did they sneak through? Frankly, because not enough people beta-tested Plasma 6.1. Plasma is enormous and can be used in wildly diverse ways, and there are only so many use cases that developers can notice. Automatic testing helps, and we’re getting better at this, but many features are difficult or impossible to test in an automatic fashion. Our faithful beta testers also find many regressions, but by far the majority go unnoticed until the final release. This is a problem!
If you use have multiple systems or an adventurous personality, you can really help us out by installing beta versions of Plasma using your distro’s available repos and reporting bugs. Arch, Fedora, and openSUSE Tumbleweed are examples of great distros for this purpose. So please please do try out Plasma beta versions. It really helps us! Heck, if you’re very adventurous, live on the nightly repos. I’ve been doing this full-time for 5 years with my sole computer and it’s surprisingly stable.
Does that sound too scary? Consider donating today instead! That helps too.
Otherwise, visit https://community.kde.org/Get_Involved to discover other ways to be part of a project that really matters. Each contributor makes a huge difference in KDE; you are not a number or a cog in a machine! You don’t have to already be a programmer, either. I wasn’t when I got started. Try it, you’ll like it! We don’t bite!