Create activities for an user with Stream-Framework - python

I'm trying to setup stream-framework the one here not the newer getstream. I've setup the Redis server and the environment properly, the issue I'm facing is in creating the activities for a user.
I've been trying to create activities, following the documentation to add an activity but it gives me an error message as follows:
...
File "/Users/.../stream_framework/activity.py", line 110, in serialization_id
if self.object_id >= 10 ** 10 or self.verb.id >= 10 ** 3:
AttributeError: 'int' object has no attribute 'id'
Here is the code
from stream_framework.activity import Activity
from stream_framework.feeds.redis import RedisFeed
class PinFeed(RedisFeed):
key_format = 'feed:normal:%(user_id)s'
class UserPinFeed(PinFeed):
key_format = 'feed:user:%(user_id)s'
feed = UserPinFeed(13)
print(feed)
activity = Activity(
actor=13, # Thierry's user id
verb=1, # The id associated with the Pin verb
object=1, # The id of the newly created Pin object
)
feed.add(activity) # Error at this line
I think there is something missing in the documentation or maybe I'm doing something wrong. I'll be very grateful if anyone helps me get the stream framework working properly.

The documentation is inconsistent. The verb you pass to the activity should be (an instance of?*) a subclass of stream_framework.verbs.base.Verb. Check out this documentation page on custom verbs and the tests for this class.
The following should fix the error you posted:
from stream_framework.activity import Activity
from stream_framework.feeds.redis import RedisFeed
from stream_framework.verbs import register
from stream_framework.verbs.base import Verb
class PinFeed(RedisFeed):
key_format = 'feed:normal:%(user_id)s'
class UserPinFeed(PinFeed):
key_format = 'feed:user:%(user_id)s'
class Pin(Verb):
id = 5
infinitive = 'pin'
past_tense = 'pinned'
register(Pin)
feed = UserPinFeed(13)
activity = Activity(
actor=13,
verb=Pin,
object=1,
)
feed.add(activity)
I quickly looked over the code for Activity and it looks like passing ints for actor and object should work. However, it is possible that these parameters are also outdated in the documentation.
* The tests pass in classes as verb. However, the Verb base class has the methods serialize and __str__ that can only be meaningfully invoked if you have an object of this class. So I'm still unsure which is required here. It seems like in the current state, the framework never calls these methods, so classes still work, but I feel like the author originally intended to pass instances.

With the help of great answer by #He3lixxx, I was able to solve it partially. As the package is no more maintained, the package installs the latest Redis client for python which was creating too many issues so by installation redis-2.10.5 if using stream-framework-1.3.7, should fix the issue.
I would also like to add a complete guide to properly add activity to a user feed.
Key points:
If you are not using feed manager, then make sure to first insert the activity before you add it to the user with feed.insert_activity(activity) method.
In case of getting feeds with feed[:] throws an error something like below:
File "/Users/.../stream_framework/activity.py", line 44, in get_hydrated
activity = activities[int(self.serialization_id)]
KeyError: 16223026351730000000001005L
then you need to clear data for that user using the key format for it in my case the key is feed:user:13 for user 13, delete it with DEL feed:user:13, In case if that doesn't fix the issue then you can FLUSHALL which will delete everything from Redis.
Sample code:
from stream_framework.activity import Activity
from stream_framework.feeds.redis import RedisFeed
from stream_framework.verbs import register
from stream_framework.verbs.base import Verb
class PinFeed(RedisFeed):
key_format = 'feed:normal:%(user_id)s'
class UserPinFeed(PinFeed):
key_format = 'feed:user:%(user_id)s'
class Pin(Verb):
id = 5
infinitive = 'pin'
past_tense = 'pinned'
register(Pin)
feed = UserPinFeed(13)
print(feed[:])
activity = Activity(
actor=13,
verb=Pin,
object=1)
feed.insert_activity(activity)
activity_id = feed.add(activity)
print(activity_id)
print(feed[:])

Related

Cannot (always) fetch an attribute in an object even though it exists

