Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{ pkgs ? (import <nixpkgs> {}), pythonPackages ? "python35Packages" }:
let
basePythonPackages = with builtins; if isAttrs pythonPackages
then pythonPackages
else getAttr pythonPackages pkgs;

inherit (pkgs.lib) fix extends;
elem = builtins.elem;
basename = path: with pkgs.lib; last (splitString "/" path);
startsWith = prefix: full: let
actualPrefix = builtins.substring 0 (builtins.stringLength prefix) full;
in actualPrefix == prefix;

src-filter = path: type: with pkgs.lib;
let
ext = last (splitString "." path);
in
!elem (basename path) [".git" "__pycache__" ".eggs"] &&
!elem ext ["egg-info" "pyc"] &&
!startsWith "result" path;

gutter-src = builtins.filterSource src-filter ./.;

localOverrides = self: super: {
gutter = super.gutter.override (attrs: {
src = gutter-src;
});
durabledict = super.durabledict.override (attrs: {
# Needs correct import from durabledict.redis, >0.9.2
src = pkgs.fetchurl {
url = https://github.com/disqus/durabledict/archive/17dfccdcee18da4df7c9dbc0557dc27a4ea6f3cc.zip;
sha256 = "16xmsa57lwzd53s80id73722c0bj6378lbbfpzd6kks0rirkfpcv";
};
});
traceback2 = super.traceback2.override (attrs: {
buildInputs = attrs.buildInputs ++ (
with super; [pbr]);
});

linecache2 = super.linecache2.override (attrs: {
buildInputs = attrs.buildInputs ++ (
with super; [pbr]);
});
};

pythonPackagesWithLocals = self: basePythonPackages.override (a: {
inherit self;
})
// (scopedImport {
self = self;
super = basePythonPackages;
inherit pkgs;
inherit (pkgs) fetchurl fetchgit;
} ./python-packages.nix);

myPythonPackages =
(fix
(extends localOverrides
pythonPackagesWithLocals));

in myPythonPackages.gutter
2 changes: 1 addition & 1 deletion gutter/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

try:
VERSION = __import__('pkg_resources').get_distribution('gutter').version
except Exception, e:
except Exception as e:
VERSION = 'unknown'

CLIENT_CACHE = {}
Expand Down
4 changes: 2 additions & 2 deletions gutter/client/arguments/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from functools import partial

from base import Container, argument # noqa
import variables
from . import variables
from .base import Container, argument # noqa

Value = partial(argument, variables.Value)
Boolean = partial(argument, variables.Boolean)
Expand Down
6 changes: 4 additions & 2 deletions gutter/client/arguments/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from types import NoneType
import six

from gutter.client.compat import NoneType


class classproperty(object):
Expand All @@ -13,7 +15,7 @@ def __get__(self, instance, owner):
class argument(object):

def __init__(self, variable, getter):
if issubclass(type(getter), basestring):
if issubclass(type(getter), six.string_types):
self.getter = lambda self: getattr(self.input, getter)
else:
self.getter = getter
Expand Down
23 changes: 23 additions & 0 deletions gutter/client/arguments/variables.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ def func(self, *args, **kwargs):
__hash__ = __proxy_to_value_method('__hash__')
__nonzero__ = __proxy_to_value_method('__nonzero__')

# PY3
__lt__ = __proxy_to_value_method('__lt__')
__le__ = __proxy_to_value_method('__le__')
__gt__ = __proxy_to_value_method('__gt__')
__ge__ = __proxy_to_value_method('__ge__')
__eq__ = __proxy_to_value_method('__eq__')
__ne__ = __proxy_to_value_method('__ne__')
__bool__ = __proxy_to_value_method('__bool__')

@staticmethod
def to_python(value):
return value
Expand Down Expand Up @@ -62,9 +71,23 @@ class String(Base):
def __cmp__(self, other):
return cmp(self.value, other)

def __lt__(self, other):
return self.value < other

def __gt__(self, other):
return self.value > other

def __eq__(self, other):
return self.value == other

def __hash__(self):
return hash(self.value)

def __nonzero__(self, *args, **kwargs):
return bool(self.value)

