Merge branch 'master' into deploy-ng

This commit is contained in:
rdb 2018-08-20 19:13:04 +02:00
commit 57b66ebeaf
59 changed files with 633 additions and 169 deletions

View File

@ -23,7 +23,7 @@
* parameter type accepts an arbitrary (or possibly fixed) number of nested
* fields, all of which are of the same type.
*/
class DCArrayParameter : public DCParameter {
class EXPCL_DIRECT_DCPARSER DCArrayParameter : public DCParameter {
public:
DCArrayParameter(DCParameter *element_type,
const DCUnsignedIntRange &size = DCUnsignedIntRange());

View File

@ -27,7 +27,7 @@
* This defines an interface to the Distributed Class, and is always
* implemented as a remote procedure method.
*/
class DCAtomicField : public DCField {
class EXPCL_DIRECT_DCPARSER DCAtomicField : public DCField {
public:
DCAtomicField(const std::string &name, DCClass *dclass, bool bogus_field);
virtual ~DCAtomicField();

View File

@ -41,7 +41,7 @@ class DCParameter;
/**
* Defines a particular DistributedClass as read from an input .dc file.
*/
class DCClass : public DCDeclaration {
class EXPCL_DIRECT_DCPARSER DCClass : public DCDeclaration {
public:
DCClass(DCFile *dc_file, const std::string &name,
bool is_struct, bool bogus_class);

View File

@ -23,7 +23,7 @@ class DCClass;
* This represents a class (or struct) object used as a parameter itself.
* This means that all the fields of the class get packed into the message.
*/
class DCClassParameter : public DCParameter {
class EXPCL_DIRECT_DCPARSER DCClassParameter : public DCParameter {
public:
DCClassParameter(const DCClass *dclass);
DCClassParameter(const DCClassParameter &copy);

View File

@ -26,7 +26,7 @@ class DCSwitch;
* only purpose is so that classes and typedefs can be stored in one list
* together so they can be ordered correctly on output.
*/
class DCDeclaration {
class EXPCL_DIRECT_DCPARSER DCDeclaration {
public:
virtual ~DCDeclaration();

View File

@ -34,7 +34,7 @@ class HashGenerator;
/**
* A single field of a Distributed Class, either atomic or molecular.
*/
class DCField : public DCPackerInterface, public DCKeywordList {
class EXPCL_DIRECT_DCPARSER DCField : public DCPackerInterface, public DCKeywordList {
public:
DCField();
DCField(const std::string &name, DCClass *dclass);

View File

@ -29,7 +29,7 @@ class DCDeclaration;
* Represents the complete list of Distributed Class descriptions as read from
* a .dc file.
*/
class DCFile {
class EXPCL_DIRECT_DCPARSER DCFile {
PUBLISHED:
DCFile();
~DCFile();

View File

@ -25,7 +25,7 @@ class HashGenerator;
* define a communication property associated with a field, for instance
* "broadcast" or "airecv".
*/
class DCKeyword : public DCDeclaration {
class EXPCL_DIRECT_DCPARSER DCKeyword : public DCDeclaration {
public:
DCKeyword(const std::string &name, int historical_flag = ~0);
virtual ~DCKeyword();

View File

@ -23,7 +23,7 @@ class HashGenerator;
* This is a list of keywords (see DCKeyword) that may be set on a particular
* field.
*/
class DCKeywordList {
class EXPCL_DIRECT_DCPARSER DCKeywordList {
public:
DCKeywordList();
DCKeywordList(const DCKeywordList &copy);

View File

@ -25,7 +25,7 @@ class DCParameter;
* This represents a combination of two or more related atomic fields, that
* will often be treated as a unit.
*/
class DCMolecularField : public DCField {
class EXPCL_DIRECT_DCPARSER DCMolecularField : public DCField {
public:
DCMolecularField(const std::string &name, DCClass *dclass);

View File

@ -52,7 +52,7 @@ operator = (const DCNumericRange<NUM> &copy) {
* otherwise.
*/
template <class NUM>
bool DCNumericRange<NUM>::
INLINE bool DCNumericRange<NUM>::
is_in_range(Number num) const {
if (_ranges.empty()) {
return true;
@ -106,7 +106,7 @@ get_one_value() const {
*
*/
template <class NUM>
void DCNumericRange<NUM>::
INLINE void DCNumericRange<NUM>::
generate_hash(HashGenerator &hashgen) const {
if (!_ranges.empty()) {
hashgen.add_int(_ranges.size());
@ -124,7 +124,7 @@ generate_hash(HashGenerator &hashgen) const {
*
*/
template <class NUM>
void DCNumericRange<NUM>::
INLINE void DCNumericRange<NUM>::
output(std::ostream &out, Number divisor) const {
if (!_ranges.empty()) {
typename Ranges::const_iterator ri;
@ -144,7 +144,7 @@ output(std::ostream &out, Number divisor) const {
* characters.
*/
template <class NUM>
void DCNumericRange<NUM>::
INLINE void DCNumericRange<NUM>::
output_char(std::ostream &out, Number divisor) const {
if (divisor != 1) {
output(out, divisor);
@ -179,7 +179,7 @@ clear() {
* minmax overlaps an existing minmax.
*/
template <class NUM>
bool DCNumericRange<NUM>::
INLINE bool DCNumericRange<NUM>::
add_range(Number min, Number max) {
// Check for an overlap. This is probably indicative of a typo and should
// be reported.

View File

@ -23,7 +23,7 @@
* to constrain simple numeric types, as well as array sizes.
*/
template <class NUM>
class DCNumericRange {
class EXPCL_DIRECT_DCPARSER DCNumericRange {
public:
typedef NUM Number;
@ -32,20 +32,20 @@ public:
INLINE DCNumericRange(const DCNumericRange &copy);
INLINE void operator = (const DCNumericRange &copy);
bool is_in_range(Number num) const;
INLINE bool is_in_range(Number num) const;
INLINE void validate(Number num, bool &range_error) const;
INLINE bool has_one_value() const;
INLINE Number get_one_value() const;
void generate_hash(HashGenerator &hashgen) const;
INLINE void generate_hash(HashGenerator &hashgen) const;
void output(std::ostream &out, Number divisor = 1) const;
void output_char(std::ostream &out, Number divisor = 1) const;
INLINE void output(std::ostream &out, Number divisor = 1) const;
INLINE void output_char(std::ostream &out, Number divisor = 1) const;
public:
INLINE void clear();
bool add_range(Number min, Number max);
INLINE bool add_range(Number min, Number max);
INLINE bool is_empty() const;
INLINE int get_num_ranges() const;

View File

@ -19,7 +19,7 @@
/**
* This is a block of data that receives the results of DCPacker.
*/
class DCPackData {
class EXPCL_DIRECT_DCPARSER DCPackData {
PUBLISHED:
INLINE DCPackData();
INLINE ~DCPackData();

View File

@ -31,7 +31,7 @@ class DCSwitchParameter;
* See also direct/src/doc/dcPacker.txt for a more complete description and
* examples of using this class.
*/
class DCPacker {
class EXPCL_DIRECT_DCPARSER DCPacker {
PUBLISHED:
DCPacker();
~DCPacker();

View File

@ -26,7 +26,7 @@ class DCSwitchParameter;
* requested from a particular field; its ownership is retained by the field
* so it must not be deleted.
*/
class DCPackerCatalog {
class EXPCL_DIRECT_DCPARSER DCPackerCatalog {
private:
DCPackerCatalog(const DCPackerInterface *root);
DCPackerCatalog(const DCPackerCatalog &copy);

View File

@ -64,7 +64,7 @@ END_PUBLISH
* Normally these methods are called only by the DCPacker object; the user
* wouldn't normally call these directly.
*/
class DCPackerInterface {
class EXPCL_DIRECT_DCPARSER DCPackerInterface {
public:
DCPackerInterface(const std::string &name = std::string());
DCPackerInterface(const DCPackerInterface &copy);

View File

@ -32,7 +32,7 @@ class HashGenerator;
* This may also be a typedef reference to another type, which has the same
* properties as the referenced type, but a different name.
*/
class DCParameter : public DCField {
class EXPCL_DIRECT_DCPARSER DCParameter : public DCField {
protected:
DCParameter();
DCParameter(const DCParameter &copy);

View File

@ -43,7 +43,7 @@ extern DCFile *dc_file;
// that has member functions in a union), so we'll use a class instead. That
// means we need to declare it externally, here.
class DCTokenType {
class EXPCL_DIRECT_DCPARSER DCTokenType {
public:
union U {
int s_int;

View File

@ -25,7 +25,7 @@
* divisor, which is meaningful only for the numeric type elements (and
* represents a fixed-point numeric convention).
*/
class DCSimpleParameter : public DCParameter {
class EXPCL_DIRECT_DCPARSER DCSimpleParameter : public DCParameter {
public:
DCSimpleParameter(DCSubatomicType type, unsigned int divisor = 1);
DCSimpleParameter(const DCSimpleParameter &copy);

View File

@ -27,7 +27,7 @@ class DCField;
* and represents two or more alternative unpacking schemes based on the first
* field read.
*/
class DCSwitch : public DCDeclaration {
class EXPCL_DIRECT_DCPARSER DCSwitch : public DCDeclaration {
public:
DCSwitch(const std::string &name, DCField *key_parameter);
virtual ~DCSwitch();

View File

@ -23,7 +23,7 @@ class DCSwitch;
* This represents a switch object used as a parameter itself, which packs the
* appropriate fields of the switch into the message.
*/
class DCSwitchParameter : public DCParameter {
class EXPCL_DIRECT_DCPARSER DCSwitchParameter : public DCParameter {
public:
DCSwitchParameter(const DCSwitch *dswitch);
DCSwitchParameter(const DCSwitchParameter &copy);

View File

@ -23,7 +23,7 @@ class DCParameter;
* This represents a single typedef declaration in the dc file. It assigns a
* particular type to a new name, just like a C typedef.
*/
class DCTypedef : public DCDeclaration {
class EXPCL_DIRECT_DCPARSER DCTypedef : public DCDeclaration {
public:
DCTypedef(DCParameter *parameter, bool implicit = false);
DCTypedef(const std::string &name);

View File

@ -70,6 +70,11 @@
#define END_PUBLISH
#define BLOCKING
// These control the declspec(dllexport/dllimport) on Windows. When compiling
// outside of Panda, we assume we aren't part of a DLL.
#define EXPCL_DIRECT_DCPARSER
#define EXPTP_DIRECT_DCPARSER
// Panda defines some assert-type macros. We map those to the standard assert
// macro outside of Panda.
#define nassertr(condition, return_value) assert(condition)

View File

@ -20,7 +20,7 @@
/**
* This class generates an arbitrary hash number from a sequence of ints.
*/
class HashGenerator {
class EXPCL_DIRECT_DCPARSER HashGenerator {
public:
HashGenerator();

View File

@ -30,7 +30,7 @@ typedef std::vector<int> vector_int;
* For a given integer n, it will return the nth prime number. This will
* involve a recompute step only if n is greater than any previous n.
*/
class PrimeNumberGenerator {
class EXPCL_DIRECT_DCPARSER PrimeNumberGenerator {
public:
PrimeNumberGenerator();

View File

@ -18,6 +18,7 @@
/* BUILDING_DIRECT is just a buildsystem shortcut for all of these: */
#ifdef BUILDING_DIRECT
#define BUILDING_DIRECT_DCPARSER
#define BUILDING_DIRECT_DEADREC
#define BUILDING_DIRECT_DIRECTD
#define BUILDING_DIRECT_INTERVAL
@ -26,6 +27,14 @@
#define BUILDING_DIRECT_DISTRIBUTED
#endif
#ifdef BUILDING_DIRECT_DCPARSER
#define EXPCL_DIRECT_DCPARSER EXPORT_CLASS
#define EXPTP_DIRECT_DCPARSER EXPORT_TEMPL
#else
#define EXPCL_DIRECT_DCPARSER IMPORT_CLASS
#define EXPTP_DIRECT_DCPARSER IMPORT_TEMPL
#endif
#ifdef BUILDING_DIRECT_DEADREC
#define EXPCL_DIRECT_DEADREC EXPORT_CLASS
#define EXPTP_DIRECT_DEADREC EXPORT_TEMPL

View File

@ -25,8 +25,8 @@ class PyDatagram(Datagram):
STUint64: (Datagram.addUint64, int),
STFloat64: (Datagram.addFloat64, None),
STString: (Datagram.addString, None),
STBlob: (Datagram.addString, None),
STBlob32: (Datagram.addString32, None),
STBlob: (Datagram.addBlob, None),
STBlob32: (Datagram.addBlob32, None),
}
#def addChannel(self, channelId):

View File

@ -23,8 +23,8 @@ class PyDatagramIterator(DatagramIterator):
STUint64: DatagramIterator.getUint64,
STFloat64: DatagramIterator.getFloat64,
STString: DatagramIterator.getString,
STBlob: DatagramIterator.getString,
STBlob32: DatagramIterator.getString32,
STBlob: DatagramIterator.getBlob,
STBlob32: DatagramIterator.getBlob32,
}
getChannel = DatagramIterator.getUint64

View File

@ -292,6 +292,10 @@ output_instance(ostream &out, int indent_level, CPPScope *scope,
out << str;
} else if (_flags & F_operator_typecast) {
out << "operator ";
_return_type->output_instance(out, indent_level, scope, complete, "", prename + str);
} else {
if (prename.empty()) {
_return_type->output_instance(out, indent_level, scope, complete,

View File

@ -30,6 +30,20 @@ struct AtomicAdjust {
#include "atomicAdjustDummyImpl.h"
typedef AtomicAdjustDummyImpl AtomicAdjust;
#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || (defined(__clang__) && (__clang_major__ >= 3))
// GCC 4.7 and above has built-in __atomic functions for atomic operations.
// Clang 3.0 and above also supports them.
#include "atomicAdjustGccImpl.h"
typedef AtomicAdjustGccImpl AtomicAdjust;
#if (__GCC_ATOMIC_INT_LOCK_FREE + __GCC_ATOMIC_LONG_LOCK_FREE) > 0
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
#endif
#if __GCC_ATOMIC_POINTER_LOCK_FREE > 0
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
#endif
#elif (defined(__i386__) || defined(_M_IX86)) && !defined(__APPLE__)
// For an i386 architecture, we'll always use the i386 implementation. It
// should be safe for any OS, and it might be a bit faster than any OS-
@ -45,20 +59,6 @@ typedef AtomicAdjustI386Impl AtomicAdjust;
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
#elif (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7))) || (defined(__clang__) && (__clang_major__ >= 3))
// GCC 4.7 and above has built-in __atomic functions for atomic operations.
// Clang 3.0 and above also supports them.
#include "atomicAdjustGccImpl.h"
typedef AtomicAdjustGccImpl AtomicAdjust;
#if (__GCC_ATOMIC_INT_LOCK_FREE + __GCC_ATOMIC_INT_LOCK_FREE) > 0
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE 1
#endif
#if __GCC_ATOMIC_POINTER_LOCK_FREE > 0
#define HAVE_ATOMIC_COMPARE_AND_EXCHANGE_PTR 1
#endif
#elif defined(THREAD_WIN32_IMPL)
#include "atomicAdjustWin32Impl.h"

View File

@ -789,8 +789,6 @@ InterfaceMakerPythonNative::
*/
void InterfaceMakerPythonNative::
write_prototypes(ostream &out_code, ostream *out_h) {
Functions::iterator fi;
if (out_h != nullptr) {
*out_h << "#include \"py_panda.h\"\n\n";
}
@ -917,7 +915,6 @@ write_prototypes_class_external(ostream &out, Object *obj) {
void InterfaceMakerPythonNative::
write_prototypes_class(ostream &out_code, ostream *out_h, Object *obj) {
std::string ClassName = make_safe_name(obj->_itype.get_scoped_name());
Functions::iterator fi;
out_code << "/**\n";
out_code << " * Forward declarations for top-level class " << ClassName << "\n";
@ -1089,6 +1086,27 @@ write_class_details(ostream &out, Object *obj) {
}
}
// Are there any implicit cast operators that can cast this object to our
// desired pointer?
for (Function *func : obj->_methods) {
for (FunctionRemap *remap : func->_remaps) {
if (remap->_type == FunctionRemap::T_typecast_method &&
is_remap_legal(remap) &&
!remap->_return_type->return_value_needs_management() &&
(remap->_cppfunc->_storage_class & CPPInstance::SC_explicit) == 0 &&
TypeManager::is_pointer(remap->_return_type->get_new_type())) {
CPPType *cast_type = remap->_return_type->get_orig_type();
CPPType *obj_type = TypeManager::unwrap(TypeManager::resolve_type(remap->_return_type->get_new_type()));
string return_expr = "(" + cast_type->get_local_name(&parser) + ")*local_this";
out << " // " << *remap->_cppfunc << "\n";
out << " if (requested_type == Dtool_Ptr_" << make_safe_name(obj_type->get_local_name(&parser)) << ") {\n";
out << " return (void *)(" << remap->_return_type->get_return_expr(return_expr) << ");\n";
out << " }\n";
}
}
}
out << " return nullptr;\n";
out << "}\n\n";
@ -3301,7 +3319,7 @@ write_prototype_for(ostream &out, InterfaceMaker::Function *func) {
*/
void InterfaceMakerPythonNative::
write_prototype_for_name(ostream &out, InterfaceMaker::Function *func, const std::string &function_namename) {
Function::Remaps::const_iterator ri;
// Function::Remaps::const_iterator ri;
// for (ri = func->_remaps.begin(); ri != func->_remaps.end(); ++ri) {
// FunctionRemap *remap = (*ri);

View File

@ -5316,7 +5316,7 @@ if (PkgSkip("DIRECT")==0):
#
if (PkgSkip("DIRECT")==0):
OPTS=['DIR:direct/src/dcparser', 'WITHINPANDA', 'BISONPREFIX_dcyy', 'PYTHON']
OPTS=['DIR:direct/src/dcparser', 'BUILDING:DIRECT_DCPARSER', 'WITHINPANDA', 'BISONPREFIX_dcyy', 'PYTHON']
CreateFile(GetOutputDir()+"/include/dcParser.h")
TargetAdd('p3dcparser_dcParser.obj', opts=OPTS, input='dcParser.yxx')
TargetAdd('dcParser.h', input='p3dcparser_dcParser.obj', opts=['DEPENDENCYONLY'])

61
makepanda/test_wheel.py Executable file
View File

@ -0,0 +1,61 @@
#!/usr/bin/env python
"""
Tests a .whl file by installing it and pytest into a virtual environment and
running the test suite.
Requires pip to be installed, as well as 'virtualenv' on Python 2.
"""
import os
import sys
import shutil
import subprocess
import tempfile
from optparse import OptionParser
def test_wheel(wheel, verbose=False):
envdir = tempfile.mkdtemp(prefix="venv-")
print("Setting up virtual environment in {0}".format(envdir))
if sys.version_info >= (3, 0):
subprocess.call([sys.executable, "-m", "venv", "--clear", envdir])
else:
subprocess.call([sys.executable, "-m", "virtualenv", "--clear", envdir])
# Install pytest into the environment, as well as our wheel.
if sys.platform == "win32":
pip = os.path.join(envdir, "Scripts", "pip.exe")
else:
pip = os.path.join(envdir, "bin", "pip")
if subprocess.call([pip, "install", "pytest", wheel]) != 0:
shutil.rmtree(envdir)
sys.exit(1)
# Run the test suite.
if sys.platform == "win32":
python = os.path.join(envdir, "Scripts", "python.exe")
else:
python = os.path.join(envdir, "bin", "python")
test_cmd = [python, "-m", "pytest", "tests"]
if verbose:
test_cmd.append("--verbose")
exit_code = subprocess.call(test_cmd)
shutil.rmtree(envdir)
if exit_code != 0:
sys.exit(exit_code)
if __name__ == "__main__":
parser = OptionParser(usage="%prog [options] file...")
parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False)
(options, args) = parser.parse_args()
if not args:
parser.print_usage()
sys.exit(1)
for arg in args:
test_wheel(arg, verbose=options.verbose)

View File

@ -16,6 +16,7 @@
#include "collisionRay.h"
#include "collisionSphere.h"
#include "collisionSegment.h"
#include "collisionTube.h"
#include "collisionHandler.h"
#include "collisionEntry.h"
#include "config_collide.h"

View File

@ -558,7 +558,7 @@ remove_doubled_verts(bool closed) {
*/
void EggPrimitive::
remove_nonunique_verts() {
Vertices::iterator vi, vj;
Vertices::iterator vi;
Vertices new_vertices;
int num_removed = 0;

View File

@ -2661,7 +2661,6 @@ set_occluder_polygon(EggGroup *egg_group, OccluderNode *pnode) {
} else {
LMatrix4d mat = poly->get_vertex_to_node();
EggPolygon::const_iterator vi;
LPoint3d v0 = (*poly)[0]->get_pos3() * mat;
LPoint3d v1 = (*poly)[1]->get_pos3() * mat;
LPoint3d v2 = (*poly)[2]->get_pos3() * mat;

View File

@ -11,30 +11,11 @@
* @date 2000-06-06
*/
/**
* Constructs an empty datagram.
*/
INLINE Datagram::
Datagram() :
#ifdef STDFLOAT_DOUBLE
_stdfloat_double(true)
#else
_stdfloat_double(false)
#endif
{
}
/**
* Constructs a datagram from an existing block of data.
*/
INLINE Datagram::
Datagram(const void *data, size_t size) :
#ifdef STDFLOAT_DOUBLE
_stdfloat_double(true)
#else
_stdfloat_double(false)
#endif
{
Datagram(const void *data, size_t size) {
append_data(data, size);
}
@ -43,13 +24,7 @@ Datagram(const void *data, size_t size) :
*/
INLINE Datagram::
Datagram(vector_uchar data) :
_data(std::move(data)),
#ifdef STDFLOAT_DOUBLE
_stdfloat_double(true)
#else
_stdfloat_double(false)
#endif
{
_data(std::move(data)) {
}
/**
@ -295,6 +270,35 @@ add_fixed_string(const std::string &str, size_t size) {
}
}
/**
* Adds a variable-length binary blob to the datagram. This actually adds a
* count followed by n bytes.
*/
INLINE void Datagram::
add_blob(const vector_uchar &data) {
// The max sendable size for a blob is 2^16.
nassertv(data.size() <= (uint16_t)0xffff);
// Blobs always are preceded by their size
add_uint16((uint16_t)data.size());
// Add the blob
append_data(data.data(), data.size());
}
/**
* Adds a variable-length binary blob to the datagram, using a 32-bit length
* field to allow very long blobs.
*/
INLINE void Datagram::
add_blob32(const vector_uchar &data) {
// Blobs always are preceded by their size
add_uint32((uint32_t)data.size());
// Add the blob
append_data(data.data(), data.size());
}
/**
* Appends some more raw data to the end of the datagram.
*/
@ -316,18 +320,6 @@ get_message() const {
}
}
/**
* Returns the datagram's data as a bytes object.
*/
INLINE vector_uchar Datagram::
__bytes__() const {
if (!_data.empty()) {
return vector_uchar(_data.v());
} else {
return vector_uchar();
}
}
/**
* Returns a pointer to the beginning of the datagram's data.
*/
@ -482,3 +474,8 @@ INLINE void
generic_write_datagram(Datagram &dest, const std::wstring &value) {
dest.add_wstring(value);
}
INLINE void
generic_write_datagram(Datagram &dest, const vector_uchar &value) {
dest.add_blob(value);
}

View File

@ -37,7 +37,7 @@
*/
class EXPCL_PANDA_EXPRESS Datagram : public TypedObject {
PUBLISHED:
INLINE Datagram();
INLINE Datagram() = default;
INLINE Datagram(const void *data, size_t size);
INLINE explicit Datagram(vector_uchar data);
Datagram(const Datagram &copy) = default;
@ -81,15 +81,23 @@ PUBLISHED:
INLINE void add_fixed_string(const std::string &str, size_t size);
void add_wstring(const std::wstring &str);
INLINE void add_blob(const vector_uchar &);
INLINE void add_blob32(const vector_uchar &);
void pad_bytes(size_t size);
void append_data(const void *data, size_t size);
INLINE void append_data(const vector_uchar &data);
public:
void assign(const void *data, size_t size);
INLINE std::string get_message() const;
INLINE vector_uchar __bytes__() const;
INLINE const void *get_data() const;
PUBLISHED:
EXTENSION(INLINE PyObject *get_message() const);
EXTENSION(INLINE PyObject *__bytes__() const);
INLINE size_t get_length() const;
INLINE void set_array(PTA_uchar data);
@ -109,7 +117,12 @@ PUBLISHED:
private:
PTA_uchar _data;
bool _stdfloat_double;
#ifdef STDFLOAT_DOUBLE
bool _stdfloat_double = true;
#else
bool _stdfloat_double = false;
#endif
public:
@ -148,6 +161,8 @@ INLINE void
generic_write_datagram(Datagram &dest, const std::string &value);
INLINE void
generic_write_datagram(Datagram &dest, const std::wstring &value);
INLINE void
generic_write_datagram(Datagram &dest, const vector_uchar &value);
#include "datagram.I"

View File

@ -400,6 +400,22 @@ get_be_float64() {
return tempvar;
}
/**
* Extracts a variable-length binary blob.
*/
INLINE vector_uchar DatagramIterator::
get_blob() {
return extract_bytes(get_uint16());
}
/**
* Extracts a variable-length binary blob with a 32-bit size field.
*/
INLINE vector_uchar DatagramIterator::
get_blob32() {
return extract_bytes(get_uint32());
}
/**
* Skips over the indicated number of bytes in the datagram.
*/
@ -485,3 +501,8 @@ INLINE void
generic_read_datagram(std::wstring &result, DatagramIterator &source) {
result = source.get_wstring();
}
INLINE void
generic_read_datagram(vector_uchar &result, DatagramIterator &source) {
result = source.get_blob();
}

View File

@ -61,6 +61,9 @@ PUBLISHED:
std::string get_fixed_string(size_t size);
std::wstring get_wstring();
INLINE vector_uchar get_blob();
INLINE vector_uchar get_blob32();
INLINE void skip_bytes(size_t size);
vector_uchar extract_bytes(size_t size);
size_t extract_bytes(unsigned char *into, size_t size);

View File

@ -0,0 +1,35 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file datagram_ext.I
* @author rdb
* @date 2018-08-19
*/
/**
* Returns the datagram's data as a bytes object.
*/
INLINE PyObject *Extension<Datagram>::
get_message() const {
const char *data = (const char *)_this->get_data();
size_t size = _this->get_length();
#if PY_MAJOR_VERSION >= 3
return PyBytes_FromStringAndSize((char *)data, size);
#else
return PyString_FromStringAndSize((char *)data, size);
#endif
}
/**
* Returns the datagram's data as a bytes object.
*/
PyObject *Extension<Datagram>::
__bytes__() const {
return get_message();
}

View File

@ -0,0 +1,40 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file datagram_ext.h
* @author rdb
* @date 2018-08-19
*/
#ifndef DATAGRAM_EXT_H
#define DATAGRAM_EXT_H
#include "dtoolbase.h"
#ifdef HAVE_PYTHON
#include "extension.h"
#include "datagram.h"
#include "py_panda.h"
/**
* This class defines the extension methods for Datagram, which are called
* instead of any C++ methods with the same prototype.
*/
template<>
class Extension<Datagram> : public ExtensionBase<Datagram> {
public:
INLINE PyObject *get_message() const;
INLINE PyObject *__bytes__() const;
};
#include "datagram_ext.I"
#endif // HAVE_PYTHON
#endif // DATAGRAM_EXT_H

View File

@ -24,7 +24,7 @@
/**
* The streambuf object that implements IDecompressStream and OCompressStream.
*/
class EXPCL_PANDA_DOWNLOADER ZStreamBuf : public std::streambuf {
class EXPCL_PANDA_EXPRESS ZStreamBuf : public std::streambuf {
public:
ZStreamBuf();
virtual ~ZStreamBuf();

View File

@ -44,6 +44,14 @@ size() {
return 3;
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LMatrix3)::Row::
operator const FLOATNAME(LVecBase3) &() const {
return *(const FLOATNAME(LVecBase3) *)_row;
}
/**
* Defines a row-level constant accessor to the matrix.
*/
@ -68,6 +76,14 @@ size() {
return 3;
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LMatrix3)::CRow::
operator const FLOATNAME(LVecBase3) &() const {
return *(const FLOATNAME(LVecBase3) *)_row;
}
/**
* Returns an identity matrix.
*
@ -132,6 +148,32 @@ FLOATNAME(LMatrix3)(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02,
_m(2, 2) = e22;
}
/**
* Constructs the matrix from three individual rows.
*/
INLINE_LINMATH FLOATNAME(LMatrix3)::
FLOATNAME(LMatrix3)(const FLOATNAME(LVecBase3) &row0,
const FLOATNAME(LVecBase3) &row1,
const FLOATNAME(LVecBase3) &row2) {
TAU_PROFILE("LMatrix3::LMatrix3(const LVecBase3 &, ...)", " ", TAU_USER);
#ifdef HAVE_EIGEN
_m.row(0) = row0._v;
_m.row(1) = row1._v;
_m.row(2) = row2._v;
#else
_m(0, 0) = row0._v(0);
_m(0, 1) = row0._v(1);
_m(0, 2) = row0._v(2);
_m(1, 0) = row1._v(0);
_m(1, 1) = row1._v(1);
_m(1, 2) = row1._v(2);
_m(2, 0) = row2._v(0);
_m(2, 1) = row2._v(1);
_m(2, 2) = row2._v(2);
#endif // HAVE_EIGEN
}
/**
*
*/

View File

@ -38,6 +38,7 @@ PUBLISHED:
INLINE_LINMATH FLOATTYPE operator [](int i) const;
INLINE_LINMATH FLOATTYPE &operator [](int i);
INLINE_LINMATH static int size();
INLINE_LINMATH operator const FLOATNAME(LVecBase3) &() const;
public:
FLOATTYPE *_row;
friend class FLOATNAME(LMatrix3);
@ -48,6 +49,7 @@ PUBLISHED:
PUBLISHED:
INLINE_LINMATH FLOATTYPE operator [](int i) const;
INLINE_LINMATH static int size();
INLINE_LINMATH operator const FLOATNAME(LVecBase3) &() const;
public:
const FLOATTYPE *_row;
friend class FLOATNAME(LMatrix3);
@ -58,10 +60,12 @@ PUBLISHED:
INLINE_LINMATH FLOATNAME(LMatrix3) &operator = (
const FLOATNAME(LMatrix3) &other);
INLINE_LINMATH FLOATNAME(LMatrix3) &operator = (FLOATTYPE fill_value);
INLINE_LINMATH FLOATNAME(LMatrix3)(
FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02,
FLOATTYPE e10, FLOATTYPE e11, FLOATTYPE e12,
FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22);
INLINE_LINMATH FLOATNAME(LMatrix3)(FLOATTYPE, FLOATTYPE, FLOATTYPE,
FLOATTYPE, FLOATTYPE, FLOATTYPE,
FLOATTYPE, FLOATTYPE, FLOATTYPE);
INLINE_LINMATH FLOATNAME(LMatrix3)(const FLOATNAME(LVecBase3) &,
const FLOATNAME(LVecBase3) &,
const FLOATNAME(LVecBase3) &);
ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix3));
EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);

View File

@ -44,6 +44,14 @@ size() {
return 4;
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LMatrix4)::Row::
operator const FLOATNAME(LVecBase4) &() const {
return *(const FLOATNAME(LVecBase4) *)_row;
}
/**
* Defines a row-level constant accessor to the matrix.
*/
@ -68,6 +76,14 @@ size() {
return 4;
}
/**
*
*/
INLINE_LINMATH FLOATNAME(LMatrix4)::CRow::
operator const FLOATNAME(LVecBase4) &() const {
return *(const FLOATNAME(LVecBase4) *)_row;
}
/**
* Returns an identity matrix.
*
@ -178,6 +194,41 @@ FLOATNAME(LMatrix4)(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02, FLOATTYPE e03,
_m(3, 3) = e33;
}
/**
* Constructs the matrix from four individual rows.
*/
INLINE_LINMATH FLOATNAME(LMatrix4)::
FLOATNAME(LMatrix4)(const FLOATNAME(LVecBase4) &row0,
const FLOATNAME(LVecBase4) &row1,
const FLOATNAME(LVecBase4) &row2,
const FLOATNAME(LVecBase4) &row3) {
TAU_PROFILE("LMatrix4::LMatrix4(const LVecBase4 &, ...)", " ", TAU_USER);
#ifdef HAVE_EIGEN
_m.row(0) = row0._v;
_m.row(1) = row1._v;
_m.row(2) = row2._v;
_m.row(3) = row3._v;
#else
_m(0, 0) = row0._v(0);
_m(0, 1) = row0._v(1);
_m(0, 2) = row0._v(2);
_m(0, 3) = row0._v(3);
_m(1, 0) = row1._v(0);
_m(1, 1) = row1._v(1);
_m(1, 2) = row1._v(2);
_m(1, 3) = row1._v(3);
_m(2, 0) = row2._v(0);
_m(2, 1) = row2._v(1);
_m(2, 2) = row2._v(2);
_m(2, 3) = row2._v(3);
_m(3, 0) = row3._v(0);
_m(3, 1) = row3._v(1);
_m(3, 2) = row3._v(2);
_m(3, 3) = row3._v(3);
#endif // HAVE_EIGEN
}
/**
*
*/

View File

@ -36,6 +36,7 @@ PUBLISHED:
INLINE_LINMATH FLOATTYPE operator [](int i) const;
INLINE_LINMATH FLOATTYPE &operator [](int i);
INLINE_LINMATH static int size();
INLINE_LINMATH operator const FLOATNAME(LVecBase4) &() const;
public:
FLOATTYPE *_row;
friend class FLOATNAME(LMatrix4);
@ -46,6 +47,7 @@ PUBLISHED:
PUBLISHED:
INLINE_LINMATH FLOATTYPE operator [](int i) const;
INLINE_LINMATH static int size();
INLINE_LINMATH operator const FLOATNAME(LVecBase4) &() const;
public:
const FLOATTYPE *_row;
friend class FLOATNAME(LMatrix4);
@ -60,10 +62,14 @@ PUBLISHED:
const FLOATNAME(UnalignedLMatrix4) &other);
INLINE_LINMATH FLOATNAME(LMatrix4) &operator = (FLOATTYPE fill_value);
INLINE_LINMATH FLOATNAME(LMatrix4)(FLOATTYPE e00, FLOATTYPE e01, FLOATTYPE e02, FLOATTYPE e03,
FLOATTYPE e10, FLOATTYPE e11, FLOATTYPE e12, FLOATTYPE e13,
FLOATTYPE e20, FLOATTYPE e21, FLOATTYPE e22, FLOATTYPE e23,
FLOATTYPE e30, FLOATTYPE e31, FLOATTYPE e32, FLOATTYPE e33);
INLINE_LINMATH FLOATNAME(LMatrix4)(FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE,
FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE,
FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE,
FLOATTYPE, FLOATTYPE, FLOATTYPE, FLOATTYPE);
INLINE_LINMATH FLOATNAME(LMatrix4)(const FLOATNAME(LVecBase4) &,
const FLOATNAME(LVecBase4) &,
const FLOATNAME(LVecBase4) &,
const FLOATNAME(LVecBase4) &);
ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix4));
EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);

View File

@ -115,7 +115,6 @@ apply_attribs_to_vertices(const AccumulatedAttribs &attribs, int attrib_types,
Thread *current_thread = Thread::get_current_thread();
OPEN_ITERATE_CURRENT_AND_UPSTREAM(_cycler, current_thread) {
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
GeomList::iterator gi;
PT(GeomList) geoms = cdata->modify_geoms();
// Iterate based on the number of geoms, not using STL iterators. This

View File

@ -742,7 +742,6 @@ make_compatible_state(GeomNode *node) {
}
GeomNode::CDWriter cdata(node->_cycler);
GeomNode::GeomList::iterator gi;
PT(GeomNode::GeomList) geoms = cdata->modify_geoms();
// For each geom, calculate a canonicalized RenderState, and classify all

View File

@ -82,10 +82,7 @@ play_frame(DatagramIterator &scan, BamReader *manager) {
int num_packets = scan.get_uint16();
for (int i = 0; i < num_packets; i++) {
size_t size = scan.get_uint16();
vector_uchar packet(size);
scan.extract_bytes(&packet[0], size);
_data.push_back(Datagram(std::move(packet)));
_data.push_back(Datagram(scan.get_blob()));
}
}

View File

@ -1072,7 +1072,6 @@ render_polygon_contours(TextGlyph *glyph, bool face, bool extrude) {
// create more vertices--they don't share the same normals.
for (ci = _contours.begin(); ci != _contours.end(); ++ci) {
const Contour &contour = (*ci);
Points::const_iterator pi;
for (size_t i = 0; i < contour._points.size(); ++i) {
const ContourPoint &cp = contour._points[i];

View File

@ -837,12 +837,12 @@ int MayaEggGeom::GetVert(EggVertex *vert, EggGroup *context)
void MayaEggGeom::AssignNames(void)
{
string name = _pool->get_name();
int nsize = name.size();
if ((nsize > 6) && (name.rfind(".verts")==(nsize-6))) {
name.resize(nsize-6);
size_t nsize = name.size();
if (nsize > 6 && name.rfind(".verts") == (nsize - 6)) {
name.resize(nsize - 6);
}
if ((nsize > 4) && (name.rfind(".cvs")==(nsize-4))) {
name.resize(nsize-4);
if (nsize > 4 && name.rfind(".cvs") == (nsize - 4)) {
name.resize(nsize - 4);
}
MFnDependencyNode dnshape(_shapeNode);
@ -913,7 +913,7 @@ void MayaEggGeom::AddEggFlag(MString fieldName) {
typedef phash_map<LTexCoordd, int> TVertTable;
typedef phash_map<LColor, int> CVertTable;
class MayaEggMesh : public MayaEggGeom
class MayaEggMesh final : public MayaEggGeom
{
public:
MColorArray _faceColorArray;
@ -937,7 +937,7 @@ public:
int GetCVert(const LColor &col);
int AddFace(unsigned numVertices, MIntArray mvertIndices, MIntArray mtvertIndices, MayaEggTex *tex);
void ConnectTextures(void);
void ConnectTextures(void) override;
};
int MayaEggMesh::GetTVert(const LTexCoordd &uv)
@ -2012,7 +2012,7 @@ void MayaEggLoader::PrintData(MayaEggMesh *mesh)
void MayaEggLoader::ParseFrameInfo(string comment)
{
int pos, ls, le;
size_t pos, ls, le;
pos = comment.find("-fri");
if (pos != string::npos) {
@ -2143,7 +2143,7 @@ bool MayaEggLoader::ConvertEggFile(const char *name, bool merge, bool model, boo
MObject MayaEggLoader::GetDependencyNode(string givenName)
{
MObject node = MObject::kNullObj;
int pos;
size_t pos;
string name;
pos = givenName.find(":");

View File

@ -2742,7 +2742,7 @@ set_shader_legacy(EggPrimitive &primitive, const MayaShader &shader,
// shader on the list is the base one, which should always pick up
// the alpha from the texture file. But the top textures may have
// to strip the alpha
if (i!=shader._color.size()-1) {
if ((size_t)i != shader._color.size() - 1) {
if (!i && is_interpolate) {
// this is the grass path mode where alpha on this texture
// determines whether to show layer1 or layer2. Since by now
@ -2846,7 +2846,7 @@ set_shader_legacy(EggPrimitive &primitive, const MayaShader &shader,
_textures.create_unique_texture(tex, ~0);
if (mesh) {
if (uvset_name.find("not found") == -1) {
if (uvset_name.find("not found") == string::npos) {
primitive.add_texture(new_tex);
color_def->_uvset_name.assign(uvset_name.c_str());
if (uvset_name != "map1") {

View File

@ -37,7 +37,8 @@ def test_egg2pg_transform_ident(egg_coordsys, coordsys):
@pytest.mark.parametrize("coordsys", COORD_SYSTEMS)
def test_egg2pg_transform_mat_unchanged(coordsys):
# Ensures that the matrix remains unchanged if coordinate system is same.
mat = (5, 2, -3, 4, 5, 6, 7, 8, 9, 1, -3, 2, 5, 2, 5, 2)
matv = (5, 2, -3, 4, 5, 6, 7, 8, 9, 1, -3, 2, 5, 2, 5, 2)
mat = core.Mat4D(*matv)
group = egg.EggGroup("group")
group.add_matrix4(mat)
assert not group.transform_is_identity()
@ -57,7 +58,7 @@ def test_egg2pg_transform_mat_unchanged(coordsys):
assert root
node, = root.children
assert node.transform.mat == mat
assert node.transform.mat == core.Mat4(*matv)
@pytest.mark.parametrize("egg_coordsys", COORD_SYSTEMS)

View File

@ -22,8 +22,10 @@ def image_rgb_path():
"Generates an RGB image."
file = tempfile.NamedTemporaryFile(suffix='-rgb.png')
write_image(file.name, 3)
yield file.name
path = core.Filename.from_os_specific(file.name)
path.make_true_case()
write_image(path, 3)
yield path
file.close()
@ -32,8 +34,10 @@ def image_rgba_path():
"Generates an RGBA image."
file = tempfile.NamedTemporaryFile(suffix='-rgba.png')
write_image(file.name, 4)
yield file.name
path = core.Filename.from_os_specific(file.name)
path.make_true_case()
write_image(path, 4)
yield path
file.close()
@ -42,8 +46,10 @@ def image_gray_path():
"Generates a grayscale image."
file = tempfile.NamedTemporaryFile(suffix='-gray.png')
write_image(file.name, 1)
yield file.name
path = core.Filename.from_os_specific(file.name)
path.make_true_case()
write_image(path, 1)
yield path
file.close()

View File

@ -0,0 +1,62 @@
import pytest
from copy import copy
from panda3d import core
def test_mat3_aliases():
assert core.LMatrix3 is core.Mat3
assert core.LMatrix3f is core.Mat3F
assert core.LMatrix3d is core.Mat3D
assert (core.LMatrix3f is core.Mat3) != (core.LMatrix3d is core.Mat3)
@pytest.mark.parametrize("type", (core.LMatrix3f, core.LMatrix3d))
def test_mat3_constructor(type):
# Test that three ways of construction produce the same matrix.
mat1 = type((1, 2, 3),
(4, 5, 6),
(7, 8, 9))
mat2 = type(1, 2, 3, 4, 5, 6, 7, 8, 9)
mat3 = type((1, 2, 3, 4, 5, 6, 7, 8, 9))
assert mat1 == mat2
assert mat2 == mat3
assert mat1 == mat3
@pytest.mark.parametrize("type", (core.LMatrix3d, core.LMatrix3f))
def test_mat3_copy_constuctor(type):
mat1 = type((1, 2, 3),
(4, 5, 6),
(7, 8, 9))
# Make a copy. Changing it should not change the original.
mat2 = type(mat1)
assert mat1 == mat2
mat2[0][0] = 100
assert mat1 != mat2
# Make a copy by unpacking.
mat2 = type(*mat1)
assert mat1 == mat2
mat2[0][0] = 100
assert mat1 != mat2
# Make a copy by calling copy.copy.
mat2 = copy(mat1)
assert mat1 == mat2
mat2[0][0] = 100
assert mat1 != mat2
@pytest.mark.parametrize("type", (core.LMatrix3d, core.LMatrix3f))
def test_mat3_invert_same_type(type):
mat = type((1, 0, 0,
0, 1, 0,
1, 2, 3))
inv = core.invert(mat)
assert mat.__class__ == inv.__class__

View File

@ -0,0 +1,89 @@
import pytest
from copy import copy
from panda3d import core
def test_mat4_aliases():
assert core.LMatrix4 is core.Mat4
assert core.LMatrix4f is core.Mat4F
assert core.LMatrix4d is core.Mat4D
assert (core.LMatrix4f is core.Mat4) != (core.LMatrix4d is core.Mat4)
@pytest.mark.parametrize("type", (core.LMatrix4d, core.LMatrix4f))
def test_mat4_constructor(type):
# Test that three ways of construction produce the same matrix.
mat1 = type((1, 2, 3, 4),
(5, 6, 7, 8),
(9, 10, 11, 12),
(13, 14, 15, 16))
mat2 = type(1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16)
mat3 = type((1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16))
assert mat1 == mat2
assert mat2 == mat3
assert mat1 == mat3
@pytest.mark.parametrize("type", (core.LMatrix4d, core.LMatrix4f))
def test_mat4_copy_constuctor(type):
mat1 = type((1, 2, 3, 4),
(5, 6, 7, 8),
(9, 10, 11, 12),
(13, 14, 15, 16))
# Make a copy. Changing it should not change the original.
mat2 = type(mat1)
assert mat1 == mat2
mat2[0][0] = 100
assert mat1 != mat2
# Make a copy by unpacking.
mat2 = type(*mat1)
assert mat1 == mat2
mat2[0][0] = 100
assert mat1 != mat2
# Make a copy by calling copy.copy.
mat2 = copy(mat1)
assert mat1 == mat2
mat2[0][0] = 100
assert mat1 != mat2
@pytest.mark.parametrize("type", (core.LMatrix4d, core.LMatrix4f))
def test_mat4_invert_same_type(type):
mat = type((1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
1, 2, 3, 1))
inv = core.invert(mat)
assert mat.__class__ == inv.__class__
@pytest.mark.parametrize("type", (core.LMatrix4d, core.LMatrix4f))
def test_mat4_invert_correct(type):
mat = type((1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
1, 2, 3, 1))
inv = type()
assert inv.invert_from(mat)
assert inv == type(( 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
-1, -2, -3, 1))
assert (mat * inv).is_identity()
assert (inv * mat).is_identity()

View File

@ -1,20 +0,0 @@
import pytest
from panda3d import core
@pytest.mark.parametrize("type", (core.Mat4, core.Mat4D))
def test_mat4_invert(type):
mat = type((1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
1, 2, 3, 1))
inv = type()
assert inv.invert_from(mat)
assert inv == type(( 1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
-1, -2, -3, 1))
assert (mat * inv).is_identity()
assert (inv * mat).is_identity()

View File

@ -1,6 +1,7 @@
import pytest
from panda3d import core
import sys
import tempfile
# Fixtures for generating interesting datagrams (and verification functions) on
# the fly...
@ -28,6 +29,9 @@ def datagram_small(request):
dg.add_string32('this is another string')
dg.add_string('this is yet a third string')
dg.add_blob(b'blob data \x00\xf2\xa0\x00\x00')
dg.add_blob32(b'\xc9\x8f\x00 test blob32')
dg.add_stdfloat(800.2)
dg.add_stdfloat(3.1415926)
dg.add_stdfloat(2.7182818)
@ -49,6 +53,9 @@ def datagram_small(request):
assert dgi.get_string32() == 'this is another string'
assert dgi.get_string() == 'this is yet a third string'
assert dgi.get_blob() == b'blob data \x00\xf2\xa0\x00\x00'
assert dgi.get_blob32() == b'\xc9\x8f\x00 test blob32'
assert dgi.get_stdfloat() == pytest.approx(800.2)
assert dgi.get_stdfloat() == pytest.approx(3.1415926)
assert dgi.get_stdfloat() == pytest.approx(2.7182818)
@ -88,6 +95,12 @@ def test_datagram_bytes():
dgi.get_remaining_bytes() == b'abc\x00\xff123'
def test_datagram_get_message():
dg = core.Datagram(b'abc\x00')
dg.append_data(b'\xff123')
assert dg.get_message() == b'abc\x00\xff123'
def test_iterator(datagram_small):
"""This tests Datagram/DatagramIterator, and sort of serves as a self-check
of the test fixtures too."""
@ -135,30 +148,39 @@ def do_file_test(dg, verify, filename):
dgi = core.DatagramIterator(dg2)
verify(dgi)
def test_file_small(datagram_small, tmpdir):
@pytest.fixture
def tmpfile():
file = tempfile.NamedTemporaryFile(suffix='.bin')
yield file
file.close()
def test_file_small(datagram_small, tmpfile):
"""This tests DatagramOutputFile/DatagramInputFile on small datagrams."""
dg, verify = datagram_small
p = tmpdir.join('datagram.bin')
filename = core.Filename.from_os_specific(str(p))
file = tempfile.NamedTemporaryFile(suffix='.bin')
filename = core.Filename.from_os_specific(file.name)
filename.make_true_case()
do_file_test(dg, verify, filename)
def test_file_large(datagram_large, tmpdir):
def test_file_large(datagram_large, tmpfile):
"""This tests DatagramOutputFile/DatagramInputFile on very large datagrams."""
dg, verify = datagram_large
p = tmpdir.join('datagram.bin')
filename = core.Filename.from_os_specific(str(p))
file = tempfile.NamedTemporaryFile(suffix='.bin')
filename = core.Filename.from_os_specific(file.name)
filename.make_true_case()
do_file_test(dg, verify, filename)
def test_file_corrupt(datagram_small, tmpdir):
def test_file_corrupt(datagram_small, tmpfile):
"""This tests DatagramInputFile's handling of a corrupt size header."""
dg, verify = datagram_small
p = tmpdir.join('datagram.bin')
filename = core.Filename.from_os_specific(str(p))
file = tempfile.NamedTemporaryFile(suffix='.bin')
filename = core.Filename.from_os_specific(file.name)
filename.make_true_case()
dof = core.DatagramOutputFile()
dof.open(filename)
@ -166,9 +188,9 @@ def test_file_corrupt(datagram_small, tmpdir):
dof.close()
# Corrupt the size header to 1GB
with p.open(mode='r+b') as f:
f.seek(0)
f.write(b'\xFF\xFF\xFF\x4F')
file.seek(0)
file.write(b'\xFF\xFF\xFF\x4F')
file.flush()
dg2 = core.Datagram()
dif = core.DatagramInputFile()
@ -178,8 +200,7 @@ def test_file_corrupt(datagram_small, tmpdir):
# Truncate the file
for size in [12, 8, 4, 3, 2, 1, 0]:
with p.open(mode='r+b') as f:
f.truncate(size)
file.truncate(size)
dg2 = core.Datagram()
dif = core.DatagramInputFile()