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): |