I'm currently developing locally an Azure function that communicates with Microsoft Sentinel, in order to fetch the alert rules from it, and more specifically their respective querys :
credentials = AzureCliCredential()
alert_rules_operations = SecurityInsights(credentials, SUBSCRIPTION_ID).alert_rules
list_alert_rules = alert_rules_operations.list(resource_group_name=os.getenv('RESOURCE_GROUP_NAME'), workspace_name=os.getenv('WORKSPACE_NAME'))
The issue is that when I'm looping over list_alert_rules, and try to see each rule's query, I get an error:
Exception: AttributeError: 'FusionAlertRule' object has no attribute 'query'.
Yet, when I check their type via the type() function:
list_alert_rules = alert_rules_operations.list(resource_group_name=os.getenv(
'RESOURCE_GROUP_NAME'), workspace_name=os.getenv('WORKSPACE_NAME'))
for rule in list_alert_rules:
print(type(rule))
##console: <class 'azure.mgmt.securityinsight.models._models_py3.ScheduledAlertRule'>
The weirder issue is that this error appears only when you don't print the attribute. Let me show you:
Print:
for rule in list_alert_rules:
query = rule.query
print('query', query)
##console: query YAY I GET WHAT I WANT
No print:
for rule in list_alert_rules:
query = rule.query
...
##console: Exception: AttributeError: 'FusionAlertRule' object has no attribute 'query'.
I posted the issue on the GitHub repo, but I'm not sure whether it's a package bug or a runtime issue. Has anyone ran into this kind of problems?
BTW I'm running Python 3.10.8
TIA!
EDIT:
I've tried using a map function, same issue:
def format_list(rule):
query = rule.query
# print('query', query)
# query = query.split('\n')
# query = list(filter(lambda line: "//" not in line, query))
# query = '\n'.join(query)
return rule
def main(mytimer: func.TimerRequest) -> None:
# results = fetch_missing_data()
credentials = AzureCliCredential()
alert_rules_operations = SecurityInsights(
credentials, SUBSCRIPTION_ID).alert_rules
list_alert_rules = alert_rules_operations.list(resource_group_name=os.getenv(
'RESOURCE_GROUP_NAME'), workspace_name=os.getenv('WORKSPACE_NAME'))
list_alert_rules = list(map(format_list, list_alert_rules))
I have tried with same as you used After I changed like below; I get the valid response.
# Management Plane - Alert Rules
alertRules = mgmt_client.alert_rules.list_by_resource_group('<ResourceGroup>')
for rule in alertRules:
# Try this
test.query = rule.query //Get the result
#print(rule)
if mytimer.past_due:
logging.info('The timer is past due!')
Instead of this
for rule in list_alert_rules:
query = rule.query
Try below
for rule in list_alert_rules:
# Try this
test.query = rule.query
Sorry for the late answer as I've been under tons of work these last few days.
Python has an excellent method called hasattr that checks if the object contains a specific key.
I've used it in the following way:
for rule in rules:
if hasattr(rule, 'query'):
...
The reason behind using this is because the method returns object of different classes, however inherited from the one same mother class.
Hope this helps.

no value for argument self in unbound method call

Thanks for reading this. I've spent the past 48 hours trying to get this code to work. First of all I must disclose that this is for a college assignment. I'm not looking for any assistance or comment on how I might 'gain' in the assignment, I just need to figure out what I'm doing wrong. I have googled the issue and I've read through tutorials on classes and I do feel like I understand them and have got the examples to work. This one issue is stumping me.
So, I have a class which will read a database as follows:
import mysql.connector
import pandas as pd
class DAOdv:
#dbConn=mysql.connector.connect()
def __init__(self):
# import the config file
config=pd.read_csv('./files/config.ini')
dbName=config.iloc[int(config[config['item']=='databaseName'].index[0])]['setting']
uname=config.iloc[int(config[config['item']=='username'].index[0])]['setting']
hst=config.iloc[int(config[config['item']=='host'].index[0])]['setting']
prt=config.iloc[int(config[config['item']=='port'].index[0])]['setting']
# create the connection
self.dbConn=mysql.connector.connect(
host=hst,
database=dbName,
port=prt,
username=uname,
password='' # no password on Server as yet
)
def allClients(self):
cursor=self.dbConn.cursor()
sSQL = 'SELECT * FROM clients'
cursor.execute(sSQL)
results=cursor.fetchall()
return results
daoDV=DAOdv()
and the 'server' code which is:
from flask import Flask
from daoDV import DAOdv
app=Flask(__name__, static_url_path='',static_folder='')
# curl "http://127.0.0.1:5000/clients"
#app.route('/clients')
def getAll():
results=DAOdv.allClients()
return results
In python, the second last line above, DAOdv is underlined in red and hovering over it produces the message "no value for argument self in unbound method call"
What am I doing wrong? I'm assuming the error is in the class?? but I can't figure out what.
Many thanks for your help with this.
Seamus
DAOdv is the class itself, not the instantiated object which you create at the end with: daoDV=DAOdv().
Change your server code to:
from daoDV import daoDV # note the capitalization - we're importing the object here
#(...)
results = daoDV.allClients()
Your method allClients() is an instance method, not a class method.
That's why you should call it like:
results=DAOdv().allClients()
Methods can be an instance or class method.
Class methods are methods which have #classmethod decorator.

class variable was caches in next request when use django-rest-framework renderer

I make use of uwsgi, django and django-rest-framework to develop one application.
I introduced one class variable in renderer class, this variable will be fill as one part of response.
the problem seems likes as following:
class xxxRenderer(xxxBase)
response_pb_msg = obj # it's one instance of protobuf message
def render():
if True:
self.response_pb_msg.items = []
else:
self.response_pb_msg.retCode = 100
self.response_pb_msg.otherXXXX = xxxx
In django logger handler, I access this class variable again like following:
xxxRenderer.response_pb_msg.ParseFromString(body)
after the first response, this class variable 'response_pb_msg' only has one property "retCode"
but the second response, it has three properties "retCode", "otherXXXX " and "items "
it's strange, the second response contain all content which was exist in the first response.
after a time, I re-wrote this class like following:
class xxxBaserender(xxRender)
def __init__():
if self.response_pb_msg_cls is not None and isinstance(self.response_pb_msg_cls, GeneratedProtocolMessageType):
self.response_pb_message = self.response_pb_msg_cls()
class xxxRenderer(xxxBaserender)
response_pb_msg_cls = msgName # the class of protobuf message
theoretically, the second class is ok. I tested, didn't duplicate that question.
Let's return to where we started
Every request finisehd, all resoure should be clean.
but I'm very puzzled with that problem, it seems that class variable not been released in uwsgi progress after response return.
I read “PEP 3333”, didn't get any valuable information.
I think I didn't fully understand class variaable, wsgi and web processing flow in python.
anyone can help me to understand this problem?
thanks vey much.

Accessing portal content with custom workflow and no 'View' permissions

I have a problem where I need to be able to make custom content accessible for search and retrieval via portal_catalog by anonymous users but not viewable by them.
I used custom content types and a custom workflow, what I'm getting is most likely a permission issue. I defined a custom workflow through ZMI -> portal_workflow and then exported it into source code as an XML definition. I set the permissions for anonymous users as 'Access Content Information' but not 'View'. Note that 'active' in the code snippet is a workflow state that has that permission enabled -- sales_workflow
Brain lookup works for 'Manager' role, but when the role is switched to 'Anonymous', catalog returns an empty list.
import unittest2 as unittest
from . import INTEGRATION_TESTING
from AccessControl import getSecurityManager
from plone.app.testing import setRoles, logout
from plone.app.testing import TEST_USER_ID
from Products.CMFCore.utils import getToolByName
def drop_to_anonymous(self):
"""
Drop site roles to anonymous user only.
Note this is a class method and not a function
assign this method as a class member and then call it
"""
logout()
setRoles(self.portal, TEST_USER_ID, ['Anonymous'])
user = getSecurityManager().getUser()
roles = user.getRolesInContext(self.portal)
self.assertListEqual(['Anonymous'], roles)
class TestSalesRepWorkflow(unittest.TestCase):
layer = INTEGRATION_TESTING
drop_to_anonymous = drop_to_anonymous
def setUp(self):
self.portal = self.layer['portal']
self.wftool = getToolByName(self.portal, 'portal_workflow')
self.catalog = getToolByName(self.portal, 'portal_catalog')
def test_workflow_lookup_anon(self):
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.portal.invokeFactory(
'CustomProduct',
'prod1',
title="Product 1"
)
prod1 = self.portal['prod1']
self.wftool.doActionFor(prod1, action='activate')
review_state = self.wftool.getInfoFor(prod1, 'review_state')
prod1.reindexObject()
self.assertEqual('active', review_state)
lookup = self.catalog(portal_type='CustomProduct', Title='Product 1',
review_state='active')
#This test passes with managerial permissions
self.assertEqual(len(lookup), 1)
#Repeat the same test in 'Anonymous' role
self.drop_to_anonymous()
lookup1 = self.catalog(portal_type='CustomProduct', Title='Product 1',
review_state='active')
#When dropped to anonymous role, the test fails,
#lookup returns an empty list
self.assertEqual(len(lookup1), 1)
Is there a way to fix this without drastically reworking permissions?
Using unrestrictedSearchResults seems to fix the search, but whenever I attempt to run 'getObject' on a brain, the following error gets raised:
Unauthorized: You are not allowed to access 'XXX' in this context
Your active state needs to give the View permission to Anonymous. Currently it is restricted to these roles:
<state state_id="active" title="">
<!-- other information elided here -->
<permission-map name="View" acquired="False">
<permission-role>Manager</permission-role>
<permission-role>Owner</permission-role>
<permission-role>Reviewer</permission-role>
<permission-role>SalesRep</permission-role>
<permission-role>Site Administrator</permission-role>
</permission-map>
Without the View permission anonymous cannot see your objects even when given the active state, nor can they be found in the catalog by that user.
You can override this behaviour of the catalog by using the .unrestrictedSearchResults() method of the catalog:
lookup1 = self.catalog.unrestrictedSearchResults(
portal_type='SalesProduct', Title='Product 1', review_state='active')
This method cannot be used from restricted code.
The returned brain objects are perfectly accessible by anonymous users, but you cannot use the getObject() method on them because that'll use the current user's permissions to traverse to it. If you need to get the actual object from the brain, there is again a special, private method to get to the actual object without those restrictions, called ._unrestrictedGetObject():
obj = brain._unrestrictedGetObject()
This method is, once again, only available to unrestricted code.

