Paketimde setup.py (setuptools) içinde tanımlanan sürümü nasıl edinebilirim?


Yanıtlar:


246

Önceden yüklenmiş dağıtımın sürüm dizesini sorgula

Süreyi çalışma zamanında paketinizin içinden almak için (sorunuzun gerçekten sorduğu soru), şunları kullanabilirsiniz:

import pkg_resources  # part of setuptools
version = pkg_resources.require("MyProject")[0].version

Yükleme sırasında kullanım için sürüm dizesini saklama

Diğer yöne gitmek istiyorsanız (bu, diğer yanıt yazarlarının sorduğunuzu düşündüğü gibi görünüyor), sürüm dizesini ayrı bir dosyaya yerleştirin ve o dosyanın içeriğini okuyun setup.py.

Bir ile paketinde bir version.py yapabiliriz __version__ardından, hat kullanan setup.py dosyası onu okumak execfile('mypackage/version.py')o ayarlar böylece, __version__setup.py ad.

Tüm Python sürümleriyle ve hatta sürüm dizesine erişmesi gerekebilecek Python olmayan dillerle çalışacak daha basit bir yol istiyorsanız:

Sürüm dizesini, örneğin adlı bir düz metin dosyasının tek içeriği olarak saklayın VERSIONve sırasında bu dosyayı okuyun setup.py.

version_file = open(os.path.join(mypackage_root_dir, 'VERSION'))
version = version_file.read().strip()

Aynı VERSIONdosya Python olmayanlar da dahil olmak üzere başka herhangi bir programda da aynı şekilde çalışır ve sürüm dizesini tüm programlar için tek bir yerde değiştirmeniz yeterlidir.

Kurulum sırasında yarış durumu hakkında uyarı

Bu arada, paketinizi burada başka bir cevapta önerildiği gibi setup.py'den içe aktarmayın: sizin için çalışıyor gibi görünecektir (çünkü paketinizin bağımlılıkları zaten yüklüdür), ancak paketinizin yeni kullanıcılarını tahrip edecektir. , çünkü önce bağımlılıkları manuel olarak yüklemeden paketinizi kuramazlar.


1
Buradaki en iyi yanıt budur: en iyi yol, paketi paketinizden almak için setup.py dosyasına ihtiyacınız varsa execfile kullanmaktır.
trinth

2
execfilegerçekten iyi çalışıyor ... ama (ne yazık ki) Python 3 ile çalışmıyor.
medmunds

