3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-01 01:09:22 +01:00

Condense (deep)copy definitions into structures.CopyWrapper

This commit is contained in:
James Lu 2017-08-25 17:05:53 -07:00
parent 8c0f19422f
commit 0907f05296
2 changed files with 42 additions and 21 deletions

View File

@ -12,7 +12,6 @@ import time
import socket import socket
import ssl import ssl
import hashlib import hashlib
from copy import copy, deepcopy
import inspect import inspect
import ipaddress import ipaddress
import queue import queue
@ -480,6 +479,8 @@ class PyLinkNetworkCore(utils.DeprecatedAttributesObject, utils.CamelCaseToSnake
except AttributeError: except AttributeError:
return False return False
structures._BLACKLISTED_COPY_TYPES.append(PyLinkNetworkCore)
class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore): class PyLinkNetworkCoreWithUtils(PyLinkNetworkCore):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -1567,7 +1568,7 @@ class Server():
IrcServer = Server IrcServer = Server
class Channel(utils.DeprecatedAttributesObject, utils.CamelCaseToSnakeCase): class Channel(utils.DeprecatedAttributesObject, utils.CamelCaseToSnakeCase, structures.CopyWrapper):
"""PyLink IRC channel class.""" """PyLink IRC channel class."""
def __init__(self, irc, name=None): def __init__(self, irc, name=None):
@ -1599,22 +1600,6 @@ class Channel(utils.DeprecatedAttributesObject, utils.CamelCaseToSnakeCase):
self.users.discard(target) self.users.discard(target)
removeuser = remove_user removeuser = remove_user
def __deepcopy__(self, memo):
"""Returns a deep copy of the channel object."""
# XXX: we can't pickle IRCNetwork, so just return a reference of it.
channel_copy = copy(self)
# For everything else, create a copy.
for attr, val in self.__dict__.items():
if not isinstance(val, PyLinkNetworkCore):
setattr(channel_copy, attr, deepcopy(val))
memo[id(self)] = channel_copy
return channel_copy
def deepcopy(self):
return deepcopy(self)
def is_voice(self, uid): def is_voice(self, uid):
"""Returns whether the given user is voice in the channel.""" """Returns whether the given user is voice in the channel."""
return uid in self.prefixmodes['voice'] return uid in self.prefixmodes['voice']

View File

@ -10,10 +10,13 @@ import json
import pickle import pickle
import os import os
import threading import threading
from copy import copy, deepcopy
from .log import log from .log import log
from . import conf from . import conf
_BLACKLISTED_COPY_TYPES = []
class KeyedDefaultdict(collections.defaultdict): class KeyedDefaultdict(collections.defaultdict):
""" """
Subclass of defaultdict allowing the key to be passed to the default factory. Subclass of defaultdict allowing the key to be passed to the default factory.
@ -26,7 +29,34 @@ class KeyedDefaultdict(collections.defaultdict):
value = self[key] = self.default_factory(key) value = self[key] = self.default_factory(key)
return value return value
class CaseInsensitiveFixedSet(collections.abc.Set): class CopyWrapper():
"""
Base container class implementing copy methods.
"""
def copy(self):
"""Returns a shallow copy of this object instance."""
return copy(self)
def __deepcopy__(self, memo):
"""Returns a deep copy of the channel object."""
newobj = copy(self)
log.debug('CopyWrapper: _BLACKLISTED_COPY_TYPES = %s', _BLACKLISTED_COPY_TYPES)
for attr, val in self.__dict__.items():
# We can't pickle IRCNetwork, so just return a reference of it.
if not isinstance(val, tuple(_BLACKLISTED_COPY_TYPES)):
log.debug('CopyWrapper: copying attr %r', attr)
setattr(newobj, attr, deepcopy(val))
memo[id(self)] = newobj
return newobj
def deepcopy(self):
"""Returns a deep copy of this object instance."""
return deepcopy(self)
class CaseInsensitiveFixedSet(collections.abc.Set, CopyWrapper):
""" """
Implements a fixed set storing items case-insensitively. Implements a fixed set storing items case-insensitively.
""" """
@ -55,8 +85,8 @@ class CaseInsensitiveFixedSet(collections.abc.Set):
def __contains__(self, key): def __contains__(self, key):
return self._data.__contains__(self._keymangle(key)) return self._data.__contains__(self._keymangle(key))
def copy(self, *args, **kwargs): def __copy__(self):
return self._data.copy(*args, **kwargs) return self.__class__(data=self._data.copy())
class CaseInsensitiveDict(collections.abc.MutableMapping, CaseInsensitiveFixedSet): class CaseInsensitiveDict(collections.abc.MutableMapping, CaseInsensitiveFixedSet):
""" """
@ -92,6 +122,9 @@ class IRCCaseInsensitiveDict(CaseInsensitiveDict):
"""Converts the given key to lowercase.""" """Converts the given key to lowercase."""
return self._irc.to_lower(key) return self._irc.to_lower(key)
def __copy__(self):
return self.__class__(self._irc, data=self._data.copy())
class CaseInsensitiveSet(collections.abc.MutableSet, CaseInsensitiveFixedSet): class CaseInsensitiveSet(collections.abc.MutableSet, CaseInsensitiveFixedSet):
""" """
A mutable set storing items case insensitively. A mutable set storing items case insensitively.
@ -115,6 +148,9 @@ class IRCCaseInsensitiveSet(CaseInsensitiveSet):
"""Converts the given key to lowercase.""" """Converts the given key to lowercase."""
return self._irc.to_lower(key) return self._irc.to_lower(key)
def __copy__(self):
return self.__class__(self._irc, data=self._data.copy())
class DataStore: class DataStore:
""" """
Generic database class. Plugins should use a subclass of this such as JSONDataStore or Generic database class. Plugins should use a subclass of this such as JSONDataStore or