Merge lp:~james-w/linaro-image-tools/add-relations-to-packages-file into lp:linaro-image-tools/11.11

Proposed by James Westby
Status: Merged
Merged at revision: 75
Proposed branch: lp:~james-w/linaro-image-tools/add-relations-to-packages-file
Merge into: lp:linaro-image-tools/11.11
Prerequisite: lp:~james-w/linaro-image-tools/split-package-fetcher
Diff against target: 223 lines (+130/-11)
3 files modified
hwpack/packages.py (+55/-8)
hwpack/testing.py (+2/-1)
hwpack/tests/test_packages.py (+73/-2)
To merge this branch: bzr merge lp:~james-w/linaro-image-tools/add-relations-to-packages-file
Reviewer Review Type Date Requested Status
Zygmunt Krynicki (community) Approve
Review via email: mp+35167@code.launchpad.net

Description of the change

Hi,

This adds "depends" to FetchedPackage, corresponding to the "Depends"
that should be put in the Packages file.

First it allows you to set it on the object, and works it in to __eq__,
__hash__ etc.

It then adds code the Packages file creation to write out the dependencies
in the file.

Then it adds a "from_apt" constructor to FetchedPackage that allows you
to create one from a python-apt apt.package.Version (meaning a single
version of a package) instance. This centralises that code, and allows
us to encapsulate the tedious process of going from apt's object definition
of dependencies to the string version that we want.

The tests for that use IsolatedAptCache from the previous branch to
get an actual python-apt object to use.

We should do the same for other dependencies (Pre-Depends and Conflicts being
the most important), but I'll put that in a separate branch.

Thanks,

James

To post a comment you must log in.
Revision history for this message
Zygmunt Krynicki (zyga) wrote :

Hi.

I'm not familiar with this API but this method seems quite magic.
You could add a docstring explaining what it does.

+ @classmethod
+ def from_apt(cls, pkg, filename, content):
+ depends = None
+ pkg_dependencies = pkg.get_dependencies("Depends")
+ if pkg_dependencies:
+ depends_list = []
+ for or_dep in pkg_dependencies:
+ or_list = []
+ for or_alternative in or_dep.or_dependencies:
+ suffix = ""
+ if or_alternative.relation:
+ suffix = " (%s %s)" % (
+ or_alternative.relation, or_alternative.version)
+ or_list.append("%s%s" % (or_alternative.name, suffix))
+ depends_list.append(" | ".join(or_list))
+ depends = ", ".join(depends_list)
+ return cls(
+ pkg.package.name, pkg.version, filename, content, pkg.size,
+ pkg.md5, pkg.architecture, depends=depends)

134. By James Westby

Add a docstring to from_apt. Thanks Zygmunt.

Revision history for this message
James Westby (james-w) wrote :

> Hi.
>
> I'm not familiar with this API but this method seems quite magic.
> You could add a docstring explaining what it does.

Done, thanks.

The next branch refactors this and explains more of the intent
of that odd code in the docstring of the new function. I can
pull that in to this branch if you like.

Thanks,

James

Revision history for this message
Zygmunt Krynicki (zyga) wrote :

> > I'm not familiar with this API but this method seems quite magic.
> > You could add a docstring explaining what it does.
>
> Done, thanks.

> The next branch refactors this and explains more of the intent
> of that odd code in the docstring of the new function. I can
> pull that in to this branch if you like.

I read the next branch, it's much better.
You don't need to merge it here, just go ahead and merge one by one.

Zygmunt

review: Approve
Revision history for this message
James Westby (james-w) wrote :

On Tue, 14 Sep 2010 15:09:40 -0000, Zygmunt Krynicki <email address hidden> wrote:
> Review: Approve
> > > I'm not familiar with this API but this method seems quite magic.
> > > You could add a docstring explaining what it does.
> >
> > Done, thanks.
>
> > The next branch refactors this and explains more of the intent
> > of that odd code in the docstring of the new function. I can
> > pull that in to this branch if you like.
>
> I read the next branch, it's much better.
> You don't need to merge it here, just go ahead and merge one by one.

Ok, thanks.

