osc打包出现错误 'NoneType' object has no attribute 'startswith'

#1

在虚拟机里面的 tumbleweed 上打包一个软件 经常出现这个错误 不知道怎么回事儿
网上查了一下说是个 bug 去年就一直有了 有人碰到过类似的吗?

suse:~/home:liangzi/onedrive # osc build onedrive-obs.spec
WARNING: package is not existing on server yet
WARNING: source service from package or project will not be executed. This may not be the same build as on server!
Building onedrive-obs.spec for openSUSE_Tumbleweed/x86_64
Getting buildinfo from server and store to /root/home:liangzi/onedrive/.osc/_buildinfo-openSUSE_Tumbleweed-x86_64.xml
Getting buildconfig from server and store to /root/home:liangzi/onedrive/.osc/_buildconfig-openSUSE_Tumbleweed-x86_64
Updating cache of required packages
95.4% cache miss. 10/219 dependencies cached.

1/209 (openSUSE:Factory) bash-5.0-2.1.x86_64.rpm
2/209 (openSUSE:Factory) glibc-2.29-1.3.x86_64.rpm
3/209 (openSUSE:Factory) libgcc_s1-8.2.1+r268506-1.1.x86_64.rpm
Traceback (most recent call last):
  File "/usr/bin/osc", line 41, in <module>
    r = babysitter.run(osccli)
  File "/usr/lib/python2.7/site-packages/osc/babysitter.py", line 60, in run
    return prg.main(argv)
  File "/usr/lib/python2.7/site-packages/osc/cmdln.py", line 344, in main
    return self.cmd(args)
  File "/usr/lib/python2.7/site-packages/osc/cmdln.py", line 367, in cmd
    retval = self.onecmd(argv)
  File "/usr/lib/python2.7/site-packages/osc/cmdln.py", line 501, in onecmd
    return self._dispatch_cmd(handler, argv)
  File "/usr/lib/python2.7/site-packages/osc/cmdln.py", line 1232, in _dispatch_cmd
    return handler(argv[0], opts, *args)
  File "/usr/lib/python2.7/site-packages/osc/commandline.py", line 6341, in do_build
    return osc.build.main(self.get_api_url(), opts, args)
  File "/usr/lib/python2.7/site-packages/osc/build.py", line 911, in main
    fetcher.run(bi)
  File "/usr/lib/python2.7/site-packages/osc/fetch.py", line 244, in run
    self.fetch(i, prefix=prefix)
  File "/usr/lib/python2.7/site-packages/osc/fetch.py", line 146, in fetch
    self.move_package(tmpfile.name, pac.localdir, pac)
  File "/usr/lib/python2.7/site-packages/osc/fetch.py", line 178, in move_package
    fullfilename = os.path.join(destdir, canonname)
  File "/usr/lib64/python2.7/posixpath.py", line 68, in join
    if b.startswith('/'):
AttributeError: 'NoneType' object has no attribute 'startswith'

openSUSE-Gossip-20190101-20190407
#2

我昨天遇到了,错误在这里:

File "/usr/lib/python2.7/site-packages/osc/fetch.py", line 178, in move_package
  fullfilename = os.path.join(destdir, canonname)

这里调用 python 2.7 原生的 posixpath.py 出错了。

按照 python 官方文档的说法,path.join(a, *b),如果 b 为空,效果是把 a 的后面加上 “/”。但官方实际的代码不是这样的,第一个判断就是 b.startswith,这就默认了 b 是 string 了,然后 None 的判断是在 else 里。实际上第一个就应该判断 b == None,就不会有这个错误了。

所以现在我不确定是应该给上游 python 报 bug,还是在 osc 这边加检查让 canonname 不为 None。看起来更像是 python 2.7 的 bug,但是感觉一门语言的开发者不至于连这个都写不好吧…

#3

看起来就是python的bug然而我是无力报了:joy:.....
这个错误我都碰到好几次了 实在是无语了 而且一看到python就头大

#4

好像是我看太快了,理解有误:

# Join pathnames.
# Ignore the previous parts if a part is absolute.
# Insert a '/' unless the first part is empty or already ends in '/'.
def join(a, *p):
  """Join two or more pathname components, inserting '/' as needed.
  If any component is an absolute path, all previous path components
  will be discarded."""
  path = a
  for b in p:
    if b.startswith('/'):
      path = b
    elif path == '' or path.endswith('/'):
      path +=  b
    else:
      path += '/' + b
  return path

这个函数的意思是说,如果 b 是绝对路径(以“/”开始),就返回 b。如果 b 是空字符串或者 b 以 “/” 结尾,就返回 a + b。否则返回 a + b 中间加个 “/”。

也就是说它不处理 NoneType 的情况。

我现在有一个 package 是 100% 可以复现的:X11:Cinnamon:Factory cjs。我准备在 osc 端修一下。

#5

原因是 download.opensuse.org 似乎针对 openSUSE_Factory 给了个 redirect,但是 osc 似乎解析不了,于是就把 Mirror 的 metalink 文件当成 rpm 下载回来了。这个 metalink 除了不是 rpm 别的什么属性都有。但是 move_package 那里最后的退而求其次方案是使用 binary 的名字,这家伙不是 binary,于是返回 None。到了 python 2.7 官方的 join path 那里就过不去了。

暂时性的解决办法是加上 --download-api-only。直接从 OBS 取包。

我提交了一个 pull request 只是把错误美化了一下,加上 workaround 提示。

真正的修复要么应该在服务器上,要么 osc 这边重写逻辑,遇到 metalink 也要处理而不是简单的扔掉。

Has Likes
#6

我觉得OSC作为一个打包工具 这个识别能力应该是要有的 虽然锅可以甩给蟒蛇:rofl: