mirror of
				https://github.com/lubuntu-team/lugito.git
				synced 2025-11-04 02:24:03 +00:00 
			
		
		
		
	Added .lugitorc configuration and hooked the config files into the connectors. Updates to HISTORY.rst, README.rst and AUTHORS.rst
This commit is contained in:
		
							parent
							
								
									f327136c34
								
							
						
					
					
						commit
						e445368ef9
					
				
							
								
								
									
										27
									
								
								.arcconfig
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								.arcconfig
									
									
									
									
									
								
							@ -1,27 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
    "hosts": {
 | 
			
		||||
        "http://phab.lubuntu.me/": {
 | 
			
		||||
            "token": ""
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "default": "http://phab.lubunutu.me/api/"
 | 
			
		||||
    },
 | 
			
		||||
    "HMAC": i{
 | 
			
		||||
        "irc": "",
 | 
			
		||||
    },
 | 
			
		||||
    "irc": {
 | 
			
		||||
        "host": "irc.freenode.net",
 | 
			
		||||
        "port": "6697",
 | 
			
		||||
        "username": "",
 | 
			
		||||
        "password": "",
 | 
			
		||||
        "channel": "#lubuntu-devel"
 | 
			
		||||
    },
 | 
			
		||||
    "launchpad": {
 | 
			
		||||
        "application": "lugito",
 | 
			
		||||
        "staging": "production",
 | 
			
		||||
        "version": "devel",
 | 
			
		||||
        "supported_versions": ["Cosmic", "Bionic", "Xenial", "Trusty"]
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,6 +1,11 @@
 | 
			
		||||
# Created by .ignore support plugin (hsz.mobi)
 | 
			
		||||
# Config file
 | 
			
		||||
.arcconfig
 | 
			
		||||
.lugitorc
 | 
			
		||||
 | 
			
		||||
# launchpad files
 | 
			
		||||
devel/*
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
### Python template
 | 
			
		||||
# Byte-compiled / optimized / DLL files
 | 
			
		||||
 | 
			
		||||
@ -5,9 +5,9 @@ Credits
 | 
			
		||||
Development Lead
 | 
			
		||||
----------------
 | 
			
		||||
 | 
			
		||||
* Ben Johnston <bjohnston@neomailbox.net>
 | 
			
		||||
* Simon Quigley
 | 
			
		||||
 | 
			
		||||
Contributors
 | 
			
		||||
------------
 | 
			
		||||
-----------
 | 
			
		||||
 | 
			
		||||
None yet. Why not be the first?
 | 
			
		||||
* Ben Johnston (docEbrown) <bjohnston@neomailbox.net>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										27
									
								
								HISTORY.rst
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								HISTORY.rst
									
									
									
									
									
								
							@ -2,7 +2,28 @@
 | 
			
		||||
History
 | 
			
		||||
=======
 | 
			
		||||
 | 
			
		||||
0.1.0 (2018-11-07)
 | 
			
		||||
------------------
 | 
			
		||||
0.1.0 (20th May 2018)
 | 
			
		||||
----------------------
 | 
			
		||||
 | 
			
		||||
* First release on PyPI.
 | 
			
		||||
* Initial Release
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
0.2.0 (21st November 2018)
 | 
			
		||||
---------------------------
 | 
			
		||||
 | 
			
		||||
* added functionality for reporting creation, comments and edits on comments of
 | 
			
		||||
  diffs
 | 
			
		||||
* Refactored into Python package
 | 
			
		||||
* irc and launchpad connections written into separate Python modules
 | 
			
		||||
* corrected issues with reporting using links with anchors via IRC
 | 
			
		||||
* added some unittests
 | 
			
		||||
 | 
			
		||||
* **Still TODO**
 | 
			
		||||
 | 
			
		||||
  * Documentation - read the docs
 | 
			
		||||
  * Add decorators to Lugito class to check that a request has been validated before other tasks can be completed
 | 
			
		||||
  * Improve test coverage
 | 
			
		||||
  * Pypi upload
 | 
			
		||||
  * Add exceptions in the event that connector send method calls are not executed correctly
 | 
			
		||||
  * CI and automated docs and Pypi udpate
 | 
			
		||||
  * in-situ testing
 | 
			
		||||
							
								
								
									
										66
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										66
									
								
								README.md
									
									
									
									
									
								
							@ -1,5 +1,65 @@
 | 
			
		||||
# Lugito
 | 
			
		||||
lugito
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
This is Lubuntu's friendly IRC notifications bot, hooked up to our Phabricator instance at phab.lubuntu.me
 | 
			
		||||
[](https://pypi.python.org/pypi/lugito)
 | 
			
		||||
 | 
			
		||||
The code is licensed under the 3-clause BSD license, and is copyrighted by the Lubuntu team. More info available in LICENSE.
 | 
			
		||||
[](https://travis-ci.org/doc-E-brown/lugito)
 | 
			
		||||
 | 
			
		||||
[](https://lugito.readthedocs.io/en/latest/?badge=latest)
 | 
			
		||||
 | 
			
		||||
Python Boilerplate contains all the boilerplate you need to create a
 | 
			
		||||
Python package.
 | 
			
		||||
 | 
			
		||||
-   Free software: 3 Clause BSD license
 | 
			
		||||
-   Documentation: <https://lugito.readthedocs.io>.
 | 
			
		||||
 | 
			
		||||
Temp - Example .lugitorc
 | 
			
		||||
------------------------
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
[phabricator]
 | 
			
		||||
host = http://127.0.0.1:9091/api/
 | 
			
		||||
token = api-nojs2ip33hmp4zn6u6cf72w7d6yh
 | 
			
		||||
 | 
			
		||||
[phabricator.hooks]
 | 
			
		||||
irc = cqg42zdcuqysff632kc6rnsu4m3hjg6c
 | 
			
		||||
commithook = znkyfflbcia5gviqx5ybad7s6uyfywxi
 | 
			
		||||
 | 
			
		||||
[connector.irc]
 | 
			
		||||
host = irc.freenode.net
 | 
			
		||||
port  = 6697
 | 
			
		||||
username = someusername
 | 
			
		||||
password = somepassword
 | 
			
		||||
channel = #somechannel
 | 
			
		||||
 | 
			
		||||
[connector.launchpad]
 | 
			
		||||
application = lugito
 | 
			
		||||
staging = production
 | 
			
		||||
version = devel
 | 
			
		||||
supported_versions =
 | 
			
		||||
    Cosmic
 | 
			
		||||
    Bionic
 | 
			
		||||
    Xenial
 | 
			
		||||
    Trusty
 | 
			
		||||
 | 
			
		||||
[connector.launchpad.package_names]
 | 
			
		||||
rDEFAULTSETTINGS = lubuntu-default-settings
 | 
			
		||||
rART = lubuntu-artwork
 | 
			
		||||
rCALASETTINGS = calamares-settings-ubuntu
 | 
			
		||||
rQTERMINALPACKAGING = qterminal
 | 
			
		||||
rLXQTCONFIGPACKAGING = lxqt-config
 | 
			
		||||
rNMTRAYPACKAGING = nm-tray
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Features
 | 
			
		||||
--------
 | 
			
		||||
 | 
			
		||||
-   TODO
 | 
			
		||||
 | 
			
		||||
Credits
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
This package was created with
 | 
			
		||||
[Cookiecutter](https://github.com/audreyr/cookiecutter) and the
 | 
			
		||||
[audreyr/cookiecutter-pypackage](https://github.com/audreyr/cookiecutter-pypackage)
 | 
			
		||||
project template.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										52
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										52
									
								
								README.rst
									
									
									
									
									
								
							@ -2,25 +2,55 @@
 | 
			
		||||
lugito
 | 
			
		||||
======
 | 
			
		||||
 | 
			
		||||
lugito is a Python package that provides a webserver for connecting updates from Phabricator to communication tools such as irc and other services such as launchpad.
 | 
			
		||||
 | 
			
		||||
.. image:: https://img.shields.io/pypi/v/lugito.svg
 | 
			
		||||
        :target: https://pypi.python.org/pypi/lugito
 | 
			
		||||
Installation
 | 
			
		||||
-------------
 | 
			
		||||
 | 
			
		||||
.. image:: https://img.shields.io/travis/doc-E-brown/lugito.svg
 | 
			
		||||
        :target: https://travis-ci.org/doc-E-brown/lugito
 | 
			
		||||
 | 
			
		||||
.. image:: https://readthedocs.org/projects/lugito/badge/?version=latest
 | 
			
		||||
        :target: https://lugito.readthedocs.io/en/latest/?badge=latest
 | 
			
		||||
        :alt: Documentation Status
 | 
			
		||||
lugito can be installed via Pyp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
* Free software: 3 Clause BSD license
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Python Boilerplate contains all the boilerplate you need to create a Python package.
 | 
			
		||||
Temp - Example .lugitorc
 | 
			
		||||
-------------------------
 | 
			
		||||
 | 
			
		||||
.. code:: 
 | 
			
		||||
 | 
			
		||||
    [phabricator]
 | 
			
		||||
    host = http://127.0.0.1:9091/api/
 | 
			
		||||
    token = api-nojs2ip33hmp4zn6u6cf72w7d6yh
 | 
			
		||||
    
 | 
			
		||||
    [phabricator.hooks]
 | 
			
		||||
    irc = cqg42zdcuqysff632kc6rnsu4m3hjg6c
 | 
			
		||||
    commithook = znkyfflbcia5gviqx5ybad7s6uyfywxi
 | 
			
		||||
    
 | 
			
		||||
    [connector.irc]
 | 
			
		||||
    host = irc.freenode.net
 | 
			
		||||
    port  = 6697
 | 
			
		||||
    username = someusername
 | 
			
		||||
    password = somepassword
 | 
			
		||||
    channel = #somechannel
 | 
			
		||||
    
 | 
			
		||||
    [connector.launchpad]
 | 
			
		||||
    application = lugito
 | 
			
		||||
    staging = production
 | 
			
		||||
    version = devel
 | 
			
		||||
    supported_versions =
 | 
			
		||||
        Cosmic
 | 
			
		||||
        Bionic
 | 
			
		||||
        Xenial
 | 
			
		||||
        Trusty
 | 
			
		||||
    
 | 
			
		||||
    [connector.launchpad.package_names]
 | 
			
		||||
    rDEFAULTSETTINGS = lubuntu-default-settings
 | 
			
		||||
    rART = lubuntu-artwork
 | 
			
		||||
    rCALASETTINGS = calamares-settings-ubuntu
 | 
			
		||||
    rQTERMINALPACKAGING = qterminal
 | 
			
		||||
    rLXQTCONFIGPACKAGING = lxqt-config
 | 
			
		||||
    rNMTRAYPACKAGING = nm-tray
 | 
			
		||||
 | 
			
		||||
* Free software: BSD license
 | 
			
		||||
* Documentation: https://lugito.readthedocs.io.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Features
 | 
			
		||||
 | 
			
		||||
@ -2,14 +2,7 @@ from lugito.lugito import (
 | 
			
		||||
    Lugito,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from lugito.connectors.irc import (
 | 
			
		||||
    IRCConnector,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from lugito.connectors.launchpad import (
 | 
			
		||||
        LPConnectook,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
import lugito.config
 | 
			
		||||
 | 
			
		||||
from ._version import get_versions
 | 
			
		||||
__version__ = get_versions()['version']
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,6 @@
 | 
			
		||||
# Imports
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
from lugito.webhooks import run
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
    from lugito.webhooks import run
 | 
			
		||||
    run()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										135
									
								
								lugito/config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								lugito/config.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,135 @@
 | 
			
		||||
#! /usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# S.D.G
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
:mod:`lugito.config`
 | 
			
		||||
======================================
 | 
			
		||||
 | 
			
		||||
Module to manage lugito configuration
 | 
			
		||||
 | 
			
		||||
.. currentmodule:: lugito.config
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# Imports
 | 
			
		||||
import os
 | 
			
		||||
import logging
 | 
			
		||||
import configparser
 | 
			
		||||
 | 
			
		||||
DEFAULT_CONFIG_FILE = os.path.join(
 | 
			
		||||
    os.getcwd(), '.lugitorc')
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger('lugito.config')
 | 
			
		||||
 | 
			
		||||
# Add log level
 | 
			
		||||
ch = logging.StreamHandler()
 | 
			
		||||
 | 
			
		||||
formatter = logging.Formatter(
 | 
			
		||||
    '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
 | 
			
		||||
 | 
			
		||||
ch.setFormatter(formatter)
 | 
			
		||||
logger.addHandler(ch)
 | 
			
		||||
logger.setLevel(logging.DEBUG)
 | 
			
		||||
 | 
			
		||||
CONFIG = {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def update_config(config_file=DEFAULT_CONFIG_FILE):
 | 
			
		||||
    """
 | 
			
		||||
    Update the system config from a config file
 | 
			
		||||
 | 
			
		||||
    Parameters
 | 
			
		||||
    ----------
 | 
			
		||||
 | 
			
		||||
    config_file: str
 | 
			
		||||
       The path of the lugito config file
 | 
			
		||||
 | 
			
		||||
    Returns
 | 
			
		||||
    -------
 | 
			
		||||
 | 
			
		||||
    config: dictionary
 | 
			
		||||
       A dictionary of config parameters
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    config = configparser.ConfigParser()
 | 
			
		||||
    config.read(config_file)
 | 
			
		||||
 | 
			
		||||
    # Make some basic assertions for minimum functionality
 | 
			
		||||
    if 'phabricator' not in config:
 | 
			
		||||
        raise ValueError('phabricator section missing from config file: %s' %\
 | 
			
		||||
            config_file)
 | 
			
		||||
 | 
			
		||||
    if 'host' not in config['phabricator']:
 | 
			
		||||
        raise ValueError('host value missing from phabricator section in'\
 | 
			
		||||
            ' config file: %s' % config_file)
 | 
			
		||||
 | 
			
		||||
    if 'token' not in config['phabricator']:
 | 
			
		||||
        raise ValueError('token value missing from phabricator section in'\
 | 
			
		||||
            ' config file: %s' % config_file)
 | 
			
		||||
 | 
			
		||||
    CONFIG['phabricator'] = {}
 | 
			
		||||
    CONFIG['phabricator']['host'] = config['phabricator']['host']
 | 
			
		||||
    CONFIG['phabricator']['token'] = config['phabricator']['token']
 | 
			
		||||
 | 
			
		||||
    CONFIG['phabricator']['hooks'] = {}
 | 
			
		||||
 | 
			
		||||
    # Iterate through hooks for HMAC keys
 | 
			
		||||
    if 'phabricator.hooks' in config:
 | 
			
		||||
 | 
			
		||||
        for key, value in config['phabricator.hooks'].items():
 | 
			
		||||
            CONFIG['phabricator']['hooks'][key] = value
 | 
			
		||||
 | 
			
		||||
    CONFIG['connectors'] = {}
 | 
			
		||||
 | 
			
		||||
    # Iterate through available connectors
 | 
			
		||||
    for key in config.keys():
 | 
			
		||||
 | 
			
		||||
        # Is a connector section
 | 
			
		||||
        if ('connector.' in key) and (key.count('.') == 1) :
 | 
			
		||||
            connector = key.split('.')[1]
 | 
			
		||||
 | 
			
		||||
            if 'connectors' not in CONFIG:
 | 
			
		||||
                CONFIG['connectors'] = {}
 | 
			
		||||
 | 
			
		||||
            if connector not in CONFIG['connectors']:
 | 
			
		||||
                CONFIG['connectors'][connector] = {}
 | 
			
		||||
 | 
			
		||||
            for param, value in config[key].items():
 | 
			
		||||
 | 
			
		||||
                # Check for multiple values for a parameter
 | 
			
		||||
                if value.find('\n') >= 0:
 | 
			
		||||
                    value = value[1:].split('\n')
 | 
			
		||||
 | 
			
		||||
                CONFIG['connectors'][connector][param] = value
 | 
			
		||||
 | 
			
		||||
        # Is a connector sub-section
 | 
			
		||||
        elif ('connector.' in key) and (key.count('.') > 1) :
 | 
			
		||||
            sections = key.split('.')
 | 
			
		||||
            connector = sections[1]
 | 
			
		||||
            subsection = sections[-1]
 | 
			
		||||
 | 
			
		||||
            if 'connectors' not in CONFIG:
 | 
			
		||||
                CONFIG['connectors'] = {}
 | 
			
		||||
 | 
			
		||||
            if connector not in CONFIG['connectors']:
 | 
			
		||||
                CONFIG['connectors'][connector] = {}
 | 
			
		||||
 | 
			
		||||
            CONFIG['connectors'][connector][subsection] = {}
 | 
			
		||||
 | 
			
		||||
            for param, value in config[key].items():
 | 
			
		||||
 | 
			
		||||
                # Check for multiple values for a parameter
 | 
			
		||||
                if value.find('\n') >= 0:
 | 
			
		||||
                    value = value[1:].split('\n')
 | 
			
		||||
 | 
			
		||||
                # configparser reads the parameters as lower case
 | 
			
		||||
                # convert all but first character to upper case
 | 
			
		||||
                param = 'r{}'.format(param[1:].upper())
 | 
			
		||||
                CONFIG['connectors'][connector][subsection][param] = value
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
try:
 | 
			
		||||
    update_config()
 | 
			
		||||
except ValueError:
 | 
			
		||||
    # The config file is not present
 | 
			
		||||
    logging.warning('Default config file: %s not found' % DEFAULT_CONFIG_FILE)
 | 
			
		||||
@ -1,3 +1,11 @@
 | 
			
		||||
#! /usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# S.D.G
 | 
			
		||||
 | 
			
		||||
from lugito.connectors.irc import (
 | 
			
		||||
    irc,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
from lugito.connectors.launchpad import (
 | 
			
		||||
    launchpad,
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -18,25 +18,27 @@ import socket
 | 
			
		||||
import logging
 | 
			
		||||
import threading
 | 
			
		||||
import phabricator
 | 
			
		||||
import lugito
 | 
			
		||||
from time import sleep
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class IRCConnector(object):
 | 
			
		||||
class irc(object):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, log_level=logging.DEBUG):
 | 
			
		||||
    def __init__(self, log_level=logging.DEBUG, sleep_delay=5):
 | 
			
		||||
 | 
			
		||||
        # IRC info
 | 
			
		||||
        # Read the configuration out of the .arcconfig file
 | 
			
		||||
        self.host = phabricator.ARCRC['irc']['host']
 | 
			
		||||
        self.port = int(phabricator.ARCRC['irc']['port'])
 | 
			
		||||
        self.username = phabricator.ARCRC['irc']['username']
 | 
			
		||||
        self.password = phabricator.ARCRC['irc']['password']
 | 
			
		||||
        self.channel = phabricator.ARCRC['irc']['channel']
 | 
			
		||||
        self.host = lugito.config.CONFIG['connectors']['irc']['host']
 | 
			
		||||
        self.port = int(lugito.config.CONFIG['connectors']['irc']['port'])
 | 
			
		||||
        self.username = lugito.config.CONFIG['connectors']['irc']['username']
 | 
			
		||||
        self.password = lugito.config.CONFIG['connectors']['irc']['password']
 | 
			
		||||
        self.channel = lugito.config.CONFIG['connectors']['irc']['channel']
 | 
			
		||||
 | 
			
		||||
        # Phabricator info
 | 
			
		||||
        self.phab = phabricator.Phabricator()
 | 
			
		||||
        self.phab_host = phabricator.ARCRC['config']['default'].replace(
 | 
			
		||||
            'api/', '')
 | 
			
		||||
        self.phab = phabricator.Phabricator(
 | 
			
		||||
            host=lugito.config.CONFIG['phabricator']['host'],
 | 
			
		||||
            token=lugito.config.CONFIG['phabricator']['token'],)
 | 
			
		||||
        self.phab_host = self.phab.host.replace('api/', '')
 | 
			
		||||
 | 
			
		||||
        self.logger = logging.getLogger('lugito.connector.IRCConnector')
 | 
			
		||||
 | 
			
		||||
@ -50,14 +52,17 @@ class IRCConnector(object):
 | 
			
		||||
        self.logger.addHandler(ch)
 | 
			
		||||
        self.logger.setLevel(log_level)
 | 
			
		||||
 | 
			
		||||
        self.sleep_delay = sleep_delay
 | 
			
		||||
 | 
			
		||||
    def _send_raw(self, message):
 | 
			
		||||
 | 
			
		||||
    def _send_raw(self, message): # pragma: no cover
 | 
			
		||||
        """Low level send"""
 | 
			
		||||
 | 
			
		||||
        self.conn.send(message.encode('utf-8'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def _socket_conn(self):
 | 
			
		||||
    def _setup_connection(self):
 | 
			
		||||
        """Setup connection"""
 | 
			
		||||
        self.conn = ssl.wrap_socket(
 | 
			
		||||
            socket.socket(socket.AF_INET, socket.SOCK_STREAM))
 | 
			
		||||
        self.conn.connect((self.host, self.port))
 | 
			
		||||
@ -66,11 +71,11 @@ class IRCConnector(object):
 | 
			
		||||
    def connect(self):
 | 
			
		||||
        """Connect"""
 | 
			
		||||
 | 
			
		||||
        self._socket_conn()
 | 
			
		||||
        self.logger.info("Connecting to IRC.")
 | 
			
		||||
        self._setup_connection()
 | 
			
		||||
 | 
			
		||||
        setup = False
 | 
			
		||||
        usersuffix = 0
 | 
			
		||||
        self.logger.info("Connecting to IRC.")
 | 
			
		||||
 | 
			
		||||
        while not setup:
 | 
			
		||||
            response = self.conn.recv(512).decode("utf-8")
 | 
			
		||||
@ -84,11 +89,11 @@ class IRCConnector(object):
 | 
			
		||||
                    self.username, self.password))
 | 
			
		||||
 | 
			
		||||
            if "You are now identified" in response:
 | 
			
		||||
                sleep(5)
 | 
			
		||||
                sleep(self.sleep_delay)
 | 
			
		||||
                self._send_raw("JOIN {}\r\n".format(self.channel))
 | 
			
		||||
 | 
			
		||||
            if "477" in response:
 | 
			
		||||
                sleep(5)
 | 
			
		||||
                sleep(self.sleep_delay)
 | 
			
		||||
                self._send_raw("JOIN {}\r\n".format(self.channel))
 | 
			
		||||
 | 
			
		||||
            if "433" in response:
 | 
			
		||||
@ -106,20 +111,32 @@ class IRCConnector(object):
 | 
			
		||||
 | 
			
		||||
        self.logger.info("Successfully connected to the IRC server.")
 | 
			
		||||
 | 
			
		||||
    def send_notice(self, message):
 | 
			
		||||
    def send_notice(self, message): # pragma: no cover
 | 
			
		||||
        self._send_raw("NOTICE {} :{}\r\n".format(self.channel, message))
 | 
			
		||||
 | 
			
		||||
    def send(self, objectstr, who, body, link):
 | 
			
		||||
    def send(self, *args, **kwargs):
 | 
			
		||||
        """Send a formatted message"""
 | 
			
		||||
 | 
			
		||||
        if len(args) == 4:
 | 
			
		||||
            objectstr, who, body, link = args
 | 
			
		||||
 | 
			
		||||
        elif len(kwargs) == 4:
 | 
			
		||||
            objectstr = kwargs['objectstr']
 | 
			
		||||
            who = kwargs['who']
 | 
			
		||||
            body = kwargs['body']
 | 
			
		||||
            link = kwargs['link']
 | 
			
		||||
 | 
			
		||||
        # else
 | 
			
		||||
        # raise exception
 | 
			
		||||
 | 
			
		||||
        # e.g. [T31: Better IRC integration]
 | 
			
		||||
        message = "\x033[\x03\x0313" + objectstr + "\x03\x033]\x03 "
 | 
			
		||||
        # e.g. tsimonq2 (Simon Quigley)
 | 
			
		||||
        message = message + "\x0315" + who + "\x03 "
 | 
			
		||||
        message += "\x0315" + who + "\x03 "
 | 
			
		||||
        # e.g. commented on the task:
 | 
			
		||||
        message = message + body + ": "
 | 
			
		||||
        message += body + ": "
 | 
			
		||||
        # e.g. https://phab.lubuntu.me/T40#779
 | 
			
		||||
        message = message + "\x032" + link + "\x03"
 | 
			
		||||
        message += "\x032" + link + "\x03"
 | 
			
		||||
        # Make sure we can debug this if it goes haywire
 | 
			
		||||
        self.logger.debug(message)
 | 
			
		||||
        # Sleep for a fifth of a second, so when we have a bunch of messages we have a buffer
 | 
			
		||||
@ -127,7 +144,7 @@ class IRCConnector(object):
 | 
			
		||||
        # Aaaaand, send it off!
 | 
			
		||||
        self.send_notice(message)
 | 
			
		||||
 | 
			
		||||
    def gettaskinfo(self, task):
 | 
			
		||||
    def get_task_info(self, task):
 | 
			
		||||
 | 
			
		||||
        sendmessage = ""
 | 
			
		||||
 | 
			
		||||
@ -170,7 +187,7 @@ class IRCConnector(object):
 | 
			
		||||
            if color is not None:
 | 
			
		||||
                sendmessage += ", "
 | 
			
		||||
 | 
			
		||||
            sendmessage +=  taskinfo["statusName"] + "\x03\x033]\x03 "
 | 
			
		||||
            sendmessage += taskinfo["statusName"] + "\x03\x033]\x03 "
 | 
			
		||||
 | 
			
		||||
            # Put the title in there as well.
 | 
			
		||||
            sendmessage += taskinfo["title"].strip() + ": "
 | 
			
		||||
@ -189,8 +206,14 @@ class IRCConnector(object):
 | 
			
		||||
 | 
			
		||||
        # If someone wrote something like "Tblah", obviously that's not right.
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            self.send_notice("\x034Error: " + task.strip() + "is an invalid task reference.\x03")
 | 
			
		||||
            return None
 | 
			
		||||
 | 
			
		||||
            if anchor is not None:
 | 
			
		||||
                link = '{}#{}'.format(task.strip(), anchor)
 | 
			
		||||
            else:
 | 
			
		||||
                link = task.strip()
 | 
			
		||||
 | 
			
		||||
            self.send_notice("\x034Error: " + link +\
 | 
			
		||||
                " is an invalid task reference.\x03")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def bot(self, message, msgtype):
 | 
			
		||||
@ -200,7 +223,7 @@ class IRCConnector(object):
 | 
			
		||||
 | 
			
		||||
            for item in message.split():
 | 
			
		||||
                if item.startswith("T") or item.startwith("D"):
 | 
			
		||||
                    self.gettaskinfo(item.strip())
 | 
			
		||||
                    self.get_task_info(item.strip())
 | 
			
		||||
 | 
			
		||||
        elif msgtype == "link":
 | 
			
		||||
 | 
			
		||||
@ -208,7 +231,7 @@ class IRCConnector(object):
 | 
			
		||||
                if (item.split()[0].strip().startswith("T")) or \
 | 
			
		||||
                    (item.split()[0].strip().startswith("D")):
 | 
			
		||||
 | 
			
		||||
                    self.gettaskinfo(item.split()[0].strip())
 | 
			
		||||
                    self.get_task_info(item.split()[0].strip())
 | 
			
		||||
 | 
			
		||||
        else:
 | 
			
		||||
            self.sendnotice("\x034Error: unknown command.\x03")
 | 
			
		||||
 | 
			
		||||
@ -11,29 +11,53 @@ Define a launchpad connector class
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# Imports
 | 
			
		||||
import re
 | 
			
		||||
import logging
 | 
			
		||||
import phabricator
 | 
			
		||||
from launchpadlib.launchpad import Launchpad
 | 
			
		||||
import lugito
 | 
			
		||||
from string import Template
 | 
			
		||||
from launchpadlib.launchpad import Launchpad as lp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class LPConnector(object):
 | 
			
		||||
BUG_MESSAGE = Template(
 | 
			
		||||
        "This bug has been marked as fixed in the Git repository: $link\n"
 | 
			
		||||
        "The commit message is the following: $commit_message\n\n"
 | 
			
		||||
        "(Note: I am only a bot. If this message was received in error, "
 | 
			
		||||
        "please contact my owners on the Lubuntu Team.)")
 | 
			
		||||
 | 
			
		||||
RE_COMMIT_MSG = re.compile(r"lp:\s+\#\d+(?:,\s*\#\d+)*")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class launchpad(object):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, log_level=logging.DEBUG):
 | 
			
		||||
 | 
			
		||||
        # Launchpad info
 | 
			
		||||
        # Read the configuration out of the .arcconfig file
 | 
			
		||||
        self.application = phabricator.ARCRC['launchpad']['application']
 | 
			
		||||
        self.staging = phabricator.ARCRC['launchpad']['staging']
 | 
			
		||||
        self.version = phabricator.ARCRC['launchpad']['version']
 | 
			
		||||
        # Read the configuration out of the .lugitorc file
 | 
			
		||||
        self.application = lugito.config.CONFIG['connectors']\
 | 
			
		||||
            ['launchpad']['application']
 | 
			
		||||
        self.staging = lugito.config.CONFIG['connectors']\
 | 
			
		||||
            ['launchpad']['staging']
 | 
			
		||||
        self.version = lugito.config.CONFIG['connectors']\
 | 
			
		||||
            ['launchpad']['version']
 | 
			
		||||
        self.supported_vers =\
 | 
			
		||||
            phabricator.ARCRC['launchpad']['supported_versions']
 | 
			
		||||
            lugito.config.CONFIG['connectors']\
 | 
			
		||||
            ['launchpad']['supported_versions']
 | 
			
		||||
        self.package_names =\
 | 
			
		||||
            lugito.config.CONFIG['connectors']\
 | 
			
		||||
            ['launchpad']['package_names']
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        # Phabricator info
 | 
			
		||||
        self.phab = phabricator.Phabricator()
 | 
			
		||||
        self.phab_host = phabricator.ARCRC['config']['default'].replace(
 | 
			
		||||
        self.phab = phabricator.Phabricator(
 | 
			
		||||
            host=lugito.config.CONFIG['phabricator']['host'],
 | 
			
		||||
            token=lugito.config.CONFIG['phabricator']['token'],
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.phab_host = lugito.config.CONFIG['phabricator']['host'].replace(
 | 
			
		||||
            'api/', '')
 | 
			
		||||
 | 
			
		||||
        self.logger = logging.getLogger('lugito.connector.LPConnector')
 | 
			
		||||
        self.logger = logging.getLogger('lugito.connector.launchpad')
 | 
			
		||||
 | 
			
		||||
        # Add log level
 | 
			
		||||
        ch = logging.StreamHandler()
 | 
			
		||||
@ -50,17 +74,74 @@ class LPConnector(object):
 | 
			
		||||
        """Connect"""
 | 
			
		||||
 | 
			
		||||
        self.logger.info("Connecting to Launchpad")
 | 
			
		||||
        self.lp = lp.login_with(
 | 
			
		||||
            self.application,
 | 
			
		||||
            self.staging,
 | 
			
		||||
            self.version)
 | 
			
		||||
 | 
			
		||||
    def get_package_name(self, name):
 | 
			
		||||
        """Need to check"""
 | 
			
		||||
 | 
			
		||||
        if name in self.package_names:
 | 
			
		||||
            return self.package_names[name]
 | 
			
		||||
 | 
			
		||||
        self.logger.debug('{} is an unsupported repository'.format(
 | 
			
		||||
            name))
 | 
			
		||||
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    def get_bugs_list(self, link):
 | 
			
		||||
        """Get bugs list using a link"""
 | 
			
		||||
 | 
			
		||||
        regex_search = RE_COMMIT_MSG.search(link.lower())
 | 
			
		||||
        if not regex_search:
 | 
			
		||||
            self.logger.debug('{} not a commit message'.format(link))
 | 
			
		||||
            return []
 | 
			
		||||
 | 
			
		||||
        return regex_search.group(0).strip("lp: ").replace("#", "").split(", ")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def send(self, objectstr, who, body, link):
 | 
			
		||||
        pass
 | 
			
		||||
    def send(self, *args, **kwargs):
 | 
			
		||||
        """Send the commit message"""
 | 
			
		||||
 | 
			
		||||
        if len(args) == 2:
 | 
			
		||||
            package_name, commit_msg = args
 | 
			
		||||
 | 
			
		||||
        elif len(kwargs) == 2:
 | 
			
		||||
            commit_msg = kwargs['commit_msg']
 | 
			
		||||
            package_name = kwargs['package_name']
 | 
			
		||||
 | 
			
		||||
        # else
 | 
			
		||||
        # raise exception
 | 
			
		||||
 | 
			
		||||
        package_name = self.get_package_name(package_name)
 | 
			
		||||
        bug_list = self.get_bugs_list(commit_msg)
 | 
			
		||||
 | 
			
		||||
        if package_name and bug_list:
 | 
			
		||||
 | 
			
		||||
            for bug in bug_list:
 | 
			
		||||
                goodtask = None
 | 
			
		||||
                bug = self.lp.load("/bugs/" + str(bug).strip())
 | 
			
		||||
 | 
			
		||||
                for task in bug.bug_tasks:
 | 
			
		||||
                    for rel in self.supported_vers:
 | 
			
		||||
                        if package_name + " (Ubuntu " + rel + ")" in task.bug_target_display_name:
 | 
			
		||||
                            goodtask = task
 | 
			
		||||
                            break
 | 
			
		||||
 | 
			
		||||
                    if not goodtask:
 | 
			
		||||
                        if package_name + " (Ubuntu)" in task.bug_target_display_name:
 | 
			
		||||
                            goodtask = task
 | 
			
		||||
 | 
			
		||||
                if goodtask:
 | 
			
		||||
                    message = BUG_MESSAGE.substitute(
 | 
			
		||||
                        link=self.phab_host + package_name,
 | 
			
		||||
                        commit_message=commit_msg,
 | 
			
		||||
                    )
 | 
			
		||||
                    bug.newMessage(content=message)
 | 
			
		||||
                    goodtask.status = "Fix Committed"
 | 
			
		||||
                    goodtask.lp_save()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def listen(self):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
if __name__ == "__main__":
 | 
			
		||||
 | 
			
		||||
    obj = LPConnector()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@ import hmac
 | 
			
		||||
import http
 | 
			
		||||
import logging
 | 
			
		||||
import phabricator
 | 
			
		||||
import lugito
 | 
			
		||||
from hashlib import sha256
 | 
			
		||||
 | 
			
		||||
PHAB_WEBHOOK_SIG = "X-Phabricator-Webhook-Signature"
 | 
			
		||||
@ -31,9 +32,12 @@ class Lugito(object):
 | 
			
		||||
        Initialise
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        self.phab = phabricator.Phabricator()
 | 
			
		||||
        self.HMAC = phabricator.ARCRC['HMAC']
 | 
			
		||||
        self.host = phabricator.ARCRC['config']['default']
 | 
			
		||||
        self.phab = phabricator.Phabricator(
 | 
			
		||||
            host=lugito.config.CONFIG['phabricator']['host'],
 | 
			
		||||
            token=lugito.config.CONFIG['phabricator']['token'],
 | 
			
		||||
        )
 | 
			
		||||
        self.HMAC = lugito.config.CONFIG['phabricator']['hooks']
 | 
			
		||||
        self.host = lugito.config.CONFIG['phabricator']['host']
 | 
			
		||||
 | 
			
		||||
        self.logger = logging.getLogger('lugito.lugito')
 | 
			
		||||
 | 
			
		||||
@ -51,15 +55,7 @@ class Lugito(object):
 | 
			
		||||
            self.HMAC[key] = bytes(u'%s' % val, 'utf-8')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def _transaction_search(self):
 | 
			
		||||
        self.transaction = self.phab.transaction.search(objectIdentifier=
 | 
			
		||||
            self.request_data["object"]["phid"])["data"]
 | 
			
		||||
 | 
			
		||||
    def _request_data(self, request):
 | 
			
		||||
        self.request_data = json.loads(request.data)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    def validate_HMAC(self, hmac_key, request):
 | 
			
		||||
    def validate_request(self, hmac_key, request):
 | 
			
		||||
        """
 | 
			
		||||
        Check a request originated from Phabricator.  This method must be called
 | 
			
		||||
        first to validate a request is from Phabricator before any other method
 | 
			
		||||
@ -86,8 +82,13 @@ class Lugito(object):
 | 
			
		||||
 | 
			
		||||
        # check if from phabricator
 | 
			
		||||
        if hash_.hexdigest() == request.headers[PHAB_WEBHOOK_SIG]:
 | 
			
		||||
            self._request_data(request)
 | 
			
		||||
            self._transaction_search()
 | 
			
		||||
 | 
			
		||||
            # Store the request and transaction
 | 
			
		||||
            self.request_data = json.loads(request.data)
 | 
			
		||||
            self.transaction = self.phab.transaction.search(objectIdentifier=
 | 
			
		||||
                self.request_data["object"]["phid"])["data"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            self.logger.info('received phid: %s' %\
 | 
			
		||||
                self.request_data["object"]["phid"])
 | 
			
		||||
            return True
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ import logging
 | 
			
		||||
import threading
 | 
			
		||||
from flask import Flask, request
 | 
			
		||||
from lugito import Lugito
 | 
			
		||||
from lugito.connectors.irc import IRCConnector
 | 
			
		||||
from lugito.connectors import irc, launchpad
 | 
			
		||||
 | 
			
		||||
# Constants
 | 
			
		||||
GLOBAL_LOG_LEVEL = logging.DEBUG
 | 
			
		||||
@ -26,7 +26,9 @@ GLOBAL_LOG_LEVEL = logging.DEBUG
 | 
			
		||||
lugito = Lugito(GLOBAL_LOG_LEVEL)
 | 
			
		||||
WEBSITE = lugito.host.replace('/api/', '')
 | 
			
		||||
 | 
			
		||||
irc_con = IRCConnector()
 | 
			
		||||
# Connectors
 | 
			
		||||
irc_con = irc()
 | 
			
		||||
launchpad_con = launchpad()
 | 
			
		||||
 | 
			
		||||
# Logging
 | 
			
		||||
logger = logging.getLogger('lugito.webhooks')
 | 
			
		||||
@ -45,11 +47,41 @@ logger.setLevel(GLOBAL_LOG_LEVEL)
 | 
			
		||||
app = Flask('lugito')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@app.route("/commithook", methods=["POST"])
 | 
			
		||||
def commithook():
 | 
			
		||||
    """Commit hook"""
 | 
			
		||||
 | 
			
		||||
    if lugito.validate_request('commithook', request):
 | 
			
		||||
 | 
			
		||||
        author = lugito.get_author_fullname()
 | 
			
		||||
 | 
			
		||||
        # Without the author we can't continue
 | 
			
		||||
        if author is None:
 | 
			
		||||
            return 'Ok'
 | 
			
		||||
 | 
			
		||||
        object_type = lugito.request_data["object"]["type"]
 | 
			
		||||
 | 
			
		||||
        if object_type == "CMIT":
 | 
			
		||||
            logger.debug("Object is a commit.")
 | 
			
		||||
 | 
			
		||||
            commit_msg = lugito.get_object_string("fullName").replace(
 | 
			
		||||
                lugito.get_object_string("name") + ": ", "")
 | 
			
		||||
            pkg_name = lugito.get_object_string("name")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            launchpad_con.send(pkg_name, commit_msg)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    return 'Ok'
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@app.route("/irc", methods=["POST"])
 | 
			
		||||
def _main():
 | 
			
		||||
    """Main route"""
 | 
			
		||||
 | 
			
		||||
    if lugito.validate_HMAC('irc', request):
 | 
			
		||||
    if lugito.validate_request('irc', request):
 | 
			
		||||
 | 
			
		||||
        author = lugito.get_author_fullname()
 | 
			
		||||
 | 
			
		||||
@ -136,6 +168,7 @@ def _main():
 | 
			
		||||
 | 
			
		||||
def run():
 | 
			
		||||
    irc_con.connect()
 | 
			
		||||
    launchpad_con.connect()
 | 
			
		||||
    t = threading.Thread(target=irc_con.listen)
 | 
			
		||||
    t.daemon = True
 | 
			
		||||
    t.start()
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
[pytest]
 | 
			
		||||
timeout=100
 | 
			
		||||
python_files = tests.py test_*.py *_tests.py
 | 
			
		||||
pytest_plugins = "pytest_cov", "pep8"
 | 
			
		||||
addopts = --doctest-modules --cov-config=.coveragerc --cov=lugito --cov-report=term-missing
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,6 @@ keyring==16.0.2
 | 
			
		||||
launchpadlib==1.10.6
 | 
			
		||||
lazr.restfulclient==0.14.0
 | 
			
		||||
lazr.uri==1.0.3
 | 
			
		||||
-e git+ssh://git@phab.lubuntu.me:2222/source/lugito.git@165c866a5d5a184b0b36552334fa11aba95b5fb8#egg=lugito
 | 
			
		||||
MarkupSafe==1.1.0
 | 
			
		||||
more-itertools==4.3.0
 | 
			
		||||
oauthlib==2.1.0
 | 
			
		||||
@ -31,5 +30,7 @@ pytest-cov==2.6.0
 | 
			
		||||
SecretStorage==3.1.0
 | 
			
		||||
six==1.11.0
 | 
			
		||||
testresources==2.0.1
 | 
			
		||||
versioneer==0.18
 | 
			
		||||
wadllib==1.3.3
 | 
			
		||||
Werkzeug==0.14.1
 | 
			
		||||
twine==1.12.1
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										17
									
								
								setup.py
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								setup.py
									
									
									
									
									
								
							@ -2,7 +2,7 @@
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
 | 
			
		||||
"""The setup script."""
 | 
			
		||||
# import versioneer
 | 
			
		||||
import versioneer
 | 
			
		||||
from setuptools import setup, find_packages
 | 
			
		||||
 | 
			
		||||
with open('README.rst') as readme_file:
 | 
			
		||||
@ -29,8 +29,8 @@ test_requirements = [
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
setup(
 | 
			
		||||
    author="",
 | 
			
		||||
    author_email='',
 | 
			
		||||
    author="Ben Johnston (docEbrown)",
 | 
			
		||||
    author_email='bjohnston@neomailbox.net',
 | 
			
		||||
    classifiers=[
 | 
			
		||||
        'Development Status :: 2 - Pre-Alpha',
 | 
			
		||||
        'Intended Audience :: Developers',
 | 
			
		||||
@ -42,11 +42,11 @@ setup(
 | 
			
		||||
        'Programming Language :: Python :: 3.6',
 | 
			
		||||
        'Programming Language :: Python :: 3.7',
 | 
			
		||||
    ],
 | 
			
		||||
    description="Python Boilerplate contains all the boilerplate "\
 | 
			
		||||
        "you need to create a Python package.",
 | 
			
		||||
    description="Python package to connect services such as irc and launchpad"\
 | 
			
		||||
        " to Phabricator and provide updates",
 | 
			
		||||
    entry_points={
 | 
			
		||||
        'console_scripts': [
 | 
			
		||||
            'lugito=lugito.cli:run',
 | 
			
		||||
            'lugito=lugito.webhooks:run',
 | 
			
		||||
        ],
 | 
			
		||||
    },
 | 
			
		||||
    install_requires=requirements,
 | 
			
		||||
@ -60,8 +60,7 @@ setup(
 | 
			
		||||
    test_suite='tests',
 | 
			
		||||
    tests_require=test_requirements,
 | 
			
		||||
    url='',
 | 
			
		||||
    version='0.1.0',
 | 
			
		||||
    zip_safe=False,
 | 
			
		||||
#    version=versioneer.get_version(),
 | 
			
		||||
#    cmdclass=versioneer.get_cmdclass(),
 | 
			
		||||
    version=versioneer.get_version(),
 | 
			
		||||
    cmdclass=versioneer.get_cmdclass(),
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -4,24 +4,4 @@
 | 
			
		||||
            "token": "api-nojs2ip33hmp4zn6u6cf72w7d6yh"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "default": "http://127.0.0.1:9091/api/"
 | 
			
		||||
    },
 | 
			
		||||
    "HMAC": {
 | 
			
		||||
        "diffhook": "vglzi6t4gsumnilv27r27no7rs3vgs75",
 | 
			
		||||
        "commithook": "znkyfflbcia5gviqx5ybad7s6uyfywxi"
 | 
			
		||||
    },
 | 
			
		||||
    "irc": {
 | 
			
		||||
        "host": "irc.freenode.net",
 | 
			
		||||
        "port": "6697",
 | 
			
		||||
        "username": "someusername",
 | 
			
		||||
        "password": "somepassword",
 | 
			
		||||
        "channel": "#somechannel"
 | 
			
		||||
    },
 | 
			
		||||
    "launchpad": {
 | 
			
		||||
        "application": "lugito",
 | 
			
		||||
        "staging": "production",
 | 
			
		||||
        "version": "devel",
 | 
			
		||||
        "supported_versions": ["Cosmic", "Bionic", "Xenial", "Trusty"]
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										32
									
								
								tests/.lugitorc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								tests/.lugitorc
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
[phabricator]
 | 
			
		||||
host = http://127.0.0.1:9091/api/
 | 
			
		||||
token = api-nojs2ip33hmp4zn6u6cf72w7d6yh
 | 
			
		||||
 | 
			
		||||
[phabricator.hooks]
 | 
			
		||||
diffhook = vglzi6t4gsumnilv27r27no7rs3vgs75
 | 
			
		||||
commithook = znkyfflbcia5gviqx5ybad7s6uyfywxi
 | 
			
		||||
 | 
			
		||||
[connector.irc]
 | 
			
		||||
host = irc.freenode.net
 | 
			
		||||
port  = 6697
 | 
			
		||||
username = someusername
 | 
			
		||||
password = somepassword
 | 
			
		||||
channel = #somechannel
 | 
			
		||||
 | 
			
		||||
[connector.launchpad]
 | 
			
		||||
application = lugito
 | 
			
		||||
staging = production
 | 
			
		||||
version = devel
 | 
			
		||||
supported_versions =
 | 
			
		||||
    Cosmic
 | 
			
		||||
    Bionic
 | 
			
		||||
    Xenial
 | 
			
		||||
    Trusty
 | 
			
		||||
 | 
			
		||||
[connector.launchpad.package_names]
 | 
			
		||||
rDEFAULTSETTINGS = lubuntu-default-settings
 | 
			
		||||
rART = lubuntu-artwork
 | 
			
		||||
rCALASETTINGS = calamares-settings-ubuntu
 | 
			
		||||
rQTERMINALPACKAGING = qterminal
 | 
			
		||||
rLXQTCONFIGPACKAGING = lxqt-config
 | 
			
		||||
rNMTRAYPACKAGING = nm-tray
 | 
			
		||||
							
								
								
									
										23
									
								
								tests/.lugitorc_no_host
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/.lugitorc_no_host
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
[phabricator]
 | 
			
		||||
token = api-nojs2ip33hmp4zn6u6cf72w7d6yh
 | 
			
		||||
 | 
			
		||||
[phabricator.hooks]
 | 
			
		||||
diffhook = vglzi6t4gsumnilv27r27no7rs3vgs75
 | 
			
		||||
commithook = znkyfflbcia5gviqx5ybad7s6uyfywxi
 | 
			
		||||
 | 
			
		||||
[connector.irc]
 | 
			
		||||
host = irc.freenode.net
 | 
			
		||||
port  = 6697
 | 
			
		||||
username = someusername
 | 
			
		||||
password = somepassword
 | 
			
		||||
channel = #somechannel
 | 
			
		||||
 | 
			
		||||
[connector.launchpad]
 | 
			
		||||
application = lugito
 | 
			
		||||
staging = production
 | 
			
		||||
version = devel
 | 
			
		||||
supported_versions =
 | 
			
		||||
    Cosmic
 | 
			
		||||
    Bionic
 | 
			
		||||
    Xenial
 | 
			
		||||
    Trusty
 | 
			
		||||
							
								
								
									
										20
									
								
								tests/.lugitorc_no_phab
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								tests/.lugitorc_no_phab
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
[phabricator.hooks]
 | 
			
		||||
diffhook = vglzi6t4gsumnilv27r27no7rs3vgs75
 | 
			
		||||
commithook = znkyfflbcia5gviqx5ybad7s6uyfywxi
 | 
			
		||||
 | 
			
		||||
[connector.irc]
 | 
			
		||||
host = irc.freenode.net
 | 
			
		||||
port  = 6697
 | 
			
		||||
username = someusername
 | 
			
		||||
password = somepassword
 | 
			
		||||
channel = #somechannel
 | 
			
		||||
 | 
			
		||||
[connector.launchpad]
 | 
			
		||||
application = lugito
 | 
			
		||||
staging = production
 | 
			
		||||
version = devel
 | 
			
		||||
supported_versions =
 | 
			
		||||
    Cosmic
 | 
			
		||||
    Bionic
 | 
			
		||||
    Xenial
 | 
			
		||||
    Trusty
 | 
			
		||||
							
								
								
									
										23
									
								
								tests/.lugitorc_no_token
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/.lugitorc_no_token
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,23 @@
 | 
			
		||||
[phabricator]
 | 
			
		||||
host = http://127.0.0.1/api/
 | 
			
		||||
 | 
			
		||||
[phabricator.hooks]
 | 
			
		||||
diffhook = vglzi6t4gsumnilv27r27no7rs3vgs75
 | 
			
		||||
commithook = znkyfflbcia5gviqx5ybad7s6uyfywxi
 | 
			
		||||
 | 
			
		||||
[connector.irc]
 | 
			
		||||
host = irc.freenode.net
 | 
			
		||||
port  = 6697
 | 
			
		||||
username = someusername
 | 
			
		||||
password = somepassword
 | 
			
		||||
channel = #somechannel
 | 
			
		||||
 | 
			
		||||
[connector.launchpad]
 | 
			
		||||
application = lugito
 | 
			
		||||
staging = production
 | 
			
		||||
version = devel
 | 
			
		||||
supported_versions =
 | 
			
		||||
    Cosmic
 | 
			
		||||
    Bionic
 | 
			
		||||
    Xenial
 | 
			
		||||
    Trusty
 | 
			
		||||
							
								
								
									
										1
									
								
								tests/lugito.ini
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/lugito.ini
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
[lugito]
 | 
			
		||||
							
								
								
									
										114
									
								
								tests/test_config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								tests/test_config.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,114 @@
 | 
			
		||||
#! /usr/bin/env python
 | 
			
		||||
# -*- coding: utf-8 -*-
 | 
			
		||||
# S.D.G
 | 
			
		||||
 | 
			
		||||
"""Test config values
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
:author: Ben Johnston
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
# Imports
 | 
			
		||||
import os
 | 
			
		||||
import pytest
 | 
			
		||||
import lugito.config
 | 
			
		||||
 | 
			
		||||
TEST_FILE = os.path.join(
 | 
			
		||||
    os.path.dirname(__file__),
 | 
			
		||||
    '.lugitorc')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_FILE_NO_PHAB = os.path.join(
 | 
			
		||||
    os.path.dirname(__file__),
 | 
			
		||||
    '.lugitorc_no_phab')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_FILE_NO_HOST = os.path.join(
 | 
			
		||||
    os.path.dirname(__file__),
 | 
			
		||||
    '.lugitorc_no_host')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST_FILE_NO_TOKEN = os.path.join(
 | 
			
		||||
    os.path.dirname(__file__),
 | 
			
		||||
    '.lugitorc_no_token')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_loading_config_hooks():
 | 
			
		||||
    """Test loading config"""
 | 
			
		||||
 | 
			
		||||
    lugito.config.update_config(TEST_FILE)
 | 
			
		||||
    CONFIG = lugito.config.CONFIG
 | 
			
		||||
 | 
			
		||||
    assert(CONFIG['phabricator']['host'] == 'http://127.0.0.1:9091/api/')
 | 
			
		||||
    assert(CONFIG['phabricator']['token'] == 'api-nojs2ip33hmp4zn6u6cf72w7d6yh')
 | 
			
		||||
 | 
			
		||||
    # Hooks
 | 
			
		||||
    assert(CONFIG['phabricator']['hooks']['diffhook'] ==\
 | 
			
		||||
        'vglzi6t4gsumnilv27r27no7rs3vgs75')
 | 
			
		||||
    assert(CONFIG['phabricator']['hooks']['commithook'] ==\
 | 
			
		||||
        'znkyfflbcia5gviqx5ybad7s6uyfywxi')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_loading_config_connectors():
 | 
			
		||||
    """Test loading config connectors"""
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    lugito.config.update_config(TEST_FILE)
 | 
			
		||||
    CONFIG = lugito.config.CONFIG
 | 
			
		||||
 | 
			
		||||
    # Connectors
 | 
			
		||||
    assert(CONFIG['connectors']['irc'] == {
 | 
			
		||||
        'host': 'irc.freenode.net',
 | 
			
		||||
        'port': '6697',
 | 
			
		||||
        'username': 'someusername',
 | 
			
		||||
        'password':'somepassword',
 | 
			
		||||
        'channel': '#somechannel',
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    if not (CONFIG['connectors']['launchpad'] == {
 | 
			
		||||
        'application': 'lugito',
 | 
			
		||||
        'staging': 'production',
 | 
			
		||||
        'version': 'devel',
 | 
			
		||||
        'supported_versions': ['Cosmic', 'Bionic', 'Xenial', 'Trusty'],
 | 
			
		||||
        'package_names': {
 | 
			
		||||
            'rDEFAULTSETTINGS': 'lubuntu-default-settings',
 | 
			
		||||
            'rART': 'lubuntu-artwork',
 | 
			
		||||
            'rCALASETTINGS': 'calamares-settings-ubuntu',
 | 
			
		||||
            'rQTERMINALPACKAGING': 'qterminal',
 | 
			
		||||
            'rLXQTCONFIGPACKAGING': 'lxqt-config',
 | 
			
		||||
            'rNMTRAYPACKAGING': 'nm-tray',
 | 
			
		||||
        },
 | 
			
		||||
        }):
 | 
			
		||||
        import pdb;pdb.set_trace()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_load_config_no_phab():
 | 
			
		||||
    """Test loading config to load phabricator"""
 | 
			
		||||
 | 
			
		||||
    with pytest.raises(ValueError) as err:
 | 
			
		||||
 | 
			
		||||
        lugito.config.update_config(TEST_FILE_NO_PHAB)
 | 
			
		||||
 | 
			
		||||
        assert('phabricator section missing from config file' in str(err))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_load_config_no_host():
 | 
			
		||||
    """Test loading config to load phabricator"""
 | 
			
		||||
 | 
			
		||||
    with pytest.raises(ValueError) as err:
 | 
			
		||||
        lugito.config.update_config(TEST_FILE_NO_HOST)
 | 
			
		||||
 | 
			
		||||
        assert('host value missing from phabricator section config file' in str(err))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_load_config_no_token():
 | 
			
		||||
    """Test loading config to load phabricator"""
 | 
			
		||||
 | 
			
		||||
    with pytest.raises(ValueError) as err:
 | 
			
		||||
 | 
			
		||||
        lugito.config.update_config(TEST_FILE_NO_TOKEN)
 | 
			
		||||
 | 
			
		||||
        assert('host value missing from phabricator conffig file' in str(err))
 | 
			
		||||
@ -10,25 +10,49 @@ Test IRC connector
 | 
			
		||||
import os
 | 
			
		||||
import json
 | 
			
		||||
import phabricator
 | 
			
		||||
from lugito import IRCConnector
 | 
			
		||||
from unittest.mock import MagicMock
 | 
			
		||||
import lugito
 | 
			
		||||
import pytest
 | 
			
		||||
from lugito.connectors import irc
 | 
			
		||||
# docEbrown - 20181120
 | 
			
		||||
# There is a bug in inspect.unwrap preventing the import of call directly
 | 
			
		||||
import unittest.mock
 | 
			
		||||
from unittest.mock import MagicMock, patch
 | 
			
		||||
 | 
			
		||||
# Setup ###############################################################
 | 
			
		||||
 | 
			
		||||
TEST_DIR = os.path.dirname(__file__)
 | 
			
		||||
lugito.config.CONFIG = {
 | 
			
		||||
    'phabricator': {
 | 
			
		||||
        'host': 'http://127.0.0.1:9091/api/',
 | 
			
		||||
        'token': 'api-nojs2ip33hmp4zn6u6cf72w7d6yh',
 | 
			
		||||
        'hooks': {
 | 
			
		||||
            'diffhook': 'vglzi6t4gsumnilv27r27no7rs3vgs75',
 | 
			
		||||
            'commithook': 'znkyfflbcia5gviqx5ybad7s6uyfywxi',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    'connectors': {
 | 
			
		||||
        'irc': {
 | 
			
		||||
            'host': 'irc.freenode.net',
 | 
			
		||||
            'port': '6697',
 | 
			
		||||
            'username': 'someusername',
 | 
			
		||||
            'password': 'somepassword',
 | 
			
		||||
            'channel': '#somechannel',
 | 
			
		||||
        },
 | 
			
		||||
    'launchpad': {
 | 
			
		||||
        'application': 'lugito',
 | 
			
		||||
        'staging': 'production',
 | 
			
		||||
        'version': 'devel',
 | 
			
		||||
        'supported_versions': ['Cosmic', 'Bionic', 'Xenial', 'Trusty'],
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Force phabricator to use the ./tests/.arcconfig file
 | 
			
		||||
TEST_CONFIG = os.path.join(TEST_DIR, '.arcconfig')
 | 
			
		||||
 | 
			
		||||
with open(TEST_CONFIG, 'r') as f:
 | 
			
		||||
    phabricator.ARCRC = json.load(f)
 | 
			
		||||
 | 
			
		||||
# Tests ###############################################################
 | 
			
		||||
 | 
			
		||||
def test_init():
 | 
			
		||||
    """Test initialise irc connector"""
 | 
			
		||||
 | 
			
		||||
    obj = IRCConnector()
 | 
			
		||||
    obj = irc()
 | 
			
		||||
 | 
			
		||||
    assert('irc.freenode.net' == obj.host)
 | 
			
		||||
    assert(6697 == obj.port)
 | 
			
		||||
@ -38,12 +62,179 @@ def test_init():
 | 
			
		||||
    assert('http://127.0.0.1:9091/' == obj.phab_host)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_connect():
 | 
			
		||||
@patch('phabricator.Phabricator')
 | 
			
		||||
def test_connect(phab_mock):
 | 
			
		||||
    """Test initial connection"""
 | 
			
		||||
 | 
			
		||||
    obj = IRCConnector()
 | 
			
		||||
    obj = irc()
 | 
			
		||||
 | 
			
		||||
    obj._socket_conn = MagicMock()
 | 
			
		||||
    assert(phab_mock.is_called())
 | 
			
		||||
 | 
			
		||||
#    obj.conn.recv = MagicMock(side_effect=[
 | 
			
		||||
 | 
			
		||||
@patch('phabricator.Phabricator')
 | 
			
		||||
def test_send(phab_mock):
 | 
			
		||||
    """Test sending a message"""
 | 
			
		||||
 | 
			
		||||
    obj = irc()
 | 
			
		||||
    obj.send_notice = MagicMock()
 | 
			
		||||
 | 
			
		||||
    objectstr = "objectstr"
 | 
			
		||||
    who = "who"
 | 
			
		||||
    body = "body"
 | 
			
		||||
    link = "link"
 | 
			
		||||
 | 
			
		||||
    obj.send(objectstr, who, body, link)
 | 
			
		||||
 | 
			
		||||
    obj.send_notice.assert_called_with(
 | 
			
		||||
        '\x033[\x03\x0313objectstr\x03\x033]\x03 \x0315who\x03 body: \x032link\x03')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@patch('phabricator.Phabricator')
 | 
			
		||||
def test_send_kwargs(phab_mock):
 | 
			
		||||
    """Test sending a message - kwargs"""
 | 
			
		||||
 | 
			
		||||
    obj = irc()
 | 
			
		||||
    obj.send_notice = MagicMock()
 | 
			
		||||
 | 
			
		||||
    objectstr = "objectstr"
 | 
			
		||||
    who = "who"
 | 
			
		||||
    body = "body"
 | 
			
		||||
    link = "link"
 | 
			
		||||
 | 
			
		||||
    obj.send(objectstr=objectstr, who=who, body=body, link=link)
 | 
			
		||||
 | 
			
		||||
    obj.send_notice.assert_called_with(
 | 
			
		||||
        '\x033[\x03\x0313objectstr\x03\x033]\x03 \x0315who\x03 body: \x032link\x03')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_connect():
 | 
			
		||||
    """Test connect"""
 | 
			
		||||
 | 
			
		||||
    obj = irc(sleep_delay=0)
 | 
			
		||||
 | 
			
		||||
    obj._send_raw = MagicMock()
 | 
			
		||||
    obj._setup_connection = MagicMock()
 | 
			
		||||
    obj.conn = MagicMock()
 | 
			
		||||
 | 
			
		||||
    obj.conn.recv.side_effect = [
 | 
			
		||||
        b'No Ident response',
 | 
			
		||||
        b'You are now identified',
 | 
			
		||||
        b'477',
 | 
			
		||||
        b'433',
 | 
			
		||||
        b'PING: something',
 | 
			
		||||
        b'366',
 | 
			
		||||
    ]
 | 
			
		||||
 | 
			
		||||
    obj.connect()
 | 
			
		||||
 | 
			
		||||
    # No Ident response results
 | 
			
		||||
    assert(unittest.mock.call('NICK someusername1\r\n') in\
 | 
			
		||||
        obj._send_raw.call_args_list)
 | 
			
		||||
    assert(unittest.mock.call('USER someusername * * :someusername\r\n') in\
 | 
			
		||||
        obj._send_raw.call_args_list)
 | 
			
		||||
    assert(unittest.mock.call('PRIVMSG nickserv :identify someusername'\
 | 
			
		||||
        ' somepassword\r\n') in obj._send_raw.call_args_list)
 | 
			
		||||
 | 
			
		||||
    # Now identified / 477
 | 
			
		||||
    assert(unittest.mock.call('JOIN #somechannel\r\n') in\
 | 
			
		||||
        obj._send_raw.call_args_list)
 | 
			
		||||
 | 
			
		||||
    # 433
 | 
			
		||||
    assert(unittest.mock.call('NICK someusername1\r\n') in\
 | 
			
		||||
        obj._send_raw.call_args_list)
 | 
			
		||||
    assert(unittest.mock.call('USER someusername1 * * :someusername1\r\n') in\
 | 
			
		||||
        obj._send_raw.call_args_list)
 | 
			
		||||
 | 
			
		||||
    # Ping
 | 
			
		||||
    assert(unittest.mock.call('PONG : something\r\n') in\
 | 
			
		||||
        obj._send_raw.call_args_list)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# docEbrown - 20181120
 | 
			
		||||
# Address including anchors in reference
 | 
			
		||||
# https://phab.lubuntu.me/T88#3230
 | 
			
		||||
def test_get_task_info_with_anchor():
 | 
			
		||||
    """Test getting task info with anchor"""
 | 
			
		||||
 | 
			
		||||
    obj = irc()
 | 
			
		||||
 | 
			
		||||
    obj.send_notice = MagicMock()
 | 
			
		||||
    obj.phab = MagicMock()
 | 
			
		||||
    obj.phab.maniphest.info = MagicMock(
 | 
			
		||||
        return_value={
 | 
			
		||||
            'priorityColor': 'pink',
 | 
			
		||||
            'statusName': 'Open',
 | 
			
		||||
            'title': 'Fix shortcuts related to Super key',
 | 
			
		||||
            'uri': 'https://phab.lubuntu.me/T154'
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    link_with_anchor = 'https://phab.lubuntu.me/T154#3228'
 | 
			
		||||
    obj.get_task_info(link_with_anchor)
 | 
			
		||||
 | 
			
		||||
    assert(unittest.mock.call(task_id=154) in\
 | 
			
		||||
        obj.phab.maniphest.info.call_args_list)
 | 
			
		||||
    assert(obj.send_notice.call_args == \
 | 
			
		||||
        unittest.mock.call('\x033[\x03\x035Unbreak Now!, Open\x03\x033]\x03 '
 | 
			
		||||
            'Fix shortcuts related to Super key: '\
 | 
			
		||||
            '\x032https://phab.lubuntu.me/T154#3228\x03'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_diff_info_with_anchor():
 | 
			
		||||
    """Test getting diff info with anchor"""
 | 
			
		||||
 | 
			
		||||
    obj = irc()
 | 
			
		||||
 | 
			
		||||
    obj.send_notice = MagicMock()
 | 
			
		||||
    obj.phab = MagicMock()
 | 
			
		||||
    obj.phab.differential.query = MagicMock(
 | 
			
		||||
        return_value=[{
 | 
			
		||||
            'statusName': 'Closed',
 | 
			
		||||
            'title': 'Some diff title',
 | 
			
		||||
            'uri': 'https://phab.lubuntu.me/D24'
 | 
			
		||||
        },]
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    link_with_anchor = 'https://phab.lubuntu.me/D24#123'
 | 
			
		||||
    obj.get_task_info(link_with_anchor)
 | 
			
		||||
 | 
			
		||||
    assert(unittest.mock.call(ids=[24]) in\
 | 
			
		||||
        obj.phab.differential.query.call_args_list)
 | 
			
		||||
    assert(obj.send_notice.call_args == \
 | 
			
		||||
        unittest.mock.call('\x033[\x03Closed\x03\x033]\x03 '
 | 
			
		||||
            'Some diff title: '\
 | 
			
		||||
            '\x032https://phab.lubuntu.me/D24#123\x03'))
 | 
			
		||||
 | 
			
		||||
def test_get_task_info_with_error_anchor():
 | 
			
		||||
    """Test getting task info with anchor"""
 | 
			
		||||
 | 
			
		||||
    obj = irc()
 | 
			
		||||
 | 
			
		||||
    obj.send_notice = MagicMock()
 | 
			
		||||
    obj.phab = MagicMock()
 | 
			
		||||
    obj.phab.maniphest.info = MagicMock(side_effect=ValueError(''))
 | 
			
		||||
 | 
			
		||||
    link_with_anchor = 'https://phab.lubuntu.me/T154#3228'
 | 
			
		||||
 | 
			
		||||
    obj.get_task_info(link_with_anchor)
 | 
			
		||||
 | 
			
		||||
    assert(obj.send_notice.call_args ==
 | 
			
		||||
        unittest.mock.call('\x034Error: https://phab.lubuntu.me/T154#3228'\
 | 
			
		||||
            ' is an invalid task reference.\x03'))
 | 
			
		||||
 | 
			
		||||
def test_get_task_info_with_error_no_anchor():
 | 
			
		||||
    """Test getting task info with no anchor"""
 | 
			
		||||
 | 
			
		||||
    obj = irc()
 | 
			
		||||
 | 
			
		||||
    obj.send_notice = MagicMock()
 | 
			
		||||
    obj.phab = MagicMock()
 | 
			
		||||
    obj.phab.maniphest.info = MagicMock(side_effect=ValueError(''))
 | 
			
		||||
 | 
			
		||||
    link_with_anchor = 'https://phab.lubuntu.me/T154'
 | 
			
		||||
 | 
			
		||||
    obj.get_task_info(link_with_anchor)
 | 
			
		||||
 | 
			
		||||
    assert(obj.send_notice.call_args ==
 | 
			
		||||
        unittest.mock.call('\x034Error: https://phab.lubuntu.me/T154'\
 | 
			
		||||
            ' is an invalid task reference.\x03'))
 | 
			
		||||
 | 
			
		||||
@ -9,19 +9,90 @@ Test launchpad connector
 | 
			
		||||
# Imports
 | 
			
		||||
import json
 | 
			
		||||
import phabricator
 | 
			
		||||
from lugito.connectors.launchpad import LPConnector
 | 
			
		||||
import lugito
 | 
			
		||||
from lugito.connectors import launchpad
 | 
			
		||||
 | 
			
		||||
# Setup ###############################################################
 | 
			
		||||
 | 
			
		||||
TEST_DIR = os.path.dirname(__file__)
 | 
			
		||||
lugito.config.CONFIG = {
 | 
			
		||||
    'phabricator': {
 | 
			
		||||
        'host': 'http://127.0.0.1:9091/api/',
 | 
			
		||||
        'token': 'api-nojs2ip33hmp4zn6u6cf72w7d6yh',
 | 
			
		||||
        'hooks': {
 | 
			
		||||
            'diffhook': 'vglzi6t4gsumnilv27r27no7rs3vgs75',
 | 
			
		||||
            'commithook': 'znkyfflbcia5gviqx5ybad7s6uyfywxi',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    'connectors': {
 | 
			
		||||
        'irc': {
 | 
			
		||||
            'host': 'irc.freenode.net',
 | 
			
		||||
            'port': '6697',
 | 
			
		||||
            'username': 'someusername',
 | 
			
		||||
            'password': 'somepassword',
 | 
			
		||||
            'channel': '#somechannel',
 | 
			
		||||
        },
 | 
			
		||||
    'launchpad': {
 | 
			
		||||
        'application': 'lugito',
 | 
			
		||||
        'staging': 'production',
 | 
			
		||||
        'version': 'devel',
 | 
			
		||||
        'supported_versions': ['Cosmic', 'Bionic', 'Xenial', 'Trusty'],
 | 
			
		||||
        'package_names': {
 | 
			
		||||
            'rDEFAULTSETTINGS': 'lubuntu-default-settings',
 | 
			
		||||
            'rART': 'lubuntu-artwork',
 | 
			
		||||
            'rCALASETTINGS': 'calamares-settings-ubuntu',
 | 
			
		||||
            'rQTERMINALPACKAGING': 'qterminal',
 | 
			
		||||
            'rLXQTCONFIGPACKAGING': 'lxqt-config',
 | 
			
		||||
            'rNMTRAYPACKAGING': 'nm-tray',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# Force phabricator to use the ./tests/.arcconfig file
 | 
			
		||||
TEST_CONFIG = os.path.join(TEST_DIR, '.arcconfig')
 | 
			
		||||
 | 
			
		||||
with open(TEST_CONFIG, 'r') as f:
 | 
			
		||||
    phabricator.ARCRC = json.load(f)
 | 
			
		||||
 | 
			
		||||
# Tests ###############################################################
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_init()
 | 
			
		||||
def test_init():
 | 
			
		||||
    """Test initialising LPConnector"""
 | 
			
		||||
 | 
			
		||||
    obj = launchpad()
 | 
			
		||||
 | 
			
		||||
    assert(obj.application == "lugito")
 | 
			
		||||
    assert(obj.staging == "production")
 | 
			
		||||
    assert(obj.version == "devel")
 | 
			
		||||
    assert(obj.supported_vers == ["Cosmic", "Bionic", "Xenial", "Trusty"])
 | 
			
		||||
    assert(obj.package_names == {
 | 
			
		||||
        'rDEFAULTSETTINGS': 'lubuntu-default-settings',
 | 
			
		||||
        'rART': 'lubuntu-artwork',
 | 
			
		||||
        'rCALASETTINGS': 'calamares-settings-ubuntu',
 | 
			
		||||
        'rQTERMINALPACKAGING': 'qterminal',
 | 
			
		||||
        'rLXQTCONFIGPACKAGING': 'lxqt-config',
 | 
			
		||||
        'rNMTRAYPACKAGING': 'nm-tray',
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_package_name():
 | 
			
		||||
    """Test get package name"""
 | 
			
		||||
 | 
			
		||||
    obj = launchpad()
 | 
			
		||||
 | 
			
		||||
    assert(obj.get_package_name('rART') == 'lubuntu-artwork')
 | 
			
		||||
    assert(obj.get_package_name('rT') is None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_package_name():
 | 
			
		||||
    """Test getting package name"""
 | 
			
		||||
 | 
			
		||||
    obj = launchpad()
 | 
			
		||||
 | 
			
		||||
    assert(obj.get_package_name('rNMTRAYPACKAGING') == 'nm-tray')
 | 
			
		||||
    assert(obj.get_package_name('rNMTRKAGING') is None)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_get_bugs_list():
 | 
			
		||||
    """Test getting buglist"""
 | 
			
		||||
 | 
			
		||||
    obj = launchpad()
 | 
			
		||||
 | 
			
		||||
    assert(obj.get_bugs_list("lp: #1234") == ['1234'])
 | 
			
		||||
    assert(obj.get_bugs_list("#1234") == [])
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,7 @@ import pytest
 | 
			
		||||
import phabricator
 | 
			
		||||
import json
 | 
			
		||||
import http
 | 
			
		||||
import lugito
 | 
			
		||||
from lugito import Lugito
 | 
			
		||||
from unittest.mock import MagicMock
 | 
			
		||||
 | 
			
		||||
@ -19,11 +20,33 @@ from unittest.mock import MagicMock
 | 
			
		||||
 | 
			
		||||
TEST_DIR = os.path.dirname(__file__)
 | 
			
		||||
 | 
			
		||||
# Force phabricator to use the ./tests/.arcconfig file
 | 
			
		||||
TEST_CONFIG = os.path.join(TEST_DIR, '.arcconfig')
 | 
			
		||||
# Apply default values
 | 
			
		||||
lugito.config.CONFIG = {
 | 
			
		||||
    'phabricator': {
 | 
			
		||||
        'host': 'http://127.0.0.1:9091/api/',
 | 
			
		||||
        'token': 'api-nojs2ip33hmp4zn6u6cf72w7d6yh',
 | 
			
		||||
        'hooks': {
 | 
			
		||||
            'diffhook': 'vglzi6t4gsumnilv27r27no7rs3vgs75',
 | 
			
		||||
            'commithook': 'znkyfflbcia5gviqx5ybad7s6uyfywxi',
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    'connectors': {
 | 
			
		||||
        'irc': {
 | 
			
		||||
            'host': 'irc.freenode.net',
 | 
			
		||||
            'port': '6697',
 | 
			
		||||
            'username': 'someusername',
 | 
			
		||||
            'password': 'somepassword',
 | 
			
		||||
            'channel': '#somechannel',
 | 
			
		||||
        },
 | 
			
		||||
    'launchpad': {
 | 
			
		||||
        'application': 'lugito',
 | 
			
		||||
        'staging': 'production',
 | 
			
		||||
        'version': 'devel',
 | 
			
		||||
        'supported_versions': ['Cosmic', 'Bionic', 'Xenial', 'Trusty'],
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
with open(TEST_CONFIG, 'r') as f:
 | 
			
		||||
    phabricator.ARCRC = json.load(f)
 | 
			
		||||
 | 
			
		||||
# Pre-prepared request
 | 
			
		||||
FAKE_REQUEST = os.path.join(TEST_DIR, 'request.json')
 | 
			
		||||
@ -56,10 +79,12 @@ def test_init():
 | 
			
		||||
        'utf-8'))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_validate_HMAC():
 | 
			
		||||
def test_validate_request():
 | 
			
		||||
    """Test validating HMAC"""
 | 
			
		||||
 | 
			
		||||
    obj = Lugito()
 | 
			
		||||
    obj.phab = MagicMock()
 | 
			
		||||
    obj.phab.transaction.search = MagicMock()
 | 
			
		||||
 | 
			
		||||
    request_mock = MagicMock()
 | 
			
		||||
 | 
			
		||||
@ -71,7 +96,8 @@ def test_validate_HMAC():
 | 
			
		||||
        "a8f636f03ed4464ddb398ea873ffab409d941f87396f28fa9d22bb58cfbedc9f"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assert(obj.validate_HMAC('diffhook', request_mock))
 | 
			
		||||
    assert(obj.validate_request('diffhook', request_mock))
 | 
			
		||||
    assert(obj.phab.transaction.search.is_called())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_invalid_HMAC():
 | 
			
		||||
@ -89,7 +115,7 @@ def test_invalid_HMAC():
 | 
			
		||||
        "a8f6364464ddb398ea873ffab409d941f87396f28fa9d22bb58cfbedc9f"
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    assert(not obj.validate_HMAC('diffhook', request_mock))
 | 
			
		||||
    assert(not obj.validate_request('diffhook', request_mock))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def test_author_fullname():
 | 
			
		||||
@ -141,8 +167,6 @@ def test_get_object_type():
 | 
			
		||||
    with open(FAKE_REQ_DATA, 'r') as f:
 | 
			
		||||
        obj.request_data = json.load(f)
 | 
			
		||||
 | 
			
		||||
    obj._transaction_search()
 | 
			
		||||
 | 
			
		||||
    assert(obj.get_object_type() == 'DREV')
 | 
			
		||||
 | 
			
		||||
def test_is_new_object_false():
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user