Thursday, 29 January 2026

Python3 super()

Putting an example:

class B(C):

   @staticmethod

   def test():

        print('unbound supers can only call static methods of classes')

   def test2(self):

        print('bound methods require bound instances or self argument')

class A(B):

   def __init__(self):

       self.super() # returns this object as a parent (B) instance

       self.super(A, self) # returns this object as a bound B instance

       self.super(B, self) # returns this object as a bound C instance

       self.super(B) # returns this object as an unbound reference to B!!

       self.super(B).__thisclass__.test() # usable, but complex

       type(self).__mro__[1].test() # equivalent call

       B.test() # when you explicitly one to point to a given method

       B.test2(self) # ídem, but bound


Summarizing:

   - Use self.super().method() when wanting to access the parent version of a method

   - Use self.super(<type>, self).method() when wanting to go to the parent of an specific class

   - Use <type>.method(self,...) when you already know the object to call

Wednesday, 9 January 2019

apt / apt-get / aptitude recipes

First, update your package lists


  • $ sudo apt-get update


Get all available versions of a package (when you have multiple repos)


  • $ apt-cache madison python-panic

you can install one specific version with 

  • apt-get install <packagename>=<packageversion>

Get currently installed version; probably there's a better way, but a simulated call to apt-get install will print the already installed package


  • $ sudo apt-get -s install python-panic


Addendum by SB:


$ apt-cache policy ctpc
ctpc:
  Installed: 2.0.13-0~bpo9+0~alba+1
  Candidate: 2.0.13-0~bpo9+0~alba+1
  Version table:
 *** 2.0.13-0~bpo9+0~alba+1 500

There is also another alternative from apt instead of apt-cache

$ apt list ctpc -a
Listing... Done
ctpc/stretch,now 2.0.13-0~bpo9+0~alba+1 all [installed]
ctpc/stretch 2.0.11-0~bpo9+0~alba+1 all
(...)

Use the one that fits better to your needs.

Wednesday, 5 December 2018

Setting up a Telegram Bot

Configuring PyAlarm to send Telegram messages

First of all, you'll need a telegram account and sign-in to https://web.telegram.org
To send messages to Telegram users we will need a Bot (https://core.telegram.org/bots/api).
  • Open a chat with @BotFather bot
  • Type /newbot
  • Enter your bot name and bot_address
  • Take note of your bot token (a long number like NNNN:ASDFASDFASDFAASDF )
Once you have it, you can test your bot:
https://web.telegram.org/#/im?p=@<bot_address>
https://api.telegram.org/bot<token>/getMe
Then, add a new property TGConfig to PyAlarm with your token:
fandango.tango.put_device_property('your/device/name','TGConfig','NNNNN:YOURBOTTOKEN')
To start sending messages you will need now your user_id or chat_id (not your username, but a numeric identifier).
To obtain it:
  • Open a chat with @userinfobot to get your numeric user_id.
  • Add your previously created Bot to a group and call https://api.telegram.org/bot<token>/getUpdates to see the group chat_id.
Once you have the ID, just add a new receiver:
TG:654654654

Friday, 19 October 2018

Testing PyTangoArchiving package on virtualenv

git clone https://github.com/tango-controls/pytangoarchiving

cd pytangoarchiving

# I assume that PyTango is already installed, it doesn't work if installed from venv as dependency

virtualenv --system-site-packages TEST

. TEST/bin/activate
python setup.py install 


export TANGO_HOST=test01:10000

archiving2csv --modes test.csv

deactivate

Monday, 30 July 2018

Running a Tango Device Server without database

The device has been launched as
.../ds/MyServer <instance> -v4 -ORBendPoint giop:tdb::10000 -nodb -dlist sr/id/ds01
The client has been created as
dp = PyTango.DeviceProxy('tango://127.0.0.1:10000/sr/id/ds01#dbase=no')

Wednesday, 22 November 2017

Showing Raw Data curves in TaurusPlot or TaurusTrend

The easiest way is to use the importAscii method to load data from a file:
    !head test.csv
    1383260422.0    0.0928575       0.0116941
    1383260452.0    0.0975427       0.00988106
    1383260482.0    0.0953354       0.00834905

from taurus.qt.qtgui.application import TaurusApplication
from taurus.qt.qtgui.plot import TaurusPlot
import sys

csvfile = sys.argv[1:]

app = TaurusApplication()
plot = TaurusPlot()
plot.importAscii(filenames=csvfile,xcol=0)
plot.setXIsTime(True)
plot.show()

sys.exit(app.exec_())

It can be done also using raw PyQwt
import fandango
import PyTangoArchiving as pta
rd = pta.Reader('hdb')

ats = fandango.tango.get_matching_device_attributes('sr04/vc/eps-plc-01/*TC*'
vals = rd.get_attributes_values(ats,'2011-10-18','2011-10-22',correlate=False,text=False,asHistoryBuffer=False)

from PyQt4 import Qt,Qwt5
from PyQt4.Qwt5 import qpl

qapp = Qt.QApplication([])
def get_color_for_i(i):
    top = 256**3
    tot = top/i
    c = tot
    return Qt.QColor(c%256,(c/256)%256,((c/256)/256)%256
p = qplt.Plot(*[qplt.Curve([x[0] for x in c],[y[1] for y in c],'curve %d'%i,qplt.Pen(get_color_for_i(i))) for i,c in enumerate(vals.values())])

----

I've actually done a pull request on Taurus to do it in this way:

generate raw data from archiving and/or matlab:

archiving2csv --noheader --noepoch <model1> <model2> <date1> <date2> /tmp/file.csv
the generated file can then be opened by taurusplot just doing:

taurusplot -x t --import=/tmp/file.csv

Wednesday, 15 November 2017

Qt5 / QWebKit, an script to show a webpage in a widget and save it to .jpg

# This script could be launched with -profile offscreen to avoid using a desktop; but it failed due to missing fonts


import sys
from PyQt5 import Qt,QtWebKitWidgets

SIZE = 1440,720
URL = 'https://.../Reports/wr/msGUI-js.html'
FILE = '/tmp/test.jpg'
SHOW = True

if not SHOW: ops = sys.argv+['-platform','offscreen']
else: ops = sys.argv

qapp = Qt.QApplication(ops)
    
qwv = QtWebKitWidgets.QWebView()
qwv.load(Qt.QUrl(URL))

qwv.resize(*SIZE)
if SHOW: qwv.show()

def grabber():
    pm = qwv.grab()
    pm.save(FILE,'jpg')
    print('%s done'%FILE)

timer = Qt.QTimer()
timer.timeout.connect(grabber)
timer.start(5000.)

print('starting ...')
sys.exit(qapp.exec_())

Wednesday, 13 September 2017

MONGODB, fast, simple howto

See http://api.mongodb.com/python/current/tutorial.html

For a GUI, look at: https://github.com/mongo-express/mongo-express/

REST APIs at https://docs.mongodb.com/ecosystem/tools/http-interfaces/

The default REST api is unsecure, but can be tested adding rest = True at /etc/mongodb.conf

To access the db created in this howto:

http://127.0.0.1:28017/snaps/alarms/
http://127.0.0.1:28017/snaps/alarms/?filter_name=alarm%201

----

# aptitude install mongodb python-pymongo

$ ipython

In [1]: import pymongo

In [2]: client = pymongo.MongoClient()


# or >>> client = MongoClient('localhost', 27017)

# Databases and Collections are created on-the-fly

In [3]: snapsdb = client.snaps

In [10]: client.snaps
Out[10]: Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), u'snaps')


In [11]: alarms = snapsdb.alarms

# To insert data in a collection, just throw a dictionary of basetypes

In [8]: post = {"name":"alarm 1","values":{"attr1":0,"attr2":['just','three','strings']}}

In [12]: s = alarms.insert_one(post)

In [13]: s.inserted_id
Out[13]: ObjectId('59ba22c0496ae3058504e362')


In [16]: snapsdb.collection_names()
Out[16]: [u'alarms']


# Find_one may be colled with filters(dict) or without them

In [19]: alarms.find_one()
Out[19]:  
{u'_id': ObjectId('59ba22c0496ae3058504e362'),
u'name': u'alarm 1',
u'values': {u'attr1': 0, u'attr2': [u'just', u'three', u'strings']}}

In [20]: post = {"name":"alarm 2","values":{"attr1":4,"attr2":['just','two',]}}

In [21]: alarms.insert_one(post)

In [25]: alarms.find_one({"name":"alarm 2"})
Out[25]:  
{u'_id': ObjectId('59ba2342496ae3058504e363'),
u'name': u'alarm 2',
u'values': {u'attr1': 4, u'attr2': [u'just', u'two']}}


# Regexp searches syntax is ugly, but works

In [30]: alarms.find_one({"name":{'$regex':"alarm .*"}})
Out[30]:  
{u'_id': ObjectId('59ba22c0496ae3058504e362'),
u'name': u'alarm 1',
u'values': {u'attr1': 0, u'attr2': [u'just', u'three', u'strings']}}


# Find multiple values

In [31]: alarms.find({"name":{'$regex':"alarm .*"}})
Out[31]: <pymongo.cursor.Cursor at 0x7f18d00fe110>

In [32]: cursor = alarms.find({"name":{'$regex':"alarm .*"}})

In [33]: list(cursor)
Out[33]:  
[{u'_id': ObjectId('59ba22c0496ae3058504e362'),
 u'name': u'alarm 1',
 u'values': {u'attr1': 0, u'attr2': [u'just', u'three', u'strings']}},
{u'_id': ObjectId('59ba2342496ae3058504e363'),
 u'name': u'alarm 2',
 u'values': {u'attr1': 4, u'attr2': [u'just', u'two']}}]