Hello community,

here is the log from the commit of package python-bencode for openSUSE:Factory 
checked in at 2019-06-06 18:16:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-bencode (Old)
 and      /work/SRC/openSUSE:Factory/.python-bencode.new.4811 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-bencode"

Thu Jun  6 18:16:52 2019 rev:5 rq:707409 version:2.0.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-bencode/python-bencode.changes    
2018-12-13 19:39:38.713357308 +0100
+++ /work/SRC/openSUSE:Factory/.python-bencode.new.4811/python-bencode.changes  
2019-06-06 18:16:54.300693360 +0200
@@ -1,0 +2,11 @@
+Tue Jun  4 07:01:19 UTC 2019 - [email protected]
+
+- version update to 2.0.0
+  * Support for bytes
+  * File read/write functions: bread(fp), bwrite(data, fp)
+  * Improved support for unicode strings
+- added sources
+  https://github.com/fuzeman/bencode.py/issues/12
+  + BitTorrent-1.1.txt
+
+-------------------------------------------------------------------

Old:
----
  bencode.py-1.2.0.tar.gz

New:
----
  BitTorrent-1.1.txt
  bencode.py-2.0.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-bencode.spec ++++++
--- /var/tmp/diff_new_pack.sIIvlF/_old  2019-06-06 18:16:54.832693204 +0200
+++ /var/tmp/diff_new_pack.sIIvlF/_new  2019-06-06 18:16:54.832693204 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-bencode
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,17 +19,22 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define oldpython python
 Name:           python-bencode
-Version:        1.2.0
+Version:        2.0.0
 Release:        0
 Summary:        The BitTorrent bencode module as light-weight, standalone 
package
 License:        BitTorrent-1.1
 Group:          Development/Languages/Python
-Url:            http://bittorrent.com/
-Source:         
https://files.pythonhosted.org/packages/source/b/bencode.py/bencode.py-1.2.0.tar.gz
+Url:            https://github.com/fuzeman/bencode.py
+Source0:        
https://files.pythonhosted.org/packages/source/b/bencode.py/bencode.py-%{version}.tar.gz
+# https://github.com/fuzeman/bencode.py/issues/12
+Source1:        
https://raw.githubusercontent.com/spdx/license-list/master/BitTorrent-1.1.txt
 BuildRequires:  %{python_module pbr}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
+# SECTION test requirements
+BuildRequires:  %{python_module pytest}
+# /SECTION
 BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 BuildArch:      noarch
 %python_subpackages
@@ -42,6 +47,7 @@
 
 %prep
 %setup -q -n bencode.py-%{version}
+cp %{SOURCE1} .
 
 %build
 %python_build
@@ -50,8 +56,12 @@
 %python_install
 %python_expand %fdupes -s %{buildroot}%{$python_sitelib}
 
+%check
+%pytest
+
 %files %{python_files}
 %defattr(-,root,root,-)
