Friday, March 08, 2019

Please protect the right to create public domain works

snap is a package format for faster release cycle on Ubuntu. Recently its snapcraft.yml description file has got license field:

# License for the snap content, based on SPDX license expressions.
license: <expression>

Which led me to discover corporate looking SPDX website that aims to set standard on package metadata. And this metadata doesn't allow public domain code:

I expected that such project would be equally inclusive to protect the rights of people to release their code without copyright regulations. I would expect it to work with corporate and public services to enable this option, clarify its meaning and champion changes in legislation. But instead this Linux Foundation project decides that public domain code is too bothersome to deal with.

Most of my Python code is released as public domain. I like the total freedom of not being forced to deal with strings attached, and I want to give this freedom to people who use my code. I don't even want this code to be "my". I do not need copyright at all. Giving credits to people and supporting those who need support - this activity doesn't need copyright. Technology can make it automated. Being present in copyright header doesn't mean that people care. This problem copyright can not fix.

Copyright was invented before the internet, 300 hundred years ago, before git and Mercurial, and lawyers are still (ab)using it in their legal warfare, turning it against those who could show how we could use technology to build a better world, with less stress and more transparency. With the next generation mentality of the internet children, it is possible to create a next generation of ecosystem with cooperative gameplay and better ecological goals. We really need to ask each other personally - "What do you want? What do you need?" - and help each other grow internally - not externally. Collaborate on building better systems, better code, instead of squabbling on what's already been written.

Starting with myself - What did I want? I wanted recognition. I didn't want money. Copyright didn't help me to get recognition. Recognition came from my social activity, from interacting with people, building open source, collaborating together, trying to solve some problems in a better way. Many years later recognition came from inside. From mindfulness, and that was a huge relief - not trying to compete with people and show off to seem better on outside. Copyright didn't help me to get money - they came from solving problems for other people without adding new ones. Money came as a result of interacting with others over the things that I found challenging and interesting enough.

I've been paid money, because I can not survive without them, and my network was responsive to my need. I didn't write CV letters or applied to job fairs or went by advertisement in factories. Once I've become transparent to the network with open hands to be helpful, the money found their flow to compensate me for my time. In seven years I signed only one legal paper, one contract with NDA, and that was the only case when I was not paid after finishing the job. I don't want to live in your legal network - I want to be left in mine. In the network where we transparent and don't attack each other with long legal "electronic documents" that are just a scanned paper. I want to live in a netowrk where my will is a signed data structure on a public blockchain, where people are connected and understand what being a human is not easy, and appreciate our nature and support each other towards greater goal.

I don't mind people playing the copyright game. People need games to play. But I do not approve it. Suing programmers for their pet projects that got more popular than mundane office project, taking money for access to scientific papers and not paying scientists who produced them. I am tired, I am scared, because I am paranoid, and I want to opt-out from this system.

I needed support and I joined the Gratipay project. In Gratipay I didn't do much, but in the process I learned to support other people. People whose code I like, people I admire, or people who experienced difficulties, or just people who know how to have fun. I started contributing to Gratipay, because it was public domain and it was completely transparent down to the last penny - I could leave at any point and use the code that I learned in my other projects. I tried to make it better and contribute back. I learned a lot and the more questions I asked, the more interesting things I learned. About people, about economics, about financial gameplay. That was an awesome time and a great experience. I wish that everybody in their live could join a project like this. Helping completely open and transparent company. Gratipay could not survive in U.S., and now its public domain code is serving Liberapay in France.

Public domain was the only way to opt-out from copyright, and with the decision to abandon the fight for it, Linux Foundation closes the door for me to share my code with no strings attached. Treating public domain works "the same way as any license" is the worst decision the SPDX project could take. Public domain is in the "conflict of interests" zone of copyright lawyers, because it is about ignoring their domain, about the right not to care about their business and not being touched by their activities. The task for protecting public domain is for true legal hackers, the ones who go beyond compliance to see the people on the other end. Because there is always a person behind Twitter handle or GitHub account and the person means a little bit more than a "copyright holder".

SPDX raised an important point - Public Domain is not copyright. The right programmatic solution is it to add a separate copyright-optout: true field that is mutually exclusive with license, because this semantic is completely different from the paper based kludges and cargo cults of the past. It cleans up the space for the next generation of internet connected people to ask questions - how do we give credits and how do we support other people in the age of technology.

Please fight for Public Domain - it may appear more important for positive development of technology than we currently see, and it may provide a foundation for better bringing us together.

Wednesday, May 17, 2017

Why Git suxx

$ git checkout master
Already on 'master'
Your branch is up-to-date with 'origin/master'.
$ git checkout
 Checkout aborted
 There's no file https:\\gratipay\\pull\178 at HEAD
$ git switch
git: 'switch' is not a git command. See 'git --help'.


Download to your git --exec-path.

Wednesday, November 02, 2016

Python Usability Bugs: Formatting argparse subcommands

Suppose you want to build a tool with a simple interface:
usage: sub <command>


  status -  show status
  list   -  print list
Python proposes to use argparse module. And if you follow documentation, the best you can get will be this output:
usage: sub {status,list} ...

