1 # -*- coding: UTF-8 -*- |
|
2 # Copyright (c) 2011 - 2014, Pascal Volk |
|
3 # See COPYING for distribution information. |
|
4 """ |
|
5 VirtualMailManager.quotalimit |
|
6 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
7 |
|
8 Virtual Mail Manager's QuotaLimit class to manage quota limits |
|
9 for domains and accounts. |
|
10 """ |
|
11 |
|
12 from VirtualMailManager.pycompat import all |
|
13 |
|
14 _ = lambda msg: msg |
|
15 |
|
16 |
|
17 class QuotaLimit(object): |
|
18 """Class to handle quota limit specific data.""" |
|
19 __slots__ = ('_dbh', '_qid', '_bytes', '_messages') |
|
20 _kwargs = ('qid', 'bytes', 'messages') |
|
21 |
|
22 def __init__(self, dbh, **kwargs): |
|
23 """Create a new QuotaLimit instance. |
|
24 |
|
25 Either the `qid` keyword or the `bytes` and `messages` keywords |
|
26 must be specified. |
|
27 |
|
28 Arguments: |
|
29 |
|
30 `dbh` : pyPgSQL.PgSQL.Connection || psycopg2._psycopg.connection |
|
31 A database connection for the database access. |
|
32 |
|
33 Keyword arguments: |
|
34 |
|
35 `qid` : int |
|
36 The id of a quota limit |
|
37 `bytes` : long |
|
38 The quota limit in bytes. |
|
39 `messages` : int |
|
40 The quota limit in number of messages |
|
41 """ |
|
42 self._dbh = dbh |
|
43 self._qid = 0 |
|
44 self._bytes = 0 |
|
45 self._messages = 0 |
|
46 |
|
47 for key in kwargs.iterkeys(): |
|
48 if key not in self.__class__._kwargs: |
|
49 raise ValueError('unrecognized keyword: %r' % key) |
|
50 qid = kwargs.get('qid') |
|
51 if qid is not None: |
|
52 assert isinstance(qid, (int, long)) |
|
53 self._load_by_qid(qid) |
|
54 else: |
|
55 bytes_, msgs = kwargs.get('bytes'), kwargs.get('messages') |
|
56 assert all(isinstance(i, (int, long)) for i in (bytes_, msgs)) |
|
57 if bytes_ < 0: |
|
58 self._bytes = -bytes_ |
|
59 else: |
|
60 self._bytes = bytes_ |
|
61 if msgs < 0: |
|
62 self._messages = -msgs |
|
63 else: |
|
64 self._messages = msgs |
|
65 self._load_by_limit() |
|
66 |
|
67 @property |
|
68 def bytes(self): |
|
69 """Quota limit in bytes.""" |
|
70 return self._bytes |
|
71 |
|
72 @property |
|
73 def messages(self): |
|
74 """Quota limit in number of messages.""" |
|
75 return self._messages |
|
76 |
|
77 @property |
|
78 def qid(self): |
|
79 """The quota limit's unique ID.""" |
|
80 return self._qid |
|
81 |
|
82 def __eq__(self, other): |
|
83 if isinstance(other, self.__class__): |
|
84 return self._qid == other._qid |
|
85 return NotImplemented |
|
86 |
|
87 def __ne__(self, other): |
|
88 if isinstance(other, self.__class__): |
|
89 return self._qid != other._qid |
|
90 return NotImplemented |
|
91 |
|
92 def _load_by_limit(self): |
|
93 """Load the quota limit by limit values from the database.""" |
|
94 dbc = self._dbh.cursor() |
|
95 dbc.execute('SELECT qid FROM quotalimit WHERE bytes = %s AND ' |
|
96 'messages = %s', (self._bytes, self._messages)) |
|
97 res = dbc.fetchone() |
|
98 dbc.close() |
|
99 if res: |
|
100 self._qid = res[0] |
|
101 else: |
|
102 self._save() |
|
103 |
|
104 def _load_by_qid(self, qid): |
|
105 """Load the quota limit by its unique ID from the database.""" |
|
106 dbc = self._dbh.cursor() |
|
107 dbc.execute('SELECT bytes, messages FROM quotalimit WHERE qid = %s', |
|
108 (qid,)) |
|
109 res = dbc.fetchone() |
|
110 dbc.close() |
|
111 if not res: |
|
112 raise ValueError('Unknown quota limit id specified: %r' % qid) |
|
113 self._qid = qid |
|
114 self._bytes, self._messages = res |
|
115 |
|
116 def _save(self): |
|
117 """Store a new quota limit in the database.""" |
|
118 dbc = self._dbh.cursor() |
|
119 dbc.execute("SELECT nextval('quotalimit_id')") |
|
120 self._qid = dbc.fetchone()[0] |
|
121 dbc.execute('INSERT INTO quotalimit (qid, bytes, messages) VALUES ' |
|
122 '(%s, %s, %s)', (self._qid, self._bytes, self._messages)) |
|
123 self._dbh.commit() |
|
124 dbc.close() |
|
125 |
|
126 del _ |
|