Commit 1f991db7 authored by Nico Alt's avatar Nico Alt

Add tests with pylint and pycodestyle

parent 59c0060f
Pipeline #3498 passed with stage
in 1 minute and 30 seconds
test:lints:
image: debian:stretch
script:
- apt update && apt install --no-install-recommends -y gir1.2-gtk-3.0 python3-gi python3-pip python3-setuptools
- pip3 install -r requirements-dev.txt
- tools/tests/test-pycodestyle.sh
- tools/tests/test-pylint.sh
[MASTER]
disable=attribute-defined-outside-init,
fixme,
missing-docstring
-r requirements.txt
pycodestyle>=2.5.0
pylint>=2.3.1
......@@ -13,6 +13,9 @@ import os
import signal
import sys
import gi
gi.require_version('Gtk', '3.0')
pkgdatadir = '@pkgdatadir@'
localedir = '@localedir@'
......
......@@ -2,9 +2,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md
from briar.api.constants import BASE_HTTP_URL, BRIAR_AUTH_TOKEN, BRIAR_DB
from briar.api.models.socket_listener import SocketListener
from os.path import isfile
from subprocess import Popen, PIPE, STDOUT
from threading import Thread
......@@ -12,6 +9,9 @@ from time import sleep
from urllib.error import HTTPError, URLError
from urllib.request import urlopen
from briar.api.constants import BASE_HTTP_URL, BRIAR_AUTH_TOKEN, BRIAR_DB
from briar.api.models.socket_listener import SocketListener
class Api:
......@@ -25,7 +25,8 @@ class Api:
self.socket_listener = SocketListener(self)
def has_account(self):
@staticmethod
def has_account():
return isfile(BRIAR_DB)
def is_running(self):
......@@ -65,7 +66,7 @@ class Api:
urlopen(BASE_HTTP_URL)
sleep(0.1)
except HTTPError as http_error:
if(http_error.code == 404):
if http_error.code == 404:
self._load_auth_token()
callback(True)
return
......@@ -87,8 +88,7 @@ class Api:
credentials[1] + '\n').encode("utf-8"))
def _load_auth_token(self):
if not self.has_account():
if not Api.has_account():
raise Exception("Can't load authentication token")
with open(BRIAR_AUTH_TOKEN, 'r') as file:
self.auth_token = file.read()
......@@ -3,7 +3,7 @@
# License-Filename: LICENSE.md
class Model:
class Model: # pylint: disable=too-few-public-methods
_headers = {}
......
......@@ -2,16 +2,18 @@
# SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md
from briar.api.constants import BASE_HTTP_URL
from briar.api.model import Model
from urllib.parse import urljoin
from requests import get as _get
from urllib.parse import urljoin
from briar.api.constants import BASE_HTTP_URL
from briar.api.model import Model
class Contacts(Model):
# TODO: remove pylint disable once we have more methods
class Contacts(Model): # pylint: disable=too-few-public-methods
def get(self):
url = urljoin(BASE_HTTP_URL, 'contacts')
r = _get(url, headers=self._headers)
return r.json()
request = _get(url, headers=self._headers)
return request.json()
......@@ -2,12 +2,13 @@
# SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md
from briar.api.constants import BASE_HTTP_URL
from briar.api.model import Model
from urllib.parse import urljoin
from requests import get as _get
from requests import post as _post
from urllib.parse import urljoin
from briar.api.constants import BASE_HTTP_URL
from briar.api.model import Model
class PrivateChat(Model):
......
......@@ -2,17 +2,19 @@
# SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md
from briar.api.constants import WEBSOCKET_URL
from briar.api.model import Model
import asyncio
import json
from threading import Thread
import websockets
from briar.api.constants import WEBSOCKET_URL
from briar.api.model import Model
# TODO: Make more general; currently very specific to private messages
class SocketListener(Model):
# TODO: remove pylint disable once we have more methods
class SocketListener(Model): # pylint: disable=too-few-public-methods
def watch(self, callback, event, contact_id="0"):
websocket_thread = Thread(target=self._start_watch_loop,
......@@ -27,6 +29,8 @@ class SocketListener(Model):
loop.run_forever()
loop.close()
# TODO: use contact id
# pylint: disable=unused-argument
async def _start_websocket(self, callback, event, contact_id="0"):
async with websockets.connect(WEBSOCKET_URL) as websocket:
await websocket.send(self._api.auth_token)
......@@ -34,11 +38,11 @@ class SocketListener(Model):
async def _watch_messages(self, websocket, event, callback):
while not websocket.closed and not\
asyncio.get_event_loop().is_closed():
asyncio.get_event_loop().is_closed():
message = await websocket.recv()
message = json.loads(message)
if message['name'] == event:
callback(message['data'])
if not asyncio.get_event_loop().is_closed():
asyncio.get_event_loop().create_task(
self._watch_messages(websocket, callback))
self._watch_messages(websocket, event, callback))
......@@ -6,14 +6,12 @@
# Initial version based on GNOME Lollypop
# https://gitlab.gnome.org/World/lollypop/blob/1.0.2/lollypop/application.py
from gi.repository import Gdk, Gio, GLib, Gtk
from briar.api.api import Api
from briar.gtk.window import Window
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gdk, Gio, GLib, Gtk
class Application(Gtk.Application):
......@@ -22,28 +20,35 @@ class Application(Gtk.Application):
GLib.set_prgname("Briar")
super().__init__(application_id='app.briar.gtk')
self.window = None
self._set_version(version)
# pylint: disable=arguments-differ
def do_startup(self):
Gtk.Application.do_startup(self)
cssProviderFile = Gio.File.new_for_uri(
css_provider_file = Gio.File.new_for_uri(
"resource:///app/briar/gtk/ui/application.css")
cssProvider = Gtk.CssProvider()
cssProvider.load_from_file(cssProviderFile)
css_provider = Gtk.CssProvider()
css_provider.load_from_file(css_provider_file)
screen = Gdk.Screen.get_default()
styleContext = Gtk.StyleContext()
styleContext.add_provider_for_screen(screen, cssProvider,
Gtk.STYLE_PROVIDER_PRIORITY_USER)
style_context = Gtk.StyleContext()
style_context.add_provider_for_screen(screen, css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_USER)
self.api = Api('/app/briar/briar-headless.jar')
# pylint: disable=arguments-differ
def do_activate(self):
if self.window is None:
self.window = Window()
self.window.show()
self.window.present()
# pylint: disable=arguments-differ
def quit(self):
self.api.stop()
self.window.hide()
Gio.Application.quit(self)
def _set_version(self, version):
self._version = version
......@@ -2,8 +2,6 @@
# SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
......
......@@ -2,14 +2,12 @@
# SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md
from gi.repository import GLib, Gtk
from briar.api.models.private_chat import PrivateChat
from briar.gtk.container import Container
from briar.gtk.define import App
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk
class ChatContainer(Container):
......@@ -46,6 +44,7 @@ class ChatContainer(Container):
def _add_message_async(self, message):
GLib.idle_add(self._add_message, message["text"], False)
# pylint: disable=unused-argument
def _key_pressed(self, widget, event):
if event.hardware_keycode != 36 and event.hardware_keycode != 104:
return
......
......@@ -2,14 +2,12 @@
# SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md
from gi.repository import GLib, Gtk
from briar.api.models.contacts import Contacts
from briar.gtk.container import Container
from briar.gtk.define import App
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, Gtk
class MainContainer(Container):
......@@ -30,10 +28,12 @@ class MainContainer(Container):
contacts_list_box = self.builder.get_object("contacts_list")
for contact in contacts_list:
contact_button = Gtk.Button(contact["author"]["name"])
contact_button.connect("clicked", self._contact_clicked,
contact_button.connect("clicked", MainContainer._contact_clicked,
contact["contactId"])
contact_button.show()
contacts_list_box.add(contact_button)
def _contact_clicked(self, widget, contactId):
GLib.idle_add(App().window.open_private_chat, contactId)
# pylint: disable=unused-argument
@staticmethod
def _contact_clicked(widget, contact_id):
GLib.idle_add(App().window.open_private_chat, contact_id)
......@@ -2,39 +2,42 @@
# SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md
from gi.repository import GLib, GObject, Gtk
from briar.gtk.container import Container
from briar.gtk.define import App
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib, GObject, Gtk
class StartupContainer(Container):
def __init__(self):
super().__init__()
self._api = App().api
self._register_signals()
StartupContainer._register_signals()
self._setup_view()
# pylint: disable=unused-argument
def on_username_button_clicked(self, button):
self.builder.get_object("username_grid").set_visible(False)
self.builder.get_object("password_grid").set_visible(True)
self.username = self.builder.get_object("username_entry").get_text()
# pylint: disable=unused-argument
def on_password_button_clicked(self, button):
password = self.builder.get_object("password_entry").get_text()
password_confirm = self.builder.get_object("password_confirm_entry").get_text()
password_confirm = self.builder.get_object(
"password_confirm_entry").get_text()
if password != password_confirm:
raise Exception("Passwords do not match")
self._api.register((self.username, password), self._startup_finished)
# pylint: disable=unused-argument
def on_login_pressed(self, button):
password = self.builder.get_object("password_entry").get_text()
self._api.login(password, self._startup_finished)
def _register_signals(self):
@staticmethod
def _register_signals():
GObject.signal_new("briar_startup_completed", Gtk.Overlay,
GObject.SignalFlags.RUN_LAST, GObject.TYPE_BOOLEAN,
(GObject.TYPE_STRING,))
......
......@@ -8,4 +8,4 @@
from gi.repository import Gio
App = Gio.Application.get_default
App = Gio.Application.get_default # pylint: disable=invalid-name
......@@ -6,8 +6,6 @@
# Initial version based on GNOME Lollypop
# https://gitlab.gnome.org/World/lollypop/blob/1.0.12/lollypop/toolbar.py
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
......@@ -30,4 +28,3 @@ class Toolbar(Gtk.HeaderBar):
raise Exception("Callback needed when showing back button")
back_button.show()
back_button.connect("clicked", callback)
......@@ -2,86 +2,86 @@
# SPDX-License-Identifier: AGPL-3.0-only
# License-Filename: LICENSE.md
from gi.repository import Gtk
from briar.gtk.containers.chat import ChatContainer
from briar.gtk.containers.main import MainContainer
from briar.gtk.containers.startup import StartupContainer
from briar.gtk.define import App
from briar.gtk.toolbar import Toolbar
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class Window(Gtk.ApplicationWindow):
def __init__(self):
Gtk.ApplicationWindow.__init__(self, application=App(), title="Briar",
icon_name="app.briar.gtk")
self.__setup_content()
self._setup_content()
@property
def container(self):
return self.__container
return self._container
@property
def toolbar(self):
return self.__toolbar
return self._toolbar
def __setup_content(self):
self.__setup_size((600, 400)) # TODO: do properly (constants, save)
self.__setup_toolbar()
self.__setup_grid()
self.__setup_startup_container()
def _setup_content(self):
self._setup_size((600, 400)) # TODO: do properly (constants, save)
self._setup_toolbar()
self._setup_grid()
self._setup_startup_container()
def __setup_size(self, size):
def _setup_size(self, size):
if len(size) == 2 and\
isinstance(size[0], int) and\
isinstance(size[1], int):
self.resize(size[0], size[1])
def __setup_toolbar(self):
self.__toolbar = Toolbar()
self.__toolbar.show()
self.__toolbar.set_show_close_button(True)
self.set_titlebar(self.__toolbar)
def __setup_grid(self):
self.__grid = Gtk.Grid()
self.__grid.set_orientation(Gtk.Orientation.HORIZONTAL)
self.__grid.show()
self.add(self.__grid)
def __setup_startup_container(self):
self.__container = StartupContainer()
self.__container.show()
self.__container.connect("briar_startup_completed",
self.__on_startup_completed)
self.__grid.add(self.__container)
def __on_startup_completed(self, inst, obj):
self.__grid.destroy()
self.__setup_grid()
self.__setup_main_container()
def __setup_main_container(self):
self.__container = MainContainer()
self.__container.show()
self.__grid.add(self.__container)
def _setup_toolbar(self):
self._toolbar = Toolbar()
self._toolbar.show()
self._toolbar.set_show_close_button(True)
self.set_titlebar(self._toolbar)
def _setup_grid(self):
self._grid = Gtk.Grid()
self._grid.set_orientation(Gtk.Orientation.HORIZONTAL)
self._grid.show()
self.add(self._grid)
def _setup_startup_container(self):
self._container = StartupContainer()
self._container.show()
self._container.connect("briar_startup_completed",
self._on_startup_completed)
self._grid.add(self._container)
# TODO: remove unused arguments
# pylint: disable=unused-argument
def _on_startup_completed(self, inst, obj):
self._grid.destroy()
self._setup_grid()
self._setup_main_container()
def _setup_main_container(self):
self._container = MainContainer()
self._container.show()
self._grid.add(self._container)
def open_private_chat(self, contact_id):
self.__grid.destroy()
self.__setup_grid()
self.__setup_private_chat(contact_id)
def __setup_private_chat(self, contact_id):
self.__container = ChatContainer(contact_id)
self.__container.show()
self.__grid.add(self.__container)
self.__toolbar.show_back_button(True, self.__back_to_main)
def __back_to_main(self, widget):
self.__grid.destroy()
self.__setup_grid()
self.__toolbar.show_back_button(False)
self.__setup_main_container()
self._grid.destroy()
self._setup_grid()
self._setup_private_chat(contact_id)
def _setup_private_chat(self, contact_id):
self._container = ChatContainer(contact_id)
self._container.show()
self._grid.add(self._container)
self._toolbar.show_back_button(True, self._back_to_main)
def _back_to_main(self, widget):
self._grid.destroy()
self._setup_grid()
self._toolbar.show_back_button(False)
self._setup_main_container()
......@@ -6,19 +6,19 @@
from os import environ, path
from subprocess import call
prefix = environ.get('MESON_INSTALL_PREFIX', '/usr/local')
datadir = path.join(prefix, 'share')
destdir = environ.get('DESTDIR', '')
PREFIX = environ.get('MESON_INSTALL_PREFIX', '/usr/local')
DATA_DIR = path.join(PREFIX, 'share')
DESTINATION_DIR = environ.get('DESTDIR', '')
# Package managers set this so we don't need to run
if not destdir:
if not DESTINATION_DIR:
print('Updating icon cache...')
call(['gtk-update-icon-cache', '-qtf', path.join(datadir, 'icons', 'hicolor')])
call(['gtk-update-icon-cache', '-qtf',
path.join(DATA_DIR, 'icons', 'hicolor')])
print('Updating desktop database...')
call(['update-desktop-database', '-q', path.join(datadir, 'applications')])
call(['update-desktop-database', '-q',
path.join(DATA_DIR, 'applications')])
print('Compiling GSettings schemas...')
call(['glib-compile-schemas', path.join(datadir, 'glib-2.0', 'schemas')])
call(['glib-compile-schemas', path.join(DATA_DIR, 'glib-2.0', 'schemas')])
#!/usr/bin/env bash
tools/tests/test-pycodestyle.sh
tools/tests/test-pylint.sh
#!/usr/bin/env bash
pycodestyle --show-source --show-pep8 src
#!/usr/bin/env bash
pylint src
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment