Forum Archive

[Bug] objc_util and dir()

blmacbeth

Hey @omz, I got back in to playing around with objc_util and found this:

>>> dir(OMJavaScriptSyntaxHighlighter)
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/var/mobile/Containers/Bundle/Application/61407674-7331-47C2-B308-BDB7BBE52166/Pythonista3.app/Frameworks/PythonistaKit3.framework/pylib/site-packages/objc_util.py", line 380, in __dir__
    py_method_name = sel_name.replace(':', '_')
TypeError: a bytes-like object is required, not 'str'

This error come from the way Python3.* encodes ASCII vs Unicode strings. When you run the following:

om_classes = [cls for cls in ObjCClass.get_names() if cls.startswith(b'OM')]
for cls in om_classes:
    print(cls)

You get the following (truncated for brevity):

b'OMAutoresizingMaskView'
b'OMBarButton'
b'OMBarButtonItem'
b'OMBaseSyntaxHighlighter'
b'OMBasicPythonCompletionProvider'
b'OMBasicPythonCompletionProviderTokenizedLine'
b'OMButtonFieldSpecifier'
b'OMCSSSyntaxHighlighter'
b'OMCaretView'
b'OMCheckCell'
b'OMCheckFieldSpecifier'
…
b'OMUIWidgetViewScrollView'
b'OMUIWidgetViewSegmentedControl'
b'OMUIWidgetViewSlider'
b'OMUIWidgetViewStickyNote'
b'OMUIWidgetViewSwitch'
b'OMUIWidgetViewTableView'
b'OMUIWidgetViewTextField'
b'OMUIWidgetViewTextView'
b'OMUIWidgetViewWebView'

Notice the b before the string. So, when you want to run string operations, which are now encoded as UTF-8, it throws a TypeError because ASCII is (for whatever reason) a byte-like object, not a string.

To fix this you can have .get_names() return strings, or add the b prefix to the strings in replace() method in objc_util.

omz

Thanks, will be fixed in the next build (get_names will return unicode strings instead of bytes).

Btw, you can just pass a prefix to ObjCClass.get_names() instead of doing the filtering yourself (in the current beta, it would have to be a byte string though).

blmacbeth

@omz said:

Btw, you can just pass a prefix to ObjCClass.get_names() instead of doing the filtering yourself (in the current beta, it would have to be a byte string though).

Did not know that…

ccc
# In Pythonista version 3.0 (300005) on iOS 9.2.1...
from objc_util import ObjCClass
print('\n'.join(ObjCClass.get_names('OM')))