File chromium-enable-vaapi.patch of Package chromium.openSUSE_13.1_Update

diff -urNB chromium-48.0.2564.82/chrome/browser/about_flags.cc new/chrome/browser/about_flags.cc
--- chromium-48.0.2564.82/chrome/browser/about_flags.cc	2016-01-20 21:01:19.000000000 +0100
+++ new/chrome/browser/about_flags.cc	2016-01-23 17:52:38.785820994 +0100
@@ -1017,7 +1017,7 @@
      "disable-accelerated-video-decode",
      IDS_FLAGS_DISABLE_ACCELERATED_VIDEO_DECODE_NAME,
      IDS_FLAGS_DISABLE_ACCELERATED_VIDEO_DECODE_DESCRIPTION,
-     kOsMac | kOsWin | kOsCrOS,
+     kOsMac | kOsWin | kOsCrOS | kOsLinux,
      SINGLE_VALUE_TYPE(switches::kDisableAcceleratedVideoDecode),
     },
 #if defined(USE_ASH)
diff -urNB chromium-48.0.2564.82/content/common/gpu/media/gpu_jpeg_decode_accelerator.cc new/content/common/gpu/media/gpu_jpeg_decode_accelerator.cc
--- chromium-48.0.2564.82/content/common/gpu/media/gpu_jpeg_decode_accelerator.cc	2016-01-20 21:01:21.000000000 +0100
+++ new/content/common/gpu/media/gpu_jpeg_decode_accelerator.cc	2016-01-23 17:51:10.502723081 +0100
@@ -20,7 +20,7 @@
 #include "media/filters/jpeg_parser.h"
 #include "ui/gfx/geometry/size.h"
 
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
 #if defined(ARCH_CPU_X86_FAMILY)
 #include "content/common/gpu/media/vaapi_jpeg_decode_accelerator.h"
 #endif
