Skip to main content

MetaContext

It’s always been possible to write domain specific languages in python, but it’s rigid syntax, the lack of smalltalk like “blocks” (or at least anonymous closures which can contain statements) make it hard, if not impossible, to design slick DSL.

This library provides a powerful language extension mechanism that tries to follow the python language design principles and avoid creating confusing syntax constructs that will break compatibilities with editor extensions such as emacs flymake.

With MetaContext you can define macros which can manipulate the AST of it’s body and inject abitrary code.

Example

Imagine you want to build a pattern matching construct. Without MetaContext you could design the DSL like this:

with pattern_match(msg) as case:

  @case(('something', ANY))
  def _(value):
     do_something_with(value)

  @case(('error', ANY))
  def _(e):
     handle_error(e)

The pattern_match context manager can check if at least one case has been executed and raise a NoMatch exception otherwise.

However this DSL has two problems:

  1. It’s more verbose than necessary

  2. It requires the case mangers to be contained in closures which cannot break out of loops, perform (non local) returns, yield out of a generator etc.

With MetaContext you can define the DSL as:

with pattern_match(msg):
  with case(('something', ANY)) as value:
     do_something_with(value)
  with case(('error', ANY)) as e:
     handle_error(e)

This construct will allow you to interact nicely with generator based coroutines (like twisted inline callbacks):

with pattern_match(msg):
  with case(('something', ANY)) as value:
     res = yield do_something_with(value)
     do_something_else(res)
  with case(('error', ANY)) as e:
     handle_error(e)

Or perform returns:

with pattern_match(msg):
  with case(('something', ANY)) as value:
     res = do_something_with(value)
     if is_it_the_correct_one(res):
       return
  with case(ANY):
     pass

Another possible use case is retryng a body in case of exceptions:

with retry(IOException):
  do_something()
  do_something_else()

Which would have been written as:

while True:
  try:
    do_something()
    do_something_else()
  except IOException:
    pass
  else:
    break

How to create your own meta context mangers

Just create a Keyword subclass:

class retry(Keyword):
   def __init__(self, *excs):
      self.exceptions = excs

   def transform(self, translator, body, args, var):
      # ... return a transformed python AST object
      # you will get the `with` body in `body`

How to use your meta context manger

If you want to use your meta context manger, you first have to register the MetaContext import hook:

import metacontext
metacontext.register_importer_hook()

Then every source file that imports a symbol that resolves to a subclass of Keyword will be intercepted by the import hook and it’s AST will be given to the meta context mangers which will usually transform the body of the with statement:

from yourpackage.retrymanger import retry

# ...

with retry():
  # ....

Macro definition language

Maniuplating the AST directly is a verbose and cumbersome process, especially since you have to care about preserving original line number information for debugging and stack trace purposes.

MetaContext offers a macro definition DSL that you can use to quickly create your own meta context mangers:

The macro definition DSL itself is built using MetaContext constructs:

class retry(Keyword):
   def __init__(self, *excs):
      self.exceptions = excs

   def template(self, translator, body, args, var):
      with quote() as q:
        while True:
          try:
            unquote_stmts(body)
          except IOException:
            pass
          else:
            break

      return q

The MetaContext library will do it’s best to preserve the original line number of the unquoted statements so that you can seamlessly use your constructs in your sources as if they were native python.

Notes

Currently, since the library is in development, the modules which you want to transform with MetaContext have to contain this line as the first line of their source:

#- LANGUAGE compile-time-context-manager -#

This restriction will be lifted as soon as we make sure we can correctly handle all the import hook rough edges.

Metadata

Release files for metacontext 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for metacontext 0.2.2
File Size Uploaded
metacontext-0.2.2.tar.gz 9.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for metacontext 0.2.2
File Interpreter ABI Platform
metacontext-0.2.2-py2.7.egg Legacy Egg format - - Details

Total release size: 31.2 kB

Release files / metacontext-0.2.2.tar.gz

Download URL metacontext-0.2.2.tar.gz
Size 9.2 kB
Tags Source
SHA-256 checksum
How to use checksums
7bdd2f507a1e4d304508ef8f8216d132f98606c7b96813f4164d39df3c49d536
BLAKE2b-256 checksum
How to use checksums
9314ebdf5411c510bbe556fa1d9cc76cb98e8ae222784cde87b91d3e5fc78ca8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release files / metacontext-0.2.2-py2.7.egg

Download URL metacontext-0.2.2-py2.7.egg
Size 22.0 kB
Tags Egg
SHA-256 checksum
How to use checksums
36331eced6b4ba42da5a8da41765f5a10cdaeb5499f452d4fcf167aef9e4fed0
BLAKE2b-256 checksum
How to use checksums
96f3eb12132597720fae515c82225b253623012854f12a39aaba371f2b6d3b32
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 release files

0.2.1

2 release files

0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page