Google Analytics and Python

I'm brand new at Python and I'm trying to write an extension to an app that imports GA information and parses it into MySQL. There is a shamfully sparse amount of infomation on the topic. The Google Docs only seem to have examples in JS and Java...
...I have gotten to the point where my user can authenticate into GA using SubAuth. That code is here:
import gdata.service
import gdata.analytics
from django import http
from django import shortcuts
from django.shortcuts import render_to_response
def authorize(request):
next = 'http://localhost:8000/authconfirm'
scope = 'https://www.google.com/analytics/feeds'
secure = False # set secure=True to request secure AuthSub tokens
session = False
auth_sub_url = gdata.service.GenerateAuthSubRequestUrl(next, scope, secure=secure, session=session)
return http.HttpResponseRedirect(auth_sub_url)
So, step next is getting at the data. I have found this library: (beware, UI is offensive) http://gdata-python-client.googlecode.com/svn/trunk/pydocs/gdata.analytics.html
However, I have found it difficult to navigate. It seems like I should be gdata.analytics.AnalyticsDataEntry.getDataEntry(), but I'm not sure what it is asking me to pass it.
I would love a push in the right direction. I feel I've exhausted google looking for a working example.
Thank you!!
EDIT: I have gotten farther, but my problem still isn't solved. The below method returns data (I believe).... the error I get is: "'str' object has no attribute '_BecomeChildElement'" I believe I am returning a feed? However, I don't know how to drill into it. Is there a way for me to inspect this object?
def auth_confirm(request):
gdata_service = gdata.service.GDataService('iSample_acctSample_v1.0')
feedUri='https://www.google.com/analytics/feeds/accounts/default?max-results=50'
# request feed
feed = gdata.analytics.AnalyticsDataFeed(feedUri)
print str(feed)
Maybe this post can help out. Seems like there are not Analytics specific bindings yet, so you are working with the generic gdata.
I've been using GA for a little over a year now and since about April 2009, i have used python bindings supplied in a package called python-googleanalytics by Clint Ecker et al. So far, it works quite well.
Here's where to get it: http://github.com/clintecker/python-googleanalytics.
Install it the usual way.
To use it: First, so that you don't have to manually pass in your login credentials each time you access the API, put them in a config file like so:
[Credentials]
google_account_email = youraccount#gmail.com
google_account_password = yourpassword
Name this file '.pythongoogleanalytics' and put it in your home directory.
And from an interactive prompt type:
from googleanalytics import Connection
import datetime
connection = Connection() # pass in id & pw as strings **if** not in config file
account = connection.get_account(<*your GA profile ID goes here*>)
start_date = datetime.date(2009, 12, 01)
end_data = datetime.date(2009, 12, 13)
# account object does the work, specify what data you want w/
# 'metrics' & 'dimensions'; see 'USAGE.md' file for examples
account.get_data(start_date=start_date, end_date=end_date, metrics=['visits'])
The 'get_account' method will return a python list (in above instance, bound to the variable 'account'), which contains your data.
You need 3 files within the app. client_secrets.json, analytics.dat and google_auth.py.
Create a module Query.py within the app:
class Query(object):
def __init__(self, startdate, enddate, filter, metrics):
self.startdate = startdate.strftime('%Y-%m-%d')
self.enddate = enddate.strftime('%Y-%m-%d')
self.filter = "ga:medium=" + filter
self.metrics = metrics
Example models.py: #has the following function
import google_auth
service = googleauth.initialize_service()
def total_visit(self):
object = AnalyticsData.objects.get(utm_source=self.utm_source)
trial = Query(object.date.startdate, object.date.enddate, object.utm_source, ga:sessions")
result = service.data().ga().get(ids = 'ga:<your-profile-id>', start_date = trial.startdate, end_date = trial.enddate, filters= trial.filter, metrics = trial.metrics).execute()
total_visit = result.get('rows')
<yr save command, ColumnName.object.create(data=total_visit) goes here>

Categories

Resources