Commit 4239eed7 authored by Stefane Fermigier's avatar Stefane Fermigier Committed by GitHub

Merge pull request #3 from abilian/config_file+postgres_backend

config_file + postgres_backend + auth
parents de960516 a1d3ff81
************************
* IMPORTANT *
************************
1) the id columns must have _id at the end (product_id, person_id...)
2) each table's column name must be unique from the other tables column names
3) the columns name must be in a good order (hierarchy)
4) use a simple star modele with one key and numeric measures ( the other cases not tested yet)
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
"store_id";"store_type";"store_name";"store_number";"store_street_address";"store_city";"store_state";"store_postal_code";"store_country";"store_manager";"store_phone";"store_fax";"first_opened_date";"last_remodel_date";"store_sqft";"grocery_sqft";"frozen_sqft";"meat_sqft";"coffee_bar";"video_store";"salad_bar";"prepared_food";"florist"
0;"HeadQuarters";"HQ";0;"1 Alameda Way";"Alameda";"CA";"55555";"USA";"";"";"";"";"";0;0;0;0;0;0;0;0;0
1;"Supermarket";"Store 1";1;"2853 Bailey Rd";"Acapulco";"Guerrero";"55555";"Mexico";"Jones";"262-555-5124";"262-555-5121";"1982-01-09 00:00:00";"1990-12-05 00:00:00";23593;17475;3671;2447;0;0;0;0;0
2;"Small Grocery";"Store 2";2;"5203 Catanzaro Way";"Bellingham";"WA";"55555";"USA";"Smith";"605-555-8203";"605-555-8201";"1970-04-02 00:00:00";"1973-06-04 00:00:00";28206;22271;3561;2374;1;0;0;0;0
3;"Supermarket";"Store 3";3;"1501 Ramsey Circle";"Bremerton";"WA";"55555";"USA";"Davis";"509-555-1596";"509-555-1591";"1959-06-14 00:00:00";"1967-11-19 00:00:00";39696;24390;9184;6122;0;0;1;1;0
4;"Gourmet Supermarket";"Store 4";4;"433 St George Dr";"Camacho";"Zacatecas";"55555";"Mexico";"Johnson";"304-555-1474";"304-555-1471";"1994-09-27 00:00:00";"1995-12-01 00:00:00";23759;16844;4149;2766;1;0;1;1;1
5;"Small Grocery";"Store 5";5;"1250 Coggins Drive";"Guadalajara";"Jalisco";"55555";"Mexico";"Green";"801-555-4324";"801-555-4321";"1978-09-18 00:00:00";"1991-06-29 00:00:00";24597;15012;5751;3834;1;0;0;0;0
6;"Gourmet Supermarket";"Store 6";6;"5495 Mitchell Canyon Road";"Beverly Hills";"CA";"55555";"USA";"Maris";"958-555-5002";"958-555-5001";"1981-01-03 00:00:00";"1991-03-13 00:00:00";23688;15337;5011;3340;1;1;1;1;1
7;"Supermarket";"Store 7";7;"1077 Wharf Drive";"Los Angeles";"CA";"55555";"USA";"White";"477-555-7967";"477-555-7961";"1971-05-21 00:00:00";"1981-10-20 00:00:00";23598;14210;5633;3755;0;0;0;0;1
8;"Deluxe Supermarket";"Store 8";8;"3173 Buena Vista Ave";"Merida";"Yucatan";"55555";"Mexico";"Williams";"797-555-3417";"797-555-3411";"1958-09-23 00:00:00";"1967-11-18 00:00:00";30797;20141;6393;4262;1;1;1;1;1
9;"Mid-Size Grocery";"Store 9";9;"1872 El Pintado Road";"Mexico City";"DF";"55555";"Mexico";"Stuber";"439-555-3524";"439-555-3521";"1955-03-18 00:00:00";"1959-06-07 00:00:00";36509;22450;8435;5624;0;0;0;0;0
10;"Supermarket";"Store 10";10;"7894 Rotherham Dr";"Orizaba";"Veracruz";"55555";"Mexico";"Merz";"212-555-4774";"212-555-4771";"1979-04-13 00:00:00";"1982-01-30 00:00:00";34791;26354;5062;3375;0;0;1;1;0
11;"Supermarket";"Store 11";11;"5371 Holland Circle";"Portland";"OR";"55555";"USA";"Erickson";"685-555-8995";"685-555-8991";"1976-09-17 00:00:00";"1982-05-15 00:00:00";20319;16232;2452;1635;0;0;0;0;0
12;"Deluxe Supermarket";"Store 12";12;"1120 Westchester Pl";"Hidalgo";"Zacatecas";"55555";"Mexico";"Kalman";"151-555-1702";"151-555-1701";"1968-03-25 00:00:00";"1993-12-18 00:00:00";30584;21938;5188;3458;1;1;1;1;1
13;"Deluxe Supermarket";"Store 13";13;"5179 Valley Ave";"Salem";"OR";"55555";"USA";"Inmon";"977-555-2724";"977-555-2721";"1957-04-13 00:00:00";"1997-11-10 00:00:00";27694;18670;5415;3610;1;1;1;1;1
14;"Small Grocery";"Store 14";14;"4365 Indigo Ct";"San Francisco";"CA";"55555";"USA";"Strehlo";"135-555-4888";"135-555-4881";"1957-11-24 00:00:00";"1958-01-07 00:00:00";22478;15321;4294;2863;1;0;0;0;0
15;"Supermarket";"Store 15";15;"5006 Highland Drive";"Seattle";"WA";"55555";"USA";"Ollom";"893-555-1024";"893-555-1021";"1969-07-24 00:00:00";"1973-10-19 00:00:00";21215;13305;4746;3164;1;0;0;0;0
16;"Supermarket";"Store 16";16;"5922 La Salle Ct";"Spokane";"WA";"55555";"USA";"Mantle";"643-555-3645";"643-555-3641";"1974-08-23 00:00:00";"1977-07-13 00:00:00";30268;22063;4923;3282;0;0;0;0;0
17;"Deluxe Supermarket";"Store 17";17;"490 Risdon Road";"Tacoma";"WA";"55555";"USA";"Mays";"855-555-5581";"855-555-5581";"1970-05-30 00:00:00";"1976-06-23 00:00:00";33858;22123;7041;4694;1;0;1;1;1
18;"Mid-Size Grocery";"Store 18";18;"6764 Glen Road";"Hidalgo";"Zacatecas";"55555";"Mexico";"Brown";"528-555-8317";"528-555-8311";"1969-06-28 00:00:00";"1975-08-30 00:00:00";38382;30351;4819;3213;0;0;0;0;0
19;"Deluxe Supermarket";"Store 19";19;"6644 Sudance Drive";"Vancouver";"BC";"55555";"Canada";"Ruth";"862-555-7395";"862-555-7391";"1977-03-27 00:00:00";"1990-10-25 00:00:00";23112;16418;4016;2678;1;1;1;1;1
20;"Mid-Size Grocery";"Store 20";20;"3706 Marvelle Ln";"Victoria";"BC";"55555";"Canada";"Cobb";"897-555-1931";"897-555-1931";"1980-02-06 00:00:00";"1987-04-09 00:00:00";34452;27463;4193;2795;1;0;0;0;1
21;"Deluxe Supermarket";"Store 21";21;"4093 Steven Circle";"San Andres";"DF";"55555";"Mexico";"Jones";"493-555-4781";"493-555-4781";"1986-02-07 00:00:00";"1990-04-16 00:00:00";0;0;0;0;1;0;1;1;1
22;"Small Grocery";"Store 22";22;"9606 Julpum Loop";"Walla Walla";"WA";"55555";"USA";"Byrg";"881-555-5117";"881-555-5111";"1951-01-24 00:00:00";"1969-10-17 00:00:00";0;0;0;0;0;0;0;0;0
23;"Mid-Size Grocery";"Store 23";23;"3920 Noah Court";"Yakima";"WA";"55555";"USA";"Johnson";"170-555-8424";"170-555-8421";"1977-07-16 00:00:00";"1987-07-24 00:00:00";0;0;0;0;0;0;0;0;0
24;"Supermarket";"Store 24";24;"2342 Waltham St.";"San Diego";"CA";"55555";"USA";"Byrd";"111-555-0303";"111-555-0304";"1979-05-22 00:00:00";"1986-04-20 00:00:00";0;0;0;0;1;0;1;0;1
This diff is collapsed.
"warehouse_id";"warehouse_name";"wa_address1";"wa_address2";"wa_address3";"wa_address4";"warehouse_city";"warehouse_state_province";"warehouse_postal_code";"warehouse_country";"warehouse_owner_name";"warehouse_phone";"warehouse_fax"
1;"Salka Warehousing";"9716 Alovera Road";"";"";"";"Acapulco";"Guerrero";"55555";"Mexico";"";"821-555-1658";"594-555-2908"
2;"Foster Products";"958 Hilltop Dr";"";"";"";"Bellingham";"WA";"55555";"USA";"";"315-555-8947";"119-555-3826"
3;"Destination, Inc.";"4162 Euclid Ave";"";"";"";"Bremerton";"WA";"55555";"USA";"";"517-555-3022";"136-555-4501"
4;"Anderson Warehousing";"5657 Georgia Dr";"";"";"";"Camacho";"Zacatecas";"55555";"Mexico";"";"681-555-1655";"946-555-4848"
5;"Focus, Inc.";"9116 Tice Valley Blv.";"";"";"";"Guadalajara";"Jalisco";"55555";"Mexico";"";"344-555-5530";"379-555-9065"
6;"Big Quality Warehouse";"3521 Fourth Stret";"";"";"";"Beverly Hills";"CA";"55555";"USA";"";"892-555-3590";"388-555-7926"
7;"Artesia Warehousing, Inc.";"9889 Matterhorn Court";"";"";"";"Los Angeles";"CA";"55555";"USA";"";"859-555-2792";"740-555-6556"
8;"Bastani and Sons";"1893 Northridge Drive";"";"";"";"Marida";"Yucatan";"55555";"Mexico";"";"846-555-3024";"804-555-6674"
9;"Freeman And Co";"234 West Covina Pkwy";"";"";"";"Mexico City";"DF";"55555";"Mexico";"";"";""
10;"Jamison, Inc.";"1172 Liana Lane";"";"";"";"Orizaba";"Veracruz";"55555";"Mexico";"";"379-555-5756";"436-555-7920"
11;"Quality Distribution, Inc.";"6085 Darlene Drive";"";"";"";"Portland";"OR";"55555";"USA";"";"181-555-3588";"269-555-8381"
12;"Arnold and Sons";"5617 Saclan Terrace";"";"";"";"Hidalgo";"Zacatecas";"55555";"Mexico";"";"360-555-8035";"263-555-1427"
13;"Treehouse Distribution";"5473 Olive Hill";"";"";"";"Salem";"OR";"55555";"USA";"";"831-555-6210";"481-555-1317"
14;"Food Service Storage, Inc.";"5259 Mildred Ln";"";"";"";"San Francisco";"CA";"55555";"USA";"";"471-555-2456";"552-555-3249"
15;"Quality Warehousing and Trucking";"3337 Northpoint Ct";"";"";"";"Seattle";"WA";"55555";"USA";"";"427-555-9060";"869-555-1652"
16;"Jones International";"3377 Coachman Place";"";"";"";"Spokane";"WA";"55555";"USA";"";"144-555-5192";"971-555-6213"
17;"Jorge Garcia, Inc.";"4364 Viera Avenue";"";"";"";"Tacoma";"WA";"55555";"USA";"";"200-555-1310";"442-555-5874"
18;"Worthington Food Products";"4659 Cape Cod Way";"";"";"";"Hidalgo";"Zacatecas";"55555";"Mexico";"";"609-555-5413";"952-555-8492"
19;"Bellmont Distributing";"5900 May Rd";"";"";"";"Vancouver";"BC";"55555";"Canada";"";"226-555-5335";"361-555-7385"
20;"Rose Food Warehousing";"9104 Jacobsen Street";"";"";"";"Victoria";"BC";"55555";"Canada";"";"143-555-7496";"332-555-1803"
21;"Derby and Hunt";"600 Lake Nadine Place";"";"";"";"San Andres";"DF";"55555";"Mexico";"";"922-555-5214";"618-555-6578"
22;"Valdez Warehousing";"6714 Roundtree Court";"";"";"";"Walla Walla";"WA";"55555";"USA";"";"301-555-8174";"666-555-9881"
23;"Maddock Stored Foods";"8463 Kim Court";"";"";"";"Yakima";"WA";"55555";"USA";"";"803-555-8978";"630-555-2485"
24;"Jorgensen Service Storage";"4832 Park Glen Ct";"";"";"";"San Diego";"CA";"55555";"USA";"";"259-555-2824";"470-555-4760"
Day;City;Licence;Amount;Count
May 12,2010;Madrid;Personal;1;84
May 13,2010;Barcelona;Personal;2;841
May 14,2010;Paris;Personal;4;2
May 15,2010;Lausanne;Personal;8;231
May 16,2010;Lausanne;Corporate;16;4
May 17,2010;Lausanne;Partnership;32;65
May 18,2010;Zurich;Partnership;64;64
May 19,2010;Geneva;Corporate;128;13
May 20,2010;New York;Corporate;256;12
May 21,2010;New York;Corporate;512;564
Continent;Country;City
America;Canada;Quebec
America;Canada;Toronto
America;United States;Los Angeles
America;United States;New York
America;United States;San Francisco
America;Mexico;Mexico
America;Venezuela;Caracas
Europe;France;Paris
Europe;Spain;Barcelona
Europe;Spain;Madrid
Europe;Spain;Valencia
Europe;Switzerland;Geneva
Europe;Switzerland;Lausanne
Europe;Switzerland;Zurich
Company;Article;Licence
Crazy Development;olapy;Corporate
Crazy Development;olapy;Partnership
Crazy Development;olapy;Personal
Crazy Development;olapy;Startup
This diff is collapsed.
class ConditionError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
This diff is collapsed.
from __future__ import absolute_import, division, print_function
import os
from lxml import etree
from .models import Cube, Facts, Dimension
class ConfigParser:
def __init__(self, cube_path, file_name='cubes-config.xml'):
self.cube_path = cube_path
self.file_name = file_name
def config_file_exist(self):
return os.path.isfile(os.path.join(self.cube_path, self.file_name))
def xmla_authentication(self):
with open(os.path.join(self.cube_path, self.file_name)) as config_file:
parser = etree.XMLParser()
tree = etree.parse(config_file, parser)
try:
return tree.xpath('/cubes/xmla_authentication')[
0].text == 'True'
except:
return False
def get_cubes_names(self):
with open(os.path.join(self.cube_path, self.file_name)) as config_file:
parser = etree.XMLParser()
tree = etree.parse(config_file, parser)
try:
return {
cube.find('name').text: cube.find('source').text
for cube in tree.xpath('/cubes/cube')
}
except:
raise ('missed name or source tags')
def construct_cubes(self):
if self.config_file_exist():
try:
with open(os.path.join(self.cube_path,
self.file_name)) as config_file:
parser = etree.XMLParser()
tree = etree.parse(config_file, parser)
facts = [
Facts(
table_name=xml_facts.find('table_name').text,
keys={
key.text: key.attrib['ref']
for key in xml_facts.findall(
'keys/column_name')
},
measures=[
mes.text
for mes in xml_facts.findall('measures/name')
]) for xml_facts in tree.xpath('/cubes/cube/facts')
]
dimensions = [
Dimension(
name=xml_dimension.find('name').text,
displayName=xml_dimension.find('displayName').text,
columns=[
column_name.text
for column_name in xml_dimension.findall(
'columns/name')
])
for xml_dimension in tree.xpath(
'/cubes/cube/dimensions/dimension')
]
return [
Cube(
name=xml_cube.find('name').text,
source=xml_cube.find('source').text,
facts=facts,
dimensions=dimensions)
for xml_cube in tree.xpath('/cubes/cube')
]
except:
raise ('Bad configuration in the configuration file')
else:
raise ("Config file don't exist")
import psycopg2 as pg
class MyDB(object):
def __init__(self, username='postgres', password='root', db=None,host='localhost'):
if db is None:
self.connection = pg.connect(
"user={0} password={1}".format(username, password))
else:
try:
self.connection = pg.connect("user={0} password={1} dbname='{2}' host='{3}'".
format(username, password, db,host))
except:
print("can't connect")
def __del__(self):
if hasattr(self, 'connection'):
self.connection.close()
\ No newline at end of file
class Facts:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __str__(self):
return str(self.__dict__)
class Dimension:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __str__(self):
return str(self.__dict__)
class Cube:
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __str__(self):
return str(self.__dict__)
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
from spyne import ComplexModel, Integer, String, Unicode, XmlAttribute from spyne import ComplexModel, Integer, Unicode, XmlAttribute
from spyne.model.fault import Fault
class Tuple(object): class Tuple(object):
def __init__(self, Hierarchy, UName, Caption, LName, LNum, DisplayInfo, def __init__(self, Hierarchy, UName, Caption, LName, LNum, DisplayInfo,
PARENT_UNIQUE_NAME, HIERARCHY_UNIQUE_NAME, Value): PARENT_UNIQUE_NAME, HIERARCHY_UNIQUE_NAME, Value):
self.Hierarchy = Hierarchy self.Hierarchy = Hierarchy
...@@ -92,7 +92,9 @@ class Propertielist(ComplexModel): ...@@ -92,7 +92,9 @@ class Propertielist(ComplexModel):
class Command(ComplexModel): class Command(ComplexModel):
_type_info = {'Statement': Unicode,} _type_info = {
'Statement': Unicode,
}
class ExecuteRequest(ComplexModel): class ExecuteRequest(ComplexModel):
...@@ -106,6 +108,7 @@ class DiscoverRequest(ComplexModel): ...@@ -106,6 +108,7 @@ class DiscoverRequest(ComplexModel):
Properties = Propertielist Properties = Propertielist
class DiscoverResponse(ComplexModel): # class AuthenticationError(Fault):
__namespace__ = "urn:schemas-microsoft-com:xml-analysis:rowset" # __namespace__ = 'spyne.examples.authentication'
root = String # faultcode='Client.AuthenticationError',
# faultstring='Invalid authentication request'
# -*- encoding: utf8 -*-
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
import os
from datetime import datetime from datetime import datetime
from os.path import expanduser
from lxml import etree from lxml import etree
from spyne import AnyXml, Application, ServiceBase, rpc from spyne import AnyXml, Application, ServiceBase, rpc
from spyne.error import InvalidCredentialsError
from spyne.protocol.soap import Soap11 from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication from spyne.server.wsgi import WsgiApplication
from ..services.models import DiscoverRequest, ExecuteRequest, Session from ..mdx.tools.config_file_parser import ConfigParser
from ..services.models import DiscoverRequest, ExecuteRequest, Session\
# , AuthenticationError
from .xmla_discover_tools import XmlaDiscoverTools from .xmla_discover_tools import XmlaDiscoverTools
from .xmla_execute_tools import XmlaExecuteTools from .xmla_execute_tools import XmlaExecuteTools
from .xmla_execute_xsds import execute_xsd from .xmla_execute_xsds import execute_xsd
...@@ -31,10 +39,14 @@ class XmlaProviderService(ServiceBase): ...@@ -31,10 +39,14 @@ class XmlaProviderService(ServiceBase):
discover_tools = XmlaDiscoverTools() discover_tools = XmlaDiscoverTools()
SessionId = discover_tools.SessionId SessionId = discover_tools.SessionId
@rpc(DiscoverRequest, @rpc(
_returns=AnyXml, DiscoverRequest,
_body_style="bare", _returns=AnyXml,
_out_header=Session) _body_style="bare",
_out_header=Session,
_throws=InvalidCredentialsError
# _throws=AuthenticationError
)
def Discover(ctx, request): def Discover(ctx, request):
""" """
the first principle function of xmla protocol the first principle function of xmla protocol
...@@ -51,6 +63,19 @@ class XmlaProviderService(ServiceBase): ...@@ -51,6 +63,19 @@ class XmlaProviderService(ServiceBase):
discover_tools = XmlaProviderService.discover_tools discover_tools = XmlaProviderService.discover_tools
ctx.out_header = Session(SessionId=str(XmlaProviderService.SessionId)) ctx.out_header = Session(SessionId=str(XmlaProviderService.SessionId))
config_parser = ConfigParser(discover_tools.executer.cube_path)
if config_parser.xmla_authentication():
# TODO call (labster) login function or create login with token (according to labster db)
if ctx.transport.req_env['QUERY_STRING'] != 'admin':
raise InvalidCredentialsError(
fault_string=
'You do not have permission to access this resource',
fault_object=None)
# raise AuthenticationError()
if request.RequestType == "DISCOVER_DATASOURCES": if request.RequestType == "DISCOVER_DATASOURCES":
return discover_tools.discover_datasources_response() return discover_tools.discover_datasources_response()
...@@ -82,7 +107,8 @@ class XmlaProviderService(ServiceBase): ...@@ -82,7 +107,8 @@ class XmlaProviderService(ServiceBase):
return discover_tools.discover_mdschema_measures__response(request) return discover_tools.discover_mdschema_measures__response(request)
elif request.RequestType == "MDSCHEMA_DIMENSIONS": elif request.RequestType == "MDSCHEMA_DIMENSIONS":
return discover_tools.discover_mdschema_dimensions_response(request) return discover_tools.discover_mdschema_dimensions_response(
request)
elif request.RequestType == "MDSCHEMA_HIERARCHIES": elif request.RequestType == "MDSCHEMA_HIERARCHIES":
return discover_tools.discover_mdschema_hierarchies_response( return discover_tools.discover_mdschema_hierarchies_response(
...@@ -100,17 +126,19 @@ class XmlaProviderService(ServiceBase): ...@@ -100,17 +126,19 @@ class XmlaProviderService(ServiceBase):
request) request)
elif request.RequestType == "MDSCHEMA_PROPERTIES": elif request.RequestType == "MDSCHEMA_PROPERTIES":
return discover_tools.discover_mdschema_properties_response(request) return discover_tools.discover_mdschema_properties_response(
request)
elif request.RequestType == "MDSCHEMA_MEMBERS": elif request.RequestType == "MDSCHEMA_MEMBERS":
return discover_tools.discover_mdschema_members_response(request) return discover_tools.discover_mdschema_members_response(request)
# Execute function must take 2 argument ( JUST 2 ! ) Command and Properties # Execute function must take 2 argument ( JUST 2 ! ) Command and Properties
# we encapsulate them in ExecuteRequest object # we encapsulate them in ExecuteRequest object
@rpc(ExecuteRequest, @rpc(
_returns=AnyXml, ExecuteRequest,
_body_style="bare", _returns=AnyXml,
_out_header=Session) _body_style="bare",
_out_header=Session)
def Execute(ctx, request): def Execute(ctx, request):
""" """
the second principle function of xmla protocol the second principle function of xmla protocol
...@@ -137,6 +165,7 @@ class XmlaProviderService(ServiceBase): ...@@ -137,6 +165,7 @@ class XmlaProviderService(ServiceBase):
executer.mdx_query = request.Command.Statement executer.mdx_query = request.Command.Statement
df = executer.execute_mdx() df = executer.execute_mdx()
xmla_tools = XmlaExecuteTools(executer) xmla_tools = XmlaExecuteTools(executer)
return etree.fromstring(""" return etree.fromstring("""
<return> <return>
<root xmlns="urn:schemas-microsoft-com:xml-analysis:mddataset" <root xmlns="urn:schemas-microsoft-com:xml-analysis:mddataset"
...@@ -175,7 +204,16 @@ class XmlaProviderService(ServiceBase): ...@@ -175,7 +204,16 @@ class XmlaProviderService(ServiceBase):
xmla_tools.generate_xs0(df), xmla_tools.generate_xs0(df),
xmla_tools.generate_slicer_axis(df), xmla_tools.generate_slicer_axis(df),
xmla_tools.generate_cell_data(df), xmla_tools.generate_cell_data(df),
datetime.now().strftime('%Y-%m-%dT%H:%M:%S'))) datetime.now().strftime('%Y-%m-%dT%H:%M:%S')).replace(
'&', '&amp;'))
# Problem:
# An XML parser returns the error “xmlParseEntityRef: noname”
#
# Cause:
# There is a stray ‘&’ (ampersand character) somewhere in the XML text eg. some text & some more text
# Solution
# .replace('&', '&amp;')
application = Application( application = Application(
...@@ -208,13 +246,19 @@ def start_server(write_on_file=False): ...@@ -208,13 +246,19 @@ def start_server(write_on_file=False):
# log to the file # log to the file
# TODO FIX it with os # TODO FIX it with os
if write_on_file: if write_on_file:
logging.basicConfig(level=logging.DEBUG, filename="C:\\logs\\xmla.log") home_directory = expanduser("~")
if not os.path.isdir(os.path.join(home_directory, 'logs')):
os.makedirs(os.path.join(home_directory, 'logs'))
logging.basicConfig(
level=logging.DEBUG,
filename=os.path.join(home_directory, 'logs', 'xmla.log'))
else: else:
logging.basicConfig(level=logging.DEBUG) logging.basicConfig(level=logging.DEBUG)
logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG) logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
logging.info("listening to http://127.0.0.1:8000/xmla") logging.info("listening to http://127.0.0.1:8000/xmla")
logging.info("wsdl is at: http://localhost:8000/xmla?wsdl") logging.info("wsdl is at: http://localhost:8000/xmla?wsdl")
server = make_server('127.0.0.1', 8000, wsgi_application) server = make_server('127.0.0.1', 8000, wsgi_application)
# server = make_server('192.168.101.139', 8000, wsgi_application)
server.serve_forever() server.serve_forever()
......
# -*- encoding: utf8 -*-
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
import uuid import uuid
...@@ -5,19 +7,14 @@ import uuid ...@@ -5,19 +7,14 @@ import uuid
from lxml import etree from lxml import etree
from ..mdx.executor.execute import MdxEngine from ..mdx.executor.execute import MdxEngine
from .xmla_discover_xsds import (dbschema_catalogs_xsd, dbschema_tables_xsd, from .xmla_discover_xsds import (
discover_datasources_xsd, dbschema_catalogs_xsd, dbschema_tables_xsd, discover_datasources_xsd,
discover_literals_xsd, discover_literals_xsd, discover_preperties_xsd,
discover_preperties_xsd, discover_schema_rowsets_xsd, mdschema_cubes_xsd, mdschema_dimensions_xsd,
discover_schema_rowsets_xsd, mdschema_hierarchies_xsd, mdschema_kpis_xsd, mdschema_levels_xsd,
mdschema_cubes_xsd, mdschema_dimensions_xsd, mdschema_measures_xsd, mdschema_measuresgroups_dimensions_xsd,
mdschema_hierarchies_xsd, mdschema_kpis_xsd, mdschema_measuresgroups_xsd, mdschema_members_xsd,
mdschema_levels_xsd, mdschema_measures_xsd, mdschema_properties_PROPERTIES_xsd, mdschema_sets_xsd)
mdschema_measuresgroups_dimensions_xsd,
mdschema_measuresgroups_xsd,
mdschema_members_xsd,
mdschema_properties_PROPERTIES_xsd,
mdschema_sets_xsd)
# TODO clean # TODO clean
...@@ -76,7 +73,6 @@ class XmlaDiscoverTools(): ...@@ -76,7 +73,6 @@ class XmlaDiscoverTools():
</return>""") </return>""")
def discover_properties_response(self, request): def discover_properties_response(self, request):
def get_props(xsd, PropertyName, PropertyDescription, PropertyType, def get_props(xsd, PropertyName, PropertyDescription, PropertyType,
PropertyAccessType, IsRequired, Value): PropertyAccessType, IsRequired, Value):
return etree.fromstring(""" return etree.fromstring("""
...@@ -118,15 +114,15 @@ class XmlaDiscoverTools(): ...@@ -118,15 +114,15 @@ class XmlaDiscoverTools():
elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxSubqueries': elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxSubqueries':
if 'Unspecified' in request.Properties.PropertyList.Catalog: if 'Unspecified' in request.Properties.PropertyList.Catalog:
return get_props(discover_preperties_xsd, 'MdpropMdxSubqueries', return get_props(discover_preperties_xsd,
'MdpropMdxSubqueries', 'int', 'Read', 'false', 'MdpropMdxSubqueries', 'MdpropMdxSubqueries',
'15') 'int', 'Read', 'false', '15')
if request.Properties.PropertyList.Catalog is not None: if request.Properties.PropertyList.Catalog is not None:
self.change_catalogue(request.Properties.PropertyList.Catalog) self.change_catalogue(request.Properties.PropertyList.Catalog)
return get_props(discover_preperties_xsd, 'MdpropMdxSubqueries', return get_props(discover_preperties_xsd,
'MdpropMdxSubqueries', 'int', 'Read', 'false', 'MdpropMdxSubqueries', 'MdpropMdxSubqueries',
'15') 'int', 'Read', 'false', '15')
elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxDrillFunctions': elif request.Restrictions.RestrictionList.PropertyName == 'MdpropMdxDrillFunctions':
if 'Unspecified' in request.Properties.PropertyList.Catalog: if 'Unspecified' in request.Properties.PropertyList.Catalog:
...@@ -1826,8 +1822,15 @@ class XmlaDiscoverTools(): ...@@ -1826,8 +1822,15 @@ class XmlaDiscoverTools():
request.Properties.PropertyList.Catalog) request.Properties.PropertyList.Catalog)
rows = "" rows = ""
ord = 1 ord = 1
for tables in self.executer.get_all_tables_names( for tables in self.executer.get_all_tables_names(
ignore_fact=True): ignore_fact=True):
# TODO in another idea, change this
# TO CHANGE NAME DISPLAY THAT EXISTS IN CONFIG FILE
if MdxEngine.dimension_display_name != []:
if tables in MdxEngine.dimension_display_name:
continue
rows += """ rows += """
<row> <row>
<CATALOG_NAME>{0}</CATALOG_NAME> <CATALOG_NAME>{0}</CATALOG_NAME>
...@@ -2264,34 +2267,38 @@ class XmlaDiscoverTools(): ...@@ -2264,34 +2267,38 @@ class XmlaDiscoverTools():
# separed_tuple -> [Product].[Product].[Company].[Crazy Development] # separed_tuple -> [Product].[Product].[Company].[Crazy Development]
# joined -> [Product].[Product].[Company] # joined -> [Product].[Product].[Company]
last_attribut = ''.join(att for att in separed_tuple[-1]
if att not in '[]').replace(
'&', '&amp;')
return etree.fromstring(""" return etree.fromstring("""
<return> <return>
<root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset" <root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
""" + mdschema_members_xsd + """ """ + mdschema_members_xsd + """
<row> <row>
<CATALOG_NAME>{0}</CATALOG_NAME> <CATALOG_NAME>{0}</CATALOG_NAME>
<CUBE_NAME>{0}</CUBE_NAME> <CUBE_NAME>{0}</CUBE_NAME>
<DIMENSION_UNIQUE_NAME>{1}</DIMENSION_UNIQUE_NAME> <DIMENSION_UNIQUE_NAME>{1}</DIMENSION_UNIQUE_NAME>
<HIERARCHY_UNIQUE_NAME>{1}.{1}</HIERARCHY_UNIQUE_NAME> <HIERARCHY_UNIQUE_NAME>{1}.{1}</HIERARCHY_UNIQUE_NAME>
<LEVEL_UNIQUE_NAME>{2}</LEVEL_UNIQUE_NAME> <LEVEL_UNIQUE_NAME>{2}</LEVEL_UNIQUE_NAME>
<LEVEL_NUMBER>0</LEVEL_NUMBER> <LEVEL_NUMBER>0</LEVEL_NUMBER>
<MEMBER_ORDINAL>0</MEMBER_ORDINAL> <MEMBER_ORDINAL>0</MEMBER_ORDINAL>
<MEMBER_NAME>{4}</MEMBER_NAME> <MEMBER_NAME>""" + last_attribut +
<MEMBER_UNIQUE_NAME>{3}</MEMBER_UNIQUE_NAME> """</MEMBER_NAME>
<MEMBER_TYPE>1</MEMBER_TYPE> <MEMBER_UNIQUE_NAME>{3}</MEMBER_UNIQUE_NAME>
<MEMBER_CAPTION>{4}</MEMBER_CAPTION> <MEMBER_TYPE>1</MEMBER_TYPE>
<CHILDREN_CARDINALITY>1</CHILDREN_CARDINALITY> <MEMBER_CAPTION>""" + last_attribut +
<PARENT_LEVEL>0</PARENT_LEVEL> """</MEMBER_CAPTION>
<PARENT_COUNT>0</PARENT_COUNT> <CHILDREN_CARDINALITY>1</CHILDREN_CARDINALITY>
<MEMBER_KEY>{4}</MEMBER_KEY> <PARENT_LEVEL>0</PARENT_LEVEL>
<IS_PLACEHOLDERMEMBER>false</IS_PLACEHOLDERMEMBER> <PARENT_COUNT>0</PARENT_COUNT>
<IS_DATAMEMBER>false</IS_DATAMEMBER> <MEMBER_KEY>""" + last_attribut + """</MEMBER_KEY>
</row> <IS_PLACEHOLDERMEMBER>false</IS_PLACEHOLDERMEMBER>
</root> <IS_DATAMEMBER>false</IS_DATAMEMBER>
</return> </row>
""".format( </root>
self.selected_catalogue, separed_tuple[0], joined, </return>
request.Restrictions.RestrictionList.MEMBER_UNIQUE_NAME, """.format(self.selected_catalogue, separed_tuple[0],
''.join(c for c in separed_tuple[-1] if c not in '[]'))) joined, request.Restrictions.RestrictionList.
MEMBER_UNIQUE_NAME))
...@@ -325,6 +325,8 @@ class XmlaExecuteTools(): ...@@ -325,6 +325,8 @@ class XmlaExecuteTools():
cell_data = "" cell_data = ""
index = 0 index = 0
for value in columns_loop: for value in columns_loop:
if value == -1:
value = ''
cell_data += """ cell_data += """
<Cell CellOrdinal="{0}"> <Cell CellOrdinal="{0}">
<Value xsi:type="xsi:long">{1}</Value> <Value xsi:type="xsi:long">{1}</Value>
......
...@@ -4,6 +4,7 @@ pandas<1 ...@@ -4,6 +4,7 @@ pandas<1
lxml==3.6.0 #lxml 3.7 causes problems in windows lxml==3.6.0 #lxml 3.7 causes problems in windows
spyne<3 spyne<3
treelib<2 treelib<2
psycopg2
# Web # Web
Flask Flask
......
...@@ -4,13 +4,14 @@ ...@@ -4,13 +4,14 @@
# #
# pip-compile --output-file requirements.txt requirements.in # pip-compile --output-file requirements.txt requirements.in
# #
appdirs==1.4.3 # via setuptools appdirs==1.4.3 # via setuptools
astroid==1.4.9 # via pylint astroid==1.5.2 # via pylint
backports.functools-lru-cache==1.3 # via pylint backports.functools-lru-cache==1.3 # via astroid, pylint
click==6.7 # via flask, pip-tools click==6.7 # via flask, pip-tools
configparser==3.5.0 # via flake8, pylint configparser==3.5.0 # via flake8, pylint
coverage==4.3.4 # via pytest-cov coverage==4.3.4 # via pytest-cov
enum34==1.1.6 # via flake8 enum34==1.1.6 # via astroid, flake8
first==2.0.1 # via pip-tools first==2.0.1 # via pip-tools
flake8-tidy-imports==1.0.6 flake8-tidy-imports==1.0.6
flake8==3.3.0 flake8==3.3.0
...@@ -19,12 +20,12 @@ Flask-Script==2.0.5 ...@@ -19,12 +20,12 @@ Flask-Script==2.0.5
Flask-Session==0.3.0 Flask-Session==0.3.0
Flask-SQLAlchemy==2.1 Flask-SQLAlchemy==2.1
Flask-WTF==0.12 Flask-WTF==0.12
flask==0.12 flask==0.12.1
gprof2dot==2016.10.13 gprof2dot==2016.10.13
grako==3.19.1 grako==3.22.0
isort==4.2.5 isort==4.2.5
itsdangerous==0.24 # via flask itsdangerous==0.24 # via flask
jinja2==2.9.5 # via flask jinja2==2.9.6 # via flask
lazy-object-proxy==1.2.2 # via astroid lazy-object-proxy==1.2.2 # via astroid
lxml==3.6.0 lxml==3.6.0
markupsafe==1.0 # via jinja2 markupsafe==1.0 # via jinja2
...@@ -33,26 +34,28 @@ numpy==1.12.1 # via pandas ...@@ -33,26 +34,28 @@ numpy==1.12.1 # via pandas
olap==0.3 # via xmla olap==0.3 # via xmla
packaging==16.8 # via setuptools packaging==16.8 # via setuptools
pandas==0.19.2 pandas==0.19.2
pip-tools==1.8.0 pip-tools==1.9.0
plotly==1.12.9 plotly==1.12.9
pluggy==0.4.0 # via tox pluggy==0.4.0 # via tox
prettytable==0.7.2 prettytable==0.7.2
py-cpuinfo==0.2.7 psycopg2==2.7.1
py-cpuinfo==3.2.0
py==1.4.33 # via pytest, tox py==1.4.33 # via pytest, tox
pycodestyle==2.3.1 # via flake8 pycodestyle==2.3.1 # via flake8
pyflakes==1.5.0 # via flake8 pyflakes==1.5.0 # via flake8
pylint==1.6.5 pylint==1.7.1
pyparsing==2.2.0 # via packaging pyparsing==2.2.0 # via packaging
pytest-cov==2.4.0 pytest-cov==2.4.0
pytest==3.0.7 pytest==3.0.7
python-dateutil==2.6.0 # via pandas python-dateutil==2.6.0 # via pandas
pytz==2016.10 # via pandas, plotly, spyne pytz==2017.2 # via pandas, plotly, spyne
requests==1.2.3 # via plotly, xmla requests==1.2.3 # via plotly, xmla
six==1.10.0 # via astroid, packaging, pip-tools, plotly, pylint, python-dateutil, setuptools singledispatch==3.4.0.3 # via astroid, pylint
six==1.10.0 # via astroid, packaging, pip-tools, plotly, pylint, python-dateutil, setuptools, singledispatch
spyne==2.12.14 spyne==2.12.14
sqlalchemy==1.0.17 sqlalchemy==1.0.17
suds==0.4 # via xmla suds==0.4 # via xmla
tox==2.6.0 tox==2.7.0
treelib==1.3.5 treelib==1.3.5
virtualenv==15.1.0 # via tox virtualenv==15.1.0 # via tox
werkzeug==0.12.1 # via flask, flask-wtf werkzeug==0.12.1 # via flask, flask-wtf
...@@ -60,9 +63,9 @@ wrapt==1.10.10 # via astroid ...@@ -60,9 +63,9 @@ wrapt==1.10.10 # via astroid
wtforms==2.1 wtforms==2.1
XlsxWriter==0.9.3 XlsxWriter==0.9.3
xmla==0.7.2 xmla==0.7.2
yapf==0.15.2 yapf==0.16.1
zope.event==4.2.0 # via zope.schema zope.event==4.2.0 # via zope.schema
zope.interface==4.3.3 # via olap, zope.schema zope.interface==4.4.0 # via olap, zope.schema
zope.schema==4.4.2 # via olap zope.schema==4.4.2 # via olap
# The following packages are considered to be unsafe in a requirements file: # The following packages are considered to be unsafe in a requirements file:
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function from __future__ import absolute_import, division, print_function
import pip import os
import zipfile
from os.path import expanduser
from pip.download import PipSession
from pip.req import parse_requirements
from setuptools import find_packages, setup from setuptools import find_packages, setup
session = pip.download.PipSession() RUNNING_TOX = 'RUNTING_TOX' in os.environ
_install_requires = pip.req.parse_requirements(
session = PipSession()
_install_requires = parse_requirements(
'requirements.txt', session=session) 'requirements.txt', session=session)
install_requires = [str(ir.req) for ir in _install_requires] install_requires = [str(ir.req) for ir in _install_requires]
...@@ -29,3 +36,18 @@ setup( ...@@ -29,3 +36,18 @@ setup(
"Programming Language :: Python :: 2.7", "Programming Language :: Python :: 2.7",
# "Topic :: Business intelligence", # "Topic :: Business intelligence",
],) ],)
# initiate cubes examples
if RUNNING_TOX:
home_directory = os.environ.get('HOME_DIR')
else:
home_directory = expanduser("~")
if not os.path.isdir(os.path.join(home_directory, 'olapy-data', 'cubes')):
try:
os.makedirs(os.path.join(home_directory, 'olapy-data', 'cubes'))
zip_ref = zipfile.ZipFile('cubes_templates/cubes_temp.zip', 'r')
zip_ref.extractall(os.path.join(home_directory, 'olapy-data', 'cubes'))
zip_ref.close()
except:
raise ('unable to create cubes directory !')
...@@ -5,10 +5,10 @@ envlist = py27 ...@@ -5,10 +5,10 @@ envlist = py27
[testenv] [testenv]
setenv= setenv=
RUNTING_TOX=true RUNTING_TOX=true
HOME_DIR = {homedir}
whitelist_externals= whitelist_externals=
make make
commands= commands=
pip install -q -r requirements.txt pip install -q -r requirements.txt
pytest tests pytest tests
make lint make lint
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment