Browse Source

Make metaclass for lazy init objects

devel
bashmak 8 years ago
parent
commit
a4d914c7f2
  1. 10
      agent/core.py
  2. 6
      agent/mod_mikrotik.py
  3. 37
      djing/lib/decorators.py

10
agent/core.py

@ -1,4 +1,4 @@
from abc import ABCMeta, abstractmethod
from abc import ABC, abstractmethod
from typing import Iterator, Any, Tuple, Optional from typing import Iterator, Any, Tuple, Optional
from .structs import AbonStruct, TariffStruct, VectorAbon, VectorTariff, IpStruct from .structs import AbonStruct, TariffStruct, VectorAbon, VectorTariff, IpStruct
@ -15,7 +15,7 @@ class NasNetworkError(Exception):
# Communicate with NAS # Communicate with NAS
class BaseTransmitter(metaclass=ABCMeta):
class BaseTransmitter(ABC):
@abstractmethod @abstractmethod
def add_user_range(self, user_list: VectorAbon): def add_user_range(self, user_list: VectorAbon):
"""add subscribers list to NAS""" """add subscribers list to NAS"""
@ -106,12 +106,6 @@ class BaseTransmitter(metaclass=ABCMeta):
def sync_nas(self, users_from_db: Iterator): def sync_nas(self, users_from_db: Iterator):
list_for_add, list_for_del = self._diff_users(users_from_db) list_for_add, list_for_del = self._diff_users(users_from_db)
if len(list_for_del) > 0: if len(list_for_del) > 0:
print('FOR DELETE')
for ld in list_for_del:
print(ld)
self.remove_user_range(list_for_del) self.remove_user_range(list_for_del)
if len(list_for_add) > 0: if len(list_for_add) > 0:
print('FOR ADD')
for la in list_for_add:
print(la)
self.add_user_range(list_for_add) self.add_user_range(list_for_add)

6
agent/mod_mikrotik.py

@ -1,10 +1,12 @@
import re import re
import socket import socket
import binascii import binascii
from abc import ABCMeta
from hashlib import md5 from hashlib import md5
from ipaddress import ip_network from ipaddress import ip_network
from typing import Iterable, Optional, Tuple, Generator, Dict from typing import Iterable, Optional, Tuple, Generator, Dict
from djing.lib.decorators import LazyInitMetaclass
from .structs import TariffStruct, AbonStruct, IpStruct, VectorAbon, VectorTariff from .structs import TariffStruct, AbonStruct, IpStruct, VectorAbon, VectorTariff
from . import settings as local_settings from . import settings as local_settings
from django.conf import settings from django.conf import settings
@ -30,8 +32,6 @@ class ApiRos(object):
sk.connect((ip, port or 8728)) sk.connect((ip, port or 8728))
self.sk = sk self.sk = sk
self.currenttag = 0
def login(self, username, pwd): def login(self, username, pwd):
if self.is_login: if self.is_login:
return return
@ -172,7 +172,7 @@ class IpAddressListObj(IpStruct):
self.mk_id = str(mk_id).replace('*', '') self.mk_id = str(mk_id).replace('*', '')
class MikrotikTransmitter(BaseTransmitter, ApiRos):
class MikrotikTransmitter(BaseTransmitter, ApiRos, metaclass=type('_ABC_Lazy_mcs', (ABCMeta, LazyInitMetaclass), {})):
def __init__(self, login=None, password=None, ip=None, port=None): def __init__(self, login=None, password=None, ip=None, port=None):
ip = ip or getattr(local_settings, 'NAS_IP') ip = ip or getattr(local_settings, 'NAS_IP')

37
djing/lib/decorators.py

@ -55,3 +55,40 @@ def hash_auth_view(fn):
else: else:
return HttpResponseForbidden('Access Denied') return HttpResponseForbidden('Access Denied')
return wrapped return wrapped
# Lazy initialize metaclass
class LazyInitMetaclass(type):
"""
Type this metaclass if you want to make your object with lazy initialize.
Method __init__ called only when you try to call something method
from object of your class.
"""
def __new__(mcs, name: str, bases: tuple, attrs: dict):
new_class_new = super(LazyInitMetaclass, mcs).__new__
def _lazy_call_decorator(fn):
def wrapped(self, *args, **kwargs):
if not self._is_initialized:
self._lazy_init(*self._args, **self._kwargs)
return fn(self, *args, **kwargs)
return wrapped
# Apply decorator to all public class methods
new_attrs = {k: _lazy_call_decorator(v) for k, v in attrs.items() if not k.startswith('__') and not k.endswith('__') and callable(v)}
if new_attrs:
attrs.update(new_attrs)
attrs['_is_initialized'] = False
new_class = new_class_new(mcs, name, bases, attrs)
real_init = getattr(new_class, '__init__')
def _lazy_init(self, *args, **kwargs):
self._args = args
self._kwargs = kwargs
setattr(new_class, '__init__', _lazy_init)
setattr(new_class, '_lazy_init', real_init)
return new_class
Loading…
Cancel
Save