Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Copy this to the CIRCUITPY MSC drive on a CircuitPython board,
then compress it:
gzip -k
Then you can do something like the following:
>>> from import_gzip import import_gzip
>>> module = import_gzip('')
>>> module.make_a_thing()
Requires CircuitPython built with
This file is public domain
class MyThing:
def __repr__(self):
return 'MyThing()'
def make_a_thing():
return MyThing()
Header implementation only slightly modified by me, otherwise copied from, and thus
licensed MIT, Copyright (c) 2016 SEOmoz
GzippedModule, eval_module, and import_gzip all mine, licensed MIT
Copyright 2018 Josh Klar <>
Requires CircuitPython built with
import gc
import struct
import time
import uzlib
# pylint: disable=too-many-instance-attributes
class Header(object):
'''Read, write, hold Gzip file headers.'''
# Constatnts
MAGIC = b'\x1F\x8B'
METHOD = b'\x08' # zlib.DEFLATED
# Flags
FTEXT = 0x1
FMULTI = 0x2
FEXTRA = 0x4
FNAME = 0x8
# The attributes for this class
__slots__ = (
# pylint: disable=too-many-arguments
def __init__(self, flags=0, mtime=None, extra_flags=2, os_flags=255, extra=None,
name=None, comment=None):
self.flags = flags
self.mtime = mtime or int(time.time())
self.extra_flags = extra_flags
self.os_flags = os_flags
self.extra = extra = name
self.comment = comment
def read_null_terminated(cls, fobj):
'''Read a null-terminated string.'''
result = b''
while True:
char =
if not char or char == b'\x00':
result += char
return result
def read(cls, fobj):
'''Read in headers from a file object.'''
if != cls.MAGIC:
raise Error('Invalid magic.')
if != cls.METHOD:
raise Error('Unknown compression method')
flags = ord(
mtime = struct.unpack('<L',[0]
extra_flags = ord(
os_flags = ord(
extra = None
if flags & cls.FEXTRA:
length = struct.unpack('<H',[0]
extra =
name = None
if flags & cls.FNAME:
raw = cls.read_null_terminated(fobj)
name = str(raw, 'utf-8')
comment = None
if flags & cls.FCOMMENT:
comment = cls.read_null_terminated(fobj).decode('latin-1')
if flags & cls.FMULTI:
raise ValueError('Multipart gzips not supported.')
return cls(flags, mtime, extra_flags, os_flags, extra, name,
def write(self, fobj):
'''Write this header to a file object.'''
self.flags = (
(self.FNAME if ( is not None) else 0) |
(self.FEXTRA if (self.extra is not None) else 0) |
(self.FCOMMENT if (self.comment is not None) else 0))
fobj.write(self.MAGIC) # magic header
fobj.write(self.METHOD) # compression method
fobj.write(chr(self.flags)) # flags
fobj.write(struct.pack('<L', self.mtime)) # Modification time
fobj.write(chr(self.extra_flags)) # eXtra FLags (max compression)
fobj.write(chr(self.os_flags)) # Operating system (unknown)
if (self.flags & self.FEXTRA) and self.extra:
fobj.write(struct.pack('<H', len(self.extra)))
if (self.flags & self.FNAME) and
if (self.flags & self.FCOMMENT) and self.comment:
def __repr__(self):
joined = ', '.join(
'%s=%s' % (attr, getattr(self, attr)) for attr in self.__slots__)
return '<Gzip.Header %s>' % joined
def __eq__(self, other):
return all(
getattr(self, attr) == getattr(other, attr) for attr in self.__slots__)
class GzippedModule:
def __init__(self, name, filename, attrs=None):
self.__name__ = name
self.__file__ = filename
if attrs is not None:
for k, v in attrs.items():
setattr(self, k, v)
def __repr__(self):
return "<gzipped module '{}' from '{}'>".format(
def eval_module(mstr, name=None, file=None):
# generate a new local scope to avoid weird "undefined" errors
# this simulates the bizarre file scope that Python creates, which I
# don't fully understand, however if global and local scope are not
# synced within the exec'd file, things get _bizarre_ - class
# definitions will work, and are even usable from the `module` object
# we return below, but will be inaccessible from anywhere else within
# the file being exec'd - meaning a function within module wouldn't be
# able to access a class also within module
scope = dict()
if name is not None:
scope['__name__'] = name
if file is not None:
scope['__file__'] = file
exec(mstr, scope, scope)
return scope
def import_gzip(path):
with open(path, 'rb') as gz_file:
header =
module_bytes = uzlib.decompress(, -1)
filename = or path
module_str = str(module_bytes, 'utf-8')
del module_bytes
module = eval_module(module_str, file=filename)
# forcibly clean up after ourselves
del header
del module_str
return GzippedModule(
filename[:-3] if filename.endswith('.py') else filename,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment