stop using .tac files: make it possible to change appname, Python package-directory name, perhaps other names #1159
Labels
No labels
c/code
c/code-dirnodes
c/code-encoding
c/code-frontend
c/code-frontend-cli
c/code-frontend-ftp-sftp
c/code-frontend-magic-folder
c/code-frontend-web
c/code-mutable
c/code-network
c/code-nodeadmin
c/code-peerselection
c/code-storage
c/contrib
c/dev-infrastructure
c/docs
c/operational
c/packaging
c/unknown
c/website
kw:2pc
kw:410
kw:9p
kw:ActivePerl
kw:AttributeError
kw:DataUnavailable
kw:DeadReferenceError
kw:DoS
kw:FileZilla
kw:GetLastError
kw:IFinishableConsumer
kw:K
kw:LeastAuthority
kw:Makefile
kw:RIStorageServer
kw:StringIO
kw:UncoordinatedWriteError
kw:about
kw:access
kw:access-control
kw:accessibility
kw:accounting
kw:accounting-crawler
kw:add-only
kw:aes
kw:aesthetics
kw:alias
kw:aliases
kw:aliens
kw:allmydata
kw:amazon
kw:ambient
kw:annotations
kw:anonymity
kw:anonymous
kw:anti-censorship
kw:api_auth_token
kw:appearance
kw:appname
kw:apport
kw:archive
kw:archlinux
kw:argparse
kw:arm
kw:assertion
kw:attachment
kw:auth
kw:authentication
kw:automation
kw:avahi
kw:availability
kw:aws
kw:azure
kw:backend
kw:backoff
kw:backup
kw:backupdb
kw:backward-compatibility
kw:bandwidth
kw:basedir
kw:bayes
kw:bbfreeze
kw:beta
kw:binaries
kw:binutils
kw:bitcoin
kw:bitrot
kw:blacklist
kw:blocker
kw:blocks-cloud-deployment
kw:blocks-cloud-merge
kw:blocks-magic-folder-merge
kw:blocks-merge
kw:blocks-raic
kw:blocks-release
kw:blog
kw:bom
kw:bonjour
kw:branch
kw:branding
kw:breadcrumbs
kw:brians-opinion-needed
kw:browser
kw:bsd
kw:build
kw:build-helpers
kw:buildbot
kw:builders
kw:buildslave
kw:buildslaves
kw:cache
kw:cap
kw:capleak
kw:captcha
kw:cast
kw:centos
kw:cffi
kw:chacha
kw:charset
kw:check
kw:checker
kw:chroot
kw:ci
kw:clean
kw:cleanup
kw:cli
kw:cloud
kw:cloud-backend
kw:cmdline
kw:code
kw:code-checks
kw:coding-standards
kw:coding-tools
kw:coding_tools
kw:collection
kw:compatibility
kw:completion
kw:compression
kw:confidentiality
kw:config
kw:configuration
kw:configuration.txt
kw:conflict
kw:connection
kw:connectivity
kw:consistency
kw:content
kw:control
kw:control.furl
kw:convergence
kw:coordination
kw:copyright
kw:corruption
kw:cors
kw:cost
kw:coverage
kw:coveralls
kw:coveralls.io
kw:cpu-watcher
kw:cpyext
kw:crash
kw:crawler
kw:crawlers
kw:create-container
kw:cruft
kw:crypto
kw:cryptography
kw:cryptography-lib
kw:cryptopp
kw:csp
kw:curl
kw:cutoff-date
kw:cycle
kw:cygwin
kw:d3
kw:daemon
kw:darcs
kw:darcsver
kw:database
kw:dataloss
kw:db
kw:dead-code
kw:deb
kw:debian
kw:debug
kw:deep-check
kw:defaults
kw:deferred
kw:delete
kw:deletion
kw:denial-of-service
kw:dependency
kw:deployment
kw:deprecation
kw:desert-island
kw:desert-island-build
kw:design
kw:design-review-needed
kw:detection
kw:dev-infrastructure
kw:devpay
kw:directory
kw:directory-page
kw:dirnode
kw:dirnodes
kw:disconnect
kw:discovery
kw:disk
kw:disk-backend
kw:distribute
kw:distutils
kw:dns
kw:do_http
kw:doc-needed
kw:docker
kw:docs
kw:docs-needed
kw:dokan
kw:dos
kw:download
kw:downloader
kw:dragonfly
kw:drop-upload
kw:duplicity
kw:dusty
kw:earth-dragon
kw:easy
kw:ec2
kw:ecdsa
kw:ed25519
kw:egg-needed
kw:eggs
kw:eliot
kw:email
kw:empty
kw:encoding
kw:endpoint
kw:enterprise
kw:enum34
kw:environment
kw:erasure
kw:erasure-coding
kw:error
kw:escaping
kw:etag
kw:etch
kw:evangelism
kw:eventual
kw:example
kw:excess-authority
kw:exec
kw:exocet
kw:expiration
kw:extensibility
kw:extension
kw:failure
kw:fedora
kw:ffp
kw:fhs
kw:figleaf
kw:file
kw:file-descriptor
kw:filename
kw:filesystem
kw:fileutil
kw:fips
kw:firewall
kw:first
kw:floatingpoint
kw:flog
kw:foolscap
kw:forward-compatibility
kw:forward-secrecy
kw:forwarding
kw:free
kw:freebsd
kw:frontend
kw:fsevents
kw:ftp
kw:ftpd
kw:full
kw:furl
kw:fuse
kw:garbage
kw:garbage-collection
kw:gateway
kw:gatherer
kw:gc
kw:gcc
kw:gentoo
kw:get
kw:git
kw:git-annex
kw:github
kw:glacier
kw:globalcaps
kw:glossary
kw:google-cloud-storage
kw:google-drive-backend
kw:gossip
kw:governance
kw:grid
kw:grid-manager
kw:gridid
kw:gridsync
kw:grsec
kw:gsoc
kw:gvfs
kw:hackfest
kw:hacktahoe
kw:hang
kw:hardlink
kw:heartbleed
kw:heisenbug
kw:help
kw:helper
kw:hint
kw:hooks
kw:how
kw:how-to
kw:howto
kw:hp
kw:hp-cloud
kw:html
kw:http
kw:https
kw:i18n
kw:i2p
kw:i2p-collab
kw:illustration
kw:image
kw:immutable
kw:impressions
kw:incentives
kw:incident
kw:init
kw:inlineCallbacks
kw:inotify
kw:install
kw:installer
kw:integration
kw:integration-test
kw:integrity
kw:interactive
kw:interface
kw:interfaces
kw:interoperability
kw:interstellar-exploration
kw:introducer
kw:introduction
kw:iphone
kw:ipkg
kw:iputil
kw:ipv6
kw:irc
kw:jail
kw:javascript
kw:joke
kw:jquery
kw:json
kw:jsui
kw:junk
kw:key-value-store
kw:kfreebsd
kw:known-issue
kw:konqueror
kw:kpreid
kw:kvm
kw:l10n
kw:lae
kw:large
kw:latency
kw:leak
kw:leasedb
kw:leases
kw:libgmp
kw:license
kw:licenss
kw:linecount
kw:link
kw:linux
kw:lit
kw:localhost
kw:location
kw:locking
kw:logging
kw:logo
kw:loopback
kw:lucid
kw:mac
kw:macintosh
kw:magic-folder
kw:manhole
kw:manifest
kw:manual-test-needed
kw:map
kw:mapupdate
kw:max_space
kw:mdmf
kw:memcheck
kw:memory
kw:memory-leak
kw:mesh
kw:metadata
kw:meter
kw:migration
kw:mime
kw:mingw
kw:minimal
kw:misc
kw:miscapture
kw:mlp
kw:mock
kw:more-info-needed
kw:mountain-lion
kw:move
kw:multi-users
kw:multiple
kw:multiuser-gateway
kw:munin
kw:music
kw:mutability
kw:mutable
kw:mystery
kw:names
kw:naming
kw:nas
kw:navigation
kw:needs-review
kw:needs-spawn
kw:netbsd
kw:network
kw:nevow
kw:new-user
kw:newcaps
kw:news
kw:news-done
kw:news-needed
kw:newsletter
kw:newurls
kw:nfc
kw:nginx
kw:nixos
kw:no-clobber
kw:node
kw:node-url
kw:notification
kw:notifyOnDisconnect
kw:nsa310
kw:nsa320
kw:nsa325
kw:numpy
kw:objects
kw:old
kw:openbsd
kw:openitp-packaging
kw:openssl
kw:openstack
kw:opensuse
kw:operation-helpers
kw:operational
kw:operations
kw:ophandle
kw:ophandles
kw:ops
kw:optimization
kw:optional
kw:options
kw:organization
kw:os
kw:os.abort
kw:ostrom
kw:osx
kw:osxfuse
kw:otf-magic-folder-objective1
kw:otf-magic-folder-objective2
kw:otf-magic-folder-objective3
kw:otf-magic-folder-objective4
kw:otf-magic-folder-objective5
kw:otf-magic-folder-objective6
kw:p2p
kw:packaging
kw:partial
kw:password
kw:path
kw:paths
kw:pause
kw:peer-selection
kw:performance
kw:permalink
kw:permissions
kw:persistence
kw:phone
kw:pickle
kw:pip
kw:pipermail
kw:pkg_resources
kw:placement
kw:planning
kw:policy
kw:port
kw:portability
kw:portal
kw:posthook
kw:pratchett
kw:preformance
kw:preservation
kw:privacy
kw:process
kw:profile
kw:profiling
kw:progress
kw:proxy
kw:publish
kw:pyOpenSSL
kw:pyasn1
kw:pycparser
kw:pycrypto
kw:pycrypto-lib
kw:pycryptopp
kw:pyfilesystem
kw:pyflakes
kw:pylint
kw:pypi
kw:pypy
kw:pysqlite
kw:python
kw:python3
kw:pythonpath
kw:pyutil
kw:pywin32
kw:quickstart
kw:quiet
kw:quotas
kw:quoting
kw:raic
kw:rainhill
kw:random
kw:random-access
kw:range
kw:raspberry-pi
kw:reactor
kw:readonly
kw:rebalancing
kw:recovery
kw:recursive
kw:redhat
kw:redirect
kw:redressing
kw:refactor
kw:referer
kw:referrer
kw:regression
kw:rekey
kw:relay
kw:release
kw:release-blocker
kw:reliability
kw:relnotes
kw:remote
kw:removable
kw:removable-disk
kw:rename
kw:renew
kw:repair
kw:replace
kw:report
kw:repository
kw:research
kw:reserved_space
kw:response-needed
kw:response-time
kw:restore
kw:retrieve
kw:retry
kw:review
kw:review-needed
kw:reviewed
kw:revocation
kw:roadmap
kw:rollback
kw:rpm
kw:rsa
kw:rss
kw:rst
kw:rsync
kw:rusty
kw:s3
kw:s3-backend
kw:s3-frontend
kw:s4
kw:same-origin
kw:sandbox
kw:scalability
kw:scaling
kw:scheduling
kw:schema
kw:scheme
kw:scp
kw:scripts
kw:sdist
kw:sdmf
kw:security
kw:self-contained
kw:server
kw:servermap
kw:servers-of-happiness
kw:service
kw:setup
kw:setup.py
kw:setup_requires
kw:setuptools
kw:setuptools_darcs
kw:sftp
kw:shared
kw:shareset
kw:shell
kw:signals
kw:simultaneous
kw:six
kw:size
kw:slackware
kw:slashes
kw:smb
kw:sneakernet
kw:snowleopard
kw:socket
kw:solaris
kw:space
kw:space-efficiency
kw:spam
kw:spec
kw:speed
kw:sqlite
kw:ssh
kw:ssh-keygen
kw:sshfs
kw:ssl
kw:stability
kw:standards
kw:start
kw:startup
kw:static
kw:static-analysis
kw:statistics
kw:stats
kw:stats_gatherer
kw:status
kw:stdeb
kw:storage
kw:streaming
kw:strports
kw:style
kw:stylesheet
kw:subprocess
kw:sumo
kw:survey
kw:svg
kw:symlink
kw:synchronous
kw:tac
kw:tahoe-*
kw:tahoe-add-alias
kw:tahoe-admin
kw:tahoe-archive
kw:tahoe-backup
kw:tahoe-check
kw:tahoe-cp
kw:tahoe-create-alias
kw:tahoe-create-introducer
kw:tahoe-debug
kw:tahoe-deep-check
kw:tahoe-deepcheck
kw:tahoe-lafs-trac-stream
kw:tahoe-list-aliases
kw:tahoe-ls
kw:tahoe-magic-folder
kw:tahoe-manifest
kw:tahoe-mkdir
kw:tahoe-mount
kw:tahoe-mv
kw:tahoe-put
kw:tahoe-restart
kw:tahoe-rm
kw:tahoe-run
kw:tahoe-start
kw:tahoe-stats
kw:tahoe-unlink
kw:tahoe-webopen
kw:tahoe.css
kw:tahoe_files
kw:tahoewapi
kw:tarball
kw:tarballs
kw:tempfile
kw:templates
kw:terminology
kw:test
kw:test-and-set
kw:test-from-egg
kw:test-needed
kw:testgrid
kw:testing
kw:tests
kw:throttling
kw:ticket999-s3-backend
kw:tiddly
kw:time
kw:timeout
kw:timing
kw:to
kw:to-be-closed-on-2011-08-01
kw:tor
kw:tor-protocol
kw:torsocks
kw:tox
kw:trac
kw:transparency
kw:travis
kw:travis-ci
kw:trial
kw:trickle
kw:trivial
kw:truckee
kw:tub
kw:tub.location
kw:twine
kw:twistd
kw:twistd.log
kw:twisted
kw:twisted-14
kw:twisted-trial
kw:twitter
kw:twn
kw:txaws
kw:type
kw:typeerror
kw:ubuntu
kw:ucwe
kw:ueb
kw:ui
kw:unclean
kw:uncoordinated-writes
kw:undeletable
kw:unfinished-business
kw:unhandled-error
kw:unhappy
kw:unicode
kw:unit
kw:unix
kw:unlink
kw:update
kw:upgrade
kw:upload
kw:upload-helper
kw:uri
kw:url
kw:usability
kw:use-case
kw:utf-8
kw:util
kw:uwsgi
kw:ux
kw:validation
kw:variables
kw:vdrive
kw:verify
kw:verlib
kw:version
kw:versioning
kw:versions
kw:video
kw:virtualbox
kw:virtualenv
kw:vista
kw:visualization
kw:visualizer
kw:vm
kw:volunteergrid2
kw:volunteers
kw:vpn
kw:wapi
kw:warners-opinion-needed
kw:warning
kw:weapi
kw:web
kw:web.port
kw:webapi
kw:webdav
kw:webdrive
kw:webport
kw:websec
kw:website
kw:websocket
kw:welcome
kw:welcome-page
kw:welcomepage
kw:wiki
kw:win32
kw:win64
kw:windows
kw:windows-related
kw:winscp
kw:workaround
kw:world-domination
kw:wrapper
kw:write-enabler
kw:wui
kw:x86
kw:x86-64
kw:xhtml
kw:xml
kw:xss
kw:zbase32
kw:zetuptoolz
kw:zfec
kw:zookos-opinion-needed
kw:zope
kw:zope.interface
p/blocker
p/critical
p/major
p/minor
p/normal
p/supercritical
p/trivial
r/cannot reproduce
r/duplicate
r/fixed
r/invalid
r/somebody else's problem
r/was already fixed
r/wontfix
r/worksforme
t/defect
t/enhancement
t/task
v/0.2.0
v/0.3.0
v/0.4.0
v/0.5.0
v/0.5.1
v/0.6.0
v/0.6.1
v/0.7.0
v/0.8.0
v/0.9.0
v/1.0.0
v/1.1.0
v/1.10.0
v/1.10.1
v/1.10.2
v/1.10a2
v/1.11.0
v/1.12.0
v/1.12.1
v/1.13.0
v/1.14.0
v/1.15.0
v/1.15.1
v/1.2.0
v/1.3.0
v/1.4.1
v/1.5.0
v/1.6.0
v/1.6.1
v/1.7.0
v/1.7.1
v/1.7β
v/1.8.0
v/1.8.1
v/1.8.2
v/1.8.3
v/1.8β
v/1.9.0
v/1.9.0-s3branch
v/1.9.0a1
v/1.9.0a2
v/1.9.0b1
v/1.9.1
v/1.9.2
v/1.9.2a1
v/cloud-branch
v/unknown
No milestone
No project
No assignees
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: tahoe-lafs/trac#1159
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
(Reported to tahoe-dev by Nathan Eisenberg.)
In the 1.8beta release, when a user attempts to start a node using a node directory generated by an earlier version (or trunk), it will fail to start and will report a traceback similar to:
This happens because the appname was changed to "
tahoe-lafs-ticket798
" for the beta [4595/ticket798], but existing.tac
files contain references to the previous "allmydata-tahoe
" appname. For example,tahoe-client.tac
typically contains:Note that the appname change [has not been made on trunk]source:setup.py@4668#L329, only on the ticket798 branch from which the beta was built.
We should therefore withdraw the beta, because otherwise users may generate new node directories that will not work in future versions (due to the opposite problem, i.e.
DistributionNotFound: tahoe-lafs-ticket798
).This failed to be detected because there are no tests that check compatibility with a node directory generated by a previous version. To prevent this happening again, we need the test suite to run at least a smoke test with a node directory that looks like one generated by an earlier version (perhaps check one in as a resource, with a big-fat-warning not to change it).
Hm, there are four overlapping namespaces here.
One is the "appname" which is defined by us (the Tahoe-LAFS project) to distinguish different variants or forks of Tahoe-LAFS or independent implementations of the LAFS protocol. We agreed on how to do this versioning in this message to tahoe-dev. The appname is used in [in allmydata/init.py]source:src/allmydata/init.py@4597#L61 to construct a variable named
*full_version*
, which is used in a few places such as [storage/server.py]source:src/allmydata/storage/server.py@4595#L270. The appname for Tahoe-LAFS has been "allmydata-tahoe" for the last couple of years, and we would like to change the appname to "tahoe-lafs" someday.Another namespace is the Python "distribution" namespace. (A "distribution" is what the Python world calls a package.) This is a global namespace where everyone on the planet is supposed to avoid choosing colliding names. An important central locus of this namespace is the Python Package Index (which I suppose ought to be called the "Python Distribution Index")—installers such as
easy_install
andpip
, when asked to install a distribution named$DIST
, will by default look for it at<http://pypi.python.org/pypi/$DIST>
. The distribution name for Tahoe-LAFS has been "allmydata-tahoe" and we would like to change it to "tahoe-lafs".The third namespace is the Python "package" namespace. (A "package" is what the Python world calls a directory containing an
*init*.py
file.) This namespace is global and is populated by all of the Python distributions that you install on your system. Collisions are silently resolved by a complicated algorithm involving yourPYTHONPATH
and a certain widely disliked hack due originally to setuptools (setuptool #53). Thetahoe-client.tac
file loads a package namedallmydata
. We would probably like to change that in the future totahoe
.Now currently [our build scripts]source:trunk/setup.py@4616#L329 ensure that the Python distribution name is always equal to the appname, and the [create-node command]source:src/allmydata/scripts/create_node.py@4641#L31 adds
pkg_resources.require(APPNAME)
to thetahoe-client.tac
file.The fourth namespace is the scripts and executables in your system, where we currently create a file named
tahoe
.One thing that we can do right away to ease this is change create-node to stop putting the call to
pkg_resources.require()
in the tahoe-client.tac.Replying to zooko:
As far as I understood, these were intended to be the same by definition, at least for Python implementations of the protocol. I.e. the "
application-version
" field in introduction messages is specifying the implementation version (not a protocol version), and the distribution string is also specifying the implementation version, and so we put the latter string intoapplication-version
. (Clearly there can be non-Python implementations of the protocol, and they would use whatever is the nearest equivalent of the distribution string.)Is there any reason for these not to be the same by definition, for Python implementations?
No, absolutely not! That's the module namespace. A package is something else entirely; see below.
(Okay, much of the Python world may be inconsistent in the terminology they use, but the official docs are consistent on this point.)
More precisely (and it's important to be precise here), a distribution is named by
appname+'-'+version
. The things named by anappname
alone are called "packages" (hence "Python Package Index"). A distribution contains a particular version of a package.(Packages are also called "projects" in some of the setuptools documentation, but no-one uses that, not even the rest of the setuptools docs and code.)
As far as I understand, the ostensible purpose of that call is to ensure that when we import modules named
allmydata.*
, we're getting them from some version of theallmydata-tahoe
package (this doesn't help to ensure that we're getting the right version). On the other hand, I don't think it actually succeeds in doing even that, if another package defines anallmydata
module and happens to be earlier onsys.path
, which is currently possible. However I think it is also necessary in order for the call toload_entry_point
in the CLI wrapper script to work correctly.(The implementation of
pkg_resources.require
in zetuptoolz is here. Good luck tracing that :-)I seem to recall that the
pkg_resources.require
API is intended to let programs express a dependency on specific versions (or version ranges) of other package/modules, in the actual code that does theimport
(as opposed to off in some remotesetup.py
world). Using it without a version number specification seems to be not particularly useful, although I think it probably does serve to tell setuptools to fuss around with PYTHONPATH enough to allow theimport
to maybe work.I think I'd like to see a list of all the things in our tree that depend upon PYTHONPATH being set in some particular way (probably bin/tahoe and test_runner), and then see if there's a way to accomplish this by either removing those places or purely by manipulating PYTHONPATH, depending less upon setuptools mechanisms. In particular, I think that
twistd
has been loadable as a library for several years now, so I think that the subprocess-spawning done bytahoe start
/tahoe run
can go away, which might remove one of the needs to change PYTHONPATH. (the test_runner code that really does want to spawn a subprocess, because it wants to kill the subprocess, may be replaceable with anos.fork
or something, so the child can simply inherit the environment of the parent).This bug is not present in the 1.8.0c1 release candidate, but leaving open because we need a test.
Replying to [davidsarah]comment:2:
Agreed.
I can't think of any at the moment.
What docs are you referring to? I really wish that there was some official justification to use "package" to mean a package, but sadly I was unable to persuade the distutils-sig mailing list to get behind a full-scale renaming. Therefore we are currently stuck with this:
http://guide.python-distribute.org/glossary.html
Distribution
That might be our only hope -- the word "project" isn't already used to mean something else within Python, so maybe we could start consistently using it to mean all-versions-of the source that is used to produce distributions (each of which has a version number).
By the way I think that Brian in comment:380142 is showing that he is confused about the difference between distributions (sometimes called packages, especially by the rest of the world outside of Python), packages (directories that have
*init*.py
files in them), and modules (importable bundles of Python code). Thepkg_resources
API is intended to express a dependency on a project, i.e. a range (possibly "any") of versions of distributions of that project. (Note the name begins with "pkg", which stands for "distribution". Ha ha.)David-Sarah wrote in comment:2:
My purpose in adding that call to
pkg_resources
was to ensure that if the distribution ("package"? "project"?) was not installed that we would get an explicit error at that point instead of proceding. Actually, it was more to ensure that the transitive closure of theinstall_requires
of theallmydata-tahoe
distribution were installed. It has been a long time since I've felt like I needed that double-check and I don't object to removing it.Replying to [zooko]comment:5:
I meant that the python.org docs are consistent in not using "package" when they mean "module" (at least I haven't seen any counterexamples on python.org).
OK, that's not too bad.
Gahh. This is completely wrong and unnecessarily confusing. Pretend they didn't say that.
The right term for the latter concept is "module directory".
(Module code can also be stored in zipfiles, so this isn't necessarily a directory in a filesystem.)
[...]
I've no objection to using "project", if you think "package" is ambiguous.
The strings specifying a package/project possibly with a version constraint, e.g. "allmydata-tahoe>=1.7.0", are called "requirements".
The argument to
pkg_resources.require
is a requirement. In this case it is just a requirement for an unspecified version of theallmydata-tahoe
project, which is not all that useful, I think.I don't think it actually checks that.
Let's try that (for after 1.8.0) and see if it breaks anything.
My vague recollection is that it does, because I think I remember having
a Foolscap installed in such a way that 'import foolscap' worked fine but
setuptools/pkg_resources didn't believe it was present (or wasn't of the
required version), and that commenting out the
pkg_resources.require
call was necessary to make it stop throwing
NoSuchDistribution
exceptions or the like.
I wasn't too thorough about checking that, so I could be wrong.
Replying to warner:
Yeah, it does:
[by davidsarah: this test is misleading. it's not the call to
pkg_resources.require('allmydata-tahoe')
in the tac file that performs this check; the check is done as a side-effect of "import pkg_resources
" after setting*requires*
in the setuptools-generated support script. All explicit calls topkg_resources.require
for package names that were already in*requires*
are redundant.]editWhat are the next steps on this ticket? I think it is to remove the
pkg_resources.require()
in intahoe-client.tac
, and possibly to make a facility to overwritetahoe-client.tac
with a new version on install so that when people install Tahoe-LAFS v1.9.0 they get this new version.1.8beta is incompatible with existing node directories due to change of appnameto make it possible to change appname, Python package-directory name, perhaps other namesReplying to zooko:
How would we know where all of the
.tac
files are on install? I think that to be sufficiently compatible, we'd have to work correctly even when the.tac
file used when starting a node is one that we've never seen before.Someone please explain what the benefit is of using
.tac
files at all? Is that just "the way it's done" in Twisted?Re .tac files:
It's probably time for them to die. When I wrote the very first
get-a-client-running framework (30-Nov-2006, wow), I copied the scheme I'd
used in buildbot, since it was an easy way to get a daemon process running.
The original idea of .tac files (and .tap and .tax files, their black-sheep
siblings) was to decouple the implementation of a service from the
deployment. From a developer's point of view, it's pretty easy to create a
service in the Twisted world: you make a subclass of
twisted.application.service.Service
, overridestartService
/stopService
to control startup/shutdown, and connectother services in a tree shape with
setServiceParent
.To actually start this, the cheap "
__main__
" way is to useservice.startService(); reactor.run()
, and the cheap way to configureit is to pass arguments into your service's constructor. But ops folks (or,
you know, users) who want to run your service don't want to write python
code. And they might want to configure the service without writing python
code.
The "official" way to do this, at least as of 2006, was a Twisted tool named
'
mktap
'. This uses plugins (which you write just after you write yourService subclass) to transform command-line arguments (a
twisted.python.usage.Usage instance) into a fully-configured Service
instance, and then serializes (with
pickle
) the Service out into a .tapfile. Then, later, you use '
twistd foo.tap
' to thaw out the Service andstart it running (properly daemonized and setuided and all).
twistd
would also serialize the Service object when you quit the process, so you
could achieve persistence by running '
twistd foo-shutdown.tap
' onsubsequent runs.
Eventually
twistd
learned how to use themktap
plugins directly,so I think you can run
twistd web --path .
to do the same thing asmktap web --path . ; twistd web.tap
but without the leftover .tap file.But, pickle files are a drag, and the auto-persistence -shutdown.tap feature
turned out to be a bad idea. Once you stop using pickle, then having a
non-human-readable configuration/deployment file is a drag. So .tac (which is
a python program that provides a distinguished 'application' symbol, and is
evaluated by
twistd
) becomes reasonable.Anyways, the benefit of writing out a .tac file is that you could use the
generic
twistd
to launch the service (assuming that everything is onyour PYTHONPATH), which gives you a bunch of maybe-useful options for free:
--syslog, --profile, --rundir, --chroot, --uid, --reactor
. There arealso some tools which make it easy to launch twistd-style jobs from
/etc/init.d/
initscripts, or from macLaunchAgent
plists.But, now that twistd is invokable as a library, it's easier to get those free
arguments without needing to duplicate them all in the '
tahoe start
'option parser. If we commit to having
bin/tahoe
be the only way tolaunch tahoe, then it can set up
sys.path
before importingtwisted.scripts.twistd
.So maybe what's left is to define a data file (perhaps named
client.tac
, for backwards compatibility), from whichtahoe start
can determine that it ought to instantiate an
allmydata.client.Client
instead of an
allmydata.introducer.IntroducerNode
. And then changetahoe start
to do whateverpkg_resources.require
might reallyreally be necessary before scanning the data file and doing the conditional
import.
Or maybe
tahoe start
could look for "tahoe.cfg" to decide if the targetdirectory is really a tahoe nodedir, look either for a key in it or the
presence of
client.tac
/introducer.tac
to decide what top-levelService to instantiate, but then otherwise ignore the .tac file. And new
versions of
tahoe create-node
could write thenodetype=
key intotahoe.cfg and not write the .tac file.
Oh, one caveat: since we delegate daemonization/etc to
twistd
, we're limited in the set of entry points we can use. The easiest one istwisted.scripts.twistd.run
, for which the arguments are effectivelysys.argv
, which means it really wants to find a.tac
file. What we want is a way to build thetwisted.application.service.Application
or.MultiService
instance and hand it fully-formed into twistd. So we'd need to find a stable/reasonable point-of-entry into the twistd code that accepts a Service but is still before the daemonization/logging/etc setup.one hack might be to set up the plugins table, then set
argv
to something with a "subcommand" which vectors into a special tahoe-Service-making "plugin" (which really doesn't exist anywhere else on the filesystem, only in RAM). Another would be to somehow overridetwisted.application.app.ApplicationRunner.createOrGetApplication
, possibly by monkeypatchingtwisted.scripts.twistd._SomeApplicationRunner
, which sounds like a bad idea. (ApplicationRunner
is the parent class of bothWindowsApplicationRunner
andUnixApplicationRunner
, andtwisted/scripts/twistd.py
is responsible for loading the right one).It might also be possible to grab control by wrapping the
runApp
intwistd.py
before it is passed toapp.run
. I've not yet investigated whether that would help, though, it might be too late.I'm not completely following the details, but the general idea sounds great to me.
I just started to write up a duplicate ticket.. fixing up the tags on this one so I can find it next time.
make it possible to change appname, Python package-directory name, perhaps other namesto stop using .tac files: make it possible to change appname, Python package-directory name, perhaps other namesReplying to warner:
Or we can put a
.tac
file in the source tree, and direct twistd to that one (using something likeos.path.join(os.path.dirname(allmydata.*file*), 'tahoe_node.tac')
), rather than to the one in the node directory. Even though it doesn't "stop using .tac files", that would solve the problems in this ticket because the in-source.tac
can change without any compatibility issues.This depends on the Tahoe source not being zipped, but we already say in source:setup.py that it is not zip-safe.
Elrond on
#tahoe-lafs
said that they had a problem starting nodes with a (slightly modified) version of the Tahoe-LAFS 1.8.2-3 Debian package, due to thepkg_resources.require('twisted')
in the .tac file. Apparently twisted had been manually installed in a way that wasn't recognized by pkg_resources(possibly due to http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=631163). Commenting out thepkg_resources.require
worked.The output of
tahoe --version-and-path
wasWhen investigating workarounds, note that we can now depend on Twisted >= 10.1.
This is one of those tickets that needs to spawn off smaller and more closeable subtickets.
I just created #1539 which is a small step we could do (I think) right away and that might ease things in the future.
Replying to warner:
Brian made this change in changeset:ac3b26ecf29c08cb.
Okay, having re-read this ticket, it sounds like the way forward is for someone to figure out how to use
twistd
as an importable library instead of as a command that gets executed and then loads our code. See comment:380154, comment:380155, comment:380156, comment:17. Is that the next step?Replying to zooko:
Yes. comment:17 is a way of doing that that will work, but is ugly. I don't know whether there's a more elegant way. (Duplicating some of twistd's daemonizing code would also work but would be even uglier.)
I was able to use the first technique from comment:380156 in my "toolbed" app (i.e. creating a fake in-RAM "plugin", then a sys.argv that references it). I'll build a patch that changes 'tahoe start' to use that technique so we can give it a spin.
Attachment notac.diff (10818 bytes) added
stop using contents of .tac files
davidsarah: How's that look?
Will review.
Starting review.
The patch applies cleanly to trunk and passes existing tests.
Re: this comment
That's OK but the error message that you're likely to get is "--basedir '--nodaemon' doesn't exist", which is not as helpful as it could be.
The patch adjusts some tests but doesn't appear to fully test the change in functionality. Will think about what tests there should be.
Continuing review...
tahoe start --help
says "Usage: tahoe start options NODEDIR
, which is wrong if the options should be after the nodedir. (Similarly forrestart
etc.)The
twistd
options are available but not documented intahoe start --help
. Seetahoe debug trial --help
for an example of how it is possible to get those options listed.Does the fact that "
# also ("--logfile", "tahoesvc.log")
" is commented out mean that there is some regression in logging functionality?Replying to davidsarah:
Oh, that applies only to
startstop_node.run
, and it has the effect of not redirecting stdout/stderr fortahoe run
and so fixing #1489. That's a good change, but the comment should be removed or clarified, and/or we should document the change.Replying to [davidsarah]comment:34:
in source:git/docs/logging.rst for example.
"XYZ"
could probably be something less mysterious like"StartTahoeNode"
, while still having negligible chance of colliding with any existing subcommand.Could an argument to
tahoe
that does not start with"--"
be confused bytwistd
for the command name?If I try
tahoe start ~/.tahoe foo
(which should be an error), I get a twistd options listing followed by a TypeError traceback, which appears to be due to a bug atstartstop_node.py
line 114. This change fixes the bug, and snips some implementation details about twistd from the end of the options listing:I pushed patches addressing some of the above comments to https://github.com/davidsarah/tahoe-lafs/commits/1159-no-tac.
https://github.com/davidsarah/tahoe-lafs/commit/a7e4cab9c3367048d8ea326f559f65a6accdb8c1 is warner's original patch and subsequent ones are mine. They do not yet address comment:380177.
The
-d
/--node-directory=
/-C
/--basedir=
option isn't working correctly when twistd options are given, because there's nothing to separate the tahoe options from the twistd options. Not sure what to do about that, but it interacts with #166.I want this, but won't block 1.10 for it. Kicking it and its cousin #1539 into 1.11 . Should be easy to get done early in the next cycle.
+1 for kicking this out.
This is a blocker for #1950.
I've updated my branch with daira's recommended patches. https://github.com/warner/tahoe-lafs/tree/1159-notac
Is the code review completed on this one? Does it need to be updated or done once more?
zs260: hi, i'm trying to create systemd for tahoe introducer. i got the client working fine, but for introducer, i need to run it in foreground mode, tahoe run, and it complains " looks like it contains a non-client node (tahoe-introducer.tac). Use tahoe start instead of tahoe run"
zs260: introducer works fine with tahoe start, but when i use with systemd, type="forking", it does not work. systemd keeps waiting
daira: oh, zs260 left. I was just about to answer their question
daira: the fact that 'tahoe run' doesn't work for introducers (or key-generators or stats-gatherers) is a ticketed bug
daira: #1159 (also #937 which was closed as a duplicate of #1159)
daira: #1159 is likely to be fixed for 1.11
daira: if you need me to rebase my branch, please let me know. I'll run tests locally and make sure it hasn't bitrotted.
Yes please! Reassign me when you're done.
I've rebased the branch (and fixed one test which was failing.. not sure what exactly was happening there, the fix was to revert a test change that I made to allow the original patch to pass). The new branch is here:
https://github.com/warner/tahoe-lafs/tree/1159-notac-2
I think we should land this, and then close #1539 because this branch supercedes that one.
Note that this patch doesn't completely close #1159: it stops using the contents of the .tac files, but still relies upon their presence, in particular their filename: if "client" is a substring of the filename of the first .tac file found in the node's basedir, then we instantiate a
Client
, if "introducer" is in the string, we instantiate anIntroducerNode
, etc.We'll want another patch, after 1.11, to move this indicator into tahoe.cfg (and look for a .tac filename as a backwards-compatibility tool).
Rebased at https://github.com/tahoe-lafs/tahoe-lafs/tree/1159-notac-3. Reviewing now.
Fixed in changeset:87a6894e6299148d639279fbd909110ba00d0080/trunk.
Replying to warner:
Filed as #2325. What we've done with this patch is sufficient to "make it possible to change appname (#2011), Python package-directory name (#1950), perhaps other names".