positional arguments:
    status       show status
    list         print list
And it you implement proper formatting, your code will look like this:
import argparse
import sys

class CustomHelpFormatter(argparse.HelpFormatter):
  def _format_action(self, action):
    if type(action) == argparse._SubParsersAction:
      # inject new class variable for subcommand formatting
      subactions = action._get_subactions()
      invocations = [self._format_action_invocation(a) for a in subactions]
      self._subcommand_max_length = max(len(i) for i in invocations)

    if type(action) == argparse._SubParsersAction._ChoicesPseudoAction:
      # format subcommand help line
      subcommand = self._format_action_invocation(action) # type: str
      width = self._subcommand_max_length
      help_text = ""
          help_text = self._expand_help(action)
      return "  {:{width}} -  {}\n".format(subcommand, help_text, width=width)

    elif type(action) == argparse._SubParsersAction:
      # process subcommand help section
      msg = '\n'
      for subaction in action._get_subactions():
          msg += self._format_action(subaction)
      return msg
      return super(CustomHelpFormatter, self)._format_action(action)

def check():
  return 0

parser = argparse.ArgumentParser(usage="sub <command>", add_help=False,

subparser = parser.add_subparsers(dest="cmd")
subparser.add_parser('status', help='show status')
subparser.add_parser('list', help='print list')

# custom help messge
parser._positionals.title = "commands"

# hack to show help when no arguments supplied
if len(sys.argv) == 1:

args = parser.parse_args()

if args.cmd == 'list':
elif args.cmd == 'status':

Here you may see the failure of OOP (object oriented programming). The proper answer to this formatting problem is just to define a data structure for command line help in JSON or similar format and let people dump and process it with templates. Once option definition is parsed, the information there is static, so there is no need in those intertwined recursive method calls. So just do it in 2 pass - get dataset and render template.

Saturday, September 17, 2016

Python Usability Bugs: subprocess.Popen executable

subprocess.Popen seems to be designed as a "swiss army knife" of managing external processes, and while the task is pretty hard to solve in cross-platform way, it seems the people who have contributed to it did manage to achieve that. But it still came with some drawbacks and complications. Let's study one of these that I think is a top one from usability point of view, because it confuses people a lot.

I've got a simple program that prints its name and own arguments (forgive me for Windows code, as I was debugging the issue on Windows, but this works the same on Linux too). The program is written in Go to get single executable, because subprocess has special handling for child Python processes (another usability bug for another time).
>argi.exe 1 2 3 4
prog: E:\argi.exe
args: [1 2 3 4]
Let's execute it with subprocess.Popen, and for that I almost always look up the official documentation for Popen prototype:
subprocess.Popen(argsbufsize=0executable=Nonestdin=None, stdout=Nonestderr=Nonepreexec_fn=Noneclose_fds=False, shell=Falsecwd=Noneenv=Noneuniversal_newlines=False, startupinfo=Nonecreationflags=0)
Quite scary, right? But let's skip confusing part and quickly figure out something out of it (because time is scarce). Looks like this should do the trick:
import subprocess

args = "1 2 3 4".split()
p = subprocess.Popen(args, executable="argi.exe")
After saving this code to "" and running it, you'd probably expect something like this :
> python
prog: E:\argi.exe
args: [1 2 3 4]
And... you won't get this. What you get is this:
> python
prog: 1
args: [2 3 4]
And that's kind of crazy - not only the executable was renamed, but the first argument was lost, and it appears that this is actually a documented behavior. So let's define Python Usability Bug as something that is documented but not expected (by most folks who is going to read the code). The trick to get code do what is expected is never use executable argument to subprocess.Popen:
import subprocess

args = "1 2 3 4".split()
args.insert(0, "argi.exe")
p = subprocess.Popen(args)
prog: argi.exe
args: [1 2 3 4]
The explanation for former "misbehavior" is that executable is a hack that allows to rename program when running subprocess. It should be named substitute, or - even better - altname to work as an alternative name to pass to child process (instead of providing alternative executable for the former name). To make subprocess.Popen even more intuitive, the args argument should have been named command.

From the high level design point of view, the drawbacks of this function is that it *does way too much*, its arguments are not always intuitive - it takes *a lot of time to grok official docs*, and I need to read it *every time*, because there are too many little important details of Popen behavior (have anybody tried to create its state machine?), so over the last 5 years I still discover various problems with it. Today I just wanted to save you some hours that I've wasted myself while debugging pymake on Windows.

That's it for now. Bonus points to update this post with link when I get more time / mana for it:

  • [ ] people who have contributed to it
  • [ ] it came with drawbacks
  • [ ] have anybody tried to create its state machine?
  • [ ] subprocess has special handling for child Python processes

Thursday, June 16, 2016

Why Python community should take UX seriously

UX is a discipline that is dedicated to measuring user emotions and satisfaction while using a product in order to improve them. When you grow experience in any programming language you start to experience negative emotions towards small warts and glitches that constantly get in your way. You compare it to different languages and soon you're no more satisfied with it. Backward compatibility etc. doesn't allow to change things, but they should be changed, and UX is the criteria and method to answer how. But why?

People are dying too quickly. The process of learning new technology is fun and exciting, but when you look at the ideas in the past you'll see that we are not inventing anything new. People thought about many ideas, and couldn't implement them. I still don't have automation line that pours me coffee in the morning and bakes omelet and this idea is like 20 years old. I have no information about where my products are coming from - this idea is about 10 years old, and those fruits that are coming from hydroponics and pretty tasteless, so I'd prefer to buy something bathed in organic sun. Where are those inventions now? I am pretty sure somebody is trying to design these things in own basement, but those inventions will never see the light, because they are fragile, needs a lot of experience and education. Why learning is hard? It needs a lot of experience and education to learn concepts, operating systems internals and get used to various glitches and workarounds from the past. If Python was easier, if operating systems were more easy to learn and intuitively understand, not relying on elitist part of hacker culture, we could hack on more fun and reliable things today.

Tuesday, June 07, 2016

Why Roundup needs a router? is powered by ancient software. Most people nowadays won't install it. They would rather find something newer, with more features (consumers) or invent something from scratch that will be more modern from the start (makers).

How about trying a different approach - how about an approach that means constant evolution of the software? The reason why people reinvent things from scratch is because they often can not understand the complexity of what was already written. The burden of complexity is like tar that glues us to the surface, needs more force to take a step and slows us down. One way to get rid of it is to start again clean. But there is no guarantee that the same story won't happen if you couldn't see past complexity before.

A way of evolution is to face the complexity and deal with it. The way to deal with complexity tar is to learn to fly over it. Visualization, art, story-telling are helping to people to overcome limitations of our attention, interest, motivation and focus. There are tools to make complex things simple, there are things to look at the surface from above and choose a path that is still unexplored.

Router is a component that directs URL request to processing. Router says that http://../file142 should be processed by function that handles files, and http://../issue42 should be handled by function that processes issues. This logic is hardcoded into Roundup, so its URL structure doesn't change. If Roundup had this router, then it could be used as a replacement for existing trackers without breaking links. Router also allows Roundup extensions add new endpoints, such as ones required for OAuth2 processing or REST and ajax interface.

So, how to evolve software? It takes media and coordination skills first, and code review and design second. Additional code that makes code more complex should be backed up by documentation that explains it, every lengthy documentation that gives details should be accompanied by concise overview and reminder picture, every yak shaving process should be automated, every upstream tools need to be improved. Evolution is a global process, and it is hard (if not impossible) to evolve one agent if the whole ecosystem is not changing. Changing ecosystem or tools that are already stable like Python require process shift that drastically changes how people coordinate, approve, mutate and select the branches with features that comfort them.

Wednesday, May 11, 2016

Open Source, Death, and Open Economy

Open Source is a great idea, great movement and a great boost to the progress of civilization. Open Data made transparent governments possible, which allowed people to regulate tough problems, not hide them. Open systems like Linux and Open Stack enabled building more useful software on top of more solid and stable basis (first for single operating system nodes and now for clouds and networks).

So why Open Source is dead? Because there is no such thing as software product - any software is alive as long as its code is live in the heads of its maintainers. As soon as maintainers leave, the product enters death spiral - new people enter the field to patch the product to the death. Open Source is dead, because maintaining Open Source software requires time, and every minute of that time you need to pay for food, for shelter, for the privilege to meet with your friends and be inspired. Open Source maintenance does not release maintainers from paying for all this stuff and doesn't bring them those payment tokens called `money`. So code in maintainers heads will have to die.

How come that current economy is so flawed? Does Open Source produce value? Definitely, yes. Does it solve problems for people? Yes. Do people feel grateful for Open Source? Well, sometimes (but that's also the question of consumer culture forced by current economy). And still open source developers leave their products to join (often meaningless) activities of reinventing things from scratch for other projects. Often doing things that they've paid for and not things they know and like.

How come that people with developed skills doing useful things have nothing to eat, and for food and shelter have to reformat their brain and became compliant with office slavery? Sometimes I feel like we should extend software freedom conservancy model from software to people and remove "people with money" from power part of this equation. Blockchain allows us to calculate personal values to remove this money-for-money gameplay. Gameplay that creates parasites out of people, parasites that are motivated to produce garbage, to consume and to battle each other for "market domination". Parasites don't like to be exposed, and they don't like to be parasites, so maybe Open Economy is an answer that can bring our focus back to the planet with depleting resources and increasing pollution that pushes our health and general feeling of the world down to the level of committing a suicide.

I'd like to believe, but I am loosing my insight sometimes. There are many good people who care about me in this world, and this letter won't be there if not them. But their lifetime is limited, and so is mine. I really wanted to boost progress to help with my health and global problems, but it seems I failed. This post is filled under a Python tag, which always was a part of that unconscious plan. I thought that I could enhance it to be an easier, and more intuitive tool to augment limited human abilities for automation, to help them concentrate on more important things. But it seems I failed. I still see things how they should be done, I still see that DX (developer's experience) need to raise to the top of people priorities. It is just that I am exhausted to compete for food and shelter and feel depressed over the need to reformat my natural intelligence network to do those (often meaningless) office things just to keep my body alive.