9
... Tamam, Python 2 ve 3 için with open('mypackage/version.py') as f: exec(f.read())yerine kullanın execfile('mypackage/version.py'). ( Stackoverflow.com/a/437857/647002
adresinden

5
Wreak tahribat kısmı mutlaka doğru değildir ... sadece paketteki init .py dosyanızda kod ithalatı bağımlılıkları varsa (doğrudan veya dolaylı) tahribat yaratacaktır .
Pykler

2
Django'nun setup.py dosyalarında __import__ araması yaptığını belirtmek gerekir . '__İmport__' ve 'içe aktarma' bunu güvenli hale getiriyor mu? Onlara herhangi bir soruna yol açıyor gibi görünmüyor.
user1978019

33

örnek çalışma: mymodule

Bu yapılandırmayı düşünün:

setup.py
mymodule/
        / __init__.py
        / version.py
        / myclasses.py

Sonra bağımlılıkların olduğu ve setup.pyaşağıdaki gibi göründüğünüz bazı normal senaryoları düşünün :

setup(...
    install_requires=['dep1','dep2', ...]
    ...)

Ve bir örnek __init__.py:

from mymodule.myclasses import *
from mymodule.version import __version__

Örneğin myclasses.py:

# these are not installed on your system.
# importing mymodule.myclasses would give ImportError
import dep1
import dep2

Sorun # 1: mymoduleKurulum sırasında içe aktarma

Eğer setup.pyithalatınız mymoduleo zaman kurulum sırasında büyük olasılıkla bir alırsınız ImportError. Paketinizin bağımlılıkları olduğunda bu çok yaygın bir hatadır. Paketinizde yerleşiklerden başka bağımlılıklar yoksa güvenli olabilirsiniz; ancak bu iyi bir uygulama değildir. Bunun nedeni geleceğe dönük olmamasıdır; yarın kodunuzun başka bir bağımlılık tüketmesi gerektiğini söyleyin.

problem # 2: benim nerede __version__?

Eğer hardcode __version__içinde setup.pyo zaman size modülünde gemi olacağını sürümünü aynı olmayabilir. Tutarlı olmak için, onu tek bir yere koyacak ve ihtiyacınız olduğunda aynı yerden okuyacaksınız. Kullanmanız import1 numaralı sorunu çözebilir.

çözüm: à la setuptools

Sen bir arada kullanmak istiyorsunuz open, execve bir dicti sağlamak execeklenti değişkenlere:

# setup.py
from setuptools import setup, find_packages
from distutils.util import convert_path

main_ns = {}
ver_path = convert_path('mymodule/version.py')
with open(ver_path) as ver_file:
    exec(ver_file.read(), main_ns)

setup(...,
    version=main_ns['__version__'],
    ...)

Ve mymodule/version.pysürümü ortaya çıkarmak:

__version__ = 'some.semantic.version'

Bu şekilde, sürüm modülle birlikte gönderilir ve kurulum sırasında eksik bağımlılıkları olan (henüz yüklenmemiş) bir modülü almaya çalışırken sorun yaşarsınız.


2
Bu en makul çözüm gibi görünüyor çünkü sadece izin verilen bağımlılıklara dayanıyor.
Dogweather

Paket sürümü kavramı itibaren setup.py dosyası farklı tanımlanır sürümü ?
değişken

16

En iyi teknik, __version__ürün kodunuzda tanımlamak ve daha sonra oradan setup.py dosyasına aktarmaktır. Bu, çalışan modülünüzde okuyabileceğiniz bir değer verir ve bunu tanımlamak için yalnızca bir yer vardır.

Setup.py içindeki değerler kurulmaz ve setup.py kurulumdan sonra takılmaz.

Scope.py içinde ne yaptım (örneğin):

# coverage/__init__.py
__version__ = "3.2"


# setup.py
from coverage import __version__

setup(
    name = 'coverage',
    version = __version__,
    ...
    )

GÜNCELLEME (2017): scope.py artık sürümü almak için kendini içe aktarmıyor. Kendi kodunuzu içe aktarmak, kodun kaldırılmasını sağlayabilir, çünkü ürün kodunuz henüz yüklenmemiş olan bağımlılıkları içe aktarmaya çalışır, çünkü setup.py bunları yükleyen şeydir.


4
@Evan: "Yalnızca bu değeri kaynaktan alın" konusunda ne elde ettiğinden emin değilim. İçindeki dosya bir şekilde bozulursa, __version__içe aktarmanız da bozulur. Python sadece istediğiniz ifadeleri nasıl yorumlayacağını bilmiyor. @pjeby doğru: modülünüzün diğer modülleri içe aktarması gerekiyorsa, bunlar henüz yüklenmemiş olabilir ve kaotik olacaktır. Bu teknik, içe aktarma işleminin uzun bir başka ithalat zincirine neden olmadığına dikkat ederseniz işe yarar.
Ned Batchelder

1
@Ned Batchelder Sürümü kaynak dosyada herhangi bir içe aktarmadan önce koyarsanız ve yalnızca bir 'modül içe aktarma sürümüne' koyarsanız, kaynak dosyadan gerekenden daha fazla söz konusu olmayacaktır. Ayrıca, bozuk kodu kim yayınlayacak? Paket bağımlılık gerektiriyorsa, setuptools kullanın veya yıl içinde daha sonra distutils2'nin serbest bırakılmasını bekleyin.
Evan Plaice

15
@Evan, üzgünüm, ancak kısmi dosyaları içe aktarma konusunda yanılıyorsunuz. Uzun bir modülün sonuna bir print ifadesi koymayı deneyin ve dosyada tanımlanan ilk değişkeni içe aktarın. Print deyimi yürütülür.
Ned Batchelder

23
Bunun için düştüm, ama @pjeby tamamen doğru: "Bu arada, paketinizi burada başka bir cevapta önerildiği gibi setup.py'den içe aktarmayın: sizin için çalışıyor gibi görünecektir (çünkü paketinizin bağımlılıkları zaten yüklüdür ), ancak önce bağımlılıkları manuel olarak yüklemeden paketinizi yükleyemeyeceklerinden, paketinizin yeni kullanıcılarına zarar verecektir. " Ned, cevabına uyarı eklemeyi düşünür müsün?
Dr.Jan-Philip Gehrcke

1
Jan-PhilipGehrcke @ ben PyPI için böyle bir setup.py dosyayı yükleyip zaman ki gibi o pip install <packagename>, aşağıdaki hatayı alıyorum: ImportError: No module named <packagename>. Lütfen okuyucunuzu, paketin henüz kurulu olmadığı ortamlarda setup.py dosyalarını çalıştıramayacağınıza UYARI!
ocak

14

Sorunuz biraz belirsiz, ama bence sorduğunuz şey onu nasıl belirleyeceğiniz.

Şöyle tanımlamanız gerekir __version__:

__version__ = '1.4.4'

Ardından setup.py'nin az önce belirttiğiniz sürümü bildiğini onaylayabilirsiniz:

% ./setup.py --version
1.4.4

9

Bu cevaplardan memnun değildim ... kurulum araçları gerektirmedi, tek bir değişken için ayrı bir modül yapmak istemedim, bu yüzden bunları buldum.

Ana modülün pep8 tarzında olduğundan ve bu şekilde kalacağından emin olduğunuzda:

version = '0.30.unknown'
with file('mypkg/mymod.py') as f:
    for line in f:
        if line.startswith('__version__'):
            _, _, version = line.replace("'", '').split()
            break

Daha dikkatli olmak ve gerçek bir ayrıştırıcı kullanmak istiyorsanız:

import ast
version = '0.30.unknown2'
with file('mypkg/mymod.py') as f:
    for line in f:
        if line.startswith('__version__'):
            version = ast.parse(line).body[0].value.s
            break

setup.py bir ıskarta modülüdür, bu yüzden biraz çirkinse sorun olmaz.


Güncelleme: yeterince komik Son yıllarda bundan uzaklaştım ve pakette ayrı bir dosya kullanmaya başladım meta.py. Sık sık değiştirmek isteyebileceğim birçok meta veri koydum. Yani, sadece bir değer için değil.


+1. Nispeten basittir, sürüm numarasını tek bir yerde tutar, içermek için ayrı bir dosya gerektirmez ve python modülünün setup.py'ye içe aktarma bağımlılıklarını dayatmaz. Hatta setup.py kadar kısa süreli bir programda içerik yöneticisi ile uğraşmazdım.
ɈsәɹoɈ

Normal ifade kullanmaktan çok daha güzel, teşekkürler. Ayrıca kullanabilirsiniz ast.get_docstring()bazılarıyla .split('\n')[0].strip()otomatik doldurmak için vb descriptionkaynaktan. Senkronize tutmak için bir şey daha az
kaybetti

4

Kaynak ağacınızda, örneğin basedir / paketiniz / _version.py gibi bir dosya oluşturun. Bu dosyanın şu şekilde yalnızca tek bir kod satırı içermesine izin verin:

__version__ = "1.1.0-r4704"

Ardından setup.py dosyasında bu dosyayı açın ve sürüm numarasını şu şekilde ayrıştırın:

verstr = "bilinmiyor"
Deneyin:
    verstrline = open ('paketiniz / _version.py', "rt"). read ()
EnvironmentError hariç:
    pass # Tamam, sürüm dosyası yok.
Başka:
    VSRE = r "^ __ version__ = ['\"] ([^' \ "] *) ['\"] "
    mo = yeniden arama (VSRE, verstrline, re.M)
    eğer mo:
        verstr = mo.grup (1)
    Başka:
        Yükseltmek RuntimeError ("paketinizdeki sürümü bulamıyorum / _version.py")

Son olarak, yourbasedir/yourpackage/__init__.pyimport_version'da şöyle:

__version__ = "bilinmiyor"
Deneyin:
    from _version import Instagram Hesabındaki Resim ve Videoları __version__
ImportError hariç:
    # _Version.py olmayan bir ağaçta koşuyoruz, bu yüzden sürümümüzün ne olduğunu bilmiyoruz.
    geçmek

Bunu yapan bir kod örneği ben korumak "pyutil" paketidir. (Bkz. PyPI veya google arama - stackoverflow bu yanıta bir köprü eklememe izin vermiyor.)

@pjeby, paketinizi kendi setup.py dosyasından içe aktarmamanız gerektiği konusunda haklıdır. Bu, yeni bir Python yorumlayıcısı oluşturarak ve ilk şeyde setup.py uygulayarak test ettiğinizde işe yarayacaktır: python setup.pyancak işe yaramayacağı durumlar vardır. Bunun nedeni import youpackage, "paketiniz" adlı bir dizinin geçerli çalışma dizinini okumak anlamına gelmez, geçerli olana "paketiniz" sys.modulesanahtarını aramak ve sonra yoksa çeşitli şeyler yapmak anlamına gelir . Bu yüzden her zaman yaptığınızda işe python setup.pyyarar çünkü taze, boş bir şeyiniz vardır sys.modules, ancak bu genel olarak çalışmaz.

Örneğin, py2exe, bir uygulamayı paketleme sürecinin bir parçası olarak setup.py dosyanızı çalıştırıyorsa ne olur? Paketin sürüm numarasını aldığı için py2exe'nin bir pakete yanlış sürüm numarasını koyacağı bir durum gördümimport myownthingancak bu paketin farklı bir sürümü daha önce py2exe çalıştırması sırasında içe aktarılmıştı. Benzer şekilde, setuptools, easy_install, dağıtma veya distutils2, paketinizi kendinize bağlı farklı bir paket kurma işleminin bir parçası olarak oluşturmaya çalışıyorsa ne olacak? Ardından, paketinizin setup.py değerlendirilirken içe aktarılıp aktarılmadığı veya paketinizin bu Python yorumlayıcısının ömrü boyunca içe aktarılmış bir sürümü olup olmadığı veya paketinizi içe aktarmanın önce başka paketlerin yüklenmesini gerektirip gerektirmediği , veya yan etkileri varsa, sonuçları değiştirebilir. Py2exe ve setuptools gibi araçlar için sorunlara neden olan Python paketlerini yeniden kullanmaya çalışırken çeşitli kurulumlar yaşadım çünkü onların setup.py sürüm numarasını bulmak için paketin kendisini içe aktarıyor.

Bu arada, bu teknik yourpackage/_version.py, örneğin revizyon kontrol geçmişinizi okuyarak ve revizyon kontrol geçmişindeki en son etikete dayanan bir sürüm numarası yazarak dosyayı sizin için otomatik olarak oluşturmak için araçlarla güzelce oynar . İşte bunu darcs için yapan bir araç: http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.rst ve git için aynı şeyi yapan bir kod snippet'i: http: // github .com / warner / python-ECDSA / damla / 0ed702a9d4057ecf33eea969b8cf280eaccd89a1 / setup.py # L34


3

Bu, düzenli ifadeler kullanarak ve meta veri alanlarına bağlı olarak aşağıdaki gibi bir biçime sahip olmalıdır:

__fieldname__ = 'value'

Setup.py dosyanızın başlangıcında aşağıdakileri kullanın:

import re
main_py = open('yourmodule.py').read()
metadata = dict(re.findall("__([a-z]+)__ = '([^']+)'", main_py))

Bundan sonra, betiğinizdeki meta verileri şu şekilde kullanabilirsiniz:

print 'Author is:', metadata['author']
print 'Version is:', metadata['version']

Yukarıda söylediğim gibi, sadece str.split kullanın :)
Éric Araujo

