curved-vase-73456
03/31/2019, 1:03 AM1.13.0
to 1.14.0
and one of our supported plugins (forked from fsqio
) failed with
<class 'fsqio.pants.spindle.tasks.build_spindle.BuildSpindle_build_spindle'> must set an options_scope class-level property
More details
Bug happens between transition from 1.14.0dev1
to 1.14.0dev2
Seems like we’re missing setting related to optionable.py
(https://github.com/pantsbuild/pants/blob/d9eb4403d551df3c3fe107cbdc272f169ec7599e/src/python/pants/option/optionable.py#L140):
cls = type(self)
if not isinstance(cls.options_scope, str):
raise NotImplementedError('{} must set an options_scope class-level property.'.format(cls))
- adding options_scope
val to class didn’t help
- adding custom init
to class that prints related to the issue lines and calls super outputs this:
type(self): <class 'fsqio.pants.spindle.tasks.build_spindle.BuildSpindle_build_spindle'>
type(self).options_scope: build-spindle
isinstance(type(self).options_scope, str): True
last parts of the stack trace
File "/Users/michael/.cache/pants/setup/bootstrap-Darwin-x86_64/1.14.0/lib/python2.7/site-packages/pants/engine/round_engine.py", line 42, in attempt
task = task_type(self._context, task_workdir)
File "/Users/michael/sigma_project/sigma-monorepo/src/python/fsqio/pants/spindle/tasks/build_spindle.py", line 58, in __init__
super(BuildSpindle, self).__init__(*args, **kwargs)
File "/Users/michael/.cache/pants/setup/bootstrap-Darwin-x86_64/1.14.0/lib/python2.7/site-packages/pants/backend/jvm/tasks/nailgun_task.py", line 71, in __init__
super(NailgunTaskBase, self).__init__(*args, **kwargs)
File "/Users/michael/.cache/pants/setup/bootstrap-Darwin-x86_64/1.14.0/lib/python2.7/site-packages/pants/task/task.py", line 690, in __init__
super(Task, self).__init__(context, workdir)
File "/Users/michael/.cache/pants/setup/bootstrap-Darwin-x86_64/1.14.0/lib/python2.7/site-packages/pants/task/task.py", line 173, in __init__
super(TaskBase, self).__init__()
File "/Users/michael/.cache/pants/setup/bootstrap-Darwin-x86_64/1.14.0/lib/python2.7/site-packages/pants/option/optionable.py", line 151, in __init__
raise NotImplementedError('{} must set an options_scope class-level property.'.format(cls))
Exception message: <class 'fsqio.pants.spindle.tasks.build_spindle.BuildSpindle_build_spindle'> must set an options_scope class-level property.
^ without custom init super(BuildSpindle, self).__init__(*args, **kwargs)
is just skipped from the output but overall trace stays the same
As codebase is forked and works fine for out purposes we usually try to avoid changes unless it breaks so it might be that underlying issue was there before and just was brought to surface with recent update, still if there any ideas what might affect it’d be great to know, version of the referred file that we forked from (and haven’t changed much since except for small tweaks):
https://github.com/foursquare/fsqio/blob/master/src/python/fsqio/pants/spindle/tasks/build_spindle.py
🙏🏼 for your help and guidancehundreds-father-404
03/31/2019, 1:09 AMcurved-vase-73456
03/31/2019, 1:11 AMtype(self): <class 'fsqio.pants.spindle.tasks.build_spindle.BuildSpindle_build_spindle'>
type(self).options_scope: build-spindle
isinstance(type(self).options_scope, str): True
so options_scope
is not only defined but proved to be set therecurved-vase-73456
03/31/2019, 1:18 AMhundreds-father-404
03/31/2019, 1:19 AMcurved-vase-73456
03/31/2019, 1:19 AMhundreds-father-404
03/31/2019, 1:22 AMoptions_scope
to SpindleTask
?
Also, what does your custom __init__
look like for BuildSpindle
?curved-vase-73456
03/31/2019, 1:22 AMdef __init__(self, *args, **kwargs):
print("type(self): {}".format(type(self)))
print("type(self).options_scope: {}".format(type(self).options_scope))
print("isinstance(type(self).options_scope, str): {}".format(isinstance(type(self).options_scope, str)))
super(BuildSpindle, self).__init__(*args, **kwargs)
curved-vase-73456
03/31/2019, 1:23 AMoptions_scope
there as well JICcurved-vase-73456
03/31/2019, 1:25 AMSpindleTask
as it’s getting properly overriden by BuildSpindle
hundreds-father-404
03/31/2019, 1:30 AMfuture
library installed? When running with Python 2, that library override’s the builtin str
to be the same as Python 3's unicode str.
I’ll run a quick test to see if this indeed is the issuecurved-vase-73456
03/31/2019, 1:32 AMunicode_literals
hundreds-father-404
03/31/2019, 1:34 AMisinstance(b"test", str)
isinstance(u"test", str)
curved-vase-73456
03/31/2019, 1:36 AMTrue
False
hundreds-father-404
03/31/2019, 1:39 AMisinstance(options_scope, str)
that means you’re asserting it’s really bytes.
With our use of the future library, our check is asserting it’s really unicode. It’s confusing because Pants / the future library overwrites what the builtin str
means.
So, this means the property is being stored as bytes, which makes sense because this is how Python 2 stores properties. It’s an issue with our code that I will hotfix before we release 1.15.0. I’m trying to think of a workaround for you in the meantime..curved-vase-73456
03/31/2019, 1:40 AMoptions_scope
in some manner maybe?hundreds-father-404
03/31/2019, 1:42 AMoptions_scope
is being stored as unicode like it should, but the key in the dictionary, i.e. options_scope
, is being stored as bytes because Python 2 works that way.
We need some way to get Python to store the key as unicode.. trying to think if there’s a way to monkey patch thathundreds-father-404
03/31/2019, 1:46 AMcurved-vase-73456
03/31/2019, 1:47 AMcurved-vase-73456
03/31/2019, 1:47 AMcurved-vase-73456
03/31/2019, 1:49 AMhundreds-father-404
03/31/2019, 1:50 AMfuture==0.17.1
, but I’m not sure it will fix things.
I’m still trying to figure out how this change didn’t break Pants code - we run our integration tests with Python 2 every night, so those should have failed 🤔
--
Yes. And Pants 1.15.0 will be Python 2.7 or 3.6, Pants 1.16.0 will be 2.7, 3.6, or 3.7, and 1.17.0 will be 3.6 or 3.7.curved-vase-73456
03/31/2019, 1:57 AMfrom builtins import str, super
I got to
False
True
and init now outputs:
isinstance(type(self).options_scope, str): False
curved-vase-73456
03/31/2019, 1:58 AMhundreds-father-404
03/31/2019, 1:58 AMcurved-vase-73456
03/31/2019, 1:59 AMhundreds-father-404
03/31/2019, 1:59 AMhundreds-father-404
03/31/2019, 2:06 AMhundreds-father-404
03/31/2019, 2:15 AMprint(type(self).options_scope)
curved-vase-73456
03/31/2019, 2:17 AMcurved-vase-73456
03/31/2019, 2:22 AMhundreds-father-404
03/31/2019, 2:26 AMprint(type(self).options_scope)
, try repr(type(self).options_scope)
. print()
strips the u''
prefix
And then change to options_scope = u"build-spindle"
as a sanity checkhundreds-father-404
03/31/2019, 2:30 AMpex --python=python2.7 future==0.17.1
Python 2.7.15 (default, Jan 14 2019, 13:17:44)
[GCC 4.2.1 Compatible Apple LLVM 10.0.0 (clang-1000.10.44.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from builtins import str
>>> class Test(object):
... options_scope = u"test"
...
>>> isinstance(Test.options_scope, str)
True
>>> isinstance(type(Test()).options_scope, str)
True
curved-vase-73456
03/31/2019, 2:37 AMFalse
there, even though u'type(self).options_scope: build-spindle'
hundreds-father-404
03/31/2019, 2:39 AMtype(self).options_scope:
in the repr()
call, because the call to .format()
will remove the u''
prefixcurved-vase-73456
03/31/2019, 2:40 AM'build-spindle'
hundreds-father-404
03/31/2019, 2:42 AMoptions_scope
is being stored as bytes. Weird
Realized thanks to John’s comment on that PR that what I was saying earlier about the property name is irrelevant. The issue is the property’s value, not the name of the propertyhundreds-father-404
03/31/2019, 2:43 AMoptions_scope = b"test".decode('utf-8')
curved-vase-73456
03/31/2019, 2:44 AMcurved-vase-73456
03/31/2019, 2:54 AMoptions_scope
, it’s build-spindle
no matter what I docurved-vase-73456
03/31/2019, 3:24 AMoptions_scope
value comes somehow from task name in register.py
task(name='build-spindle', action=BuildSpindle).install()
curved-vase-73456
03/31/2019, 3:49 AMu
fixed it, i.e changing to task(name=u'build-spindle', action=BuildSpindle).install()
curved-vase-73456
03/31/2019, 3:49 AMhundreds-father-404
03/31/2019, 4:03 AMcurved-vase-73456
03/31/2019, 4:06 AMregister.py
didn’t 😞 wrong imports omg, ty for going though this with me