@@ -402,7 +402,7 @@
 GpuJpegDecodeAccelerator::CreateV4L2JDA(
     const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) {
   scoped_ptr<media::JpegDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(USE_V4L2_CODEC)
   scoped_refptr<V4L2Device> device = V4L2Device::Create(
       V4L2Device::kJpegDecoder);
   if (device)
@@ -416,7 +416,7 @@
 GpuJpegDecodeAccelerator::CreateVaapiJDA(
     const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) {
   scoped_ptr<media::JpegDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(ARCH_CPU_X86_FAMILY)
   decoder.reset(new VaapiJpegDecodeAccelerator(io_task_runner));
 #endif
   return decoder.Pass();
diff -urNB chromium-48.0.2564.82/content/common/gpu/media/gpu_video_decode_accelerator.cc new/content/common/gpu/media/gpu_video_decode_accelerator.cc
--- chromium-48.0.2564.82/content/common/gpu/media/gpu_video_decode_accelerator.cc	2016-01-20 21:01:21.000000000 +0100
+++ new/content/common/gpu/media/gpu_video_decode_accelerator.cc	2016-01-23 17:55:00.068430421 +0100
@@ -33,7 +33,7 @@
 #include "content/common/gpu/media/dxva_video_decode_accelerator.h"
 #elif defined(OS_MACOSX)
 #include "content/common/gpu/media/vt_video_decode_accelerator.h"
-#elif defined(OS_CHROMEOS)
+#elif defined(OS_CHROMEOS) || defined(OS_LINUX)
 #if defined(USE_V4L2_CODEC)
 #include "content/common/gpu/media/v4l2_device.h"
 #include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h"
@@ -164,7 +164,7 @@
   // can be initialized by corresponding VDA successfully.
 #if defined(OS_WIN)
   profiles = DXVAVideoDecodeAccelerator::GetSupportedProfiles();
-#elif defined(OS_CHROMEOS)
+#elif defined(OS_CHROMEOS) || defined(OS_LINUX)
   media::VideoDecodeAccelerator::SupportedProfiles vda_profiles;
 #if defined(USE_V4L2_CODEC)
   vda_profiles = V4L2VideoDecodeAccelerator::GetSupportedProfiles();
@@ -389,7 +389,7 @@
 scoped_ptr<media::VideoDecodeAccelerator>
 GpuVideoDecodeAccelerator::CreateV4L2VDA() {
   scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(USE_V4L2_CODEC)
   scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
   if (device.get()) {
     decoder.reset(new V4L2VideoDecodeAccelerator(
@@ -407,7 +407,7 @@
 scoped_ptr<media::VideoDecodeAccelerator>
 GpuVideoDecodeAccelerator::CreateV4L2SliceVDA() {
   scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(USE_V4L2_CODEC)
   scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
   if (device.get()) {
     decoder.reset(new V4L2SliceVideoDecodeAccelerator(
@@ -438,7 +438,7 @@
 scoped_ptr<media::VideoDecodeAccelerator>
 GpuVideoDecodeAccelerator::CreateVaapiVDA() {
   scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(ARCH_CPU_X86_FAMILY)
   decoder.reset(new VaapiVideoDecodeAccelerator(
       make_context_current_, base::Bind(&GpuVideoDecodeAccelerator::BindImage,
                                         base::Unretained(this))));
diff -urNB chromium-48.0.2564.82/content/common/gpu/media/gpu_video_encode_accelerator.cc new/content/common/gpu/media/gpu_video_encode_accelerator.cc
--- chromium-48.0.2564.82/content/common/gpu/media/gpu_video_encode_accelerator.cc	2016-01-20 21:01:21.000000000 +0100
+++ new/content/common/gpu/media/gpu_video_encode_accelerator.cc	2016-01-23 17:51:10.506723039 +0100
@@ -20,7 +20,7 @@
 #include "media/base/limits.h"
 #include "media/base/video_frame.h"
 
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
 #if defined(USE_V4L2_CODEC)
 #include "content/common/gpu/media/v4l2_video_encode_accelerator.h"
 #endif
@@ -197,7 +197,7 @@
 scoped_ptr<media::VideoEncodeAccelerator>
 GpuVideoEncodeAccelerator::CreateV4L2VEA() {
   scoped_ptr<media::VideoEncodeAccelerator> encoder;
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(USE_V4L2_CODEC)
   scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder);
   if (device)
     encoder.reset(new V4L2VideoEncodeAccelerator(device));
@@ -209,7 +209,7 @@
 scoped_ptr<media::VideoEncodeAccelerator>
 GpuVideoEncodeAccelerator::CreateVaapiVEA() {
   scoped_ptr<media::VideoEncodeAccelerator> encoder;
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(ARCH_CPU_X86_FAMILY)
   const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
   if (!cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode))
     encoder.reset(new VaapiVideoEncodeAccelerator());
diff -urNB chromium-48.0.2564.82/content/common/gpu/media/vaapi_wrapper.cc new/content/common/gpu/media/vaapi_wrapper.cc
--- chromium-48.0.2564.82/content/common/gpu/media/vaapi_wrapper.cc	2016-01-20 21:01:21.000000000 +0100
+++ new/content/common/gpu/media/vaapi_wrapper.cc	2016-01-23 17:51:10.506723039 +0100
@@ -312,7 +312,9 @@
   static bool vaapi_functions_initialized = PostSandboxInitialization();
   if (!vaapi_functions_initialized) {
     bool running_on_chromeos = false;
-#if defined(OS_CHROMEOS)
+#if defined(OS_LINUX)
+    running_on_chromeos = true;
+#elif defined(OS_CHROMEOS)
     // When chrome runs on linux with chromeos=1, do not log error message
     // without VAAPI libraries.
     running_on_chromeos = base::SysInfo::IsRunningOnChromeOS();
diff -urNB chromium-48.0.2564.82/content/common/sandbox_linux/bpf_gpu_policy_linux.cc new/content/common/sandbox_linux/bpf_gpu_policy_linux.cc
--- chromium-48.0.2564.82/content/common/sandbox_linux/bpf_gpu_policy_linux.cc	2016-01-20 21:01:21.000000000 +0100
+++ new/content/common/sandbox_linux/bpf_gpu_policy_linux.cc	2016-01-23 17:51:10.506723039 +0100
@@ -21,6 +21,8 @@
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
 #include "build/build_config.h"
+// Auto-generated for dlopen libva libraries
+#include "content/common/gpu/media/va_stubs.h"
 #include "content/common/sandbox_linux/sandbox_bpf_base_policy_linux.h"
 #include "content/common/sandbox_linux/sandbox_seccomp_bpf_linux.h"
 #include "content/common/set_process_title.h"
@@ -31,6 +33,8 @@
 #include "sandbox/linux/syscall_broker/broker_file_permission.h"
 #include "sandbox/linux/syscall_broker/broker_process.h"
 #include "sandbox/linux/system_headers/linux_syscalls.h"
+#include "third_party/libva/va/va.h"
+#include "third_party/libva/va/va_x11.h"
 
 using sandbox::arch_seccomp_data;
 using sandbox::bpf_dsl::Allow;
@@ -40,6 +44,11 @@
 using sandbox::syscall_broker::BrokerProcess;
 using sandbox::SyscallSets;
 
+using content_common_gpu_media::kModuleVa;
+using content_common_gpu_media::kModuleVa_x11;
+using content_common_gpu_media::InitializeStubs;
+using content_common_gpu_media::StubPathMap;
+
 namespace content {
 
 namespace {
@@ -94,7 +103,7 @@
 
 bool IsAcceleratedVaapiVideoEncodeEnabled() {
   bool accelerated_encode_enabled = false;
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
   accelerated_encode_enabled =
@@ -299,27 +308,41 @@
     // inside the sandbox, so preload them now.
     if (IsAcceleratedVaapiVideoEncodeEnabled() ||
         IsAcceleratedVideoDecodeEnabled()) {
-      const char* I965DrvVideoPath = NULL;
-      const char* I965HybridDrvVideoPath = NULL;
+      DVLOG(1) << "Attempting to enable hardware video acceleration.";
+      StubPathMap paths;
+      paths[kModuleVa].push_back("libva.so.1");
+      paths[kModuleVa_x11].push_back("libva-x11.so.1");
+      if (!InitializeStubs(paths)) {
+        DVLOG(1) << "Failed to initialize stubs";
+        return false;
+      }
 
-      if (IsArchitectureX86_64()) {
-        I965DrvVideoPath = "/usr/lib64/va/drivers/i965_drv_video.so";
-        I965HybridDrvVideoPath = "/usr/lib64/va/drivers/hybrid_drv_video.so";
-      } else if (IsArchitectureI386()) {
-        I965DrvVideoPath = "/usr/lib/va/drivers/i965_drv_video.so";
+      // libva drivers won't get loaded even above two libraries get dlopened.
+      // Thus, libva calls will fail after post sandbox stage.
+      //
+      // To get the va driver loaded before sandboxing, upstream simply dlopen
+      // the hard-coded va driver path because ChromeOS is the only platform
+      // that Google want to support libva.
+      //
+      // While generic linux distros ship va driver as anywhere they want.
+      // Fortunately, the va driver will be loadded when vaInitialize() get
+      // called.
+      // So the following code is to call vaInitialize() before sandboxing.
+      Display* x_display = XOpenDisplay(NULL);
+      VADisplay va_display = vaGetDisplay(x_display);
+      if (!vaDisplayIsValid(va_display)) {
+        DVLOG(1) << "Failed to call vaGetDisplay()";
+        return false;
       }
 
-      dlopen(I965DrvVideoPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
-      if (I965HybridDrvVideoPath)
-        dlopen(I965HybridDrvVideoPath, RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
-      dlopen("libva.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
-#if defined(USE_OZONE)
-      dlopen("libva-drm.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
-#elif defined(USE_X11)
-      dlopen("libva-x11.so.1", RTLD_NOW|RTLD_GLOBAL|RTLD_NODELETE);
-#endif
-    }
-  }
+      int major_version, minor_version;
+      if (vaInitialize(va_display, &major_version, &minor_version)
+          != VA_STATUS_SUCCESS) {
+        DVLOG(1) << "Failed to call vaInitialize()";
+        return false;
+      }
+    }  // end of IsAcceleratedVaapiVideoEncodeEnabled() || IsAcceleratedVideoDecodeEnabled()
+  }  // end of IsArchitectureX86_64() || IsArchitectureI386()
 
   return true;
 }
diff -urNB chromium-48.0.2564.82/content/content_common.gypi new/content/content_common.gypi
--- chromium-48.0.2564.82/content/content_common.gypi	2016-01-20 21:01:21.000000000 +0100
+++ new/content/content_common.gypi	2016-01-23 17:51:10.510722998 +0100
@@ -821,7 +821,7 @@
         'public/common/webrtc_ip_handling_policy.h',
       ],
     }],
-    ['use_v4lplugin==1 and chromeos==1', {
+    ['use_v4lplugin==1 and (chromeos==1 or desktop_linux==1)', {
       'defines': [
         'USE_LIBV4L2'
       ],
@@ -865,7 +865,7 @@
         },
       ],
     }],
-    ['chromeos==1', {
+    ['chromeos==1 or desktop_linux==1', {
       'sources': [
         'common/gpu/media/accelerated_video_decoder.h',
         'common/gpu/media/h264_decoder.cc',
@@ -882,7 +882,7 @@
         'common/gpu/media/vp9_picture.h',
       ],
     }],
-    ['chromeos==1 and use_v4l2_codec==1', {
+    ['(chromeos==1 or desktop_linux==1) and use_v4l2_codec==1', {
       'direct_dependent_settings': {
         'defines': [
           'USE_V4L2_CODEC'
@@ -915,13 +915,13 @@
         '<(DEPTH)/third_party/khronos',
       ],
     }],
-    ['target_arch == "arm" and chromeos == 1', {
+    ['target_arch == "arm" and (chromeos == 1 or desktop_linux==1)', {
       'sources': [
         'common/gpu/media/tegra_v4l2_device.cc',
         'common/gpu/media/tegra_v4l2_device.h',
       ],
     }],
-    ['target_arch != "arm" and chromeos == 1', {
+    ['target_arch != "arm" and (chromeos == 1 or desktop_linux==1)', {
       'dependencies': [
         '../media/media.gyp:media',
         '../third_party/libyuv/libyuv.gyp:libyuv',
diff -urNB chromium-48.0.2564.82/content/content_gpu.gypi new/content/content_gpu.gypi
--- chromium-48.0.2564.82/content/content_gpu.gypi	2016-01-14 02:49:23.000000000 +0100
+++ new/content/content_gpu.gypi	2016-01-23 17:51:10.510722998 +0100
@@ -38,7 +38,7 @@
         ],
       },
     }],
-    ['target_arch!="arm" and chromeos == 1', {
+    ['target_arch!="arm" and (chromeos == 1 or desktop_linux==1)', {
       'include_dirs': [
         '<(DEPTH)/third_party/libva',
       ],
diff -urNB chromium-48.0.2564.82/content/content_tests.gypi new/content/content_tests.gypi
--- chromium-48.0.2564.82/content/content_tests.gypi	2016-01-20 21:01:21.000000000 +0100
+++ new/content/content_tests.gypi	2016-01-23 17:51:10.510722998 +0100
@@ -1652,7 +1652,7 @@
         },
       ],
     }],
-    ['chromeos==1 or OS=="win" or OS=="android"', {
+    ['(chromeos==1 or desktop_linux==1) or OS=="win" or OS=="android"', {
       'targets': [
           {
             'target_name': 'video_decode_accelerator_unittest',
@@ -1721,7 +1721,7 @@
                   '../ui/gfx/x/gfx_x11.gyp:gfx_x11',
                 ],
               }],
-              ['use_ozone==1 and chromeos==1', {
+              ['use_ozone==1 and (chromeos==1 or desktop_linux==1)', {
                 'dependencies': [
                   '../ui/display/display.gyp:display',  # Used by rendering_helper.cc
                   '../ui/ozone/ozone.gyp:ozone',  # Used by rendering_helper.cc
@@ -1733,7 +1733,7 @@
           },
         ]
     }],
-    ['chromeos==1 and target_arch != "arm"', {
+    ['(chromeos==1 or desktop_linux==1) and target_arch != "arm"', {
       'targets': [
           {
             'target_name': 'vaapi_jpeg_decoder_unittest',
@@ -1765,7 +1765,7 @@
           }
         ]
     }],
-    ['chromeos==1', {
+    ['chromeos==1 or desktop_linux==1', {
       'targets': [
         {
           'target_name': 'video_encode_accelerator_unittest',
diff -urNB chromium-48.0.2564.82/content/gpu/gpu_main.cc new/content/gpu/gpu_main.cc
--- chromium-48.0.2564.82/content/gpu/gpu_main.cc	2016-01-20 21:01:21.000000000 +0100
+++ new/content/gpu/gpu_main.cc	2016-01-23 17:51:10.510722998 +0100
@@ -72,7 +72,7 @@
 #include "content/common/sandbox_mac.h"
 #endif
 
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(ARCH_CPU_X86_FAMILY)
 #include "content/common/gpu/media/vaapi_wrapper.h"
 #endif
 
@@ -237,7 +237,7 @@
   GetGpuInfoFromCommandLine(gpu_info, command_line);
   gpu_info.in_process_gpu = false;
 
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
+#if (defined(OS_CHROMEOS) || defined(OS_LINUX)) && defined(ARCH_CPU_X86_FAMILY)
   VaapiWrapper::PreSandboxInitialization();
 #endif
 
diff -urNB chromium-48.0.2564.82/content/public/common/content_switches.cc new/content/public/common/content_switches.cc
--- chromium-48.0.2564.82/content/public/common/content_switches.cc	2016-01-20 21:01:21.000000000 +0100
+++ new/content/public/common/content_switches.cc	2016-01-23 17:51:10.510722998 +0100
@@ -931,7 +931,9 @@
 #if defined(OS_CHROMEOS)
 // Disables panel fitting (used for mirror mode).
 const char kDisablePanelFitting[]           = "disable-panel-fitting";
+#endif
 
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
 // Disables VA-API accelerated video encode.
 const char kDisableVaapiAcceleratedVideoEncode[] =
     "disable-vaapi-accelerated-video-encode";
diff -urNB chromium-48.0.2564.82/content/public/common/content_switches.h new/content/public/common/content_switches.h
--- chromium-48.0.2564.82/content/public/common/content_switches.h	2016-01-20 21:01:21.000000000 +0100
+++ new/content/public/common/content_switches.h	2016-01-23 17:51:10.514722956 +0100
@@ -275,6 +275,8 @@
 
 #if defined(OS_CHROMEOS)
 CONTENT_EXPORT extern const char kDisablePanelFitting[];
+#endif
+#if defined(OS_CHROMEOS) || defined(OS_LINUX)
 CONTENT_EXPORT extern const char kDisableVaapiAcceleratedVideoEncode[];
 #endif
 
diff -urNB chromium-48.0.2564.82/gpu/config/software_rendering_list_json.cc new/gpu/config/software_rendering_list_json.cc
--- chromium-48.0.2564.82/gpu/config/software_rendering_list_json.cc	2016-01-20 21:01:22.000000000 +0100
+++ new/gpu/config/software_rendering_list_json.cc	2016-01-23 17:51:10.514722956 +0100
@@ -481,17 +481,6 @@
       ]
     },
     {
-      "id": 48,
-      "description": "Accelerated video decode is unavailable on Linux",
-      "cr_bugs": [137247],
-      "os": {
-        "type": "linux"
-      },
-      "features": [
-        "accelerated_video_decode"
-      ]
-    },
-    {
       "id": 49,
       "description": "NVidia GeForce GT 650M can cause the system to hang with flash 3D",
       "cr_bugs": [140175],
@@ -1041,6 +1030,11 @@
           }
         },
         {
+          "os": {
+            "type": "linux"
+          }
+        },
+        {
           "os": {
             "type": "android"
           },
diff -urNB chromium-48.0.2564.82/media/media.gyp new/media/media.gyp
--- chromium-48.0.2564.82/media/media.gyp	2016-01-20 21:01:22.000000000 +0100
+++ new/media/media.gyp	2016-01-23 17:51:10.514722956 +0100
@@ -764,7 +764,7 @@
           ],
         }],
         # For VaapiVideoEncodeAccelerator.
-        ['target_arch != "arm" and chromeos == 1', {
+        ['target_arch != "arm" and (chromeos == 1 or desktop_linux==1)', {
           'sources': [
             'filters/h264_bitstream_buffer.cc',
             'filters/h264_bitstream_buffer.h',
@@ -1398,7 +1398,7 @@
             'cdm/cdm_adapter_unittest.cc',
           ],
         }],
-        ['target_arch != "arm" and chromeos == 1 and use_x11 == 1', {
+        ['target_arch != "arm" and (chromeos == 1 or desktop_linux==1) and use_x11 == 1', {
           'sources': [
             'filters/h264_bitstream_buffer_unittest.cc',
           ],
diff -urNB chromium-48.0.2564.82/third_party/catapult/third_party/Paste/paste/urlmap.py.orig new/third_party/catapult/third_party/Paste/paste/urlmap.py.orig
--- chromium-48.0.2564.82/third_party/catapult/third_party/Paste/paste/urlmap.py.orig	2016-01-20 21:01:58.000000000 +0100
+++ new/third_party/catapult/third_party/Paste/paste/urlmap.py.orig	1970-01-01 01:00:00.000000000 +0100
@@ -1,263 +0,0 @@
-# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
-# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
-"""
-Map URL prefixes to WSGI applications.  See ``URLMap``
-"""
-
-import re
-import os
-import cgi
-try:
-    # Python 3
-    from collections import MutableMapping as DictMixin
-except ImportError:
-    # Python 2
-    from UserDict import DictMixin
-
-from paste import httpexceptions
-
-__all__ = ['URLMap', 'PathProxyURLMap']
-
-def urlmap_factory(loader, global_conf, **local_conf):
-    if 'not_found_app' in local_conf:
-        not_found_app = local_conf.pop('not_found_app')
-    else:
-        not_found_app = global_conf.get('not_found_app')
-    if not_found_app:
-        not_found_app = loader.get_app(not_found_app, global_conf=global_conf)
-    urlmap = URLMap(not_found_app=not_found_app)
-    for path, app_name in local_conf.items():
-        path = parse_path_expression(path)
-        app = loader.get_app(app_name, global_conf=global_conf)
-        urlmap[path] = app
-    return urlmap
-
-def parse_path_expression(path):
-    """
-    Parses a path expression like 'domain foobar.com port 20 /' or
-    just '/foobar' for a path alone.  Returns as an address that
-    URLMap likes.
-    """
-    parts = path.split()
-    domain = port = path = None
-    while parts:
-        if parts[0] == 'domain':
-            parts.pop(0)
-            if not parts:
-                raise ValueError("'domain' must be followed with a domain name")
-            if domain:
-                raise ValueError("'domain' given twice")
-            domain = parts.pop(0)
-        elif parts[0] == 'port':
-            parts.pop(0)
-            if not parts:
-                raise ValueError("'port' must be followed with a port number")
-            if port:
-                raise ValueError("'port' given twice")
-            port = parts.pop(0)
-        else:
-            if path:
-                raise ValueError("more than one path given (have %r, got %r)"
-                                 % (path, parts[0]))
-            path = parts.pop(0)
-    s = ''
-    if domain:
-        s = 'http://%s' % domain
-    if port:
-        if not domain:
-            raise ValueError("If you give a port, you must also give a domain")
-        s += ':' + port
-    if path:
-        if s:
-            s += '/'
-        s += path
-    return s
-
-class URLMap(DictMixin):
-
-    """
-    URLMap instances are dictionary-like object that dispatch to one
-    of several applications based on the URL.
-
-    The dictionary keys are URLs to match (like
-    ``PATH_INFO.startswith(url)``), and the values are applications to
-    dispatch to.  URLs are matched most-specific-first, i.e., longest
-    URL first.  The ``SCRIPT_NAME`` and ``PATH_INFO`` environmental
-    variables are adjusted to indicate the new context.
-
-    URLs can also include domains, like ``http://blah.com/foo``, or as
-    tuples ``('blah.com', '/foo')``.  This will match domain names; without
-    the ``http://domain`` or with a domain of ``None`` any domain will be
-    matched (so long as no other explicit domain matches).  """
-
-    def __init__(self, not_found_app=None):
-        self.applications = []
-        if not not_found_app:
-            not_found_app = self.not_found_app
-        self.not_found_application = not_found_app
-
-    def __len__(self):
-        return len(self.applications)
-
-    def __iter__(self):
-        for app_url, app in self.applications:
-            yield app_url
-
-    norm_url_re = re.compile('//+')
-    domain_url_re = re.compile('^(http|https)://')
-
-    def not_found_app(self, environ, start_response):
-        mapper = environ.get('paste.urlmap_object')
-        if mapper:
-            matches = [p for p, a in mapper.applications]
-            extra = 'defined apps: %s' % (
-                ',\n  '.join(map(repr, matches)))
-        else:
-            extra = ''
-        extra += '\nSCRIPT_NAME: %r' % cgi.escape(environ.get('SCRIPT_NAME'))
-        extra += '\nPATH_INFO: %r' % cgi.escape(environ.get('PATH_INFO'))
-        extra += '\nHTTP_HOST: %r' % cgi.escape(environ.get('HTTP_HOST'))
-        app = httpexceptions.HTTPNotFound(
-            environ['PATH_INFO'],
-            comment=cgi.escape(extra)).wsgi_application
-        return app(environ, start_response)
-
-    def normalize_url(self, url, trim=True):
-        if isinstance(url, (list, tuple)):
-            domain = url[0]
-            url = self.normalize_url(url[1])[1]
-            return domain, url
-        assert (not url or url.startswith('/')
-                or self.domain_url_re.search(url)), (
-            "URL fragments must start with / or http:// (you gave %r)" % url)
-        match = self.domain_url_re.search(url)
-        if match:
-            url = url[match.end():]
-            if '/' in url:
-                domain, url = url.split('/', 1)
-                url = '/' + url
-            else:
-                domain, url = url, ''
-        else:
-            domain = None
-        url = self.norm_url_re.sub('/', url)
-        if trim:
-            url = url.rstrip('/')
-        return domain, url
-
-    def sort_apps(self):
-        """
-        Make sure applications are sorted with longest URLs first
-        """
-        def key(app_desc):
-            (domain, url), app = app_desc
-            if not domain:
-                # Make sure empty domains sort last:
-                return '\xff', -len(url)
-            else:
-                return domain, -len(url)
-        apps = [(key(desc), desc) for desc in self.applications]
-        apps.sort()
-        self.applications = [desc for (sortable, desc) in apps]
-
-    def __setitem__(self, url, app):
-        if app is None:
-            try:
-                del self[url]
-            except KeyError:
-                pass
-            return
-        dom_url = self.normalize_url(url)
-        if dom_url in self:
-            del self[dom_url]
-        self.applications.append((dom_url, app))
-        self.sort_apps()
-
-    def __getitem__(self, url):
-        dom_url = self.normalize_url(url)
-        for app_url, app in self.applications:
-            if app_url == dom_url:
-                return app
-        raise KeyError(
-            "No application with the url %r (domain: %r; existing: %s)"
-            % (url[1], url[0] or '*', self.applications))
-
-    def __delitem__(self, url):
-        url = self.normalize_url(url)
-        for app_url, app in self.applications:
-            if app_url == url:
-                self.applications.remove((app_url, app))
-                break
-        else:
-            raise KeyError(
-                "No application with the url %r" % (url,))
-
-    def keys(self):
-        return [app_url for app_url, app in self.applications]
-
-    def __call__(self, environ, start_response):
-        host = environ.get('HTTP_HOST', environ.get('SERVER_NAME')).lower()
-        if ':' in host:
-            host, port = host.split(':', 1)
-        else:
-            if environ['wsgi.url_scheme'] == 'http':
-                port = '80'
-            else:
-                port = '443'
-        path_info = environ.get('PATH_INFO')
-        path_info = self.normalize_url(path_info, False)[1]
-        for (domain, app_url), app in self.applications:
-            if domain and domain != host and domain != host+':'+port:
-                continue
-            if (path_info == app_url
-                or path_info.startswith(app_url + '/')):
-                environ['SCRIPT_NAME'] += app_url
-                environ['PATH_INFO'] = path_info[len(app_url):]
-                return app(environ, start_response)
-        environ['paste.urlmap_object'] = self
-        return self.not_found_application(environ, start_response)
-
-
-class PathProxyURLMap(object):
-
-    """
-    This is a wrapper for URLMap that catches any strings that
-    are passed in as applications; these strings are treated as
-    filenames (relative to `base_path`) and are passed to the
-    callable `builder`, which will return an application.
-
-    This is intended for cases when configuration files can be
-    treated as applications.
-
-    `base_paste_url` is the URL under which all applications added through
-    this wrapper must go.  Use ``""`` if you want this to not
-    change incoming URLs.
-    """
-
-    def __init__(self, map, base_paste_url, base_path, builder):
-        self.map = map
-        self.base_paste_url = self.map.normalize_url(base_paste_url)
-        self.base_path = base_path
-        self.builder = builder
-
-    def __setitem__(self, url, app):
-        if isinstance(app, (str, unicode)):
-            app_fn = os.path.join(self.base_path, app)
-            app = self.builder(app_fn)
-        url = self.map.normalize_url(url)
-        # @@: This means http://foo.com/bar will potentially
-        # match foo.com, but /base_paste_url/bar, which is unintuitive
-        url = (url[0] or self.base_paste_url[0],
-               self.base_paste_url[1] + url[1])
-        self.map[url] = app
-
-    def __getattr__(self, attr):
-        return getattr(self.map, attr)
-
-    # This is really the only settable attribute
-    def not_found_application__get(self):
-        return self.map.not_found_application
-    def not_found_application__set(self, value):
-        self.map.not_found_application = value
-    not_found_application = property(not_found_application__get,
-                                     not_found_application__set)
diff -urNB chromium-48.0.2564.82/third_party/catapult/third_party/Paste/paste/util/template.py.orig new/third_party/catapult/third_party/Paste/paste/util/template.py.orig
--- chromium-48.0.2564.82/third_party/catapult/third_party/Paste/paste/util/template.py.orig	2016-01-20 21:01:58.000000000 +0100
+++ new/third_party/catapult/third_party/Paste/paste/util/template.py.orig	1970-01-01 01:00:00.000000000 +0100
@@ -1,762 +0,0 @@
-"""
-A small templating language
-
-This implements a small templating language for use internally in
-Paste and Paste Script.  This language implements if/elif/else,
-for/continue/break, expressions, and blocks of Python code.  The
-syntax is::
-
-  {{any expression (function calls etc)}}
-  {{any expression | filter}}
-  {{for x in y}}...{{endfor}}
-  {{if x}}x{{elif y}}y{{else}}z{{endif}}
-  {{py:x=1}}
-  {{py:
-  def foo(bar):
-      return 'baz'
-  }}
-  {{default var = default_value}}
-  {{# comment}}
-
-You use this with the ``Template`` class or the ``sub`` shortcut.
-The ``Template`` class takes the template string and the name of
-the template (for errors) and a default namespace.  Then (like
-``string.Template``) you can call the ``tmpl.substitute(**kw)``
-method to make a substitution (or ``tmpl.substitute(a_dict)``).
-
-``sub(content, **kw)`` substitutes the template immediately.  You
-can use ``__name='tmpl.html'`` to set the name of the template.
-
-If there are syntax errors ``TemplateError`` will be raised.
-"""
-
-import re
-import six
-import sys
-import cgi
-from six.moves.urllib.parse import quote
-from paste.util.looper import looper
-
-__all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate',
-           'sub_html', 'html', 'bunch']
-
-token_re = re.compile(r'\{\{|\}\}')
-in_re = re.compile(r'\s+in\s+')
-var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
-
-class TemplateError(Exception):
-    """Exception raised while parsing a template
-    """
-
-    def __init__(self, message, position, name=None):
-        self.message = message
-        self.position = position
-        self.name = name
-
-    def __str__(self):
-        msg = '%s at line %s column %s' % (
-            self.message, self.position[0], self.position[1])
-        if self.name:
-            msg += ' in %s' % self.name
-        return msg
-
-class _TemplateContinue(Exception):
-    pass
-
-class _TemplateBreak(Exception):
-    pass
-
-class Template(object):
-
-    default_namespace = {
-        'start_braces': '{{',
-        'end_braces': '}}',
-        'looper': looper,
-        }
-
-    default_encoding = 'utf8'
-
-    def __init__(self, content, name=None, namespace=None):
-        self.content = content
-        self._unicode = isinstance(content, six.text_type)
-        self.name = name
-
-        if not self._unicode:
-            content = content.decode(self.default_encoding)
-            self._unicode = True
-
-        self._parsed = parse(content, name=name)
-        if namespace is None:
-            namespace = {}
-        self.namespace = namespace
-
-    def from_filename(cls, filename, namespace=None, encoding=None):
-        f = open(filename, 'rb')
-        c = f.read()
-        f.close()
-        if encoding:
-            c = c.decode(encoding)
-        return cls(content=c, name=filename, namespace=namespace)
-
-    from_filename = classmethod(from_filename)
-
-    def __repr__(self):
-        return '<%s %s name=%r>' % (
-            self.__class__.__name__,
-            hex(id(self))[2:], self.name)
-
-    def substitute(self, *args, **kw):
-        if args:
-            if kw:
-                raise TypeError(
-                    "You can only give positional *or* keyword arguments")
-            if len(args) > 1:
-                raise TypeError(
-                    "You can only give on positional argument")
-            kw = args[0]
-        ns = self.default_namespace.copy()
-        ns.update(self.namespace)
-        ns.update(kw)
-        result = self._interpret(ns)
-        return result
-
-    def _interpret(self, ns):
-        __traceback_hide__ = True
-        parts = []
-        self._interpret_codes(self._parsed, ns, out=parts)
-        return ''.join(parts)
-
-    def _interpret_codes(self, codes, ns, out):
-        __traceback_hide__ = True
-        for item in codes:
-            if isinstance(item, six.string_types):
-                out.append(item)
-            else:
-                self._interpret_code(item, ns, out)
-
-    def _interpret_code(self, code, ns, out):
-        __traceback_hide__ = True
-        name, pos = code[0], code[1]
-        if name == 'py':
-            self._exec(code[2], ns, pos)
-        elif name == 'continue':
-            raise _TemplateContinue()
-        elif name == 'break':
-            raise _TemplateBreak()
-        elif name == 'for':
-            vars, expr, content = code[2], code[3], code[4]
-            expr = self._eval(expr, ns, pos)
-            self._interpret_for(vars, expr, content, ns, out)
-        elif name == 'cond':
-            parts = code[2:]
-            self._interpret_if(parts, ns, out)
-        elif name == 'expr':
-            parts = code[2].split('|')
-            base = self._eval(parts[0], ns, pos)
-            for part in parts[1:]:
-                func = self._eval(part, ns, pos)
-                base = func(base)
-            out.append(self._repr(base, pos))
-        elif name == 'default':
-            var, expr = code[2], code[3]
-            if var not in ns:
-                result = self._eval(expr, ns, pos)
-                ns[var] = result
-        elif name == 'comment':
-            return
-        else:
-            assert 0, "Unknown code: %r" % name
-
-    def _interpret_for(self, vars, expr, content, ns, out):
-        __traceback_hide__ = True
-        for item in expr:
-            if len(vars) == 1:
-                ns[vars[0]] = item
-            else:
-                if len(vars) != len(item):
-                    raise ValueError(
-                        'Need %i items to unpack (got %i items)'
-                        % (len(vars), len(item)))
-                for name, value in zip(vars, item):
-                    ns[name] = value
-            try:
-                self._interpret_codes(content, ns, out)
-            except _TemplateContinue:
-                continue
-            except _TemplateBreak:
-                break
-
-    def _interpret_if(self, parts, ns, out):
-        __traceback_hide__ = True
-        # @@: if/else/else gets through
-        for part in parts:
-            assert not isinstance(part, six.string_types)
-            name, pos = part[0], part[1]
-            if name == 'else':
-                result = True
-            else:
-                result = self._eval(part[2], ns, pos)
-            if result:
-                self._interpret_codes(part[3], ns, out)
-                break
-
-    def _eval(self, code, ns, pos):
-        __traceback_hide__ = True
-        try:
-            value = eval(code, ns)
-            return value
-        except:
-            exc_info = sys.exc_info()
-            e = exc_info[1]
-            if getattr(e, 'args'):
-                arg0 = e.args[0]
-            else:
-                arg0 = str(e)
-            e.args = (self._add_line_info(arg0, pos),)
-            six.reraise(exc_info[0], e, exc_info[2])
-
-    def _exec(self, code, ns, pos):
-        __traceback_hide__ = True
-        try:
-            six.exec_(code, ns)
-        except:
-            exc_info = sys.exc_info()
-            e = exc_info[1]
-            e.args = (self._add_line_info(e.args[0], pos),)
-            six.reraise(exc_info[0], e, exc_info[2])
-
-    def _repr(self, value, pos):
-        __traceback_hide__ = True
-        try:
-            if value is None:
-                return ''
-            if self._unicode:
-                try:
-                    value = six.text_type(value)
-                except UnicodeDecodeError:
-                    value = str(value)
-            else:
-                value = str(value)
-        except:
-            exc_info = sys.exc_info()
-            e = exc_info[1]
-            e.args = (self._add_line_info(e.args[0], pos),)
-            six.reraise(exc_info[0], e, exc_info[2])
-        else:
-            if self._unicode and isinstance(value, six.binary_type):
-                if not self.default_encoding:
-                    raise UnicodeDecodeError(
-                        'Cannot decode str value %r into unicode '
-                        '(no default_encoding provided)' % value)
-                value = value.decode(self.default_encoding)
-            elif not self._unicode and isinstance(value, six.text_type):
-                if not self.default_encoding:
-                    raise UnicodeEncodeError(
-                        'Cannot encode unicode value %r into str '
-                        '(no default_encoding provided)' % value)
-                value = value.encode(self.default_encoding)
-            return value
-
-
-    def _add_line_info(self, msg, pos):
-        msg = "%s at line %s column %s" % (
-            msg, pos[0], pos[1])
-        if self.name:
-            msg += " in file %s" % self.name
-        return msg
-
-def sub(content, **kw):
-    name = kw.get('__name')
-    tmpl = Template(content, name=name)
-    return tmpl.substitute(kw)
-
-def paste_script_template_renderer(content, vars, filename=None):
-    tmpl = Template(content, name=filename)
-    return tmpl.substitute(vars)
-
-class bunch(dict):
-
-    def __init__(self, **kw):
-        for name, value in kw.items():
-            setattr(self, name, value)
-
-    def __setattr__(self, name, value):
-        self[name] = value
-
-    def __getattr__(self, name):
-        try:
-            return self[name]
-        except KeyError:
-            raise AttributeError(name)
-
-    def __getitem__(self, key):
-        if 'default' in self:
-            try:
-                return dict.__getitem__(self, key)
-            except KeyError:
-                return dict.__getitem__(self, 'default')
-        else:
-            return dict.__getitem__(self, key)
-
-    def __repr__(self):
-        items = [
-            (k, v) for k, v in self.items()]
-        items.sort()
-        return '<%s %s>' % (
-            self.__class__.__name__,
-            ' '.join(['%s=%r' % (k, v) for k, v in items]))
-
-############################################################
-## HTML Templating
-############################################################
-
-class html(object):
-    def __init__(self, value):
-        self.value = value
-    def __str__(self):
-        return self.value
-    def __repr__(self):
-        return '<%s %r>' % (
-            self.__class__.__name__, self.value)
-
-def html_quote(value):
-    if value is None:
-        return ''
-    if not isinstance(value, six.string_types):
-        if hasattr(value, '__unicode__'):
-            value = unicode(value)
-        else:
-            value = str(value)
-    value = cgi.escape(value, 1)
-    if isinstance(value, unicode):
-        value = value.encode('ascii', 'xmlcharrefreplace')
-    return value
-
-def url(v):
-    if not isinstance(v, six.string_types):
-        if hasattr(v, '__unicode__'):
-            v = unicode(v)
-        else:
-            v = str(v)
-    if isinstance(v, unicode):
-        v = v.encode('utf8')
-    return quote(v)
-
-def attr(**kw):
-    kw = kw.items()
-    kw.sort()
-    parts = []
-    for name, value in kw:
-        if value is None:
-            continue
-        if name.endswith('_'):
-            name = name[:-1]
-        parts.append('%s="%s"' % (html_quote(name), html_quote(value)))
-    return html(' '.join(parts))
-
-class HTMLTemplate(Template):
-
-    default_namespace = Template.default_namespace.copy()
-    default_namespace.update(dict(
-        html=html,
-        attr=attr,
-        url=url,
-        ))
-
-    def _repr(self, value, pos):
-        plain = Template._repr(self, value, pos)
-        if isinstance(value, html):
-            return plain
-        else:
-            return html_quote(plain)
-
-def sub_html(content, **kw):
-    name = kw.get('__name')
-    tmpl = HTMLTemplate(content, name=name)
-    return tmpl.substitute(kw)
-
-
-############################################################
-## Lexing and Parsing
-############################################################
-
-def lex(s, name=None, trim_whitespace=True):
-    """
-    Lex a string into chunks:
-
-        >>> lex('hey')
-        ['hey']
-        >>> lex('hey {{you}}')
-        ['hey ', ('you', (1, 7))]
-        >>> lex('hey {{')
-        Traceback (most recent call last):
-            ...
-        TemplateError: No }} to finish last expression at line 1 column 7
-        >>> lex('hey }}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: }} outside expression at line 1 column 7
-        >>> lex('hey {{ {{')
-        Traceback (most recent call last):
-            ...
-        TemplateError: {{ inside expression at line 1 column 10
-
-    """
-    in_expr = False
-    chunks = []
-    last = 0
-    last_pos = (1, 1)
-    for match in token_re.finditer(s):
-        expr = match.group(0)
-        pos = find_position(s, match.end())
-        if expr == '{{' and in_expr:
-            raise TemplateError('{{ inside expression', position=pos,
-                                name=name)
-        elif expr == '}}' and not in_expr:
-            raise TemplateError('}} outside expression', position=pos,
-                                name=name)
-        if expr == '{{':
-            part = s[last:match.start()]
-            if part:
-                chunks.append(part)
-            in_expr = True
-        else:
-            chunks.append((s[last:match.start()], last_pos))
-            in_expr = False
-        last = match.end()
-        last_pos = pos
-    if in_expr:
-        raise TemplateError('No }} to finish last expression',
-                            name=name, position=last_pos)
-    part = s[last:]
-    if part:
-        chunks.append(part)
-    if trim_whitespace:
-        chunks = trim_lex(chunks)
-    return chunks
-
-statement_re = re.compile(r'^(?:if |elif |else |for |py:)')
-single_statements = ['endif', 'endfor', 'continue', 'break']
-trail_whitespace_re = re.compile(r'\n[\t ]*$')
-lead_whitespace_re = re.compile(r'^[\t ]*\n')
-
-def trim_lex(tokens):
-    r"""
-    Takes a lexed set of tokens, and removes whitespace when there is
-    a directive on a line by itself:
-
-       >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False)
-       >>> tokens
-       [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny']
-       >>> trim_lex(tokens)
-       [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y']
-    """
-    for i in range(len(tokens)):
-        current = tokens[i]
-        if isinstance(tokens[i], six.string_types):
-            # we don't trim this
-            continue
-        item = current[0]
-        if not statement_re.search(item) and item not in single_statements:
-            continue
-        if not i:
-            prev = ''
-        else:
-            prev = tokens[i-1]
-        if i+1 >= len(tokens):
-            next = ''
-        else:
-            next = tokens[i+1]
-        if (not isinstance(next, six.string_types)
-            or not isinstance(prev, six.string_types)):
-            continue
-        if ((not prev or trail_whitespace_re.search(prev))
-            and (not next or lead_whitespace_re.search(next))):
-            if prev:
-                m = trail_whitespace_re.search(prev)
-                # +1 to leave the leading \n on:
-                prev = prev[:m.start()+1]
-                tokens[i-1] = prev
-            if next:
-                m = lead_whitespace_re.search(next)
-                next = next[m.end():]
-                tokens[i+1] = next
-    return tokens
-
-
-def find_position(string, index):
-    """Given a string and index, return (line, column)"""
-    leading = string[:index].splitlines()
-    return (len(leading), len(leading[-1])+1)
-
-def parse(s, name=None):
-    r"""
-    Parses a string into a kind of AST
-
-        >>> parse('{{x}}')
-        [('expr', (1, 3), 'x')]
-        >>> parse('foo')
-        ['foo']
-        >>> parse('{{if x}}test{{endif}}')
-        [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))]
-        >>> parse('series->{{for x in y}}x={{x}}{{endfor}}')
-        ['series->', ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])]
-        >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}')
-        [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])]
-        >>> parse('{{py:x=1}}')
-        [('py', (1, 3), 'x=1')]
-        >>> parse('{{if x}}a{{elif y}}b{{else}}c{{endif}}')
-        [('cond', (1, 3), ('if', (1, 3), 'x', ['a']), ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))]
-
-    Some exceptions::
-
-        >>> parse('{{continue}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: continue outside of for loop at line 1 column 3
-        >>> parse('{{if x}}foo')
-        Traceback (most recent call last):
-            ...
-        TemplateError: No {{endif}} at line 1 column 3
-        >>> parse('{{else}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: else outside of an if block at line 1 column 3
-        >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: Unexpected endif at line 1 column 25
-        >>> parse('{{if}}{{endif}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: if with no expression at line 1 column 3
-        >>> parse('{{for x y}}{{endfor}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: Bad for (no "in") in 'x y' at line 1 column 3
-        >>> parse('{{py:x=1\ny=2}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: Multi-line py blocks must start with a newline at line 1 column 3
-    """
-    tokens = lex(s, name=name)
-    result = []
-    while tokens:
-        next, tokens = parse_expr(tokens, name)
-        result.append(next)
-    return result
-
-def parse_expr(tokens, name, context=()):
-    if isinstance(tokens[0], six.string_types):
-        return tokens[0], tokens[1:]
-    expr, pos = tokens[0]
-    expr = expr.strip()
-    if expr.startswith('py:'):
-        expr = expr[3:].lstrip(' \t')
-        if expr.startswith('\n'):
-            expr = expr[1:]
-        else:
-            if '\n' in expr:
-                raise TemplateError(
-                    'Multi-line py blocks must start with a newline',
-                    position=pos, name=name)
-        return ('py', pos, expr), tokens[1:]
-    elif expr in ('continue', 'break'):
-        if 'for' not in context:
-            raise TemplateError(
-                'continue outside of for loop',
-                position=pos, name=name)
-        return (expr, pos), tokens[1:]
-    elif expr.startswith('if '):
-        return parse_cond(tokens, name, context)
-    elif (expr.startswith('elif ')
-          or expr == 'else'):
-        raise TemplateError(
-            '%s outside of an if block' % expr.split()[0],
-            position=pos, name=name)
-    elif expr in ('if', 'elif', 'for'):
-        raise TemplateError(
-            '%s with no expression' % expr,
-            position=pos, name=name)
-    elif expr in ('endif', 'endfor'):
-        raise TemplateError(
-            'Unexpected %s' % expr,
-            position=pos, name=name)
-    elif expr.startswith('for '):
-        return parse_for(tokens, name, context)
-    elif expr.startswith('default '):
-        return parse_default(tokens, name, context)
-    elif expr.startswith('#'):
-        return ('comment', pos, tokens[0][0]), tokens[1:]
-    return ('expr', pos, tokens[0][0]), tokens[1:]
-
-def parse_cond(tokens, name, context):
-    start = tokens[0][1]
-    pieces = []
-    context = context + ('if',)
-    while 1:
-        if not tokens:
-            raise TemplateError(
-                'Missing {{endif}}',
-                position=start, name=name)
-        if (isinstance(tokens[0], tuple)
-            and tokens[0][0] == 'endif'):
-            return ('cond', start) + tuple(pieces), tokens[1:]
-        next, tokens = parse_one_cond(tokens, name, context)
-        pieces.append(next)
-
-def parse_one_cond(tokens, name, context):
-    (first, pos), tokens = tokens[0], tokens[1:]
-    content = []
-    if first.endswith(':'):
-        first = first[:-1]
-    if first.startswith('if '):
-        part = ('if', pos, first[3:].lstrip(), content)
-    elif first.startswith('elif '):
-        part = ('elif', pos, first[5:].lstrip(), content)
-    elif first == 'else':
-        part = ('else', pos, None, content)
-    else:
-        assert 0, "Unexpected token %r at %s" % (first, pos)
-    while 1:
-        if not tokens:
-            raise TemplateError(
-                'No {{endif}}',
-                position=pos, name=name)
-        if (isinstance(tokens[0], tuple)
-            and (tokens[0][0] == 'endif'
-                 or tokens[0][0].startswith('elif ')
-                 or tokens[0][0] == 'else')):
-            return part, tokens
-        next, tokens = parse_expr(tokens, name, context)
-        content.append(next)
-
-def parse_for(tokens, name, context):
-    first, pos = tokens[0]
-    tokens = tokens[1:]
-    context = ('for',) + context
-    content = []
-    assert first.startswith('for ')
-    if first.endswith(':'):
-        first = first[:-1]
-    first = first[3:].strip()
-    match = in_re.search(first)
-    if not match:
-        raise TemplateError(
-            'Bad for (no "in") in %r' % first,
-            position=pos, name=name)
-    vars = first[:match.start()]
-    if '(' in vars:
-        raise TemplateError(
-            'You cannot have () in the variable section of a for loop (%r)'
-            % vars, position=pos, name=name)
-    vars = tuple([
-        v.strip() for v in first[:match.start()].split(',')
-        if v.strip()])
-    expr = first[match.end():]
-    while 1:
-        if not tokens:
-            raise TemplateError(
-                'No {{endfor}}',
-                position=pos, name=name)
-        if (isinstance(tokens[0], tuple)
-            and tokens[0][0] == 'endfor'):
-            return ('for', pos, vars, expr, content), tokens[1:]
-        next, tokens = parse_expr(tokens, name, context)
-        content.append(next)
-
-def parse_default(tokens, name, context):
-    first, pos = tokens[0]
-    assert first.startswith('default ')
-    first = first.split(None, 1)[1]
-    parts = first.split('=', 1)
-    if len(parts) == 1:
-        raise TemplateError(
-            "Expression must be {{default var=value}}; no = found in %r" % first,
-            position=pos, name=name)
-    var = parts[0].strip()
-    if ',' in var:
-        raise TemplateError(
-            "{{default x, y = ...}} is not supported",
-            position=pos, name=name)
-    if not var_re.search(var):
-        raise TemplateError(
-            "Not a valid variable name for {{default}}: %r"
-            % var, position=pos, name=name)
-    expr = parts[1].strip()
-    return ('default', pos, var, expr), tokens[1:]
-
-_fill_command_usage = """\
-%prog [OPTIONS] TEMPLATE arg=value
-
-Use py:arg=value to set a Python value; otherwise all values are
-strings.
-"""
-
-def fill_command(args=None):
-    import sys, optparse, pkg_resources, os
-    if args is None:
-        args = sys.argv[1:]
-    dist = pkg_resources.get_distribution('Paste')
-    parser = optparse.OptionParser(
-        version=str(dist),
-        usage=_fill_command_usage)
-    parser.add_option(
-        '-o', '--output',
-        dest='output',
-        metavar="FILENAME",
-        help="File to write output to (default stdout)")
-    parser.add_option(
-        '--html',
-        dest='use_html',
-        action='store_true',
-        help="Use HTML style filling (including automatic HTML quoting)")
-    parser.add_option(
-        '--env',
-        dest='use_env',
-        action='store_true',
-        help="Put the environment in as top-level variables")
-    options, args = parser.parse_args(args)
-    if len(args) < 1:
-        print('You must give a template filename')
-        print(dir(parser))
-        assert 0
-    template_name = args[0]
-    args = args[1:]
-    vars = {}
-    if options.use_env:
-        vars.update(os.environ)
-    for value in args:
-        if '=' not in value:
-            print('Bad argument: %r' % value)
-            sys.exit(2)
-        name, value = value.split('=', 1)
-        if name.startswith('py:'):
-            name = name[:3]
-            value = eval(value)
-        vars[name] = value
-    if template_name == '-':
-        template_content = sys.stdin.read()
-        template_name = '<stdin>'
-    else:
-        f = open(template_name, 'rb')
-        template_content = f.read()
-        f.close()
-    if options.use_html:
-        TemplateClass = HTMLTemplate
-    else:
-        TemplateClass = Template
-    template = TemplateClass(template_content, name=template_name)
-    result = template.substitute(vars)
-    if options.output:
-        f = open(options.output, 'wb')
-        f.write(result)
-        f.close()
-    else:
-        sys.stdout.write(result)
-
-if __name__ == '__main__':
-    from paste.util.template import fill_command
-    fill_command()
-
-
openSUSE Build Service is sponsored by