bazelbuild / rules_closure

Closure rules for Bazel
https://developers.google.com/closure
Apache License 2.0
152 stars 114 forks source link

Implement closure_template_py_library() #14

Open jart opened 8 years ago

jart commented 8 years ago

This feature was requested by @kjiwa.

wolfgangmeyers commented 8 years ago

Any more details?

jart commented 8 years ago

It simply isn't implemented. Soy compilation is implemented for java and js though. Why do you ask? Do you need this functionality?

kjiwa commented 8 years ago

I took a preliminary stab at implementing this, based on the code in closure_js_template_library.bzl. I found the overall implementation can look very similar as the tools to generate JS and PY code have similar options. However, one problematic option is SoyToPySrcCompiler's --runtimePath, which is expected to be a Python import path (using dot notation) to the python/ directory (https://github.com/google/closure-templates/tree/master/python).

The two things I came up against:

  1. How do I reference the location of this directory from within the BZL file?
  2. Dot notation means directories cannot have characters like '-' or '.'. One workaround might be to set the PYTHONPATH environment variable before executing the SoyToPySrcCompiler.
jart commented 8 years ago

First asking the obvious: have you checked out the imports attribute in the Python rules?

If you want to turn the current directory into a python package name, I would recommend something like the following:

def _label_to_package(ctx, label):
  pkg = []
  root = label.workspace_root
  if root:
    if root.startswith('external/'):
      root = root[len('external/'):]
    pkg.extend(root.split('/'))
  elif ctx.workspace_name != '__main__':
    pkg.append(ctx.workspace_name)
  if label.package:
    pkg.extend(label.package.split('/'))
  return pkg

def _package_to_py(pkg): # might return empty string
  return '.'.join(pkg)

Then you can say _package_to_py(_label_to_package(ctx, ctx.label)).

Dealing with directories in Bazel is difficult. Canonicalizing labels into package names is something I still need to clean up better for JS ES6 modules. I think the code above should do a pretty good job for Label objects. But it would have to be rewritten if the input is a File object.

As for package names with stuff like hyphens, I say just let the code fail. This is the behavior internally at Google I know for protobuf. Some languages, like TypeScript when it's compiled to goog.module code will replace weird characters with $XX. But Python doesn't let you have $ so like I said, probably better to just generate code that will fail.

jart commented 8 years ago

Also thank you for taking the time to contribute!