Gentoo Archives: gentoo-commits

From: Slava Bacherikov <slava@××××××××××××××.ua>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/gentoo-packages:master commit in: gpackages/libs/package_info/, gpackages/libs/package_info/generic_metadata/
Date: Tue, 03 Jul 2012 21:08:54
Message-Id: 1341349628.1141ccb27e72421a606f2e7c5324ce32f7cff426.bacher09@gentoo
1 commit: 1141ccb27e72421a606f2e7c5324ce32f7cff426
2 Author: Slava Bacherikov <slava <AT> bacher09 <DOT> org>
3 AuthorDate: Tue Jul 3 20:23:07 2012 +0000
4 Commit: Slava Bacherikov <slava <AT> bacherikov <DOT> org <DOT> ua>
5 CommitDate: Tue Jul 3 21:07:08 2012 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/gentoo-packages.git;a=commit;h=1141ccb2
7
8 Add layer for work with portage news
9
10 ---
11 .../libs/package_info/generic_metadata/news.py | 133 ++++++++++++++++++++
12 gpackages/libs/package_info/mixins.py | 14 ++-
13 2 files changed, 146 insertions(+), 1 deletions(-)
14
15 diff --git a/gpackages/libs/package_info/generic_metadata/news.py b/gpackages/libs/package_info/generic_metadata/news.py
16 new file mode 100644
17 index 0000000..d84ac6b
18 --- /dev/null
19 +++ b/gpackages/libs/package_info/generic_metadata/news.py
20 @@ -0,0 +1,133 @@
21 +import os
22 +import os.path
23 +import re
24 +import hashlib
25 +from datetime import datetime
26 +from email import message_from_string
27 +from email.utils import getaddresses
28 +from ..generic import ToStrMixin, toint, file_get_content
29 +
30 +NEWS_STR_RE = r'^(?P<date>\d{4,4}-\d{2}-\d{2})-(?P<title>.*)$'
31 +news_re = re.compile(NEWS_STR_RE)
32 +
33 +class News(ToStrMixin):
34 +
35 + def __init__(self, repo_path = '/usr/portage'):
36 + self.news_path = os.path.join(repo_path, 'metadata', 'news')
37 + if not os.path.isdir(self.news_path):
38 + raise ValueError
39 + # For repr
40 + self.repo_path = repo_path
41 +
42 + def iter_news(self):
43 + for name in os.listdir(self.news_path):
44 + try:
45 + i = NewsItem(self.news_path, name)
46 + except ValueError:
47 + pass
48 + else:
49 + yield i
50 +
51 + def __iter__(self):
52 + return self.iter_news()
53 +
54 + def __unicode__(self):
55 + return unicode(self.repo_path)
56 +
57 +class NewsItem(ToStrMixin):
58 +
59 + N_ITEM_P = r'^%(name)s\.(?P<lang>[a-z]{2})\.txt$'
60 +
61 + def __init__(self, news_path, news_dir):
62 + ndir = os.path.join(news_path, news_dir)
63 + if not os.path.isdir(ndir):
64 + raise ValueError
65 + m = news_re.match(news_dir)
66 + if m is None:
67 + raise ValueError
68 + p_dct = m.groupdict()
69 + try:
70 + date = datetime.strptime(p_dct['date'], '%Y-%m-%d')
71 + except ValueError:
72 + raise
73 + else:
74 + self.date = date.date()
75 +
76 + self.title = p_dct['title']
77 + self.name = news_dir
78 + self.news_dir = ndir
79 + self._news_dict = {}
80 + self._fetch_news()
81 +
82 + def _iter_news_items(self):
83 + pattern_str = self.N_ITEM_P % {'name': self.name}
84 + pattern = re.compile(pattern_str)
85 + for item in os.listdir(self.news_dir):
86 + m = pattern.match(item)
87 + full_path = os.path.join(self.news_dir, item)
88 + if m is not None and os.path.isfile(full_path):
89 + lang = m.groupdict()['lang']
90 + yield (full_path, lang)
91 +
92 + def _fetch_news(self):
93 + for item, lang in self._iter_news_items():
94 + self._news_dict[lang] = NewsItemLang(item,
95 + self.date,
96 + lang,
97 + self.title)
98 +
99 + @property
100 + def default_news(self):
101 + return self._news_dict['en']
102 +
103 + @property
104 + def news(self):
105 + return self._news_dict
106 +
107 + def __unicode__(self):
108 + return unicode(self.name)
109 +
110 +class NewsItemLang(object):
111 +
112 + def __init__(self, item, date, lang = 'en', name = ''):
113 + f = file_get_content(item)
114 + self.sha1 = hashlib.sha1(f).hexdigest()
115 + self._mes_obj = message_from_string(f)
116 + self.date = date
117 + self.lang = lang
118 + self.name = name
119 +
120 + @property
121 + def title(self):
122 + return self._mes_obj.get('Title')
123 +
124 + @property
125 + def revision(self):
126 + return toint(self._mes_obj.get('Revision', 1),1)
127 +
128 + @property
129 + def format_ver(self):
130 + g = self._mes_obj.get('News-Item-Format', '1.0')
131 + try:
132 + maj, min = g.split('.')
133 + except ValueError:
134 + maj, min = 1, 0
135 +
136 + return toint(maj,1), toint(min, 0)
137 +
138 + @property
139 + def authors(self):
140 + "Returns list of tuples"
141 + authors = self._mes_obj.get_all('Author')
142 + return getaddresses(authors)
143 +
144 + @property
145 + def translators(self):
146 + "Returns list of tuples"
147 + translators = self._mes_obj.get_all('Translator')
148 + return getaddresses(translators)
149 +
150 + @property
151 + def message(self):
152 + return self._mes_obj.get_payload()
153 +
154
155 diff --git a/gpackages/libs/package_info/mixins.py b/gpackages/libs/package_info/mixins.py
156 index 923fcc8..0ef9b4d 100644
157 --- a/gpackages/libs/package_info/mixins.py
158 +++ b/gpackages/libs/package_info/mixins.py
159 @@ -13,6 +13,8 @@ from .generic_metadata.category_metadata import CategoryMetadata
160 from .generic_metadata.package_metadata import PackageMetaData
161 #License group metadata
162 from .generic_metadata.license_groups import LicenseGroups
163 +# News
164 +from .generic_metadata.news import News
165 # Validators
166 from .validators import validate_url, validate_email, ValidationError
167 #Generic objects
168 @@ -126,6 +128,15 @@ class PortTreeBaseMixin(ToStrMixin):
169 def __unicode__(self):
170 return self.name
171
172 +class PortTreeNewsMixin(object):
173 +
174 + @cached_property
175 + def news(self):
176 + try:
177 + return News(self.porttree_path)
178 + except:
179 + return None
180 +
181 class PortTreeIteratorMixin(AutoGeneratorMixin):
182 main_iterator = 'iter_categories'
183 generator_names = ('iter_packages', 'iter_ebuilds')
184 @@ -335,7 +346,8 @@ class PackageGenericMixin(PackageBaseMixin, PackageFilesMixin):
185 class PortageMixin(PortageGenericMixin, PortageIteratorMixin, AbstractPortage):
186 pass
187
188 -class PortTreeMixin(PortTreeBaseMixin, PortTreeIteratorMixin, AbstractPortTree):
189 +class PortTreeMixin(PortTreeBaseMixin, PortTreeIteratorMixin, \
190 + PortTreeNewsMixin, AbstractPortTree):
191 pass
192
193 class CategoryMixin(CategoryBaseMixin, CategoryIteratorMixin, AbstractCategory):