James

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'hwpack/packages.py'
2--- hwpack/packages.py 2010-09-10 21:53:40 +0000
3+++ hwpack/packages.py 2010-09-10 21:53:40 +0000
4@@ -22,8 +22,9 @@
5 parts.append('Version: %s' % package.version)
6 parts.append('Filename: %s' % package.filename)
7 parts.append('Size: %d' % package.size)
8- # TODO: architecture support
9 parts.append('Architecture: %s' % package.architecture)
10+ if package.depends:
11+ parts.append('Depends: %s' % package.depends)
12 parts.append('MD5sum: %s' % package.md5)
13 content += "\n".join(parts)
14 content += "\n\n"
15@@ -78,10 +79,14 @@
16 :ivar architecture: the architecture that the package is for, may be
17 'all'.
18 :type architecture: str
19+ :ivar depends: the depends string that the package has, i.e. the
20+ dependencies as specified in debian/control. May be None if the
21+ package has none.
22+ :type depends: str or None
23 """
24
25 def __init__(self, name, version, filename, content, size, md5,
26- architecture):
27+ architecture, depends=None):
28 """Create a FetchedPackage.
29
30 See the instance variables for the arguments.
31@@ -93,6 +98,41 @@
32 self.size = size
33 self.md5 = md5
34 self.architecture = architecture
35+ self.depends = depends
36+
37+ @classmethod
38+ def from_apt(cls, pkg, filename, content):
39+ """Create a FetchedPackage from a python-apt Version (package).
40+
41+ This is an alternative constructor for FetchedPackages that
42+ takes most of the information from an apt.package.Version
43+ object (i.e. a single version of a package), with some additional
44+ information supplied by tha caller.
45+
46+ :param pkg: the python-apt package to take the information from.
47+ :type pkg: apt.package.Version instance
48+ :param filename: the filename that the package has.
49+ :type filename: str
50+ :param content: the content of the package.
51+ :type content: file-like object
52+ """
53+ depends = None
54+ pkg_dependencies = pkg.get_dependencies("Depends")
55+ if pkg_dependencies:
56+ depends_list = []
57+ for or_dep in pkg_dependencies:
58+ or_list = []
59+ for or_alternative in or_dep.or_dependencies:
60+ suffix = ""
61+ if or_alternative.relation:
62+ suffix = " (%s %s)" % (
63+ or_alternative.relation, or_alternative.version)
64+ or_list.append("%s%s" % (or_alternative.name, suffix))
65+ depends_list.append(" | ".join(or_list))
66+ depends = ", ".join(depends_list)
67+ return cls(
68+ pkg.package.name, pkg.version, filename, content, pkg.size,
69+ pkg.md5, pkg.architecture, depends=depends)
70
71 def __eq__(self, other):
72 return (self.name == other.name
73@@ -101,11 +141,20 @@
74 and self.content.read() == other.content.read()
75 and self.size == other.size
76 and self.md5 == other.md5
77- and self.architecture == other.architecture)
78+ and self.architecture == other.architecture
79+ and self.depends == other.depends)
80
81 def __hash__(self):
82 return hash(
83- (self.name, self.version, self.filename, self.size, self.md5))
84+ (self.name, self.version, self.filename, self.size, self.md5,
85+ self.depends))
86+
87+ def __repr__(self):
88+ return (
89+ '<%s name=%s version=%s size=%s md5=%s architecture=%s '
90+ 'depends="%s">' % (self.__class__.__name__, self.name,
91+ self.version, self.size, self.md5, self.architecture,
92+ self.depends))
93
94
95 class IsolatedAptCache(object):
96@@ -242,9 +291,7 @@
97 raise FetchError(
98 "The item %r could not be fetched: %s" %
99 (acqfile.destfile, acqfile.error_text))
100- result_package = FetchedPackage(
101- candidate.package.name, candidate.version, base,
102- open(destfile), candidate.size, candidate.md5,
103- candidate.architecture)
104+ result_package = FetchedPackage.from_apt(
105+ candidate, base, open(destfile))
106 results.append(result_package)
107 return results
108
109=== modified file 'hwpack/testing.py'
110--- hwpack/testing.py 2010-09-10 21:53:40 +0000
111+++ hwpack/testing.py 2010-09-10 21:53:40 +0000
112@@ -54,10 +54,11 @@
113 See FetchedPackage for the instance variables.
114 """
115
116- def __init__(self, name, version, architecture="all"):
117+ def __init__(self, name, version, architecture="all", depends=None):
118 self.name = name
119 self.version = version
120 self.architecture = architecture
121+ self.depends = depends
122
123 @property
124 def filename(self):
125
126=== modified file 'hwpack/tests/test_packages.py'
127--- hwpack/tests/test_packages.py 2010-09-10 21:53:40 +0000
128+++ hwpack/tests/test_packages.py 2010-09-10 21:53:40 +0000
129@@ -41,8 +41,24 @@
130 get_packages_file([package1]) + get_packages_file([package2]),
131 get_packages_file([package1, package2]))
132
133-
134-class FetchedPackageTests(TestCase):
135+ def test_with_depends(self):
136+ package = DummyFetchedPackage("foo", "1.1", depends="bar | baz")
137+ self.assertEqual(textwrap.dedent("""\
138+ Package: foo
139+ Version: 1.1
140+ Filename: %(filename)s
141+ Size: %(size)d
142+ Architecture: all
143+ Depends: bar | baz
144+ MD5sum: %(md5)s
145+ \n""" % {
146+ 'filename': package.filename,
147+ 'size': package.size,
148+ 'md5': package.md5,
149+ }), get_packages_file([package]))
150+
151+
152+class FetchedPackageTests(TestCaseWithFixtures):
153
154 def test_attributes(self):
155 package = FetchedPackage(
156@@ -112,6 +128,33 @@
157 "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "i386")
158 self.assertNotEqual(package1, package2)
159
160+ def test_not_equal_different_depends(self):
161+ package1 = FetchedPackage(
162+ "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel",
163+ depends="bar")
164+ package2 = FetchedPackage(
165+ "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel",
166+ depends="baz")
167+ self.assertNotEqual(package1, package2)
168+
169+ def test_not_equal_different_depends_one_None(self):
170+ package1 = FetchedPackage(
171+ "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel",
172+ depends="bar")
173+ package2 = FetchedPackage(
174+ "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel",
175+ depends=None)
176+ self.assertNotEqual(package1, package2)
177+
178+ def test_equal_same_depends(self):
179+ package1 = FetchedPackage(
180+ "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel",
181+ depends="bar")
182+ package2 = FetchedPackage(
183+ "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel",
184+ depends="bar")
185+ self.assertEqual(package1, package2)
186+
187 def test_equal_hash_equal(self):
188 package1 = FetchedPackage(
189 "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel")
190@@ -119,6 +162,34 @@
191 "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel")
192 self.assertEqual(hash(package1), hash(package2))
193
194+ def test_equal_hash_equal_with_depends(self):
195+ package1 = FetchedPackage(
196+ "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel",
197+ depends="bar")
198+ package2 = FetchedPackage(
199+ "foo", "1.1", "foo_1.1.deb", StringIO("xxxx"), 4, "aaaa", "armel",
200+ depends="bar")
201+ self.assertEqual(hash(package1), hash(package2))
202+
203+ def test_from_apt(self):
204+ target_package = DummyFetchedPackage("foo", "1.0")
205+ source = self.useFixture(AptSourceFixture([target_package]))
206+ with IsolatedAptCache([source.sources_entry]) as cache:
207+ candidate = cache.cache['foo'].candidate
208+ created_package = FetchedPackage.from_apt(
209+ candidate, target_package.filename, target_package.content)
210+ self.assertEqual(target_package, created_package)
211+
212+ def test_from_apt_with_depends(self):
213+ target_package = DummyFetchedPackage(
214+ "foo", "1.0", depends="bar | baz (>= 1.0), zap")
215+ source = self.useFixture(AptSourceFixture([target_package]))
216+ with IsolatedAptCache([source.sources_entry]) as cache:
217+ candidate = cache.cache['foo'].candidate
218+ created_package = FetchedPackage.from_apt(
219+ candidate, target_package.filename, target_package.content)
220+ self.assertEqual(target_package, created_package)
221+
222
223 class AptCacheTests(TestCaseWithFixtures):
224

Subscribers

People subscribed via source and target branches