366 lines
8.7 KiB
Python
366 lines
8.7 KiB
Python
|
#!/usr/bin/python
|
||
|
#
|
||
|
# Copyright 2010 Google Inc. All Rights Reserved.
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
|
||
|
"""Data model classes for parsing and generating XML for both the
|
||
|
Google Analytics Data Export and Management APIs. Although both APIs
|
||
|
operate on different parts of Google Analytics, they share common XML
|
||
|
elements and are released in the same module.
|
||
|
|
||
|
The Management API supports 5 feeds all using the same ManagementFeed
|
||
|
data class.
|
||
|
"""
|
||
|
|
||
|
__author__ = 'api.nickm@google.com (Nick Mihailovski)'
|
||
|
|
||
|
|
||
|
import gdata.data
|
||
|
import atom.core
|
||
|
import atom.data
|
||
|
|
||
|
|
||
|
# XML Namespace used in Google Analytics API entities.
|
||
|
DXP_NS = '{http://schemas.google.com/analytics/2009}%s'
|
||
|
GA_NS = '{http://schemas.google.com/ga/2009}%s'
|
||
|
GD_NS = '{http://schemas.google.com/g/2005}%s'
|
||
|
|
||
|
|
||
|
class GetProperty(object):
|
||
|
"""Utility class to simplify retrieving Property objects."""
|
||
|
|
||
|
def get_property(self, name):
|
||
|
"""Helper method to return a propery object by its name attribute.
|
||
|
|
||
|
Args:
|
||
|
name: string The name of the <dxp:property> element to retrieve.
|
||
|
|
||
|
Returns:
|
||
|
A property object corresponding to the matching <dxp:property> element.
|
||
|
if no property is found, None is returned.
|
||
|
"""
|
||
|
|
||
|
for prop in self.property:
|
||
|
if prop.name == name:
|
||
|
return prop
|
||
|
|
||
|
return None
|
||
|
|
||
|
GetProperty = get_property
|
||
|
|
||
|
|
||
|
class GetMetric(object):
|
||
|
"""Utility class to simplify retrieving Metric objects."""
|
||
|
|
||
|
def get_metric(self, name):
|
||
|
"""Helper method to return a propery value by its name attribute
|
||
|
|
||
|
Args:
|
||
|
name: string The name of the <dxp:metric> element to retrieve.
|
||
|
|
||
|
Returns:
|
||
|
A property object corresponding to the matching <dxp:metric> element.
|
||
|
if no property is found, None is returned.
|
||
|
"""
|
||
|
|
||
|
for met in self.metric:
|
||
|
if met.name == name:
|
||
|
return met
|
||
|
|
||
|
return None
|
||
|
|
||
|
GetMetric = get_metric
|
||
|
|
||
|
|
||
|
class GetDimension(object):
|
||
|
"""Utility class to simplify retrieving Dimension objects."""
|
||
|
|
||
|
def get_dimension(self, name):
|
||
|
"""Helper method to return a dimention object by its name attribute
|
||
|
|
||
|
Args:
|
||
|
name: string The name of the <dxp:dimension> element to retrieve.
|
||
|
|
||
|
Returns:
|
||
|
A dimension object corresponding to the matching <dxp:dimension> element.
|
||
|
if no dimension is found, None is returned.
|
||
|
"""
|
||
|
|
||
|
for dim in self.dimension:
|
||
|
if dim.name == name:
|
||
|
return dim
|
||
|
|
||
|
return None
|
||
|
|
||
|
GetDimension = get_dimension
|
||
|
|
||
|
|
||
|
class GaLinkFinder(object):
|
||
|
"""Utility class to return specific links in Google Analytics feeds."""
|
||
|
|
||
|
def get_parent_links(self):
|
||
|
"""Returns a list of all the parent links in an entry."""
|
||
|
|
||
|
links = []
|
||
|
for link in self.link:
|
||
|
if link.rel == link.parent():
|
||
|
links.append(link)
|
||
|
|
||
|
return links
|
||
|
|
||
|
GetParentLinks = get_parent_links
|
||
|
|
||
|
def get_child_links(self):
|
||
|
"""Returns a list of all the child links in an entry."""
|
||
|
|
||
|
links = []
|
||
|
for link in self.link:
|
||
|
if link.rel == link.child():
|
||
|
links.append(link)
|
||
|
|
||
|
return links
|
||
|
|
||
|
GetChildLinks = get_child_links
|
||
|
|
||
|
def get_child_link(self, target_kind):
|
||
|
"""Utility method to return one child link.
|
||
|
|
||
|
Returns:
|
||
|
A child link with the given target_kind. None if the target_kind was
|
||
|
not found.
|
||
|
"""
|
||
|
|
||
|
for link in self.link:
|
||
|
if link.rel == link.child() and link.target_kind == target_kind:
|
||
|
return link
|
||
|
|
||
|
return None
|
||
|
|
||
|
GetChildLink = get_child_link
|
||
|
|
||
|
|
||
|
class StartDate(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:startDate>"""
|
||
|
_qname = DXP_NS % 'startDate'
|
||
|
|
||
|
|
||
|
class EndDate(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:endDate>"""
|
||
|
_qname = DXP_NS % 'endDate'
|
||
|
|
||
|
|
||
|
class Metric(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:metric>"""
|
||
|
_qname = DXP_NS % 'metric'
|
||
|
name = 'name'
|
||
|
type = 'type'
|
||
|
value = 'value'
|
||
|
confidence_interval = 'confidenceInterval'
|
||
|
|
||
|
|
||
|
class Aggregates(atom.core.XmlElement, GetMetric):
|
||
|
"""Analytics Data Feed <dxp:aggregates>"""
|
||
|
_qname = DXP_NS % 'aggregates'
|
||
|
metric = [Metric]
|
||
|
|
||
|
|
||
|
class TableId(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:tableId>"""
|
||
|
_qname = DXP_NS % 'tableId'
|
||
|
|
||
|
|
||
|
class TableName(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:tableName>"""
|
||
|
_qname = DXP_NS % 'tableName'
|
||
|
|
||
|
|
||
|
class Property(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:property>"""
|
||
|
_qname = DXP_NS % 'property'
|
||
|
name = 'name'
|
||
|
value = 'value'
|
||
|
|
||
|
|
||
|
class Definition(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:definition>"""
|
||
|
_qname = DXP_NS % 'definition'
|
||
|
|
||
|
|
||
|
class Segment(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:segment>"""
|
||
|
_qname = DXP_NS % 'segment'
|
||
|
id = 'id'
|
||
|
name = 'name'
|
||
|
definition = Definition
|
||
|
|
||
|
|
||
|
class Engagement(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:engagement>"""
|
||
|
_qname = GA_NS % 'engagement'
|
||
|
type = 'type'
|
||
|
comparison = 'comparison'
|
||
|
threshold_value = 'thresholdValue'
|
||
|
|
||
|
|
||
|
class Step(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:step>"""
|
||
|
_qname = GA_NS % 'step'
|
||
|
number = 'number'
|
||
|
name = 'name'
|
||
|
path = 'path'
|
||
|
|
||
|
|
||
|
class Destination(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:destination>"""
|
||
|
_qname = GA_NS % 'destination'
|
||
|
step = [Step]
|
||
|
expression = 'expression'
|
||
|
case_sensitive = 'caseSensitive'
|
||
|
match_type = 'matchType'
|
||
|
step1_required = 'step1Required'
|
||
|
|
||
|
|
||
|
class Goal(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:goal>"""
|
||
|
_qname = GA_NS % 'goal'
|
||
|
destination = Destination
|
||
|
engagement = Engagement
|
||
|
number = 'number'
|
||
|
name = 'name'
|
||
|
value = 'value'
|
||
|
active = 'active'
|
||
|
|
||
|
|
||
|
class CustomVariable(atom.core.XmlElement):
|
||
|
"""Analytics Data Feed <dxp:customVariable>"""
|
||
|
_qname = GA_NS % 'customVariable'
|
||
|
index = 'index'
|
||
|
name = 'name'
|
||
|
scope = 'scope'
|
||
|
|
||
|
|
||
|
class DataSource(atom.core.XmlElement, GetProperty):
|
||
|
"""Analytics Data Feed <dxp:dataSource>"""
|
||
|
_qname = DXP_NS % 'dataSource'
|
||
|
table_id = TableId
|
||
|
table_name = TableName
|
||
|
property = [Property]
|
||
|
|
||
|
|
||
|
class Dimension(atom.core.XmlElement):
|
||
|
"""Analytics Feed <dxp:dimension>"""
|
||
|
_qname = DXP_NS % 'dimension'
|
||
|
name = 'name'
|
||
|
value = 'value'
|
||
|
|
||
|
|
||
|
class AnalyticsLink(atom.data.Link):
|
||
|
"""Subclass of link <link>"""
|
||
|
target_kind = GD_NS % 'targetKind'
|
||
|
|
||
|
@classmethod
|
||
|
def parent(cls):
|
||
|
"""Parent target_kind"""
|
||
|
return '%s#parent' % GA_NS[1:-3]
|
||
|
|
||
|
@classmethod
|
||
|
def child(cls):
|
||
|
"""Child target_kind"""
|
||
|
return '%s#child' % GA_NS[1:-3]
|
||
|
|
||
|
|
||
|
# Account Feed.
|
||
|
class AccountEntry(gdata.data.GDEntry, GetProperty):
|
||
|
"""Analytics Account Feed <entry>"""
|
||
|
_qname = atom.data.ATOM_TEMPLATE % 'entry'
|
||
|
table_id = TableId
|
||
|
property = [Property]
|
||
|
goal = [Goal]
|
||
|
custom_variable = [CustomVariable]
|
||
|
|
||
|
|
||
|
class AccountFeed(gdata.data.GDFeed):
|
||
|
"""Analytics Account Feed <feed>"""
|
||
|
_qname = atom.data.ATOM_TEMPLATE % 'feed'
|
||
|
segment = [Segment]
|
||
|
entry = [AccountEntry]
|
||
|
|
||
|
|
||
|
# Data Feed.
|
||
|
class DataEntry(gdata.data.GDEntry, GetMetric, GetDimension):
|
||
|
"""Analytics Data Feed <entry>"""
|
||
|
_qname = atom.data.ATOM_TEMPLATE % 'entry'
|
||
|
dimension = [Dimension]
|
||
|
metric = [Metric]
|
||
|
|
||
|
def get_object(self, name):
|
||
|
"""Returns either a Dimension or Metric object with the same name as the
|
||
|
name parameter.
|
||
|
|
||
|
Args:
|
||
|
name: string The name of the object to retrieve.
|
||
|
|
||
|
Returns:
|
||
|
Either a Dimension or Object that has the same as the name parameter.
|
||
|
"""
|
||
|
|
||
|
output = self.GetDimension(name)
|
||
|
if not output:
|
||
|
output = self.GetMetric(name)
|
||
|
|
||
|
return output
|
||
|
|
||
|
GetObject = get_object
|
||
|
|
||
|
|
||
|
class DataFeed(gdata.data.GDFeed):
|
||
|
"""Analytics Data Feed <feed>.
|
||
|
|
||
|
Although there is only one datasource, it is stored in an array to replicate
|
||
|
the design of the Java client library and ensure backwards compatibility if
|
||
|
new data sources are added in the future.
|
||
|
"""
|
||
|
|
||
|
_qname = atom.data.ATOM_TEMPLATE % 'feed'
|
||
|
start_date = StartDate
|
||
|
end_date = EndDate
|
||
|
aggregates = Aggregates
|
||
|
data_source = [DataSource]
|
||
|
entry = [DataEntry]
|
||
|
segment = Segment
|
||
|
|
||
|
|
||
|
# Management Feed.
|
||
|
class ManagementEntry(gdata.data.GDEntry, GetProperty, GaLinkFinder):
|
||
|
"""Analytics Managememt Entry <entry>."""
|
||
|
|
||
|
_qname = atom.data.ATOM_TEMPLATE % 'entry'
|
||
|
kind = GD_NS % 'kind'
|
||
|
property = [Property]
|
||
|
goal = Goal
|
||
|
segment = Segment
|
||
|
link = [AnalyticsLink]
|
||
|
|
||
|
|
||
|
class ManagementFeed(gdata.data.GDFeed):
|
||
|
"""Analytics Management Feed <feed>.
|
||
|
|
||
|
This class holds the data for all 5 Management API feeds: Account,
|
||
|
Web Property, Profile, Goal, and Advanced Segment Feeds.
|
||
|
"""
|
||
|
|
||
|
_qname = atom.data.ATOM_TEMPLATE % 'feed'
|
||
|
entry = [ManagementEntry]
|
||
|
kind = GD_NS % 'kind'
|