You are not logged in.
Hello there,
I make update notifier for conky and I hope that it will be useful for someone. Code may be bad, but it works
Installation:
1. insert into conky something like this ${texeci 10800 python path/to/python/script}
2. into cron insert (e.g. /etc/cron.hourly/) shell script
pacman -Sy
3. insert somewhere this python script (e.g. /home/user/notify.py)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Description: Python script for notifying archlinux updates.
# Usage: Put shell script with command 'pacman -Sy' into /etc/cron.hourly/
# Conky: e.g. put in conky '${texeci 1800 python path/to/this/file}'
# Author: Michal Orlik <thror.fw@gmail.com>, sabooky <sabooky@yahoo.com>
################################################################################
# SETTINGS - main settings
# set this to True if you just want one summary line (True/False)
brief = False
# number of packages to display (0 = display all)
num_of_pkgs = 5
#show only important packages
onlyImportant = False
########################################
# OPTIONAL SETTINGS
# PACKAGE RATING - prioritize packages by rating
# pkgs will be sorted by rating. pkg rating = ratePkg + rateRepo for that pkg
# pkg (default=0, wildcards accepted)
ratePkg = {
'kernel*':10,
'pacman':9,
'nvidia*':8,
}
# repo (default=0, wildcards accepted)
rateRepo = {
'core':5,
'extra':4,
'community':3,
'testing':2,
'unstable':1,
}
# at what point is a pkg considered "important"
iThresh = 5
########################################
# OUTPUT SETINGS - configure the output format
# change width of output
width = 52
# if you would use horizontal you possibly want to disable 'block'
horizontally = False
# separator of horizontal layout
separator = ' ---'
# pkg template - this is how individual pkg info is displayed ('' = disabled)
# valid keywords - %(name)s, %(repo)s, %(size).2f, %(ver)s, %(rate)s
pkgTemplate = " %(repo)s/%(name)s %(ver)s"
# important pkg tempalte - same as above but for "important" pkgs
ipkgTemplate = " *!* %(repo)s/%(name)s %(ver)s"
# summary template - this is the summary line at the end
# valid keywords - %(numpkg)d, %(size).2f, %(inumpkg), %(isize).2f, %(pkgstring)s
summaryTemplate = " %(numpkg)d %(pkgstring)s"
# important summary template - same as above if "important" pkgs are found
isummaryTemplate = summaryTemplate + " (%(inumpkg)d important %(isize).2f MB)"
# pkg right column template - individual pkg right column
# valid keywords - same as pkgTemplate
pkgrightcolTemplate = "%(size).2f MB"
# important pkg right column template - same as above but for important pkgs
ipkgrightcolTemplate = pkgrightcolTemplate
# summary right column template - summay line right column
# valid keywords - same as summaryTemplate
summaryrightcolTemplate = "%(size).2f MB"
# important summary right column template - same as above if "important" pkgs are found
isummaryrightcolTemplate = summaryrightcolTemplate
# seperator before summary ('' = disabled)
block = '-' * 12
# up to date msg
u2d = ' Your system is up-to-date'
################################################################################
import subprocess
import re
from time import sleep
from glob import glob
from fnmatch import fnmatch
program = []
pkgs = []
url = None
def runpacman():
"""runs pacman returning the popen object"""
p = subprocess.Popen(['pacman','-Qu'],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
return p
def cmpPkgs(x, y):
"""Compares packages for sorting"""
if x['rate']==y['rate']:
return cmp(x['size'], y['size'])
else:
return x['rate']-y['rate']
if onlyImportant:
pkgTemplate, pkgrightcolTemplate = '',''
p = runpacman()
#parse pacmans output
for line in p.stdout:
if re.match('(Cíle|Pakete|Targets|Se procesará|Cibles|Pacchetti|'
'Celuje|Pacotes|Цели):', line):
program = line.split()[1:]
for line in p.stdout:
if not line.strip():
break
program += line.split()
for item in program:
pkg = {}
desc_path = False
desc_paths = glob('/var/lib/pacman/sync/*/%s'%item)
if not desc_path:
desc_path = desc_paths[0] + '/desc'
pkg['repo'] = desc_path.split('/')[-3]
desc = open(desc_path).readlines()
checkName = 0
checkSize = 0
checkVersion = 0
for index, line in enumerate(desc):
if line=='%NAME%\n' and checkName == 0:
pkgName = desc[index+1].strip()
pkg['name'] = pkgName
checkName = 1
if line=='%CSIZE%\n' and checkSize == 0:
pkgSize = int(desc[index+1].strip())
pkg['size'] = pkgSize / 1024.0 / 1024
checkSize = 1
if line=='%VERSION%\n' and checkVersion == 0:
pkgVersion = desc[index+1].strip()
pkg['ver'] = pkgVersion
checkVersion = 1
pkgRate = [v for x, v in ratePkg.iteritems()
if fnmatch(pkg['name'], x)]
repoRate = [v for x, v in rateRepo.iteritems()
if fnmatch(pkg['repo'], x)]
pkg['rate'] = sum(pkgRate + repoRate)
pkgs.append(pkg)
# echo list of pkgs
if pkgs:
summary = {}
summary['numpkg'] = len(pkgs)
summary['size'] = sum([x['size'] for x in pkgs])
if summary['numpkg'] == 1:
summary['pkgstring'] = 'package'
else:
summary['pkgstring'] = 'packages'
summary['inumpkg'] = 0
summary['isize'] = 0
lines = []
pkgs.sort(cmpPkgs, reverse=True)
for pkg in pkgs:
important = False
if pkg['rate'] >= iThresh:
summary['isize'] += pkg['size']
summary['inumpkg'] += 1
pkgString = ipkgTemplate % pkg
sizeValueString = ipkgrightcolTemplate % pkg
else:
pkgString = pkgTemplate % pkg
sizeValueString = pkgrightcolTemplate % pkg
if len(pkgString)+len(sizeValueString)>width-1:
pkgString = pkgString[:width-len(sizeValueString)-4]+'...'
line = pkgString.ljust(width - len(sizeValueString)) + sizeValueString
if line.strip():
lines.append(line)
if not horizontally:
separator = '\n'
if not brief:
if num_of_pkgs:
print separator.join(lines[:num_of_pkgs])
else:
print separator.join(lines)
if block:
print block.rjust(width)
if summary['inumpkg']:
overallString = isummaryTemplate % summary
overallMBString = summaryrightcolTemplate % summary
else:
overallString = summaryTemplate % summary
overallMBString = isummaryrightcolTemplate % summary
summaryline = overallString.ljust(width - len(overallMBString)) \
+ overallMBString
if summaryline and not horizontally:
print summaryline
else:
print u2d
4. make python script executable (chmod +x notify.py)
5. enjoy!
And there is how it looks:
If you have some ideas for improving the program, I will be glad to know it
Is there someone, who knows how to handle with colors in conky with "exec"?
UPDATED
- thanks to sabooky for his idea (package info from disk)
- important package setting and showing with '*!*' prefix
- number of printed packages
- summary line
- horizontal output
Last edited by Majkhii (2008-06-07 21:55:33)
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
maybe add some functionality to colorize important updates.
e.g.: add an array of package-names; if there is an update for one of this packages, display it in red.
i don't "speak" python, but to give a bash-like example how this could be realized and easily adjusted by the user for his needs:
IMPORTANTPKG = "kernel anotherpkg some-other-important-pkg"
IMPORTANTCOL = "FF0000"
said in another way: give the user an easy option to adjust the packages which he wants to be displayed in another color, and give him an easy option to choose the color.
some days ago i found a perl script that just checks if there are updates available (using the updates.log and the cronjob), and just outputs "Arch-pkg: available (5)" to console/conky. in this case, the output tells the user that there are 5 updates available.
don't know if you are the author of this perl script too. but would be nice, if the output would be extended by a "!!!" if there is an important update.
Offline
I saw this perl script and I was only inspired by it. Colored output is nice idea and I'll try to make it.
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
You shouldn't need urllib and ftplib to get the package size, it is stored locally in /var/lib/pacman/$REPO/$PKG/desc under %CSIZE%.
example:
import glob
pkg = "pcre-7.3-2"
desc_path = glob.glob('/var/lib/pacman/*/%s'%pkg)[0]+"/desc"
desc = open(desc_path).readlines()
size = desc[desc.index('%CSIZE%\n')+1]
print size
If you're using urllib2 and ftplib for something else, sorry...kinda late, just skimmed over your program.
PS: Awesome idea for a script.
Last edited by sabooky (2007-09-17 06:43:54)
Offline
Script updated.
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
Small fix for package names that end with -i686 or -x86_64. since the pkg folder doesn't have the -i686/-x86_64 ending, they need to be stripped from the name.
--- notify.py.orig 2007-09-18 00:14:40.000000000 -0400
+++ notify.py 2007-09-18 00:13:34.000000000 -0400
@@ -38,8 +38,11 @@
urlArrayItems = len(urlArray)
programPkg = urlArray[urlArrayItems-1]
- programPkg = rsplit(programPkg, '.', 3)
- program.append(programPkg[0])
+ programPkg = rsplit(programPkg, '.', 3)[0]
+ for x in ("-i686", "-x86_64"):
+ if programPkg.endswith(x):
+ programPkg = programPkg[:-len(x)]
+ program.append(programPkg)
for item in program:
desc_path = glob('/var/lib/pacman/*/%s'%item)[0]+"/desc"
Offline
Updated - thanks
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
Is there someone, who knows how to handle with colors in conky with "exec"?
I tried, and failed :'(
Though I can think of two solutions:
1. Instead of colors use something like "*" to signify important updates. (not really a solution, but might be a good option to have)
2. Have the python script output to two text files (important/normal) and use the "tail" command in conky to tail the file itself. This way you can choose separate colors for each file, and important updates will be grouped up.
Offline
Updated...
I chose first option of hilighting important packages
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
Updated
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
thanks, using the script now. love it so far.
Offline
updated...Thanks sabooky...I learned a lot with your code
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
small mistake I've made..
change
print p.stdout
to
print p.stdout.read()
Offline
This script is very cool and works great. Thanks.
% whereis whatis whence which whoami whois who
Offline
Hmm, this script has stopped working after updating Pacman to 3.1.0. Anyone can fix this?
To console I got:
$ python notify.py
Traceback (most recent call last):
File "notify.py", line 85, in <module>
sleep(45)
KeyboardInterrupt
And Conky says:
error: you cannot perform this operation unless you are root
Last edited by LinuxPatsku (2008-01-13 17:43:11)
ArchLinux with Xfce4.
Offline
I know about this problem, but now I have too much work in school...I will update the script as soon as possible...
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
http://bugs.archlinux.org/task/8905 - that's why.
i patched my version to use sudo in the script itself. this is a VERY BAD thing to do but it works. the only other changes i made were changing the path of the cache from /var/lib/pacman to /var/lib/pacman/sync (i believe these are the paths, im not on my box right now.)
majkhii i can send this to you if youd like.
archlinux - please read this and this — twice — then ask questions.
--
http://rsontech.net | http://github.com/rson
Offline
http://bugs.archlinux.org/task/8905 - that's why.
i patched my version to use sudo in the script itself. this is a VERY BAD thing to do but it works. the only other changes i made were changing the path of the cache from /var/lib/pacman to /var/lib/pacman/sync (i believe these are the paths, im not on my box right now.)
majkhii i can send this to you if youd like.
post it here...:)
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
Again, i do not suggest that this is a good way of solving the problem, but if you've got sudo already set up to run pacman with no password then this modification works. hopefully that bug will be rubbed out not too long from now.
<<link removed>> Use the script below as it is a much better way to do this.
notable changes are on lines 79, 107, and 115. i may have missed a few.
!! NOTE: the config section has been uglified by me. don't use it
Last edited by rson451 (2008-01-14 16:51:21)
archlinux - please read this and this — twice — then ask questions.
--
http://rsontech.net | http://github.com/rson
Offline
Again, i do not suggest that this is a good way of solving the problem, but if you've got sudo already set up to run pacman with no password then this modification works. hopefully that bug will be rubbed out not too long from now.
http://pastebin.archlinux.org/23805
notable changes are on lines 79, 107, and 115. i may have missed a few.
!! NOTE: the config section has been uglified by me. don't use it
I've actually changed the way my local script works, but never posted it (this was a few months back). Basically you don't need sudo (and yes it's a bad way of doing things).
My local version uses 'pacman -Qu' which gives two benifites:
1. can be run as any user
2. It doesn't create/check for a lck file, since it's only doing a read operation. (this is why i made the change)
That being said, new pacman did break the script due to the directory changes. I'll probably fix it up sometime this week (hopefully tonight). Also another change I would like to do is adding functions to the script. Which will make future changes easier to manage.
Last edited by sabooky (2008-01-14 15:09:04)
Offline
Ok, I think the script is working now. Since I used my local copy to fix the script I'll list the changes. These are changes I've made every now and then, I apologize for not posting some of these changes earlier.
Changes:
- 'pacman -Sup' changed to 'pacman -Qu'
- This takes out the need for checking lck files, the whole sleep/try again code is gone now
- Even when pacman -Sup was runnable as user it created a system wide lock on the pacman db, the change to root is a good thing IMO.
- changed '/var/lib/pacman/' to '/var/lib/pacman/sync' (also means this will no longer work with the older pacman, will implement backwards compatibility if requested)
- Added show "onlyImportant" option (Never actually used this, might be buggy)
- ipkgTemplate no longer dependent on pkgTemplate.
- packages with equal 'rating' are sorted based on 'size'
- if package name is wider then width, it is cropped and followed with a '...'
Customization differences:
- Width = 52 (instead of 47)
To do:
- I'd like to break the script down into functions to make maintainability easier.
- If anyone has any feature requests post it here or email me.
EDIT:
- changed "Targets:" to do a regex search for all the languages.
- except for hu.po, can't figure out how to extract that, if anyone knows please tell me. I get "Clok:"
conkypac.py:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Description: Python script for notifying archlinux updates.
# Usage: Put shell script with command 'pacman -Sy' into /etc/cron.hourly/
# Conky: e.g. put in conky '${texeci 1800 python path/to/this/file}'
# Author: Michal Orlik <thror.fw@gmail.com>, sabooky <sabooky@yahoo.com>
################################################################################
# SETTINGS - main settings
# set this to True if you just want one summary line (True/False)
brief = False
# number of packages to display (0 = display all)
num_of_pkgs = 5
#show only important packages
onlyImportant = False
########################################
# OPTIONAL SETTINGS
# PACKAGE RATING - prioritize packages by rating
# pkgs will be sorted by rating. pkg rating = ratePkg + rateRepo for that pkg
# pkg (default=0, wildcards accepted)
ratePkg = {
'kernel*':10,
'pacman':9,
'nvidia*':8,
}
# repo (default=0, wildcards accepted)
rateRepo = {
'core':5,
'extra':4,
'community':3,
'testing':2,
'unstable':1,
}
# at what point is a pkg considered "important"
iThresh = 5
########################################
# OUTPUT SETINGS - configure the output format
# change width of output
width = 52
# pkg template - this is how individual pkg info is displayed ('' = disabled)
# valid keywords - %(name)s, %(repo)s, %(size).2f, %(ver)s, %(rate)s
pkgTemplate = " %(repo)s/%(name)s %(ver)s"
# important pkg tempalte - same as above but for "important" pkgs
ipkgTemplate = " *!* %(repo)s/%(name)s %(ver)s"
# summary template - this is the summary line at the end
# valid keywords - %(numpkg)d, %(size).2f, %(inumpkg), %(isize).2f, %(pkgstring)s
summaryTemplate = " %(numpkg)d %(pkgstring)s"
# important summary template - same as above if "important" pkgs are found
isummaryTemplate = summaryTemplate + " (%(inumpkg)d important %(isize).2f MB)"
# pkg right column template - individual pkg right column
# valid keywords - same as pkgTemplate
pkgrightcolTemplate = "%(size).2f MB"
# important pkg right column template - same as above but for important pkgs
ipkgrightcolTemplate = pkgrightcolTemplate
# summary right column template - summay line right column
# valid keywords - same as summaryTemplate
summaryrightcolTemplate = "%(size).2f MB"
# important summary right column template - same as above if "important" pkgs are found
isummaryrightcolTemplate = summaryrightcolTemplate
# seperator before summary ('' = disabled)
block = '-' * 12
# up to date msg
u2d = ' Your system is up-to-date'
################################################################################
import subprocess
import re
from time import sleep
from glob import glob
from fnmatch import fnmatch
program = []
pkgs = []
url = None
def runpacman():
"""runs pacman returning the popen object"""
p = subprocess.Popen(['pacman','-Qu'],
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
return p
def cmpPkgs(x, y):
"""Compares packages for sorting"""
if x['rate']==y['rate']:
return cmp(x['size'], y['size'])
else:
return x['rate']-y['rate']
if onlyImportant:
pkgTemplate, pkgrightcolTemplate = '',''
p = runpacman()
#parse pacmans output
for line in p.stdout:
if re.match('(Cíle|Pakete|Targets|Se procesará|Cibles|Pacchetti|'
'Celuje|Pacotes|Цели):', line):
program = line.split()[1:]
for line in p.stdout:
if not line.strip():
break
program += line.split()
for item in program:
pkg = {}
desc_path = False
desc_paths = glob('/var/lib/pacman/sync/*/%s'%item)
if not desc_path:
desc_path = desc_paths[0] + '/desc'
pkg['repo'] = desc_path.split('/')[-3]
desc = open(desc_path).readlines()
checkName = 0
checkSize = 0
checkVersion = 0
for index, line in enumerate(desc):
if line=='%NAME%\n' and checkName == 0:
pkgName = desc[index+1].strip()
pkg['name'] = pkgName
checkName = 1
if line=='%CSIZE%\n' and checkSize == 0:
pkgSize = int(desc[index+1].strip())
pkg['size'] = pkgSize / 1024.0 / 1024
checkSize = 1
if line=='%VERSION%\n' and checkVersion == 0:
pkgVersion = desc[index+1].strip()
pkg['ver'] = pkgVersion
checkVersion = 1
pkgRate = [v for x, v in ratePkg.iteritems()
if fnmatch(pkg['name'], x)]
repoRate = [v for x, v in rateRepo.iteritems()
if fnmatch(pkg['repo'], x)]
pkg['rate'] = sum(pkgRate + repoRate)
pkgs.append(pkg)
# echo list of pkgs
if pkgs:
summary = {}
summary['numpkg'] = len(pkgs)
summary['size'] = sum([x['size'] for x in pkgs])
if summary['numpkg'] == 1:
summary['pkgstring'] = 'package'
else:
summary['pkgstring'] = 'packages'
summary['inumpkg'] = 0
summary['isize'] = 0
lines = []
pkgs.sort(cmpPkgs, reverse=True)
for pkg in pkgs:
important = False
if pkg['rate'] >= iThresh:
summary['isize'] += pkg['size']
summary['inumpkg'] += 1
pkgString = ipkgTemplate % pkg
sizeValueString = ipkgrightcolTemplate % pkg
else:
pkgString = pkgTemplate % pkg
sizeValueString = pkgrightcolTemplate % pkg
if len(pkgString)+len(sizeValueString)>width-1:
pkgString = pkgString[:width-len(sizeValueString)-4]+'...'
line = pkgString.ljust(width - len(sizeValueString)) + sizeValueString
if line.strip():
lines.append(line)
if not brief:
if num_of_pkgs:
print '\n'.join(lines[:num_of_pkgs])
else:
print '\n'.join(lines)
if block:
print block.rjust(width)
if summary['inumpkg']:
overallString = isummaryTemplate % summary
overallMBString = summaryrightcolTemplate % summary
else:
overallString = summaryTemplate % summary
overallMBString = isummaryrightcolTemplate % summary
summaryline = overallString.ljust(width - len(overallMBString)) \
+ overallMBString
if summaryline:
print summaryline
else:
print u2d
Last edited by sabooky (2008-01-16 16:41:25)
Offline
nice sabooky, i'll test yours out as soon as i can get on my laptop today. i've removed the link to my pastebin so hopefully people will use your script instead as it is much more safe.
archlinux - please read this and this — twice — then ask questions.
--
http://rsontech.net | http://github.com/rson
Offline
Mmm...i tried the script and didn't work for me...always is system up2date...
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
So, i find the little bug in script...this script is only for english pacman and i have czech.
I must change the line:
if line.startswith('Targets:'):
to:
if line.startswith('Cíle:'):
so i think it would be better to do this by regular expressions?
Last edited by Majkhii (2008-01-15 21:37:44)
Proud to be ArchLinux64 user.
configs: http://github.com/Mihairu/config-files/tree/master
current desktop: here
Offline
So, i find the little bug in script...this script is only for english pacman and i have czech.
I must change the line:if line.startswith('Targets:'):
to:
if line.startswith('Cíle:'):
so i think it would be better to do this by regular expressions?
Thanks, fixed using regex on the words I found in the *.po files in the pacman source.
Not sure how to parse hu.po though, I get "Clok:", that's the only language that I didn't know how to do, maybe someone here will know.
I edited my code above, instead of posting it all over again so I don't clutter the thread.
Last edited by sabooky (2008-01-16 16:47:35)
Offline