[Merge] ~rs2009/unity:master into unity:master
Dmitry Shachnev
mp+437213 at code.launchpad.net
Sat Feb 18 14:07:06 UTC 2023
Review: Needs Fixing
Diff comments:
> diff --git a/CMakeLists.txt b/CMakeLists.txt
> index 1d58a46..03be190 100644
> --- a/CMakeLists.txt
> +++ b/CMakeLists.txt
> @@ -29,7 +29,7 @@ option(
> option(
> ENABLE_UNIT_TESTS
> "Enable Unity Unit Tests"
> - ON
> + OFF
Disabling auto-tests is usually a bad idea.
Ideally, fix them. Or disable just the failing test(s), with a comment why they can't be fixed.
> )
>
> # This is due to bug lp:668799 - qemu-arm segfaults executing msgmerge
> diff --git a/debian/control b/debian/control
> index c61edb5..b24c845 100644
> --- a/debian/control
> +++ b/debian/control
> @@ -59,6 +59,12 @@ Build-Depends: cmake (>= 3.17.0),
> xserver-xorg-video-dummy,
> xsltproc,
> yaru-theme-icon,
> + xorg,
> + libxinerama-dev,
> + libcairo2-dev,
> + python3-gi,
> + gir1.2-gtk-3.0,
> + gir1.2-glib-2.0
Please keep the list of build-deps sorted.
> Standards-Version: 3.9.5
> Homepage: https://launchpad.net/unity
> # If you aren't a member of ~unity-team but need to upload packaging changes,
> diff --git a/debian/rules b/debian/rules
> index 4b29c43..24136bb 100755
> --- a/debian/rules
> +++ b/debian/rules
> @@ -42,7 +42,13 @@ override_dh_install:
> cd $(CURDIR)
> find debian/tmp/usr/lib -name \*.*a -exec rm {} \;
> rm -rf debian/tmp/usr/share/gconf/schemas
> - dh_install --fail-missing
> + # install uwidgets
> + cd uwidgets; \
> + set -ex; for python in $(shell py3versions -r); do \
Installing just for the default Python version (python3) is enough, unless it's a public Python module.
> + $$python setup.py install --root=$(CURDIR)/debian/tmp --install-layout=deb; \
> + done;
> + install -Dm755 $(CURDIR)/debian/tmp/usr/etc/xdg/autostart/uwidgets-runner.desktop $(CURDIR)/debian/tmp/etc/xdg/autostart/uwidgets-runner.desktop
> + cd $(CURDIR); dh_install --fail-missing
>
> override_dh_gencontrol:
> dh_gencontrol -- -Vcoreabiversion=$(CORE_ABIVERSION) -Vnuxabiversion=$(NUX_ABIVERSION) -Vunity-default-masterscopes="$(SCOPES_RECOMMENDS)"
> @@ -51,7 +57,7 @@ override_dh_makeshlibs:
> dh_makeshlibs -plibunity-core-6.0-9 -V 'libunity-core-6.0-9 (>= 7.0.0)'
>
> override_dh_shlibdeps:
> - dh_shlibdeps -l$(LIBUNITY_PRIVATE) -O--parallel
> + echo hello
What? Please revert this.
>
> override_dh_auto_test:
> ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS)))
> diff --git a/uwidgets/official-widgets/clock/clock.py b/uwidgets/official-widgets/clock/clock.py
> new file mode 100755
> index 0000000..09041af
> --- /dev/null
> +++ b/uwidgets/official-widgets/clock/clock.py
> @@ -0,0 +1,104 @@
> +#!/usr/bin/env python3
> +
> +"""
> +This file is part of "blighty" and "uwidgets" which is released under GPL.
> +
> +See file LICENCE or go to http://www.gnu.org/licenses/ for full license
You meant LICENSE.md, not LICENCE? (here and in other files)
> +details.
> +
> +uwidgets is a desktop widget creation and management library for Python 3.
> +
> +Copyright (c) 2022 Rudra Saraswat <rs2009 at ubuntu.com>.
> +Copyright (c) 2018 Gabriele N. Tornetta <phoenix1987 at gmail.com>.
> +All rights reserved.
> +
> +This program is free software: you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation, either version 3 of the License, or
> +(at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +GNU General Public License for more details.
> +You should have received a copy of the GNU General Public License
> +along with this program. If not, see <http://www.gnu.org/licenses/>.
> +"""
> +
> +from uwidgets import CanvasGravity, brush
> +from uwidgets.x11 import Canvas, start_event_loop
> +
> +import datetime
> +import subprocess
> +import configparser
> +
> +from math import pi as PI
> +
> +
> +class Clock(Canvas):
> + def on_button_pressed(self, button, state, x, y):
> + if button == 3: # Right button
> + subprocess.run(['unity-control-center', 'datetime'])
> +
> + def draw_circle_background(ctx):
> + ctx.arc(2, 1, 90, 0, 2*PI)
> + ctx.set_source_rgba(0, 0, 0, 0.6)
> + ctx.fill()
> +
> + def draw_rect_background(ctx):
> + ctx.rectangle(-180, -180, 360, 360)
> + ctx.set_source_rgba(0, 0, 0, 0.6)
> + ctx.fill()
> +
> + ctx.rectangle(-180, -100, 360, 3)
> + ctx.set_source_rgba(1, 1, 1, 1)
> + ctx.fill()
> +
> + @brush
> + def hand(ctx, angle, length, thickness):
> + ctx.save()
> + ctx.set_source_rgba(1, 1, 1, 1)
> + ctx.set_line_width(thickness)
> + ctx.rotate(angle)
> + ctx.move_to(0, length * .2)
> + ctx.line_to(0, -length)
> + ctx.stroke()
> + ctx.restore()
> +
> + def on_draw(self, ctx):
> + now = datetime.datetime.now()
> +
> + ctx.translate(self.width >> 1, self.height >> 1)
> +
> + eval(f"ctx.draw_{config.get('settings', 'clock_style')}_background()")
eval is not necessary here, getattr should be enough:
getattr(ctx, f"draw_{config.get('settings', 'clock_style')}_background")()
> +
> + ctx.hand(
> + angle = now.second / 30 * PI,
> + length = ((self.height >> 1) * .9) - 20,
> + thickness = 1
> + )
> +
> + mins = now.minute + now.second / 60
> + ctx.hand(
> + angle = mins / 30 * PI,
> + length = ((self.height >> 1) * .8) - 20,
> + thickness = 3
> + )
> +
> + hours = (now.hour % 12) + mins / 60
> + ctx.hand(
> + angle = hours / 6 * PI,
> + length = ((self.height >> 1) * .5) - 20,
> + thickness = 4.5
> + )
> +
> +if __name__ == "__main__":
> + config = configparser.ConfigParser()
> + config.read('settings.ini')
> + clock = Clock(eval(config.get('settings', 'margin_x')),
> + eval(config.get('settings', 'margin_y')),
Is this need just to cast text to int, or you want to allow arithmetical expressions in config files?
I would avoid it, as it puts a security hole — an attacker with access to your config file can execute random code.
> + 200,
> + 200,
> + gravity = eval('CanvasGravity.' + config.get('settings', 'gravity')))
Here getattr should work too.
> + clock.show()
> + start_event_loop()
> diff --git a/uwidgets/official-widgets/cpu/cpu.py b/uwidgets/official-widgets/cpu/cpu.py
> new file mode 100755
> index 0000000..fa4d5cf
> --- /dev/null
> +++ b/uwidgets/official-widgets/cpu/cpu.py
> @@ -0,0 +1,169 @@
> +#!/usr/bin/env python3
> +
> +from math import pi as PI
> +
> +import configparser
> +import psutil
> +import cairo
> +import os
> +from uwidgets import CanvasGravity, TextAlign
> +from uwidgets.legacy import Graph
> +from uwidgets.x11 import Canvas, start_event_loop
> +
> +
> +class AttrDict(dict):
> + def __init__(self, *args, **kwargs):
> + super(AttrDict, self).__init__(*args, **kwargs)
> + self.__dict__ = self
> +
> +class Fonts(type):
There is no point in inheriting from type (here and in other files).
Just "class Fonts:".
> + UBUNTU_NORMAL = "Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL
> +
> +
> +class Cpu(Canvas):
> + SIZE = (256, 256)
> + CORE_POLYGON = AttrDict({"height": 30, "length": 20})
> +
> + def __init__(self, *args, **kwargs):
> + super().__init__(*args, **kwargs)
> +
> + with open('/proc/cpuinfo', 'r') as fin:
> + raw_cpuinfo = fin.read().strip()
> +
> + self.coreinfo = [
> + {
> + k.strip(): v
> + for k, v in [p.split(":") for p in core.split('\n')]
> + }
> + for core in raw_cpuinfo.split('\n\n')
> + ]
> +
> + self.graph = Graph(0, 110, self.width, 40)
> +
> + @staticmethod
> + def build(x = 0, y = 0, gravity = CanvasGravity.CENTER):
> + return Cpu(x, y, *Cpu.SIZE, gravity = gravity, interval = 2000)
> +
> + def on_button_pressed(self, button, *args):
> + os.system('stacer')
> +
> + def draw_polygon(c, n, x, y, size):
> + a = 2 * PI / n
> +
> + c.save()
> +
> + c.translate(x, y)
> + c.move_to(size, 0)
> + for i in range(n):
> + c.rotate(a)
> + c.line_to(size, 0)
> + c.stroke()
> +
> + c.restore()
> +
> + def draw_core_polygon(c, x, y):
> + size = Cpu.CORE_POLYGON.height
> + length = Cpu.CORE_POLYGON.length
> +
> + c.save()
> +
> + c.translate(x, y)
> +
> + c.set_source_rgb(.8, .8, .8)
> +
> + cpus = psutil.cpu_percent(0.1, percpu = True)
> + n = len(cpus)
> + a = 2 * PI / n
> +
> + c.set_line_width(1)
> + c.draw_polygon(n, 0, 0, size)
> +
> + c.set_line_width(2)
> + c.set_source_rgb(1, 1, 1)
> + c.move_to(size + length * cpus[-1] / 100, 0)
> + for i in range(n):
> + c.rotate(a)
> + c.line_to(size + length * cpus[i] / 100, 0)
> + c.stroke()
> +
> + value = int(sum(cpus) / n)
> + c.canvas.graph.push_value(value)
> +
> + c.set_font_size(18)
> + c.write_text(0, 0, '{}%'.format(value), TextAlign.CENTER_MIDDLE)
> +
> + c.restore()
> +
> + return value
> +
> + def draw_processes(c):
> + ps = [
> + p.info
> + for p in psutil.process_iter(attrs=['pid', 'name', 'cpu_percent'])
> + ]
> +
> + ps = sorted(ps, key=lambda p: p["cpu_percent"], reverse=True)[:5]
> +
> + y = 170
> + c.save()
> + c.select_font_face(*Fonts.UBUNTU_NORMAL)
> + c.set_font_size(12)
> + for p in ps:
> + c.write_text(48, y, str(p["pid"]), align = TextAlign.TOP_RIGHT)
> + c.write_text(52, y, p["name"][:24])
> + c.write_text(
> + c.canvas.width - 15, y, "{}%".format(p["cpu_percent"]),
> + align=TextAlign.TOP_RIGHT
> + )
> + y += 18
> +
> + c.restore()
> +
> + def draw_cpu_name(c):
> + c.save()
> + c.set_font_size(12)
> + c.write_text(
> + 15, 110,
> + c.canvas.coreinfo[0]["model name"].strip()
> + .replace("(TM)", "™")
> + .replace("(R)", "©")
> + )
> + c.restore()
> +
> + def draw_background(c):
> + size = c.canvas.get_size()
> + c.rectangle(0, 0, *size)
> + c.set_source_rgba(0, 0, 0, 0.6)
> + c.fill()
> +
> + c.rectangle(0, 0, c.canvas.width, 3)
> + c.set_source_rgba(1, 1, 1, 1)
> + c.fill()
> +
> + def on_draw(self, c):
> + c.draw_background()
> +
> + c.select_font_face(*Fonts.UBUNTU_NORMAL)
> + c.set_font_size(36)
> + c.set_source_rgb(1, 1, 1)
> +
> + w, h = Cpu.SIZE
> +
> + y_poly = (Cpu.CORE_POLYGON.height + Cpu.CORE_POLYGON.length)
> +
> + c.write_text(15, y_poly, "CPU", align = TextAlign.TOP_LEFT)
> + c.draw_core_polygon(w - y_poly, y_poly)
> + c.draw_processes()
> + c.draw_cpu_name()
> +
> + c.set_source_rgb(1, 1, 1)
> + self.graph.draw(c)
> +
> +
> +if __name__ == "__main__":
> + config = configparser.ConfigParser()
> + config.read('settings.ini')
> + Cpu.build(eval(config.get('settings', 'margin_x')),
> + eval(config.get('settings', 'margin_y')),
Same concerns about getattr.
> + gravity = eval('CanvasGravity.' + config.get('settings', 'gravity'))).show()
> + start_event_loop()
> diff --git a/uwidgets/official-widgets/spotify/spotify.py b/uwidgets/official-widgets/spotify/spotify.py
> new file mode 100755
> index 0000000..a6ab7ca
> --- /dev/null
> +++ b/uwidgets/official-widgets/spotify/spotify.py
> @@ -0,0 +1,176 @@
> +#!/usr/bin/env python3
> +
> +"""
> +This file is part of "blighty" and "uwidgets" which is released under GPL.
> +
> +See file LICENCE or go to http://www.gnu.org/licenses/ for full license
> +details.
> +
> +uwidgets is a desktop widget creation and management library for Python 3.
> +
> +Copyright (c) 2022 Rudra Saraswat <rs2009 at ubuntu.com>.
> +Copyright (c) 2018 Gabriele N. Tornetta <phoenix1987 at gmail.com>.
> +All rights reserved.
> +
> +This program is free software: you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation, either version 3 of the License, or
> +(at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +GNU General Public License for more details.
> +You should have received a copy of the GNU General Public License
> +along with this program. If not, see <http://www.gnu.org/licenses/>.
> +"""
> +
> +from uwidgets import CanvasGravity
> +from uwidgets.x11 import Canvas, start_event_loop
> +from uwidgets import CanvasType
> +
> +import cairo
> +import shutil
> +import requests
> +import subprocess
> +import configparser
> +
> +from gi.repository import GLib
> +
> +from PIL import Image
> +from pydbus import SessionBus
> +
> +
> +class Fonts(type):
> + UBUNTU_NORMAL = "Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL
> +
> +
> +class SpotifyDBus:
> + def __init__(self):
> + self.proxy = SessionBus().get(
> + 'org.mpris.MediaPlayer2.spotify',
> + '/org/mpris/MediaPlayer2'
> + )
> +
> + def get_metadata(self):
> + return {k.split(':')[1]: v for k, v in self.proxy.Metadata.items()}
> +
> + def toggle_play(self):
> + self.proxy.PlayPause()
> +
> + def is_paused(self):
> + return self.proxy.PlaybackStatus == "Paused"
> +
> +
> +class Spotify(Canvas):
> + def __init__(self, *args, **kwargs):
> + super().__init__(*args, **kwargs)
> +
> + self.init_dbus()
> +
> + def init_dbus(self):
> + try:
> + self.spotify = SpotifyDBus()
> + except GLib.Error:
> + self.spotify = None
> +
> + self.last_art_url = ""
> +
> + def on_button_pressed(self, button, state, x, y):
> + if button == 1: # Left button
> + self.spotify.toggle_play()
> + elif button == 3: # Right button
> + subprocess.run(['spotify'])
> +
> + def draw_background(ctx):
> + size = ctx.canvas.get_size()
> + ctx.rectangle(0, 0, *size)
> + ctx.set_source_rgba(0, 0, 0, 0.6)
> + ctx.fill()
> +
> + def draw_decoration(ctx):
> + ctx.rectangle(0, 0, ctx.canvas.width, 3)
> + ctx.set_source_rgba(1, 1, 1, 1)
> + ctx.fill()
> +
> + def draw_art(ctx, url, pause):
> + temp_file = "/tmp/spotify_art"
> + temp_img = temp_file + ".png"
> +
> + if ctx.canvas.last_art_url != url:
> + response = requests.get(url, stream=True)
> + with open(temp_file, 'wb') as out_file:
> + shutil.copyfileobj(response.raw, out_file)
> + del response
> + ctx.canvas.last_art_url = url
> +
> + # Ensure it is a PNG image
> + size = min(ctx.canvas.width, ctx.canvas.height)
> + image = Image.open(temp_file)
> + image.thumbnail((size, size), Image.ANTIALIAS)
> + image.save(temp_img)
> +
> + surface = cairo.ImageSurface.create_from_png(temp_img)
> + ctx.set_source_surface(surface, 0, 0)
> + ctx.paint()
> +
> + if pause:
> + ctx.set_source_rgba(0, 0, 0, 0.75)
> + ctx.rectangle(0, 0, size, size)
> + ctx.fill()
> + ctx.set_source_rgba(.8, 0.8, 0.8, 0.5)
> + size2 = size >> 1
> + size4 = size2 >> 1
> + size5 = size // 5
> + ctx.rectangle(size4, size4, size5, size2)
> + ctx.rectangle(size - size4 - size5, size4, size5, size2)
> + ctx.fill()
> +
> + def draw_metadata(ctx, metadata):
> + ctx.set_source_rgb(0.9, 0.9, 0.9)
> +
> + ctx.select_font_face(*Fonts.UBUNTU_NORMAL)
> + ctx.set_font_size(24)
> + ctx.move_to(112, 42)
> + ctx.show_text(metadata["title"])
> +
> + ctx.set_source_rgb(0.5, 0.5, 0.5)
> + ctx.set_font_size(15)
> + ctx.move_to(112, 72)
> + ctx.show_text("{artists} ({album})".format(
> + artists = ", ".join(metadata["artist"]),
> + album = metadata["album"]
> + ))
> +
> + def on_draw(self, ctx):
> + if self.spotify is None:
> + self.init_dbus()
> + return
> +
> + try:
> + metadata = self.spotify.get_metadata()
> + except GLib.Error:
> + self.spotify = None
> + return
> +
> + _ctx = ctx
> + ctx.draw_background()
> + ctx.draw_art(metadata["artUrl"], self.spotify.is_paused())
> + ctx.draw_metadata(metadata)
> + ctx.draw_decoration()
> +
> +
> +if __name__ == "__main__":
> + config = configparser.ConfigParser()
> + config.read('settings.ini')
> + spotify = Spotify(
> + x = eval(config.get('settings', 'margin_x')),
> + y = eval(config.get('settings', 'margin_y')),
Same concerns about eval.
> + width = 540,
> + height = 96,
> + gravity = eval('CanvasGravity.' + config.get('settings', 'gravity')),
> + interval = 1000
> + )
> +
> + spotify.show()
> + start_event_loop()
> diff --git a/uwidgets/official-widgets/unsplash-background/unsplash-background.py b/uwidgets/official-widgets/unsplash-background/unsplash-background.py
> new file mode 100755
> index 0000000..5fc2b52
> --- /dev/null
> +++ b/uwidgets/official-widgets/unsplash-background/unsplash-background.py
> @@ -0,0 +1,96 @@
> +#!/usr/bin/env python3
> +
> +"""
> +This file is part of "blighty" and "uwidgets" which is released under GPL.
> +
> +See file LICENCE or go to http://www.gnu.org/licenses/ for full license
> +details.
> +
> +uwidgets is a desktop widget creation and management library for Python 3.
> +
> +Copyright (c) 2022 Rudra Saraswat <rs2009 at ubuntu.com>.
> +Copyright (c) 2018 Gabriele N. Tornetta <phoenix1987 at gmail.com>.
> +All rights reserved.
> +
> +This program is free software: you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation, either version 3 of the License, or
> +(at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +GNU General Public License for more details.
> +You should have received a copy of the GNU General Public License
> +along with this program. If not, see <http://www.gnu.org/licenses/>.
> +"""
> +
> +from uwidgets import CanvasGravity
> +from uwidgets.x11 import Canvas, start_event_loop
> +from uwidgets.settings import UnityWallpaper
> +
> +import cairo
> +import subprocess
> +import configparser
> +
> +from gi.repository import GLib
> +
> +
> +class Fonts(type):
> + UBUNTU_NORMAL = "Ubuntu", cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL
> +
> +
> +class UnBackground(Canvas):
> + def on_button_pressed(self, button, state, x, y):
> + if button == 1: # Left button
> + self.change_wallpaper()
> + elif button == 3: # Right button
> + subprocess.run(['unity-control-center', 'appearance'])
> +
> + def change_wallpaper(ctx):
> + UnityWallpaper().set_wallpaper_from_url("https://source.unsplash.com/random/3840x2160")
> +
> + def draw_background(ctx):
> + size = ctx.canvas.get_size()
> + ctx.rectangle(0, 0, *size)
> + ctx.set_source_rgba(0, 0, 0, 0.6)
> + ctx.fill()
> +
> + def draw_decoration(ctx):
> + ctx.rectangle(0, 0, ctx.canvas.width, 3)
> + ctx.set_source_rgba(1, 1, 1, 1)
> + ctx.fill()
> +
> + def draw_info(ctx):
> + ctx.set_source_rgb(0.9, 0.9, 0.9)
> +
> + ctx.select_font_face(*Fonts.UBUNTU_NORMAL)
> + ctx.set_font_size(24)
> + ctx.move_to(20, 42)
> + ctx.show_text('Unsplash | Random Background')
> +
> + ctx.set_source_rgb(0.5, 0.5, 0.5)
> + ctx.set_font_size(15)
> + ctx.move_to(20, 64)
> + ctx.show_text('Click this to set a random Unsplash background (requires internet).')
> +
> + def on_draw(self, ctx):
> + ctx.draw_background()
> + ctx.draw_decoration()
> + ctx.draw_info()
> +
> +
> +if __name__ == "__main__":
> + config = configparser.ConfigParser()
> + config.read('settings.ini')
> + unbg = UnBackground(
> + x = eval(config.get('settings', 'margin_x')),
> + y = eval(config.get('settings', 'margin_y')),
Same concerns about eval.
> + width = 540,
> + height = 80,
> + gravity = eval('CanvasGravity.' + config.get('settings', 'gravity')),
> + interval = 1000
> + )
> +
> + unbg.show()
> + start_event_loop()
> diff --git a/uwidgets/setup.py b/uwidgets/setup.py
> new file mode 100755
> index 0000000..34ca713
> --- /dev/null
> +++ b/uwidgets/setup.py
> @@ -0,0 +1,69 @@
> +#!/usr/bin/env python3
> +
> +"""
> +This file is part of "uwidgets" which is released under GPL.
> +
> +See file LICENCE or go to http://www.gnu.org/licenses/ for full license
> +details.
> +
> +uwidgets is a desktop widget creation and management library for Python 3.
> +
> +Copyright (c) 2022 Rudra Saraswat <rs2009 at ubuntu.com>.
> +Copyright (c) 2018 Gabriele N. Tornetta <phoenix1987 at gmail.com>.
> +
> +This program is free software: you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation, either version 3 of the License, or
> +(at your option) any later version.
> +
> +This program is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +GNU General Public License for more details.
> +You should have received a copy of the GNU General Public License
> +along with this program. If not, see <http://www.gnu.org/licenses/>.
> +"""
> +
> +from setuptools import Extension, find_packages, setup
> +
> +x11 = Extension('uwidgets._x11',
> + include_dirs = ['/usr/include/cairo/'],
> + libraries = ['cairo', 'X11', 'Xinerama'],
> + extra_compile_args = ['-std=c99'],
> + sources = [
> + 'uwidgets/x11/_x11module.c',
> + 'uwidgets/x11/atelier.c',
> + 'uwidgets/x11/base_canvas.c',
> + ]
> +)
> +
> +
> +setup(
> + name = 'uwidgets',
> + version = '1.0.0',
> + description = 'Desktop Widget Manager for Unity, based on Blighty.',
> + author = 'Rudra Saraswat',
> + author_email = 'rs2009 at ubuntu.com',
> + url = 'https://unityd.org',
> + classifiers=[
> + 'Development Status :: 1 - Production/Stable',
Production/Stable is 5, not 1.
> +
> + 'Intended Audience :: Developers',
> + 'Topic :: Software Development :: Build Tools',
> +
> + 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
> +
> + 'Programming Language :: Python :: 3',
> + 'Programming Language :: Python :: 3.4',
> + 'Programming Language :: Python :: 3.5',
> + 'Programming Language :: Python :: 3.6',
These versions look to old, Ubuntu Lunar will have 3.11 (only).
> + ],
> + keywords = 'desklet widget infotainment',
> + packages = find_packages(exclude=['contrib', 'docs']),
> + ext_modules = [x11],
> + install_requires = ['pycairo'],
> + scripts = ['uwidgets-runner'],
> + extras_require = {
> + 'test': ['pytest-xvfb', 'numpy', 'matplotlib', 'psutil'],
Why do you need numpy and matplotlib here?
> + },
> +)
> diff --git a/uwidgets/uwidgets-runner b/uwidgets/uwidgets-runner
> new file mode 100755
> index 0000000..3c5092f
> --- /dev/null
> +++ b/uwidgets/uwidgets-runner
> @@ -0,0 +1,19 @@
> +#!/usr/bin/env python3
> +
> +import os
> +import configparser
> +
> +widgets=[]
> +widgets_dir=os.path.expanduser('~/.local/share/unity/widgets')
> +
> +if os.path.exists(widgets_dir):
> + for widget in [f.path for f in os.scandir(widgets_dir) if f.is_dir() and os.path.exists(os.path.join(f, 'widget.ini'))]:
> + try:
> + os.chdir(widget)
> + config = configparser.ConfigParser()
> + config.read(os.path.join(widget, 'widget.ini'))
> + if config.get('widget', 'enabled') == 'true':
> + os.popen(config.get('widget', 'exec'))
> + except:
Bare except: is discouraged practice. Catch the exceptions you want to catch explicitly.
> + print(f'uwidget-runner: error occurred when attempting to run {widget}')
> +
> diff --git a/uwidgets/uwidgets/__init__.py b/uwidgets/uwidgets/__init__.py
> new file mode 100644
> index 0000000..a310622
> --- /dev/null
> +++ b/uwidgets/uwidgets/__init__.py
> @@ -0,0 +1,77 @@
> +# This file is part of "blighty" and "uwidgets" which is released under GPL.
> +#
> +# See file LICENCE or go to http://www.gnu.org/licenses/ for full license
> +# details.
> +#
> +# uwidgets is a desktop widget creation and management library for Python 3.
> +#
> +# Copyright (c) 2018 Gabriele N. Tornetta <phoenix1987 at gmail.com>.
> +# All rights reserved.
> +#
> +# This program is free software: you can redistribute it and/or modify
> +# it under the terms of the GNU General Public License as published by
> +# the Free Software Foundation, either version 3 of the License, or
> +# (at your option) any later version.
> +#
> +# This program is distributed in the hope that it will be useful,
> +# but WITHOUT ANY WARRANTY; without even the implied warranty of
> +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> +# GNU General Public License for more details.
> +# You should have received a copy of the GNU General Public License
> +# along with this program. If not, see <http://www.gnu.org/licenses/>.
> +
> +"""
> +This module contains the common objects and types for the different kind of
> +canvases provided by ``uwidgets``.
> +"""
> +
> +# XWayland fix
> +import os
> +os.environ["GDK_BACKEND"] = "x11"
> +
> +from . _extended_context import ExtendedContext
> +
> +from . _brush import brush, TextAlign
> +
> +
> +class CanvasType(type):
The same type is declared in canvastype.py, why do we need to duplicate it in two places?
> + """The Canvas type.
> +
> + The canvas types enumerated in this Python type reflect the same window
> + types that one can request to the window manager via the `Extended
> + Window Manager Hints <https://standards.freedesktop.org/wm-spec/wm-spec-1.3.html>`_.
> +
> + - ``NORMAL`` is a normal top-level window.
> + - ``DESKTOP`` is a window drawn directly on the desktop.
> + - ``DOCK`` indicates a dock or panel window that will usually stay on top
> + of other windows.
> + - ``UNDECORATED`` is a type of window that behaves as a toolbar. As such,
> + it is undecorated.
> + """
> +
> + NORMAL = 0 # _NET_WM_WINDOW_TYPE_NORMAL
> + DESKTOP = 1 # _NET_WM_WINDOW_TYPE_DESKTOP
> + DOCK = 2 # _NET_WM_WINDOW_TYPE_DOCK
> + UNDECORATED = 3 # _NET_WM_WINDOW_TYPE_TOOLBAR
> +
> +
> +class CanvasGravity(type):
> + """Window gravity control type.
> +
> + The positioning of a canvas on the screen is controlled by its gravity.
> + By default, a window is positioned in a coordinate system where the origin
> + is located in the top-left corner of the screen, with the *x* axis running
> + horizontally from left to right, and the *y* from top to bottom. To change
> + the location of the origin, use one of the following values.
> + """
> +
> + NORTH_WEST = 1
> + NORTH = 2
> + NORTH_EAST = 3
> + WEST = 4
> + CENTER = 5
> + EAST = 6
> + SOUTH_WEST = 7
> + SOUTH = 8
> + SOUTH_EAST = 9
> + STATIC = 10
> diff --git a/uwidgets/uwidgets/canvastype.py b/uwidgets/uwidgets/canvastype.py
> new file mode 100644
> index 0000000..c5cd030
> --- /dev/null
> +++ b/uwidgets/uwidgets/canvastype.py
> @@ -0,0 +1,19 @@
> +class CanvasType(type):
Again no need to inherit from type, but you may want to inherit from enum.Enum:
https://docs.python.org/3/library/enum.html
> + """The Canvas type.
> +
> + The canvas types enumerated in this Python type reflect the same window
> + types that one can request to the window manager via the `Extended
> + Window Manager Hints <https://standards.freedesktop.org/wm-spec/wm-spec-1.3.html>`_.
> +
> + - ``NORMAL`` is a normal top-level window.
> + - ``DESKTOP`` is a window drawn directly on the desktop.
> + - ``DOCK`` indicates a dock or panel window that will usually stay on top
> + of other windows.
> + - ``UNDECORATED`` is a type of window that behaves as a toolbar. As such,
> + it is undecorated.
> + """
> +
> + NORMAL = 0 # _NET_WM_WINDOW_TYPE_NORMAL
> + DESKTOP = 1 # _NET_WM_WINDOW_TYPE_DESKTOP
> + DOCK = 2 # _NET_WM_WINDOW_TYPE_DOCK
> + UNDECORATED = 3 # _NET_WM_WINDOW_TYPE_TOOLBAR
> \ No newline at end of file
--
https://code.launchpad.net/~rs2009/unity/+git/unity/+merge/437213
Your team Unity Team is subscribed to branch unity:master.
More information about the Ubuntu-reviews
mailing list