# # LMA.py - local modifications area interface # # Copyright (c) 2006-2007 The DITrack Project, www.ditrack.org. # # $Id: LMA.py 1696 2007-07-10 22:45:31Z vss $ # $HeadURL: https://127.0.0.1/ditrack/src/tags/0.7/DITrack/DB/LMA.py $ # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, # this list of conditions and the following disclaimer in the documentation # and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # import os.path import shelve # DITrack modules import DITrack.DB.Issue import DITrack.Common from DITrack.Logging import DEBUG LMA_FILE = "LMA" class LocalModsArea: """ Class representing local modifications area. MEMBERS: data A mapping of existing LMA issues: maps identifiers (as strings) to issue objects. """ def __contains__(self, key): """ Check if the issue KEY (string) is contained in the LMA. """ return key in self.data; def __del__(self): self.data.close() def __getitem__(self, key): return self.data[key] def __init__(self, path): datadir = os.path.join(path, DITrack.DB.Common.LOCAL_DT_DIR) if not os.path.exists(datadir): os.mkdir(datadir, 0755) fname = os.path.join(datadir, LMA_FILE) self.data = shelve.open(fname) def _comment_keys(self, issue_id): """ Return a sorted list of comment names for all comments of the issue ISSUE_ID in the LMA. """ prefix = "%s." % issue_id ids = filter(lambda x: x.startswith(prefix), self.data.keys()) ids.sort() return ids def comments(self, issue_id): """ Return a sorted list of tuples (ID, COMMENT) for all comments of the issue ISSUE_ID in the LMA. """ return [(x, self.data[x]) for x in self._comment_keys(issue_id)] def issues(self, firm=True, local=True): """ Return a sorted list of tuples (ID, ISSUE) for all issues in the LMA. The FIRM and LOCAL parameters control which kind of issues to include into the resulting list. Firm issues precede local ones in the result. Either FIRM or LOCAL should be True (or both). """ assert firm or local, "firm=%s, local=%s" % (firm, local) # XXX: replace with is_valid_XXX() once those are available for the # whole module. def is_firm(s): try: int(s) except ValueError: return False return True keys = filter( lambda x: (firm and is_firm(x)) or (local and not is_firm(x)), self.data.keys() ) keys.sort() return [(k, self.data[k]) for k in keys] def new_comment(self, issue_id, comment): """ Add issue ISSUE_ID (string) COMMENT to the LMA. Returns newly assigned comment name. """ DEBUG("Creating a new comment in the LMA for issue '%s'" % issue_id) try: issue = self.data[issue_id] except KeyError: # The very first local comment to the issue. issue = DITrack.DB.Issue.Issue() # Don't update the info, since this issue is merely a collection of # comments. # # XXX: make it a list then? name = issue.add_comment(comment, is_local=True, update_info=False) self.data[issue_id] = issue return name def new_issue(self, issue): # Figure out a name for the new issue name = DITrack.DB.Common.next_entity_name( [k for k, i in self.issues(firm=False)] ) self.data[name] = issue return name def remove_comment(self, issue_number, comment_name): """ Removes comment COMMENT_NAME from the issue ISSUE_NUMBER in the LMA. The issue and comment should exist. If the issue has no comments after the removal, removes the issue altogether. """ assert issue_number in self.data, "issue_number='%s'" % issue_number issue = self.data[issue_number] issue.remove_comment(comment_name) if len(issue): self.data[issue_number] = issue else: del self.data[issue_number] def remove_issue(self, name): del self.data[name]