Bare bones of a notification system

This commit is contained in:
Ian Cordasco 2015-12-28 23:32:42 -06:00
parent f013698072
commit 7b2a1c157b
9 changed files with 209 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
.cache/*
.tox/*
*.pyc
*.sw*
*.egg-info

10
example.py Normal file
View file

@ -0,0 +1,10 @@
from flake8 import _trie as trie
tree = trie.Trie()
for i in range(5):
tree.add('E103', 'E103-listener-{0}'.format(i))
j = i + 1
tree.add('E1{0}3'.format(j), 'E1{0}3-listener'.format(j))
for i in range(10):
tree.add('W1{0:02d}'.format(i), 'W1{0:02d}-listener'.format(i))

1
flake8/__init__.py Normal file
View file

@ -0,0 +1 @@
__version__ = '3.0.0a1'

74
flake8/_trie.py Normal file
View file

@ -0,0 +1,74 @@
"""Independent implementation of a Trie tree."""
__all__ = ('Trie', 'TrieNode')
def _iterate_stringlike_objects(string):
for i in range(len(string)):
yield string[i:i+1]
class Trie(object):
"""The object that manages the trie nodes."""
def __init__(self):
"""Initialize an empty trie."""
self.root = TrieNode(None, None)
def add(self, path, node_data):
"""Add the node data to the path described."""
node = self.root
for prefix in _iterate_stringlike_objects(path):
child = node.find_prefix(prefix)
if child is None:
child = node.add_child(prefix, [])
node = child
node.data.append(node_data)
def find(self, path):
"""Find a node based on the path provided."""
node = self.root
for prefix in _iterate_stringlike_objects(path):
child = node.find_prefix(prefix)
if child is None:
return None
node = child
return node
class TrieNode(object):
"""The majority of the implementation details of a Trie."""
def __init__(self, prefix, data, children=None):
"""Initialize a TrieNode with data and children."""
self.children = children or {}
self.data = data
self.prefix = prefix
def __repr__(self):
"""Generate an easy to read representation of the node."""
return 'TrieNode(prefix={0}, data={1}, children={2})'.format(
self.prefix, self.data, dict(self.children)
)
def find_prefix(self, prefix):
"""Find the prefix in the children of this node.
:returns: A child matching the prefix or None.
:rtype: :class:`~TrieNode` or None
"""
return self.children.get(prefix, None)
def add_child(self, prefix, data, children=None):
"""Create and add a new child node.
:returns: The newly created node
:rtype: :class:`~TrieNode`
"""
new_node = TrieNode(prefix, data, children)
self.children[prefix] = new_node
return new_node
def traverse(self):
"""Traverse children of this node in order."""
raise NotImplementedError()

22
flake8/notifier.py Normal file
View file

@ -0,0 +1,22 @@
from flake8 import _trie
class Notifier(object):
def __init__(self):
self.listeners = _trie.Trie()
def listeners_for(self, error_code):
node = self.listeners.find(error_code)
for listener in node.data:
yield listener
if node.children:
for child in node.traverse():
for listener in child.data:
yield listener
def notify(self, error_code, *args, **kwargs):
for listener in self.listeners_for(error_code):
listener.notify(*args, **kwargs)
def register_listener(self, error_code, listener):
self.listeners.add(error_code, listener)

0
flake8/style_guide.py Normal file
View file

75
setup.py Normal file
View file

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
from __future__ import with_statement
from setuptools import setup
try:
# Work around a traceback with Nose on Python 2.6
# http://bugs.python.org/issue15881#msg170215
__import__('multiprocessing')
except ImportError:
pass
try:
# Use https://docs.python.org/3/library/unittest.mock.html
from unittest import mock
except ImportError:
# < Python 3.3
mock = None
tests_require = ['nose']
if mock is None:
tests_require += ['mock']
def get_version(fname='flake8/__init__.py'):
with open(fname) as f:
for line in f:
if line.startswith('__version__'):
return eval(line.split('=')[-1])
def get_long_description():
descr = []
for fname in ('README.rst', 'CHANGES.rst'):
with open(fname) as f:
descr.append(f.read())
return '\n\n'.join(descr)
setup(
name="flake8",
license="MIT",
version=get_version(),
description="the modular source code checker: pep8, pyflakes and co",
# long_description=get_long_description(),
author="Tarek Ziade",
author_email="tarek@ziade.org",
maintainer="Ian Cordasco",
maintainer_email="graffatcolmingov@gmail.com",
url="https://gitlab.com/pycqa/flake8",
packages=["flake8"],
install_requires=[
"pyflakes >= 0.8.1, < 1.1",
"pep8 >= 1.5.7, != 1.6.0, != 1.6.1, != 1.6.2",
"mccabe >= 0.2.1, < 0.4",
],
entry_points={
'distutils.commands': ['flake8 = flake8.main:Flake8Command'],
'console_scripts': ['flake8 = flake8.main:main'],
'flake8.extension': [
'F = flake8._pyflakes:FlakesChecker',
],
},
classifiers=[
"Environment :: Console",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 3",
"Topic :: Software Development :: Libraries :: Python Modules",
"Topic :: Software Development :: Quality Assurance",
],
tests_require=tests_require,
test_suite='nose.collector',
)

14
tests/test_trie.py Normal file
View file

@ -0,0 +1,14 @@
from flake8 import _trie as trie
def test_build_tree():
tree = trie.Trie()
for i in range(5):
tree.add('E103', 'E103-listener-{0}'.format(i))
j = i + 1
tree.add('E1{0}3'.format(j), 'E1{0}3-listener'.format(j))
for i in range(10):
tree.add('W1{0:02d}'.format(i), 'W1{0:02d}-listener'.format(i))
assert tree.find('E103') is not None
assert tree.find('E200') is None

8
tox.ini Normal file
View file

@ -0,0 +1,8 @@
[tox]
envlist = py26,py27,py32,py33,py34,py35
[testenv]
deps =
pytest
commands =
py.test