Oh tanrım hayır. Python'u Python'da mı ayrıştırıyorsunuz? En azından eval (), child kullanın.
slacy

3
Zavallı tavsiye küfüründen, bu kadar kolay olduğunda değerlendirmeden kaçınılmalıdır.
Gringo Suave

3

Böyle bir yapı ile:

setup.py
mymodule/
        / __init__.py
        / version.py
        / myclasses.py

Burada version.py şunları içerir:

__version__ = 'version_string'

Bunu setup.py'de yapabilirsiniz :

import sys

sys.path[0:0] = ['mymodule']

from version import __version__

Bu, mymodule / __ init__.py bağımlılığınızla ilgili herhangi bir soruna neden olmaz.


2

Bir dosyayı içe aktarmaktan (ve dolayısıyla kodunu yürütmekten) kaçınmak için dosyayı ayrıştırabilir ve versionsözdizim ağacından özniteliği kurtarabilirsiniz :

# assuming 'path' holds the path to the file

import ast

with open(path, 'rU') as file:
    t = compile(file.read(), path, 'exec', ast.PyCF_ONLY_AST)
    for node in (n for n in t.body if isinstance(n, ast.Assign)):
        if len(node.targets) == 1:
            name = node.targets[0]
            if isinstance(name, ast.Name) and \
                    name.id in ('__version__', '__version_info__', 'VERSION'):
                v = node.value
                if isinstance(v, ast.Str):
                    version = v.s
                    break
                if isinstance(v, ast.Tuple):
                    r = []
                    for e in v.elts:
                        if isinstance(e, ast.Str):
                            r.append(e.s)
                        elif isinstance(e, ast.Num):
                            r.append(str(e.n))
                    version = '.'.join(r)
                    break

