Skip to main content

A Python3 replacement for the deprecated cgi module

Project description

mycgi - A Python3 Replacement for the Deprecated cgi Module

Other than using different class names (mycgi.Form instead of cgi.FieldStorage and mycgi.Field instead of cgi.FieldStorage) this module should be quite backward-compatible with the mycgi module. Additionally, JSON-encoded PUT and POST requests are supported.

Note that this module depends on the python-multipart package for handling POST and PUT requests that are not JSON-encoded.

Some Usage Examples

# Instead of:
#from cgi import FieldStorage
# Use:
from mycgi import Form

form = Form()

# name is a text input field:
name = form.getvalue('name') # this will be a list if the form has multiple 'name' fields
# or: name = form.getfirst('name')
# or: names = form.getlist('name')

# spreadsheet is a file input field:
fileitem = form['spreadsheet']
# The name of the uploaded file:
filename = fileitem.filename
# Get the file contents as bytes 3 different ways:
contents = fileitem.file.read()
contents = fileitem.value
contents = form.getvalue('spreadsheet')

Documentation

The initializer for the mycgi.Form class is:

    def __init__(self,
                 environ: Mapping=os.environ,
                 fp: BinaryIO | None=None,
                 keep_blank_values: bool=False
        ) -> None:
        """
        Initialize a Form instance.

        Arguments (all are optional):

        environ: environment dictionary
                 default: os.environ

        fp: stream containing encoded POST and PUT data used
            for PUT and POST requests.
            default: None (in which case if environ['wsgi.input'] exists it
                     will be used else sys.stdin.buffer will be used)

        keep_blank_values: flag indicating whether blank values in
                           percent-encoded forms should be treated as blank
                           strings.
                           default: False
        """

A mycgi.Form instance is a specialized dictionary whose keys are the field names and whose values are either a mycgi.Field instance or a list of these instances. A mycgi.Field instance has the following attributes:

1. name:     The form field name.
2. filename: If this field is for a file, then the file's filename, else None.
3. value:    The form field value (or a file's contents as bytes).
4. file:     If this field is for a file, then a stream that can be read to get the uploaded file's value, else None.

The mycgi.Form class supports the getvalue, getlist and getfirst methods that behave identically to the like-named methods of the deprecated cgi.FieldStorage class and which make it unnecessary to access the mycgi.Field instances, although doing so can be useful for processing file uploads.

JSON-encoded PUT and POST requests

Also supported are POST and PUT requests where the data is a JSON-encoded dictionary.

WSGI Application Usage

To use mycgi.Form with a WSGI application:

from mycgi import Form

def wsgiApp(environ, start_response):
    form = Form(environ=environ)
    ...

Tests To Demonstrate mycgi Usage

from mycgi import Form
import io

# Test a GET request:
form = Form(environ={'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'x=1&x=2&y=3'})
assert repr(form) == "{'x': [Field('x', None, '1'), Field('x', None, '2')], 'y': Field('y', None, '3')}"

assert form.getvalue('x') == ['1', '2']
assert form.getlist('x') == ['1', '2']
assert form.getfirst('x') == '1'
assert [field.filename for field in form['x']] == [None, None]
assert [field.value for field in form['x']] == ['1', '2']

assert form.getvalue('y') == '3'
assert form.getlist('y') == ['3']
assert form.getfirst('y') == '3'
assert form['y'].name == 'y'
assert form['y'].filename is None
assert form['y'].value == '3'

# Test a multipart POST request:
# We have here a text input field named 'act' whose value is 'abc' and two
# file input fields named 'the_file' where a file has been selected for only the
# first occurence:
fp = io.BytesIO(b'------WebKitFormBoundarytQ0DkMXsDqxwxBlp\r\nContent-Disposition: form-data; name="act"\r\n\r\nTest\r\n------WebKitFormBoundarytQ0DkMXsDqxwxBlp\r\nContent-Disposition: form-data; name="the_file"; filename="test.txt"\r\nContent-Type: text/plain\r\n\r\nabc\r\n------WebKitFormBoundarytQ0DkMXsDqxwxBlp\r\nContent-Disposition: form-data; name="the_file"; filename=""\r\nContent-Type: application/octet-stream\r\n\r\n\r\n------WebKitFormBoundarytQ0DkMXsDqxwxBlp--\r\n')
environ = {
    'REQUEST_METHOD': 'POST',
    'CONTENT_LENGTH': '431',
    'CONTENT_TYPE': 'multipart/form-data; boundary=----WebKitFormBoundarytQ0DkMXsDqxwxBlp',
    }
form = Form(environ=environ, fp=fp)

assert form['act'].name == 'act'
assert form['act'].filename is None
assert form['act'].value == 'Test'

assert form['the_file'][0].name == 'the_file'
assert form['the_file'][0].filename == 'test.txt'
assert form['the_file'][0].value == b'abc'

assert form['the_file'][1].name == 'the_file'
assert form['the_file'][1].filename == ''
assert form['the_file'][1].value == b''

assert form.getvalue('the_file') == [b'abc', b'']

# Test a JSON-encoded POST request:
fp = io.BytesIO(b'{"x": [1,2], "y": 3}')
environ = {
    'REQUEST_METHOD': 'POST',
    'CONTENT_LENGTH': '20',
    'CONTENT_TYPE': 'application/json',
    }
form = Form(environ=environ, fp=fp)

assert form.getvalue('x') == [1, 2]
assert form.getlist('x') == [1, 2]
assert form.getfirst('x') == 1
assert [field.filename for field in form['x']] == [None, None]
assert [field.value for field in form['x']] == [1, 2]
assert [field.file for field in form['x']] == [None, None]

assert form.getvalue('y') == 3
assert form.getlist('y') == [3]
assert form.getfirst('y') == 3
assert form['y'].name == 'y'
assert form['y'].filename is None
assert form['y'].value == 3
assert form['y'].file is None

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

mycgi-0.0.11.tar.gz (6.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mycgi-0.0.11-py3-none-any.whl (6.0 kB view details)

Uploaded Python 3

File details

Details for the file mycgi-0.0.11.tar.gz.

File metadata

  • Download URL: mycgi-0.0.11.tar.gz
  • Upload date:
  • Size: 6.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for mycgi-0.0.11.tar.gz
Algorithm Hash digest
SHA256 730551dc095f88ad25c87a9968e2fc934bf76ca2eb7c2d5fe3affcf190da4e9d
MD5 408148f1c94838d301ebc7b056d3b2d8
BLAKE2b-256 2d999832459391d55fddf731f69fe3300e0cbc18a32c46993bf48d9d30388fcf

See more details on using hashes here.

File details

Details for the file mycgi-0.0.11-py3-none-any.whl.

File metadata

  • Download URL: mycgi-0.0.11-py3-none-any.whl
  • Upload date:
  • Size: 6.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for mycgi-0.0.11-py3-none-any.whl
Algorithm Hash digest
SHA256 16e6f0f3ea7a3c12be38c4fae6df34e04de39b55515d5eae840d8afa4554c0bb
MD5 6e4dceec8f927c7a272f4ff6f2356fbb
BLAKE2b-256 7a094b729144b9b3fb57651917f834719deec5f185e42e2a0c23ebe8324d0dd6

See more details on using hashes here.

Supported by

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