2014-04-19 27 views
5

Stworzyłem pakiet w Py2.7 i staram się, aby był zgodny z Py3. Problem polega na tym, że jeśli to unicode_literals wpaczki setup.py i unicode_literals

__init__.py 

importuje powraca budować ten błąd

error in daysgrounded setup command: package_data must be a dictionary mapping 
package names to lists of wildcard patterns 

Czytałem PEP, ale nie mogę zrozumieć, co to ma do czynienia z dyktować jak

__pkgdata__ 

może ktoś pomóc?

__init__.py 
#!/usr/bin/env python 
# -*- coding: latin-1 -*- 

"""Manage child(s) grounded days.""" 

from __future__ import (absolute_import, division, print_function, 
         unicode_literals) 
# ToDo: correct why the above unicode_literals import prevents setup.py from working 

import sys 
from os import path 
sys.path.insert(1, path.dirname(__file__)) 

__all__ = ['__title__', '__version__', 
      '__desc__', '__license__', '__url__', 
      '__author__', '__email__', 
      '__copyright__', 
      '__keywords__', '__classifiers__', 
      #'__packages__', 
      '__entrypoints__', '__pkgdata__'] 

__title__ = 'daysgrounded' 
__version__ = '0.0.9' 

__desc__ = __doc__.strip() 
__license__ = 'GNU General Public License v2 or later (GPLv2+)' 
__url__ = 'https://github.com/jcrmatos/DaysGrounded' 

__author__ = 'Joao Matos' 
__email__ = '[email protected]' 

__copyright__ = 'Copyright 2014 Joao Matos' 

__keywords__ = 'days grounded' 
__classifiers__ = [# Use below to prevent any unwanted publishing 
        #'Private :: Do Not Upload' 
        'Development Status :: 4 - Beta', 
        'Environment :: Console', 
        'Environment :: Win32 (MS Windows)', 
        'Intended Audience :: End Users/Desktop', 
        'Intended Audience :: Developers', 
        'Natural Language :: English', 
        'Natural Language :: Portuguese', 
        'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', 
        'Operating System :: OS Independent', 
        'Programming Language :: Python', 
        'Programming Language :: Python :: 2.7', 
        'Programming Language :: Python :: 3.4', 
        'Topic :: Other/Nonlisted Topic'] 

#__packages__ = ['daysgrounded'] 

__entrypoints__ = { 
    'console_scripts': ['daysgrounded = daysgrounded.__main__:main'], 
    #'gui_scripts': ['app_gui = daysgrounded.daysgrounded:start'] 
    } 

__pkgdata__ = {'daysgrounded': ['*.txt']} 
#__pkgdata__= {'': ['*.txt'], 'daysgrounded': ['*.txt']} 


setup.py 
#!/usr/bin/env python 
# -*- coding: latin-1 -*- 

from __future__ import (absolute_import, division, print_function, 
         unicode_literals) 

from setuptools import setup, find_packages 
#import py2exe 

#from daysgrounded import * 
from daysgrounded import (__title__, __version__, 
          __desc__, __license__, __url__, 
          __author__, __email__, 
          __keywords__, __classifiers__, 
          #__packages__, 
          __entrypoints__, __pkgdata__) 

setup(
    name=__title__, 
    version=__version__, 

    description=__desc__, 
    long_description=open('README.txt').read(), 
    #long_description=(read('README.txt') + '\n\n' + 
    #     read('CHANGES.txt') + '\n\n' + 
    #     read('AUTHORS.txt')), 
    license=__license__, 
    url=__url__, 

    author=__author__, 
    author_email=__email__, 

    keywords=__keywords__, 
    classifiers=__classifiers__, 

    packages=find_packages(exclude=['tests*']), 
    #packages=__packages__, 

    entry_points=__entrypoints__, 
    install_requires=open('requirements.txt').read(), 
    #install_requires=open('requirements.txt').read().splitlines(), 

    include_package_data=True, 
    package_data=__pkgdata__, 

    #console=['daysgrounded\\__main__.py'] 
) 

Dzięki

JM

Odpowiedz

5

użyciu unicode_literals jest taka sama jak przy użyciu u'...' dla każdej struny dosłownym w pliku wejściowego, co oznacza, że ​​w __init__.py określając

__pkgdata__ = {'daysgrounded': ['*.txt']} 

jest faktycznie taki sam jak

__pkgdata__ = {u'daysgrounded': [u'*.txt']} 

dla python2, setuptools nie spodziewa siętutaj, ale str, więc nie powiedzie się.

Jak się wydaje, nie używasz żadnych znaków Unicode w literałach ciągów znaków w __init__.py tak, po prostu ascii, więc możesz po prostu usunąć import unicode_literals. Jeśli naprawdę używasz literałów w standardzie Unicode w jakimś miejscu pliku, który nie jest widoczny w twoim wpisie, użyj tam jawnie literałów Unicode.

3

To jest błąd w setuptools. Sprawdza poprawność wartości za pomocą isinstance(k, str), która nie powiedzie się, gdy łańcuchy zostaną przekształcone w klasę 2.x unicode według importu unicode_literals. Powinien być poprawiony, aby użyć isinstance(k, basestring).

Najprostszym rozwiązaniem jest ustawienie ustawień bezpośrednio w setup.py zamiast zapisywania ich w __init__.py. Jeśli potrzebujesz programowego dostępu do __version__, umieść go w osobnym pakiecie, który jest dołączany zarówno przez setup.py, jak i __init__.py.

Od setuptools dist.py:

def check_package_data(dist, attr, value): 
    """Verify that value is a dictionary of package names to glob lists""" 
    if isinstance(value,dict): 
     for k,v in value.items(): 
      if not isinstance(k,str): break 
      try: iter(v) 
      except TypeError: 
       break 
     else: 
     return 
    raise DistutilsSetupError(
     attr+" must be a dictionary mapping package names to lists of " 
     "wildcard patterns" 
    ) 
+0

"jest to błąd w setuptools": Czy wiesz, czy istnieje zgłoszenie błędu? –

0

Wykorzystanie unicode_literals jest doprowadzenie do zgodności Python 2 Python 3 Kod gdzie str jest teraz Unicode ciągi vs ciągów bajtów w Pythonie 2. Jest świetny w zapobiega mieszaniu ciągów bajtowych i ciągów unicode, długotrwały problem na Py2, jednak istnieje kilka takich problemów, jak ten problem.

Kevin wyjaśnił błąd a ja powiedziałbym dla setup.py nie jest bezwzględnie wymagane, aby naprawić to jest trochę brzydki zwłaszcza jeśli masz dużą liczbę wpisów na package_data.


Jeśli chcesz zachować unicode_literals w konfiguracji.py trzeba tylko zakodować kluczyk dict jako bajt-string:

__pkgdata__ = {b'daysgrounded': ['*.txt']} 

Jednak pod Python 3 nie będą mogły z tej samej wiadomości, więc muszą obejmować zarówno wersje:

if sys.version_info.major == 2: 
    __pkgdata__ = {b'daysgrounded': ['*.txt']} 
else: 
    __pkgdata__ = {'daysgrounded': ['*.txt']} 

Alternatywnie można użyć bytes_to_native_str z future modułu:

from future.utils import bytes_to_native_str 

__pkgdata__ = {bytes_to_native_str(b'daysgrounded'): ['*.txt']}