[27267] in Source-Commits
python-discuss commit: Implement automatic meeting location
daemon@ATHENA.MIT.EDU (Victor Vasiliev)
Sat Sep 7 15:06:56 2013
Date: Sat, 7 Sep 2013 15:06:48 -0400
From: Victor Vasiliev <vasilvv@MIT.EDU>
Message-Id: <201309071906.r87J6moF002776@drugstore.mit.edu>
To: source-commits@MIT.EDU
https://github.com/mit-athena/python-discuss/commit/f3db06ee90eb422023f5e9a23457ebb128f5bd71
commit f3db06ee90eb422023f5e9a23457ebb128f5bd71
Author: Victor Vasiliev <vasilvv@mit.edu>
Date: Sat Sep 7 03:32:05 2013 -0400
Implement automatic meeting location
This allows users not to care in particular on which server the meeting
is located, which is helpful because there are not that many discuss
servers in existence.
discuss/__init__.py | 1 +
discuss/client.py | 5 +++
discuss/locator.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 80 insertions(+), 0 deletions(-)
diff --git a/discuss/__init__.py b/discuss/__init__.py
index ea60e9e..1ccd01b 100644
--- a/discuss/__init__.py
+++ b/discuss/__init__.py
@@ -1,3 +1,4 @@
from .client import *
from .rcfile import *
+from .locator import *
diff --git a/discuss/client.py b/discuss/client.py
index 9599256..a137a2e 100644
--- a/discuss/client.py
+++ b/discuss/client.py
@@ -65,6 +65,11 @@ class Client(object):
reply = self.rpc.request(request)
return reply.read_string()
+ def close(self):
+ """Disconnect from the server."""
+
+ self.rpc.socket.close()
+
class Meeting(object):
"""Discuss meeting."""
diff --git a/discuss/locator.py b/discuss/locator.py
new file mode 100644
index 0000000..f2a3045
--- /dev/null
+++ b/discuss/locator.py
@@ -0,0 +1,74 @@
+#
+# Python client for Project Athena forum system.
+# See LICENSE file for more details.
+#
+# The following file contains routine used to locate
+# a meeting my its name using the two sources for location
+# lists: /etc/discuss/servers and ~/.dsc_servers. Both
+# of those files are formatted as lists of hostnames
+# with both empty lines and comments prefixed by "#" sign.
+#
+
+from .client import Client, Meeting, DiscussError
+from .constants import NO_SUCH_MTG
+from functools import partial
+import errno
+import os
+import re
+
+def _read_server_list(filename):
+ """Parses the given list of discuss servers."""
+
+ try:
+ source = open(filename, "r")
+ lines = source.readlines()
+ source.close()
+
+ remove_comments = partial(re.sub, "#.*", "")
+
+ lines = map(remove_comments, lines) # comments
+ lines = map(str.strip, lines) # whitespace
+ lines = filter(lambda x: x, lines) # empty lines
+
+ return lines
+ except IOError as err:
+ # File is allowed not to exist
+ if err.errno == errno.ENOENT:
+ return []
+ else:
+ raise err
+
+def get_servers():
+ global_list_path = "/etc/discuss/servers"
+ user_list_path = os.path.expanduser("~/.dsc_servers")
+
+ global_servers = _read_server_list(global_list_path)
+ user_servers = _read_server_list(user_list_path)
+
+ return global_servers + [ server
+ for server in user_servers if server not in global_servers ]
+
+def locate(name):
+ """Attempts to locate the meeting by looking for it on known
+ discuss servers. If found, returns the meeting object with a live
+ connection."""
+
+ servers = get_servers()
+ for server in servers:
+ client = Client(server)
+ for prefix in ("/var/spool/discuss/", "/usr/spool/discuss/"):
+ mtg_path = prefix + name
+ mtg = Meeting(client, mtg_path)
+ try:
+ mtg.load_info()
+ return mtg
+ except DiscussError as err:
+ if err.code == NO_SUCH_MTG:
+ continue
+ else:
+ client.close()
+ raise err
+
+ client.close()
+
+ return None