Bu kod , modül dönüşünün en üst düzeyindeki atamayı __version__veya VERSIONdize değerini bulmaya çalışır . Sağ taraf bir dize veya bir demet olabilir.


3
Bu akıllı ve karmaşık görünüyor :) Sadece bir ödev içeren bir _version.py dosyasına sahip olmak ve bunu open-read-str.split ile ayrıştırmak daha basit olurdu.
Éric Araujo

Bunu gönderdiğiniz için teşekkürler. Bu durum için çok karmaşık olduğunu düşünüyorum, ancak bir kişinin soruna nasıl yaklaşabileceğini anlamak için çok yararlı. Sürüm numarasını tek bir yerde tutar, içermek için ayrı bir dosya gerektirmez ve python modülünün içe aktarma bağımlılıklarını kurulum komut dosyasına dayatmaz.
ɈsәɹoɈ

2

Bir kediyi yüzmek için bin yol var - işte benim:

# Copied from (and hacked):
# https://github.com/pypa/virtualenv/blob/develop/setup.py#L42
def get_version(filename):
    import os
    import re

    here = os.path.dirname(os.path.abspath(__file__))
    f = open(os.path.join(here, filename))
    version_file = f.read()
    f.close()
    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
                              version_file, re.M)
    if version_match:
        return version_match.group(1)
    raise RuntimeError("Unable to find version string.")