__bool__ = __nonzero__

@staticmethod
def to_python(value):
return str(value)
22 changes: 22 additions & 0 deletions gutter/client/compat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"""
Python 3 compatibility.
"""

import six


if six.PY3:
import unittest
ifilter = filter
else:
import unittest2 as unittest
from itertools import ifilter


NoneType = type(None)


class TestCaseMixin(object):
if six.PY3:
def assertItemsEqual(self, actual, expected, msg=None):
self.assertCountEqual(actual, expected, msg=None)
50 changes: 48 additions & 2 deletions gutter/client/encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,59 @@


class JsonPickleEncoding(PickleEncoding):

ENCODING = 'utf-8'

@staticmethod
def encode(data):
return pickle.dumps(data)
json_string = pickle.dumps(data)
return json_string.encode(JsonPickleEncoding.ENCODING)

@staticmethod
def decode(data):
try:
return pickle.loads(data)
json_string = data.decode(JsonPickleEncoding.ENCODING)
return pickle.loads(json_string)
except Exception:
return PickleEncoding.decode(data)


class KeyEncoderProxy:
"""
Helps to ensure that keys are encoded and decoded.

This is mainly useful on Python3 where we use text values as the key but on
some storages like redis we can only store byte values. Without a
consistent encoding switches cannot be found again, because the returned
keys are `bytes` objects instead of `str` objects.
"""

def __init__(self, storage, encoding='utf-8'):
self._encoding = encoding
self._storage = storage

def __setitem__(self, key, val):
key = key.encode(self._encoding)
self._storage[key] = val

def __delitem__(self, key):
key = key.encode(self._encoding)
del self._storage[key]

def __getitem__(self, key):
key = key.encode(self._encoding)
return self._storage[key]

def __contains__(self, key):
key = key.encode(self._encoding)
return key in self._storage

def items(self):
return (
(key.decode(self._encoding), val)
for key, val in self._storage.items())

def keys(self):
return (
key.decode(self._encoding)
for key in self._storage.keys())
13 changes: 9 additions & 4 deletions gutter/client/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@
import threading
from collections import defaultdict
from functools import partial
from itertools import ifilter

# External Libraries
import six
from gutter.client import signals
from gutter.client.compat import ifilter

DEFAULT_SEPARATOR = ':'

Expand Down Expand Up @@ -330,6 +331,9 @@ def __eq__(self, other):
self.negative is other.negative
)

# TODO: not sure if that's ok
__hash__ = object.__hash__

def call(self, inpt):
"""
Returns if the condition applies to the ``inpt``.
Expand Down Expand Up @@ -410,7 +414,7 @@ def __init__(

if namespace is None:
namespace = self.default_namespace
elif isinstance(namespace, basestring):
elif isinstance(namespace, six.string_types):
namespace = [namespace]

self.storage = storage
Expand Down Expand Up @@ -440,7 +444,7 @@ def switches(self):
List of all switches currently registered.
"""
results = [
switch for name, switch in self.storage.iteritems()
switch for name, switch in six.iteritems(self.storage)
if name.startswith(self.__joined_namespace)
]

Expand Down Expand Up @@ -491,7 +495,8 @@ def register(self, switch, signal=signals.switch_registered):
def unregister(self, switch_or_name):
switch = getattr(switch_or_name, 'name', switch_or_name)

map(self.unregister, self.get_children(switch))
for child in self.get_children(switch):
self.unregister(child)

if switch in self:
signals.switch_unregistered.call(self.switch(switch))
Expand Down
3 changes: 2 additions & 1 deletion gutter/client/testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
:copyright: (c) 2010-2012 DISQUS.
:license: Apache License 2.0, see LICENSE for more details.
"""
import six

from functools import wraps
from gutter.client import get_gutter_client
Expand Down Expand Up @@ -39,7 +40,7 @@ def __init__(self, gutter=None, **keys):
def gutter(self):
if self._gutter is None:
self._gutter = get_gutter_client()
elif isinstance(self._gutter, basestring):
elif isinstance(self._gutter, six.string_types):
self._gutter = get_gutter_client(alias=self._gutter)
return self._gutter

Expand Down
Loading