There are no reviews yet. Be the first to send feedback to the community and the maintainers!
optfunc ======= Parse command line options in Python using function introspection. Post feedback here: http://simonwillison.net/2009/May/28/optfunc/ I can never remember how to use any of Python's regular command line parsing libraries. optfunc uses introspection to make a Python function available as a command line utility. It's syntactic sugar around optparse from the standard library. Here's what the API looks like so far: import optfunc def upper(filename, verbose = False): "Usage: %prog <file> [--verbose] - output file content in uppercase" s = open(filename).read() if verbose: print "Processing %s bytes..." % len(s) print s.upper() if __name__ == '__main__': optfunc.run(upper) And here's the resulting command-line interface: $ ./demo.py --help Usage: demo.py <file> [--verbose] - output file content in uppercase Options: -h, --help show this help message and exit -v, --verbose $ ./demo.py README.txt OPTFUNC ... $ ./demo.py README.txt -v Processing 2049 bytes... OPTFUNC ... If you don't mind relying on some stack inspecting magic, you can replace the __name__ == '__main__ idiom with the following: optfunc.main(upper) If you like really short scripts, you can even use this function as a decorator: @optfunc.main def upper(filename): print open(filename).read().upper() How arguments work ------------------ Non-keyword arguments are treated as required arguments - optfunc.run will throw an error if they number of arguments provided on the command line doesn't match the number expected by the function (unless @notstrict is used, see below). Keyword arguments with defaults are treated as options. At the moment, only string and boolean arguments are supported. Other types are planned. Consider the following: def geocode(s, api_key='', geocoder='google', list_geocoders=False): 's' is a required argument. api_key, geocoder and list_geocoders are all options, with defaults provided. Since list_geocoders has a boolean as its default it will be treated slightly differently (in optparse terms, it will store True if the flag is provided on the command line and False otherwise). The command line options are derived from the parameter names like so: Options: -h, --help show this help message and exit -l, --list-geocoders -a API_KEY, --api-key=API_KEY -g GEOCODER, --geocoder=GEOCODER Note that the boolean --list-geocoders is a flag, not an option that sets a value. The short option is derived from the first letter of the parameter. If that character is already in use, the second character will be used and so on. The long option is the full name of the parameter with underscores converted to hyphens. If you want complete control over the name of the options, simply name your parameter as follows: def foo(q_custom_name=False): This will result in a short option of -q and a long option of --custom-name. Special arguments ----------------- Arguments with the names 'stdin', 'stdout' or 'stderr' will be automatically passed the relevant Python objects, for example: #!/usr/bin/env python # upper.py import optfunc @optfunc.main def upper_stdin(stdin, stdout): stdout.write(stdin.read().upper()) Does the following: $ echo "Hello, world" | ./upper.py HELLO, WORLD Subcommands ----------- Some command line applications feature subcommands, with the first argument to the application indicating which subcommand should be executed. optfunc has the beginnings of support for this - you can pass an array of functions to the optfunc.run() and the names of the functions will be used to select a subcommand based on the first argument: import optfunc def one(arg): print "One: %s" % arg def two(arg): print "Two: %s" % arg def three(arg): print "Three: %s" % arg if __name__ == '__main__': optfunc.run([one, two, three]) Usage looks like this: $ ./subcommands_demo.py Unknown command: try 'one', 'two' or 'three' $ ./subcommands_demo.py one one: Required 1 arguments, got 0 $ ./subcommands_demo.py two arg Two: arg This approach is limited in that help can be provided for an individual option but not for the application as a whole. If anyone knows how to get optparse to handle the subcommand pattern please let me know. Decorators ---------- optfunc also supports two decorators for stuff I couldn't work out how to shoehorn in to a regular function definition. geocode.py shows them in action: @optfunc.notstrict @optfunc.arghelp('list_geocoders', 'list available geocoders and exit') def geocode(s, api_key='', geocoder='google', list_geocoders=False): # ... @notstrict means "don't throw an error if one of the required positional arguments is missing" - in the above example we use this because we still want the list_geocoders argument to work even if a string has not been provided. @arghelp('arg-name', 'help text') allows you to provide help on individual arguments, which will then be displayed when --help is called. TODO ---- * Support for different argument types (int, string, filehandle, choices) * Special handling for 'stdin' as an argument name * Proper unix error semantics (sys.exit(1) etc) * Allow the function to be a generator, print iterations to stdout * Support for *args (I don't think **kwargs makes sense for optfunc) * Subcommands need to interact with --help better
datasette
An open source multi-tool for exploring and publishing datasqlite-utils
Python CLI utility and library for manipulating SQLite databasesshot-scraper
A command-line utility for taking automated screenshots of websitescsvs-to-sqlite
Convert CSV files into a SQLite databasetil
Today I Learneddjango-sql-dashboard
Django app for building dashboards using raw SQL queriessimonw
https://simonwillison.net/2020/Jul/10/self-updating-profile-readme/llm
Access large language models from the command-linedb-to-sqlite
CLI tool for exporting tables or queries from any SQL database to a SQLite filedjangode
Utilities functions for node.js that borrow some useful concepts from Djangocsv-diff
Python CLI tool and library for diffing CSV and JSON filesdatasette-lite
Datasette running in your browser using WebAssembly and Pyodideshot-scraper-template
Template repository for setting up shot-scrapergeocoders
Ultra simple API for geocoding a single string against various web services.ca-fires-history
Tracking fire data from www.fire.ca.govdjango-openid
A modern library for integrating OpenID with Django - incomplete, but really nearly there (promise)openai-to-sqlite
Save OpenAI API results to a SQLite databaseaction-transcription
A tool for creating a repository of transcribed videoss3-credentials
A tool for creating credentials for accessing S3 bucketsgit-history
Tools for analyzing Git history using SQLitegoogle-drive-to-sqlite
Create a SQLite database containing metadata from Google Drivedjango-queryset-transform
Experimental .transform(fn) method for Django QuerySets, for clever lazily evaluated optimisations.ratelimitcache
A memcached backed rate limiting decorator for Django.djng
Turtles all the way downcougar-or-not
An API for identifying cougars v.s. bobcats v.s. other USA cat speciessimonwillisonblog
The source code behind my blogadvent-of-code-2022-in-rust
Copilot-assisted Advent of Code 2022 to learn Rustdjangopeople.net
A geographical community site for Django developers.scrape-chatgpt-plugin-prompts
s3-ocr
Tools for running OCR against files stored in S3datasette-app
The Datasette macOS applicationdjango-redis-monitor
Request per second / SQLop per second monitoring for Django, using Redis for storagepython-lib
Opinionated cookiecutter template for creating a new Python libraryttok
Count and truncate text based on tokensmytweets
Script for saving a JSON archive of your tweets.airtable-export
Export Airtable data to YAML, JSON or SQLite files on diskdatasette-graphql
Datasette plugin providing an automatic GraphQL API for your SQLite databasesllm-mlc
LLM plugin for running models using MLCstrip-tags
CLI tool for stripping tags from HTMLdjango_cropper
Integration of jCrop with the Django adminclick-app
Cookiecutter template for creating new Click command-line toolsdatasette-ripgrep
Web interface for searching your code using ripgrep, built as a Datasette plugindownload-esm
Download ESM modules from npm and jsdelivrdatasette.io
The official project website for Datasetteftfy-web
Paste in some broken unicode text and FTFY will tell you how to fix it!markdown-to-sqlite
CLI tool for loading markdown files into a SQLite databasesqlite-history
Track changes to SQLite tables using triggersyaml-to-sqlite
Utility for converting YAML files to SQLitesqlite-diffable
Tools for dumping/loading a SQLite database to diffable directory structurecovid-19-datasette
Deploys a Datasette instance of COVID-19 data from Johns Hopkins CSSE and the New York Timesdogproxy
Experimental HTTP proxy (using node.js) for avoiding the dog pile effect.soupselect
CSS selector support for BeautifulSoup.laion-aesthetic-datasette
Use Datasette to explore LAION improved_aesthetics_6plus training data used by Stable DIffusiondatasette-cluster-map
Datasette plugin that shows a map for any data with latitude/longitude columnsaction-transcription-demo
A tool for creating a repository of transcribed videosdatasette-vega
Datasette plugin for visualizing data using Vegapge-outages-pre-2024
Tracking PG&E outagesgoogle-calendar-to-sqlite
Create a SQLite database containing your data from Google Calendarurl-map
Use URL parameters to generate a map with markers, using Leaflet and OpenStreetMapdisaster-scrapers
Scrapers for disaster data - writes to https://github.com/simonw/disaster-datadjp
A plugin system for Djangogeojson-to-sqlite
CLI tool for converting GeoJSON files to SQLite (with SpatiaLite)asgi-csrf
ASGI middleware for protecting against CSRF attacksdatasette-chatgpt-plugin
A Datasette plugin that turns a Datasette instance into a ChatGPT pluginnodecast
A simple comet broadcast server, originally implemented as a demo for Full Frontal 2009.bugle_project
Group collaboration tools for hackers in forts.django-html
A way of rendering django.forms widgets that differentiates between HTML and XHTML.datasette-auth-github
Datasette plugin that authenticates users against GitHubpuppeteer-screenshot
Vercel app for taking screenshots of web pages using Puppeteerllm-replicate
LLM plugin for models hosted on Replicatepython-lib-template-repository
GitHub template repository for creating new Python libraries, using the simonw/python-lib cookiecutter templatedjango-signed
Signing utilities for Django, to try out an API which is being proposed for inclusion in Django core.museums
A website recommending niche museums to visitpypi-rename
Cookiecutter template for creating renamed PyPI packageshelp-scraper
Record a history of --help for various commandsdbf-to-sqlite
CLI tool for converting DBF files (dBase, FoxPro etc) to SQLitedisaster-data
Data scraped by https://github.com/simonw/disaster-scrapersasyncinject
Run async workflows using pytest-fixtures-style dependency injectiondatasette-publish-vercel
Datasette plugin for publishing data using Vercelgzthermal-web
A web interface to gzthermal by caveman on encode.ruasgi-auth-github
ASGI middleware that authenticates users against GitHubjson-head
JSON microservice for performing HEAD requestsdjango-safeform
CSRF protection for Django forms.s3-image-proxy
A tiny proxy for serving and resizing images fetched from a private S3 bucketsqlite-transform
Tool for running transformations on columns in a SQLite databasewebhook-relay
A simple Node.js server for queueing and relaying webhook requestsdatasette-tiddlywiki
Run TiddlyWiki in Datasette and save Tiddlers to a SQLite databaseimage-diff
CLI tool for comparing imagesgetlatlon.com
Source code for getlatlon.com - a simple, single page, pure JavaScript Google Maps application.sf-tree-history
Tracking the history of trees in San Franciscoscrape-hacker-news-by-domain
Scrape HN to track links from specific domainstimezones-api
A Datasette-powered API for finding the time zone for a latitude/longitude pointowlsnearme
A website that tells you where your nearest owls are!datasette-table
A Web Component for embedding a Datasette table on a pagexml-analyser
Simple command line tool for quickly analysing the structure of an arbitrary XML fileshapefile-to-sqlite
Load shapefiles into a SQLite (optionally SpatiaLite) databasecdc-vaccination-history
A git scraper recording the CDC's Covid Data Tracker numbers on number of vaccinations per state.json-flatten
Python functions for flattening a JSON object to a single dictionary of pairs, and unflattening that dictionary back to a JSON objectdatasette-json-html
Datasette plugin for rendering HTML based on JSON valuesdjangocon-2022-productivity
Supporting links for my DjangoCon 2022 talkLove Open Source and this site? Check out how you can help us