Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/zejn/cubes into zejn-mast…
Browse files Browse the repository at this point in the history
…er with changes
  • Loading branch information
Stiivi committed Jul 2, 2016
2 parents 75cd1c3 + 3701504 commit 2b397c9
Show file tree
Hide file tree
Showing 12 changed files with 54 additions and 57 deletions.
6 changes: 3 additions & 3 deletions cubes/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@
"slicer":"cubes.server.store:SlicerModelProvider",
},
"request_log_handlers": {
"default":"cubes.server.logging:DefaultRequestLogger",
"csv":"cubes.server.logging:CSVRequestLogger",
"json":"cubes.server.logging:JSONRequestLogger",
"default":"cubes.server.logging:DefaultRequestLogHandler",
"csv":"cubes.server.logging:CSVFileRequestLogHandler",
"json":"cubes.server.logging:JSONRequestLogHandler",
"sql":"cubes.sql.logging:SQLRequestLogger",
},
"stores": {
Expand Down
1 change: 1 addition & 0 deletions cubes/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def create_logger(path=None, format_=None, name=None):
"""Create a default logger"""
global logger
logger = getLogger(name or DEFAULT_LOGGER_NAME)
logger.propagate = False

if not logger.handlers:
formatter = Formatter(fmt=format_ or DEFAULT_FORMAT)
Expand Down
2 changes: 1 addition & 1 deletion cubes/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -2304,7 +2304,7 @@ def __init__(self, name, label=None, description=None, order=None,
other measure that refers to this one (no circular reference).
The `aggregates` is an optional property and is used for:
* measure aggergate object preparation
* measure aggregate object preparation
* optional validation
String representation of a `Measure` returns its full reference.
Expand Down
2 changes: 1 addition & 1 deletion cubes/server/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import absolute_import

from .blueprint import slicer, API_VERSION
from .base import run_server, create_server
from .base import run_server, create_server, read_slicer_config
from .auth import Authenticator, NotAuthenticated
from .local import workspace
37 changes: 29 additions & 8 deletions cubes/server/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
from .blueprint import slicer
from flask import Flask
import shlex
import os

from .utils import *
from .. import compat
from ..logging import get_logger

__all__ = (
"create_server",
Expand All @@ -16,7 +18,7 @@
# Server Instantiation and Running
# ================================

def _read_config(config):
def read_slicer_config(config):
if not config:
return compat.ConfigParser()
elif isinstance(config, compat.string_type):
Expand All @@ -32,10 +34,7 @@ def create_server(config=None, **_options):
"""Returns a Flask server application. `config` is a path to a
``slicer.ini`` file with Cubes workspace and server configuration."""

config = read_server_config(config)

# Load extensions

if config.has_option("server", "modules"):
modules = shlex.split(config.get("server", "modules"))
for module in modules:
Expand All @@ -48,12 +47,24 @@ def create_server(config=None, **_options):

return app


def run_server(config, debug=False):
def run_server(config, debug=False, app=None):
"""Run OLAP server with configuration specified in `config`"""

config = read_server_config(config)
app = create_server(config)
config = read_slicer_config(config)

logger = get_logger()

if config.has_option("server", "debug"):
if debug is False and config.getboolean("server", "debug"):
debug = True

if debug:
logger.warning('Server running under DEBUG, so logging level set to DEBUG.')
import logging
logger.setLevel(logging.DEBUG)

if app is None:
app = create_server(config)

if config.has_option("server", "host"):
host = config.get("server", "host")
Expand All @@ -75,6 +86,16 @@ def run_server(config, debug=False):
else:
processes = 1

if config.has_option("server", "pid_file"):
path = config.get("server", "pid_file")
try:
with open(path, "w") as f:
f.write(str(os.getpid()))
except IOError as e:
logger.error("Unable to write PID file '%s'. Check the "
"directory existence or permissions." % path)
raise

app.run(host, port, debug=debug, processes=processes,
use_reloader=use_reloader)

5 changes: 3 additions & 2 deletions cubes/server/blueprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
from ..errors import *
from ..formatters import JSONLinesGenerator, csv_generator
from .. import ext
from ..logging import get_logger
from .logging import configured_request_log_handlers, RequestLogger
from .logging import AsyncRequestLogger
from .utils import *
from .errors import *
from .decorators import *
from .local import *
Expand Down Expand Up @@ -85,8 +85,8 @@ def initialize_slicer(state):

with state.app.app_context():
config = state.options["config"]
config = read_server_config(config)

logger = get_logger()
# Create workspace and other app objects
# We avoid pollution of the current_app context, as we are a Blueprint
params = CustomDict()
Expand All @@ -103,6 +103,7 @@ def initialize_slicer(state):
current_app.cubes_workspace = Workspace(config, **_options)

# Configure the application
# FIXME XXX this shouldn't be in the "server" section
_store_option(config, "prettyprint", False, "bool")
_store_option(config, "json_record_limit", 1000, "int")
_store_option(config, "hide_private_cuts", False, "bool")
Expand Down
11 changes: 0 additions & 11 deletions cubes/server/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,15 +120,4 @@ def formatted_response(response, fields, labels, iterable=None):
mimetype='text/csv',
headers=headers)

def read_server_config(config):
if not config:
return compat.ConfigParser()
elif isinstance(config, compat.string_type):
try:
path = config
config = compat.ConfigParser()
config.read(path)
except Exception as e:
raise Exception("Unable to load configuration: %s" % e)
return config

20 changes: 4 additions & 16 deletions cubes/slicer/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from ..workspace import Workspace
from ..errors import CubesError
from ..server import run_server
from ..server.base import read_slicer_config

from .. import ext

Expand Down Expand Up @@ -58,15 +59,7 @@ def serve(ctx, config, visualizer):
"""Run Slicer HTTP server."""
config = read_config(config)

if config.has_option("server", "pid_file"):
path = config.get("server", "pid_file")
try:
with open(path, "w") as handle:
handle.write("%s\n" % os.getpid())
except IOError:
raise CubesError("Unable to write PID file '%s'. Check the "
"directory existence or permissions." % path)

# FIXME: "visualizer" shouldn't be in "server" section
if visualizer:
config.set("server", "visualizer", visualizer)

Expand Down Expand Up @@ -273,6 +266,7 @@ def test(aggregate, exclude_stores, include_stores, config, cube):
facts = browser.test(aggregate=aggregate)
except NotImplementedError:
click.echo("pass - no test")
# FIXME XXX CubesError not defined
except CubesError as e:
errors.append((name, e))
click.echo("ERROR")
Expand Down Expand Up @@ -318,13 +312,7 @@ def convert(ctx, model_format, force, model_path, target):

def read_config(cfg):
"""Read the configuration file."""
config = compat.ConfigParser()
try:
config.read(cfg)
except Exception as e:
raise Exception("Unable to load config: %s" % e)

return config
return read_slicer_config(cfg)

################################################################################
# Group: sql
Expand Down
2 changes: 1 addition & 1 deletion cubes/sql/browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ def aggregation_statement(self, cell, aggregates, drilldown=None,
# Basic assertions

if not aggregates:
raise ArgumentError("List of aggregates sohuld not be empty")
raise ArgumentError("List of aggregates should not be empty")

if not isinstance(drilldown, Drilldown):
raise InternalError("Drilldown should be a Drilldown object. "
Expand Down
17 changes: 6 additions & 11 deletions cubes/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,12 @@ def __init__(self, config=None, stores=None, load_base_model=True,
# FIXME: **_options is temporary solution/workaround before we get
# better configuration. Used internally. Don't use!

if isinstance(config, compat.string_type):
cp = ConfigParser()
try:
cp.read(config)
except Exception as e:
raise ConfigurationError("Unable to load config %s. "
"Reason: %s" % (config, str(e)))

config = cp

elif not config:
# Expect to get ConfigParser instance
if config is not None and not isinstance(config, ConfigParser):
raise ConfigurationError("config should be a ConfigParser instance,"
" but is %r" % (type(config),))

if not config:
# Read ./slicer.ini
config = ConfigParser()

Expand Down
3 changes: 2 additions & 1 deletion tests/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ class SlicerTestCaseBase(CubesTestCaseBase):
def setUp(self):
super(SlicerTestCaseBase, self).setUp()

self.slicer = create_server()
self.config = compat.ConfigParser()
self.slicer = create_server(self.config)
self.slicer.debug = True
self.server = Client(self.slicer, BaseResponse)
self.logger = self.slicer.logger
Expand Down
5 changes: 3 additions & 2 deletions tests/test_workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,19 @@
from cubes.workspace import Workspace
from cubes.stores import Store
from cubes.model import *
from cubes.server.base import read_slicer_config

from .common import CubesTestCaseBase
# FIXME: remove this once satisfied

class WorkspaceTestCaseBase(CubesTestCaseBase):
def default_workspace(self, model_name=None):
model_name = model_name or "model.json"
ws = Workspace(config=self.data_path("slicer.ini"))
config = read_slicer_config(self.data_path("slicer.ini"))
ws = Workspace(config=config)
ws.import_model(self.model_path("model.json"))
return ws


class WorkspaceModelTestCase(WorkspaceTestCaseBase):
def test_get_cube(self):
ws = self.default_workspace()
Expand Down

0 comments on commit 2b397c9

Please sign in to comment.