diff --git a/pyopencl/__init__.py b/pyopencl/__init__.py
index 256d1c1437ac91b09f78092ef48130bedc69e40a..a22c5565ae1c337e16d80baf92cb257bfe05c4e2 100644
--- a/pyopencl/__init__.py
+++ b/pyopencl/__init__.py
@@ -37,6 +37,78 @@ def compiler_output(text):
 
 
 
+# {{{ Program (including caching support)
+
+class Program(object):
+    def __init__(self, context, arg1, arg2=None):
+        if arg2 is None:
+            source = arg1
+
+            import sys
+            if isinstance(source, unicode) and sys.version_info < (3,):
+                from warnings import warn
+                warn("Received OpenCL source code in Unicode, "
+                        "should be ASCII string. Attempting conversion.",
+                        stacklevel=2)
+                source = str(source)
+
+            self._context = context
+            self._source = source
+            self._prg = None
+        else:
+            # 3-argument form: context, devices, binaries
+            self._prg = _cl._Program(context, arg1, arg2)
+
+    def _get_prg(self):
+        if self._prg is not None:
+            return self._prg
+        else:
+            # "no program" can only happen in from-source case.
+            from warnings import warn
+            warn("Pre-build attribute access defeats compiler caching.", stacklevel=3)
+
+            self._prg = _cl._Program(self._context, self._source)
+            del self._context
+            del self._source
+            return self._prg
+
+    def get_info(self, arg):
+        return self._get_prg().get_info(arg)
+
+    def get_build_info(self, *args, **kwargs):
+        return self._get_prg().get_build_info(*args, **kwargs)
+
+    def all_kernels(self):
+        return self._get_prg().all_kernels()
+
+    def __getattr__(self, attr):
+        try:
+            knl = Kernel(self._get_prg(), attr)
+            # Nvidia does not raise errors even for invalid names,
+            # but this will give an error if the kernel is invalid.
+            knl.num_args
+            return knl
+        except LogicError:
+            raise AttributeError("'%s' was not found as a program "
+                    "info attribute or as a kernel name" % attr)
+
+    def build(self, options=[], devices=None, cache_dir=None):
+        if isinstance(options, str):
+            options = [options]
+
+        options = options + ["-I", _find_pyopencl_include_path()]
+
+        if self._prg is not None:
+            self._prg._build(options, devices)
+        else:
+            from pyopencl.cache import create_built_program_from_source_cached
+            self._prg = create_built_program_from_source_cached(
+                    self._context, self._source, options, devices,
+                    cache_dir=cache_dir)
+
+        return self
+
+    # }}}
 
 def _add_functionality():
     cls_to_info_cls = {
@@ -54,6 +126,8 @@ def _add_functionality():
                 (MemoryObjectHolder.get_info,_cl.mem_info),
             _cl.Image:
                 (Image.get_image_info, _cl.image_info),
+            Program:
+                (Program.get_info, _cl.program_info),
             _cl.Kernel:
                 (Kernel.get_info, _cl.kernel_info),
             _cl.Sampler:
@@ -425,79 +499,6 @@ def _find_pyopencl_include_path():
 
 # }}}
 
-# {{{ Program (including caching support)
-
-class Program(object):
-    def __init__(self, context, arg1, arg2=None):
-        if arg2 is None:
-            source = arg1
-
-            import sys
-            if isinstance(source, unicode) and sys.version_info < (3,):
-                from warnings import warn
-                warn("Received OpenCL source code in Unicode, "
-                        "should be ASCII string. Attempting conversion.", 
-                        stacklevel=2)
-                source = str(source)
-
-            self._context = context
-            self._source = source
-            self._prg = None
-        else:
-            # 3-argument form: context, devices, binaries
-            self._prg = _cl._Program(context, arg1, arg2)
-
-    def _get_prg(self):
-        if self._prg is not None:
-            return self._prg
-        else:
-            # "no program" can only happen in from-source case.
-            from warnings import warn
-            warn("Pre-build attribute access defeats compiler caching.", stacklevel=3)
-
-            self._prg = _cl._Program(self._context, self._source)
-            del self._context
-            del self._source
-            return self._prg
-
-    def get_info(self, arg):
-        return self._get_prg().get_info(arg)
-
-    def get_build_info(self, *args, **kwargs):
-        return self._get_prg().get_build_info(*args, **kwargs)
-
-    def all_kernels(self):
-        return self._get_prg().all_kernels()
-
-    def __getattr__(self, attr):
-        try:
-            knl = Kernel(self._get_prg(), attr)
-            # Nvidia does not raise errors even for invalid names,
-            # but this will give an error if the kernel is invalid.
-            knl.num_args
-            return knl
-        except LogicError:
-            raise AttributeError("'%s' was not found as a program "
-                    "info attribute or as a kernel name" % attr)
-
-    def build(self, options=[], devices=None, cache_dir=None):
-        if isinstance(options, str):
-            options = [options]
-
-        options = options + ["-I", _find_pyopencl_include_path()]
-
-        if self._prg is not None:
-            self._prg._build(options, devices)
-        else:
-            from pyopencl.cache import create_built_program_from_source_cached
-            self._prg = create_built_program_from_source_cached(
-                    self._context, self._source, options, devices,
-                    cache_dir=cache_dir)
-
-        return self
-
-    # }}}
-
 # {{{ convenience -------------------------------------------------------------
 def create_some_context(interactive=True, answers=None):
     import os