2

@ Gringo-suave'den https://stackoverflow.com/a/12413800 temizlenmesi :

from itertools import ifilter
from os import path
from ast import parse

with open(path.join('package_name', '__init__.py')) as f:
    __version__ = parse(next(ifilter(lambda line: line.startswith('__version__'),
                                     f))).body[0].value.s

2

Şimdi bu iğrenç ve bazı rafineri gerekiyor (pkg_resources içinde cevapsız bir üye çağrısı bile olabilir özledim), ama ben sadece bunun neden işe ya da neden kimse bugüne kadar önerdi görmüyorum (Googling vardır bunu açmadı) ... bunun Python 2.x olduğunu ve pkg_resources (sigh) gerektirdiğini unutmayın:

import pkg_resources

version_string = None
try:
    if pkg_resources.working_set is not None:
        disto_obj = pkg_resources.working_set.by_key.get('<my pkg name>', None)
        # (I like adding ", None" to gets)
        if disto_obj is not None:
            version_string = disto_obj.version
except Exception:
    # Do something
    pass

2

Bizim paketi hakkında meta bilgileri koymak istedim pypackageryiçinde __init__.pyama PJ Eby zaten (onun cevabını ve yarış durumuyla ilgili uyarı bakınız) belirttiği gibi üçüncü taraf bağımlılıkları vardır değil çünkü yapamadım.

