1
0
mirror of https://github.com/webrecorder/pywb.git synced 2025-03-24 06:59:52 +01:00

loader improvements: add PackageLoader for pkg:// scheme

use pkgutil.get_data() instead of pkg_resources
template loading: load assets file through load() interface, use standard PackageLoader
This commit is contained in:
Ilya Kreymer 2016-12-18 20:57:17 -08:00
parent fa85793e97
commit c52efa0f9b
3 changed files with 46 additions and 27 deletions

View File

@ -1,5 +1,7 @@
from pywb.utils.timeutils import timestamp_to_datetime, timestamp_to_sec from pywb.utils.timeutils import timestamp_to_datetime, timestamp_to_sec
from pywb.utils.timeutils import timestamp_now from pywb.utils.timeutils import timestamp_now
from pywb.utils.loaders import load
from six.moves.urllib.parse import urlsplit from six.moves.urllib.parse import urlsplit
from jinja2 import Environment from jinja2 import Environment
@ -15,13 +17,6 @@ import json
import os import os
# ============================================================================
class FileOnlyPackageLoader(PackageLoader):
def get_source(self, env, template):
dir_, file_ = os.path.split(template)
return super(FileOnlyPackageLoader, self).get_source(env, file_)
# ============================================================================ # ============================================================================
class RelEnvironment(Environment): class RelEnvironment(Environment):
"""Override join_path() to enable relative template paths.""" """Override join_path() to enable relative template paths."""
@ -65,7 +60,7 @@ class JinjaEnv(object):
# init assets # init assets
if assets_path: if assets_path:
assets_loader = YAMLLoader(assets_path) assets_loader = YAMLLoader(load(assets_path))
assets_env = assets_loader.load_environment() assets_env = assets_loader.load_environment()
assets_env.resolver = PkgResResolver() assets_env.resolver = PkgResResolver()
jinja_env.assets_environment = assets_env jinja_env.assets_environment = assets_env
@ -78,7 +73,7 @@ class JinjaEnv(object):
# add loaders for all specified packages # add loaders for all specified packages
for package in packages: for package in packages:
loaders.append(FileOnlyPackageLoader(package)) loaders.append(PackageLoader(package))
return loaders return loaders

View File

@ -12,7 +12,7 @@ from six.moves.urllib.request import pathname2url, url2pathname
from six.moves.urllib.parse import urljoin, unquote_plus, urlsplit, urlencode from six.moves.urllib.parse import urljoin, unquote_plus, urlsplit, urlencode
import time import time
import pkg_resources import pkgutil
import base64 import base64
import cgi import cgi
@ -39,16 +39,20 @@ def to_file_url(filename):
return url return url
#=================================================================
def load(filename):
return BlockLoader().load(filename)
#================================================================= #=================================================================
def load_yaml_config(config_file): def load_yaml_config(config_file):
import yaml import yaml
config = None config = None
configdata = None configdata = None
try: try:
configdata = BlockLoader().load(config_file) configdata = load(config_file)
config = yaml.load(configdata) config = yaml.load(configdata)
finally: finally:
configdata.close()
if configdata: if configdata:
configdata.close() configdata.close()
@ -310,6 +314,7 @@ class BlockLoader(BaseLoader):
BlockLoader.loaders['https'] = HttpLoader BlockLoader.loaders['https'] = HttpLoader
BlockLoader.loaders['s3'] = S3Loader BlockLoader.loaders['s3'] = S3Loader
BlockLoader.loaders['file'] = LocalFileLoader BlockLoader.loaders['file'] = LocalFileLoader
BlockLoader.loaders['pkg'] = PackageLoader
@staticmethod @staticmethod
def set_profile_loader(src): def set_profile_loader(src):
@ -326,7 +331,33 @@ class BlockLoader(BaseLoader):
#================================================================= #=================================================================
class LocalFileLoader(BaseLoader): class PackageLoader(BaseLoader):
def load(self, url, offset=0, length=-1):
if url.startswith('pkg://'):
url = url[len('pkg://'):]
# then, try as package.path/file
pkg_split = url.split('/', 1)
if len(pkg_split) == 1:
raise
data = pkgutil.get_data(pkg_split[0], pkg_split[1])
if offset > 0:
data = data[offset:]
if length > -1:
data = data[:length]
buff = BytesIO(data)
buff.name = url
return buff
#afile = pkg_resources.resource_stream(pkg_split[0],
# pkg_split[1])
#=================================================================
class LocalFileLoader(PackageLoader):
def load(self, url, offset=0, length=-1): def load(self, url, offset=0, length=-1):
""" """
Load a file-like reader from the local file system Load a file-like reader from the local file system
@ -348,13 +379,7 @@ class LocalFileLoader(BaseLoader):
if file_only: if file_only:
raise raise
# then, try as package.path/file return super(LocalFileLoader, self).load(url, offset, length)
pkg_split = url.split('/', 1)
if len(pkg_split) == 1:
raise
afile = pkg_resources.resource_stream(pkg_split[0],
pkg_split[1])
if offset > 0: if offset > 0:
afile.seek(offset) afile.seek(offset)

View File

@ -9,6 +9,7 @@ from contextlib import closing
from pywb.utils.timeutils import timestamp_to_http_date from pywb.utils.timeutils import timestamp_to_http_date
from pywb.utils.wbexception import BadRequestException from pywb.utils.wbexception import BadRequestException
from pywb.utils.loaders import load_yaml_config
from six.moves.urllib.parse import quote from six.moves.urllib.parse import quote
from tempfile import SpooledTemporaryFile from tempfile import SpooledTemporaryFile
@ -223,22 +224,20 @@ def load_config(main_env_var, main_default_file='',
overlay_env_var='', overlay_file=''): overlay_env_var='', overlay_file=''):
configfile = os.environ.get(main_env_var, main_default_file) configfile = os.environ.get(main_env_var, main_default_file)
config = None
if configfile: if configfile:
configfile = os.path.expandvars(configfile) configfile = os.path.expandvars(configfile)
# Load config
with open(configfile, 'rb') as fh:
config = yaml.load(fh)
else: config = load_yaml_config(configfile)
config = {}
config = config or {}
overlay_configfile = os.environ.get(overlay_env_var, overlay_file) overlay_configfile = os.environ.get(overlay_env_var, overlay_file)
if overlay_configfile: if overlay_configfile:
overlay_configfile = os.path.expandvars(overlay_configfile) overlay_configfile = os.path.expandvars(overlay_configfile)
with open(overlay_configfile, 'rb') as fh: config.update(load_yaml_config(overlay_configfile))
config.update(yaml.load(fh))
return config return config