2024-03-25 4.2.6 - Validate creation date if it exists. 2024-03-09 4.2.5 - Bugfix: Include symbolic links in the torrent's files. 2023-12-04 4.2.4 - Bugfix: Remove hardcoded minimum and maximum piece sizes from Torrent.calculate_piece_size(). 2023-12-01 4.2.3 - Torrent.calculate_piece_size() now returns 16 MiB for content sizes bigger than 16 GiB. (Thanks @cannibalChipper) 2023-09-11 4.2.2 - Fix a bug that was introduced in 4.2.0. Instead of forcibly decoding all encodings as UTF-8, go back to defaulting to undecoded bytes (like before) and only perform a decode-and-replace-invalid-characters routine on known strings like ["info"]["name"]. 2023-07-02 4.2.1 - Setting Torrent.piece_size_min/max now also sets Torrent.piece_size if it is too small/big. 2023-04-16 4.2.0 - When reading torrent files, strings are now always decoded as UTF-8 (except for ["info"]["pieces"]). This makes it harder to store binary data in non-standard fields, but it also means ["info"]["name"] is always a unicode string. - Allow any "piece length" that is divisible by 16 KiB. Previously, power of 2 was required. 2023-01-26 4.1.4 - Fix "Too many open files" error when creating a torrent with loads of small files. 2023-01-09 4.1.3 - Try to reduce memory usage before being out of memory. - Terminate piece hashing threads if they are idle for more than 500 milliseconds. 2022-11-24 4.1.2 - Bugfix: Torrent's piece_size_min and piece_size_max arguments are no longer ignored. - Torrent.piece_size_min and Torrent.piece_size_max are now properties. They default to the new class attributes piece_size_min_default and piece_size_max_default. - Torrent.calculate_piece_size(): New arguments: min_size, max_size specify the minimum and maximum piece size. 2022-11-15 4.1.1 - Bugfix: Don't crash if "creation date" is something weird like an empty string. 2022-11-09 4.1.0 - Torrent now accepts piece_size_min and piece_size_max arguments. - Bugfix: Don't reuse a torrent that has a smaller piece_size than piece_size_min. 2022-09-22 4.0.4 - Bugfix: Expect non-standard fields (e.g. "md5sum") in file list when reusing torrent. 2022-07-02 4.0.3 - Bugfix: Copy file order from reused torrent. 2022-06-19 4.0.2 - Bugfix: Don't reuse a torrent that has a bigger piece_size than piece_size_max. 2022-05-17 4.0.1 - Bugfix: RecursionError when pickling File objects 2022-05-05 4.0.0 - Torrent.verify(): The "skip_on_error" argument was removed. - The new TorrentFileStream class lets you operate on a torrent's stream of concatenated files. - The new attribute Torrent.location provides the file system path without the torrent's name. - The new Torrent.reuse() method copies piece hashes from an existing torrent file with the same name and file tree. It can also find a matching torrent in a bunch of directories. 2020-10-29 3.1.3 - Bugfix: Exclude tests from package. 2020-10-25 3.1.2 - Bugfix: Preserve binary values of fields that aren't part of the BitTorrent specification. (Thanks, @ayasechan) 2020-09-26 3.1.1 - Bugfix: Fix poor performance when torrent contains huge number of files (Thanks, @mon) 2020-08-11 3.1.0 - Bugfix: Gracefully handle empty string for "url-list" and other URL lists in metainfo - The new properties Torrent.include_globs and Torrent.include_regexs can be used to keep files even if they match an exclude pattern. 2020-06-20 3.0.2 - Bugfix: Torrent.validate() and Torrent.read_stream() now raise MetainfoError if the "info" field is not a dictionary. - Bugfix: Magnet.from_string() raised ValueError instead of MagnetError if the "xl" parameter wasn't a number. - Bugfix: Magnet.from_string() strips whitespace from the beginning and end before parsing the URI. - Bugfix: Magnet.kt used commas to separate keywords. (I don't know why.) - Bugfix: Gracefully handle empty path components in torrent file (e.g. "foo//bar") - Torrent.private is now None instead of False if there is no "private" field in the "info" section of the metainfo. 2020-04-07 3.0.1 - Make things work with Python 3.6. - Magnet.as_torrent is now a method called Magnet.torrent(). 2020-04-02 3.0.0 - Depend on flatbencode instead of bencoder.pyx - Bug fixed: Setting the "private" property to False removed the flag from the metainfo which could potentially change the info hash if a torrent file had the flag explicitly disabled. - Bug fixed: Torrent.read() validated if the "validate" argument was False - Hashing pieces uses multiple threads for better performance. - Support for the "md5sum" field was dropped. Calculating MD5 hashes besides the SHA1 hashes is no longer easily possible due to multithreading and it's unclear to me if/how this field is even useful. - The new methods Torrent.verify_content() and Torrent.verify_filesize() check if on-disk data matches a given torrent file. - The property Torrent.exclude was replaced by Torrent.exclude_globs and Torrent.exclude_regexs. These return special lists that filter files when changed. - Torrent.path is a path-like object. - Torrent.files, Torrent.filepaths, Torrent.trackers, Torrent.webseeds and Torrent.httpseeds are mutable lists of path-like objects or URLs that automatically synchronize with Torrent.metainfo when changed. - Torrent.filetree uses File objects as leaf nodes. File is a path-like object that also stores the file size. - The new class attributes Torrent.piece_size_min and Torrent.piece_size_max can be used to quickly specify piece size limits. Setting the piece_size property to an out-of-bounds piece size or returning one with Torrent.calculate_piece_size() raises PieceSizeError. - Torrent.validate() is better at finding invalid stuff in the metainfo. - Exceptions were added and removed. If you don't catch TorfError, make sure you're expecting the correct exceptions. - Except for ReadError and WriteError, exceptions no longer have an "errno" property. - When setting the Torrent.path property to None, only "pieces" is removed from the metainfo. "piece length", "pieces", "length" and "files" are kept. "name" is only changed when a new path is set. - The license was changed to GPLv3. 2019-07-01 2.1.0 - Keep piece size smaller for large torrents and use more pieces to compensate. - Implement your own piece size calculation of arbitrary complexity by simply overloading Torrent.calculate_piece_size(). 2019-04-04 2.0.0 - Use proper version number scheme - Raise PieceSizeError if 'piece_size' is set to a number that isn't a power of two 2018-06-25 1.5 - New methods read_stream() and write_stream() to import/export a torrent from any file-like object 2018-06-15 1.4 - New method: calculate_piece_size() - Piece size is now automatically calculated when path is set instead of calculating it on demand when requested - Setting piece size to a non-number now raises ValueError instead of RuntimeError - Exclude patterns are now matched against every part of a file's path, not just the last part (i.e. the file name) - Setting torrent.path to '.' or '..' now sets the correct name - Torrent instances are equal (==) if their metainfo is equal - Torrent instances are hashable - Torrent instances can be copied with the copy() method or the copy module from the standard library 2018-04-07 1.3 - Fix 'filepaths' attribute when setting a custom name 2018-02-19 1.2 - Don't leave an empty file when calling write() on an invalid torrent 2018-02-18 1.1 - 'announce' in metainfo is now a single URL instead of the first tier (Marcin Kurczewski) 2018-02-01 1.0 - Nothing changed except that this is now the final 1.0 version 2018-01-13 1.0rc5 - Fixed a bug where overwriting a torrent file resulted in corrupt torrent - Added property 'pieces' that returns the number of pieces - Added property 'filetree' that can be used to create a beautiful tree of a torrent's content - Added property 'is_ready' that is True when torrent can be exported - When reading torrent files, don't read large files all the way to EOF before failing - All exceptions now have an 'errno' attribute (see 'errno' module) 2018-01-03 1.0rc4 - Torrent.write() and Torrent.read() take a file path instead of an opened file object - Some exception names have changed - Allow reading arbitrary bencoded data with validation turned off - Default 'created_by' value is now 'torf/' 2017-12-27 1.0rc3 - Reduce entropy with 'randomize_infohash' enabled (some parsers seem to have issues with large integers) 2017-12-25 1.0rc2 - Add 'randomize_infohash' as a Torrent argument - Add 'name' as a Torrent argument - Call generate() callback again when all pieces are hashed - Validate 'metainfo' when accessing 'infohash' property 2017-12-21 1.0rc1 Initial release