Yalnızca meta bilgileri pypackagery_meta.pyiçeren ayrı bir modül oluşturarak çözdük :

"""Define meta information about pypackagery package."""

__title__ = 'pypackagery'
__description__ = ('Package a subset of a monorepo and '
                   'determine the dependent packages.')
__url__ = 'https://github.com/Parquery/pypackagery'
__version__ = '1.0.0'
__author__ = 'Marko Ristin'
__author_email__ = 'marko.ristin@gmail.com'
__license__ = 'MIT'
__copyright__ = 'Copyright 2018 Parquery AG'

daha sonra meta bilgileri şuraya içe aktarın packagery/__init__.py:

# ...

from pypackagery_meta import __title__, __description__, __url__, \
    __version__, __author__, __author_email__, \
    __license__, __copyright__

# ...

ve nihayetinde kullandı setup.py:

import pypackagery_meta

setup(
    name=pypackagery_meta.__title__,
    version=pypackagery_meta.__version__,
    description=pypackagery_meta.__description__,
    long_description=long_description,
    url=pypackagery_meta.__url__,
    author=pypackagery_meta.__author__,
    author_email=pypackagery_meta.__author_email__,
    # ...
    py_modules=['packagery', 'pypackagery_meta'],
 )

Kurulum argümanıyla pypackagery_metapaketinize dahil etmeniz gerekir py_modules. Aksi takdirde, paketli dağıtım eksik olacağından kurulum sırasında içe aktaramazsınız.


1

Basit ve düz, source/package_name/version.pyaşağıdaki içeriklerle bir dosya oluşturun :

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
__version__ = "2.6.9"

Ardından, dosyanızda source/package_name/__init__.py, diğer kişilerin kullanması için sürümü içe aktarırsınız:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
from .version import __version__

Şimdi, bunu giyebilirsin setup.py

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys

