summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorEuclid Linden <euclid@lindenlab.com>2022-04-18 21:56:26 +0000
committerEuclid Linden <euclid@lindenlab.com>2022-04-18 21:56:26 +0000
commite71201ac125cab5f3d3cf7d6a30500253fc29d90 (patch)
tree270e46eb85dd46fb6962a36a9357dbf31c3afb29 /indra/llcommon
parent2d63d2044e0a00d1969c3da254e016a6e520c0d5 (diff)
parent035b1996df3f357b5060e3eb778588da5b9e7b37 (diff)
Merged in DV528-merge-6.5.5 (pull request #945)
DRTVWR-528 merge up to 6.5.5
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llcoros.cpp27
-rw-r--r--indra/llcommon/llerror.cpp10
-rw-r--r--indra/llcommon/lleventcoro.cpp2
-rw-r--r--indra/llcommon/llleap.cpp2
-rw-r--r--indra/llcommon/llmetricperformancetester.cpp1
-rw-r--r--indra/llcommon/llsdutil.cpp7
-rw-r--r--indra/llcommon/llsdutil.h4
-rw-r--r--indra/llcommon/llsys.cpp59
-rw-r--r--indra/llcommon/tests/llleap_test.cpp41
-rw-r--r--indra/llcommon/tests/llprocess_test.cpp30
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp15
11 files changed, 120 insertions, 78 deletions
diff --git a/indra/llcommon/llcoros.cpp b/indra/llcommon/llcoros.cpp
index 75fc0fec99..c2d353b0fc 100644
--- a/indra/llcommon/llcoros.cpp
+++ b/indra/llcommon/llcoros.cpp
@@ -249,14 +249,25 @@ std::string LLCoros::launch(const std::string& prefix, const callable_t& callabl
// protected_fixedsize_stack sets a guard page past the end of the new
// stack so that stack underflow will result in an access violation
// instead of weird, subtle, possibly undiagnosed memory stomps.
- boost::fibers::fiber newCoro(boost::fibers::launch::dispatch,
- std::allocator_arg,
- boost::fibers::protected_fixedsize_stack(mStackSize),
- [this, &name, &callable](){ toplevel(name, callable); });
- // You have two choices with a fiber instance: you can join() it or you
- // can detach() it. If you try to destroy the instance before doing
- // either, the program silently terminates. We don't need this handle.
- newCoro.detach();
+
+ try
+ {
+ boost::fibers::fiber newCoro(boost::fibers::launch::dispatch,
+ std::allocator_arg,
+ boost::fibers::protected_fixedsize_stack(mStackSize),
+ [this, &name, &callable]() { toplevel(name, callable); });
+
+ // You have two choices with a fiber instance: you can join() it or you
+ // can detach() it. If you try to destroy the instance before doing
+ // either, the program silently terminates. We don't need this handle.
+ newCoro.detach();
+ }
+ catch (std::bad_alloc&)
+ {
+ // Out of memory on stack allocation?
+ LL_ERRS("LLCoros") << "Bad memory allocation in LLCoros::launch(" << prefix << ")!" << LL_ENDL;
+ }
+
return name;
}
diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp
index 3fe8ce5f0e..55a06f8326 100644
--- a/indra/llcommon/llerror.cpp
+++ b/indra/llcommon/llerror.cpp
@@ -539,8 +539,6 @@ namespace
protected:
Globals();
public:
- std::ostringstream messageStream;
- bool messageStreamInUse;
std::string mFatalMessage;
void addCallSite(LLError::CallSite&);
@@ -557,8 +555,7 @@ namespace
};
Globals::Globals()
- : messageStream(),
- messageStreamInUse(false),
+ :
callSites(),
mSettingsConfig(new SettingsConfig())
{
@@ -1434,7 +1431,10 @@ namespace LLError
if (site.mLevel == LEVEL_ERROR)
{
g->mFatalMessage = message;
- s->mCrashFunction(message);
+ if (s->mCrashFunction)
+ {
+ s->mCrashFunction(message);
+ }
}
}
}
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index 995356dc52..067b5e6fbc 100644
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -101,7 +101,7 @@ void storeToLLSDPath(LLSD& dest, const LLSD& path, const LLSD& value)
}
// Drill down to where we should store 'value'.
- llsd::drill(dest, path) = value;
+ llsd::drill_ref(dest, path) = value;
}
} // anonymous
diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp
index e8ea0ab398..2704f8b6de 100644
--- a/indra/llcommon/llleap.cpp
+++ b/indra/llcommon/llleap.cpp
@@ -86,7 +86,7 @@ public:
// notice Python specially: we provide Python LLSD serialization
// support, so there's a pretty good reason to implement plugins
// in that language.
- if (cparams.args.size() && (desclower == "python" || desclower == "python.exe"))
+ if (cparams.args.size() && (desclower == "python" || desclower == "python3" || desclower == "python.exe"))
{
mDesc = LLProcess::basename(cparams.args()[0]);
}
diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp
index f8a93baf45..100eb57555 100644
--- a/indra/llcommon/llmetricperformancetester.cpp
+++ b/indra/llcommon/llmetricperformancetester.cpp
@@ -189,7 +189,6 @@ LLMetricPerformanceTesterBasic::~LLMetricPerformanceTesterBasic()
void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd)
{
incrementCurrentCount() ;
- (*sd)[getCurrentLabelName()]["Name"] = mName ;
}
void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd)
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index eb3a96b133..fc10fcece3 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -29,6 +29,7 @@
#include "linden_common.h"
#include "llsdutil.h"
+#include <sstream>
#if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN
@@ -862,7 +863,7 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, int bits)
namespace llsd
{
-LLSD& drill(LLSD& blob, const LLSD& rawPath)
+LLSD& drill_ref(LLSD& blob, const LLSD& rawPath)
{
// Treat rawPath uniformly as an array. If it's not already an array,
// store it as the only entry in one. (But let's say Undefined means an
@@ -917,9 +918,9 @@ LLSD& drill(LLSD& blob, const LLSD& rawPath)
LLSD drill(const LLSD& blob, const LLSD& path)
{
- // non-const drill() does exactly what we want. Temporarily cast away
+ // drill_ref() does exactly what we want. Temporarily cast away
// const-ness and use that.
- return drill(const_cast<LLSD&>(blob), path);
+ return drill_ref(const_cast<LLSD&>(blob), path);
}
} // namespace llsd
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index 8678ca97f2..1321615805 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -184,10 +184,10 @@ namespace llsd
* - Anything else is an error.
*
* By implication, if path.isUndefined() or otherwise equivalent to an empty
- * LLSD::Array, drill() returns 'blob' as is.
+ * LLSD::Array, drill[_ref]() returns 'blob' as is.
*/
LLSD drill(const LLSD& blob, const LLSD& path);
-LLSD& drill( LLSD& blob, const LLSD& path);
+LLSD& drill_ref( LLSD& blob, const LLSD& path);
}
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index 2ca15a31c6..cdc1d83b59 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -107,7 +107,7 @@ LLOSInfo::LLOSInfo() :
#if LL_WINDOWS
- if (IsWindowsVersionOrGreater(10, 0, 0))
+ if (IsWindows10OrGreater())
{
mMajorVer = 10;
mMinorVer = 0;
@@ -195,18 +195,6 @@ LLOSInfo::LLOSInfo() :
GetSystemInfo(&si); //if it fails get regular system info
//(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
- //msdn microsoft finds 32 bit and 64 bit flavors this way..
- //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
- //of windows than this code does (in case it is needed for the future)
- if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) //check for 64 bit
- {
- mOSStringSimple += "64-bit ";
- }
- else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
- {
- mOSStringSimple += "32-bit ";
- }
-
// Try calling GetVersionEx using the OSVERSIONINFOEX structure.
OSVERSIONINFOEX osvi;
ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));
@@ -240,7 +228,34 @@ LLOSInfo::LLOSInfo() :
ubr = data;
}
}
- }
+
+ if (mBuild >= 22000)
+ {
+ // At release Windows 11 version was 10.0.22000.194
+ // Windows 10 version was 10.0.19043.1266
+ // There is no warranty that Win10 build won't increase,
+ // so until better solution is found or Microsoft updates
+ // SDK with IsWindows11OrGreater(), indicate "10/11"
+ //
+ // Current alternatives:
+ // Query WMI's Win32_OperatingSystem for OS string. Slow
+ // and likely to return 'compatibility' string.
+ // Check presence of dlls/libs or may be their version.
+ mOSStringSimple = "Microsoft Windows 10/11 ";
+ }
+ }
+
+ //msdn microsoft finds 32 bit and 64 bit flavors this way..
+ //http://msdn.microsoft.com/en-us/library/ms724429(VS.85).aspx (example code that contains quite a few more flavors
+ //of windows than this code does (in case it is needed for the future)
+ if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64) //check for 64 bit
+ {
+ mOSStringSimple += "64-bit ";
+ }
+ else if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
+ {
+ mOSStringSimple += "32-bit ";
+ }
mOSString = mOSStringSimple;
if (mBuild > 0)
@@ -1222,7 +1237,12 @@ BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
LLFILE *dst = NULL;
S32 bytes = 0;
tmpfile = dstfile + ".t";
- src = gzopen(srcfile.c_str(), "rb");
+#ifdef LL_WINDOWS
+ llutf16string utf16filename = utf8str_to_utf16str(srcfile);
+ src = gzopen_w(utf16filename.c_str(), "rb");
+#else
+ src = gzopen(srcfile.c_str(), "rb");
+#endif
if (! src) goto err;
dst = LLFile::fopen(tmpfile, "wb"); /* Flawfinder: ignore */
if (! dst) goto err;
@@ -1256,7 +1276,14 @@ BOOL gzip_file(const std::string& srcfile, const std::string& dstfile)
LLFILE *src = NULL;
S32 bytes = 0;
tmpfile = dstfile + ".t";
- dst = gzopen(tmpfile.c_str(), "wb"); /* Flawfinder: ignore */
+
+#ifdef LL_WINDOWS
+ llutf16string utf16filename = utf8str_to_utf16str(tmpfile);
+ dst = gzopen_w(utf16filename.c_str(), "wb");
+#else
+ dst = gzopen(tmpfile.c_str(), "wb");
+#endif
+
if (! dst) goto err;
src = LLFile::fopen(srcfile, "rb"); /* Flawfinder: ignore */
if (! src) goto err;
diff --git a/indra/llcommon/tests/llleap_test.cpp b/indra/llcommon/tests/llleap_test.cpp
index 9d71e327d8..9754353ab0 100644
--- a/indra/llcommon/tests/llleap_test.cpp
+++ b/indra/llcommon/tests/llleap_test.cpp
@@ -145,13 +145,13 @@ namespace tut
" data = ''.join(parts)\n"
" assert len(data) == length\n"
" try:\n"
- " return llsd.parse(data)\n"
+ " return llsd.parse(data.encode())\n"
// Seems the old indra.base.llsd module didn't properly
// convert IndexError (from running off end of string) to
// LLSDParseError.
- " except (IndexError, llsd.LLSDParseError), e:\n"
+ " except (IndexError, llsd.LLSDParseError) as e:\n"
" msg = 'Bad received packet (%s)' % e\n"
- " print >>sys.stderr, '%s, %s bytes:' % (msg, len(data))\n"
+ " print('%s, %s bytes:' % (msg, len(data)), file=sys.stderr)\n"
" showmax = 40\n"
// We've observed failures with very large packets;
// dumping the entire packet wastes time and space.
@@ -167,12 +167,12 @@ namespace tut
" data = data[:trunc]\n"
" ellipsis = '... (%s more)' % (length - trunc)\n"
" offset = -showmax\n"
- " for offset in xrange(0, len(data)-showmax, showmax):\n"
- " print >>sys.stderr, '%04d: %r +' % \\\n"
- " (offset, data[offset:offset+showmax])\n"
+ " for offset in range(0, len(data)-showmax, showmax):\n"
+ " print('%04d: %r +' % \\\n"
+ " (offset, data[offset:offset+showmax]), file=sys.stderr)\n"
" offset += showmax\n"
- " print >>sys.stderr, '%04d: %r%s' % \\\n"
- " (offset, data[offset:], ellipsis)\n"
+ " print('%04d: %r%s' % \\\n"
+ " (offset, data[offset:], ellipsis), file=sys.stderr)\n"
" raise ParseError(msg, data)\n"
"\n"
"# deal with initial stdin message\n"
@@ -189,7 +189,7 @@ namespace tut
" sys.stdout.flush()\n"
"\n"
"def send(pump, data):\n"
- " put(llsd.format_notation(dict(pump=pump, data=data)))\n"
+ " put(llsd.format_notation(dict(pump=pump, data=data)).decode())\n"
"\n"
"def request(pump, data):\n"
" # we expect 'data' is a dict\n"
@@ -253,7 +253,7 @@ namespace tut
{
set_test_name("bad stdout protocol");
NamedTempFile script("py",
- "print 'Hello from Python!'\n");
+ "print('Hello from Python!')\n");
CaptureLog log(LLError::LEVEL_WARN);
waitfor(LLLeap::create(get_test_name(),
sv(list_of(PYTHON)(script.getName()))));
@@ -438,8 +438,8 @@ namespace tut
// guess how many messages it will take to
// accumulate BUFFERED_LENGTH
"count = int(" << BUFFERED_LENGTH << "/samplen)\n"
- "print >>sys.stderr, 'Sending %s requests' % count\n"
- "for i in xrange(count):\n"
+ "print('Sending %s requests' % count, file=sys.stderr)\n"
+ "for i in range(count):\n"
" request('" << api.getName() << "', dict(reqid=i))\n"
// The assumption in this specific test that
// replies will arrive in the same order as
@@ -450,7 +450,7 @@ namespace tut
// arbitrary order, and we'd have to tick them
// off from a set.
"result = ''\n"
- "for i in xrange(count):\n"
+ "for i in range(count):\n"
" resp = get()\n"
" if resp['data']['reqid'] != i:\n"
" result = 'expected reqid=%s in %s' % (i, resp)\n"
@@ -476,13 +476,13 @@ namespace tut
"desired = int(sys.argv[1])\n"
// 7 chars per item: 6 digits, 1 comma
"count = int((desired - 50)/7)\n"
- "large = ''.join('%06d,' % i for i in xrange(count))\n"
+ "large = ''.join('%06d,' % i for i in range(count))\n"
// Pass 'large' as reqid because we know the API
// will echo reqid, and we want to receive it back.
"request('" << api.getName() << "', dict(reqid=large))\n"
"try:\n"
" resp = get()\n"
- "except ParseError, e:\n"
+ "except ParseError as e:\n"
" # try to find where e.data diverges from expectation\n"
// Normally we'd expect a 'pump' key in there,
// too, with value replypump(). But Python
@@ -493,17 +493,18 @@ namespace tut
// strange.
" expect = llsd.format_notation(dict(data=dict(reqid=large)))\n"
" chunk = 40\n"
- " for offset in xrange(0, max(len(e.data), len(expect)), chunk):\n"
+ " for offset in range(0, max(len(e.data), len(expect)), chunk):\n"
" if e.data[offset:offset+chunk] != \\\n"
" expect[offset:offset+chunk]:\n"
- " print >>sys.stderr, 'Offset %06d: expect %r,\\n'\\\n"
+ " print('Offset %06d: expect %r,\\n'\\\n"
" ' get %r' %\\\n"
" (offset,\n"
" expect[offset:offset+chunk],\n"
- " e.data[offset:offset+chunk])\n"
+ " e.data[offset:offset+chunk]),\n"
+ " file=sys.stderr)\n"
" break\n"
" else:\n"
- " print >>sys.stderr, 'incoming data matches expect?!'\n"
+ " print('incoming data matches expect?!', file=sys.stderr)\n"
" send('" << result.getName() << "', '%s: %s' % (e.__class__.__name__, e))\n"
" sys.exit(1)\n"
"\n"
@@ -512,7 +513,7 @@ namespace tut
" send('" << result.getName() << "', '')\n"
" sys.exit(0)\n"
// Here we know echoed did NOT match; try to find where
- "for i in xrange(count):\n"
+ "for i in range(count):\n"
" start = 7*i\n"
" end = 7*(i+1)\n"
" if end > len(echoed)\\\n"
diff --git a/indra/llcommon/tests/llprocess_test.cpp b/indra/llcommon/tests/llprocess_test.cpp
index f0eafa8201..e530975e86 100644
--- a/indra/llcommon/tests/llprocess_test.cpp
+++ b/indra/llcommon/tests/llprocess_test.cpp
@@ -360,10 +360,10 @@ namespace tut
"import time" EOL
EOL
"time.sleep(2)" EOL
- "print >>sys.stdout, 'stdout after wait'" EOL
+ "print('stdout after wait', file=sys.stdout)" EOL
"sys.stdout.flush()" EOL
"time.sleep(2)" EOL
- "print >>sys.stderr, 'stderr after wait'" EOL
+ "print('stderr after wait', file=sys.stderr)" EOL
"sys.stderr.flush()" EOL
);
@@ -381,7 +381,11 @@ namespace tut
std::vector<const char*> argv;
apr_proc_t child;
+#if defined(LL_WINDOWS)
argv.push_back("python");
+#else
+ argv.push_back("python3");
+#endif
// Have to have a named copy of this std::string so its c_str() value
// will persist.
std::string scriptname(script.getName());
@@ -573,7 +577,7 @@ namespace tut
// note nonstandard output-file arg!
"with open(sys.argv[3], 'w') as f:\n"
" for arg in sys.argv[1:]:\n"
- " print >>f, arg\n");
+ " print(arg, file=f)\n");
// We expect that PythonProcessLauncher has already appended
// its own NamedTempFile to mParams.args (sys.argv[0]).
py.mParams.args.add("first arg"); // sys.argv[1]
@@ -742,7 +746,7 @@ namespace tut
"with open(sys.argv[1], 'w') as f:\n"
" f.write('ok')\n"
"# wait for 'go' from test program\n"
- "for i in xrange(60):\n"
+ "for i in range(60):\n"
" time.sleep(1)\n"
" with open(sys.argv[2]) as f:\n"
" go = f.read()\n"
@@ -804,7 +808,7 @@ namespace tut
"with open(sys.argv[1], 'w') as f:\n"
" f.write('ok')\n"
"# wait for 'go' from test program\n"
- "for i in xrange(60):\n"
+ "for i in range(60):\n"
" time.sleep(1)\n"
" with open(sys.argv[2]) as f:\n"
" go = f.read()\n"
@@ -857,7 +861,7 @@ namespace tut
set_test_name("'bogus' test");
CaptureLog recorder;
PythonProcessLauncher py(get_test_name(),
- "print 'Hello world'\n");
+ "print('Hello world')\n");
py.mParams.files.add(LLProcess::FileParam("bogus"));
py.mPy = LLProcess::create(py.mParams);
ensure("should have rejected 'bogus'", ! py.mPy);
@@ -872,7 +876,7 @@ namespace tut
// Replace this test with one or more real 'file' tests when we
// implement 'file' support
PythonProcessLauncher py(get_test_name(),
- "print 'Hello world'\n");
+ "print('Hello world')\n");
py.mParams.files.add(LLProcess::FileParam());
py.mParams.files.add(LLProcess::FileParam("file"));
py.mPy = LLProcess::create(py.mParams);
@@ -887,7 +891,7 @@ namespace tut
// implement 'tpipe' support
CaptureLog recorder;
PythonProcessLauncher py(get_test_name(),
- "print 'Hello world'\n");
+ "print('Hello world')\n");
py.mParams.files.add(LLProcess::FileParam());
py.mParams.files.add(LLProcess::FileParam("tpipe"));
py.mPy = LLProcess::create(py.mParams);
@@ -904,7 +908,7 @@ namespace tut
// implement 'npipe' support
CaptureLog recorder;
PythonProcessLauncher py(get_test_name(),
- "print 'Hello world'\n");
+ "print('Hello world')\n");
py.mParams.files.add(LLProcess::FileParam());
py.mParams.files.add(LLProcess::FileParam());
py.mParams.files.add(LLProcess::FileParam("npipe"));
@@ -980,7 +984,7 @@ namespace tut
{
set_test_name("get*Pipe() validation");
PythonProcessLauncher py(get_test_name(),
- "print 'this output is expected'\n");
+ "print('this output is expected)'\n");
py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stdin
py.mParams.files.add(LLProcess::FileParam()); // inherit stdout
py.mParams.files.add(LLProcess::FileParam("pipe")); // pipe for stderr
@@ -1001,13 +1005,13 @@ namespace tut
set_test_name("talk to stdin/stdout");
PythonProcessLauncher py(get_test_name(),
"import sys, time\n"
- "print 'ok'\n"
+ "print('ok')\n"
"sys.stdout.flush()\n"
"# wait for 'go' from test program\n"
"go = sys.stdin.readline()\n"
"if go != 'go\\n':\n"
" sys.exit('expected \"go\", saw %r' % go)\n"
- "print 'ack'\n");
+ "print('ack')\n");
py.mParams.files.add(LLProcess::FileParam("pipe")); // stdin
py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
py.launch();
@@ -1118,7 +1122,7 @@ namespace tut
{
set_test_name("ReadPipe \"eof\" event");
PythonProcessLauncher py(get_test_name(),
- "print 'Hello from Python!'\n");
+ "print('Hello from Python!')\n");
py.mParams.files.add(LLProcess::FileParam()); // stdin
py.mParams.files.add(LLProcess::FileParam("pipe")); // stdout
py.launch();
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 642c1c3879..c246f5ee56 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1795,7 +1795,7 @@ namespace tut
set_test_name("verify NamedTempFile");
python("platform",
"import sys\n"
- "print 'Running on', sys.platform\n");
+ "print('Running on', sys.platform)\n");
}
// helper for test<3>
@@ -1825,14 +1825,14 @@ namespace tut
const char pydata[] =
"def verify(iterable):\n"
" it = iter(iterable)\n"
- " assert it.next() == 17\n"
- " assert abs(it.next() - 3.14) < 0.01\n"
- " assert it.next() == '''\\\n"
+ " assert next(it) == 17\n"
+ " assert abs(next(it) - 3.14) < 0.01\n"
+ " assert next(it) == '''\\\n"
"This string\n"
"has several\n"
"lines.'''\n"
" try:\n"
- " it.next()\n"
+ " next(it)\n"
" except StopIteration:\n"
" pass\n"
" else:\n"
@@ -1855,7 +1855,7 @@ namespace tut
" yield llsd.parse(item)\n" <<
pydata <<
// Don't forget raw-string syntax for Windows pathnames.
- "verify(parse_each(open(r'" << file.getName() << "')))\n");
+ "verify(parse_each(open(r'" << file.getName() << "', 'rb')))\n");
}
template<> template<>
@@ -1870,7 +1870,6 @@ namespace tut
python("write Python notation",
placeholders::arg1 <<
- "from __future__ import with_statement\n" <<
import_llsd <<
"DATA = [\n"
" 17,\n"
@@ -1884,7 +1883,7 @@ namespace tut
// N.B. Using 'print' implicitly adds newlines.
"with open(r'" << file.getName() << "', 'w') as f:\n"
" for item in DATA:\n"
- " print >>f, llsd.format_notation(item)\n");
+ " print(llsd.format_notation(item).decode(), file=f)\n");
std::ifstream inf(file.getName().c_str());
LLSD item;