Posts tagged with "Free Software"

GitHub Copilot wants our interaction data

4 min read

I guess it was inevitable1, but yesterday GitHub announced a new opt-out approach to learning from people's interactions with Copilot. I don't have anything novel or insightful to say on this switch, and I'm sure folk with better-informed opinions have already rushed out posts and articles about this, but I did want to jot down just how curious I am to see this roll out.

For starters: for me this feels like one of those things that will get a lot of backlash, and in a day or so GitHub will say they're pausing rolling this out while they reevaluate this approach2. Then, eventually, they roll it out anyway after a "period of consultation with the community". That sort of thing.

I've not read further this morning, but before going to bed last night it wasn't a happy time in the comments section of the FAQ. I can also see why some would be cynical about this change, given the tone of some of the questions and answers in that FAQ. I'll hand it to them: they're pretty candid and honest with the FAQs, but kinda yikes too.

A bad time in the FAQ

Here's the key thing I'm curious about, and which I'll be thinking about and watching for movement on in the next few days: all the talk here seems to be about protecting the privacy of the proprietary code of businesses3. That... is understandable, from a business point of view, from a commercial adoption point of view, from a "we want all software engineering departments to use Copilot" point of view. But how the heck are they really going to manage that?

In the comments in the FAQ this explanation stood out:

We do not train on the contents from any paid organization’s repos, regardless of whether a user is working in that repo with a Copilot Free, Pro, or Pro+ subscription. If a user’s GitHub account is a member of or outside collaborator with a paid organization, we exclude their interaction data from model training.

This seems somewhat unclear to me. Let's walk this one through for a moment: my GitHub account is a member of a "paid organisation". My account is also my account, for my personal code, I've had it a long time and it's filled with a lot of FOSS repos and I keep adding more. So which scenario is the right one here?

  1. Because I'm currently a member of at least one "paid organisation" I'm always opted-out of this training no matter how the opt in/out setting is set and no matter what code I work on?
  2. Because I'm currently a member of at least one "paid organisation" I can opt in when working on code that is from a repository which is mine, but I'm opted out when I'm working on code from a repository belonging to the paid organisation?

I think it reads like it's #1. But then that seems rather odd to me because, if I go and look at my settings right now, I can elect to opt in/out of this training system. If the correct reading is #1 why not just disable that setting altogether and say below it that I'm opted-out because I'm part of a paid organisation?

Which sort of suggests we should perhaps read it as #2? If that, that raises all sorts of questions. How would Copilot know I'm working on code from such a repository? Sure, it's not impossible to infer if I am working within the context of a given repository, doing some fun stuff to work out the origin and so on, but it feels messy. It also feels like a scenario that could end up being incredibly leaky. It really would not be difficult to run into a scenario where I'm working on some non-Free code but in an environment where the licence isn't clear, or where it appears that the licence4 would permit such training.

ℹ️ Note

Editing to add: there is even a comment where it is acknowledged that someone could be working in such a way that it's impossible to know the provenance of the code: "Copilot ... can even work when you are not connected to any repo."

Or... perhaps there's a #3, or a #4, or so on, that I've not even considered yet. The fact that software engineering departments suddenly have to start thinking about this issue (yes, I know, it's been a background issue for a while but this really drags it out into the open) is going to make for a few interesting weeks, assuming people care about where their code ends up.

Who knows. Perhaps, in some strange way, this is how all software ends up being Free.


  1. And I think a bit of me is surprised that they weren't just doing it anyway. 

  2. This isn't a prediction, I'm just saying it feels like that sort of announcement. 

  3. It's not that simple, but to save getting into the deep detail... 

  4. I'm using licence here as shorthand for a lot of things to consider relating to who should have access to the code and how. 

You get what you pay for

3 min read

Just recently I saw a post go past on Mastodon, complaining about the author's perception that there was a breakdown of trust in the FOSS world, in respect to the use of AI to work on FOSS projects, or at least the willingness to accept AI-assisted contributions. The post also highlighted the author's reliance on FOSS projects and how they're driven by ethical and financial motivations (some emphasis was placed on how they had no money to spend on these things so it wasn't even necessarily a choice to FOSS up their environment).

This was, of course, in response to the current fuss about how Vim is being developed these days.

I don't want to comment on the Vim stuff -- I've got no dog in that fight -- but something about the post I mention above got me thinking, and troubled me.

