[FIXED] - Sudden BlobMedia parameter-type troubles

I’m trying to resolve this error message:
TypeError: content must be a byte-string, not str
which is occurring in code that has not changed since 2:03pm (EST) Nov. 10th. The critical line is:

self.report_file = BlobMedia("text/plain", report_as_text, name="report.txt")

The value in report_as_text has always been of type str, and it has always worked. Until today. A check of the docs says that it needs a byte-string.

Applying the fix from a Bug Report, led to trying this code instead:

byte_string = report_as_text.encode('utf-8')
print(type(byte_string))
self.report_file = BlobMedia("text/plain", byte_string, name="report.txt")

which should have constructed an object of type bytes. However, the print call showed that encode returned a value of type str. Naturally, with the 2nd parameter’s type unchanged, the BlobMedia call failed again, with the same error.

The Client does not seem to know the built-in functions bytes and bytearray, so I am currently stumped as to how to get my report converted to a “byte-string”. If anyone knows a working alternative, something that BlobMedia will accept, please reply.

Until this is resolved, I am disabling construction of my BlobMedia object. Users will be able to view their Reports, but not download them.

I really hate ‘Well it works for me posts’ but with that in mind:

some_text = "A long bleeping report\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nThe End"
byte_string = some_text.encode('utf-8')
print((type(byte_string)))
byte_text2 = some_text.encode('UTF-8')
print((type(byte_text2)))
self.report_file = BlobMedia("text/plain", byte_string, name="report.txt")
print(type(self.report_file))

…for me prints the following output in the IDE:

<class 'bytes'>
<class 'bytes'>
<class 'anvil.BlobMedia'>

I don’t know much about what your input string is, or if you how old your app version is compared to the one I am testing on (The one I used is only a few weeks old)

Maybe anvil is handling the UnicodeError exception somewhere without letting us see it? It does not sound plausible, but neither does what is happening when you are trying to create a BlobMedia that worked a few days ago and now does not, so anything is plausible.

Could you try:

byte_string = report_as_text.encode('utf-8', 'ignore')

at least to rule that out? from

[https://docs.python.org/3.6/library/codecs.html#codecs.encode](http://python.org: 7.2. codecs — Codec registry and base classes)

(I deal with Telnet encode/decode issues all the time so I might see everything as an encoding nail to be hammered)

I appreciate your looking into this. I’ve been digging, also, and I think I may have found a key part of the problem: due to my App’s age, its Client code is running as Python 2, which does not have a ‘bytes’ type.

This still does not explain why the exact same code worked yesterday. Perhaps a Skulpt update occurred?

Option 1
With that in mind, upgrading this App to Client-side Python 3 looks like the obvious solution, and will probably be the best solution, long-term. (After all, we can’t expect our good friends at Anvil to support obsolete infrastructure forever.)

Unfortunately, the App’s sheer size (my forms\ folder contains 266 files), and my unfamiliarity with the new Packages layout (a prerequisite) may make that difficult.

Maybe when I can budget the time, I’ll try out the upgrade process on a clone of the App, and watch what happens to my local copy (via Git) of the clone’s files and folders, as a result.

Option 2
For now, instead of building the BlobMedia on the Client, with its Python 2 limitations, I’m just going to try building it on the Server, where the code runs in Python 3, and returning it from there to the Client.

Posting here in response as it appears related - I’ve just resolved a similar issue with BlobMedia that was working a couple of days ago but fell over this morning

Server-side - uplink (python 3.7.7 ):

import os
def write_text_file():
    .... *lines of text strings*
    f = io.StringIO()
    f.writelines(line1, line2, line3)
    contents = f.getvalue().encode()
    text_file = anvil.BlobMedia(content_type="text/plain", contents=contents, name="text_file.txt"

Client-side
This is what was working previously:

text_file = anvil.server.call('write_text_file')
text_strings = text_file.get_bytes()

and the correction to make it work as of Nov 14

text_strings = text_file.get_bytes().decode() 

It appears something might have changed to affect .get_bytes() on the client side.

Where I was previously receiving text_strings from the server call with no problems, whatever changed mean that I was receiving a bunch of comma-separated integers. It dawned on me that I might be looking at the binary encoded version; in short .decode() did the trick.

See response for background:

With respect to this post:

Have you tried removing the ‘utf-8’ from .encode(), i,e.

byte_string = report_as_text.encode()
print(type(byte_string))
self.report_file = BlobMedia("text/plain", byte_string, name="report.txt")

I tried a similar print statement without the type - i.e.

print(byte_string)

which should return a binary string something like this:

b"byte_string"

which BlobMedia should return client-side . As per my post I suspect that:

text = self.report_file.get_bytes().decode()

to get_bytes() from Blob object (binary) and then .decode() into string text might do the trick.

thanks @p.colbert - looks like this was a bug in our client-side python 2 implementation.
The error you were seeing should now be fixed

Indeed, it is fixed.

Many thanks, @stucork. That saved me a daunting amount of work.

Edit: I suspect that @Matthew may be able to reverse his “fix” above.