try:
    filepath = 'source/package_name/version.py'
    version_file = open( filepath )
    __version__ ,= re.findall( '__version__ = "(.*)"', version_file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

finally:
    version_file.close()

Python ile bu test edilmiştir 2.7, 3.3, 3.4, 3.5, 3.6ve 3.7Linux, Windows ve Mac OS üzerinde. Tüm tez platformları için Entegrasyon ve Birim Testleri olan paketimde kullandım. Sonuçları buradan .travis.ymlve appveyor.ymlburadan görebilirsiniz:

  1. https://travis-ci.org/evandrocoan/debugtools/builds/527110800
  2. https://ci.appveyor.com/project/evandrocoan/pythondebugtools/builds/24245446

Alternatif bir sürümde bağlam yöneticisi kullanılıyor:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys

try:
    filepath = 'source/package_name/version.py'

    with open( filepath ) as file:
        __version__ ,= re.findall( '__version__ = "(.*)"', file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

Ayrıca kullanarak edilebilir codecsunicode hataları işlemek için modül Python hem 2.7ve3.6

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys
import codecs

try:
    filepath = 'source/package_name/version.py'

    with codecs.open( filepath, 'r', errors='ignore' ) as file:
        __version__ ,= re.findall( '__version__ = "(.*)"', file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

Python C Uzantıları kullanarak C / C ++ 'da% 100 Python modülü yazıyorsanız, aynı şeyi yapabilirsiniz, ancak Python yerine C / C ++ kullanın.

Bu durumda aşağıdakileri oluşturun setup.py:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys
import codecs
from setuptools import setup, Extension

try:
    filepath = 'source/version.h'

    with codecs.open( filepath, 'r', errors='ignore' ) as file:
        __version__ ,= re.findall( '__version__ = "(.*)"', file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

setup(
        name = 'package_name',
        version = __version__,

        package_data = {
                '': [ '**.txt', '**.md', '**.py', '**.h', '**.hpp', '**.c', '**.cpp' ],
            },

        ext_modules = [
            Extension(
                name = 'package_name',
                sources = [
                    'source/file.cpp',
                ],
                include_dirs = ['source'],
            )
        ],
    )

Sürümü dosyadan okur version.h:

const char* __version__ = "1.0.12";

Ancak, dosyayı MANIFEST.iniçerecek şekilde oluşturmayı unutmayın version.h:

include README.md
include LICENSE.txt

recursive-include source *.h

Ve ana uygulamaya entegre edilmiştir:

#include <Python.h>
#include "version.h"

// create the module
PyMODINIT_FUNC PyInit_package_name(void)
{
    PyObject* thismodule;
    ...

    // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
    PyObject_SetAttrString( thismodule, "__version__", Py_BuildValue( "s", __version__ ) );

    ...
}

Referanslar:

  1. python açık dosya hatası
  2. C API'sinden bir Python modülünde genel bir tanımla
  3. Setuptools / dağıtımı ile paket verileri nasıl dahil edilir?
  4. https://github.com/lark-parser/lark/blob/master/setup.py#L4
  5. Aynı ada sahip setuptools paketleri ve ext_modules nasıl kullanılır?
  6. Paket verilerinin bir parçası olarak dist utils (setup.py) kullanan alt dizinleri dahil etmek mümkün müdür?

1

indeks paketleri için paketi sunucuya ve dosya adlandırma kuralına dağıtın:

pip dinamik sürüm dönüşümü örneği:

  • win:

    • test_pkg-1.0.0-cp36-cp36m-win_amd64.whl
    • test_pkg-1.0.0-py3.6-kazan-amd64.egg
  • Mac:

    • test_pkg-1.0.0-py3.7-macosx-10.12-x86_64.egg
    • test_pkg-1.0.0-py3.7-macosx-10.12-x86_64.whl
  • linux:
    • test_pkg-1.0.0-cp36-cp36m-linux_x86_64.whl
from setuptools_scm import get_version

def _get_version():

     dev_version = str(".".join(map(str, str(get_version()).split("+")[0]\
            .split('.')[:-1])))

    return dev_version

Örnek setup.py dosyasını bul git komutundan eşleşen dinamik pip sürümünü çağırır

setup(
    version=_get_version(),
    name=NAME,
    description=DESCRIPTION,
    long_description=LONG_DESCRIPTION,
    classifiers=CLASSIFIERS,

# add few more for wheel wheel package ...conversion

)

0

Aşağıdaki gibi bir ortam değişkeni kullanıyorum

SÜRÜM = 0.0.0 python setup.py sdist bdist_wheel

Setup.py içinde


import os

setup(
    version=os.environ['VERSION'],
    ...
)

Packer sürümü ile tutarlılık kontrolü için aşağıdaki komut dosyasını kullanıyorum.

PKG_VERSION=`python -c "import pkg; print(pkg.__version__)"`
if [ $PKG_VERSION == $VERSION ]; then
    python setup.py sdist bdist_wheel
else
    echo "Package version differs from set env variable"
fi
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.