Skip to main content

Add your description here

Project description

go-flag

go-flag is a port of Go's flag package to Python.

Why??

Typically, click or argparse are going to be more straightforward than using this library. But there are a few motivations for using go-flag:

  1. You want to write a tool in Python, which behaves like a Go program. If you are using it alongside other programs that use Go-style flags, it can make your tool feel more at home in that ecosystem.
  2. You're a Gopher, and want to write some Python. In that case, this library may feel more comfortable.
  3. You are porting a Go program. This library can help minimize the amount of effort involved in translating idioms.

Also, I think this is funny.

Usage

The simplest usage of this library involves defining some flags and running a parse:

#!/usr/bin/env python

import flag

force = flag.bool_("force", False, "force the command to execute")
count = flag.int_("count", 1, "a count")
name = flag.string("name", "Josh", "a name")
threshold = flag.float_("threshold", 1.0, "a threshold")

flag.parse()

print(dict(
    force=force.deref(),
    count=count.deref(),
    name=name.deref(),
    threshold=threshold.deref()
))

With no arguments, this will print:

$ python examples/simple.py
{'force': False, 'count': 1, 'name': 'Josh', 'threshold': 1.0}

With a number of argument, we see:

$ python examples/simple.py -count 3 -force=true -name KB -threshold 0.5
{'force': True, 'count': 3, 'name': 'KB', 'threshold': 0.5}

With the help flag, this will print:

$ python examples/simple.py -h
Usage of examples/simple.py:

  -count int
    	a count (default 1)
  -force
    	force the command to execute
  -name string
    	a name (default Josh)
  -threshold float
    	a threshold (default 1)

In this usage, these flags are instances of flag.Ptr. But you may want to be a little more fancy - for instance, using a class and flag.AttrRef:

#!/usr/bin/env python

import flag


class Config:
    force: bool = flag.zero.bool_
    count: int = flag.zero.int_
    name: str = flag.zero.string
    threshold: float = flag.zero.float_


force = flag.AttrRef(Config, "force")
count = flag.AttrRef(Config, "count")
name = flag.AttrRef(Config, "name")
threshold = flag.AttrRef(Config, "threshold")

flag.bool_var(force, "force", False, "bool value")
flag.int_var(count, "count", 1, "int value")
flag.string_var(name, "name", "Josh", "string value")
flag.float_var(threshold, "threshold", 1.0, "float value")

flag.parse()

print(
    dict(
        force=Config.force,
        count=Config.count,
        name=Config.name,
        threshold=Config.threshold,
    )
)

This outputs:

$ python examples/class.py -count 3 -force=true -name KB -threshold 0.5
{'force': True, 'count': 3, 'name': 'KB', 'threshold': 0.5}

The flag.KeyRef class can implement a similar pattern with dicts.

In general, aside from the need to use classes that fake pointers and a number of data types not applicable to Python, the API should follow the same general shape as Go's flag package. For more documentation, read the source - the docstrings should be relatively complete.

Error Handling

We already saw one strange set of abstractions we needed to pretend to be Go - the Pointer protocol and its implementations. The other way in which this library emulates Go is in its error handling.

Not to worry - this library raises Exceptions like God intended. But it does have two non-overlapping classes of errors: flag.Error and flag.Panic. The former emulates cases where Go would have us return an error. The latter is raised when emulating a Go panic.

While the internal details of how Errors are created are unusual, the end result is very simple error classes. In general, you can except on flag.Error and allow raised instances of flag.Panic to crash the program. But if you wish to have more fine-grained control, you may with to except flag.Panic as well.

Development

I developed this project using uv. It is a little immature, and I honestly can't recommend it yet for production use. We will see if I stick with this stack over time.

Nevertheless, the justfile should contain most of what you need - including just format, just lint, just check, and just test. Note that type checking requires node.js, because I use pyright.

License

I licensed this under a BSD-3 license, in an attempt to stay compatible with Go's license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

go_flag-1.0.0.tar.gz (21.2 kB view details)

Uploaded Source

Built Distribution

go_flag-1.0.0-py3-none-any.whl (18.8 kB view details)

Uploaded Python 3

File details

Details for the file go_flag-1.0.0.tar.gz.

File metadata

  • Download URL: go_flag-1.0.0.tar.gz
  • Upload date:
  • Size: 21.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.2

File hashes

Hashes for go_flag-1.0.0.tar.gz
Algorithm Hash digest
SHA256 40a8b70e271877e2eaa7fe9715bebc7ad8cf9c85d5a602e49c748fb5b61f2306
MD5 009bd7af0b566516b6850b87507c75c7
BLAKE2b-256 49439384bf79e5a62c19654e0e07c2e85942bd885391e6e12e21e53af2117970

See more details on using hashes here.

File details

Details for the file go_flag-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: go_flag-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 18.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.5.2

File hashes

Hashes for go_flag-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fa6906d2f9e511ffee24a4e9ea33c8ef06079e4e5c586f420a3be39bff063614
MD5 debfc64733dbd9d1480be74448a958d7
BLAKE2b-256 2078fe02552fee90f80c3ec4d7c496ce40c4ba44af2a02d9c2b3036e308328e3

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page