Back when I first ran into the concept of Free Software, before the concept of Open Source had ever been thought of, I can remember reading stuff opposed to the idea that mostly worked along the lines of "you get what you pay for" -- the implication being that Free Software would be bad software. I think it's fair to say that history has now shown that this isn't the case.

But... I think it's fair to say that you do get what you pay for, but in a different sense.

If your computing environment is fully reliant on the time, money and effort of others; reliant on people who are willing to give all of that without the realistic expectation of any contribution back from you; I feel it's safe to say that you are getting a bloody good deal. To then question the motivations and abilities of those people, because they are exploring and embracing other methods of working, is at best a bad-faith argument and at worst betrays a deep sense of entitlement.

What I also found wild was, the post went on to document the author's concerns that they now have to worry about the ability of FOSS project maintainers to detect bad contributions. This for me suggests a lack of understanding of how non-trivial FOSS projects have worked ever since it was a thing.

I mean, sure, there are some projects that are incredibly useful and which have a solo developer working away (sometimes because nobody else wants to contribute, but also sometimes because that solo developer doesn't play well with others -- you pick which scenario you think is more healthy), but for the most part the "important" projects have multitudes working on them, with contributions coming from many people of varying levels of ability. The point here being that, all along, you've been relying on the discernment and mentoring abilities of those maintainers.

To suggest they're suddenly unworthy of your trust because they might be "using the AIs" is... well, it feels driven by dogma and it reads like a disingenuous take.

Don't get me wrong though: you are right to be suspicious, you are right to want to question the trust you place in those who donate so much to you; almost always this is made explicit in the licence they extended to you in the first place. But to suggest that suddenly they're unworthy of your trust because they're donating so much value to you in a way you don't approve of...

...well, perhaps it's time for you to pay it back?

Goodbye Textualize

3 min read

While I have been on the receiving end of redundancy once before, that was after 21 years of service at a company that, while it was in part about software development, I would never have called it a "tech" company.

So, as of today, I can finally say that the "tech layoffs" came for me and I'm one of 67% of employees being let go from a tech startup.

Achievement unlocked, I guess?

!Achievement unlocked

To be clear: I'm not annoyed about this, I'm not even shocked about this; I planned for this from the off and realised and recognised the gamble I was taking back in 2022.

Announcing being hired

I am disappointed about this. Not in a "I'm disappointed in you" kind of way, but disappointed for all involved and what it says about how FOSS projects are funded and maintained.

It's been an interesting journey, and it's been a privilege to do something I've been wanting to do since the 1990s, when I first read the GNU Manifesto and subsequently watched the free software and open source movements develop and grow: work on FOSS for a living. In doing this I've developed my thoughts about the feasibility of such an endeavour, I've refined how I feel about working in very small teams, I've learnt a lot of useful lessons I'm going to draw on in the future (keeping a journal of my experience has been a great move; I have a lot of notes and thoughts written down that I'll be reviewing and distilling for myself over the coming weeks).

Most of all: it's been an absolute blast working on something that people are actually using to build cool things, and to provide help and guidance to those people when they've needed it.

So... what happens now? Well, of course, right now, I'm looking for a new position. If you're reading this and you are looking for someone who's kinda handy with Python and a bunch of other languages and who loves learning new stuff, or if you know someone who is looking for such a person, do drop me a line!

As for what happens with Textual, and my involvement with it...

Well, what happens with Textual is Will's call, of course. As for my involvement with it: I care about FOSS and I care about Textual; I also care about the folk who have been kind enough to use their time to explore it, test it, build with it, commit to it and make neat stuff with it. My intention, as long as free time allows, is to carry on being involved, both on GitHub and in the Discord server.

It's my sincere hope that, as a community of FOSS-friendly developers, we see Textual over the 1.0 line and beyond.

But all that starts next week. It's a bank holiday weekend and I think I might have deserved a run, a bit of mucking about in VR, a beer, and just a wee bit of down time.

How not to ask for help

10 min read

My association with Textual works on two levels: on the one hand, sure, it's currently my day job; on the other hand it's a FOSS project that I'm keen to support so "free time me" tries to work with it and support others working with it too. For this reason you'll often see me being terminally1 online in the Textual Discord, trying to answer questions as they come up, every waking free moment.

Almost without exception the people who ask for help are appreciative and ask in the spirit of wanting help and wanting to work together with whoever is helping them to get an answer. That... that's actually quite a cool thing to be part of. I like the sense of community that comes from someone going "bah I'm trying to do this thing and it isn't working PLEASE HELP!".

