blob: 39417bbdb34e28e2c4bc69281896e94ba957ebfa [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
'''
Purpose: Parses the Incubator podling status files to find the list of
development mailing list archive files.
Status: Alpha
'''
from __future__ import absolute_import
import os, sys
import collections
import traceback
import xml.etree.ElementTree
sys.path.insert(0, os.path.dirname(__file__))
from utility import Issue, SiteStructure, UTC
Podling = collections.namedtuple('Podling', ('name', 'mbox_relpath'))
class Issues(object):
ERROR = 'ERROR'
WARNING = 'WARNING'
def __init__(self):
self.__issues = []
def __exfmt(self):
return ''.join(traceback.format_exception_only(*sys.exc_info()[:2]))
def __writelast(self):
issue = self.__issues[-1]
if issue.kind:
sys.stderr.write('%s: %s\n' % issue)
else:
sys.stderr.write(issue.message)
@property
def issues(self):
return self.__issues[:]
def record_warning(self, message):
self.__issues.append(Issue(self.WARNING, message))
self.__writelast()
def record_error(self, message):
self.__issues.append(Issue(self.ERROR, message))
self.__writelast()
def record_exception(self, message):
self.record_error(message)
self.__issues.append(Issue(None, self.__exfmt()))
self.__writelast()
__issues = Issues()
def __parse_xml_file(path):
"""
Parse an XML file and suppress any encountered errors.
"""
try:
return xml.etree.ElementTree.parse(path)
except:
__issues.record_exception('Could not parse ' + path)
return None
def __find_podling_names():
"""
Find names of currently active podlings.
"""
doc = __parse_xml_file(SiteStructure.podlings())
if not doc:
return None
names = []
for info in doc.iterfind('podling'):
if info.get('status') != 'current':
continue
name = info.get('resource')
if name is None:
continue
names.append(name)
return names
__incubator = 'incubator.apache.org'
def __relpath_from_email(email):
"""
Convert a list email address to an archive relative path.
"""
email = email.strip()
# Some podlings are silly and add crud to the mailing list address
offset = email.find(__incubator)
if offset < 0:
__issues.record_warning('Not an Incubator address: ' + email)
return None
if email[offset + len(__incubator):]:
__issues.record_warning('Ignoring crud following address: ' + email)
email = email[:offset + len(__incubator)]
# Split the email into list name and host name
list_name, atsign, host = email.partition('@')
if not atsign or not host:
__issues.record_warning('Invalid mail address: ' + email)
return None
# Old-style podling lists are inside the incubator archives.
# The mailing list address is podling-list@incubator.apache.org
if host == __incubator:
return os.path.join(__incubator, list_name)
# New-style podling lists have their own archive directory.
# The mailing list address is list@podling.incubator.apache.org
basedir = host[:len(host) - len(__incubator)] + 'apache.org'
return os.path.join(basedir, list_name)
def podling_archives():
try:
podlings = []
for name in __find_podling_names():
doc = __parse_xml_file(SiteStructure.project_path(name + '.xml'))
if not doc:
continue
info = doc.find('.//*[@id="mail-dev"]')
if info is None:
__issues.record_warning(name + ' has no dev list?')
continue
email = ''
for el in info.iter():
email += (el.text or '')
podlings.append(Podling(name, __relpath_from_email(email)))
return podlings, __issues
except:
__issues.record_exception('Could not find any podlings')
return [], __issues
def test():
podlings, issues = podling_archives()
for p in podlings:
print('%25s %s' % (p.name + ' dev list:', p.mbox_relpath))