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