And then... well, let's just say that sometimes the odd question will crop up that seems to be asked from a less collaborative position.

Without wanting to appear to dunk on an individual (I don't wish to), I want to break down an example that happened yesterday. For some background, I'd been AFK all day, having a wonderful time in town with a friend, shopping, lunch, a movie, that sort of thing. A nicely-chilled day where I didn't even look at the Discord notifications that had popped up on my watch and phone.

However, later on that evening, finally home and flopped on the sofa, I saw a question pop up that, while lacking any useful detail and possibly suffering a wee bit from being an XY problem, the immediate answer was clear:

BadIdentifier: 'test.udp_json_client-input' is an invalid id; identifiers must contain only letters, numbers, underscores, or hyphens, and must not begin with a number.

????????????????? a dot isn't allowed?

Like I say: it lacks context and detail, and the number of question marks doesn't really clarify much, but the core question that seems to be at play here is "is it true that a full stop can't be used as part of the ID of a widget?".

The answer is: no, it can't. There's a reason for that too, and if someone were to take a step back for a moment and think about how IDs play a part in queries and how they'd be used in a stylesheet, the reason for that might pop out. So, to help the person asking the question walk in the direction of the answer, I reply:

When you come to query that how would the parser know it’s not ID “test” combined with a class, if dot was allowed?

Before we go on, to illustrate my point, consider this ID: foo.bar. When you come to query that back, or use it in a stylesheet, how would #foo.bar look? Is it a widget with the ID foo.bar; or is it a widget with the id foo and the class bar?

As far as Textual's CSS is concerned, it would be the latter.

But at this point it didn't seem necessary to get into all that detail; I like to try and assume knowledge on the part of the person asking the question, sans any other evidence, so for the moment I'll assume a "oh, right, yeah, that's a damn good point" kind of reply. Or if not, perhaps a "I don't quite follow, could you explain?" reply, in which case I'm happy to go into all the detail.

The reply was neither:

why are element ID and classes co-mingled?

this was previously allowed so your question doesn't really make sense to me

Now I'm confused. Asking why element IDs and classes are co-mingled seems odd; but I'm used to chatting with people who don't have English as a first language so I'm going to assume it's just a wording choice; but the latter part is very odd: this has never been allowed. Or, more to the point... without any proper context I can't really appreciate what claim is being made here.

You see... I did notice a bug in Textual recently, when it came to widget IDs. Long story short: when you set your ID for the widget in your code, no actual validation of the ID was being done. This was an oversight that was fixed in the latest release.

But knowing that that's the case would be guesswork on my part; I'm also fresh at my desk after a day out; I'm probably not quite in the coding/Textual zone yet, so rather than try and guess half of the conversation, it's easier to just ask the person who is asking. So I ask them to restate the question, and give some more background.

The reply is:

the objective is to put a string like test.udp_json_client-input as the label of a tab, which previously just used the ID property. from skimming release notes, is it better to explicitly set the label, and then assign something compliant for the ID separately?

Wait... what? I thought we were talking about valid widget IDs, now we're talking about tabs and labels? Do we mean TabbeContent and the labels of a TabPane? This is a bit different. So I'm sat there trying to figure out this person's thought process so I can offer the help they're after and this follows:

okay @davep, you have a real bug. --content-tab- prefix is not ephemeral. if I create a tab and grab .id, that prefix comes with it, so if you save it for later and try to set .active, assigning .active doesn't agree that there is a tab --content-tab-thing

so I need to de-mangle the name manually before assigning .active I guess?

Wut? Like... wut? Okay, we do seem to be talking about TabbedContent, I recognise the values being mentioned here; we did some work late on last year that added some namespacing to parts of the TabbedContent widget in an effort to reduce some foot-gun situations.

But... there's no . being used in the IDs as part of that; why are we now proclaiming a bug in an unrelated PR? That's quite the leap with zero evidence. Like... sure, I'm all for being alerted to bugs and fixing them, but this doesn't seem like that.

And then there's the "so I need to..." conclusion that also seems to have no connection to the original question.

Anyone who has ever done support will recognise this situation, I'm sure. Someone has seen a problem, they've dug around a little and reached a conclusion about what the cause is, and turns up looking for help with the conclusion they've reached (very much a variant of a XY problem).

That almost never gets us where we want to go, so I do the obvious thing; I try and reboot the question; I try and get us back to the start and try and get some clarity; I try and encourage asking the question with zero assumptions:

I'm afraid I'm still not really understanding your question, as it now no longer seems to relate to what you very first asked. Perhaps you could start again, ideally with an MRE of what you're looking at and trying to do, for clarity?

I figure, whatever the problem is, it can be illustrated with like a dozen lines of code. Also, when asking people to do this, it often actually helps them rubber-duck their own problem. There's been plenty of times on Discord where someone's "found a bug" in Textual, they're asked to make an MRE of it, and they come back and go "oh, shoot, right, I did that and realised the bug was in my code". It's cool when they happens; everyone learns something.

So... no MRE comes back, but this is the reply:

I'm trying to fix multiple breakages in my application from some recent changes. Right now I can't wrap my head around what to assign a tabbed_content.active for it to work how it did before (where if you have a tab with ID sample, you can assign tabbed_content.active = "sample", but you can't do that anymore)

While not an MRE, I can work with this. It seems clear that they have a TabbedContent where they have a TabPane with the ID "sample" and they are struggling to make it the active tab by setting active to "sample". That seems hugely unlikely, this is what TabbedContent is all about, I think we'd have noticed (I'm petty sure we've got unit tests that cover this), but I'm game. I can test this. And the MRE I write will illustrate there isn't a problem.

So I reply:

Again, I can only suggest that you make an MRE of the issue you're seeing. For example, here's me making a set of tabs, the last of which has the ID "four", and I set the active to "four":

and provide the code:

from textual.app import App, ComposeResult
from textual.widgets import TabbedContent, TabPane, Label

class TabbedContentApp(App[None]):

    def compose(self) -> ComposeResult:
        with TabbedContent():
            with TabPane("One", id="one"):
                yield Label("One")
            with TabPane("Two", id="two"):
                yield Label("Two")
            with TabPane("Three", id="three"):
                yield Label("Three")
            with TabPane("Four", id="four"):
                yield Label("Four")

    def on_mount(self) -> None:
        self.query_one(TabbedContent).active = "four"

if __name__ == "__main__":
    TabbedContentApp().run()

Based on what they've most-recently said is the problem, I'm confident they'll see that this MRE is their situation in a nutshell, and we can work out from there and figure out what the problem is they're seeing and where this . in their IDs is coming from (because I'm very confident it isn't coming from the work that was done on TabbedContent).

This is good. We're getting close to heading down a good path; I can feel it!

I was wrong.

https://github.com/Textualize/textual/blob/main/src/textual/widgets/_tabbed_content.py#L513

there's no way you can deny you just added a metric ton of shenanigans with the tab ID stuff. I can't get it to work at all anymore (assigning .active), but yes I will either come up with an MRE or find the bug and let you know

So, rather than back up a wee bit, work with the MRE I wrote for them so we can take a walk through the problem, they instead decide to tell me that the PR I did last year (which still isn't implicated in any of this outwith of them seemingly assuming it's the cause of all the issues, presented with zero evidence that it is) was simply "a metric ton of shenanigans".

No!

Stop!

This is not how you ask for help.

This isn't how you ask for help from a product or service you pay for. This really isn't how you ask for help from a Free Software project, where the people who are offering you help are doing so in their free time because they want people to be able to build cool things with it.

It really isn't hard at all to show just a wee bit of respect for people's time and willingness to try and help you.

Now... I get it. I can imagine a scenario where someone has just updated Textual and their application suddenly starts throwing all sorts of weird and new errors. That happens. That happened to me on Thursday evening just gone. But that's no reason for approaching getting help like this.

The way to approach it is this: pin the problem dependency, perhaps publish a new version of your application so there's no accidental update of the dependency, then head to any of the help resources for the dependency has and work with people who want to help you to find the cause of the problem. Trust me, it'll go a lot faster if you work with them, take on board suggestions (no matter how odd they might first appear), and really don't call their code "a metric ton of shenanigans".

The conclusion to all of this? The person asking the question eventually found they were setting some widget's ID to an invalid ID; one with a . in it. So as I suspected and wanted to walk them to: they had invalid IDs all along and they only found out about this because ID validation was fixed.

Perhaps one day they'll retract the claim that my actually-unrelated code that wasn't "just" released but was from last year is "a metric ton of shenanigans". ¯\_(ツ)_/¯


  1. Geddit? GEDDIT?