diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62696a5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/docker-py-997e583ea9a7b33113edd91d5bee73d25d720448.tar.gz +SOURCES/docker-pycreds-0.2.1.tar.gz diff --git a/.python-docker-py.metadata b/.python-docker-py.metadata new file mode 100644 index 0000000..b62bec8 --- /dev/null +++ b/.python-docker-py.metadata @@ -0,0 +1,2 @@ +048614198d1f15fcc1c95c1e55507dc53ce10fc0 SOURCES/docker-py-997e583ea9a7b33113edd91d5bee73d25d720448.tar.gz +02e65f3b4a75bd65cd4c312835961d3551967454 SOURCES/docker-pycreds-0.2.1.tar.gz diff --git a/README.md b/README.md deleted file mode 100644 index 98f42b4..0000000 --- a/README.md +++ /dev/null @@ -1,4 +0,0 @@ -The master branch has no content - -Look at the c7 branch if you are working with CentOS-7, or the c4/c5/c6 branch for CentOS-4, 5 or 6 -If you find this file in a distro specific branch, it means that no content has been checked in yet diff --git a/SOURCES/backport-util-socket-fixes-rhbz1501782.patch b/SOURCES/backport-util-socket-fixes-rhbz1501782.patch new file mode 100644 index 0000000..edc07fa --- /dev/null +++ b/SOURCES/backport-util-socket-fixes-rhbz1501782.patch @@ -0,0 +1,153 @@ +From 7761a8cf3568f25243e7881b315b9fc922237673 Mon Sep 17 00:00:00 2001 +From: Tomas Tomecek +Date: Thu, 10 May 2018 16:10:36 +0200 +Subject: [PATCH] asd + +--- + docker/api/container.py | 4 +++- + docker/api/exec_api.py | 2 +- + docker/client.py | 22 ++++++++++++++++------ + docker/utils/socket.py | 31 +++++++++++++++++++++++++++---- + tests/unit/api_test.py | 2 +- + 5 files changed, 48 insertions(+), 13 deletions(-) + +diff --git a/docker/api/container.py b/docker/api/container.py +index b8507d8..a164e7d 100644 +--- a/docker/api/container.py ++++ b/docker/api/container.py +@@ -26,7 +26,9 @@ class ContainerApiMixin(object): + u = self._url("/containers/{0}/attach", container) + response = self._post(u, headers=headers, params=params, stream=stream) + +- return self._read_from_socket(response, stream) ++ return self._read_from_socket( ++ response, stream, self._check_is_tty(container) ++ ) + + @utils.check_resource + def attach_socket(self, container, params=None, ws=False): +diff --git a/docker/api/exec_api.py b/docker/api/exec_api.py +index 6e49996..9468f46 100644 +--- a/docker/api/exec_api.py ++++ b/docker/api/exec_api.py +@@ -78,4 +78,4 @@ class ExecApiMixin(object): + + if socket: + return self._get_raw_response_socket(res) +- return self._read_from_socket(res, stream) ++ return self._read_from_socket(res, stream, tty) +diff --git a/docker/client.py b/docker/client.py +index 3fa19e0..eb928c6 100644 +--- a/docker/client.py ++++ b/docker/client.py +@@ -16,7 +16,7 @@ from .ssladapter import ssladapter + from .tls import TLSConfig + from .transport import UnixAdapter + from .utils import utils, check_resource, update_headers, kwargs_from_env +-from .utils.socket import frames_iter ++from .utils.socket import frames_iter, socket_raw_iter + try: + from .transport import NpipeAdapter + except ImportError: +@@ -317,13 +317,19 @@ class Client( + for out in response.iter_content(chunk_size=1, decode_unicode=True): + yield out + +- def _read_from_socket(self, response, stream): ++ def _read_from_socket(self, response, stream, tty=False): + socket = self._get_raw_response_socket(response) + ++ gen = None ++ if tty is False: ++ gen = frames_iter(socket) ++ else: ++ gen = socket_raw_iter(socket) ++ + if stream: +- return frames_iter(socket) ++ return gen + else: +- return six.binary_type().join(frames_iter(socket)) ++ return six.binary_type().join(gen) + + def _disable_socket_timeout(self, socket): + """ Depending on the combination of python version and whether we're +@@ -353,9 +359,13 @@ class Client( + + s.settimeout(None) + +- def _get_result(self, container, stream, res): ++ @check_resource ++ def _check_is_tty(self, container): + cont = self.inspect_container(container) +- return self._get_result_tty(stream, res, cont['Config']['Tty']) ++ return cont['Config']['Tty'] ++ ++ def _get_result(self, container, stream, res): ++ return self._get_result_tty(stream, res, self._check_is_tty(container)) + + def _get_result_tty(self, stream, res, is_tty): + # Stream multi-plexing was only introduced in API v1.6. Anything +diff --git a/docker/utils/socket.py b/docker/utils/socket.py +index 164b845..c3a5f90 100644 +--- a/docker/utils/socket.py ++++ b/docker/utils/socket.py +@@ -59,7 +59,7 @@ def next_frame_size(socket): + try: + data = read_exactly(socket, 8) + except SocketError: +- return 0 ++ return -1 + + _, actual = struct.unpack('>BxxxL', data) + return actual +@@ -69,7 +69,30 @@ def frames_iter(socket): + """ + Returns a generator of frames read from socket + """ +- n = next_frame_size(socket) +- while n > 0: +- yield read(socket, n) ++ while True: + n = next_frame_size(socket) ++ if n < 0: ++ break ++ while n > 0: ++ result = read(socket, n) ++ if result is None: ++ continue ++ data_length = len(result) ++ if data_length == 0: ++ # We have reached EOF ++ return ++ n -= data_length ++ yield result ++ ++ ++def socket_raw_iter(socket): ++ """ ++ Returns a generator of data read from the socket. ++ This is used for non-multiplexed streams. ++ """ ++ while True: ++ result = read(socket) ++ if len(result) == 0: ++ # We have reached EOF ++ return ++ yield result +diff --git a/tests/unit/api_test.py b/tests/unit/api_test.py +index 8faca6b..3aeff85 100644 +--- a/tests/unit/api_test.py ++++ b/tests/unit/api_test.py +@@ -83,7 +83,7 @@ def fake_delete(self, url, *args, **kwargs): + return fake_request('DELETE', url, *args, **kwargs) + + +-def fake_read_from_socket(self, response, stream): ++def fake_read_from_socket(self, response, stream, tty=False): + return six.binary_type() + + url_base = '{0}/'.format(fake_api.prefix) +-- +2.17.0 + diff --git a/SOURCES/implement-cpu_rt_-switches.patch b/SOURCES/implement-cpu_rt_-switches.patch new file mode 100644 index 0000000..462b578 --- /dev/null +++ b/SOURCES/implement-cpu_rt_-switches.patch @@ -0,0 +1,142 @@ +From e2b5a06cfd5375efc9741ea6bdad1ed764a65e54 Mon Sep 17 00:00:00 2001 +From: Tomas Tomecek +Date: Wed, 6 Sep 2017 17:57:56 +0200 +Subject: [PATCH] implement cpu_rt_* switches for create_host_config + +Signed-off-by: Tomas Tomecek +--- + docker/utils/utils.py | 23 ++++++++++++++++++++++- + docs/hostconfig.md | 2 ++ + tests/integration/container_test.py | 28 ++++++++++++++++++++++++++++ + tests/unit/container_test.py | 25 +++++++++++++++++++++++++ + 4 files changed, 77 insertions(+), 1 deletion(-) + +diff --git a/docker/utils/utils.py b/docker/utils/utils.py +index 8d55b57..2a183a0 100644 +--- a/docker/utils/utils.py ++++ b/docker/utils/utils.py +@@ -609,7 +609,8 @@ def create_host_config(binds=None, port_bindings=None, lxc_conf=None, + device_write_iops=None, oom_kill_disable=False, + shm_size=None, sysctls=None, version=None, tmpfs=None, + oom_score_adj=None, dns_opt=None, cpu_shares=None, +- cpuset_cpus=None, userns_mode=None, pids_limit=None): ++ cpuset_cpus=None, userns_mode=None, pids_limit=None, ++ cpu_rt_period=None, cpu_rt_runtime=None): + + host_config = {} + +@@ -897,6 +898,26 @@ def create_host_config(binds=None, port_bindings=None, lxc_conf=None, + raise host_config_version_error('pids_limit', '1.23') + host_config["PidsLimit"] = pids_limit + ++ if cpu_rt_period: ++ if version_lt(version, '1.25'): ++ raise host_config_version_error('cpu_rt_period', '1.25') ++ ++ if not isinstance(cpu_rt_period, int): ++ raise host_config_type_error( ++ 'cpu_rt_period', cpu_rt_period, 'int' ++ ) ++ host_config['CPURealtimePeriod'] = cpu_rt_period ++ ++ if cpu_rt_runtime: ++ if version_lt(version, '1.25'): ++ raise host_config_version_error('cpu_rt_runtime', '1.25') ++ ++ if not isinstance(cpu_rt_runtime, int): ++ raise host_config_type_error( ++ 'cpu_rt_runtime', cpu_rt_runtime, 'int' ++ ) ++ host_config['CPURealtimeRuntime'] = cpu_rt_runtime ++ + return host_config + + +diff --git a/docs/hostconfig.md b/docs/hostconfig.md +index 008d5cf..c39a02c 100644 +--- a/docs/hostconfig.md ++++ b/docs/hostconfig.md +@@ -130,6 +130,8 @@ for example: + * userns_mode (str): Sets the user namespace mode for the container when user + namespace remapping option is enabled. Supported values are: `host` + * pids_limit (int): Tune a container’s pids limit. Set -1 for unlimited. ++* cpu_rt_runtime (int): Limit the CPU real-time runtime in microseconds. ++* cpu_rt_period (int): Limit the CPU real-time period in microseconds. + + **Returns** (dict) HostConfig dictionary + +diff --git a/tests/integration/container_test.py b/tests/integration/container_test.py +index e390acb..7d179d5 100644 +--- a/tests/integration/container_test.py ++++ b/tests/integration/container_test.py +@@ -1144,3 +1144,31 @@ class ContainerCPUTest(helpers.BaseTestCase): + self.client.start(container) + inspect_data = self.client.inspect_container(container) + self.assertEqual(inspect_data['HostConfig']['CpusetCpus'], cpuset_cpus) ++ ++ ++class ContainerCPURT(helpers.BaseTestCase): ++ @requires_api_version('1.25') ++ def test_container_cpu_rt_runtime(self): ++ cpu_rt_runtime = 1000 ++ container = self.client.create_container( ++ BUSYBOX, 'ls', host_config=self.client.create_host_config( ++ cpu_rt_runtime=cpu_rt_runtime ++ ) ++ ) ++ self.tmp_containers.append(container) ++ self.client.start(container) ++ inspect_data = self.client.inspect_container(container) ++ self.assertEqual(inspect_data['HostConfig']['CPURealtimeRuntime'], 1000) ++ ++ @requires_api_version('1.285') ++ def test_container_rt_period(self): ++ cpu_rt_period = 2000 ++ container = self.client.create_container( ++ BUSYBOX, 'ls', host_config=self.client.create_host_config( ++ cpu_rt_period=cpu_rt_period ++ ) ++ ) ++ self.tmp_containers.append(container) ++ self.client.start(container) ++ inspect_data = self.client.inspect_container(container) ++ self.assertEqual(inspect_data['HostConfig']['CPURealtimePeriod'], 2000) +diff --git a/tests/unit/container_test.py b/tests/unit/container_test.py +index db3dd74..8c7b2c1 100644 +--- a/tests/unit/container_test.py ++++ b/tests/unit/container_test.py +@@ -335,6 +335,31 @@ class CreateContainerTest(DockerClientTest): + self.assertEqual(args[1]['headers'], + {'Content-Type': 'application/json'}) + ++ @requires_api_version('1.25') ++ def test_create_container_with_rt(self): ++ self.client.create_container( ++ 'busybox', 'ls', host_config=self.client.create_host_config( ++ cpu_rt_period=1000, cpu_rt_runtime=1000 ++ ) ++ ) ++ ++ args = fake_request.call_args ++ self.assertEqual(args[0][1], ++ url_prefix + 'containers/create') ++ self.assertEqual(json.loads(args[1]['data']), ++ json.loads(''' ++ {"Tty": false, "Image": "busybox", ++ "Cmd": ["ls"], "AttachStdin": false, ++ "AttachStderr": true, ++ "AttachStdout": true, "OpenStdin": false, ++ "StdinOnce": false, ++ "NetworkDisabled": false, ++ "HostConfig": { ++ "CPURealtimePeriod": 1000, ++ "CPURealtimeRuntime": 1000, ++ "NetworkMode": "default" ++ }}''')) ++ + @requires_api_version('1.18') + def test_create_container_with_host_config_cpuset(self): + self.client.create_container( +-- +2.14.1 + diff --git a/SOURCES/remote-inspection.patch b/SOURCES/remote-inspection.patch new file mode 100644 index 0000000..4db85b4 --- /dev/null +++ b/SOURCES/remote-inspection.patch @@ -0,0 +1,49 @@ +From 0b66aa1d60aa05518b69dbb0b96387b504ec79e7 Mon Sep 17 00:00:00 2001 +From: Dan Walsh +Date: Thu, 7 Jan 2016 13:11:32 -0500 +Subject: [PATCH] Remote inspect binding. + +Signed-off-by: William Temple +--- + docker/api/image.py | 9 +++++++-- + tests/unit/image_test.py | 3 ++- + 2 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/docker/api/image.py b/docker/api/image.py +index 8493b38..7de76e1 100644 +--- a/docker/api/image.py ++++ b/docker/api/image.py +@@ -138,9 +138,14 @@ class ImageApiMixin(object): + return self._result(self._post(api_url, params=params)) + + @utils.check_resource +- def inspect_image(self, image): ++ def inspect_image(self, image, remote=False): ++ params = {} ++ if remote: ++ params['remote'] = 1 + return self._result( +- self._get(self._url("/images/{0}/json", image)), True ++ self._get(self._url("/images/{0}/json".format(image)), ++ params=params), ++ True + ) + + def load_image(self, data): +diff --git a/tests/unit/image_test.py b/tests/unit/image_test.py +index a46e48e..00256d2 100644 +--- a/tests/unit/image_test.py ++++ b/tests/unit/image_test.py +@@ -193,7 +193,8 @@ class ImageTest(DockerClientTest): + fake_request.assert_called_with( + 'GET', + url_prefix + 'images/test_image/json', +- timeout=DEFAULT_TIMEOUT_SECONDS ++ timeout=DEFAULT_TIMEOUT_SECONDS, ++ params={} + ) + + def test_inspect_image_undefined_id(self): +-- +2.6.4 + diff --git a/SOURCES/setup-Neuter-extras_require-that-doesn-t-work-on-Cen.patch b/SOURCES/setup-Neuter-extras_require-that-doesn-t-work-on-Cen.patch new file mode 100644 index 0000000..5f18e66 --- /dev/null +++ b/SOURCES/setup-Neuter-extras_require-that-doesn-t-work-on-Cen.patch @@ -0,0 +1,41 @@ +From 3eeef7b62131a1dbcbb2758eb9eb382578ddd0fb Mon Sep 17 00:00:00 2001 +From: Colin Walters +Date: Tue, 3 May 2016 16:35:24 +0200 +Subject: [PATCH] setup: Neuter extras_require that doesn't work on CentOS 7 + +I think the version of python-setuputils is too old or something. +--- + setup.py | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/setup.py b/setup.py +index fac5129..6a7e03c 100644 +--- a/setup.py ++++ b/setup.py +@@ -17,10 +17,10 @@ requirements = [ + if sys.platform == 'win32': + requirements.append('pypiwin32 >= 219') + +-extras_require = { +- ':python_version < "3.5"': 'backports.ssl_match_hostname >= 3.5', +- ':python_version < "3.3"': 'ipaddress >= 1.0.16', +-} ++# extras_require = { ++# ':python_version < "3.5"': 'backports.ssl_match_hostname >= 3.5', ++# ':python_version < "3.3"': 'ipaddress >= 1.0.16', ++# } + + version = None + exec(open('docker/version.py').read()) +@@ -33,7 +33,7 @@ setup( + ], + install_requires=requirements, + tests_require=test_requirements, +- extras_require=extras_require, ++ # extras_require=extras_require, + zip_safe=False, + test_suite='tests', + classifiers=[ +-- +2.4.11 + diff --git a/SPECS/python-docker-py.spec b/SPECS/python-docker-py.spec new file mode 100644 index 0000000..3cc25fc --- /dev/null +++ b/SPECS/python-docker-py.spec @@ -0,0 +1,210 @@ +%global owner docker +%global project docker-py +%global commit 997e583ea9a7b33113edd91d5bee73d25d720448 +%global shortcommit %(c=%{commit}; echo ${c:0:7}) +%global docker_pycreds_pypi_name docker-pycreds +%global docker_pycreds_version 0.2.1 + +Name: python-%{project} +Version: 1.10.6 +Release: 4%{?dist} +Summary: An API client for docker written in Python +License: ASL 2.0 +URL: https://github.com/%{owner}/%{project}/ +Source0: https://github.com/%{owner}/%{project}/archive/%{commit}/%{project}-%{commit}.tar.gz +Source1: https://files.pythonhosted.org/packages/source/d/%{docker_pycreds_pypi_name}/%{docker_pycreds_pypi_name}-%{docker_pycreds_version}.tar.gz +Patch1: remote-inspection.patch +Patch2: setup-Neuter-extras_require-that-doesn-t-work-on-Cen.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1486189 +Patch3: implement-cpu_rt_-switches.patch +# This patch fixes https://bugzilla.redhat.com/show_bug.cgi?id=1501782 and also +# contains all the fixes which happened in utils/socket.py; this module covers +# the streaming connections, custom protocol of exec/attach and other +# socket-related operations +Patch4: backport-util-socket-fixes-rhbz1501782.patch + +BuildArch: noarch +BuildRequires: python2-devel +BuildRequires: python-setuptools + +Requires: python-requests +Requires: python-websocket-client >= 0.32.0 +Requires: python-six >= 1.4.0 +Requires: python-ipaddress +Requires: python-backports-ssl_match_hostname +Requires: python-docker-pycreds + +Obsoletes: docker-python <= 1.4.0-115.x86_64 +Provides: docker-python == %{version}-%{release} + +%description +%{summary} + + +%package -n python-docker-pycreds +Summary: Python bindings for the docker credentials store API +License: ASL 2.0 +URL: https://github.com/shin-/dockerpy-creds/ +BuildArch: noarch +Requires: python-six + +%description -n python-docker-pycreds +Python bindings for the docker credentials store API + + +%prep +%setup -q -n %{project}-%{commit} +%patch1 -p 1 +%patch2 -p 1 +%patch3 -p 1 +%patch4 -p 1 +gzip -dc %{SOURCE1} | tar -xvvf - + + +%build +%{__python} setup.py build +pushd %{docker_pycreds_pypi_name}-%{docker_pycreds_version} +%{__python} setup.py build +popd + + +%install +%{__python} setup.py install --root %{buildroot} +pushd %{docker_pycreds_pypi_name}-%{docker_pycreds_version} +%{__python} setup.py install --root %{buildroot} +popd + + +%files +%doc LICENSE README.md +%{python_sitelib}/docker +%{python_sitelib}/docker_py-%{version}* + + +%files -n python-docker-pycreds +%doc %{docker_pycreds_pypi_name}-%{docker_pycreds_version}/LICENSE %{docker_pycreds_pypi_name}-%{docker_pycreds_version}/README.md +%{python_sitelib}/dockerpycreds +%{python_sitelib}/docker_pycreds-%{docker_pycreds_version}* + + +%changelog +* Thu May 10 2018 Tomas Tomecek - 1.10.6-4 +- Resolve #1501782: don't break on 0-length frames + +* Wed Sep 06 2017 Tomas Tomecek - 1.10.6-3 +- fix the backport of cpu_rt_* options + +* Mon Sep 04 2017 Tomas Tomecek - 1.10.6-2 +- backport cpu_rt_* options, rhbz#1486189 + +* Tue Dec 20 2016 Tomas Tomecek - 1.10.6-1 +- update to 1.10.6 + +* Wed Sep 07 2016 Lokesh Mandvekar - 1.9.0-1 +- Resolves: #1374058 - rebase to upstream 1.9.0 + +* Fri Mar 04 2016 Tomas Tomecek - 1.7.2-1 +- new upstream release: 1.7.2 + +* Wed Jan 13 2016 Tomas Tomecek - 1.6.0-1 +- update to 1.6.0 + +* Wed Nov 04 2015 Lokesh Mandvekar - 1.4.0-118 +- Resolves: rhbz#1254579 - previous docker-python was archful + +* Wed Sep 23 2015 Lokesh Mandvekar - 1.4.0-117 +- obsoletes docker-python + +* Wed Sep 23 2015 Lokesh Mandvekar - 1.4.0-116 +- built @rhatdan/master commit#54a154d + +* Fri Jun 19 2015 Lokesh Mandvekar - 1.2.3-1 +- Rebase to 1.2.3 + +* Thu Jun 18 2015 Lokesh Mandvekar - 1.2.2-1 +- update to 1.2.2 +- do not enforce min VR on python-coverage +- test only if docker.sock is writable + +* Wed Feb 25 2015 Lokesh Mandvekar - 1.0.0-1 +- update to upstream 1.0.0 +- Resolves: rhbz#1195627 - don't (B)R docker +- use github url instead of pypi +- run tests in check if /run/docker.sock exists + +* Wed Jan 14 2015 Lokesh Mandvekar - 0.7.1-1 +- Resolves: rhbz#1182003 - Update to 0.7.1 + +* Thu Dec 25 2014 Igor Gnatenko - 0.7.0-1 +- Update to 0.7.0 (RHBZ #1176950) + +* Mon Dec 01 2014 Tomas Radej - 0.6.0-2 +- Added Python 3 subpackage + +* Fri Nov 21 2014 Lokesh Mandvekar - 0.6.0-1 +- Resolves: rhbz#1160293 - update to 0.6.0 + +* Thu Oct 23 2014 Lokesh Mandvekar - 0.5.3-2 +- Resolves: rhbz#1145895 +- versioned python-requests req only for f21+ + +* Wed Oct 22 2014 Lokesh Mandvekar - 0.5.3-1 +- Resolves: rhbz#1153991 - update to 0.5.3 + +* Tue Sep 23 2014 Tom Prince - 0.5.0-2 +- Specify depedencies to match those in setup.py + +* Mon Sep 22 2014 Tom Prince - 0.5.0-1 +- Resolves: rhbz#1145511 - version bump to 0.5.0 + +* Tue Aug 26 2014 Lokesh Mandvekar - 0.4.0-3 +- correct bogus date + +* Tue Aug 26 2014 Lokesh Mandvekar - 0.4.0-2 +- rewrite BR&R conditionals for docker/docker-io + +* Thu Aug 21 2014 Lokesh Mandvekar - 0.4.0-1 +- update to 0.4.0 +- Resolves: rhbz#1132604 (epel7 only) + +* Sun Aug 17 2014 Fedora Release Engineering - 0.3.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Sat Jul 12 2014 Lokesh Mandvekar - 0.3.2-1 +- version bump to 0.3.2 +- Resolves: rhbz#1097415 + +* Sat Jun 07 2014 Fedora Release Engineering - 0.2.3-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Mon Feb 10 2014 Lokesh Mandvekar 0.2.3-8 +- Bug 1063369 - Fix APIError for python-requests-1.1 on rhel6 + +* Sat Feb 08 2014 Lokesh Mandvekar 0.2.3-7 +- Bug 1048667 - disable debug package cause archful + +* Fri Feb 07 2014 Lokesh Mandvekar 0.2.3-6 +- doesn't need python-mock at runtime + +* Thu Jan 09 2014 Lokesh Mandvekar 0.2.3-5 +- python3 to be added after python3-websocket-client (BZ 1049424) + +* Tue Jan 07 2014 Lokesh Mandvekar 0.2.3-4 +- double '%' to comment macros +- check section not considered for now +- python3- description in python3- subpackage conditional + +* Tue Jan 07 2014 Lokesh Mandvekar 0.2.3-3 +- Everything goes in main package +- python3 package requires corrected +- package name python-docker-py +- both packages require docker-io + +* Mon Jan 06 2014 Lokesh Mandvekar 0.2.3-2 +- python3 subpackage +- upstream uses PyPI +- package owns directories it creates +- build and runtime deps updated + +* Sun Jan 05 2014 Lokesh Mandvekar 0.2.3-1 +- Initial fedora package