+%license BitTorrent-1.1.txt
 %doc README.rst
 %{python_sitelib}/*
 

++++++ BitTorrent-1.1.txt ++++++
BitTorrent Open Source License
Version 1.1

This BitTorrent Open Source License (the "License") applies to the BitTorrent 
client and related software products as well as any updates or maintenance 
releases of that software ("BitTorrent Products") that are distributed by 
BitTorrent, Inc. ("Licensor"). Any BitTorrent Product licensed pursuant to this 
License is a Licensed Product. Licensed Product, in its entirety, is protected 
by U.S. copyright law. This License identifies the terms under which you may 
use, copy, distribute or modify Licensed Product.

Preamble

This Preamble is intended to describe, in plain English, the nature and scope 
of this License. However, this Preamble is not a part of this license. The 
legal effect of this License is dependent only upon the terms of the License 
and not this Preamble.

This License complies with the Open Source Definition and is derived from the 
Jabber Open Source License 1.0 (the "JOSL"), which has been approved by Open 
Source Initiative. Sections 4(c) and 4(f)(iii) from the JOSL have been deleted.

This License provides that:

1. You may use or give away the Licensed Product, alone or as a component of an 
aggregate software distribution containing programs from several different 
sources. No royalty or other fee is required.

2. Both Source Code and executable versions of the Licensed Product, including 
Modifications made by previous Contributors, are available for your use. (The 
terms "Licensed Product," "Modifications," "Contributors" and "Source Code" are 
defined in the License.)

3. You are allowed to make Modifications to the Licensed Product, and you can 
create Derivative Works from it. (The term "Derivative Works" is defined in the 
License.)

4. By accepting the Licensed Product under the provisions of this License, you 
agree that any Modifications you make to the Licensed Product and then 
distribute are governed by the provisions of this License. In particular, you 
must make the Source Code of your Modifications available to others free of 
charge and without a royalty.

5. You may sell, accept donations or otherwise receive compensation for 
executable versions of a Licensed Product, without paying a royalty or other 
fee to the Licensor or any Contributor, provided that such executable versions 
contain your or another Contributor's material Modifications. For the avoidance 
of doubt, to the extent your executable version of a Licensed Product does not 
contain your or another Contributor's material Modifications, you may not sell, 
accept donations or otherwise receive compensation for such executable.

You may use the Licensed Product for any purpose, but the Licensor is not 
providing you any warranty whatsoever, nor is the Licensor accepting any 
liability in the event that the Licensed Product doesn't work properly or 
causes you any injury or damages.

6. If you sublicense the Licensed Product or Derivative Works, you may charge 
fees for warranty or support, or for accepting indemnity or liability 
obligations to your customers. You cannot charge for, sell, accept donations or 
otherwise receive compensation for the Source Code.

7. If you assert any patent claims against the Licensor relating to the 
Licensed Product, or if you breach any terms of the License, your rights to the 
Licensed Product under this License automatically terminate.
You may use this License to distribute your own Derivative Works, in which case 
the provisions of this License will apply to your Derivative Works just as they 
do to the original Licensed Product.

Alternatively, you may distribute your Derivative Works under any other 
OSI-approved Open Source license, or under a proprietary license of your 
choice. If you use any license other than this License, however, you must 
continue to fulfill the requirements of this License (including the provisions 
relating to publishing the Source Code) for those portions of your Derivative 
Works that consist of the Licensed Product, including the files containing 
Modifications.

New versions of this License may be published from time to time in connection 
with new versions of a Licensed Product or otherwise. You may choose to 
continue to use the license terms in this version of the License for the 
Licensed Product that was originally licensed hereunder, however, the new 
versions of this License will at all times apply to new versions of the 
Licensed Product released by Licensor after the release of the new version of 
this License. Only the Licensor has the right to change the License terms as 
they apply to the Licensed Product.

This License relies on precise definitions for certain terms. Those terms are 
defined when they are first used, and the definitions are repeated for your 
convenience in a Glossary at the end of the License.

License Terms

1. Grant of License From Licensor. Subject to the terms and conditions of this 
License, Licensor hereby grants you a world-wide, royalty-free, non-exclusive 
license, subject to third party intellectual property claims, to do the 
following:

     a. Use, reproduce, modify, display, perform, sublicense and distribute any 
Modifications created by a Contributor or portions thereof, in both Source Code 
or as an executable program, either on an unmodified basis or as part of 
Derivative Works.
     b. Under claims of patents now or hereafter owned or controlled by 
Contributor, to make, use, sell, offer for sale, have made, and/or otherwise 
dispose of Modifications or portions thereof, but solely to the extent that any 
such claim is necessary to enable you to make, use, sell, offer for sale, have 
made, and/or otherwise dispose of Modifications or portions thereof or 
Derivative Works thereof.

2. Grant of License to Modifications From Contributor. "Modifications" means 
any additions to or deletions from the substance or structure of (i) a file 
containing a Licensed Product, or (ii) any new file that contains any part of a 
Licensed Product. Hereinafter in this License, the term "Licensed Product" 
shall include all previous Modifications that you receive from any Contributor. 
Subject to the terms and conditions of this License, By application of the 
provisions in Section 4(a) below, each person or entity who created or 
contributed to the creation of, and distributed, a Modification (a 
"Contributor") hereby grants you a world-wide, royalty-free, non-exclusive 
license, subject to third party intellectual property claims, to do the 
following:

     a. Use, reproduce, modify, display, perform, sublicense and distribute any 
Modifications created by such Contributor or portions thereof, in both Source 
Code or as an executable program, either on an unmodified basis or as part of 
Derivative Works.

     b. Under claims of patents now or hereafter owned or controlled by 
Contributor, to make, use, sell, offer for sale, have made, and/or otherwise 
dispose of Modifications or portions thereof, but solely to the extent that any 
such claim is necessary to enable you to make, use, sell, offer for sale, have 
made, and/or otherwise dispose of Modifications or portions thereof or 
Derivative Works thereof.

3. Exclusions From License Grant. Nothing in this License shall be deemed to 
grant any rights to trademarks, copyrights, patents, trade secrets or any other 
intellectual property of Licensor or any Contributor except as expressly stated 
herein. No patent license is granted separate from the Licensed Product, for 
code that you delete from the Licensed Product, or for combinations of the 
Licensed Product with other software or hardware. No right is granted to the 
trademarks of Licensor or any Contributor even if such marks are included in 
the Licensed Product. Nothing in this License shall be interpreted to prohibit 
Licensor from licensing under different terms from this License any code that 
Licensor otherwise would have a right to license. As an express condition for 
your use of the Licensed Product, you hereby agree that you will not, without 
the prior written consent of Licensor, use any trademarks, copyrights, patents, 
trade secrets or any other intellectual property of Licensor or any Contributor 
except as expressly stated herein. For the avoidance of doubt and without 
limiting the foregoing, you hereby agree that you will not use or display any 
trademark of Licensor or any Contributor in any domain name, directory 
filepath, advertisement, link or other reference to you in any manner or in any 
media.

4. Your Obligations Regarding Distribution.

     a. Application of This License to Your Modifications. As an express 
condition for your use of the Licensed Product, you hereby agree that any 
Modifications that you create or to which you contribute, and which you 
distribute, are governed by the terms of this License including, without 
limitation, Section 2. Any Modifications that you create or to which you 
contribute may be distributed only under the terms of this License or a future 
version of this License released under Section 7. You must include a copy of 
this License with every copy of the Modifications you distribute. You agree not 
to offer or impose any terms on any Source Code or executable version of the 
Licensed Product or Modifications that alter or restrict the applicable version 
of this License or the recipients' rights hereunder. However, you may include 
an additional document offering the additional rights described in Section 4(d).
        
     b. Availability of Source Code. You must make available, without charge, 
under the terms of this License, the Source Code of the Licensed Product and 
any Modifications that you distribute, either on the same media as you 
distribute any executable or other form of the Licensed Product, or via a 
mechanism generally accepted in the software development community for the 
electronic transfer of data (an "Electronic Distribution Mechanism"). The 
Source Code for any version of Licensed Product or Modifications that you 
distribute must remain available for as long as any executable or other form of 
the Licensed Product is distributed by you. You are responsible for ensuring 
that the Source Code version remains available even if the Electronic 
Distribution Mechanism is maintained by a third party.
        
     c. Intellectual Property Matters.

          i. Third Party Claims. If you have knowledge that a license to a 
third party's intellectual property right is required to exercise the rights 
granted by this License, you must include a text file with the Source Code 
distribution titled "LEGAL" that describes the claim and the party making the 
claim in sufficient detail that a recipient will know whom to contact. If you 
obtain such knowledge after you make any Modifications available as described 
in Section 4(b), you shall promptly modify the LEGAL file in all copies you 
make available thereafter and shall take other steps (such as notifying 
appropriate mailing lists or newsgroups) reasonably calculated to inform those 
who received the Licensed Product from you that new knowledge has been obtained.
          ii. Contributor APIs. If your Modifications include an application 
programming interface ("API") and you have knowledge of patent licenses that 
are reasonably necessary to implement that API, you must also include this 
information in the LEGAL file.
          iii. Representations. You represent that, except as disclosed 
pursuant to 4(c)(i) above, you believe that any Modifications you distribute 
are your original creations and that you have sufficient rights to grant the 
rights conveyed by this License.
        
     d. Required Notices. You must duplicate this License in any documentation 
you provide along with the Source Code of any Modifications you create or to 
which you contribute, and which you distribute, wherever you describe 
recipients' rights relating to Licensed Product. You must duplicate the notice 
contained in Exhibit A (the "Notice") in each file of the Source Code of any 
copy you distribute of the Licensed Product. If you created a Modification, you 
may add your name as a Contributor to the Notice. If it is not possible to put 
the Notice in a particular Source Code file due to its structure, then you must 
include such Notice in a location (such as a relevant directory file) where a 
user would be likely to look for such a notice. You may choose to offer, and 
charge a fee for, warranty, support, indemnity or liability obligations to one 
or more recipients of Licensed Product. However, you may do so only on your own 
behalf, and not on behalf of the Licensor or any Contributor. You must make it 
clear that any such warranty, support, indemnity or liability obligation is 
offered by you alone, and you hereby agree to indemnify the Licensor and every 
Contributor for any liability incurred by the Licensor or such Contributor as a 
result of warranty, support, indemnity or liability terms you offer.
        
     e. Distribution of Executable Versions. You may distribute Licensed 
Product as an executable program under a license of your choice that may 
contain terms different from this License provided (i) you have satisfied the 
requirements of Sections 4(a) through 4(d) for that distribution, (ii) you 
include a conspicuous notice in the executable version, related documentation 
and collateral materials stating that the Source Code version of the Licensed 
Product is available under the terms of this License, including a description 
of how and where you have fulfilled the obligations of Section 4(b), and (iii) 
you make it clear that any terms that differ from this License are offered by 
you alone, not by Licensor or any Contributor. You hereby agree to indemnify 
the Licensor and every Contributor for any liability incurred by Licensor or 
such Contributor as a result of any terms you offer.

     f. Distribution of Derivative Works. You may create Derivative Works 
(e.g., combinations of some or all of the Licensed Product with other code) and 
distribute the Derivative Works as products under any other license you select, 
with the proviso that the requirements of this License are fulfilled for those 
portions of the Derivative Works that consist of the Licensed Product or any 
Modifications thereto.

     g. Compensation for Distribution of Executable Versions of Licensed 
Products, Modifications or Derivative Works. Notwithstanding any provision of 
this License to the contrary, by distributing, selling, licensing, sublicensing 
or otherwise making available any Licensed Product, or Modification or 
Derivative Work thereof, you and Licensor hereby acknowledge and agree that you 
may sell, license or sublicense for a fee, accept donations or otherwise 
receive compensation for executable versions of a Licensed Product, without 
paying a royalty or other fee to the Licensor or any other Contributor, 
provided that such executable versions (i) contain your or another 
Contributor's material Modifications, or (ii) are otherwise material Derivative 
Works. For purposes of this License, an executable version of the Licensed 
Product will be deemed to contain a material Modification, or will otherwise be 
deemed a material Derivative Work, if (a) the Licensed Product is modified with 
your own or a third party's software programs or other code, and/or the 
Licensed Product is combined with a number of your own or a third party's 
software programs or code, respectively, and (b) such software programs or code 
add or contribute material value, functionality or features to the License 
Product. For the avoidance of doubt, to the extent your executable version of a 
Licensed Product does not contain your or another Contributor's material 
Modifications or is otherwise not a material Derivative Work, in each case as 
contemplated herein, you may not sell, license or sublicense for a fee, accept 
donations or otherwise receive compensation for such executable. Additionally, 
without limitation of the foregoing and notwithstanding any provision of this 
License to the contrary, you cannot charge for, sell, license or sublicense for 
a fee, accept donations or otherwise receive compensation for the Source Code.

5. Inability to Comply Due to Statute or Regulation. If it is impossible for 
you to comply with any of the terms of this License with respect to some or all 
of the Licensed Product due to statute, judicial order, or regulation, then you 
must (i) comply with the terms of this License to the maximum extent possible, 
(ii) cite the statute or regulation that prohibits you from adhering to the 
License, and (iii) describe the limitations and the code they affect. Such 
description must be included in the LEGAL file described in Section 4(d), and 
must be included with all distributions of the Source Code. Except to the 
extent prohibited by statute or regulation, such description must be 
sufficiently detailed for a recipient of ordinary skill at computer programming 
to be able to understand it.

6. Application of This License. This License applies to code to which Licensor 
or Contributor has attached the Notice in Exhibit A, which is incorporated 
herein by this reference.

7. Versions of This License.

     a. New Versions. Licensor may publish from time to time revised and/or new 
versions of the License.
     
     b. Effect of New Versions. Once Licensed Product has been published under 
a particular version of the License, you may always continue to use it under 
the terms of that version, provided that any such license be in full force and 
effect at the time, and has not been revoked or otherwise terminated. You may 
also choose to use such Licensed Product under the terms of any subsequent 
version (but not any prior version) of the License published by Licensor. No 
one other than Licensor has the right to modify the terms applicable to 
Licensed Product created under this License.

     c. Derivative Works of this License. If you create or use a modified 
version of this License, which you may do only in order to apply it to software 
that is not already a Licensed Product under this License, you must rename your 
license so that it is not confusingly similar to this License, and must make it 
clear that your license contains terms that differ from this License. In so 
naming your license, you may not use any trademark of Licensor or any 
Contributor.

8. Disclaimer of Warranty. LICENSED PRODUCT IS PROVIDED UNDER THIS LICENSE ON 
AN AS IS BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE LICENSED PRODUCT IS FREE OF 
DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE 
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LICENSED PRODUCT IS WITH 
YOU. SHOULD LICENSED PRODUCT PROVE DEFECTIVE IN ANY RESPECT, YOU (AND NOT THE 
LICENSOR OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, 
REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART 
OF THIS LICENSE. NO USE OF LICENSED PRODUCT IS AUTHORIZED HEREUNDER EXCEPT 
UNDER THIS DISCLAIMER.

9. Termination.

     a. Automatic Termination Upon Breach. This license and the rights granted 
hereunder will terminate automatically if you fail to comply with the terms 
herein and fail to cure such breach within ten (10) days of being notified of 
the breach by the Licensor. For purposes of this provision, proof of delivery 
via email to the address listed in the 'WHOIS' database of the registrar for 
any website through which you distribute or market any Licensed Product, or to 
any alternate email address which you designate in writing to the Licensor, 
shall constitute sufficient notification. All sublicenses to the Licensed 
Product that are properly granted shall survive any termination of this license 
so long as they continue to complye with the terms of this License. Provisions 
that, by their nature, must remain in effect beyond the termination of this 
License, shall survive.

     b. Termination Upon Assertion of Patent Infringement. If you initiate 
litigation by asserting a patent infringement claim (excluding declaratory 
judgment actions) against Licensor or a Contributor (Licensor or Contributor 
against whom you file such an action is referred to herein as Respondent) 
alleging that Licensed Product directly or indirectly infringes any patent, 
then any and all rights granted by such Respondent to you under Sections 1 or 2 
of this License shall terminate prospectively upon sixty (60) days notice from 
Respondent (the "Notice Period") unless within that Notice Period you either 
agree in writing (i) to pay Respondent a mutually agreeable reasonably royalty 
for your past or future use of Licensed Product made by such Respondent, or 
(ii) withdraw your litigation claim with respect to Licensed Product against 
such Respondent. If within said Notice Period a reasonable royalty and payment 
arrangement are not mutually agreed upon in writing by the parties or the 
litigation claim is not withdrawn, the rights granted by Licensor to you under 
Sections 1 and 2 automatically terminate at the expiration of said Notice 
Period.

     c. Reasonable Value of This License. If you assert a patent infringement 
claim against Respondent alleging that Licensed Product directly or indirectly 
infringes any patent where such claim is resolved (such as by license or 
settlement) prior to the initiation of patent infringement litigation, then the 
reasonable value of the licenses granted by said Respondent under Sections 1 
and 2 shall be taken into account in determining the amount or value of any 
payment or license.

     d. No Retroactive Effect of Termination. In the event of termination under 
Sections 9(a) or 9(b) above, all end user license agreements (excluding 
licenses to distributors and resellers) that have been validly granted by you 
or any distributor hereunder prior to termination shall survive termination.

10. Limitation of Liability. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, 
WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE 
LICENSOR, ANY CONTRIBUTOR, OR ANY DISTRIBUTOR OF LICENSED PRODUCT, OR ANY 
SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, 
SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, 
WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER 
FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN 
IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS 
LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL 
INJURY RESULTING FROM SUCH PARTYS NEGLIGENCE TO THE EXTENT APPLICABLE LAW 
PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR 
LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND 
LIMITATION MAY NOT APPLY TO YOU.

11. Responsibility for Claims. As between Licensor and Contributors, each party 
is responsible for claims and damages arising, directly or indirectly, out of 
its utilization of rights under this License. You agree to work with Licensor 
and Contributors to distribute such responsibility on an equitable basis. 
Nothing herein is intended or shall be deemed to constitute any admission of 
liability.

12. U.S. Government End Users. The Licensed Product is a commercial item, as 
that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of commercial 
computer software and commercial computer software documentation, as such terms 
are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 
48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End 
Users acquire Licensed Product with only those rights set forth herein.

13. Miscellaneous. This License represents the complete agreement concerning 
the subject matter hereof. If any provision of this License is held to be 
unenforceable, such provision shall be reformed only to the extent necessary to 
make it enforceable. This License shall be governed by California law 
provisions (except to the extent applicable law, if any, provides otherwise), 
excluding its conflict-of-law provisions. You expressly agree that in any 
litigation relating to this license the losing party shall be responsible for 
costs including, without limitation, court costs and reasonable attorneys fees 
and expenses. The application of the United Nations Convention on Contracts for 
the International Sale of Goods is expressly excluded. Any law or regulation 
that provides that the language of a contract shall be construed against the 
drafter shall not apply to this License.

14. Definition of You in This License. You throughout this License, whether in 
upper or lower case, means an individual or a legal entity exercising rights 
under, and complying with all of the terms of, this License or a future version 
of this License issued under Section 7. For legal entities, you includes any 
entity that controls, is controlled by, is under common control with, or 
affiliated with, you. For purposes of this definition, control means (i) the 
power, direct or indirect, to cause the direction or management of such entity, 
whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or 
more of the outstanding shares, or (iii) beneficial ownership of such entity. 
You are responsible for advising any affiliated entity of the terms of this 
License, and that any rights or privileges derived from or obtained by way of 
this License are subject to the restrictions outlined herein.

15. Glossary. All defined terms in this License that are used in more than one 
Section of this License are repeated here, in alphabetical order, for the 
convenience of the reader. The Section of this License in which each defined 
term is first used is shown in parentheses.

Contributor: Each person or entity who created or contributed to the creation 
of, and distributed, a Modification. (See Section 2)

Derivative Works: That term as used in this License is defined under U.S. 
copyright law. (See Section 1(b))

License: This BitTorrent Open Source License. (See first paragraph of License)

Licensed Product: Any BitTorrent Product licensed pursuant to this License. The 
term "Licensed Product" includes all previous Modifications from any 
Contributor that you receive. (See first paragraph of License and Section 2)

Licensor: BitTorrent, Inc. (See first paragraph of License)

Modifications: Any additions to or deletions from the substance or structure of 
(i) a file containing Licensed 
Product, or (ii) any new file that contains any part of Licensed Product. (See 
Section 2)

Notice: The notice contained in Exhibit A. (See Section 4(e))

Source Code: The preferred form for making modifications to the Licensed 
Product, including all modules contained therein, plus any associated interface 
definition files, scripts used to control compilation and installation of an 
executable program, or a list of differential comparisons against the Source 
Code of the Licensed Product. (See Section 1(a))

You: This term is defined in Section 14 of this License.

EXHIBIT A

The Notice below must appear in each file of the Source Code of any copy you 
distribute of the Licensed Product or any hereto. Contributors to any 
Modifications may add their own copyright notices to identify their own 
contributions.

License:
The contents of this file are subject to the BitTorrent Open Source License 
Version 1.0 (the License). You may not copy or use this file, in either source 
code or executable form, except in compliance with the License. You may obtain 
a copy of the License at http://www.bittorrent.com/license/.

Software distributed under the License is distributed on an AS IS basis, 
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for 
the specific language governing rights and limitations under the License.

BitTorrent, Inc.
++++++ bencode.py-1.2.0.tar.gz -> bencode.py-2.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/.gitignore 
new/bencode.py-2.0.0/.gitignore
--- old/bencode.py-1.2.0/.gitignore     2017-02-23 02:15:04.000000000 +0100
+++ new/bencode.py-2.0.0/.gitignore     2017-12-05 00:44:23.000000000 +0100
@@ -1,9 +1,11 @@
 /.cache
 /.coverage
+/.idea
 /.tox
 /build
 /dist
 /htmlcov
+/tests/.tmp
 
 *.egg-info
 *.iml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/.travis.yml 
new/bencode.py-2.0.0/.travis.yml
--- old/bencode.py-1.2.0/.travis.yml    2017-02-22 03:39:42.000000000 +0100
+++ new/bencode.py-2.0.0/.travis.yml    2017-12-05 03:17:24.000000000 +0100
@@ -12,7 +12,7 @@
 install:
   - travis_retry pip install coveralls
   - travis_retry pip install tox-travis
-  - if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then travis_retry pip install 
pyOpenSSL>=16.2.0; fi
+  - if [[ $TRAVIS_PYTHON_VERSION != 'pypy'* ]]; then travis_retry pip install 
cryptography~=1.3.4 pyOpenSSL~=16.2.0; fi
 script:
   tox
 after_success:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/MANIFEST.in 
new/bencode.py-2.0.0/MANIFEST.in
--- old/bencode.py-1.2.0/MANIFEST.in    2017-02-23 02:49:05.000000000 +0100
+++ new/bencode.py-2.0.0/MANIFEST.in    2017-12-05 03:38:55.000000000 +0100
@@ -1,5 +1,5 @@
 exclude *
 recursive-include bencode *.py
-recursive-include tests *
+recursive-include tests fixtures\* *.py
 include requirements*.txt .coveragerc .gitignore *.cfg *.in *.ini *.py *.rst 
*.yml
-global-exclude *.iml *.pyc
\ No newline at end of file
+global-exclude *.iml *.pyc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/PKG-INFO 
new/bencode.py-2.0.0/PKG-INFO
--- old/bencode.py-1.2.0/PKG-INFO       2017-02-23 02:59:31.000000000 +0100
+++ new/bencode.py-2.0.0/PKG-INFO       2017-12-05 03:41:55.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: bencode.py
-Version: 1.2.0
+Version: 2.0.0
 Summary: Simple bencode parser (for Python 2, Python 3 and PyPy)
 Home-page: https://github.com/fuzeman/bencode.py
 Author: Dean Gardiner
@@ -66,6 +66,14 @@
         
             Decode bencode formatted string ``value``.
         
+        ``bencode.bread(fd)``
+        
+            Read bencode formatted string from file or path ``fd``.
+        
+        ``bencode.bwrite(data, fd)``
+        
+            Write ``data`` as a bencode formatted string to file or path 
``fd``.
+        
         
 Keywords: bittorrent
 bencode
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/README.rst 
new/bencode.py-2.0.0/README.rst
--- old/bencode.py-1.2.0/README.rst     2017-02-23 02:51:49.000000000 +0100
+++ new/bencode.py-2.0.0/README.rst     2017-12-05 03:21:55.000000000 +0100
@@ -57,3 +57,11 @@
 ``bencode.decode(value)``
 
     Decode bencode formatted string ``value``.
+
+``bencode.bread(fd)``
+
+    Read bencode formatted string from file or path ``fd``.
+
+``bencode.bwrite(data, fd)``
+
+    Write ``data`` as a bencode formatted string to file or path ``fd``.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/bencode/__init__.py 
new/bencode.py-2.0.0/bencode/__init__.py
--- old/bencode.py-1.2.0/bencode/__init__.py    2017-02-23 02:27:20.000000000 
+0100
+++ new/bencode.py-2.0.0/bencode/__init__.py    2017-12-05 01:58:20.000000000 
+0100
@@ -1,206 +1,325 @@
-# The contents of this file are subject to the BitTorrent Open Source License
-# Version 1.1 (the License).  You may not copy or use this file, in either
-# source code or executable form, except in compliance with the License.  You
-# may obtain a copy of the License at http://www.bittorrent.com/license/.
-#
-# Software distributed under the License is distributed on an AS IS basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
-# for the specific language governing rights and limitations under the
-# License.
-
-# Written by Petru Paler
-
-"""bencode.py - bencode encoder + decoder."""
-
-from bencode.BTL import BTFailure
-from bencode.exceptions import BencodeDecodeError
-
-import sys
-
-__all__ = (
-    'BTFailure',
-    'BencodeDecodeError',
-    'bencode',
-    'bdecode',
-    'encode',
-    'decode'
-)
-
-
-def decode_int(x, f):
-    f += 1
-    newf = x.index('e', f)
-    n = int(x[f:newf])
-
-    if x[f] == '-':
-        if x[f + 1] == '0':
-            raise ValueError
-    elif x[f] == '0' and newf != f + 1:
-        raise ValueError
-
-    return n, newf + 1
-
-
-def decode_string(x, f):
-    colon = x.index(':', f)
-    n = int(x[f:colon])
-
-    if x[f] == '0' and colon != f + 1:
-        raise ValueError
-
-    colon += 1
-
-    return x[colon:colon + n], colon + n
-
-
-def decode_list(x, f):
-    r, f = [], f + 1
-
-    while x[f] != 'e':
-        v, f = decode_func[x[f]](x, f)
-        r.append(v)
-
-    return r, f + 1
-
-
-def decode_dict(x, f):
-    r, f = {}, f + 1
-
-    while x[f] != 'e':
-        k, f = decode_string(x, f)
-        r[k], f = decode_func[x[f]](x, f)
-
-    return r, f + 1
-
-
-# noinspection PyDictCreation
-decode_func = {}
-decode_func['l'] = decode_list
-decode_func['d'] = decode_dict
-decode_func['i'] = decode_int
-decode_func['0'] = decode_string
-decode_func['1'] = decode_string
-decode_func['2'] = decode_string
-decode_func['3'] = decode_string
-decode_func['4'] = decode_string
-decode_func['5'] = decode_string
-decode_func['6'] = decode_string
-decode_func['7'] = decode_string
-decode_func['8'] = decode_string
-decode_func['9'] = decode_string
-
-
-def bdecode(value):
-    """
-    Decode bencode formatted string ``value``.
-
-    :param value: Bencode formatted string
-    :type value: str
-
-    :return: Decoded value
-    :rtype: object
-    """
-    try:
-        r, l = decode_func[value[0]](value, 0)
-    except (IndexError, KeyError, ValueError):
-        raise BencodeDecodeError("not a valid bencoded string")
-
-    if l != len(value):
-        raise BencodeDecodeError("invalid bencoded value (data after valid 
prefix)")
-
-    return r
-
-
-class Bencached(object):
-    __slots__ = ['bencoded']
-
-    def __init__(self, s):
-        self.bencoded = s
-
-
-def encode_bencached(x, r):
-    r.append(x.bencoded)
-
-
-def encode_int(x, r):
-    r.extend(('i', str(x), 'e'))
-
-
-def encode_bool(x, r):
-    if x:
-        encode_int(1, r)
-    else:
-        encode_int(0, r)
-
-
-def encode_string(x, r):
-    r.extend((str(len(x)), ':', x))
-
-
-def encode_list(x, r):
-    r.append('l')
-
-    for i in x:
-        encode_func[type(i)](i, r)
-
-    r.append('e')
-
-
-def encode_dict(x, r):
-    r.append('d')
-    ilist = list(x.items())
-    ilist.sort()
-
-    for k, v in ilist:
-        r.extend((str(len(k)), ':', k))
-        encode_func[type(v)](v, r)
-
-    r.append('e')
-
-
-# noinspection PyDictCreation
-encode_func = {}
-encode_func[Bencached] = encode_bencached
-
-if sys.version_info[0] == 2:
-    from types import DictType, IntType, ListType, LongType, StringType, 
TupleType
-
-    encode_func[DictType] = encode_dict
-    encode_func[IntType] = encode_int
-    encode_func[ListType] = encode_list
-    encode_func[LongType] = encode_int
-    encode_func[StringType] = encode_string
-    encode_func[TupleType] = encode_list
-
-    try:
-        from types import BooleanType
-        encode_func[BooleanType] = encode_bool
-    except ImportError:
-        pass
-else:
-    encode_func[bool] = encode_bool
-    encode_func[dict] = encode_dict
-    encode_func[int] = encode_int
-    encode_func[list] = encode_list
-    encode_func[str] = encode_string
-    encode_func[tuple] = encode_list
-
-
-def bencode(value):
-    """
-    Encode ``value`` into the bencode format.
-
-    :param value: Value
-    :type value: object
-
-    :return: Bencode formatted string
-    :rtype: str
-    """
-    r = []
-    encode_func[type(value)](value, r)
-    return ''.join(r)
-
-
-# Method proxies (for compatibility with other libraries)
-decode = bdecode
-encode = bencode
+# The contents of this file are subject to the BitTorrent Open Source License
+# Version 1.1 (the License).  You may not copy or use this file, in either
+# source code or executable form, except in compliance with the License.  You
+# may obtain a copy of the License at http://www.bittorrent.com/license/.
+#
+# Software distributed under the License is distributed on an AS IS basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the License
+# for the specific language governing rights and limitations under the
+# License.
+
+# Written by Petru Paler
+
+"""bencode.py - bencode encoder + decoder."""
+
+from bencode.BTL import BTFailure
+from bencode.exceptions import BencodeDecodeError
+
+from collections import deque
+import sys
+
+try:
+    from collections import OrderedDict
+except ImportError:
+    OrderedDict = None
+
+try:
+    import pathlib
+except ImportError:
+    pathlib = None
+
+__all__ = (
+    'BTFailure',
+    'BencodeDecodeError',
+    'bencode',
+    'bdecode',
+    'bread',
+    'bwrite',
+    'encode',
+    'decode'
+)
+
+
+def decode_int(x, f):
+    f += 1
+    newf = x.index(b'e', f)
+    n = int(x[f:newf])
+
+    if x[f:f + 1] == b'-':
+        if x[f + 1:f + 2] == b'0':
+            raise ValueError
+    elif x[f:f + 1] == b'0' and newf != f + 1:
+        raise ValueError
+
+    return n, newf + 1
+
+
+def decode_string(x, f, try_decode_utf8=True, force_decode_utf8=False):
+    """Decode torrent bencoded 'string' in x starting at f.
+
+    An attempt is made to convert the string to a python string from utf-8.
+    However, both string and non-string binary data is intermixed in the
+    torrent bencoding standard. So we have to guess whether the byte
+    sequence is a string or just binary data. We make this guess by trying
+    to decode (from utf-8), and if that fails, assuming it is binary data.
+    There are some instances where the data SHOULD be a string though.
+    You can check enforce this by setting force_decode_utf8 to True. If the
+    decoding from utf-8 fails, an UnidcodeDecodeError is raised. Similarly,
+    if you know it should not be a string, you can skip the decoding
+    attempt by setting try_decode_utf8=False.
+    """
+    colon = x.index(b':', f)
+    n = int(x[f:colon])
+
+    if x[f:f + 1] == b'0' and colon != f + 1:
+        raise ValueError
+
+    colon += 1
+    s = x[colon:colon + n]
+
+    if try_decode_utf8:
+        try:
+            return s.decode('utf-8'), colon + n
+        except UnicodeDecodeError:
+            if force_decode_utf8:
+                raise
+
+    return bytes(s), colon + n
+
+
+def decode_list(x, f):
+    r, f = [], f + 1
+
+    while x[f:f + 1] != b'e':
+        v, f = decode_func[x[f:f + 1]](x, f)
+        r.append(v)
+
+    return r, f + 1
+
+
+def decode_dict_py26(x, f):
+    r, f = {}, f + 1
+
+    while x[f] != 'e':
+        k, f = decode_string(x, f)
+        r[k], f = decode_func[x[f]](x, f)
+
+    return r, f + 1
+
+
+def decode_dict(x, f, force_sort=True):
+    """Decode bencoded data to an OrderedDict.
+
+    The BitTorrent standard states that:
+        Keys must be strings and appear in sorted order (sorted as raw
+        strings, not alphanumerics)
+    - http://www.bittorrent.org/beps/bep_0003.html
+
+    Therefore, this function will force the keys to be strings (decoded
+    from utf-8), and by default the keys are (re)sorted after reading.
+    Set force_sort to False to keep the order of the dictionary as
+    represented in x, as many other encoders and decoders do not force this
+    property.
+    """
+    r, f = OrderedDict(), f + 1
+
+    while x[f:f + 1] != b'e':
+        k, f = decode_string(x, f, force_decode_utf8=True)
+        r[k], f = decode_func[x[f:f + 1]](x, f)
+
+    if force_sort:
+        r = OrderedDict(sorted(r.items()))
+
+    return r, f + 1
+
+
+# noinspection PyDictCreation
+decode_func = {}
+decode_func[b'l'] = decode_list
+decode_func[b'i'] = decode_int
+decode_func[b'0'] = decode_string
+decode_func[b'1'] = decode_string
+decode_func[b'2'] = decode_string
+decode_func[b'3'] = decode_string
+decode_func[b'4'] = decode_string
+decode_func[b'5'] = decode_string
+decode_func[b'6'] = decode_string
+decode_func[b'7'] = decode_string
+decode_func[b'8'] = decode_string
+decode_func[b'9'] = decode_string
+
+if sys.version_info[0] == 2 and sys.version_info[1] == 6:
+    decode_func[b'd'] = decode_dict_py26
+else:
+    decode_func[b'd'] = decode_dict
+
+
+def bdecode(value):
+    """
+    Decode bencode formatted string ``value``.
+
+    :param value: Bencode formatted string
+    :type value: str
+
+    :return: Decoded value
+    :rtype: object
+    """
+    try:
+        r, l = decode_func[value[0:1]](value, 0)
+    except (IndexError, KeyError, TypeError, ValueError):
+        raise BencodeDecodeError("not a valid bencoded string")
+
+    if l != len(value):
+        raise BencodeDecodeError("invalid bencoded value (data after valid 
prefix)")
+
+    return r
+
+
+class Bencached(object):
+    __slots__ = ['bencoded']
+
+    def __init__(self, s):
+        self.bencoded = s
+
+
+def encode_bencached(x, r):
+    r.append(x.bencoded)
+
+
+def encode_int(x, r):
+    r.extend((b'i', str(x).encode('utf-8'), b'e'))
+
+
+def encode_bool(x, r):
+    if x:
+        encode_int(1, r)
+    else:
+        encode_int(0, r)
+
+
+def encode_bytes(x, r):
+    r.extend((str(len(x)).encode('utf-8'), b':', x))
+
+
+def encode_string(x, r):
+    try:
+        s = x.encode('utf-8')
+    except UnicodeDecodeError:
+        return encode_bytes(x, r)
+
+    r.extend((str(len(s)).encode('utf-8'), b':', s))
+
+
+def encode_list(x, r):
+    r.append(b'l')
+
+    for i in x:
+        encode_func[type(i)](i, r)
+
+    r.append(b'e')
+
+
+def encode_dict(x, r):
+    r.append(b'd')
+    ilist = list(x.items())
+    ilist.sort()
+
+    for k, v in ilist:
+        k = k.encode('utf-8')
+        r.extend((str(len(k)).encode('utf-8'), b':', k))
+        encode_func[type(v)](v, r)
+
+    r.append(b'e')
+
+
+# noinspection PyDictCreation
+encode_func = {}
+encode_func[Bencached] = encode_bencached
+
+if sys.version_info[0] == 2:
+    from types import DictType, IntType, ListType, LongType, StringType, 
TupleType, UnicodeType
+
+    encode_func[DictType] = encode_dict
+    encode_func[IntType] = encode_int
+    encode_func[ListType] = encode_list
+    encode_func[LongType] = encode_int
+    encode_func[StringType] = encode_string
+    encode_func[TupleType] = encode_list
+    encode_func[UnicodeType] = encode_string
+
+    if OrderedDict is not None:
+        encode_func[OrderedDict] = encode_dict
+
+    try:
+        from types import BooleanType
+
+        encode_func[BooleanType] = encode_bool
+    except ImportError:
+        pass
+else:
+    encode_func[OrderedDict] = encode_dict
+    encode_func[bool] = encode_bool
+    encode_func[dict] = encode_dict
+    encode_func[int] = encode_int
+    encode_func[list] = encode_list
+    encode_func[str] = encode_string
+    encode_func[tuple] = encode_list
+    encode_func[bytes] = encode_bytes
+
+
+def bencode(value):
+    """
+    Encode ``value`` into the bencode format.
+
+    :param value: Value
+    :type value: object
+
+    :return: Bencode formatted string
+    :rtype: str
+    """
+    r = deque()  # makes more sense for something with lots of appends
+
+    # Encode provided value
+    encode_func[type(value)](value, r)
+
+    # Join parts
+    return b''.join(r)
+
+
+# Method proxies (for compatibility with other libraries)
+decode = bdecode
+encode = bencode
+
+
+def bread(fd):
+    """Return bdecoded data from filename, file, or file-like object.
+
+    if fd is a bytes/string or pathlib.Path-like object, it is opened and
+    read, otherwise .read() is used. if read() not available, exception
+    raised.
+    """
+    if isinstance(fd, (bytes, str)):
+        with open(fd, 'rb') as fd:
+            return bdecode(fd.read())
+    elif pathlib is not None and isinstance(fd, (pathlib.Path, 
pathlib.PurePath)):
+        with open(str(fd), 'rb') as fd:
+            return bdecode(fd.read())
+    else:
+        return bdecode(fd.read())
+
+
+def bwrite(data, fd):
+    """Write data in bencoded form to filename, file, or file-like object.
+
+    if fd is bytes/string or pathlib.Path-like object, it is opened and
+    written to, otherwise .write() is used. if write() is not available,
+    exception raised.
+    """
+    if isinstance(fd, (bytes, str)):
+        with open(fd, 'wb') as fd:
+            fd.write(bencode(data))
+    elif pathlib is not None and isinstance(fd, (pathlib.Path, 
pathlib.PurePath)):
+        with open(str(fd), 'wb') as fd:
+            fd.write(bencode(data))
+    else:
+        fd.write(bencode(data))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/bencode.py.egg-info/PKG-INFO 
new/bencode.py-2.0.0/bencode.py.egg-info/PKG-INFO
--- old/bencode.py-1.2.0/bencode.py.egg-info/PKG-INFO   2017-02-23 
02:59:28.000000000 +0100
+++ new/bencode.py-2.0.0/bencode.py.egg-info/PKG-INFO   2017-12-05 
03:41:47.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: bencode.py
-Version: 1.2.0
+Version: 2.0.0
 Summary: Simple bencode parser (for Python 2, Python 3 and PyPy)
 Home-page: https://github.com/fuzeman/bencode.py
 Author: Dean Gardiner
@@ -66,6 +66,14 @@
         
             Decode bencode formatted string ``value``.
         
+        ``bencode.bread(fd)``
+        
+            Read bencode formatted string from file or path ``fd``.
+        
+        ``bencode.bwrite(data, fd)``
+        
+            Write ``data`` as a bencode formatted string to file or path 
``fd``.
+        
         
 Keywords: bittorrent
 bencode
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/bencode.py.egg-info/SOURCES.txt 
new/bencode.py-2.0.0/bencode.py.egg-info/SOURCES.txt
--- old/bencode.py-1.2.0/bencode.py.egg-info/SOURCES.txt        2017-02-23 
02:59:31.000000000 +0100
+++ new/bencode.py-2.0.0/bencode.py.egg-info/SOURCES.txt        2017-12-05 
03:41:55.000000000 +0100
@@ -17,4 +17,6 @@
 bencode.py.egg-info/pbr.json
 bencode.py.egg-info/top_level.txt
 tests/__init__.py
-tests/bencode_tests.py
\ No newline at end of file
+tests/bencode_tests.py
+tests/file_tests.py
+tests/fixtures/alpha
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/bencode.py.egg-info/pbr.json 
new/bencode.py-2.0.0/bencode.py.egg-info/pbr.json
--- old/bencode.py-1.2.0/bencode.py.egg-info/pbr.json   2017-02-23 
02:59:29.000000000 +0100
+++ new/bencode.py-2.0.0/bencode.py.egg-info/pbr.json   2017-12-05 
03:41:49.000000000 +0100
@@ -1 +1 @@
-{"is_release": true, "git_version": "0aef61f"}
\ No newline at end of file
+{"git_version": "17923d5", "is_release": true}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/setup.cfg 
new/bencode.py-2.0.0/setup.cfg
--- old/bencode.py-1.2.0/setup.cfg      2017-02-23 02:59:31.000000000 +0100
+++ new/bencode.py-2.0.0/setup.cfg      2017-12-05 03:41:55.000000000 +0100
@@ -41,5 +41,4 @@
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/tests/bencode_tests.py 
new/bencode.py-2.0.0/tests/bencode_tests.py
--- old/bencode.py-1.2.0/tests/bencode_tests.py 2017-02-23 02:33:06.000000000 
+0100
+++ new/bencode.py-2.0.0/tests/bencode_tests.py 2017-12-05 02:09:53.000000000 
+0100
@@ -3,97 +3,156 @@
 
 """bencode.py tests."""
 
-from bencode import BTFailure, bencode, bdecode
+from bencode import Bencached, BTFailure, bencode, bdecode
 
-import unittest
+import pytest
+import sys
 
+try:
+    from collections import OrderedDict
+except ImportError:
+    OrderedDict = None
 
-class KnownValues(unittest.TestCase):
-    """
-    Test known bencode values.
-
-    Example values partially taken from http://en.wikipedia.org/wiki/Bencode, 
test case inspired
-    by Mark Pilgrim's examples: 
http://diveintopython.org/unit_testing/romantest.html
-    """
-
-    knownValues = (
-        (0, 'i0e'),
-        (1, 'i1e'),
-        (10, 'i10e'),
-        (42, 'i42e'),
-        (-42, 'i-42e'),
-        (True, 'i1e'),
-        (False, 'i0e'),
-        ('spam', '4:spam'),
-        ('parrot sketch', '13:parrot sketch'),
-        (['parrot sketch', 42], 'l13:parrot sketchi42ee'),
-        ({
-            'foo': 42,
-            'bar': 'spam'
-        }, 'd3:bar4:spam3:fooi42ee'),
-    )
-
-    def testBencodeKnownValues(self):
-        """Encode should give known result with known input."""
-        for plain, encoded in self.knownValues:
-            result = bencode(plain)
-            self.assertEqual(encoded, result)
-
-    def testBdecodeKnownValues(self):
-        """Decode should give known result with known input."""
-        for plain, encoded in self.knownValues:
-            result = bdecode(encoded)
-            self.assertEqual(plain, result)
-
-    def testRoundtripEncoded(self):
-        """Consecutive calls to decode and encode should deliver the original 
data again."""
-        for plain, encoded in self.knownValues:
-            result = bdecode(encoded)
-            self.assertEqual(encoded, bencode(result))
-
-    def testRoundtripDecoded(self):
-        """Consecutive calls to encode and decode should deliver the original 
data again."""
-        for plain, encoded in self.knownValues:
-            result = bencode(plain)
-            self.assertEqual(plain, bdecode(result))
 
+VALUES = [
+    (0, 'i0e'),
+    (1, 'i1e'),
+    (10, 'i10e'),
+    (42, 'i42e'),
+    (-42, 'i-42e'),
+    (True, 'i1e'),
+    (False, 'i0e'),
+    ('spam', '4:spam'),
+    ('parrot sketch', '13:parrot sketch'),
+    (['parrot sketch', 42], 'l13:parrot sketchi42ee'),
+    ({'foo': 42, 'bar': 'spam'}, 'd3:bar4:spam3:fooi42ee')
+]
 
-class IllegalValues(unittest.TestCase):
-    """Test handling of illegal values."""
+if OrderedDict is not None:
+    VALUES.append((OrderedDict((
+        ('bar', 'spam'),
+        ('foo', 42)
+    )), 'd3:bar4:spam3:fooi42ee'))
 
+
[email protected](sys.version_info[0] < 3, reason="Requires: Python 3+")
+def test_encode():
+    """Encode should give known result with known input."""
+    for plain, encoded in VALUES:
+        assert encoded.encode('utf-8') == bencode(plain)
+
+
[email protected](sys.version_info[0] != 2, reason="Requires: Python 2")
+def test_encode_py2():
+    """Encode should give known result with known input."""
+    for plain, encoded in VALUES:
+        assert encoded == bencode(plain)
+
+
[email protected](sys.version_info[0] < 3, reason="Requires: Python 3+")
+def test_encode_bencached():
+    """Ensure Bencached objects can be encoded."""
+    assert bencode([Bencached(bencode('test'))]) == b'l4:teste'
+
+
[email protected](sys.version_info[0] != 2, reason="Requires: Python 2")
+def test_encode_bencached_py2():
+    """Ensure Bencached objects can be encoded."""
+    assert bencode([Bencached(bencode('test'))]) == 'l4:teste'
+
+
+def test_encode_bytes():
+    """Ensure bytes can be encoded."""
+    assert bencode(b'\x9c') == b'1:\x9c'
+
+
[email protected](sys.version_info[0] < 3, reason="Requires: Python 3+")
+def test_decode():
+    """Decode should give known result with known input."""
+    for plain, encoded in VALUES:
+        assert plain == bdecode(encoded.encode('utf-8'))
+
+
[email protected](sys.version_info[0] != 2, reason="Requires: Python 2")
+def test_decode_py2():
+    """Decode should give known result with known input."""
+    for plain, encoded in VALUES:
+        assert plain == bdecode(encoded)
+
+
+def test_decode_bytes():
+    """Ensure bytes can be decoded."""
+    assert bdecode(b'1:\x9c') == b'\x9c'
+
+
[email protected](sys.version_info[0] < 3, reason="Requires: Python 3+")
+def test_encode_roundtrip():
+    """Consecutive calls to decode and encode should deliver the original data 
again."""
+    for plain, encoded in VALUES:
+        assert encoded.encode('utf-8') == 
bencode(bdecode(encoded.encode('utf-8')))
+
+
[email protected](sys.version_info[0] != 2, reason="Requires: Python 2")
+def test_encode_roundtrip_py2():
+    """Consecutive calls to decode and encode should deliver the original data 
again."""
+    for plain, encoded in VALUES:
+        assert encoded == bencode(bdecode(encoded))
+
+
+def test_decode_roundtrip():
+    """Consecutive calls to encode and decode should deliver the original data 
again."""
+    for plain, encoded in VALUES:
+        assert plain == bdecode(bencode(plain))
+
+
+# TODO: BTL implementation currently chokes on this type of input
+# def test_encode_float_error(self):
+#     """ floats cannot be encoded. """
+#     self.assertRaises(BTFailure, bencode, 1.0)
+
+def test_decode_parameter():
+    """Ensure non-strings raise an exception."""
     # TODO: BTL implementation currently chokes on this type of input
-    # def testFloatRaisesIllegalForEncode(self):
-    #     """ floats cannot be encoded. """
-    #     self.assertRaises(BTFailure, bencode, 1.0)
-
-    def testNonStringsRaiseIllegalInputForDecode(self):
-        """Ensure non-strings raise an exception."""
-        # TODO: BTL implementation currently chokes on this type of input
-        # self.assertRaises(BTFailure, bdecode, 0)
-        # self.assertRaises(BTFailure, bdecode, None)
-        # self.assertRaises(BTFailure, bdecode, 1.0)
-        self.assertRaises(BTFailure, bdecode, [1, 2])
-        self.assertRaises(BTFailure, bdecode, {'foo': 'bar'})
-
-    def testRaiseIllegalInputForDecode(self):
-        """Illegally formatted strings should raise an exception when 
decoded."""
-        self.assertRaises(BTFailure, bdecode, "foo")
-        self.assertRaises(BTFailure, bdecode, "x:foo")
-        self.assertRaises(BTFailure, bdecode, "x42e")
-
-
-class Dictionaries(unittest.TestCase):
-    """Test handling of dictionaries."""
-
-    def testSortedKeysForDicts(self):
-        """Ensure the keys of a dictionary are sorted before being encoded."""
-        encoded = bencode({'zoo': 42, 'bar': 'spam'})
-
-        self.failUnless(encoded.index('zoo') > encoded.index('bar'))
-
-    def testNestedDictionary(self):
-        """Test the handling of nested dicts."""
-        self.assertEqual(
-            bencode({'foo': 42, 'bar': {'sketch': 'parrot', 'foobar': 23}}),
-            'd3:bard6:foobari23e6:sketch6:parrote3:fooi42ee'
-        )
+    # self.assertRaises(BTFailure, bdecode, 0)
+    # self.assertRaises(BTFailure, bdecode, None)
+    # self.assertRaises(BTFailure, bdecode, 1.0)
+    with pytest.raises(BTFailure):
+        bdecode([1, 2])
+
+    with pytest.raises(BTFailure):
+        bdecode({'foo': 'bar'})
+
+
+def test_decode_errors():
+    """Illegally formatted strings should raise an exception when decoded."""
+    with pytest.raises(BTFailure):
+        bdecode("foo")
+
+    with pytest.raises(BTFailure):
+        bdecode("x:foo")
+
+    with pytest.raises(BTFailure):
+        bdecode("x42e")
+
+
+def test_dictionary_sorted():
+    """Ensure the keys of a dictionary are sorted before being encoded."""
+    encoded = bencode({'zoo': 42, 'bar': 'spam'})
+
+    assert encoded.index(b'zoo') > encoded.index(b'bar')
+
+
[email protected](sys.version_info[0] < 3, reason="Requires: Python 3+")
+def test_dictionary_nested():
+    """Test the handling of nested dictionaries."""
+    encoded = bencode({'foo': 42, 'bar': {'sketch': 'parrot', 'foobar': 23}})
+
+    assert encoded == 
'd3:bard6:foobari23e6:sketch6:parrote3:fooi42ee'.encode('utf-8')
+
+
[email protected](sys.version_info[0] != 2, reason="Requires: Python 2")
+def test_dictionary_nested_py2():
+    """Test the handling of nested dictionaries."""
+    encoded = bencode({'foo': 42, 'bar': {'sketch': 'parrot', 'foobar': 23}})
+
+    assert encoded == 'd3:bard6:foobari23e6:sketch6:parrote3:fooi42ee'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/tests/file_tests.py 
new/bencode.py-2.0.0/tests/file_tests.py
--- old/bencode.py-1.2.0/tests/file_tests.py    1970-01-01 01:00:00.000000000 
+0100
+++ new/bencode.py-2.0.0/tests/file_tests.py    2017-12-05 02:05:52.000000000 
+0100
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+"""bencode.py - file tests."""
+
+from bencode import bread, bwrite
+
+import os
+import pytest
+import sys
+
+FIXTURE_DIR = os.path.join(os.path.dirname(__file__), 'fixtures')
+TEMP_DIR = os.path.join(os.path.dirname(__file__), '.tmp')
+
+# Ensure temp directory exists
+if not os.path.exists(TEMP_DIR):
+    os.makedirs(TEMP_DIR)
+
+
+def test_read_file():
+    """Test the reading of bencode files."""
+    with open(os.path.join(FIXTURE_DIR, 'alpha'), 'rb') as fp:
+        data = bread(fp)
+
+        assert data == {'foo': 42, 'bar': {'sketch': 'parrot', 'foobar': 23}}
+
+
+def test_read_path():
+    """Test the reading of bencode paths."""
+    data = bread(os.path.join(FIXTURE_DIR, 'alpha'))
+
+    assert data == {'foo': 42, 'bar': {'sketch': 'parrot', 'foobar': 23}}
+
+
[email protected](sys.version_info < (3, 4), reason="Requires: Python 3.4+")
+def test_read_pathlib():
+    """Test the reading of bencode paths."""
+    from pathlib import Path
+
+    data = bread(Path(FIXTURE_DIR, 'alpha'))
+
+    assert data == {'foo': 42, 'bar': {'sketch': 'parrot', 'foobar': 23}}
+
+
+def test_write_file():
+    """Test the writing of bencode paths."""
+    with open(os.path.join(TEMP_DIR, 'beta'), 'wb') as fp:
+        bwrite(
+            {'foo': 42, 'bar': {'sketch': 'parrot', 'foobar': 23}},
+            fp
+        )
+
+    with open(os.path.join(TEMP_DIR, 'beta'), 'r') as fp:
+        assert fp.read() == 'd3:bard6:foobari23e6:sketch6:parrote3:fooi42ee'
+
+
+def test_write_path():
+    """Test the writing of bencode files."""
+    bwrite(
+        {'foo': 42, 'bar': {'sketch': 'parrot', 'foobar': 23}},
+        os.path.join(TEMP_DIR, 'beta')
+    )
+
+    with open(os.path.join(TEMP_DIR, 'beta'), 'r') as fp:
+        assert fp.read() == 'd3:bard6:foobari23e6:sketch6:parrote3:fooi42ee'
+
+
[email protected](sys.version_info < (3, 4), reason="Requires: Python 3.4+")
+def test_write_pathlib():
+    """Test the reading of bencode paths."""
+    from pathlib import Path
+
+    bwrite(
+        {'foo': 42, 'bar': {'sketch': 'parrot', 'foobar': 23}},
+        Path(TEMP_DIR, 'beta')
+    )
+
+    with open(os.path.join(TEMP_DIR, 'beta'), 'r') as fp:
+        assert fp.read() == 'd3:bard6:foobari23e6:sketch6:parrote3:fooi42ee'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/tests/fixtures/alpha 
new/bencode.py-2.0.0/tests/fixtures/alpha
--- old/bencode.py-1.2.0/tests/fixtures/alpha   1970-01-01 01:00:00.000000000 
+0100
+++ new/bencode.py-2.0.0/tests/fixtures/alpha   2017-12-05 00:36:09.000000000 
+0100
@@ -0,0 +1 @@
+d3:bard6:foobari23e6:sketch6:parrote3:fooi42ee
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/bencode.py-1.2.0/tox.ini new/bencode.py-2.0.0/tox.ini
--- old/bencode.py-1.2.0/tox.ini        2017-02-23 01:48:53.000000000 +0100
+++ new/bencode.py-2.0.0/tox.ini        2017-12-05 03:17:24.000000000 +0100
@@ -16,6 +16,16 @@
 commands =
   coverage erase
 
+[testenv:py26]
+deps =
+  pytest==3.2.4
+  pytest-cov
+
+[testenv:py33]
+deps =
+  pytest==3.2.4
+  pytest-cov
+
 [testenv:flake8]
 basepython = python
 skip_install = true


Reply via email to