Browse Source

Merge branch 'release/1.10.x'

rdb 7 years ago
parent
commit
ba993aea0d

+ 17 - 10
README.md

@@ -8,12 +8,12 @@ Panda3D
 Panda3D is a game engine, a framework for 3D rendering and game development for
 Python and C++ programs.  Panda3D is open-source and free for any purpose,
 including commercial ventures, thanks to its
-[liberal license](https://www.panda3d.org/license.php).  To learn more about
-Panda3D's capabilities, visit the [gallery](https://www.panda3d.org/gallery.php)
-and the [feature list](https://www.panda3d.org/features.php).  To learn how to
-use Panda3D, check the [documentation](https://www.panda3d.org/documentation.php)
+[liberal license](https://www.panda3d.org/license/). To learn more about
+Panda3D's capabilities, visit the [gallery](https://www.panda3d.org/gallery/)
+and the [feature list](https://www.panda3d.org/features/).  To learn how to
+use Panda3D, check the [documentation](https://www.panda3d.org/documentation/)
 resources. If you get stuck, ask for help from our active
-[community](https://www.panda3d.org/community.php).
+[community](https://discourse.panda3d.org).
 
 Panda3D is licensed under the Modified BSD License.  See the LICENSE file for
 more details.
@@ -21,7 +21,16 @@ more details.
 Installing Panda3D
 ==================
 
-By far, the easiest way to install the latest development build of Panda3D
+The latest Panda3D SDK can be downloaded from
+(this page)[https://www.panda3d.org/download/sdk-1-10-0/].
+If you are familiar with installing Python packages, you can use
+the following comand:
+
+```bash
+pip install panda3d
+```
+
+The easiest way to install the latest development build of Panda3D
 into an existing Python installation is using the following command:
 
 ```bash
@@ -31,9 +40,7 @@ pip install --pre --extra-index-url https://archive.panda3d.org/ panda3d
 If this command fails, please make sure your version of pip is up-to-date.
 
 If you prefer to install the full SDK with all tools, the latest development
-builds can be obtained from this page:
-
-https://www.panda3d.org/download.php?sdk&version=devel
+builds can be obtained from (this page)[https://www.panda3d.org/download/].
 
 These are automatically kept up-to-date with the latest GitHub version of Panda.
 
@@ -96,7 +103,7 @@ python makepanda/makepanda.py --everything --installer --no-egl --no-gles --no-g
 You will probably see some warnings saying that it's unable to find several
 dependency packages.  You should determine which ones you want to include in
 your build and install the respective development packages.  You may visit
-[this manual page](https://www.panda3d.org/manual/index.php/Dependencies)
+[this manual page](https://www.panda3d.org/manual/?title=Third-party_dependencies_and_license_info)
 for an overview of the various dependencies.
 
 If you are on Ubuntu, this command should cover the most frequently

+ 15 - 4
dtool/src/prc/streamReader.cxx

@@ -26,6 +26,9 @@ get_string() {
 
   // First, get the length of the string
   size_t size = get_uint16();
+  if (size == 0) {
+    return string();
+  }
 
   char *buffer = (char *)alloca(size);
   _in->read(buffer, size);
@@ -42,6 +45,9 @@ get_string32() {
 
   // First, get the length of the string
   size_t size = get_uint32();
+  if (size == 0) {
+    return string();
+  }
 
   char *buffer = (char *)PANDA_MALLOC_ARRAY(size);
   _in->read(buffer, size);
@@ -60,7 +66,7 @@ get_z_string() {
 
   string result;
   int ch = _in->get();
-  while (!_in->eof() && !_in->fail() && ch != '\0') {
+  while (!_in->fail() && ch != EOF && ch != '\0') {
     result += (char)ch;
     ch = _in->get();
   }
@@ -76,6 +82,10 @@ string StreamReader::
 get_fixed_string(size_t size) {
   nassertr(!_in->eof() && !_in->fail(), string());
 
+  if (size == 0) {
+    return string();
+  }
+
   char *buffer = (char *)alloca(size);
   _in->read(buffer, size);
   size_t read_bytes = _in->gcount();
@@ -90,8 +100,9 @@ get_fixed_string(size_t size) {
  */
 void StreamReader::
 skip_bytes(size_t size) {
-  nassertv(!_in->eof() && !_in->fail());
+  nassertv(!_in->fail());
   nassertv((int)size >= 0);
+  nassertv(size == 0 || !_in->eof());
 
   while (size > 0) {
     _in->get();
@@ -145,9 +156,9 @@ string StreamReader::
 readline() {
   string line;
   int ch = _in->get();
-  while (!_in->eof() && !_in->fail()) {
+  while (ch != EOF && !_in->fail()) {
     line += (char)ch;
-    if (ch == '\n') {
+    if (ch == '\n' || _in->eof()) {
       // Here's the newline character.
       return line;
     }

+ 2 - 2
dtool/src/prc/streamReader_ext.cxx

@@ -45,9 +45,9 @@ readline() {
 
   std::string line;
   int ch = in->get();
-  while (!in->eof() && !in->fail()) {
+  while (ch != EOF && !in->fail()) {
     line += ch;
-    if (ch == '\n') {
+    if (ch == '\n' || in->eof()) {
       // Here's the newline character.
       break;
     }

+ 0 - 5
makepanda/makewheel.py

@@ -526,11 +526,6 @@ def makewheel(version, output_dir, platform=None):
 
     # Update relevant METADATA entries
     METADATA['version'] = version
-    version_classifiers = [
-        "Programming Language :: Python :: {0}".format(*sys.version_info),
-        "Programming Language :: Python :: {0}.{1}".format(*sys.version_info),
-    ]
-    METADATA['classifiers'].extend(version_classifiers)
 
     # Build out the metadata
     details = METADATA["extensions"]["python.details"]

+ 2 - 2
panda/src/downloader/decompressor.cxx

@@ -183,7 +183,7 @@ decompress(const Filename &source_file) {
     return false;
 
   int ch = _decompress->get();
-  while (!_decompress->eof() && !_decompress->fail()) {
+  while (ch != EOF && !_decompress->fail()) {
     _dest->put(ch);
     ch = _decompress->get();
   }
@@ -207,7 +207,7 @@ decompress(Ramfile &source_and_dest_file) {
   IDecompressStream decompress(&source, false);
 
   int ch = decompress.get();
-  while (!decompress.eof() && !decompress.fail()) {
+  while (ch != EOF && !decompress.fail()) {
     dest.put(ch);
     ch = decompress.get();
   }

+ 2 - 2
panda/src/downloader/documentSpec.cxx

@@ -66,7 +66,7 @@ input(std::istream &in) {
     // Scan the tag, up to but not including the closing paren.
     std::string tag;
     in >> ch;
-    while (!in.fail() && !in.eof() && ch != ')') {
+    while (!in.fail() && ch != EOF && ch != ')') {
       tag += ch;
       // We want to include embedded whitespace, so we use get().
       ch = in.get();
@@ -81,7 +81,7 @@ input(std::istream &in) {
   // Scan the date, up to but not including the closing bracket.
   if (ch != ']') {
     std::string date;
-    while (!in.fail() && !in.eof() && ch != ']') {
+    while (!in.fail() && ch != EOF && ch != ']') {
       date += ch;
       ch = in.get();
     }

+ 2 - 2
panda/src/downloader/httpChannel.cxx

@@ -2762,7 +2762,7 @@ bool HTTPChannel::
 server_getline(string &str) {
   nassertr(!_source.is_null(), false);
   int ch = (*_source)->get();
-  while (!(*_source)->eof() && !(*_source)->fail()) {
+  while (ch != EOF && !(*_source)->fail()) {
     switch (ch) {
     case '\n':
       // end-of-line character, we're done.
@@ -2850,7 +2850,7 @@ bool HTTPChannel::
 server_get(string &str, size_t num_bytes) {
   nassertr(!_source.is_null(), false);
   int ch = (*_source)->get();
-  while (!(*_source)->eof() && !(*_source)->fail()) {
+  while (ch != EOF && !(*_source)->fail()) {
     _working_get += (char)ch;
     if (_working_get.length() >= num_bytes) {
       str = _working_get;

+ 1 - 1
panda/src/downloader/httpDate.cxx

@@ -279,7 +279,7 @@ input(std::istream &in) {
 
   string date;
   ch = in.get();
-  while (!in.fail() && !in.eof() && ch != '"') {
+  while (!in.fail() && ch != EOF && ch != '"') {
     date += ch;
     ch = in.get();
   }

+ 1 - 1
panda/src/downloader/socketStream.cxx

@@ -56,7 +56,7 @@ do_receive_datagram(Datagram &dg) {
     // Read the first two bytes: the datagram length.
     while ((int)_data_so_far.size() < _tcp_header_size) {
       int ch = _istream->get();
-      if (_istream->eof() || _istream->fail()) {
+      if (ch == EOF || _istream->fail()) {
         _istream->clear();
         return false;
       }

+ 2 - 2
panda/src/express/hashVal.cxx

@@ -50,7 +50,7 @@ input_hex(istream &in) {
   size_t i = 0;
   int ch = in.get();
 
-  while (!in.eof() && !in.fail() && isxdigit(ch)) {
+  while (ch != EOF && !in.fail() && isxdigit(ch)) {
     if (i < 32) {
       buffer[i] = (char)ch;
     }
@@ -63,7 +63,7 @@ input_hex(istream &in) {
     return;
   }
 
-  if (!in.eof()) {
+  if (ch != EOF) {
     in.putback((char)ch);
   } else {
     in.clear();

+ 1 - 1
panda/src/express/make_ca_bundle.cxx

@@ -108,7 +108,7 @@ main(int argc, char *argv[]) {
   int col = 0;
   unsigned int ch;
   ch = in.get();
-  while (!in.fail() && !in.eof()) {
+  while (!in.fail() && ch != EOF) {
     if (col == 0) {
       out << "\n  ";
     } else if (col == col_width) {

+ 4 - 5
panda/src/express/multifile.cxx

@@ -1785,8 +1785,7 @@ compare_subfile(int index, const Filename &filename) {
   in2.seekg(0);
   int byte1 = in1->get();
   int byte2 = in2.get();
-  while (!in1->fail() && !in1->eof() &&
-         !in2.fail() && !in2.eof()) {
+  while (!in1->fail() && !in2.fail()) {
     if (byte1 != byte2) {
       close_read_subfile(in1);
       return false;
@@ -2497,7 +2496,7 @@ read_index(istream &read, streampos fpos, Multifile *multifile) {
   StreamReader reader(read);
 
   streampos next_index = multifile->word_to_streampos(reader.get_uint32());
-  if (read.eof() || read.fail()) {
+  if (read.fail()) {
     _flags |= SF_index_invalid;
     return 0;
   }
@@ -2529,7 +2528,7 @@ read_index(istream &read, streampos fpos, Multifile *multifile) {
   }
 
   size_t name_length = reader.get_uint16();
-  if (read.eof() || read.fail()) {
+  if (read.fail()) {
     _flags |= SF_index_invalid;
     return 0;
   }
@@ -2543,7 +2542,7 @@ read_index(istream &read, streampos fpos, Multifile *multifile) {
   _name = string(name_buffer, name_length);
   PANDA_FREE_ARRAY(name_buffer);
 
-  if (read.eof() || read.fail()) {
+  if (read.fail()) {
     _flags |= SF_index_invalid;
     return 0;
   }

+ 2 - 2
panda/src/gobj/texture.cxx

@@ -4158,7 +4158,7 @@ do_read_dds(CData *cdata, istream &in, const string &filename, bool header_only)
     cdata->_num_mipmap_levels_read = cdata->_ram_images.size();
   }
 
-  if (in.fail() || in.eof()) {
+  if (in.fail()) {
     gobj_cat.error()
       << filename << ": truncated DDS file.\n";
     return false;
@@ -4924,7 +4924,7 @@ do_read_ktx(CData *cdata, istream &in, const string &filename, bool header_only)
     }
   }
 
-  if (in.fail() || in.eof()) {
+  if (in.fail()) {
     gobj_cat.error()
       << filename << ": truncated KTX file.\n";
     return false;

+ 4 - 4
panda/src/pnmimage/pnmimage_base.cxx

@@ -120,7 +120,7 @@ int
 pm_readbigshort(istream *in, short *sP) {
   StreamReader reader(in, false);
   *sP = reader.get_be_int16();
-  return (!in->eof() && !in->fail()) ? 0 : -1;
+  return (!in->fail()) ? 0 : -1;
 }
 
 int
@@ -134,7 +134,7 @@ int
 pm_readbiglong(istream *in, long *lP) {
   StreamReader reader(in, false);
   *lP = reader.get_be_int32();
-  return (!in->eof() && !in->fail()) ? 0 : -1;
+  return (!in->fail()) ? 0 : -1;
 }
 
 int
@@ -148,7 +148,7 @@ int
 pm_readlittleshort(istream *in, short *sP) {
   StreamReader reader(in, false);
   *sP = reader.get_int16();
-  return (!in->eof() && !in->fail()) ? 0 : -1;
+  return (!in->fail()) ? 0 : -1;
 }
 
 int
@@ -162,7 +162,7 @@ int
 pm_readlittlelong(istream *in, long *lP) {
   StreamReader reader(in, false);
   *lP = reader.get_int32();
-  return (!in->eof() && !in->fail()) ? 0 : -1;
+  return (!in->fail()) ? 0 : -1;
 }
 
 int

+ 1 - 1
pandatool/src/miscprogs/binToC.cxx

@@ -101,7 +101,7 @@ run() {
   int col = 0;
   unsigned int ch;
   ch = in.get();
-  while (!in.fail() && !in.eof()) {
+  while (!in.fail() && ch != EOF) {
     if (col == 0) {
       out << "\n  ";
     } else if (col == col_width) {

+ 11 - 0
setup.cfg

@@ -13,10 +13,21 @@ classifiers =
     Operating System :: OS Independent
     Programming Language :: C++
     Programming Language :: Python
+    Programming Language :: Python :: 2
+    Programming Language :: Python :: 2.7
+    Programming Language :: Python :: 3
+    Programming Language :: Python :: 3.4
+    Programming Language :: Python :: 3.5
+    Programming Language :: Python :: 3.6
+    Programming Language :: Python :: 3.7
+    Programming Language :: Python :: Implementation :: CPython
     Topic :: Games/Entertainment
     Topic :: Multimedia
     Topic :: Multimedia :: Graphics
     Topic :: Multimedia :: Graphics :: 3D Rendering
+    Topic :: Software Development :: Libraries
+    Topic :: Software Development :: Libraries :: Application Frameworks
+    Topic :: Software Development :: Libraries :: Python Modules
 author = Panda3D Team
 author_email = [email protected]
 

+ 12 - 0
tests/express/test_multifile.py

@@ -0,0 +1,12 @@
+from panda3d.core import Multifile, StringStream, IStreamWrapper
+
+
+def test_multifile_read_empty():
+    stream = StringStream(b'pmf\x00\n\r\x01\x00\x01\x00\x01\x00\x00\x00\xdb\x9d7\\\x00\x00\x00\x00')
+    wrapper = IStreamWrapper(stream)
+
+    m = Multifile()
+    assert m.open_read(wrapper)
+    assert m.is_read_valid()
+    assert m.get_num_subfiles() == 0
+    m.close()

+ 157 - 0
tests/prc/test_stream_reader.py

@@ -0,0 +1,157 @@
+from panda3d.core import StreamReader, StringStream
+import pytest
+
+
+def test_streamreader_string():
+    # Empty string
+    stream = StringStream(b'\x00\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_string() == ''
+
+    # String size but no string contents
+    stream = StringStream(b'\x01\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_string() == ''
+
+    # String of length 1
+    stream = StringStream(b'\x01\x00A')
+    reader = StreamReader(stream, False)
+    assert reader.get_string() == 'A'
+
+    # String with excess data
+    stream = StringStream(b'\x01\x00AB')
+    reader = StreamReader(stream, False)
+    assert reader.get_string() == 'A'
+
+    # EOF before end of string
+    stream = StringStream(b'\x03\x00AB')
+    reader = StreamReader(stream, False)
+    assert reader.get_string() == 'AB'
+
+    # Preserves null bytes
+    stream = StringStream(b'\x02\x00\x00\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_string() == '\x00\x00'
+
+
+def test_streamreader_string32():
+    # Empty string
+    stream = StringStream(b'\x00\x00\x00\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_string32() == ''
+
+    # String size but no string contents
+    stream = StringStream(b'\x01\x00\x00\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_string32() == ''
+
+    # String of length 1
+    stream = StringStream(b'\x01\x00\x00\x00A')
+    reader = StreamReader(stream, False)
+    assert reader.get_string32() == 'A'
+
+    # String with excess data
+    stream = StringStream(b'\x01\x00\x00\x00AB')
+    reader = StreamReader(stream, False)
+    assert reader.get_string32() == 'A'
+
+    # EOF before end of string
+    stream = StringStream(b'\x04\x00\x00\x00AB')
+    reader = StreamReader(stream, False)
+    assert reader.get_string32() == 'AB'
+
+    # Preserves null bytes
+    stream = StringStream(b'\x02\x00\x00\x00\x00\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_string32() == '\x00\x00'
+
+
+def test_streamreader_z_string():
+    # Empty stream
+    stream = StringStream(b'')
+    reader = StreamReader(stream, False)
+    assert reader.get_z_string() == ''
+
+    # Empty string
+    stream = StringStream(b'\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_z_string() == ''
+
+    # String of length 1
+    stream = StringStream(b'A\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_z_string() == 'A'
+
+    # String with excess data
+    stream = StringStream(b'ABC\x00AB')
+    reader = StreamReader(stream, False)
+    assert reader.get_z_string() == 'ABC'
+
+    # EOF before end of string
+    stream = StringStream(b'ABC')
+    reader = StreamReader(stream, False)
+    assert reader.get_z_string() == 'ABC'
+
+
+def test_streamreader_fixed_string():
+    # Zero-length string
+    stream = StringStream(b'ABC')
+    reader = StreamReader(stream, False)
+    assert reader.get_fixed_string(0) == ''
+
+    # Empty stream
+    stream = StringStream(b'')
+    reader = StreamReader(stream, False)
+    assert reader.get_fixed_string(1) == ''
+
+    # Empty string
+    stream = StringStream(b'\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_fixed_string(1) == ''
+
+    # String of length 1
+    stream = StringStream(b'A')
+    reader = StreamReader(stream, False)
+    assert reader.get_fixed_string(1) == 'A'
+
+    # String of length 1, excess data
+    stream = StringStream(b'ABC\x00')
+    reader = StreamReader(stream, False)
+    assert reader.get_fixed_string(1) == 'A'
+
+    # EOF before end of string
+    stream = StringStream(b'AB')
+    reader = StreamReader(stream, False)
+    assert reader.get_fixed_string(4) == 'AB'
+
+
+def test_streamreader_readline():
+    # Empty stream
+    stream = StringStream(b'')
+    reader = StreamReader(stream, False)
+    assert reader.readline() == b''
+    assert reader.readline() == b''
+
+    # Single line without newline
+    stream = StringStream(b'A')
+    reader = StreamReader(stream, False)
+    assert reader.readline() == b'A'
+    assert reader.readline() == b''
+
+    # Single newline
+    stream = StringStream(b'\n')
+    reader = StreamReader(stream, False)
+    assert reader.readline() == b'\n'
+    assert reader.readline() == b''
+
+    # Line with text followed by empty line
+    stream = StringStream(b'A\n\n')
+    reader = StreamReader(stream, False)
+    assert reader.readline() == b'A\n'
+    assert reader.readline() == b'\n'
+    assert reader.readline() == b''
+
+    # Preserve null byte
+    stream = StringStream(b'\x00\x00')
+    reader = StreamReader(stream, False)
+    assert reader.readline() == b'\x00\x00'