mirror of
https://github.com/darlinghq/darling-python.git
synced 2024-11-23 04:09:40 +00:00
python-125
That's Apple's Python version; but it's actually Python 2.7.16 (no version for 2.6; it's been dropped by Apple)
This commit is contained in:
parent
7654060c81
commit
5a405172d6
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
*~
|
||||
*.rej
|
||||
*.orig
|
||||
.DS_Store
|
||||
*.swp
|
205
2.6/GNUmakefile
205
2.6/GNUmakefile
@ -1,205 +0,0 @@
|
||||
##---------------------------------------------------------------------
|
||||
# GNUmakefile for python
|
||||
# Call Makefile to do the work, but for the install case, unpack the
|
||||
# tarball to create the project source directory
|
||||
##---------------------------------------------------------------------
|
||||
PROJECT = python
|
||||
VERSION = 2.6.9
|
||||
|
||||
PWD := $(shell pwd)
|
||||
|
||||
ifeq ($(MAKECMDGOALS),)
|
||||
MAKECMDGOALS = no_target
|
||||
endif
|
||||
ifneq ($(filter no_target install,$(MAKECMDGOALS)),)
|
||||
ifndef DSTROOT
|
||||
ifdef DESTDIR
|
||||
export DSTROOT := $(shell mkdir -p '$(DESTDIR)' && echo '$(DESTDIR)')
|
||||
else
|
||||
export DSTROOT := /
|
||||
endif
|
||||
endif
|
||||
ifndef OBJROOT
|
||||
export OBJROOT := $(shell mkdir -p '$(PWD)/OBJROOT' && echo '$(PWD)/OBJROOT')
|
||||
endif
|
||||
ifndef SYMROOT
|
||||
export SYMROOT := $(shell mkdir -p '$(PWD)/SYMROOT' && echo '$(PWD)/SYMROOT')
|
||||
endif
|
||||
endif
|
||||
|
||||
ifndef SRCROOT
|
||||
export SRCROOT := $(PWD)
|
||||
endif
|
||||
ifndef RC_ARCHS
|
||||
export RC_ARCHS := $(shell arch)
|
||||
export RC_$(RC_ARCHS) := YES
|
||||
endif
|
||||
ifndef RC_CFLAGS
|
||||
export RC_CFLAGS := $(foreach A,$(RC_ARCHS),-arch $(A)) $(RC_NONARCH_CFLAGS)
|
||||
endif
|
||||
ifndef RC_NONARCH_CFLAGS
|
||||
export RC_NONARCH_CFLAGS = -pipe
|
||||
endif
|
||||
ifndef RC_ProjectName
|
||||
export RC_ProjectName = $(PROJECT)
|
||||
endif
|
||||
|
||||
NAME = Python
|
||||
export PYTHON_CURRENT_VERSION = $(shell echo $(VERSION) | sed 's/[a-z].*$$//')
|
||||
NAMEVERS = $(NAME)-$(VERSION)
|
||||
TARBALL = $(NAMEVERS).tar.xz
|
||||
FIX = '$(OBJROOT)/fix'
|
||||
|
||||
VERS := $(shell echo $(VERSION) | sed 's/\(^[0-9]*\.[0-9]*\).*/\1/')
|
||||
FRAMEWORKS = /System/Library/Frameworks
|
||||
PYFRAMEWORK = $(FRAMEWORKS)/Python.framework
|
||||
VERSIONSVERS = $(PYFRAMEWORK)/Versions/$(VERS)
|
||||
INCLUDEPYTHONVERS = $(VERSIONSVERS)/include/$(PROJECT)$(VERS)
|
||||
LIBPYTHONVERS = $(VERSIONSVERS)/lib/$(PROJECT)$(VERS)
|
||||
|
||||
DYLIB = lib$(PROJECT)$(VERS).dylib
|
||||
USRINCLUDE = /usr/include
|
||||
USRLIB = /usr/lib
|
||||
EXTRAS = $(VERSIONSVERS)/Extras
|
||||
LIBRARYPYTHON = /Library/Python/$(VERS)
|
||||
SITEPACKAGES = $(LIBRARYPYTHON)/site-packages
|
||||
|
||||
EXTRASPYTHON = '$(DSTROOT)$(EXTRAS)/lib/python'
|
||||
PYTHON = '$(OBJROOT)/$(PROJECT)/$(PROJECT).exe'
|
||||
PYTHONENV = DYLD_FRAMEWORK_PATH='$(DSTROOT)$(FRAMEWORKS)' DYLD_NEW_LOCAL_SHARED_REGIONS=1 PYTHONPATH='$(DSTROOT)$(LIBPYTHONVERS)':$(EXTRASPYTHON)
|
||||
PYDTRACE_H = $(OBJROOT)/$(PROJECT)/Python/pydtrace.h
|
||||
|
||||
no_target: python
|
||||
|
||||
python: $(OBJROOT)/$(PROJECT)
|
||||
DSTROOT='$(DSTROOT)' OBJROOT='$(OBJROOT)/$(PROJECT)' \
|
||||
SRCROOT='$(OBJROOT)' SYMROOT='$(SYMROOT)' RC_ARCHS='$(RC_ARCHS)' \
|
||||
DYLD_NEW_LOCAL_SHARED_REGIONS=1 \
|
||||
$(MAKE) -C '$(OBJROOT)' -f Makefile \
|
||||
DSTROOT='$(DSTROOT)' OBJROOT='$(OBJROOT)/$(PROJECT)' \
|
||||
SRCROOT='$(OBJROOT)' SYMROOT='$(SYMROOT)' RC_ARCHS='$(RC_ARCHS)' \
|
||||
VERS=$(VERS)
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
# We patch configure to remove the "-arch_only ppc" option, since we
|
||||
# build fat. We also set DYLD_NEW_LOCAL_SHARED_REGIONS or else python.exe
|
||||
# will crash. And patch unixccompiler for wxWidgets (submit back to python).
|
||||
#
|
||||
# autoconf is now (normally) unavailable. So we save the output of autoconf
|
||||
# in fix/autoconf and use it to overwrite the original files. If we need
|
||||
# to update the version of python, we will need to install autoconf, and then
|
||||
# we run:
|
||||
#
|
||||
# % make `pwd`/python OBJROOT=`pwd` PYTHON_AUTOCONF=NO
|
||||
# % mv python python.bak
|
||||
# % make `pwd`/python OBJROOT=`pwd` PYTHON_AUTOCONF=YES
|
||||
# % diff -r --brief python.bak python
|
||||
#
|
||||
# Make a tarball out of the differences and put in $(FIX)/autoconf.tar.bz2
|
||||
##---------------------------------------------------------------------
|
||||
defarchflags = $(foreach u,$(RC_ARCHS),-arch $(u))
|
||||
|
||||
$(OBJROOT)/$(PROJECT):
|
||||
@set -x && \
|
||||
cd '$(OBJROOT)' && \
|
||||
tar -xof $(TARBALL) && \
|
||||
rm -rf $(PROJECT) && \
|
||||
mv $(NAMEVERS) $(PROJECT) && \
|
||||
ed - $(PROJECT)/Include/py_curses.h < $(FIX)/py_curses.h.ed && \
|
||||
ed - $(PROJECT)/Include/pymactoolbox.h < $(FIX)/pymactoolbox.h.ed && \
|
||||
ed - $(PROJECT)/Lib/ctypes/__init__.py < $(FIX)/Lib_ctypes___init__.py.ed && \
|
||||
ed - $(PROJECT)/Lib/xml/__init__.py < $(FIX)/Lib_xml___init__.py.ed && \
|
||||
ed - $(PROJECT)/Lib/distutils/command/install.py < $(FIX)/install.py.ed && \
|
||||
ed - $(PROJECT)/Lib/distutils/config.py < $(FIX)/Lib_distutils_config.py.ed && \
|
||||
sed 's/@DEFARCHFLAGS@/$(defarchflags)/' $(FIX)/sysconfig.py.ed | ed - $(PROJECT)/Lib/distutils/sysconfig.py && \
|
||||
ed - $(PROJECT)/Lib/distutils/unixccompiler.py < $(FIX)/unixccompiler.py.ed && \
|
||||
ed - $(PROJECT)/Lib/distutils/util.py < $(FIX)/Lib_distutils_util.py.ed && \
|
||||
ed - $(PROJECT)/Lib/locale.py < $(FIX)/locale.py.ed && \
|
||||
ed - $(PROJECT)/Lib/logging/handlers.py < $(FIX)/Lib_logging_handlers.py.ed && \
|
||||
ed - $(PROJECT)/Lib/os.py < $(FIX)/Lib_os.py.ed && \
|
||||
ed - $(PROJECT)/Lib/plat-mac/bundlebuilder.py < $(FIX)/bundlebuilder.py.ed && \
|
||||
ed - $(PROJECT)/Lib/plat-mac/Carbon/AppleEvents.py < $(FIX)/AppleEvents.py.ed && \
|
||||
ed - $(PROJECT)/Lib/platform.py < $(FIX)/Lib_platform.py.ed && \
|
||||
ed - $(PROJECT)/Lib/pydoc.py < $(FIX)/pydoc.py.ed && \
|
||||
ed - $(PROJECT)/Lib/rlcompleter.py < $(FIX)/rlcompleter.py.ed && \
|
||||
ed - $(PROJECT)/Lib/site.py < $(FIX)/site.py.ed && \
|
||||
ed - $(PROJECT)/Lib/test/test__locale.py < $(FIX)/Lib_test_test__locale.py.ed && \
|
||||
ed - $(PROJECT)/Lib/test/test_httpservers.py < $(FIX)/Lib_test_test_httpservers.py.ed && \
|
||||
ed - $(PROJECT)/Lib/test/test_platform.py < $(FIX)/Lib_test_test_platform.py.ed && \
|
||||
ed - $(PROJECT)/Mac/Makefile.in < $(FIX)/Mac_Makefile.in.ed && \
|
||||
patch $(PROJECT)/Mac/Modules/cf/_CFmodule.c $(FIX)/_CFmodule.c.patch && \
|
||||
ed - $(PROJECT)/Mac/Modules/cg/_CGmodule.c < $(FIX)/_CGmodule.c.ed && \
|
||||
ed - $(PROJECT)/Mac/Tools/pythonw.c < $(FIX)/pythonw.c.ed && \
|
||||
ed - $(PROJECT)/Makefile.pre.in < $(FIX)/Makefile.pre.in.ed && \
|
||||
patch $(PROJECT)/Misc/python.man $(FIX)/python.man.patch && \
|
||||
ed - $(PROJECT)/Modules/_cursesmodule.c < $(FIX)/_cursesmodule.c.ed && \
|
||||
ed - $(PROJECT)/Modules/dlmodule.c < $(FIX)/dlmodule.c.ed && \
|
||||
ed - $(PROJECT)/Modules/errnomodule.c < $(FIX)/errnomodule.c.ed && \
|
||||
rm $(PROJECT)/Modules/expat/expat.h $(PROJECT)/Modules/expat/expat_external.h && \
|
||||
ed - $(PROJECT)/Modules/getpath.c < $(FIX)/getpath.c.ed && \
|
||||
ed - $(PROJECT)/Modules/_localemodule.c < $(FIX)/_localemodule.c.ed && \
|
||||
ed - $(PROJECT)/Modules/posixmodule.c < $(FIX)/posixmodule.c.ed && \
|
||||
ed - $(PROJECT)/Modules/pwdmodule.c < $(FIX)/pwdmodule.c.ed && \
|
||||
ed - $(PROJECT)/Modules/pyexpat.c < $(FIX)/Modules_pyexpat.c.ed && \
|
||||
sed 's/@VERSION@/$(VERS)/' $(FIX)/python.c.ed | ed - $(PROJECT)/Modules/python.c && \
|
||||
ed - $(PROJECT)/Modules/readline.c < $(FIX)/readline.c.ed && \
|
||||
ex - $(PROJECT)/Modules/selectmodule.c < $(FIX)/selectmodule.c.ex && \
|
||||
patch $(PROJECT)/Objects/bufferobject.c $(FIX)/bufferobject.c.patch && \
|
||||
ed - $(PROJECT)/pyconfig.h.in < $(FIX)/pyconfig.h.in.ed && \
|
||||
ed - $(PROJECT)/Python/ceval.c < $(FIX)/ceval.c.ed && \
|
||||
ed - $(PROJECT)/Python/dynload_shlib.c < $(FIX)/dynload_shlib.c.ed && \
|
||||
ed - $(PROJECT)/Python/mactoolboxglue.c < $(FIX)/mactoolboxglue.c.ed && \
|
||||
patch $(PROJECT)/setup.py $(FIX)/setup.py-21106613.patch && \
|
||||
ed - $(PROJECT)/setup.py < $(FIX)/setup.py.ed && \
|
||||
for i in `find $(PROJECT)/Mac -name setup.py | xargs fgrep -l "'-framework', 'Carbon'"`; do \
|
||||
ed - $$i < $(FIX)/Mac_setup.py.ed || exit 1; \
|
||||
done && \
|
||||
for i in `find $(PROJECT)/Lib -name __init__.py -size 0c`; do \
|
||||
echo '#' > $$i; \
|
||||
done && \
|
||||
echo > $(PROJECT)/Lib/test/nullcert.pem
|
||||
ifdef PYTHON_AUTOCONF
|
||||
@set -x && \
|
||||
cd '$(OBJROOT)' && \
|
||||
ed - $(PROJECT)/configure.in < $(FIX)/configure.in.ed
|
||||
ifeq ($(PYTHON_AUTOCONF),YES)
|
||||
cd '$(OBJROOT)/$(PROJECT)' && autoconf
|
||||
endif
|
||||
else # !PYTHON_AUTOCONF
|
||||
tar -xof $(FIX)/autoconf.tar.bz2 -C '$(OBJROOT)/$(PROJECT)'
|
||||
endif
|
||||
dtrace -h -s $(FIX)/pydtrace.d -o '$(PYDTRACE_H)'
|
||||
|
||||
install: installpython
|
||||
install $(FIX)/audiotest.au $(DSTROOT)$(LIBPYTHONVERS)/email/test/data/audiotest.au
|
||||
install $(FIX)/audiotest.au $(DSTROOT)$(LIBPYTHONVERS)/test/audiotest.au
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
# PR-3478215 - for backwards compatibility with non-framework python, we
|
||||
# create symbolic links in /usr/include and /usr/lib. We now create the
|
||||
# links w.r.t. multiple versioning. In addition, the PYTHON_DEFAULT
|
||||
# environment variable will be set to YES if this version is the default
|
||||
# version of python.
|
||||
##---------------------------------------------------------------------
|
||||
installpython: $(OBJROOT)/$(PROJECT)
|
||||
install -d '$(DSTROOT)/usr/bin'
|
||||
DSTROOT='$(DSTROOT)' OBJROOT='$(OBJROOT)/$(PROJECT)' \
|
||||
SRCROOT='$(OBJROOT)' SYMROOT='$(SYMROOT)' RC_ARCHS='$(RC_ARCHS)' \
|
||||
DYLD_NEW_LOCAL_SHARED_REGIONS=1 \
|
||||
$(MAKE) -C '$(OBJROOT)' -f Makefile install \
|
||||
DSTROOT='$(DSTROOT)' OBJROOT='$(OBJROOT)/$(PROJECT)' \
|
||||
SRCROOT='$(OBJROOT)' SYMROOT='$(SYMROOT)' RC_ARCHS='$(RC_ARCHS)' \
|
||||
VERS=$(VERS)
|
||||
@obj= && \
|
||||
install -d '$(DSTROOT)$(USRINCLUDE)'
|
||||
ln -sf ../..$(INCLUDEPYTHONVERS) '$(DSTROOT)$(USRINCLUDE)/$(PROJECT)$(VERS)'
|
||||
install -d '$(DSTROOT)$(USRLIB)'
|
||||
ln -sf ../..$(LIBPYTHONVERS) '$(DSTROOT)$(USRLIB)/$(PROJECT)$(VERS)'
|
||||
ln -sf ../..$(VERSIONSVERS)/Python '$(DSTROOT)$(USRLIB)/$(DYLIB)'
|
||||
ifeq ($(PYTHON_DEFAULT),YES)
|
||||
ln -sf $(DYLIB) '$(DSTROOT)$(USRLIB)/lib$(PROJECT).dylib'
|
||||
endif
|
||||
install -d '$(DSTROOT)$(SITEPACKAGES)'
|
||||
|
||||
.DEFAULT:
|
||||
@$(MAKE) -f Makefile $@
|
172
2.6/Makefile
172
2.6/Makefile
@ -1,172 +0,0 @@
|
||||
##
|
||||
# Makefile for python
|
||||
##
|
||||
|
||||
Project = python
|
||||
Extra_Configure_Flags = --enable-ipv6 --with-threads --enable-framework=/System/Library/Frameworks --enable-toolbox-glue --enable-dtrace --with-system-ffi
|
||||
# Define the environment variable DEBUG to YES, to build without optimization
|
||||
ifeq ($(DEBUG),YES)
|
||||
Extra_Configure_Flags += --with-pydebug
|
||||
endif
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
# Extra_CC_Flags and Extra_LD_Flags are needed because CFLAGS gets overridden
|
||||
# by the RC_* variables. These values would normally be set by the default
|
||||
# python Makefile
|
||||
##---------------------------------------------------------------------
|
||||
Extra_CC_Flags += -fno-common -fno-strict-aliasing -fwrapv -DENABLE_DTRACE -DMACOSX -DNDEBUG -Wall -Wstrict-prototypes -Wshorten-64-to-32
|
||||
Extra_LD_Flags += -Wl,-F.
|
||||
Extra_Install_Flags = DESTDIR='$(DSTROOT)'
|
||||
GnuAfterInstall = fixup-after-install install-plist
|
||||
Extra_Environment = CCSHARED='$(RC_CFLAGS)'
|
||||
|
||||
# It's a GNU Source project
|
||||
include $(MAKEFILEPATH)/CoreOS/ReleaseControl/GNUSource.make
|
||||
|
||||
# Override compiler setting from GNUSource.make to use those set in GNUmakefile
|
||||
override CC = $(MY_CC)
|
||||
override CXX = $(MY_CXX)
|
||||
|
||||
Install_Flags := $(shell echo $(Install_Flags) | sed 's/prefix=[^ ]* *//')
|
||||
Install_Target = frameworkinstall
|
||||
|
||||
FIX = '$(SRCROOT)/fix'
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
# Patch Makefiles and pyconfig.h just after running configure
|
||||
##---------------------------------------------------------------------
|
||||
ConfigStamp2 = $(ConfigStamp)2
|
||||
|
||||
configure:: $(ConfigStamp2)
|
||||
|
||||
$(ConfigStamp2): $(ConfigStamp)
|
||||
ed - '$(OBJROOT)/Makefile' < $(FIX)/Makefile.ed
|
||||
ed - '$(OBJROOT)/pyconfig.h' < $(FIX)/pyconfig.ed
|
||||
$(TOUCH) $(ConfigStamp2)
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
# Fixup a lot of problems after the install
|
||||
##---------------------------------------------------------------------
|
||||
APPS = /Applications
|
||||
USRBIN = /usr/bin
|
||||
PYTHONAPPNAME = Python.app
|
||||
FRAMEWORKS = /System/Library/Frameworks
|
||||
PYFRAMEWORK = $(FRAMEWORKS)/Python.framework
|
||||
VERSIONSVERS = $(PYFRAMEWORK)/Versions/$(VERS)
|
||||
RESOURCESVERS = $(VERSIONSVERS)/Resources
|
||||
LIBPYTHONVERS = $(VERSIONSVERS)/lib/python$(VERS)
|
||||
PYTHONAPP = $(RESOURCESVERS)/$(PYTHONAPPNAME)
|
||||
PACONTENTS = $(PYTHONAPP)/Contents
|
||||
PAMACOS = $(PACONTENTS)/MacOS
|
||||
RUNPYTHON = DYLD_FRAMEWORK_PATH='$(OBJROOT)' '$(OBJROOT)/python.exe'
|
||||
BYTE2UTF16 = $(RUNPYTHON) $(FIX)/byte2utf16.py
|
||||
UTF162BYTE = $(RUNPYTHON) $(FIX)/utf162byte.py
|
||||
|
||||
fixup-after-install: delete-stuff \
|
||||
strip-installed-files \
|
||||
fix-PInfo \
|
||||
fix-paths \
|
||||
fix-usr-local-bin \
|
||||
fix-usr-bin \
|
||||
fix-permissions \
|
||||
fix-config-Makefile \
|
||||
additional-man-pages
|
||||
|
||||
# We leave "Build Applet.app" in $(APPS) to be deleted, because it uses
|
||||
# Carbon, and doesn't work in 64-bit. We also leave "Python Launcher.app"
|
||||
# in $(APPS) to be deleted (10692664).
|
||||
delete-stuff:
|
||||
rm -rf '$(DSTROOT)/usr/local' '$(DSTROOT)$(APPS)'
|
||||
|
||||
# We now need to create the .dSYM bundles ourselves
|
||||
# ($(DSTROOT)$(PYTHONAPP) is already stripped, so copy an unstripped binary)
|
||||
strip-installed-files:
|
||||
ditto '$(DSTROOT)$(PYTHONAPP)' '$(SYMROOT)/$(PYTHONAPPNAME)'
|
||||
ditto '$(OBJROOT)/python.exe' '$(SYMROOT)/$(PYTHONAPPNAME)/Contents/MacOS/Python'
|
||||
$(DSYMUTIL) -o '$(SYMROOT)/$(PYTHONAPPNAME).dSYM' '$(SYMROOT)/$(PYTHONAPPNAME)/Contents/MacOS/Python'
|
||||
$(STRIP) -x '$(DSTROOT)$(PAMACOS)/Python'
|
||||
ditto '$(OBJROOT)/Python.framework' '$(SYMROOT)/Python.framework'
|
||||
$(DSYMUTIL) -o '$(SYMROOT)/Python.framework.dSYM' '$(SYMROOT)/Python.framework/Python'
|
||||
$(STRIP) -x '$(DSTROOT)$(VERSIONSVERS)/Python'
|
||||
ditto '$(DSTROOT)$(LIBPYTHONVERS)'/lib-dynload/*.so '$(SYMROOT)/lib-dynload/'
|
||||
cd '$(SYMROOT)/lib-dynload' && \
|
||||
for so in *.so; do \
|
||||
$(DSYMUTIL) $$so || exit 1; \
|
||||
done
|
||||
$(STRIP) -x '$(DSTROOT)$(LIBPYTHONVERS)'/lib-dynload/*.so
|
||||
|
||||
fix-PInfo:
|
||||
ed - '$(DSTROOT)$(RESOURCESVERS)/Info.plist' < $(FIX)/pinfo.ed
|
||||
|
||||
MAN1 = /usr/share/man/man1
|
||||
additional-man-pages:
|
||||
install -m 0644 $(FIX)/pydoc.1 '$(DSTROOT)$(MAN1)'
|
||||
install -m 0644 $(FIX)/pythonw.1 '$(DSTROOT)$(MAN1)'
|
||||
ln -sf pydoc.1 '$(DSTROOT)$(MAN1)/pydoc$(VERS).1'
|
||||
ln -sf python.1 '$(DSTROOT)$(MAN1)/python$(VERS).1'
|
||||
ln -sf pythonw.1 '$(DSTROOT)$(MAN1)/pythonw$(VERS).1'
|
||||
|
||||
PYDOC = $(USRBIN)/pydoc
|
||||
PYDOCORIG = $(VERSIONSVERS)/bin/pydoc
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
# The scripts exec $(VERSIONSVERS)/bin/python$(VERS), which execs
|
||||
# $(PAMACOS)/Python. We skip the extra exec by changing the scripts
|
||||
# to exec $(PAMACOS)/Python directly.
|
||||
##---------------------------------------------------------------------
|
||||
fix-paths:
|
||||
@set -x && \
|
||||
cd '$(DSTROOT)$(VERSIONSVERS)/bin' && \
|
||||
for i in `find . -type f | sed 's,^\./,,'`; do \
|
||||
if [ -n "`file $$i | fgrep script`" ]; then \
|
||||
ed - $$i < $(FIX)/skipextraexec.ed; \
|
||||
fi || exit 1; \
|
||||
done
|
||||
|
||||
CGIPY = $(LIBPYTHONVERS)/cgi.py
|
||||
fix-usr-local-bin:
|
||||
@set -x && \
|
||||
cd '$(DSTROOT)$(VERSIONSVERS)' && \
|
||||
patch -p0 < $(FIX)/usrlocalbin.patch && \
|
||||
$(RUNPYTHON) -c "from py_compile import compile;compile('$(DSTROOT)$(CGIPY)', dfile='$(CGIPY)', doraise=True)" && \
|
||||
$(RUNPYTHON) -O -c "from py_compile import compile;compile('$(DSTROOT)$(CGIPY)', dfile='$(CGIPY)', doraise=True)"
|
||||
|
||||
##---------------------------------------------------------------------
|
||||
# config/Makefile needs the following changes:
|
||||
# remove -arch xxx flags
|
||||
# 4144521 - correct LINKFORSHARED
|
||||
# 3488297 - point BINDIR to /usr/local/bin
|
||||
##---------------------------------------------------------------------
|
||||
INSTALLPY = $(LIBPYTHONVERS)/distutils/command/install.py
|
||||
fix-config-Makefile:
|
||||
ed - '$(DSTROOT)$(LIBPYTHONVERS)/config/Makefile' < $(FIX)/config_Makefile.ed
|
||||
|
||||
fix-usr-bin:
|
||||
@set -x && \
|
||||
cd '$(DSTROOT)$(USRBIN)' && \
|
||||
rm -f idle* && \
|
||||
for i in *; do \
|
||||
rm -f $$i && \
|
||||
ln -s ../..$(VERSIONSVERS)/bin/$$i || exit 1; \
|
||||
done
|
||||
|
||||
LIBRARYPYTHON = /Library/Python
|
||||
LIBRARYPYTHONVERS = $(LIBRARYPYTHON)/$(VERS)
|
||||
|
||||
fix-permissions:
|
||||
ifeq ($(shell id -u), 0)
|
||||
@set -x && \
|
||||
for i in Applications Developer Library; do \
|
||||
chgrp -Rf admin $(DSTROOT)/$$i && \
|
||||
chmod -Rf g+w $(DSTROOT)/$$i; \
|
||||
done
|
||||
endif
|
||||
|
||||
OSV = /usr/local/OpenSourceVersions
|
||||
OSL = /usr/local/OpenSourceLicenses
|
||||
|
||||
install-plist:
|
||||
$(MKDIR) '$(DSTROOT)$(OSV)'
|
||||
$(INSTALL_FILE) '$(SRCROOT)/$(Project).plist' '$(DSTROOT)$(OSV)/$(Project).plist'
|
||||
$(MKDIR) '$(DSTROOT)$(OSL)'
|
||||
$(INSTALL_FILE) '$(OBJROOT)/LICENSE' '$(DSTROOT)$(OSL)/$(Project).txt'
|
@ -1,322 +0,0 @@
|
||||
project(python26)
|
||||
|
||||
cmake_minimum_required(VERSION 2.4.0)
|
||||
|
||||
if(COMMAND cmake_policy)
|
||||
cmake_policy(SET CMP0003 NEW)
|
||||
cmake_policy(SET CMP0005 NEW)
|
||||
endif(COMMAND cmake_policy)
|
||||
|
||||
|
||||
add_definitions(-DMACOSX)
|
||||
add_definitions(-DNDEBUG -DHAVE_NDBM_H -DHAVE_SEM_OPEN -DOBJC2RUNTIME)
|
||||
|
||||
add_definitions(-DVERSION="2.6" -DPREFIX="/System/Library/Frameworks/Python.framework/Versions/2.6" -DSUFFIX="${BITS}")
|
||||
add_definitions(-DPLATFORM="darwin" -DPYTHONPATH=":plat-darwin:plat-mac:plat-mac/lib-scriptpackages:lib-tk:lib-old")
|
||||
|
||||
add_definitions(
|
||||
-w
|
||||
-nostdinc
|
||||
)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fwrapv")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Modules/_ctypes/libffi_osx/include
|
||||
)
|
||||
|
||||
set(python_sources
|
||||
Python/asdl.c
|
||||
Python/ast.c
|
||||
Python/atof.c
|
||||
Python/bltinmodule.c
|
||||
Python/ceval.c
|
||||
Python/codecs.c
|
||||
Python/compile.c
|
||||
Python/dup2.c
|
||||
Python/dynload_shlib.c
|
||||
Python/errors.c
|
||||
Python/formatter_string.c
|
||||
Python/formatter_unicode.c
|
||||
Python/frozen.c
|
||||
Python/frozenmain.c
|
||||
Python/future.c
|
||||
Python/getargs.c
|
||||
Python/getcompiler.c
|
||||
Python/getcopyright.c
|
||||
Python/getmtime.c
|
||||
Python/getopt.c
|
||||
Python/getplatform.c
|
||||
Python/getversion.c
|
||||
Python/graminit.c
|
||||
Python/import.c
|
||||
Python/importdl.c
|
||||
# Python/mactoolboxglue.c # Needs Carbon and similar stuff
|
||||
Python/marshal.c
|
||||
Python/modsupport.c
|
||||
Python/mysnprintf.c
|
||||
Python/mystrtoul.c
|
||||
Python/peephole.c
|
||||
Python/pyarena.c
|
||||
Python/pyfpe.c
|
||||
Python/pymath.c
|
||||
Python/pystate.c
|
||||
Python/pystrcmp.c
|
||||
Python/pystrtod.c
|
||||
Python/Python-ast.c
|
||||
Python/pythonrun.c
|
||||
Python/random.c
|
||||
#Python/sigcheck.c
|
||||
Python/strdup.c
|
||||
Python/strtod.c
|
||||
Python/structmember.c
|
||||
Python/symtable.c
|
||||
Python/sysmodule.c
|
||||
Python/thread.c
|
||||
Python/traceback.c
|
||||
Python/_warnings.c
|
||||
|
||||
Parser/acceler.c
|
||||
Parser/bitset.c
|
||||
Parser/firstsets.c
|
||||
Parser/grammar1.c
|
||||
Parser/grammar.c
|
||||
#Parser/intrcheck.c
|
||||
Parser/listnode.c
|
||||
Parser/metagrammar.c
|
||||
Parser/myreadline.c
|
||||
Parser/node.c
|
||||
Parser/parser.c
|
||||
Parser/parsetok.c
|
||||
Parser/pgen.c
|
||||
#Parser/pgenmain.c
|
||||
Parser/printgrammar.c
|
||||
Parser/tokenizer.c
|
||||
#Parser/tokenizer_pgen.c
|
||||
|
||||
Objects/abstract.c
|
||||
Objects/boolobject.c
|
||||
Objects/bufferobject.c
|
||||
Objects/bytearrayobject.c
|
||||
Objects/bytes_methods.c
|
||||
Objects/cellobject.c
|
||||
Objects/classobject.c
|
||||
Objects/cobject.c
|
||||
Objects/codeobject.c
|
||||
Objects/complexobject.c
|
||||
Objects/descrobject.c
|
||||
Objects/dictobject.c
|
||||
Objects/enumobject.c
|
||||
Objects/exceptions.c
|
||||
Objects/fileobject.c
|
||||
Objects/floatobject.c
|
||||
Objects/frameobject.c
|
||||
Objects/funcobject.c
|
||||
Objects/genobject.c
|
||||
Objects/intobject.c
|
||||
Objects/iterobject.c
|
||||
Objects/listobject.c
|
||||
Objects/longobject.c
|
||||
Objects/methodobject.c
|
||||
Objects/moduleobject.c
|
||||
Objects/object.c
|
||||
Objects/obmalloc.c
|
||||
Objects/rangeobject.c
|
||||
Objects/setobject.c
|
||||
Objects/sliceobject.c
|
||||
Objects/stringobject.c
|
||||
Objects/structseq.c
|
||||
Objects/tupleobject.c
|
||||
Objects/typeobject.c
|
||||
Objects/unicodectype.c
|
||||
Objects/unicodeobject.c
|
||||
Objects/weakrefobject.c
|
||||
|
||||
Modules/gcmodule.c
|
||||
Modules/getpath.c
|
||||
Modules/config.c
|
||||
Modules/threadmodule.c
|
||||
Modules/signalmodule.c
|
||||
Modules/posixmodule.c
|
||||
Modules/errnomodule.c
|
||||
Modules/pwdmodule.c
|
||||
Modules/_sre.c
|
||||
Modules/_codecsmodule.c
|
||||
Modules/zipimport.c
|
||||
Modules/symtablemodule.c
|
||||
Modules/getbuildinfo.c
|
||||
Modules/xxsubtype.c
|
||||
)
|
||||
|
||||
set(DYLIB_COMPAT_VERSION "2.6.0")
|
||||
set(DYLIB_CURRENT_VERSION "2.6.9")
|
||||
add_framework(Python
|
||||
FAT
|
||||
SOURCES
|
||||
${python_sources}
|
||||
VERSION "2.6"
|
||||
DEPENDENCIES
|
||||
system
|
||||
)
|
||||
unset(DYLIB_COMPAT_VERSION)
|
||||
unset(DYLIB_CURRENT_VERSION)
|
||||
|
||||
include(darling_exe)
|
||||
include(darling_bundle)
|
||||
include(InstallSymlink)
|
||||
|
||||
add_darling_executable(python26exe Modules/main.c Modules/python.c)
|
||||
target_link_libraries(python26exe Python_2.6)
|
||||
set_target_properties(python26exe PROPERTIES OUTPUT_NAME python2.6)
|
||||
make_fat(python26exe)
|
||||
|
||||
install(TARGETS python26exe DESTINATION libexec/darling/System/Library/Frameworks/Python.framework/Versions/2.6/bin)
|
||||
install(FILES python2.6 DESTINATION libexec/darling/usr/bin)
|
||||
|
||||
function(pymodule modname)
|
||||
foreach(f IN LISTS ARGN)
|
||||
set(files ${files} ${f})
|
||||
endforeach(f)
|
||||
|
||||
add_darling_bundle("py26_${modname}" "${CMAKE_CURRENT_BINARY_DIR}/python2.6" ${files})
|
||||
target_link_libraries("py26_${modname}" system) # Python_2.6)
|
||||
|
||||
set_property(TARGET "py26_${modname}" APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-flat_namespace ")
|
||||
set_target_properties("py26_${modname}" PROPERTIES OUTPUT_NAME ${modname}
|
||||
PREFIX ""
|
||||
SUFFIX ".so")
|
||||
make_fat("py26_${modname}")
|
||||
add_dependencies("py26_${modname}" python26exe)
|
||||
|
||||
install(TARGETS "py26_${modname}" DESTINATION libexec/darling/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/lib-dynload)
|
||||
endfunction(pymodule)
|
||||
|
||||
set(sqlite_sources
|
||||
Modules/_sqlite/cache.c
|
||||
Modules/_sqlite/connection.c
|
||||
Modules/_sqlite/cursor.c
|
||||
Modules/_sqlite/microprotocols.c
|
||||
Modules/_sqlite/module.c
|
||||
Modules/_sqlite/prepare_protocol.c
|
||||
Modules/_sqlite/row.c
|
||||
Modules/_sqlite/statement.c
|
||||
Modules/_sqlite/util.c
|
||||
)
|
||||
|
||||
pymodule(zlib Modules/zlibmodule.c)
|
||||
target_link_libraries(py26_zlib z)
|
||||
pymodule(unicodedata Modules/unicodedata.c)
|
||||
pymodule(time Modules/timemodule.c)
|
||||
pymodule(termios Modules/termios.c)
|
||||
pymodule(syslog Modules/syslogmodule.c)
|
||||
pymodule(strop Modules/stropmodule.c)
|
||||
pymodule(select Modules/selectmodule.c)
|
||||
pymodule(resource Modules/resource.c)
|
||||
pymodule(readline Modules/readline.c)
|
||||
target_link_libraries(py26_readline ncurses edit)
|
||||
pymodule(pyexpat Modules/pyexpat.c)
|
||||
target_link_libraries(py26_pyexpat expat)
|
||||
pymodule(parser Modules/parsermodule.c)
|
||||
pymodule(operator Modules/operator.c)
|
||||
#pymodule(nis Modules/nismodule.c)
|
||||
pymodule(mmap Modules/mmapmodule.c)
|
||||
pymodule(math Modules/mathmodule.c)
|
||||
pymodule(itertools Modules/itertoolsmodule.c)
|
||||
pymodule(imageop Modules/imageop.c)
|
||||
pymodule(grp Modules/grpmodule.c)
|
||||
pymodule(future_builtins Modules/future_builtins.c)
|
||||
pymodule(fcntl Modules/fcntlmodule.c)
|
||||
pymodule(dl Modules/dlmodule.c)
|
||||
pymodule(dbm Modules/dbmmodule.c)
|
||||
pymodule(datetime Modules/datetimemodule.c Modules/timemodule.c)
|
||||
pymodule(crypt Modules/cryptmodule.c)
|
||||
pymodule(cmath Modules/cmathmodule.c)
|
||||
pymodule(cStringIO Modules/cStringIO.c)
|
||||
pymodule(cPickle Modules/cPickle.c)
|
||||
pymodule(bz2 Modules/bz2module.c)
|
||||
target_link_libraries(py26_bz2 bz2)
|
||||
pymodule(bsddb185 Modules/bsddbmodule.c)
|
||||
pymodule(binascii Modules/binascii.c)
|
||||
pymodule(audioop Modules/audioop.c)
|
||||
pymodule(array Modules/arraymodule.c)
|
||||
pymodule(_bisect Modules/_bisectmodule.c)
|
||||
pymodule(_bytesio Modules/_bytesio.c)
|
||||
pymodule(_collections Modules/_collectionsmodule.c)
|
||||
pymodule(_csv Modules/_csv.c)
|
||||
pymodule(_ctypes Modules/_ctypes/callbacks.c Modules/_ctypes/callproc.c Modules/_ctypes/cfield.c Modules/_ctypes/_ctypes.c Modules/_ctypes/malloc_closure.c Modules/_ctypes/stgdict.c Modules/_ctypes/darwin/dlfcn_simple.c
|
||||
Modules/_ctypes/libffi_osx/ffi.c Modules/_ctypes/libffi_osx/x86/darwin64.S Modules/_ctypes/libffi_osx/x86/x86-darwin.S Modules/_ctypes/libffi_osx/x86/x86-ffi64.c Modules/_ctypes/libffi_osx/x86/x86-ffi_darwin.c)
|
||||
pymodule(_ctypes_test Modules/_ctypes/_ctypes_test.c)
|
||||
pymodule(_curses_panel Modules/_curses_panel.c)
|
||||
target_link_libraries(py26__curses_panel ncurses panel)
|
||||
pymodule(_elementtree Modules/_elementtree.c) # USE_PYEXPAT_CAPI
|
||||
set_target_properties(py26__elementtree PROPERTIES COMPILE_FLAGS "-DUSE_PYEXPAT_CAPI")
|
||||
pymodule(_fileio Modules/_fileio.c)
|
||||
pymodule(_functools Modules/_functoolsmodule.c)
|
||||
pymodule(_hashlib Modules/_hashopenssl.c)
|
||||
target_link_libraries(py26__hashlib ssl098)
|
||||
target_include_directories(py26__hashlib BEFORE PRIVATE ${CMAKE_SOURCE_DIR}/src/external/openssl/src/include)
|
||||
pymodule(_heapq Modules/_heapqmodule.c)
|
||||
pymodule(_hotshot Modules/_hotshot.c)
|
||||
pymodule(_json Modules/_json.c)
|
||||
pymodule(_locale Modules/_localemodule.c)
|
||||
target_link_libraries(py26__locale CoreFoundation)
|
||||
pymodule(_lsprof Modules/_lsprof.c Modules/rotatingtree.c)
|
||||
pymodule(_multiprocessing Modules/_multiprocessing/multiprocessing.c Modules/_multiprocessing/semaphore.c Modules/_multiprocessing/socket_connection.c)
|
||||
pymodule(_random Modules/_randommodule.c)
|
||||
pymodule(_socket Modules/socketmodule.c)
|
||||
pymodule(_ssl Modules/_ssl.c)
|
||||
target_link_libraries(py26__ssl ssl098)
|
||||
target_include_directories(py26__ssl BEFORE PRIVATE ${CMAKE_SOURCE_DIR}/src/external/openssl/src/include)
|
||||
pymodule(_struct Modules/_struct.c)
|
||||
pymodule(_testcapi Modules/_testcapimodule.c)
|
||||
pymodule(_weakref Modules/_weakref.c)
|
||||
|
||||
pymodule(_sqlite ${sqlite_sources})
|
||||
target_link_libraries(py26__sqlite sqlite3)
|
||||
target_compile_definitions(py26__sqlite PRIVATE -DMODULE_NAME="sqlite3")
|
||||
|
||||
pymodule(_scproxy Mac/Modules/_scproxy.c)
|
||||
target_link_libraries(py26__scproxy SystemConfiguration)
|
||||
|
||||
function(install_lib subdir)
|
||||
file(GLOB py_files Lib/${subdir}/*.py)
|
||||
install(FILES ${py_files} DESTINATION libexec/darling/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/${subdir})
|
||||
|
||||
string(REGEX REPLACE "/" "_" target_name "py26_${subdir}")
|
||||
pyc("${target_name}" SOURCES ${py_files} DESTINATION libexec/darling/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/${subdir})
|
||||
endfunction(install_lib)
|
||||
|
||||
install_lib(.)
|
||||
install_lib(bsddb)
|
||||
install_lib(compiler)
|
||||
install_lib(ctypes)
|
||||
install_lib(ctypes/macholib)
|
||||
install_lib(curses)
|
||||
install_lib(distutils)
|
||||
install_lib(distutils/command)
|
||||
install_lib(email)
|
||||
install_lib(email/mime)
|
||||
install_lib(encodings)
|
||||
install_lib(hotshot)
|
||||
install_lib(importlib)
|
||||
install_lib(json)
|
||||
install_lib(logging)
|
||||
install_lib(multiprocessing)
|
||||
install_lib(multiprocessing/dummy)
|
||||
install_lib(plat-darwin)
|
||||
install_lib(plat-mac)
|
||||
install_lib(sqlite3)
|
||||
install_lib(wsgiref)
|
||||
install_lib(xml)
|
||||
install_lib(xml/dom)
|
||||
install_lib(xml/etree)
|
||||
install_lib(xml/parsers)
|
||||
install_lib(xml/sax)
|
||||
|
||||
install(FILES Lib/site-packages/README DESTINATION libexec/darling/Library/Python/2.6/site-packages)
|
||||
|
||||
set(EXENAME "/System/Library/Frameworks/Python.framework/Versions/2.6/bin/python2.6")
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Misc/python-config.in python-config)
|
||||
install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/python-config DESTINATION libexec/darling/usr/bin RENAME python2.6-config)
|
||||
|
@ -1,14 +0,0 @@
|
||||
#!/usr/local/bin/python
|
||||
|
||||
"""CGI test 1 - check server setup."""
|
||||
|
||||
# Until you get this to work, your web server isn't set up right or
|
||||
# your Python isn't set up right.
|
||||
|
||||
# If cgi0.sh works but cgi1.py doesn't, check the #! line and the file
|
||||
# permissions. The docs for the cgi.py module have debugging tips.
|
||||
|
||||
print "Content-type: text/html"
|
||||
print
|
||||
print "<h1>Hello world</h1>"
|
||||
print "<p>This is cgi1.py"
|
@ -1,22 +0,0 @@
|
||||
#!/usr/local/bin/python
|
||||
|
||||
"""CGI test 2 - basic use of cgi module."""
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
import cgi
|
||||
|
||||
def main():
|
||||
form = cgi.FieldStorage()
|
||||
print "Content-type: text/html"
|
||||
print
|
||||
if not form:
|
||||
print "<h1>No Form Keys</h1>"
|
||||
else:
|
||||
print "<h1>Form Keys</h1>"
|
||||
for key in form.keys():
|
||||
value = form[key].value
|
||||
print "<p>", cgi.escape(key), ":", cgi.escape(value)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,10 +0,0 @@
|
||||
#!/usr/local/bin/python
|
||||
|
||||
"""CGI test 3 (persistent data)."""
|
||||
|
||||
import cgitb; cgitb.enable()
|
||||
|
||||
from wiki import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,54 +0,0 @@
|
||||
# A simple vector class
|
||||
|
||||
|
||||
def vec(*v):
|
||||
return Vec(*v)
|
||||
|
||||
|
||||
class Vec:
|
||||
|
||||
def __init__(self, *v):
|
||||
self.v = list(v)
|
||||
|
||||
def fromlist(self, v):
|
||||
if not isinstance(v, list):
|
||||
raise TypeError
|
||||
self.v = v[:]
|
||||
return self
|
||||
|
||||
def __repr__(self):
|
||||
return 'vec(' + repr(self.v)[1:-1] + ')'
|
||||
|
||||
def __len__(self):
|
||||
return len(self.v)
|
||||
|
||||
def __getitem__(self, i):
|
||||
return self.v[i]
|
||||
|
||||
def __add__(self, other):
|
||||
# Element-wise addition
|
||||
v = map(lambda x, y: x+y, self, other)
|
||||
return Vec().fromlist(v)
|
||||
|
||||
def __sub__(self, other):
|
||||
# Element-wise subtraction
|
||||
v = map(lambda x, y: x-y, self, other)
|
||||
return Vec().fromlist(v)
|
||||
|
||||
def __mul__(self, scalar):
|
||||
# Multiply by scalar
|
||||
v = map(lambda x: x*scalar, self.v)
|
||||
return Vec().fromlist(v)
|
||||
|
||||
|
||||
|
||||
def test():
|
||||
a = vec(1, 2, 3)
|
||||
b = vec(3, 2, 1)
|
||||
print a
|
||||
print b
|
||||
print a+b
|
||||
print a-b
|
||||
print a*3.0
|
||||
|
||||
test()
|
@ -1,57 +0,0 @@
|
||||
# Makefile for embedded Python use demo.
|
||||
# (This version tailored for my Red Hat Linux 6.1 setup;
|
||||
# edit lines marked with XXX.)
|
||||
|
||||
# XXX The compiler you are using
|
||||
CC= gcc
|
||||
|
||||
# XXX Top of the build tree and source tree
|
||||
blddir= ../..
|
||||
srcdir= ../..
|
||||
|
||||
# Python version
|
||||
VERSION= 2.6
|
||||
|
||||
# Compiler flags
|
||||
OPT= -g
|
||||
INCLUDES= -I$(srcdir)/Include -I$(blddir)
|
||||
CFLAGS= $(OPT)
|
||||
CPPFLAGS= $(INCLUDES)
|
||||
|
||||
# The Python library
|
||||
LIBPYTHON= $(blddir)/libpython$(VERSION).a
|
||||
|
||||
# XXX edit LIBS (in particular) to match $(blddir)/Modules/Makefile
|
||||
LIBS= -lnsl -ldl -lreadline -ltermcap -lieee -lpthread -lutil
|
||||
LDFLAGS= -Xlinker -export-dynamic
|
||||
SYSLIBS= -lm
|
||||
MODLIBS=
|
||||
ALLLIBS= $(LIBPYTHON) $(MODLIBS) $(LIBS) $(SYSLIBS)
|
||||
|
||||
# Build the demo applications
|
||||
all: demo loop importexc
|
||||
demo: demo.o
|
||||
$(CC) $(LDFLAGS) demo.o $(ALLLIBS) -o demo
|
||||
|
||||
loop: loop.o
|
||||
$(CC) $(LDFLAGS) loop.o $(ALLLIBS) -o loop
|
||||
|
||||
importexc: importexc.o
|
||||
$(CC) $(LDFLAGS) importexc.o $(ALLLIBS) -o importexc
|
||||
|
||||
# Administrative targets
|
||||
|
||||
test: demo
|
||||
./demo
|
||||
|
||||
COMMAND="print 'hello world'"
|
||||
looptest: loop
|
||||
./loop $(COMMAND)
|
||||
|
||||
clean:
|
||||
-rm -f *.o core
|
||||
|
||||
clobber: clean
|
||||
-rm -f *~ @* '#'* demo loop importexc
|
||||
|
||||
realclean: clobber
|
@ -1,65 +0,0 @@
|
||||
/* Example of embedding Python in another program */
|
||||
|
||||
#include "Python.h"
|
||||
|
||||
void initxyzzy(void); /* Forward */
|
||||
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
/* Pass argv[0] to the Python interpreter */
|
||||
Py_SetProgramName(argv[0]);
|
||||
|
||||
/* Initialize the Python interpreter. Required. */
|
||||
Py_Initialize();
|
||||
|
||||
/* Add a static module */
|
||||
initxyzzy();
|
||||
|
||||
/* Define sys.argv. It is up to the application if you
|
||||
want this; you can also let it undefined (since the Python
|
||||
code is generally not a main program it has no business
|
||||
touching sys.argv...) */
|
||||
PySys_SetArgv(argc, argv);
|
||||
|
||||
/* Do some application specific code */
|
||||
printf("Hello, brave new world\n\n");
|
||||
|
||||
/* Execute some Python statements (in module __main__) */
|
||||
PyRun_SimpleString("import sys\n");
|
||||
PyRun_SimpleString("print sys.builtin_module_names\n");
|
||||
PyRun_SimpleString("print sys.modules.keys()\n");
|
||||
PyRun_SimpleString("print sys.executable\n");
|
||||
PyRun_SimpleString("print sys.argv\n");
|
||||
|
||||
/* Note that you can call any public function of the Python
|
||||
interpreter here, e.g. call_object(). */
|
||||
|
||||
/* Some more application specific code */
|
||||
printf("\nGoodbye, cruel world\n");
|
||||
|
||||
/* Exit, cleaning up the interpreter */
|
||||
Py_Exit(0);
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/* A static module */
|
||||
|
||||
/* 'self' is not used */
|
||||
static PyObject *
|
||||
xyzzy_foo(PyObject *self, PyObject* args)
|
||||
{
|
||||
return PyInt_FromLong(42L);
|
||||
}
|
||||
|
||||
static PyMethodDef xyzzy_methods[] = {
|
||||
{"foo", xyzzy_foo, METH_NOARGS,
|
||||
"Return the meaning of everything."},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
void
|
||||
initxyzzy(void)
|
||||
{
|
||||
PyImport_AddModule("xyzzy");
|
||||
Py_InitModule("xyzzy", xyzzy_methods);
|
||||
}
|
@ -1,248 +0,0 @@
|
||||
#
|
||||
# importers.py
|
||||
#
|
||||
# Demonstration subclasses of imputil.Importer
|
||||
#
|
||||
|
||||
# There should be consideration for the imports below if it is desirable
|
||||
# to have "all" modules be imported through the imputil system.
|
||||
|
||||
# these are C extensions
|
||||
import sys
|
||||
import imp
|
||||
import struct
|
||||
import marshal
|
||||
|
||||
# these are .py modules
|
||||
import imputil
|
||||
import os
|
||||
|
||||
######################################################################
|
||||
|
||||
_TupleType = type(())
|
||||
_StringType = type('')
|
||||
|
||||
######################################################################
|
||||
|
||||
# byte-compiled file suffic character
|
||||
_suffix_char = __debug__ and 'c' or 'o'
|
||||
|
||||
# byte-compiled file suffix
|
||||
_suffix = '.py' + _suffix_char
|
||||
|
||||
# the C_EXTENSION suffixes
|
||||
_c_suffixes = filter(lambda x: x[2] == imp.C_EXTENSION, imp.get_suffixes())
|
||||
|
||||
def _timestamp(pathname):
|
||||
"Return the file modification time as a Long."
|
||||
try:
|
||||
s = os.stat(pathname)
|
||||
except OSError:
|
||||
return None
|
||||
return long(s[8])
|
||||
|
||||
def _fs_import(dir, modname, fqname):
|
||||
"Fetch a module from the filesystem."
|
||||
|
||||
pathname = os.path.join(dir, modname)
|
||||
if os.path.isdir(pathname):
|
||||
values = { '__pkgdir__' : pathname, '__path__' : [ pathname ] }
|
||||
ispkg = 1
|
||||
pathname = os.path.join(pathname, '__init__')
|
||||
else:
|
||||
values = { }
|
||||
ispkg = 0
|
||||
|
||||
# look for dynload modules
|
||||
for desc in _c_suffixes:
|
||||
file = pathname + desc[0]
|
||||
try:
|
||||
fp = open(file, desc[1])
|
||||
except IOError:
|
||||
pass
|
||||
else:
|
||||
module = imp.load_module(fqname, fp, file, desc)
|
||||
values['__file__'] = file
|
||||
return 0, module, values
|
||||
|
||||
t_py = _timestamp(pathname + '.py')
|
||||
t_pyc = _timestamp(pathname + _suffix)
|
||||
if t_py is None and t_pyc is None:
|
||||
return None
|
||||
code = None
|
||||
if t_py is None or (t_pyc is not None and t_pyc >= t_py):
|
||||
file = pathname + _suffix
|
||||
f = open(file, 'rb')
|
||||
if f.read(4) == imp.get_magic():
|
||||
t = struct.unpack('<I', f.read(4))[0]
|
||||
if t == t_py:
|
||||
code = marshal.load(f)
|
||||
f.close()
|
||||
if code is None:
|
||||
file = pathname + '.py'
|
||||
code = _compile(file, t_py)
|
||||
|
||||
values['__file__'] = file
|
||||
return ispkg, code, values
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# Simple function-based importer
|
||||
#
|
||||
class FuncImporter(imputil.Importer):
|
||||
"Importer subclass to delegate to a function rather than method overrides."
|
||||
def __init__(self, func):
|
||||
self.func = func
|
||||
def get_code(self, parent, modname, fqname):
|
||||
return self.func(parent, modname, fqname)
|
||||
|
||||
def install_with(func):
|
||||
FuncImporter(func).install()
|
||||
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# Base class for archive-based importing
|
||||
#
|
||||
class PackageArchiveImporter(imputil.Importer):
|
||||
"""Importer subclass to import from (file) archives.
|
||||
|
||||
This Importer handles imports of the style <archive>.<subfile>, where
|
||||
<archive> can be located using a subclass-specific mechanism and the
|
||||
<subfile> is found in the archive using a subclass-specific mechanism.
|
||||
|
||||
This class defines two hooks for subclasses: one to locate an archive
|
||||
(and possibly return some context for future subfile lookups), and one
|
||||
to locate subfiles.
|
||||
"""
|
||||
|
||||
def get_code(self, parent, modname, fqname):
|
||||
if parent:
|
||||
# the Importer._finish_import logic ensures that we handle imports
|
||||
# under the top level module (package / archive).
|
||||
assert parent.__importer__ == self
|
||||
|
||||
# if a parent "package" is provided, then we are importing a
|
||||
# sub-file from the archive.
|
||||
result = self.get_subfile(parent.__archive__, modname)
|
||||
if result is None:
|
||||
return None
|
||||
if isinstance(result, _TupleType):
|
||||
assert len(result) == 2
|
||||
return (0,) + result
|
||||
return 0, result, {}
|
||||
|
||||
# no parent was provided, so the archive should exist somewhere on the
|
||||
# default "path".
|
||||
archive = self.get_archive(modname)
|
||||
if archive is None:
|
||||
return None
|
||||
return 1, "", {'__archive__':archive}
|
||||
|
||||
def get_archive(self, modname):
|
||||
"""Get an archive of modules.
|
||||
|
||||
This method should locate an archive and return a value which can be
|
||||
used by get_subfile to load modules from it. The value may be a simple
|
||||
pathname, an open file, or a complex object that caches information
|
||||
for future imports.
|
||||
|
||||
Return None if the archive was not found.
|
||||
"""
|
||||
raise RuntimeError, "get_archive not implemented"
|
||||
|
||||
def get_subfile(self, archive, modname):
|
||||
"""Get code from a subfile in the specified archive.
|
||||
|
||||
Given the specified archive (as returned by get_archive()), locate
|
||||
and return a code object for the specified module name.
|
||||
|
||||
A 2-tuple may be returned, consisting of a code object and a dict
|
||||
of name/values to place into the target module.
|
||||
|
||||
Return None if the subfile was not found.
|
||||
"""
|
||||
raise RuntimeError, "get_subfile not implemented"
|
||||
|
||||
|
||||
class PackageArchive(PackageArchiveImporter):
|
||||
"PackageArchiveImporter subclass that refers to a specific archive."
|
||||
|
||||
def __init__(self, modname, archive_pathname):
|
||||
self.__modname = modname
|
||||
self.__path = archive_pathname
|
||||
|
||||
def get_archive(self, modname):
|
||||
if modname == self.__modname:
|
||||
return self.__path
|
||||
return None
|
||||
|
||||
# get_subfile is passed the full pathname of the archive
|
||||
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# Emulate the standard directory-based import mechanism
|
||||
#
|
||||
class DirectoryImporter(imputil.Importer):
|
||||
"Importer subclass to emulate the standard importer."
|
||||
|
||||
def __init__(self, dir):
|
||||
self.dir = dir
|
||||
|
||||
def get_code(self, parent, modname, fqname):
|
||||
if parent:
|
||||
dir = parent.__pkgdir__
|
||||
else:
|
||||
dir = self.dir
|
||||
|
||||
# Return the module (and other info) if found in the specified
|
||||
# directory. Otherwise, return None.
|
||||
return _fs_import(dir, modname, fqname)
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s.%s for "%s" at 0x%x>' % (self.__class__.__module__,
|
||||
self.__class__.__name__,
|
||||
self.dir,
|
||||
id(self))
|
||||
|
||||
|
||||
######################################################################
|
||||
#
|
||||
# Emulate the standard path-style import mechanism
|
||||
#
|
||||
class PathImporter(imputil.Importer):
|
||||
def __init__(self, path=sys.path):
|
||||
self.path = path
|
||||
|
||||
def get_code(self, parent, modname, fqname):
|
||||
if parent:
|
||||
# we are looking for a module inside of a specific package
|
||||
return _fs_import(parent.__pkgdir__, modname, fqname)
|
||||
|
||||
# scan sys.path, looking for the requested module
|
||||
for dir in self.path:
|
||||
if isinstance(dir, _StringType):
|
||||
result = _fs_import(dir, modname, fqname)
|
||||
if result:
|
||||
return result
|
||||
|
||||
# not found
|
||||
return None
|
||||
|
||||
######################################################################
|
||||
|
||||
def _test_dir():
|
||||
"Debug/test function to create DirectoryImporters from sys.path."
|
||||
imputil.ImportManager().install()
|
||||
path = sys.path[:]
|
||||
path.reverse()
|
||||
for d in path:
|
||||
sys.path.insert(0, DirectoryImporter(d))
|
||||
sys.path.insert(0, imputil.BuiltinImporter())
|
||||
|
||||
def _test_revamp():
|
||||
"Debug/test function for the revamped import system."
|
||||
imputil.ImportManager().install()
|
||||
sys.path.insert(0, PathImporter())
|
||||
sys.path.insert(0, imputil.BuiltinImporter())
|
@ -1,126 +0,0 @@
|
||||
"""An Python re-implementation of hierarchical module import.
|
||||
|
||||
This code is intended to be read, not executed. However, it does work
|
||||
-- all you need to do to enable it is "import knee".
|
||||
|
||||
(The name is a pun on the klunkier predecessor of this module, "ni".)
|
||||
|
||||
"""
|
||||
|
||||
import sys, imp, __builtin__
|
||||
|
||||
|
||||
# Replacement for __import__()
|
||||
def import_hook(name, globals=None, locals=None, fromlist=None):
|
||||
parent = determine_parent(globals)
|
||||
q, tail = find_head_package(parent, name)
|
||||
m = load_tail(q, tail)
|
||||
if not fromlist:
|
||||
return q
|
||||
if hasattr(m, "__path__"):
|
||||
ensure_fromlist(m, fromlist)
|
||||
return m
|
||||
|
||||
def determine_parent(globals):
|
||||
if not globals or not globals.has_key("__name__"):
|
||||
return None
|
||||
pname = globals['__name__']
|
||||
if globals.has_key("__path__"):
|
||||
parent = sys.modules[pname]
|
||||
assert globals is parent.__dict__
|
||||
return parent
|
||||
if '.' in pname:
|
||||
i = pname.rfind('.')
|
||||
pname = pname[:i]
|
||||
parent = sys.modules[pname]
|
||||
assert parent.__name__ == pname
|
||||
return parent
|
||||
return None
|
||||
|
||||
def find_head_package(parent, name):
|
||||
if '.' in name:
|
||||
i = name.find('.')
|
||||
head = name[:i]
|
||||
tail = name[i+1:]
|
||||
else:
|
||||
head = name
|
||||
tail = ""
|
||||
if parent:
|
||||
qname = "%s.%s" % (parent.__name__, head)
|
||||
else:
|
||||
qname = head
|
||||
q = import_module(head, qname, parent)
|
||||
if q: return q, tail
|
||||
if parent:
|
||||
qname = head
|
||||
parent = None
|
||||
q = import_module(head, qname, parent)
|
||||
if q: return q, tail
|
||||
raise ImportError, "No module named " + qname
|
||||
|
||||
def load_tail(q, tail):
|
||||
m = q
|
||||
while tail:
|
||||
i = tail.find('.')
|
||||
if i < 0: i = len(tail)
|
||||
head, tail = tail[:i], tail[i+1:]
|
||||
mname = "%s.%s" % (m.__name__, head)
|
||||
m = import_module(head, mname, m)
|
||||
if not m:
|
||||
raise ImportError, "No module named " + mname
|
||||
return m
|
||||
|
||||
def ensure_fromlist(m, fromlist, recursive=0):
|
||||
for sub in fromlist:
|
||||
if sub == "*":
|
||||
if not recursive:
|
||||
try:
|
||||
all = m.__all__
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
ensure_fromlist(m, all, 1)
|
||||
continue
|
||||
if sub != "*" and not hasattr(m, sub):
|
||||
subname = "%s.%s" % (m.__name__, sub)
|
||||
submod = import_module(sub, subname, m)
|
||||
if not submod:
|
||||
raise ImportError, "No module named " + subname
|
||||
|
||||
def import_module(partname, fqname, parent):
|
||||
try:
|
||||
return sys.modules[fqname]
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
fp, pathname, stuff = imp.find_module(partname,
|
||||
parent and parent.__path__)
|
||||
except ImportError:
|
||||
return None
|
||||
try:
|
||||
m = imp.load_module(fqname, fp, pathname, stuff)
|
||||
finally:
|
||||
if fp: fp.close()
|
||||
if parent:
|
||||
setattr(parent, partname, m)
|
||||
return m
|
||||
|
||||
|
||||
# Replacement for reload()
|
||||
def reload_hook(module):
|
||||
name = module.__name__
|
||||
if '.' not in name:
|
||||
return import_module(name, name, None)
|
||||
i = name.rfind('.')
|
||||
pname = name[:i]
|
||||
parent = sys.modules[pname]
|
||||
return import_module(name[i+1:], name, parent)
|
||||
|
||||
|
||||
# Save the original hooks
|
||||
original_import = __builtin__.__import__
|
||||
original_reload = __builtin__.reload
|
||||
|
||||
# Now install our hooks
|
||||
__builtin__.__import__ = import_hook
|
||||
__builtin__.reload = reload_hook
|
@ -1,605 +0,0 @@
|
||||
<HTML>
|
||||
|
||||
<HEAD>
|
||||
<TITLE>Metaclasses in Python 1.5</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY BGCOLOR="FFFFFF">
|
||||
|
||||
<H1>Metaclasses in Python 1.5</H1>
|
||||
<H2>(A.k.a. The Killer Joke :-)</H2>
|
||||
|
||||
<HR>
|
||||
|
||||
(<i>Postscript:</i> reading this essay is probably not the best way to
|
||||
understand the metaclass hook described here. See a <A
|
||||
HREF="meta-vladimir.txt">message posted by Vladimir Marangozov</A>
|
||||
which may give a gentler introduction to the matter. You may also
|
||||
want to search Deja News for messages with "metaclass" in the subject
|
||||
posted to comp.lang.python in July and August 1998.)
|
||||
|
||||
<HR>
|
||||
|
||||
<P>In previous Python releases (and still in 1.5), there is something
|
||||
called the ``Don Beaudry hook'', after its inventor and champion.
|
||||
This allows C extensions to provide alternate class behavior, thereby
|
||||
allowing the Python class syntax to be used to define other class-like
|
||||
entities. Don Beaudry has used this in his infamous <A
|
||||
HREF="http://maigret.cog.brown.edu/pyutil/">MESS</A> package; Jim
|
||||
Fulton has used it in his <A
|
||||
HREF="http://www.digicool.com/releases/ExtensionClass/">Extension
|
||||
Classes</A> package. (It has also been referred to as the ``Don
|
||||
Beaudry <i>hack</i>,'' but that's a misnomer. There's nothing hackish
|
||||
about it -- in fact, it is rather elegant and deep, even though
|
||||
there's something dark to it.)
|
||||
|
||||
<P>(On first reading, you may want to skip directly to the examples in
|
||||
the section "Writing Metaclasses in Python" below, unless you want
|
||||
your head to explode.)
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P>Documentation of the Don Beaudry hook has purposefully been kept
|
||||
minimal, since it is a feature of incredible power, and is easily
|
||||
abused. Basically, it checks whether the <b>type of the base
|
||||
class</b> is callable, and if so, it is called to create the new
|
||||
class.
|
||||
|
||||
<P>Note the two indirection levels. Take a simple example:
|
||||
|
||||
<PRE>
|
||||
class B:
|
||||
pass
|
||||
|
||||
class C(B):
|
||||
pass
|
||||
</PRE>
|
||||
|
||||
Take a look at the second class definition, and try to fathom ``the
|
||||
type of the base class is callable.''
|
||||
|
||||
<P>(Types are not classes, by the way. See questions 4.2, 4.19 and in
|
||||
particular 6.22 in the <A
|
||||
HREF="http://www.python.org/cgi-bin/faqw.py" >Python FAQ</A>
|
||||
for more on this topic.)
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>The <b>base class</b> is B; this one's easy.<P>
|
||||
|
||||
<LI>Since B is a class, its type is ``class''; so the <b>type of the
|
||||
base class</b> is the type ``class''. This is also known as
|
||||
types.ClassType, assuming the standard module <code>types</code> has
|
||||
been imported.<P>
|
||||
|
||||
<LI>Now is the type ``class'' <b>callable</b>? No, because types (in
|
||||
core Python) are never callable. Classes are callable (calling a
|
||||
class creates a new instance) but types aren't.<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>So our conclusion is that in our example, the type of the base
|
||||
class (of C) is not callable. So the Don Beaudry hook does not apply,
|
||||
and the default class creation mechanism is used (which is also used
|
||||
when there is no base class). In fact, the Don Beaudry hook never
|
||||
applies when using only core Python, since the type of a core object
|
||||
is never callable.
|
||||
|
||||
<P>So what do Don and Jim do in order to use Don's hook? Write an
|
||||
extension that defines at least two new Python object types. The
|
||||
first would be the type for ``class-like'' objects usable as a base
|
||||
class, to trigger Don's hook. This type must be made callable.
|
||||
That's why we need a second type. Whether an object is callable
|
||||
depends on its type. So whether a type object is callable depends on
|
||||
<i>its</i> type, which is a <i>meta-type</i>. (In core Python there
|
||||
is only one meta-type, the type ``type'' (types.TypeType), which is
|
||||
the type of all type objects, even itself.) A new meta-type must
|
||||
be defined that makes the type of the class-like objects callable.
|
||||
(Normally, a third type would also be needed, the new ``instance''
|
||||
type, but this is not an absolute requirement -- the new class type
|
||||
could return an object of some existing type when invoked to create an
|
||||
instance.)
|
||||
|
||||
<P>Still confused? Here's a simple device due to Don himself to
|
||||
explain metaclasses. Take a simple class definition; assume B is a
|
||||
special class that triggers Don's hook:
|
||||
|
||||
<PRE>
|
||||
class C(B):
|
||||
a = 1
|
||||
b = 2
|
||||
</PRE>
|
||||
|
||||
This can be though of as equivalent to:
|
||||
|
||||
<PRE>
|
||||
C = type(B)('C', (B,), {'a': 1, 'b': 2})
|
||||
</PRE>
|
||||
|
||||
If that's too dense for you, here's the same thing written out using
|
||||
temporary variables:
|
||||
|
||||
<PRE>
|
||||
creator = type(B) # The type of the base class
|
||||
name = 'C' # The name of the new class
|
||||
bases = (B,) # A tuple containing the base class(es)
|
||||
namespace = {'a': 1, 'b': 2} # The namespace of the class statement
|
||||
C = creator(name, bases, namespace)
|
||||
</PRE>
|
||||
|
||||
This is analogous to what happens without the Don Beaudry hook, except
|
||||
that in that case the creator function is set to the default class
|
||||
creator.
|
||||
|
||||
<P>In either case, the creator is called with three arguments. The
|
||||
first one, <i>name</i>, is the name of the new class (as given at the
|
||||
top of the class statement). The <i>bases</i> argument is a tuple of
|
||||
base classes (a singleton tuple if there's only one base class, like
|
||||
the example). Finally, <i>namespace</i> is a dictionary containing
|
||||
the local variables collected during execution of the class statement.
|
||||
|
||||
<P>Note that the contents of the namespace dictionary is simply
|
||||
whatever names were defined in the class statement. A little-known
|
||||
fact is that when Python executes a class statement, it enters a new
|
||||
local namespace, and all assignments and function definitions take
|
||||
place in this namespace. Thus, after executing the following class
|
||||
statement:
|
||||
|
||||
<PRE>
|
||||
class C:
|
||||
a = 1
|
||||
def f(s): pass
|
||||
</PRE>
|
||||
|
||||
the class namespace's contents would be {'a': 1, 'f': <function f
|
||||
...>}.
|
||||
|
||||
<P>But enough already about writing Python metaclasses in C; read the
|
||||
documentation of <A
|
||||
HREF="http://maigret.cog.brown.edu/pyutil/">MESS</A> or <A
|
||||
HREF="http://www.digicool.com/papers/ExtensionClass.html" >Extension
|
||||
Classes</A> for more information.
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2>Writing Metaclasses in Python</H2>
|
||||
|
||||
<P>In Python 1.5, the requirement to write a C extension in order to
|
||||
write metaclasses has been dropped (though you can still do
|
||||
it, of course). In addition to the check ``is the type of the base
|
||||
class callable,'' there's a check ``does the base class have a
|
||||
__class__ attribute.'' If so, it is assumed that the __class__
|
||||
attribute refers to a class.
|
||||
|
||||
<P>Let's repeat our simple example from above:
|
||||
|
||||
<PRE>
|
||||
class C(B):
|
||||
a = 1
|
||||
b = 2
|
||||
</PRE>
|
||||
|
||||
Assuming B has a __class__ attribute, this translates into:
|
||||
|
||||
<PRE>
|
||||
C = B.__class__('C', (B,), {'a': 1, 'b': 2})
|
||||
</PRE>
|
||||
|
||||
This is exactly the same as before except that instead of type(B),
|
||||
B.__class__ is invoked. If you have read <A HREF=
|
||||
"http://www.python.org/cgi-bin/faqw.py?req=show&file=faq06.022.htp"
|
||||
>FAQ question 6.22</A> you will understand that while there is a big
|
||||
technical difference between type(B) and B.__class__, they play the
|
||||
same role at different abstraction levels. And perhaps at some point
|
||||
in the future they will really be the same thing (at which point you
|
||||
would be able to derive subclasses from built-in types).
|
||||
|
||||
<P>At this point it may be worth mentioning that C.__class__ is the
|
||||
same object as B.__class__, i.e., C's metaclass is the same as B's
|
||||
metaclass. In other words, subclassing an existing class creates a
|
||||
new (meta)inststance of the base class's metaclass.
|
||||
|
||||
<P>Going back to the example, the class B.__class__ is instantiated,
|
||||
passing its constructor the same three arguments that are passed to
|
||||
the default class constructor or to an extension's metaclass:
|
||||
<i>name</i>, <i>bases</i>, and <i>namespace</i>.
|
||||
|
||||
<P>It is easy to be confused by what exactly happens when using a
|
||||
metaclass, because we lose the absolute distinction between classes
|
||||
and instances: a class is an instance of a metaclass (a
|
||||
``metainstance''), but technically (i.e. in the eyes of the python
|
||||
runtime system), the metaclass is just a class, and the metainstance
|
||||
is just an instance. At the end of the class statement, the metaclass
|
||||
whose metainstance is used as a base class is instantiated, yielding a
|
||||
second metainstance (of the same metaclass). This metainstance is
|
||||
then used as a (normal, non-meta) class; instantiation of the class
|
||||
means calling the metainstance, and this will return a real instance.
|
||||
And what class is that an instance of? Conceptually, it is of course
|
||||
an instance of our metainstance; but in most cases the Python runtime
|
||||
system will see it as an instance of a a helper class used by the
|
||||
metaclass to implement its (non-meta) instances...
|
||||
|
||||
<P>Hopefully an example will make things clearer. Let's presume we
|
||||
have a metaclass MetaClass1. It's helper class (for non-meta
|
||||
instances) is callled HelperClass1. We now (manually) instantiate
|
||||
MetaClass1 once to get an empty special base class:
|
||||
|
||||
<PRE>
|
||||
BaseClass1 = MetaClass1("BaseClass1", (), {})
|
||||
</PRE>
|
||||
|
||||
We can now use BaseClass1 as a base class in a class statement:
|
||||
|
||||
<PRE>
|
||||
class MySpecialClass(BaseClass1):
|
||||
i = 1
|
||||
def f(s): pass
|
||||
</PRE>
|
||||
|
||||
At this point, MySpecialClass is defined; it is a metainstance of
|
||||
MetaClass1 just like BaseClass1, and in fact the expression
|
||||
``BaseClass1.__class__ == MySpecialClass.__class__ == MetaClass1''
|
||||
yields true.
|
||||
|
||||
<P>We are now ready to create instances of MySpecialClass. Let's
|
||||
assume that no constructor arguments are required:
|
||||
|
||||
<PRE>
|
||||
x = MySpecialClass()
|
||||
y = MySpecialClass()
|
||||
print x.__class__, y.__class__
|
||||
</PRE>
|
||||
|
||||
The print statement shows that x and y are instances of HelperClass1.
|
||||
How did this happen? MySpecialClass is an instance of MetaClass1
|
||||
(``meta'' is irrelevant here); when an instance is called, its
|
||||
__call__ method is invoked, and presumably the __call__ method defined
|
||||
by MetaClass1 returns an instance of HelperClass1.
|
||||
|
||||
<P>Now let's see how we could use metaclasses -- what can we do
|
||||
with metaclasses that we can't easily do without them? Here's one
|
||||
idea: a metaclass could automatically insert trace calls for all
|
||||
method calls. Let's first develop a simplified example, without
|
||||
support for inheritance or other ``advanced'' Python features (we'll
|
||||
add those later).
|
||||
|
||||
<PRE>
|
||||
import types
|
||||
|
||||
class Tracing:
|
||||
def __init__(self, name, bases, namespace):
|
||||
"""Create a new class."""
|
||||
self.__name__ = name
|
||||
self.__bases__ = bases
|
||||
self.__namespace__ = namespace
|
||||
def __call__(self):
|
||||
"""Create a new instance."""
|
||||
return Instance(self)
|
||||
|
||||
class Instance:
|
||||
def __init__(self, klass):
|
||||
self.__klass__ = klass
|
||||
def __getattr__(self, name):
|
||||
try:
|
||||
value = self.__klass__.__namespace__[name]
|
||||
except KeyError:
|
||||
raise AttributeError, name
|
||||
if type(value) is not types.FunctionType:
|
||||
return value
|
||||
return BoundMethod(value, self)
|
||||
|
||||
class BoundMethod:
|
||||
def __init__(self, function, instance):
|
||||
self.function = function
|
||||
self.instance = instance
|
||||
def __call__(self, *args):
|
||||
print "calling", self.function, "for", self.instance, "with", args
|
||||
return apply(self.function, (self.instance,) + args)
|
||||
|
||||
Trace = Tracing('Trace', (), {})
|
||||
|
||||
class MyTracedClass(Trace):
|
||||
def method1(self, a):
|
||||
self.a = a
|
||||
def method2(self):
|
||||
return self.a
|
||||
|
||||
aninstance = MyTracedClass()
|
||||
|
||||
aninstance.method1(10)
|
||||
|
||||
print "the answer is %d" % aninstance.method2()
|
||||
</PRE>
|
||||
|
||||
Confused already? The intention is to read this from top down. The
|
||||
Tracing class is the metaclass we're defining. Its structure is
|
||||
really simple.
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>The __init__ method is invoked when a new Tracing instance is
|
||||
created, e.g. the definition of class MyTracedClass later in the
|
||||
example. It simply saves the class name, base classes and namespace
|
||||
as instance variables.<P>
|
||||
|
||||
<LI>The __call__ method is invoked when a Tracing instance is called,
|
||||
e.g. the creation of aninstance later in the example. It returns an
|
||||
instance of the class Instance, which is defined next.<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>The class Instance is the class used for all instances of classes
|
||||
built using the Tracing metaclass, e.g. aninstance. It has two
|
||||
methods:
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>The __init__ method is invoked from the Tracing.__call__ method
|
||||
above to initialize a new instance. It saves the class reference as
|
||||
an instance variable. It uses a funny name because the user's
|
||||
instance variables (e.g. self.a later in the example) live in the same
|
||||
namespace.<P>
|
||||
|
||||
<LI>The __getattr__ method is invoked whenever the user code
|
||||
references an attribute of the instance that is not an instance
|
||||
variable (nor a class variable; but except for __init__ and
|
||||
__getattr__ there are no class variables). It will be called, for
|
||||
example, when aninstance.method1 is referenced in the example, with
|
||||
self set to aninstance and name set to the string "method1".<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>The __getattr__ method looks the name up in the __namespace__
|
||||
dictionary. If it isn't found, it raises an AttributeError exception.
|
||||
(In a more realistic example, it would first have to look through the
|
||||
base classes as well.) If it is found, there are two possibilities:
|
||||
it's either a function or it isn't. If it's not a function, it is
|
||||
assumed to be a class variable, and its value is returned. If it's a
|
||||
function, we have to ``wrap'' it in instance of yet another helper
|
||||
class, BoundMethod.
|
||||
|
||||
<P>The BoundMethod class is needed to implement a familiar feature:
|
||||
when a method is defined, it has an initial argument, self, which is
|
||||
automatically bound to the relevant instance when it is called. For
|
||||
example, aninstance.method1(10) is equivalent to method1(aninstance,
|
||||
10). In the example if this call, first a temporary BoundMethod
|
||||
instance is created with the following constructor call: temp =
|
||||
BoundMethod(method1, aninstance); then this instance is called as
|
||||
temp(10). After the call, the temporary instance is discarded.
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>The __init__ method is invoked for the constructor call
|
||||
BoundMethod(method1, aninstance). It simply saves away its
|
||||
arguments.<P>
|
||||
|
||||
<LI>The __call__ method is invoked when the bound method instance is
|
||||
called, as in temp(10). It needs to call method1(aninstance, 10).
|
||||
However, even though self.function is now method1 and self.instance is
|
||||
aninstance, it can't call self.function(self.instance, args) directly,
|
||||
because it should work regardless of the number of arguments passed.
|
||||
(For simplicity, support for keyword arguments has been omitted.)<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>In order to be able to support arbitrary argument lists, the
|
||||
__call__ method first constructs a new argument tuple. Conveniently,
|
||||
because of the notation *args in __call__'s own argument list, the
|
||||
arguments to __call__ (except for self) are placed in the tuple args.
|
||||
To construct the desired argument list, we concatenate a singleton
|
||||
tuple containing the instance with the args tuple: (self.instance,) +
|
||||
args. (Note the trailing comma used to construct the singleton
|
||||
tuple.) In our example, the resulting argument tuple is (aninstance,
|
||||
10).
|
||||
|
||||
<P>The intrinsic function apply() takes a function and an argument
|
||||
tuple and calls the function for it. In our example, we are calling
|
||||
apply(method1, (aninstance, 10)) which is equivalent to calling
|
||||
method(aninstance, 10).
|
||||
|
||||
<P>From here on, things should come together quite easily. The output
|
||||
of the example code is something like this:
|
||||
|
||||
<PRE>
|
||||
calling <function method1 at ae8d8> for <Instance instance at 95ab0> with (10,)
|
||||
calling <function method2 at ae900> for <Instance instance at 95ab0> with ()
|
||||
the answer is 10
|
||||
</PRE>
|
||||
|
||||
<P>That was about the shortest meaningful example that I could come up
|
||||
with. A real tracing metaclass (for example, <A
|
||||
HREF="#Trace">Trace.py</A> discussed below) needs to be more
|
||||
complicated in two dimensions.
|
||||
|
||||
<P>First, it needs to support more advanced Python features such as
|
||||
class variables, inheritance, __init__ methods, and keyword arguments.
|
||||
|
||||
<P>Second, it needs to provide a more flexible way to handle the
|
||||
actual tracing information; perhaps it should be possible to write
|
||||
your own tracing function that gets called, perhaps it should be
|
||||
possible to enable and disable tracing on a per-class or per-instance
|
||||
basis, and perhaps a filter so that only interesting calls are traced;
|
||||
it should also be able to trace the return value of the call (or the
|
||||
exception it raised if an error occurs). Even the Trace.py example
|
||||
doesn't support all these features yet.
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<H1>Real-life Examples</H1>
|
||||
|
||||
<P>Have a look at some very preliminary examples that I coded up to
|
||||
teach myself how to write metaclasses:
|
||||
|
||||
<DL>
|
||||
|
||||
<DT><A HREF="Enum.py">Enum.py</A>
|
||||
|
||||
<DD>This (ab)uses the class syntax as an elegant way to define
|
||||
enumerated types. The resulting classes are never instantiated --
|
||||
rather, their class attributes are the enumerated values. For
|
||||
example:
|
||||
|
||||
<PRE>
|
||||
class Color(Enum):
|
||||
red = 1
|
||||
green = 2
|
||||
blue = 3
|
||||
print Color.red
|
||||
</PRE>
|
||||
|
||||
will print the string ``Color.red'', while ``Color.red==1'' is true,
|
||||
and ``Color.red + 1'' raise a TypeError exception.
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A NAME=Trace></A><A HREF="Trace.py">Trace.py</A>
|
||||
|
||||
<DD>The resulting classes work much like standard
|
||||
classes, but by setting a special class or instance attribute
|
||||
__trace_output__ to point to a file, all calls to the class's methods
|
||||
are traced. It was a bit of a struggle to get this right. This
|
||||
should probably redone using the generic metaclass below.
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A HREF="Meta.py">Meta.py</A>
|
||||
|
||||
<DD>A generic metaclass. This is an attempt at finding out how much
|
||||
standard class behavior can be mimicked by a metaclass. The
|
||||
preliminary answer appears to be that everything's fine as long as the
|
||||
class (or its clients) don't look at the instance's __class__
|
||||
attribute, nor at the class's __dict__ attribute. The use of
|
||||
__getattr__ internally makes the classic implementation of __getattr__
|
||||
hooks tough; we provide a similar hook _getattr_ instead.
|
||||
(__setattr__ and __delattr__ are not affected.)
|
||||
(XXX Hm. Could detect presence of __getattr__ and rename it.)
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A HREF="Eiffel.py">Eiffel.py</A>
|
||||
|
||||
<DD>Uses the above generic metaclass to implement Eiffel style
|
||||
pre-conditions and post-conditions.
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A HREF="Synch.py">Synch.py</A>
|
||||
|
||||
<DD>Uses the above generic metaclass to implement synchronized
|
||||
methods.
|
||||
|
||||
<P>
|
||||
|
||||
<DT><A HREF="Simple.py">Simple.py</A>
|
||||
|
||||
<DD>The example module used above.
|
||||
|
||||
<P>
|
||||
|
||||
</DL>
|
||||
|
||||
<P>A pattern seems to be emerging: almost all these uses of
|
||||
metaclasses (except for Enum, which is probably more cute than useful)
|
||||
mostly work by placing wrappers around method calls. An obvious
|
||||
problem with that is that it's not easy to combine the features of
|
||||
different metaclasses, while this would actually be quite useful: for
|
||||
example, I wouldn't mind getting a trace from the test run of the
|
||||
Synch module, and it would be interesting to add preconditions to it
|
||||
as well. This needs more research. Perhaps a metaclass could be
|
||||
provided that allows stackable wrappers...
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<H2>Things You Could Do With Metaclasses</H2>
|
||||
|
||||
<P>There are lots of things you could do with metaclasses. Most of
|
||||
these can also be done with creative use of __getattr__, but
|
||||
metaclasses make it easier to modify the attribute lookup behavior of
|
||||
classes. Here's a partial list.
|
||||
|
||||
<P>
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>Enforce different inheritance semantics, e.g. automatically call
|
||||
base class methods when a derived class overrides<P>
|
||||
|
||||
<LI>Implement class methods (e.g. if the first argument is not named
|
||||
'self')<P>
|
||||
|
||||
<LI>Implement that each instance is initialized with <b>copies</b> of
|
||||
all class variables<P>
|
||||
|
||||
<LI>Implement a different way to store instance variables (e.g. in a
|
||||
list kept outside the instance but indexed by the instance's id())<P>
|
||||
|
||||
<LI>Automatically wrap or trap all or certain methods
|
||||
|
||||
<UL>
|
||||
|
||||
<LI>for tracing
|
||||
|
||||
<LI>for precondition and postcondition checking
|
||||
|
||||
<LI>for synchronized methods
|
||||
|
||||
<LI>for automatic value caching
|
||||
|
||||
</UL>
|
||||
<P>
|
||||
|
||||
<LI>When an attribute is a parameterless function, call it on
|
||||
reference (to mimic it being an instance variable); same on assignment<P>
|
||||
|
||||
<LI>Instrumentation: see how many times various attributes are used<P>
|
||||
|
||||
<LI>Different semantics for __setattr__ and __getattr__ (e.g. disable
|
||||
them when they are being used recursively)<P>
|
||||
|
||||
<LI>Abuse class syntax for other things<P>
|
||||
|
||||
<LI>Experiment with automatic type checking<P>
|
||||
|
||||
<LI>Delegation (or acquisition)<P>
|
||||
|
||||
<LI>Dynamic inheritance patterns<P>
|
||||
|
||||
<LI>Automatic caching of methods<P>
|
||||
|
||||
</UL>
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<H4>Credits</H4>
|
||||
|
||||
<P>Many thanks to David Ascher and Donald Beaudry for their comments
|
||||
on earlier draft of this paper. Also thanks to Matt Conway and Tommy
|
||||
Burnette for putting a seed for the idea of metaclasses in my
|
||||
mind, nearly three years ago, even though at the time my response was
|
||||
``you can do that with __getattr__ hooks...'' :-)
|
||||
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
@ -1,141 +0,0 @@
|
||||
"""Support Eiffel-style preconditions and postconditions."""
|
||||
|
||||
from types import FunctionType as function
|
||||
|
||||
class EiffelBaseMetaClass(type):
|
||||
|
||||
def __new__(meta, name, bases, dict):
|
||||
meta.convert_methods(dict)
|
||||
return super(EiffelBaseMetaClass, meta).__new__(meta, name, bases,
|
||||
dict)
|
||||
|
||||
@classmethod
|
||||
def convert_methods(cls, dict):
|
||||
"""Replace functions in dict with EiffelMethod wrappers.
|
||||
|
||||
The dict is modified in place.
|
||||
|
||||
If a method ends in _pre or _post, it is removed from the dict
|
||||
regardless of whether there is a corresponding method.
|
||||
"""
|
||||
# find methods with pre or post conditions
|
||||
methods = []
|
||||
for k, v in dict.iteritems():
|
||||
if k.endswith('_pre') or k.endswith('_post'):
|
||||
assert isinstance(v, function)
|
||||
elif isinstance(v, function):
|
||||
methods.append(k)
|
||||
for m in methods:
|
||||
pre = dict.get("%s_pre" % m)
|
||||
post = dict.get("%s_post" % m)
|
||||
if pre or post:
|
||||
dict[k] = cls.make_eiffel_method(dict[m], pre, post)
|
||||
|
||||
class EiffelMetaClass1(EiffelBaseMetaClass):
|
||||
# an implementation of the "eiffel" meta class that uses nested functions
|
||||
|
||||
@staticmethod
|
||||
def make_eiffel_method(func, pre, post):
|
||||
def method(self, *args, **kwargs):
|
||||
if pre:
|
||||
pre(self, *args, **kwargs)
|
||||
x = func(self, *args, **kwargs)
|
||||
if post:
|
||||
post(self, x, *args, **kwargs)
|
||||
return x
|
||||
|
||||
if func.__doc__:
|
||||
method.__doc__ = func.__doc__
|
||||
|
||||
return method
|
||||
|
||||
class EiffelMethodWrapper:
|
||||
|
||||
def __init__(self, inst, descr):
|
||||
self._inst = inst
|
||||
self._descr = descr
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self._descr.callmethod(self._inst, args, kwargs)
|
||||
|
||||
class EiffelDescriptor(object):
|
||||
|
||||
def __init__(self, func, pre, post):
|
||||
self._func = func
|
||||
self._pre = pre
|
||||
self._post = post
|
||||
|
||||
self.__name__ = func.__name__
|
||||
self.__doc__ = func.__doc__
|
||||
|
||||
def __get__(self, obj, cls):
|
||||
return EiffelMethodWrapper(obj, self)
|
||||
|
||||
def callmethod(self, inst, args, kwargs):
|
||||
if self._pre:
|
||||
self._pre(inst, *args, **kwargs)
|
||||
x = self._func(inst, *args, **kwargs)
|
||||
if self._post:
|
||||
self._post(inst, x, *args, **kwargs)
|
||||
return x
|
||||
|
||||
class EiffelMetaClass2(EiffelBaseMetaClass):
|
||||
# an implementation of the "eiffel" meta class that uses descriptors
|
||||
|
||||
make_eiffel_method = EiffelDescriptor
|
||||
|
||||
def _test(metaclass):
|
||||
class Eiffel:
|
||||
__metaclass__ = metaclass
|
||||
|
||||
class Test(Eiffel):
|
||||
|
||||
def m(self, arg):
|
||||
"""Make it a little larger"""
|
||||
return arg + 1
|
||||
|
||||
def m2(self, arg):
|
||||
"""Make it a little larger"""
|
||||
return arg + 1
|
||||
|
||||
def m2_pre(self, arg):
|
||||
assert arg > 0
|
||||
|
||||
def m2_post(self, result, arg):
|
||||
assert result > arg
|
||||
|
||||
class Sub(Test):
|
||||
def m2(self, arg):
|
||||
return arg**2
|
||||
def m2_post(self, Result, arg):
|
||||
super(Sub, self).m2_post(Result, arg)
|
||||
assert Result < 100
|
||||
|
||||
t = Test()
|
||||
t.m(1)
|
||||
t.m2(1)
|
||||
try:
|
||||
t.m2(0)
|
||||
except AssertionError:
|
||||
pass
|
||||
else:
|
||||
assert False
|
||||
|
||||
s = Sub()
|
||||
try:
|
||||
s.m2(1)
|
||||
except AssertionError:
|
||||
pass # result == arg
|
||||
else:
|
||||
assert False
|
||||
try:
|
||||
s.m2(10)
|
||||
except AssertionError:
|
||||
pass # result == 100
|
||||
else:
|
||||
assert False
|
||||
s.m2(5)
|
||||
|
||||
if __name__ == "__main__":
|
||||
_test(EiffelMetaClass1)
|
||||
_test(EiffelMetaClass2)
|
@ -1,31 +0,0 @@
|
||||
These files are from the large example of using the `parser' module. Refer
|
||||
to the Python Library Reference for more information.
|
||||
|
||||
It also contains examples for the AST parser.
|
||||
|
||||
Files:
|
||||
------
|
||||
|
||||
FILES -- list of files associated with the parser module.
|
||||
|
||||
README -- this file.
|
||||
|
||||
example.py -- module that uses the `parser' module to extract
|
||||
information from the parse tree of Python source
|
||||
code.
|
||||
|
||||
docstring.py -- sample source file containing only a module docstring.
|
||||
|
||||
simple.py -- sample source containing a "short form" definition.
|
||||
|
||||
source.py -- sample source code used to demonstrate ability to
|
||||
handle nested constructs easily using the functions
|
||||
and classes in example.py.
|
||||
|
||||
test_parser.py program to put the parser module through its paces.
|
||||
|
||||
unparse.py AST (2.5) based example to recreate source code
|
||||
from an AST. This is incomplete; contributions
|
||||
are welcome.
|
||||
|
||||
Enjoy!
|
@ -1,48 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# (Force the script to use the latest build.)
|
||||
#
|
||||
# test_parser.py
|
||||
|
||||
import parser, traceback
|
||||
|
||||
_numFailed = 0
|
||||
|
||||
def testChunk(t, fileName):
|
||||
global _numFailed
|
||||
print '----', fileName,
|
||||
try:
|
||||
ast = parser.suite(t)
|
||||
tup = parser.ast2tuple(ast)
|
||||
# this discards the first AST; a huge memory savings when running
|
||||
# against a large source file like Tkinter.py.
|
||||
ast = None
|
||||
new = parser.tuple2ast(tup)
|
||||
except parser.ParserError, err:
|
||||
print
|
||||
print 'parser module raised exception on input file', fileName + ':'
|
||||
traceback.print_exc()
|
||||
_numFailed = _numFailed + 1
|
||||
else:
|
||||
if tup != parser.ast2tuple(new):
|
||||
print
|
||||
print 'parser module failed on input file', fileName
|
||||
_numFailed = _numFailed + 1
|
||||
else:
|
||||
print 'o.k.'
|
||||
|
||||
def testFile(fileName):
|
||||
t = open(fileName).read()
|
||||
testChunk(t, fileName)
|
||||
|
||||
def test():
|
||||
import sys
|
||||
args = sys.argv[1:]
|
||||
if not args:
|
||||
import glob
|
||||
args = glob.glob("*.py")
|
||||
args.sort()
|
||||
map(testFile, args)
|
||||
sys.exit(_numFailed != 0)
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
@ -1,100 +0,0 @@
|
||||
\input texinfo @c -*-texinfo-*-
|
||||
@c %**start of header
|
||||
@setfilename parser.info
|
||||
@settitle Python Parser Module Reference
|
||||
@setchapternewpage odd
|
||||
@footnotestyle end
|
||||
@c %**end of header
|
||||
|
||||
@ifinfo
|
||||
This file describes the interfaces
|
||||
published by the optional @code{parser} module and gives examples of
|
||||
how they may be used. It contains the same text as the chapter on the
|
||||
@code{parser} module in the @cite{Python Library Reference}, but is
|
||||
presented as a separate document.
|
||||
|
||||
Copyright 1995-1996 by Fred L. Drake, Jr., Reston, Virginia, USA, and
|
||||
Virginia Polytechnic Institute and State University, Blacksburg,
|
||||
Virginia, USA. Portions of the software copyright 1991-1995 by
|
||||
Stichting Mathematisch Centrum, Amsterdam, The Netherlands. Copying is
|
||||
permitted under the terms associated with the main Python distribution,
|
||||
with the additional restriction that this additional notice be included
|
||||
and maintained on all distributed copies.
|
||||
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the names of Fred L. Drake, Jr. and
|
||||
Virginia Polytechnic Institute and State University not be used in
|
||||
advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission.
|
||||
|
||||
FRED L. DRAKE, JR. AND VIRGINIA POLYTECHNIC INSTITUTE AND STATE
|
||||
UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
EVENT SHALL FRED L. DRAKE, JR. OR VIRGINIA POLYTECHNIC INSTITUTE AND
|
||||
STATE UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
@end ifinfo
|
||||
|
||||
@titlepage
|
||||
@title Python Parser Module Reference
|
||||
@author Fred L. Drake, Jr.
|
||||
|
||||
@c The following two commands start the copyright page.
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
Copyright 1995-1996 by Fred L. Drake, Jr., Reston, Virginia, USA, and
|
||||
Virginia Polytechnic Institute and State University, Blacksburg,
|
||||
Virginia, USA. Portions of the software copyright 1991-1995 by
|
||||
Stichting Mathematisch Centrum, Amsterdam, The Netherlands. Copying is
|
||||
permitted under the terms associated with the main Python distribution,
|
||||
with the additional restriction that this additional notice be included
|
||||
and maintained on all distributed copies.
|
||||
|
||||
@center All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the names of Fred L. Drake, Jr. and
|
||||
Virginia Polytechnic Institute and State University not be used in
|
||||
advertising or publicity pertaining to distribution of the software
|
||||
without specific, written prior permission.
|
||||
|
||||
FRED L. DRAKE, JR. AND VIRGINIA POLYTECHNIC INSTITUTE AND STATE
|
||||
UNIVERSITY DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
EVENT SHALL FRED L. DRAKE, JR. OR VIRGINIA POLYTECHNIC INSTITUTE AND
|
||||
STATE UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
|
||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
PERFORMANCE OF THIS SOFTWARE.
|
||||
@end titlepage
|
||||
|
||||
|
||||
@node Top, Overview, (dir), (dir)
|
||||
@top The Python Parser Module
|
||||
|
||||
@ifinfo
|
||||
This file describes the interfaces
|
||||
published by the optional @code{parser} module and gives examples of
|
||||
how they may be used. It contains the same text as the chapter on the
|
||||
@code{parser} module in the @cite{Python Library Reference}, but is
|
||||
presented as a separate document.
|
||||
|
||||
This version corresponds to Python version 1.4 (1 Sept. 1996).
|
||||
|
||||
@end ifinfo
|
||||
|
||||
@c placeholder for the master menu -- patched by texinfo-all-menus-update
|
||||
@menu
|
||||
@end menu
|
@ -1,518 +0,0 @@
|
||||
"Usage: unparse.py <path to source file>"
|
||||
import sys
|
||||
import _ast
|
||||
import cStringIO
|
||||
import os
|
||||
|
||||
def interleave(inter, f, seq):
|
||||
"""Call f on each item in seq, calling inter() in between.
|
||||
"""
|
||||
seq = iter(seq)
|
||||
try:
|
||||
f(seq.next())
|
||||
except StopIteration:
|
||||
pass
|
||||
else:
|
||||
for x in seq:
|
||||
inter()
|
||||
f(x)
|
||||
|
||||
class Unparser:
|
||||
"""Methods in this class recursively traverse an AST and
|
||||
output source code for the abstract syntax; original formatting
|
||||
is disregarged. """
|
||||
|
||||
def __init__(self, tree, file = sys.stdout):
|
||||
"""Unparser(tree, file=sys.stdout) -> None.
|
||||
Print the source for tree to file."""
|
||||
self.f = file
|
||||
self._indent = 0
|
||||
self.dispatch(tree)
|
||||
print >>self.f,""
|
||||
self.f.flush()
|
||||
|
||||
def fill(self, text = ""):
|
||||
"Indent a piece of text, according to the current indentation level"
|
||||
self.f.write("\n"+" "*self._indent + text)
|
||||
|
||||
def write(self, text):
|
||||
"Append a piece of text to the current line."
|
||||
self.f.write(text)
|
||||
|
||||
def enter(self):
|
||||
"Print ':', and increase the indentation."
|
||||
self.write(":")
|
||||
self._indent += 1
|
||||
|
||||
def leave(self):
|
||||
"Decrease the indentation level."
|
||||
self._indent -= 1
|
||||
|
||||
def dispatch(self, tree):
|
||||
"Dispatcher function, dispatching tree type T to method _T."
|
||||
if isinstance(tree, list):
|
||||
for t in tree:
|
||||
self.dispatch(t)
|
||||
return
|
||||
meth = getattr(self, "_"+tree.__class__.__name__)
|
||||
meth(tree)
|
||||
|
||||
|
||||
############### Unparsing methods ######################
|
||||
# There should be one method per concrete grammar type #
|
||||
# Constructors should be grouped by sum type. Ideally, #
|
||||
# this would follow the order in the grammar, but #
|
||||
# currently doesn't. #
|
||||
########################################################
|
||||
|
||||
def _Module(self, tree):
|
||||
for stmt in tree.body:
|
||||
self.dispatch(stmt)
|
||||
|
||||
# stmt
|
||||
def _Expr(self, tree):
|
||||
self.fill()
|
||||
self.dispatch(tree.value)
|
||||
|
||||
def _Import(self, t):
|
||||
self.fill("import ")
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.names)
|
||||
|
||||
def _ImportFrom(self, t):
|
||||
self.fill("from ")
|
||||
self.write(t.module)
|
||||
self.write(" import ")
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.names)
|
||||
# XXX(jpe) what is level for?
|
||||
|
||||
def _Assign(self, t):
|
||||
self.fill()
|
||||
for target in t.targets:
|
||||
self.dispatch(target)
|
||||
self.write(" = ")
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _AugAssign(self, t):
|
||||
self.fill()
|
||||
self.dispatch(t.target)
|
||||
self.write(" "+self.binop[t.op.__class__.__name__]+"= ")
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _Return(self, t):
|
||||
self.fill("return")
|
||||
if t.value:
|
||||
self.write(" ")
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _Pass(self, t):
|
||||
self.fill("pass")
|
||||
|
||||
def _Break(self, t):
|
||||
self.fill("break")
|
||||
|
||||
def _Continue(self, t):
|
||||
self.fill("continue")
|
||||
|
||||
def _Delete(self, t):
|
||||
self.fill("del ")
|
||||
self.dispatch(t.targets)
|
||||
|
||||
def _Assert(self, t):
|
||||
self.fill("assert ")
|
||||
self.dispatch(t.test)
|
||||
if t.msg:
|
||||
self.write(", ")
|
||||
self.dispatch(t.msg)
|
||||
|
||||
def _Exec(self, t):
|
||||
self.fill("exec ")
|
||||
self.dispatch(t.body)
|
||||
if t.globals:
|
||||
self.write(" in ")
|
||||
self.dispatch(t.globals)
|
||||
if t.locals:
|
||||
self.write(", ")
|
||||
self.dispatch(t.locals)
|
||||
|
||||
def _Print(self, t):
|
||||
self.fill("print ")
|
||||
do_comma = False
|
||||
if t.dest:
|
||||
self.write(">>")
|
||||
self.dispatch(t.dest)
|
||||
do_comma = True
|
||||
for e in t.values:
|
||||
if do_comma:self.write(", ")
|
||||
else:do_comma=True
|
||||
self.dispatch(e)
|
||||
if not t.nl:
|
||||
self.write(",")
|
||||
|
||||
def _Global(self, t):
|
||||
self.fill("global ")
|
||||
interleave(lambda: self.write(", "), self.write, t.names)
|
||||
|
||||
def _Yield(self, t):
|
||||
self.write("(")
|
||||
self.write("yield")
|
||||
if t.value:
|
||||
self.write(" ")
|
||||
self.dispatch(t.value)
|
||||
self.write(")")
|
||||
|
||||
def _Raise(self, t):
|
||||
self.fill('raise ')
|
||||
if t.type:
|
||||
self.dispatch(t.type)
|
||||
if t.inst:
|
||||
self.write(", ")
|
||||
self.dispatch(t.inst)
|
||||
if t.tback:
|
||||
self.write(", ")
|
||||
self.dispatch(t.tback)
|
||||
|
||||
def _TryExcept(self, t):
|
||||
self.fill("try")
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
for ex in t.handlers:
|
||||
self.dispatch(ex)
|
||||
if t.orelse:
|
||||
self.fill("else")
|
||||
self.enter()
|
||||
self.dispatch(t.orelse)
|
||||
self.leave()
|
||||
|
||||
def _TryFinally(self, t):
|
||||
self.fill("try")
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
self.fill("finally")
|
||||
self.enter()
|
||||
self.dispatch(t.finalbody)
|
||||
self.leave()
|
||||
|
||||
def _ExceptHandler(self, t):
|
||||
self.fill("except")
|
||||
if t.type:
|
||||
self.write(" ")
|
||||
self.dispatch(t.type)
|
||||
if t.name:
|
||||
self.write(", ")
|
||||
self.dispatch(t.name)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
def _ClassDef(self, t):
|
||||
self.write("\n")
|
||||
self.fill("class "+t.name)
|
||||
if t.bases:
|
||||
self.write("(")
|
||||
for a in t.bases:
|
||||
self.dispatch(a)
|
||||
self.write(", ")
|
||||
self.write(")")
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
def _FunctionDef(self, t):
|
||||
self.write("\n")
|
||||
for deco in t.decorator_list:
|
||||
self.fill("@")
|
||||
self.dispatch(deco)
|
||||
self.fill("def "+t.name + "(")
|
||||
self.dispatch(t.args)
|
||||
self.write(")")
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
def _For(self, t):
|
||||
self.fill("for ")
|
||||
self.dispatch(t.target)
|
||||
self.write(" in ")
|
||||
self.dispatch(t.iter)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
if t.orelse:
|
||||
self.fill("else")
|
||||
self.enter()
|
||||
self.dispatch(t.orelse)
|
||||
self.leave
|
||||
|
||||
def _If(self, t):
|
||||
self.fill("if ")
|
||||
self.dispatch(t.test)
|
||||
self.enter()
|
||||
# XXX elif?
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
if t.orelse:
|
||||
self.fill("else")
|
||||
self.enter()
|
||||
self.dispatch(t.orelse)
|
||||
self.leave()
|
||||
|
||||
def _While(self, t):
|
||||
self.fill("while ")
|
||||
self.dispatch(t.test)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
if t.orelse:
|
||||
self.fill("else")
|
||||
self.enter()
|
||||
self.dispatch(t.orelse)
|
||||
self.leave
|
||||
|
||||
def _With(self, t):
|
||||
self.fill("with ")
|
||||
self.dispatch(t.context_expr)
|
||||
if t.optional_vars:
|
||||
self.write(" as ")
|
||||
self.dispatch(t.optional_vars)
|
||||
self.enter()
|
||||
self.dispatch(t.body)
|
||||
self.leave()
|
||||
|
||||
# expr
|
||||
def _Str(self, tree):
|
||||
self.write(repr(tree.s))
|
||||
|
||||
def _Name(self, t):
|
||||
self.write(t.id)
|
||||
|
||||
def _Repr(self, t):
|
||||
self.write("`")
|
||||
self.dispatch(t.value)
|
||||
self.write("`")
|
||||
|
||||
def _Num(self, t):
|
||||
self.write(repr(t.n))
|
||||
|
||||
def _List(self, t):
|
||||
self.write("[")
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
||||
self.write("]")
|
||||
|
||||
def _ListComp(self, t):
|
||||
self.write("[")
|
||||
self.dispatch(t.elt)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write("]")
|
||||
|
||||
def _GeneratorExp(self, t):
|
||||
self.write("(")
|
||||
self.dispatch(t.elt)
|
||||
for gen in t.generators:
|
||||
self.dispatch(gen)
|
||||
self.write(")")
|
||||
|
||||
def _comprehension(self, t):
|
||||
self.write(" for ")
|
||||
self.dispatch(t.target)
|
||||
self.write(" in ")
|
||||
self.dispatch(t.iter)
|
||||
for if_clause in t.ifs:
|
||||
self.write(" if ")
|
||||
self.dispatch(if_clause)
|
||||
|
||||
def _IfExp(self, t):
|
||||
self.write("(")
|
||||
self.dispatch(t.body)
|
||||
self.write(" if ")
|
||||
self.dispatch(t.test)
|
||||
self.write(" else ")
|
||||
self.dispatch(t.orelse)
|
||||
self.write(")")
|
||||
|
||||
def _Dict(self, t):
|
||||
self.write("{")
|
||||
def writem((k, v)):
|
||||
self.dispatch(k)
|
||||
self.write(": ")
|
||||
self.dispatch(v)
|
||||
interleave(lambda: self.write(", "), writem, zip(t.keys, t.values))
|
||||
self.write("}")
|
||||
|
||||
def _Tuple(self, t):
|
||||
self.write("(")
|
||||
if len(t.elts) == 1:
|
||||
(elt,) = t.elts
|
||||
self.dispatch(elt)
|
||||
self.write(",")
|
||||
else:
|
||||
interleave(lambda: self.write(", "), self.dispatch, t.elts)
|
||||
self.write(")")
|
||||
|
||||
unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"}
|
||||
def _UnaryOp(self, t):
|
||||
self.write(self.unop[t.op.__class__.__name__])
|
||||
self.write("(")
|
||||
self.dispatch(t.operand)
|
||||
self.write(")")
|
||||
|
||||
binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%",
|
||||
"LShift":">>", "RShift":"<<", "BitOr":"|", "BitXor":"^", "BitAnd":"&",
|
||||
"FloorDiv":"//", "Pow": "**"}
|
||||
def _BinOp(self, t):
|
||||
self.write("(")
|
||||
self.dispatch(t.left)
|
||||
self.write(" " + self.binop[t.op.__class__.__name__] + " ")
|
||||
self.dispatch(t.right)
|
||||
self.write(")")
|
||||
|
||||
cmpops = {"Eq":"==", "NotEq":"!=", "Lt":"<", "LtE":"<=", "Gt":">", "GtE":">=",
|
||||
"Is":"is", "IsNot":"is not", "In":"in", "NotIn":"not in"}
|
||||
def _Compare(self, t):
|
||||
self.write("(")
|
||||
self.dispatch(t.left)
|
||||
for o, e in zip(t.ops, t.comparators):
|
||||
self.write(" " + self.cmpops[o.__class__.__name__] + " ")
|
||||
self.dispatch(e)
|
||||
self.write(")")
|
||||
|
||||
boolops = {_ast.And: 'and', _ast.Or: 'or'}
|
||||
def _BoolOp(self, t):
|
||||
self.write("(")
|
||||
s = " %s " % self.boolops[t.op.__class__]
|
||||
interleave(lambda: self.write(s), self.dispatch, t.values)
|
||||
self.write(")")
|
||||
|
||||
def _Attribute(self,t):
|
||||
self.dispatch(t.value)
|
||||
self.write(".")
|
||||
self.write(t.attr)
|
||||
|
||||
def _Call(self, t):
|
||||
self.dispatch(t.func)
|
||||
self.write("(")
|
||||
comma = False
|
||||
for e in t.args:
|
||||
if comma: self.write(", ")
|
||||
else: comma = True
|
||||
self.dispatch(e)
|
||||
for e in t.keywords:
|
||||
if comma: self.write(", ")
|
||||
else: comma = True
|
||||
self.dispatch(e)
|
||||
if t.starargs:
|
||||
if comma: self.write(", ")
|
||||
else: comma = True
|
||||
self.write("*")
|
||||
self.dispatch(t.starargs)
|
||||
if t.kwargs:
|
||||
if comma: self.write(", ")
|
||||
else: comma = True
|
||||
self.write("**")
|
||||
self.dispatch(t.kwargs)
|
||||
self.write(")")
|
||||
|
||||
def _Subscript(self, t):
|
||||
self.dispatch(t.value)
|
||||
self.write("[")
|
||||
self.dispatch(t.slice)
|
||||
self.write("]")
|
||||
|
||||
# slice
|
||||
def _Ellipsis(self, t):
|
||||
self.write("...")
|
||||
|
||||
def _Index(self, t):
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _Slice(self, t):
|
||||
if t.lower:
|
||||
self.dispatch(t.lower)
|
||||
self.write(":")
|
||||
if t.upper:
|
||||
self.dispatch(t.upper)
|
||||
if t.step:
|
||||
self.write(":")
|
||||
self.dispatch(t.step)
|
||||
|
||||
def _ExtSlice(self, t):
|
||||
interleave(lambda: self.write(', '), self.dispatch, t.dims)
|
||||
|
||||
# others
|
||||
def _arguments(self, t):
|
||||
first = True
|
||||
nonDef = len(t.args)-len(t.defaults)
|
||||
for a in t.args[0:nonDef]:
|
||||
if first:first = False
|
||||
else: self.write(", ")
|
||||
self.dispatch(a)
|
||||
for a,d in zip(t.args[nonDef:], t.defaults):
|
||||
if first:first = False
|
||||
else: self.write(", ")
|
||||
self.dispatch(a),
|
||||
self.write("=")
|
||||
self.dispatch(d)
|
||||
if t.vararg:
|
||||
if first:first = False
|
||||
else: self.write(", ")
|
||||
self.write("*"+t.vararg)
|
||||
if t.kwarg:
|
||||
if first:first = False
|
||||
else: self.write(", ")
|
||||
self.write("**"+t.kwarg)
|
||||
|
||||
def _keyword(self, t):
|
||||
self.write(t.arg)
|
||||
self.write("=")
|
||||
self.dispatch(t.value)
|
||||
|
||||
def _Lambda(self, t):
|
||||
self.write("lambda ")
|
||||
self.dispatch(t.args)
|
||||
self.write(": ")
|
||||
self.dispatch(t.body)
|
||||
|
||||
def _alias(self, t):
|
||||
self.write(t.name)
|
||||
if t.asname:
|
||||
self.write(" as "+t.asname)
|
||||
|
||||
def roundtrip(filename, output=sys.stdout):
|
||||
source = open(filename).read()
|
||||
tree = compile(source, filename, "exec", _ast.PyCF_ONLY_AST)
|
||||
Unparser(tree, output)
|
||||
|
||||
|
||||
|
||||
def testdir(a):
|
||||
try:
|
||||
names = [n for n in os.listdir(a) if n.endswith('.py')]
|
||||
except OSError:
|
||||
print >> sys.stderr, "Directory not readable: %s" % a
|
||||
else:
|
||||
for n in names:
|
||||
fullname = os.path.join(a, n)
|
||||
if os.path.isfile(fullname):
|
||||
output = cStringIO.StringIO()
|
||||
print 'Testing %s' % fullname
|
||||
try:
|
||||
roundtrip(fullname, output)
|
||||
except Exception, e:
|
||||
print ' Failed to compile, exception is %s' % repr(e)
|
||||
elif os.path.isdir(fullname):
|
||||
testdir(fullname)
|
||||
|
||||
def main(args):
|
||||
if args[0] == '--testdir':
|
||||
for a in args[1:]:
|
||||
testdir(a)
|
||||
else:
|
||||
for a in args:
|
||||
roundtrip(a)
|
||||
|
||||
if __name__=='__main__':
|
||||
main(sys.argv[1:])
|
@ -1,322 +0,0 @@
|
||||
"""File System Proxy.
|
||||
|
||||
Provide an OS-neutral view on a file system, locally or remotely.
|
||||
The functionality is geared towards implementing some sort of
|
||||
rdist-like utility between a Mac and a UNIX system.
|
||||
|
||||
The module defines three classes:
|
||||
|
||||
FSProxyLocal -- used for local access
|
||||
FSProxyServer -- used on the server side of remote access
|
||||
FSProxyClient -- used on the client side of remote access
|
||||
|
||||
The remote classes are instantiated with an IP address and an optional
|
||||
verbosity flag.
|
||||
"""
|
||||
|
||||
import server
|
||||
import client
|
||||
import md5
|
||||
import os
|
||||
import fnmatch
|
||||
from stat import *
|
||||
import time
|
||||
import fnmatch
|
||||
|
||||
if os.name == 'mac':
|
||||
import macfs
|
||||
maxnamelen = 31
|
||||
else:
|
||||
macfs = None
|
||||
maxnamelen = 255
|
||||
|
||||
skipnames = (os.curdir, os.pardir)
|
||||
|
||||
|
||||
class FSProxyLocal:
|
||||
|
||||
def __init__(self):
|
||||
self._dirstack = []
|
||||
self._ignore = ['*.pyc'] + self._readignore()
|
||||
|
||||
def _close(self):
|
||||
while self._dirstack:
|
||||
self.back()
|
||||
|
||||
def _readignore(self):
|
||||
file = self._hide('ignore')
|
||||
try:
|
||||
f = open(file)
|
||||
except IOError:
|
||||
file = self._hide('synctree.ignorefiles')
|
||||
try:
|
||||
f = open(file)
|
||||
except IOError:
|
||||
return []
|
||||
ignore = []
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: break
|
||||
if line[-1] == '\n': line = line[:-1]
|
||||
ignore.append(line)
|
||||
f.close()
|
||||
return ignore
|
||||
|
||||
def _hidden(self, name):
|
||||
if os.name == 'mac':
|
||||
return name[0] == '(' and name[-1] == ')'
|
||||
else:
|
||||
return name[0] == '.'
|
||||
|
||||
def _hide(self, name):
|
||||
if os.name == 'mac':
|
||||
return '(%s)' % name
|
||||
else:
|
||||
return '.%s' % name
|
||||
|
||||
def visible(self, name):
|
||||
if len(name) > maxnamelen: return 0
|
||||
if name[-1] == '~': return 0
|
||||
if name in skipnames: return 0
|
||||
if self._hidden(name): return 0
|
||||
head, tail = os.path.split(name)
|
||||
if head or not tail: return 0
|
||||
if macfs:
|
||||
if os.path.exists(name) and not os.path.isdir(name):
|
||||
try:
|
||||
fs = macfs.FSSpec(name)
|
||||
c, t = fs.GetCreatorType()
|
||||
if t != 'TEXT': return 0
|
||||
except macfs.error, msg:
|
||||
print "***", name, msg
|
||||
return 0
|
||||
else:
|
||||
if os.path.islink(name): return 0
|
||||
if '\0' in open(name, 'rb').read(512): return 0
|
||||
for ign in self._ignore:
|
||||
if fnmatch.fnmatch(name, ign): return 0
|
||||
return 1
|
||||
|
||||
def check(self, name):
|
||||
if not self.visible(name):
|
||||
raise os.error, "protected name %s" % repr(name)
|
||||
|
||||
def checkfile(self, name):
|
||||
self.check(name)
|
||||
if not os.path.isfile(name):
|
||||
raise os.error, "not a plain file %s" % repr(name)
|
||||
|
||||
def pwd(self):
|
||||
return os.getcwd()
|
||||
|
||||
def cd(self, name):
|
||||
self.check(name)
|
||||
save = os.getcwd(), self._ignore
|
||||
os.chdir(name)
|
||||
self._dirstack.append(save)
|
||||
self._ignore = self._ignore + self._readignore()
|
||||
|
||||
def back(self):
|
||||
if not self._dirstack:
|
||||
raise os.error, "empty directory stack"
|
||||
dir, ignore = self._dirstack[-1]
|
||||
os.chdir(dir)
|
||||
del self._dirstack[-1]
|
||||
self._ignore = ignore
|
||||
|
||||
def _filter(self, files, pat = None):
|
||||
if pat:
|
||||
def keep(name, pat = pat):
|
||||
return fnmatch.fnmatch(name, pat)
|
||||
files = filter(keep, files)
|
||||
files = filter(self.visible, files)
|
||||
files.sort()
|
||||
return files
|
||||
|
||||
def list(self, pat = None):
|
||||
files = os.listdir(os.curdir)
|
||||
return self._filter(files, pat)
|
||||
|
||||
def listfiles(self, pat = None):
|
||||
files = os.listdir(os.curdir)
|
||||
files = filter(os.path.isfile, files)
|
||||
return self._filter(files, pat)
|
||||
|
||||
def listsubdirs(self, pat = None):
|
||||
files = os.listdir(os.curdir)
|
||||
files = filter(os.path.isdir, files)
|
||||
return self._filter(files, pat)
|
||||
|
||||
def exists(self, name):
|
||||
return self.visible(name) and os.path.exists(name)
|
||||
|
||||
def isdir(self, name):
|
||||
return self.visible(name) and os.path.isdir(name)
|
||||
|
||||
def islink(self, name):
|
||||
return self.visible(name) and os.path.islink(name)
|
||||
|
||||
def isfile(self, name):
|
||||
return self.visible(name) and os.path.isfile(name)
|
||||
|
||||
def sum(self, name):
|
||||
self.checkfile(name)
|
||||
BUFFERSIZE = 1024*8
|
||||
f = open(name)
|
||||
sum = md5.new()
|
||||
while 1:
|
||||
buffer = f.read(BUFFERSIZE)
|
||||
if not buffer:
|
||||
break
|
||||
sum.update(buffer)
|
||||
return sum.digest()
|
||||
|
||||
def size(self, name):
|
||||
self.checkfile(name)
|
||||
return os.stat(name)[ST_SIZE]
|
||||
|
||||
def mtime(self, name):
|
||||
self.checkfile(name)
|
||||
return time.localtime(os.stat(name)[ST_MTIME])
|
||||
|
||||
def stat(self, name):
|
||||
self.checkfile(name)
|
||||
size = os.stat(name)[ST_SIZE]
|
||||
mtime = time.localtime(os.stat(name)[ST_MTIME])
|
||||
return size, mtime
|
||||
|
||||
def info(self, name):
|
||||
sum = self.sum(name)
|
||||
size = os.stat(name)[ST_SIZE]
|
||||
mtime = time.localtime(os.stat(name)[ST_MTIME])
|
||||
return sum, size, mtime
|
||||
|
||||
def _list(self, function, list):
|
||||
if list is None:
|
||||
list = self.listfiles()
|
||||
res = []
|
||||
for name in list:
|
||||
try:
|
||||
res.append((name, function(name)))
|
||||
except (os.error, IOError):
|
||||
res.append((name, None))
|
||||
return res
|
||||
|
||||
def sumlist(self, list = None):
|
||||
return self._list(self.sum, list)
|
||||
|
||||
def statlist(self, list = None):
|
||||
return self._list(self.stat, list)
|
||||
|
||||
def mtimelist(self, list = None):
|
||||
return self._list(self.mtime, list)
|
||||
|
||||
def sizelist(self, list = None):
|
||||
return self._list(self.size, list)
|
||||
|
||||
def infolist(self, list = None):
|
||||
return self._list(self.info, list)
|
||||
|
||||
def _dict(self, function, list):
|
||||
if list is None:
|
||||
list = self.listfiles()
|
||||
dict = {}
|
||||
for name in list:
|
||||
try:
|
||||
dict[name] = function(name)
|
||||
except (os.error, IOError):
|
||||
pass
|
||||
return dict
|
||||
|
||||
def sumdict(self, list = None):
|
||||
return self.dict(self.sum, list)
|
||||
|
||||
def sizedict(self, list = None):
|
||||
return self.dict(self.size, list)
|
||||
|
||||
def mtimedict(self, list = None):
|
||||
return self.dict(self.mtime, list)
|
||||
|
||||
def statdict(self, list = None):
|
||||
return self.dict(self.stat, list)
|
||||
|
||||
def infodict(self, list = None):
|
||||
return self._dict(self.info, list)
|
||||
|
||||
def read(self, name, offset = 0, length = -1):
|
||||
self.checkfile(name)
|
||||
f = open(name)
|
||||
f.seek(offset)
|
||||
if length == 0:
|
||||
data = ''
|
||||
elif length < 0:
|
||||
data = f.read()
|
||||
else:
|
||||
data = f.read(length)
|
||||
f.close()
|
||||
return data
|
||||
|
||||
def create(self, name):
|
||||
self.check(name)
|
||||
if os.path.exists(name):
|
||||
self.checkfile(name)
|
||||
bname = name + '~'
|
||||
try:
|
||||
os.unlink(bname)
|
||||
except os.error:
|
||||
pass
|
||||
os.rename(name, bname)
|
||||
f = open(name, 'w')
|
||||
f.close()
|
||||
|
||||
def write(self, name, data, offset = 0):
|
||||
self.checkfile(name)
|
||||
f = open(name, 'r+')
|
||||
f.seek(offset)
|
||||
f.write(data)
|
||||
f.close()
|
||||
|
||||
def mkdir(self, name):
|
||||
self.check(name)
|
||||
os.mkdir(name, 0777)
|
||||
|
||||
def rmdir(self, name):
|
||||
self.check(name)
|
||||
os.rmdir(name)
|
||||
|
||||
|
||||
class FSProxyServer(FSProxyLocal, server.Server):
|
||||
|
||||
def __init__(self, address, verbose = server.VERBOSE):
|
||||
FSProxyLocal.__init__(self)
|
||||
server.Server.__init__(self, address, verbose)
|
||||
|
||||
def _close(self):
|
||||
server.Server._close(self)
|
||||
FSProxyLocal._close(self)
|
||||
|
||||
def _serve(self):
|
||||
server.Server._serve(self)
|
||||
# Retreat into start directory
|
||||
while self._dirstack: self.back()
|
||||
|
||||
|
||||
class FSProxyClient(client.Client):
|
||||
|
||||
def __init__(self, address, verbose = client.VERBOSE):
|
||||
client.Client.__init__(self, address, verbose)
|
||||
|
||||
|
||||
def test():
|
||||
import string
|
||||
import sys
|
||||
if sys.argv[1:]:
|
||||
port = string.atoi(sys.argv[1])
|
||||
else:
|
||||
port = 4127
|
||||
proxy = FSProxyServer(('', port))
|
||||
proxy._serverloop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
@ -1,23 +0,0 @@
|
||||
This directory contains a collection of executable Python scripts.
|
||||
|
||||
See also the Tools/scripts directory!
|
||||
|
||||
beer.py Print the classic 'bottles of beer' list.
|
||||
eqfix.py Fix .py files to use the correct equality test operator
|
||||
fact.py Factorize numbers
|
||||
find-uname.py Search for Unicode characters using regexps.
|
||||
from.py Summarize mailbox
|
||||
ftpstats.py Summarize ftp daemon log file
|
||||
lpwatch.py Watch BSD line printer queues
|
||||
makedir.py Like mkdir -p
|
||||
markov.py Markov chain simulation of words or characters
|
||||
mboxconvvert.py Convert MH or MMDF mailboxes to unix mailbox format
|
||||
mkrcs.py Fix symlinks named RCS into parallel tree
|
||||
morse.py Produce morse code (audible or on AIFF file)
|
||||
pi.py Print all digits of pi -- given enough time and memory
|
||||
pp.py Emulate some Perl command line options
|
||||
primes.py Print prime numbers
|
||||
queens.py Dijkstra's solution to Wirth's "N Queens problem"
|
||||
script.py Equivalent to BSD script(1) -- by Steen Lumholt
|
||||
unbirthday.py Print unbirthday count
|
||||
update.py Update a bunch of files according to a script.
|
@ -1,14 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# By GvR, demystified after a version by Fredrik Lundh.
|
||||
import sys
|
||||
n = 100
|
||||
if sys.argv[1:]: n = int(sys.argv[1])
|
||||
def bottle(n):
|
||||
if n == 0: return "no more bottles of beer"
|
||||
if n == 1: return "one bottle of beer"
|
||||
return str(n) + " bottles of beer"
|
||||
for i in range(n):
|
||||
print bottle(n-i), "on the wall,"
|
||||
print bottle(n-i) + "."
|
||||
print "Take one down, pass it around,"
|
||||
print bottle(n-i-1), "on the wall."
|
@ -1,47 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Factorize numbers.
|
||||
# The algorithm is not efficient, but easy to understand.
|
||||
# If there are large factors, it will take forever to find them,
|
||||
# because we try all odd numbers between 3 and sqrt(n)...
|
||||
|
||||
import sys
|
||||
from math import sqrt
|
||||
|
||||
def fact(n):
|
||||
if n < 1: raise ValueError # fact() argument should be >= 1
|
||||
if n == 1: return [] # special case
|
||||
res = []
|
||||
# Treat even factors special, so we can use i = i+2 later
|
||||
while n%2 == 0:
|
||||
res.append(2)
|
||||
n = n//2
|
||||
# Try odd numbers up to sqrt(n)
|
||||
limit = sqrt(float(n+1))
|
||||
i = 3
|
||||
while i <= limit:
|
||||
if n%i == 0:
|
||||
res.append(i)
|
||||
n = n//i
|
||||
limit = sqrt(n+1)
|
||||
else:
|
||||
i = i+2
|
||||
if n != 1:
|
||||
res.append(n)
|
||||
return res
|
||||
|
||||
def main():
|
||||
if len(sys.argv) > 1:
|
||||
for arg in sys.argv[1:]:
|
||||
n = eval(arg)
|
||||
print n, fact(n)
|
||||
else:
|
||||
try:
|
||||
while 1:
|
||||
n = input()
|
||||
print n, fact(n)
|
||||
except EOFError:
|
||||
pass
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,40 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
For each argument on the command line, look for it in the set of all Unicode
|
||||
names. Arguments are treated as case-insensitive regular expressions, e.g.:
|
||||
|
||||
% find-uname 'small letter a$' 'horizontal line'
|
||||
*** small letter a$ matches ***
|
||||
LATIN SMALL LETTER A (97)
|
||||
COMBINING LATIN SMALL LETTER A (867)
|
||||
CYRILLIC SMALL LETTER A (1072)
|
||||
PARENTHESIZED LATIN SMALL LETTER A (9372)
|
||||
CIRCLED LATIN SMALL LETTER A (9424)
|
||||
FULLWIDTH LATIN SMALL LETTER A (65345)
|
||||
*** horizontal line matches ***
|
||||
HORIZONTAL LINE EXTENSION (9135)
|
||||
"""
|
||||
|
||||
import unicodedata
|
||||
import sys
|
||||
import re
|
||||
|
||||
def main(args):
|
||||
unicode_names= []
|
||||
for ix in range(sys.maxunicode+1):
|
||||
try:
|
||||
unicode_names.append( (ix, unicodedata.name(unichr(ix))) )
|
||||
except ValueError: # no name for the character
|
||||
pass
|
||||
for arg in args:
|
||||
pat = re.compile(arg, re.I)
|
||||
matches = [(x,y) for (x,y) in unicode_names
|
||||
if pat.search(y) is not None]
|
||||
if matches:
|
||||
print "***", arg, "matches", "***"
|
||||
for (x,y) in matches:
|
||||
print "%s (%d)" % (y,x)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main(sys.argv[1:])
|
@ -1,145 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Extract statistics from ftp daemon log.
|
||||
|
||||
# Usage:
|
||||
# ftpstats [-m maxitems] [-s search] [file]
|
||||
# -m maxitems: restrict number of items in "top-N" lists, default 25.
|
||||
# -s string: restrict statistics to lines containing this string.
|
||||
# Default file is /usr/adm/ftpd; a "-" means read standard input.
|
||||
|
||||
# The script must be run on the host where the ftp daemon runs.
|
||||
# (At CWI this is currently buizerd.)
|
||||
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import string
|
||||
import getopt
|
||||
|
||||
pat = '^([a-zA-Z0-9 :]*)!(.*)!(.*)!([<>].*)!([0-9]+)!([0-9]+)$'
|
||||
prog = re.compile(pat)
|
||||
|
||||
def main():
|
||||
maxitems = 25
|
||||
search = None
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'm:s:')
|
||||
except getopt.error, msg:
|
||||
print msg
|
||||
print 'usage: ftpstats [-m maxitems] [file]'
|
||||
sys.exit(2)
|
||||
for o, a in opts:
|
||||
if o == '-m':
|
||||
maxitems = string.atoi(a)
|
||||
if o == '-s':
|
||||
search = a
|
||||
file = '/usr/adm/ftpd'
|
||||
if args: file = args[0]
|
||||
if file == '-':
|
||||
f = sys.stdin
|
||||
else:
|
||||
try:
|
||||
f = open(file, 'r')
|
||||
except IOError, msg:
|
||||
print file, ':', msg
|
||||
sys.exit(1)
|
||||
bydate = {}
|
||||
bytime = {}
|
||||
byfile = {}
|
||||
bydir = {}
|
||||
byhost = {}
|
||||
byuser = {}
|
||||
bytype = {}
|
||||
lineno = 0
|
||||
try:
|
||||
while 1:
|
||||
line = f.readline()
|
||||
if not line: break
|
||||
lineno = lineno + 1
|
||||
if search and string.find(line, search) < 0:
|
||||
continue
|
||||
if prog.match(line) < 0:
|
||||
print 'Bad line', lineno, ':', repr(line)
|
||||
continue
|
||||
items = prog.group(1, 2, 3, 4, 5, 6)
|
||||
(logtime, loguser, loghost, logfile, logbytes,
|
||||
logxxx2) = items
|
||||
## print logtime
|
||||
## print '-->', loguser
|
||||
## print '--> -->', loghost
|
||||
## print '--> --> -->', logfile
|
||||
## print '--> --> --> -->', logbytes
|
||||
## print '--> --> --> --> -->', logxxx2
|
||||
## for i in logtime, loghost, logbytes, logxxx2:
|
||||
## if '!' in i: print '???', i
|
||||
add(bydate, logtime[-4:] + ' ' + logtime[:6], items)
|
||||
add(bytime, logtime[7:9] + ':00-59', items)
|
||||
direction, logfile = logfile[0], logfile[1:]
|
||||
# The real path probably starts at the last //...
|
||||
while 1:
|
||||
i = string.find(logfile, '//')
|
||||
if i < 0: break
|
||||
logfile = logfile[i+1:]
|
||||
add(byfile, logfile + ' ' + direction, items)
|
||||
logdir = os.path.dirname(logfile)
|
||||
## logdir = os.path.normpath(logdir) + '/.'
|
||||
while 1:
|
||||
add(bydir, logdir + ' ' + direction, items)
|
||||
dirhead = os.path.dirname(logdir)
|
||||
if dirhead == logdir: break
|
||||
logdir = dirhead
|
||||
add(byhost, loghost, items)
|
||||
add(byuser, loguser, items)
|
||||
add(bytype, direction, items)
|
||||
except KeyboardInterrupt:
|
||||
print 'Interrupted at line', lineno
|
||||
show(bytype, 'by transfer direction', maxitems)
|
||||
show(bydir, 'by directory', maxitems)
|
||||
show(byfile, 'by file', maxitems)
|
||||
show(byhost, 'by host', maxitems)
|
||||
show(byuser, 'by user', maxitems)
|
||||
showbar(bydate, 'by date')
|
||||
showbar(bytime, 'by time of day')
|
||||
|
||||
def showbar(dict, title):
|
||||
n = len(title)
|
||||
print '='*((70-n)//2), title, '='*((71-n)//2)
|
||||
list = []
|
||||
keys = dict.keys()
|
||||
keys.sort()
|
||||
for key in keys:
|
||||
n = len(str(key))
|
||||
list.append((len(dict[key]), key))
|
||||
maxkeylength = 0
|
||||
maxcount = 0
|
||||
for count, key in list:
|
||||
maxkeylength = max(maxkeylength, len(key))
|
||||
maxcount = max(maxcount, count)
|
||||
maxbarlength = 72 - maxkeylength - 7
|
||||
for count, key in list:
|
||||
barlength = int(round(maxbarlength*float(count)/maxcount))
|
||||
bar = '*'*barlength
|
||||
print '%5d %-*s %s' % (count, maxkeylength, key, bar)
|
||||
|
||||
def show(dict, title, maxitems):
|
||||
if len(dict) > maxitems:
|
||||
title = title + ' (first %d)'%maxitems
|
||||
n = len(title)
|
||||
print '='*((70-n)//2), title, '='*((71-n)//2)
|
||||
list = []
|
||||
keys = dict.keys()
|
||||
for key in keys:
|
||||
list.append((-len(dict[key]), key))
|
||||
list.sort()
|
||||
for count, key in list[:maxitems]:
|
||||
print '%5d %s' % (-count, key)
|
||||
|
||||
def add(dict, key, item):
|
||||
if dict.has_key(key):
|
||||
dict[key].append(item)
|
||||
else:
|
||||
dict[key] = [item]
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,110 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Watch line printer queue(s).
|
||||
# Intended for BSD 4.3 lpq.
|
||||
|
||||
import posix
|
||||
import sys
|
||||
import time
|
||||
import string
|
||||
|
||||
DEF_PRINTER = 'psc'
|
||||
DEF_DELAY = 10
|
||||
|
||||
def main():
|
||||
delay = DEF_DELAY # XXX Use getopt() later
|
||||
try:
|
||||
thisuser = posix.environ['LOGNAME']
|
||||
except:
|
||||
thisuser = posix.environ['USER']
|
||||
printers = sys.argv[1:]
|
||||
if printers:
|
||||
# Strip '-P' from printer names just in case
|
||||
# the user specified it...
|
||||
for i in range(len(printers)):
|
||||
if printers[i][:2] == '-P':
|
||||
printers[i] = printers[i][2:]
|
||||
else:
|
||||
if posix.environ.has_key('PRINTER'):
|
||||
printers = [posix.environ['PRINTER']]
|
||||
else:
|
||||
printers = [DEF_PRINTER]
|
||||
#
|
||||
clearhome = posix.popen('clear', 'r').read()
|
||||
#
|
||||
while 1:
|
||||
text = clearhome
|
||||
for name in printers:
|
||||
text = text + makestatus(name, thisuser) + '\n'
|
||||
print text
|
||||
time.sleep(delay)
|
||||
|
||||
def makestatus(name, thisuser):
|
||||
pipe = posix.popen('lpq -P' + name + ' 2>&1', 'r')
|
||||
lines = []
|
||||
users = {}
|
||||
aheadbytes = 0
|
||||
aheadjobs = 0
|
||||
userseen = 0
|
||||
totalbytes = 0
|
||||
totaljobs = 0
|
||||
while 1:
|
||||
line = pipe.readline()
|
||||
if not line: break
|
||||
fields = string.split(line)
|
||||
n = len(fields)
|
||||
if len(fields) >= 6 and fields[n-1] == 'bytes':
|
||||
rank = fields[0]
|
||||
user = fields[1]
|
||||
job = fields[2]
|
||||
files = fields[3:-2]
|
||||
bytes = eval(fields[n-2])
|
||||
if user == thisuser:
|
||||
userseen = 1
|
||||
elif not userseen:
|
||||
aheadbytes = aheadbytes + bytes
|
||||
aheadjobs = aheadjobs + 1
|
||||
totalbytes = totalbytes + bytes
|
||||
totaljobs = totaljobs + 1
|
||||
if users.has_key(user):
|
||||
ujobs, ubytes = users[user]
|
||||
else:
|
||||
ujobs, ubytes = 0, 0
|
||||
ujobs = ujobs + 1
|
||||
ubytes = ubytes + bytes
|
||||
users[user] = ujobs, ubytes
|
||||
else:
|
||||
if fields and fields[0] <> 'Rank':
|
||||
line = string.strip(line)
|
||||
if line == 'no entries':
|
||||
line = name + ': idle'
|
||||
elif line[-22:] == ' is ready and printing':
|
||||
line = name
|
||||
lines.append(line)
|
||||
#
|
||||
if totaljobs:
|
||||
line = '%d K' % ((totalbytes+1023)//1024)
|
||||
if totaljobs <> len(users):
|
||||
line = line + ' (%d jobs)' % totaljobs
|
||||
if len(users) == 1:
|
||||
line = line + ' for %s' % (users.keys()[0],)
|
||||
else:
|
||||
line = line + ' for %d users' % len(users)
|
||||
if userseen:
|
||||
if aheadjobs == 0:
|
||||
line = line + ' (%s first)' % thisuser
|
||||
else:
|
||||
line = line + ' (%d K before %s)' % (
|
||||
(aheadbytes+1023)//1024, thisuser)
|
||||
lines.append(line)
|
||||
#
|
||||
sts = pipe.close()
|
||||
if sts:
|
||||
lines.append('lpq exit status %r' % (sts,))
|
||||
return string.joinfields(lines, ': ')
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
@ -1,117 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
class Markov:
|
||||
def __init__(self, histsize, choice):
|
||||
self.histsize = histsize
|
||||
self.choice = choice
|
||||
self.trans = {}
|
||||
def add(self, state, next):
|
||||
if not self.trans.has_key(state):
|
||||
self.trans[state] = [next]
|
||||
else:
|
||||
self.trans[state].append(next)
|
||||
def put(self, seq):
|
||||
n = self.histsize
|
||||
add = self.add
|
||||
add(None, seq[:0])
|
||||
for i in range(len(seq)):
|
||||
add(seq[max(0, i-n):i], seq[i:i+1])
|
||||
add(seq[len(seq)-n:], None)
|
||||
def get(self):
|
||||
choice = self.choice
|
||||
trans = self.trans
|
||||
n = self.histsize
|
||||
seq = choice(trans[None])
|
||||
while 1:
|
||||
subseq = seq[max(0, len(seq)-n):]
|
||||
options = trans[subseq]
|
||||
next = choice(options)
|
||||
if not next: break
|
||||
seq = seq + next
|
||||
return seq
|
||||
|
||||
def test():
|
||||
import sys, string, random, getopt
|
||||
args = sys.argv[1:]
|
||||
try:
|
||||
opts, args = getopt.getopt(args, '0123456789cdw')
|
||||
except getopt.error:
|
||||
print 'Usage: markov [-#] [-cddqw] [file] ...'
|
||||
print 'Options:'
|
||||
print '-#: 1-digit history size (default 2)'
|
||||
print '-c: characters (default)'
|
||||
print '-w: words'
|
||||
print '-d: more debugging output'
|
||||
print '-q: no debugging output'
|
||||
print 'Input files (default stdin) are split in paragraphs'
|
||||
print 'separated blank lines and each paragraph is split'
|
||||
print 'in words by whitespace, then reconcatenated with'
|
||||
print 'exactly one space separating words.'
|
||||
print 'Output consists of paragraphs separated by blank'
|
||||
print 'lines, where lines are no longer than 72 characters.'
|
||||
histsize = 2
|
||||
do_words = 0
|
||||
debug = 1
|
||||
for o, a in opts:
|
||||
if '-0' <= o <= '-9': histsize = eval(o[1:])
|
||||
if o == '-c': do_words = 0
|
||||
if o == '-d': debug = debug + 1
|
||||
if o == '-q': debug = 0
|
||||
if o == '-w': do_words = 1
|
||||
if not args: args = ['-']
|
||||
m = Markov(histsize, random.choice)
|
||||
try:
|
||||
for filename in args:
|
||||
if filename == '-':
|
||||
f = sys.stdin
|
||||
if f.isatty():
|
||||
print 'Sorry, need stdin from file'
|
||||
continue
|
||||
else:
|
||||
f = open(filename, 'r')
|
||||
if debug: print 'processing', filename, '...'
|
||||
text = f.read()
|
||||
f.close()
|
||||
paralist = string.splitfields(text, '\n\n')
|
||||
for para in paralist:
|
||||
if debug > 1: print 'feeding ...'
|
||||
words = string.split(para)
|
||||
if words:
|
||||
if do_words: data = tuple(words)
|
||||
else: data = string.joinfields(words, ' ')
|
||||
m.put(data)
|
||||
except KeyboardInterrupt:
|
||||
print 'Interrupted -- continue with data read so far'
|
||||
if not m.trans:
|
||||
print 'No valid input files'
|
||||
return
|
||||
if debug: print 'done.'
|
||||
if debug > 1:
|
||||
for key in m.trans.keys():
|
||||
if key is None or len(key) < histsize:
|
||||
print repr(key), m.trans[key]
|
||||
if histsize == 0: print repr(''), m.trans['']
|
||||
print
|
||||
while 1:
|
||||
data = m.get()
|
||||
if do_words: words = data
|
||||
else: words = string.split(data)
|
||||
n = 0
|
||||
limit = 72
|
||||
for w in words:
|
||||
if n + len(w) > limit:
|
||||
print
|
||||
n = 0
|
||||
print w,
|
||||
n = n + len(w) + 1
|
||||
print
|
||||
print
|
||||
|
||||
def tuple(list):
|
||||
if len(list) == 0: return ()
|
||||
if len(list) == 1: return (list[0],)
|
||||
i = len(list)//2
|
||||
return tuple(list[:i]) + tuple(list[i:])
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
@ -1,61 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# A rather specialized script to make sure that a symbolic link named
|
||||
# RCS exists pointing to a real RCS directory in a parallel tree
|
||||
# referenced as RCStree in an ancestor directory.
|
||||
# (I use this because I like my RCS files to reside on a physically
|
||||
# different machine).
|
||||
|
||||
import os
|
||||
|
||||
def main():
|
||||
rcstree = 'RCStree'
|
||||
rcs = 'RCS'
|
||||
if os.path.islink(rcs):
|
||||
print '%r is a symlink to %r' % (rcs, os.readlink(rcs))
|
||||
return
|
||||
if os.path.isdir(rcs):
|
||||
print '%r is an ordinary directory' % (rcs,)
|
||||
return
|
||||
if os.path.exists(rcs):
|
||||
print '%r is a file?!?!' % (rcs,)
|
||||
return
|
||||
#
|
||||
p = os.getcwd()
|
||||
up = ''
|
||||
down = ''
|
||||
# Invariants:
|
||||
# (1) join(p, down) is the current directory
|
||||
# (2) up is the same directory as p
|
||||
# Ergo:
|
||||
# (3) join(up, down) is the current directory
|
||||
#print 'p =', repr(p)
|
||||
while not os.path.isdir(os.path.join(p, rcstree)):
|
||||
head, tail = os.path.split(p)
|
||||
#print 'head = %r; tail = %r' % (head, tail)
|
||||
if not tail:
|
||||
print 'Sorry, no ancestor dir contains %r' % (rcstree,)
|
||||
return
|
||||
p = head
|
||||
up = os.path.join(os.pardir, up)
|
||||
down = os.path.join(tail, down)
|
||||
#print 'p = %r; up = %r; down = %r' % (p, up, down)
|
||||
there = os.path.join(up, rcstree)
|
||||
there = os.path.join(there, down)
|
||||
there = os.path.join(there, rcs)
|
||||
if os.path.isdir(there):
|
||||
print '%r already exists' % (there, )
|
||||
else:
|
||||
print 'making %r' % (there,)
|
||||
makedirs(there)
|
||||
print 'making symlink %r -> %r' % (rcs, there)
|
||||
os.symlink(there, rcs)
|
||||
|
||||
def makedirs(p):
|
||||
if not os.path.isdir(p):
|
||||
head, tail = os.path.split(p)
|
||||
makedirs(head)
|
||||
os.mkdir(p, 0777)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,149 +0,0 @@
|
||||
# DAH should be three DOTs.
|
||||
# Space between DOTs and DAHs should be one DOT.
|
||||
# Space between two letters should be one DAH.
|
||||
# Space between two words should be DOT DAH DAH.
|
||||
|
||||
import sys, math, audiodev
|
||||
|
||||
DOT = 30
|
||||
DAH = 3 * DOT
|
||||
OCTAVE = 2 # 1 == 441 Hz, 2 == 882 Hz, ...
|
||||
|
||||
morsetab = {
|
||||
'A': '.-', 'a': '.-',
|
||||
'B': '-...', 'b': '-...',
|
||||
'C': '-.-.', 'c': '-.-.',
|
||||
'D': '-..', 'd': '-..',
|
||||
'E': '.', 'e': '.',
|
||||
'F': '..-.', 'f': '..-.',
|
||||
'G': '--.', 'g': '--.',
|
||||
'H': '....', 'h': '....',
|
||||
'I': '..', 'i': '..',
|
||||
'J': '.---', 'j': '.---',
|
||||
'K': '-.-', 'k': '-.-',
|
||||
'L': '.-..', 'l': '.-..',
|
||||
'M': '--', 'm': '--',
|
||||
'N': '-.', 'n': '-.',
|
||||
'O': '---', 'o': '---',
|
||||
'P': '.--.', 'p': '.--.',
|
||||
'Q': '--.-', 'q': '--.-',
|
||||
'R': '.-.', 'r': '.-.',
|
||||
'S': '...', 's': '...',
|
||||
'T': '-', 't': '-',
|
||||
'U': '..-', 'u': '..-',
|
||||
'V': '...-', 'v': '...-',
|
||||
'W': '.--', 'w': '.--',
|
||||
'X': '-..-', 'x': '-..-',
|
||||
'Y': '-.--', 'y': '-.--',
|
||||
'Z': '--..', 'z': '--..',
|
||||
'0': '-----',
|
||||
'1': '.----',
|
||||
'2': '..---',
|
||||
'3': '...--',
|
||||
'4': '....-',
|
||||
'5': '.....',
|
||||
'6': '-....',
|
||||
'7': '--...',
|
||||
'8': '---..',
|
||||
'9': '----.',
|
||||
',': '--..--',
|
||||
'.': '.-.-.-',
|
||||
'?': '..--..',
|
||||
';': '-.-.-.',
|
||||
':': '---...',
|
||||
"'": '.----.',
|
||||
'-': '-....-',
|
||||
'/': '-..-.',
|
||||
'(': '-.--.-',
|
||||
')': '-.--.-',
|
||||
'_': '..--.-',
|
||||
' ': ' '
|
||||
}
|
||||
|
||||
# If we play at 44.1 kHz (which we do), then if we produce one sine
|
||||
# wave in 100 samples, we get a tone of 441 Hz. If we produce two
|
||||
# sine waves in these 100 samples, we get a tone of 882 Hz. 882 Hz
|
||||
# appears to be a nice one for playing morse code.
|
||||
def mkwave(octave):
|
||||
global sinewave, nowave
|
||||
sinewave = ''
|
||||
for i in range(100):
|
||||
val = int(math.sin(math.pi * float(i) * octave / 50.0) * 30000)
|
||||
sinewave = sinewave + chr((val >> 8) & 255) + chr(val & 255)
|
||||
nowave = '\0' * 200
|
||||
|
||||
mkwave(OCTAVE)
|
||||
|
||||
def main():
|
||||
import getopt, string
|
||||
try:
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'o:p:')
|
||||
except getopt.error:
|
||||
sys.stderr.write('Usage ' + sys.argv[0] +
|
||||
' [ -o outfile ] [ args ] ...\n')
|
||||
sys.exit(1)
|
||||
dev = None
|
||||
for o, a in opts:
|
||||
if o == '-o':
|
||||
import aifc
|
||||
dev = aifc.open(a, 'w')
|
||||
dev.setframerate(44100)
|
||||
dev.setsampwidth(2)
|
||||
dev.setnchannels(1)
|
||||
if o == '-p':
|
||||
mkwave(string.atoi(a))
|
||||
if not dev:
|
||||
import audiodev
|
||||
dev = audiodev.AudioDev()
|
||||
dev.setoutrate(44100)
|
||||
dev.setsampwidth(2)
|
||||
dev.setnchannels(1)
|
||||
dev.close = dev.stop
|
||||
dev.writeframesraw = dev.writeframes
|
||||
if args:
|
||||
line = string.join(args)
|
||||
else:
|
||||
line = sys.stdin.readline()
|
||||
while line:
|
||||
mline = morse(line)
|
||||
play(mline, dev)
|
||||
if hasattr(dev, 'wait'):
|
||||
dev.wait()
|
||||
if not args:
|
||||
line = sys.stdin.readline()
|
||||
else:
|
||||
line = ''
|
||||
dev.close()
|
||||
|
||||
# Convert a string to morse code with \001 between the characters in
|
||||
# the string.
|
||||
def morse(line):
|
||||
res = ''
|
||||
for c in line:
|
||||
try:
|
||||
res = res + morsetab[c] + '\001'
|
||||
except KeyError:
|
||||
pass
|
||||
return res
|
||||
|
||||
# Play a line of morse code.
|
||||
def play(line, dev):
|
||||
for c in line:
|
||||
if c == '.':
|
||||
sine(dev, DOT)
|
||||
elif c == '-':
|
||||
sine(dev, DAH)
|
||||
else: # space
|
||||
pause(dev, DAH + DOT)
|
||||
pause(dev, DOT)
|
||||
|
||||
def sine(dev, length):
|
||||
for i in range(length):
|
||||
dev.writeframesraw(sinewave)
|
||||
|
||||
def pause(dev, length):
|
||||
for i in range(length):
|
||||
dev.writeframesraw(nowave)
|
||||
|
||||
if __name__ == '__main__' or sys.argv[0] == __name__:
|
||||
main()
|
@ -1,59 +0,0 @@
|
||||
NEWSLIST
|
||||
========
|
||||
A program to assist HTTP browsing of newsgroups
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
WWW browsers such as NCSA Mosaic allow the user to read newsgroup
|
||||
articles by specifying the group name in a URL eg 'news:comp.answers'.
|
||||
|
||||
To browse through many groups, though, (and there are several thousand
|
||||
of them) you really need a page or pages containing links to all the
|
||||
groups. There are some good ones out there, for example,
|
||||
|
||||
http://info.cern.ch/hypertext/DataSources/News/Groups/Overview.html
|
||||
|
||||
is the standard one at CERN, but it only shows the groups available there,
|
||||
which may be rather different from those available on your machine.
|
||||
|
||||
Newslist is a program which creates a hierarchy of pages for you based
|
||||
on the groups available from YOUR server. It is written in python - a
|
||||
splendid interpreted object-oriented language which I suggest you get
|
||||
right now from the directory /pub/python at ftp.cwi.nl, if you haven't
|
||||
already got it.
|
||||
|
||||
You should be able to see some sample output by looking at:
|
||||
http://pelican.cl.cam.ac.uk/newspage/root.html
|
||||
|
||||
Descriptions of newsgroups can be added from a file with one group
|
||||
per line. eg:
|
||||
|
||||
alt.foo Articles about foo
|
||||
comp.bar Programming in 'bar' and related languages
|
||||
|
||||
A suitable list detailing most groups can be found at ftp.uu.net in
|
||||
/uunet-info/newsgroups.gz.
|
||||
|
||||
Make sure you read the information at the beginning of the program source and
|
||||
configure the variables before running.
|
||||
|
||||
In addition to python, you need:
|
||||
|
||||
An NNTP-based news feed.
|
||||
A directory in which to put the pages.
|
||||
|
||||
The programming is not very beautiful, but it works! It comes with no
|
||||
warranty, express or implied, but with the hope that some others may
|
||||
find it useful.
|
||||
|
||||
Comments, improvements & suggestions welcomed.
|
||||
Quentin Stafford-Fraser
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Quentin Stafford-Fraser
|
||||
http://pelican.cl.cam.ac.uk/people/qs101/me.html
|
||||
|
||||
Cambridge University Computer Lab Rank Xerox Cambridge EuroPARC
|
||||
qs101@cl.cam.ac.uk fraser@europarc.xerox.com
|
||||
Tel: +44 223 334411 Tel: +44 223 341521
|
||||
Fax: +44 223 334679 Fax: +44 223 341510
|
||||
----------------------------------------------------------------------
|
@ -1,366 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
#######################################################################
|
||||
# Newslist $Revision$
|
||||
#
|
||||
# Syntax:
|
||||
# newslist [ -a ]
|
||||
#
|
||||
# This is a program to create a directory full of HTML pages
|
||||
# which between them contain links to all the newsgroups available
|
||||
# on your server.
|
||||
#
|
||||
# The -a option causes a complete list of all groups to be read from
|
||||
# the server rather than just the ones which have appeared since last
|
||||
# execution. This recreates the local list from scratch. Use this on
|
||||
# the first invocation of the program, and from time to time thereafter.
|
||||
# When new groups are first created they may appear on your server as
|
||||
# empty groups. By default, empty groups are ignored by the -a option.
|
||||
# However, these new groups will not be created again, and so will not
|
||||
# appear in the server's list of 'new groups' at a later date. Hence it
|
||||
# won't appear until you do a '-a' after some articles have appeared.
|
||||
#
|
||||
# I should really keep a list of ignored empty groups and re-check them
|
||||
# for articles on every run, but I haven't got around to it yet.
|
||||
#
|
||||
# This assumes an NNTP news feed.
|
||||
#
|
||||
# Feel free to copy, distribute and modify this code for
|
||||
# non-commercial use. If you make any useful modifications, let me
|
||||
# know!
|
||||
#
|
||||
# (c) Quentin Stafford-Fraser 1994
|
||||
# fraser@europarc.xerox.com qs101@cl.cam.ac.uk
|
||||
# #
|
||||
#######################################################################
|
||||
import sys,nntplib, string, marshal, time, os, posix, string
|
||||
|
||||
#######################################################################
|
||||
# Check these variables before running! #
|
||||
|
||||
# Top directory.
|
||||
# Filenames which don't start with / are taken as being relative to this.
|
||||
topdir='/anfs/qsbigdisc/web/html/newspage'
|
||||
|
||||
# The name of your NNTP host
|
||||
# eg.
|
||||
# newshost = 'nntp-serv.cl.cam.ac.uk'
|
||||
# or use following to get the name from the NNTPSERVER environment
|
||||
# variable:
|
||||
# newshost = posix.environ['NNTPSERVER']
|
||||
newshost = 'nntp-serv.cl.cam.ac.uk'
|
||||
|
||||
# The filename for a local cache of the newsgroup list
|
||||
treefile = 'grouptree'
|
||||
|
||||
# The filename for descriptions of newsgroups
|
||||
# I found a suitable one at ftp.uu.net in /uunet-info/newgroups.gz
|
||||
# You can set this to '' if you don't wish to use one.
|
||||
descfile = 'newsgroups'
|
||||
|
||||
# The directory in which HTML pages should be created
|
||||
# eg.
|
||||
# pagedir = '/usr/local/lib/html/newspage'
|
||||
# pagedir = 'pages'
|
||||
pagedir = topdir
|
||||
|
||||
# The html prefix which will refer to this directory
|
||||
# eg.
|
||||
# httppref = '/newspage/',
|
||||
# or leave blank for relative links between pages: (Recommended)
|
||||
# httppref = ''
|
||||
httppref = ''
|
||||
|
||||
# The name of the 'root' news page in this directory.
|
||||
# A .html suffix will be added.
|
||||
rootpage = 'root'
|
||||
|
||||
# Set skipempty to 0 if you wish to see links to empty groups as well.
|
||||
# Only affects the -a option.
|
||||
skipempty = 1
|
||||
|
||||
# pagelinkicon can contain html to put an icon after links to
|
||||
# further pages. This helps to make important links stand out.
|
||||
# Set to '' if not wanted, or '...' is quite a good one.
|
||||
pagelinkicon='... <img src="http://pelican.cl.cam.ac.uk/icons/page.xbm"> '
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# Less important personal preferences:
|
||||
|
||||
# Sublistsize controls the maximum number of items the will appear as
|
||||
# an indented sub-list before the whole thing is moved onto a different
|
||||
# page. The smaller this is, the more pages you will have, but the
|
||||
# shorter each will be.
|
||||
sublistsize = 4
|
||||
|
||||
# That should be all. #
|
||||
#######################################################################
|
||||
|
||||
for dir in os.curdir, os.environ['HOME']:
|
||||
rcfile = os.path.join(dir, '.newslistrc.py')
|
||||
if os.path.exists(rcfile):
|
||||
print rcfile
|
||||
execfile(rcfile)
|
||||
break
|
||||
|
||||
from nntplib import NNTP
|
||||
from stat import *
|
||||
|
||||
rcsrev = '$Revision$'
|
||||
rcsrev = string.join(filter(lambda s: '$' not in s, string.split(rcsrev)))
|
||||
desc = {}
|
||||
|
||||
# Make (possibly) relative filenames into absolute ones
|
||||
treefile = os.path.join(topdir,treefile)
|
||||
descfile = os.path.join(topdir,descfile)
|
||||
page = os.path.join(topdir,pagedir)
|
||||
|
||||
# First the bits for creating trees ---------------------------
|
||||
|
||||
# Addtotree creates/augments a tree from a list of group names
|
||||
def addtotree(tree, groups):
|
||||
print 'Updating tree...'
|
||||
for i in groups:
|
||||
parts = string.splitfields(i,'.')
|
||||
makeleaf(tree, parts)
|
||||
|
||||
# Makeleaf makes a leaf and the branch leading to it if necessary
|
||||
def makeleaf(tree,path):
|
||||
j = path[0]
|
||||
l = len(path)
|
||||
|
||||
if not tree.has_key(j):
|
||||
tree[j] = {}
|
||||
if l == 1:
|
||||
tree[j]['.'] = '.'
|
||||
if l > 1:
|
||||
makeleaf(tree[j],path[1:])
|
||||
|
||||
# Then the bits for outputting trees as pages ----------------
|
||||
|
||||
# Createpage creates an HTML file named <root>.html containing links
|
||||
# to those groups beginning with <root>.
|
||||
|
||||
def createpage(root, tree, p):
|
||||
filename = os.path.join(pagedir,root+'.html')
|
||||
if root == rootpage:
|
||||
detail = ''
|
||||
else:
|
||||
detail = ' under ' + root
|
||||
f = open(filename,'w')
|
||||
# f.write('Content-Type: text/html\n')
|
||||
f.write('<TITLE>Newsgroups available' + detail + '</TITLE>\n')
|
||||
f.write('<H1>Newsgroups available' + detail +'</H1>\n')
|
||||
f.write('<A HREF="'+httppref+rootpage+'.html">Back to top level</A><P>\n')
|
||||
printtree(f,tree,0,p)
|
||||
f.write('<I>This page automatically created by \'newslist\' v. '+rcsrev+'.')
|
||||
f.write(time.ctime(time.time()) + '</I><P>')
|
||||
f.close()
|
||||
|
||||
# Printtree prints the groups as a bulleted list. Groups with
|
||||
# more than <sublistsize> subgroups will be put on a separate page.
|
||||
# Other sets of subgroups are just indented.
|
||||
|
||||
def printtree(f, tree, indent, p):
|
||||
global desc
|
||||
l = len(tree)
|
||||
|
||||
if l > sublistsize and indent>0:
|
||||
# Create a new page and a link to it
|
||||
f.write('<LI><B><A HREF="'+httppref+p[1:]+'.html">')
|
||||
f.write(p[1:]+'.*')
|
||||
f.write('</A></B>'+pagelinkicon+'\n')
|
||||
createpage(p[1:], tree, p)
|
||||
return
|
||||
|
||||
kl = tree.keys()
|
||||
|
||||
if l > 1:
|
||||
kl.sort()
|
||||
if indent > 0:
|
||||
# Create a sub-list
|
||||
f.write('<LI>'+p[1:]+'\n<UL>')
|
||||
else:
|
||||
# Create a main list
|
||||
f.write('<UL>')
|
||||
indent = indent + 1
|
||||
|
||||
for i in kl:
|
||||
if i == '.':
|
||||
# Output a newsgroup
|
||||
f.write('<LI><A HREF="news:' + p[1:] + '">'+ p[1:] + '</A> ')
|
||||
if desc.has_key(p[1:]):
|
||||
f.write(' <I>'+desc[p[1:]]+'</I>\n')
|
||||
else:
|
||||
f.write('\n')
|
||||
else:
|
||||
# Output a hierarchy
|
||||
printtree(f,tree[i], indent, p+'.'+i)
|
||||
|
||||
if l > 1:
|
||||
f.write('\n</UL>')
|
||||
|
||||
# Reading descriptions file ---------------------------------------
|
||||
|
||||
# This returns an array mapping group name to its description
|
||||
|
||||
def readdesc(descfile):
|
||||
global desc
|
||||
|
||||
desc = {}
|
||||
|
||||
if descfile == '':
|
||||
return
|
||||
|
||||
try:
|
||||
d = open(descfile, 'r')
|
||||
print 'Reading descriptions...'
|
||||
except (IOError):
|
||||
print 'Failed to open description file ' + descfile
|
||||
return
|
||||
l = d.readline()
|
||||
while l != '':
|
||||
bits = string.split(l)
|
||||
try:
|
||||
grp = bits[0]
|
||||
dsc = string.join(bits[1:])
|
||||
if len(dsc)>1:
|
||||
desc[grp] = dsc
|
||||
except (IndexError):
|
||||
pass
|
||||
l = d.readline()
|
||||
|
||||
# Check that ouput directory exists, ------------------------------
|
||||
# and offer to create it if not
|
||||
|
||||
def checkopdir(pagedir):
|
||||
if not os.path.isdir(pagedir):
|
||||
print 'Directory '+pagedir+' does not exist.'
|
||||
print 'Shall I create it for you? (y/n)'
|
||||
if sys.stdin.readline()[0] == 'y':
|
||||
try:
|
||||
os.mkdir(pagedir,0777)
|
||||
except:
|
||||
print 'Sorry - failed!'
|
||||
sys.exit(1)
|
||||
else:
|
||||
print 'OK. Exiting.'
|
||||
sys.exit(1)
|
||||
|
||||
# Read and write current local tree ----------------------------------
|
||||
|
||||
def readlocallist(treefile):
|
||||
print 'Reading current local group list...'
|
||||
tree = {}
|
||||
try:
|
||||
treetime = time.localtime(os.stat(treefile)[ST_MTIME])
|
||||
except:
|
||||
print '\n*** Failed to open local group cache '+treefile
|
||||
print 'If this is the first time you have run newslist, then'
|
||||
print 'use the -a option to create it.'
|
||||
sys.exit(1)
|
||||
treedate = '%02d%02d%02d' % (treetime[0] % 100 ,treetime[1], treetime[2])
|
||||
try:
|
||||
dump = open(treefile,'r')
|
||||
tree = marshal.load(dump)
|
||||
dump.close()
|
||||
except (IOError):
|
||||
print 'Cannot open local group list ' + treefile
|
||||
return (tree, treedate)
|
||||
|
||||
def writelocallist(treefile, tree):
|
||||
try:
|
||||
dump = open(treefile,'w')
|
||||
groups = marshal.dump(tree,dump)
|
||||
dump.close()
|
||||
print 'Saved list to '+treefile+'\n'
|
||||
except:
|
||||
print 'Sorry - failed to write to local group cache '+treefile
|
||||
print 'Does it (or its directory) have the correct permissions?'
|
||||
sys.exit(1)
|
||||
|
||||
# Return list of all groups on server -----------------------------
|
||||
|
||||
def getallgroups(server):
|
||||
print 'Getting list of all groups...'
|
||||
treedate='010101'
|
||||
info = server.list()[1]
|
||||
groups = []
|
||||
print 'Processing...'
|
||||
if skipempty:
|
||||
print '\nIgnoring following empty groups:'
|
||||
for i in info:
|
||||
grpname = string.split(i[0])[0]
|
||||
if skipempty and string.atoi(i[1]) < string.atoi(i[2]):
|
||||
print grpname+' ',
|
||||
else:
|
||||
groups.append(grpname)
|
||||
print '\n'
|
||||
if skipempty:
|
||||
print '(End of empty groups)'
|
||||
return groups
|
||||
|
||||
# Return list of new groups on server -----------------------------
|
||||
|
||||
def getnewgroups(server, treedate):
|
||||
print 'Getting list of new groups since start of '+treedate+'...',
|
||||
info = server.newgroups(treedate,'000001')[1]
|
||||
print 'got %d.' % len(info)
|
||||
print 'Processing...',
|
||||
groups = []
|
||||
for i in info:
|
||||
grpname = string.split(i)[0]
|
||||
groups.append(grpname)
|
||||
print 'Done'
|
||||
return groups
|
||||
|
||||
# Now the main program --------------------------------------------
|
||||
|
||||
def main():
|
||||
global desc
|
||||
|
||||
tree={}
|
||||
|
||||
# Check that the output directory exists
|
||||
checkopdir(pagedir)
|
||||
|
||||
try:
|
||||
print 'Connecting to '+newshost+'...'
|
||||
if sys.version[0] == '0':
|
||||
s = NNTP.init(newshost)
|
||||
else:
|
||||
s = NNTP(newshost)
|
||||
connected = 1
|
||||
except (nntplib.error_temp, nntplib.error_perm), x:
|
||||
print 'Error connecting to host:', x
|
||||
print 'I\'ll try to use just the local list.'
|
||||
connected = 0
|
||||
|
||||
# If -a is specified, read the full list of groups from server
|
||||
if connected and len(sys.argv) > 1 and sys.argv[1] == '-a':
|
||||
|
||||
groups = getallgroups(s)
|
||||
|
||||
# Otherwise just read the local file and then add
|
||||
# groups created since local file last modified.
|
||||
else:
|
||||
|
||||
(tree, treedate) = readlocallist(treefile)
|
||||
if connected:
|
||||
groups = getnewgroups(s, treedate)
|
||||
|
||||
if connected:
|
||||
addtotree(tree, groups)
|
||||
writelocallist(treefile,tree)
|
||||
|
||||
# Read group descriptions
|
||||
readdesc(descfile)
|
||||
|
||||
print 'Creating pages...'
|
||||
createpage(rootpage, tree, '')
|
||||
print 'Done'
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
# That's all folks
|
||||
######################################################################
|
@ -1,34 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Print digits of pi forever.
|
||||
#
|
||||
# The algorithm, using Python's 'long' integers ("bignums"), works
|
||||
# with continued fractions, and was conceived by Lambert Meertens.
|
||||
#
|
||||
# See also the ABC Programmer's Handbook, by Geurts, Meertens & Pemberton,
|
||||
# published by Prentice-Hall (UK) Ltd., 1990.
|
||||
|
||||
import sys
|
||||
|
||||
def main():
|
||||
k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L
|
||||
while 1:
|
||||
# Next approximation
|
||||
p, q, k = k*k, 2L*k+1L, k+1L
|
||||
a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
|
||||
# Print common digits
|
||||
d, d1 = a//b, a1//b1
|
||||
while d == d1:
|
||||
output(d)
|
||||
a, a1 = 10L*(a%b), 10L*(a1%b1)
|
||||
d, d1 = a//b, a1//b1
|
||||
|
||||
def output(d):
|
||||
# Use write() to avoid spaces between the digits
|
||||
# Use str() to avoid the 'L'
|
||||
sys.stdout.write(str(d))
|
||||
# Flush so the output is seen immediately
|
||||
sys.stdout.flush()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,130 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Emulate some Perl command line options.
|
||||
# Usage: pp [-a] [-c] [-d] [-e scriptline] [-F fieldsep] [-n] [-p] [file] ...
|
||||
# Where the options mean the following:
|
||||
# -a : together with -n or -p, splits each line into list F
|
||||
# -c : check syntax only, do not execute any code
|
||||
# -d : run the script under the debugger, pdb
|
||||
# -e scriptline : gives one line of the Python script; may be repeated
|
||||
# -F fieldsep : sets the field separator for the -a option [not in Perl]
|
||||
# -n : runs the script for each line of input
|
||||
# -p : prints the line after the script has run
|
||||
# When no script lines have been passed, the first file argument
|
||||
# contains the script. With -n or -p, the remaining arguments are
|
||||
# read as input to the script, line by line. If a file is '-'
|
||||
# or missing, standard input is read.
|
||||
|
||||
# XXX To do:
|
||||
# - add -i extension option (change files in place)
|
||||
# - make a single loop over the files and lines (changes effect of 'break')?
|
||||
# - add an option to specify the record separator
|
||||
# - except for -n/-p, run directly from the file if at all possible
|
||||
|
||||
import sys
|
||||
import string
|
||||
import getopt
|
||||
|
||||
FS = ''
|
||||
SCRIPT = []
|
||||
AFLAG = 0
|
||||
CFLAG = 0
|
||||
DFLAG = 0
|
||||
NFLAG = 0
|
||||
PFLAG = 0
|
||||
|
||||
try:
|
||||
optlist, ARGS = getopt.getopt(sys.argv[1:], 'acde:F:np')
|
||||
except getopt.error, msg:
|
||||
sys.stderr.write(sys.argv[0] + ': ' + msg + '\n')
|
||||
sys.exit(2)
|
||||
|
||||
for option, optarg in optlist:
|
||||
if option == '-a':
|
||||
AFLAG = 1
|
||||
elif option == '-c':
|
||||
CFLAG = 1
|
||||
elif option == '-d':
|
||||
DFLAG = 1
|
||||
elif option == '-e':
|
||||
for line in string.splitfields(optarg, '\n'):
|
||||
SCRIPT.append(line)
|
||||
elif option == '-F':
|
||||
FS = optarg
|
||||
elif option == '-n':
|
||||
NFLAG = 1
|
||||
PFLAG = 0
|
||||
elif option == '-p':
|
||||
NFLAG = 1
|
||||
PFLAG = 1
|
||||
else:
|
||||
print option, 'not recognized???'
|
||||
|
||||
if not ARGS: ARGS.append('-')
|
||||
|
||||
if not SCRIPT:
|
||||
if ARGS[0] == '-':
|
||||
fp = sys.stdin
|
||||
else:
|
||||
fp = open(ARGS[0], 'r')
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line: break
|
||||
SCRIPT.append(line[:-1])
|
||||
del fp
|
||||
del ARGS[0]
|
||||
if not ARGS: ARGS.append('-')
|
||||
|
||||
if CFLAG:
|
||||
prologue = ['if 0:']
|
||||
epilogue = []
|
||||
elif NFLAG:
|
||||
# Note that it is on purpose that AFLAG and PFLAG are
|
||||
# tested dynamically each time through the loop
|
||||
prologue = [ \
|
||||
'LINECOUNT = 0', \
|
||||
'for FILE in ARGS:', \
|
||||
' \tif FILE == \'-\':', \
|
||||
' \t \tFP = sys.stdin', \
|
||||
' \telse:', \
|
||||
' \t \tFP = open(FILE, \'r\')', \
|
||||
' \tLINENO = 0', \
|
||||
' \twhile 1:', \
|
||||
' \t \tLINE = FP.readline()', \
|
||||
' \t \tif not LINE: break', \
|
||||
' \t \tLINENO = LINENO + 1', \
|
||||
' \t \tLINECOUNT = LINECOUNT + 1', \
|
||||
' \t \tL = LINE[:-1]', \
|
||||
' \t \taflag = AFLAG', \
|
||||
' \t \tif aflag:', \
|
||||
' \t \t \tif FS: F = string.splitfields(L, FS)', \
|
||||
' \t \t \telse: F = string.split(L)' \
|
||||
]
|
||||
epilogue = [ \
|
||||
' \t \tif not PFLAG: continue', \
|
||||
' \t \tif aflag:', \
|
||||
' \t \t \tif FS: print string.joinfields(F, FS)', \
|
||||
' \t \t \telse: print string.join(F)', \
|
||||
' \t \telse: print L', \
|
||||
]
|
||||
else:
|
||||
prologue = ['if 1:']
|
||||
epilogue = []
|
||||
|
||||
# Note that we indent using tabs only, so that any indentation style
|
||||
# used in 'command' will come out right after re-indentation.
|
||||
|
||||
program = string.joinfields(prologue, '\n') + '\n'
|
||||
for line in SCRIPT:
|
||||
program = program + (' \t \t' + line + '\n')
|
||||
program = program + (string.joinfields(epilogue, '\n') + '\n')
|
||||
|
||||
import tempfile
|
||||
fp = tempfile.NamedTemporaryFile()
|
||||
fp.write(program)
|
||||
fp.flush()
|
||||
if DFLAG:
|
||||
import pdb
|
||||
pdb.run('execfile(%r)' % (tfn,))
|
||||
else:
|
||||
execfile(tfn)
|
@ -1,27 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Print prime numbers in a given range
|
||||
|
||||
def main():
|
||||
import sys
|
||||
min, max = 2, 0x7fffffff
|
||||
if sys.argv[1:]:
|
||||
min = int(eval(sys.argv[1]))
|
||||
if sys.argv[2:]:
|
||||
max = int(eval(sys.argv[2]))
|
||||
primes(min, max)
|
||||
|
||||
def primes(min, max):
|
||||
if 2 >= min: print 2
|
||||
primes = [2]
|
||||
i = 3
|
||||
while i <= max:
|
||||
for p in primes:
|
||||
if i%p == 0 or p*p > i: break
|
||||
if i%p <> 0:
|
||||
primes.append(i)
|
||||
if i >= min: print i
|
||||
i = i+2
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,85 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
"""N queens problem.
|
||||
|
||||
The (well-known) problem is due to Niklaus Wirth.
|
||||
|
||||
This solution is inspired by Dijkstra (Structured Programming). It is
|
||||
a classic recursive backtracking approach.
|
||||
|
||||
"""
|
||||
|
||||
N = 8 # Default; command line overrides
|
||||
|
||||
class Queens:
|
||||
|
||||
def __init__(self, n=N):
|
||||
self.n = n
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
n = self.n
|
||||
self.y = [None]*n # Where is the queen in column x
|
||||
self.row = [0]*n # Is row[y] safe?
|
||||
self.up = [0] * (2*n-1) # Is upward diagonal[x-y] safe?
|
||||
self.down = [0] * (2*n-1) # Is downward diagonal[x+y] safe?
|
||||
self.nfound = 0 # Instrumentation
|
||||
|
||||
def solve(self, x=0): # Recursive solver
|
||||
for y in range(self.n):
|
||||
if self.safe(x, y):
|
||||
self.place(x, y)
|
||||
if x+1 == self.n:
|
||||
self.display()
|
||||
else:
|
||||
self.solve(x+1)
|
||||
self.remove(x, y)
|
||||
|
||||
def safe(self, x, y):
|
||||
return not self.row[y] and not self.up[x-y] and not self.down[x+y]
|
||||
|
||||
def place(self, x, y):
|
||||
self.y[x] = y
|
||||
self.row[y] = 1
|
||||
self.up[x-y] = 1
|
||||
self.down[x+y] = 1
|
||||
|
||||
def remove(self, x, y):
|
||||
self.y[x] = None
|
||||
self.row[y] = 0
|
||||
self.up[x-y] = 0
|
||||
self.down[x+y] = 0
|
||||
|
||||
silent = 0 # If set, count solutions only
|
||||
|
||||
def display(self):
|
||||
self.nfound = self.nfound + 1
|
||||
if self.silent:
|
||||
return
|
||||
print '+-' + '--'*self.n + '+'
|
||||
for y in range(self.n-1, -1, -1):
|
||||
print '|',
|
||||
for x in range(self.n):
|
||||
if self.y[x] == y:
|
||||
print "Q",
|
||||
else:
|
||||
print ".",
|
||||
print '|'
|
||||
print '+-' + '--'*self.n + '+'
|
||||
|
||||
def main():
|
||||
import sys
|
||||
silent = 0
|
||||
n = N
|
||||
if sys.argv[1:2] == ['-n']:
|
||||
silent = 1
|
||||
del sys.argv[1]
|
||||
if sys.argv[1:]:
|
||||
n = int(sys.argv[1])
|
||||
q = Queens(n)
|
||||
q.silent = silent
|
||||
q.solve()
|
||||
print "Found", q.nfound, "solutions."
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,33 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
# script.py -- Make typescript of terminal session.
|
||||
# Usage:
|
||||
# -a Append to typescript.
|
||||
# -p Use Python as shell.
|
||||
# Author: Steen Lumholt.
|
||||
|
||||
|
||||
import os, time, sys
|
||||
import pty
|
||||
|
||||
def read(fd):
|
||||
data = os.read(fd, 1024)
|
||||
file.write(data)
|
||||
return data
|
||||
|
||||
shell = 'sh'
|
||||
filename = 'typescript'
|
||||
mode = 'w'
|
||||
if os.environ.has_key('SHELL'):
|
||||
shell = os.environ['SHELL']
|
||||
if '-a' in sys.argv:
|
||||
mode = 'a'
|
||||
if '-p' in sys.argv:
|
||||
shell = 'python'
|
||||
|
||||
file = open(filename, mode)
|
||||
|
||||
sys.stdout.write('Script started, file is %s\n' % filename)
|
||||
file.write('Script started on %s\n' % time.ctime(time.time()))
|
||||
pty.spawn(shell, read)
|
||||
file.write('Script done on %s\n' % time.ctime(time.time()))
|
||||
sys.stdout.write('Script done, file is %s\n' % filename)
|
@ -1,107 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
# Calculate your unbirthday count (see Alice in Wonderland).
|
||||
# This is defined as the number of days from your birth until today
|
||||
# that weren't your birthday. (The day you were born is not counted).
|
||||
# Leap years make it interesting.
|
||||
|
||||
import sys
|
||||
import time
|
||||
import calendar
|
||||
|
||||
def main():
|
||||
# Note that the range checks below also check for bad types,
|
||||
# e.g. 3.14 or (). However syntactically invalid replies
|
||||
# will raise an exception.
|
||||
if sys.argv[1:]:
|
||||
year = int(sys.argv[1])
|
||||
else:
|
||||
year = int(raw_input('In which year were you born? '))
|
||||
if 0<=year<100:
|
||||
print "I'll assume that by", year,
|
||||
year = year + 1900
|
||||
print 'you mean', year, 'and not the early Christian era'
|
||||
elif not (1850<=year<=2002):
|
||||
print "It's hard to believe you were born in", year
|
||||
return
|
||||
#
|
||||
if sys.argv[2:]:
|
||||
month = int(sys.argv[2])
|
||||
else:
|
||||
month = int(raw_input('And in which month? (1-12) '))
|
||||
if not (1<=month<=12):
|
||||
print 'There is no month numbered', month
|
||||
return
|
||||
#
|
||||
if sys.argv[3:]:
|
||||
day = int(sys.argv[3])
|
||||
else:
|
||||
day = int(raw_input('And on what day of that month? (1-31) '))
|
||||
if month == 2 and calendar.isleap(year):
|
||||
maxday = 29
|
||||
else:
|
||||
maxday = calendar.mdays[month]
|
||||
if not (1<=day<=maxday):
|
||||
print 'There are no', day, 'days in that month!'
|
||||
return
|
||||
#
|
||||
bdaytuple = (year, month, day)
|
||||
bdaydate = mkdate(bdaytuple)
|
||||
print 'You were born on', format(bdaytuple)
|
||||
#
|
||||
todaytuple = time.localtime()[:3]
|
||||
todaydate = mkdate(todaytuple)
|
||||
print 'Today is', format(todaytuple)
|
||||
#
|
||||
if bdaytuple > todaytuple:
|
||||
print 'You are a time traveler. Go back to the future!'
|
||||
return
|
||||
#
|
||||
if bdaytuple == todaytuple:
|
||||
print 'You were born today. Have a nice life!'
|
||||
return
|
||||
#
|
||||
days = todaydate - bdaydate
|
||||
print 'You have lived', days, 'days'
|
||||
#
|
||||
age = 0
|
||||
for y in range(year, todaytuple[0] + 1):
|
||||
if bdaytuple < (y, month, day) <= todaytuple:
|
||||
age = age + 1
|
||||
#
|
||||
print 'You are', age, 'years old'
|
||||
#
|
||||
if todaytuple[1:] == bdaytuple[1:]:
|
||||
print 'Congratulations! Today is your', nth(age), 'birthday'
|
||||
print 'Yesterday was your',
|
||||
else:
|
||||
print 'Today is your',
|
||||
print nth(days - age), 'unbirthday'
|
||||
|
||||
def format((year, month, day)):
|
||||
return '%d %s %d' % (day, calendar.month_name[month], year)
|
||||
|
||||
def nth(n):
|
||||
if n == 1: return '1st'
|
||||
if n == 2: return '2nd'
|
||||
if n == 3: return '3rd'
|
||||
return '%dth' % n
|
||||
|
||||
def mkdate((year, month, day)):
|
||||
# Januari 1st, in 0 A.D. is arbitrarily defined to be day 1,
|
||||
# even though that day never actually existed and the calendar
|
||||
# was different then...
|
||||
days = year*365 # years, roughly
|
||||
days = days + (year+3)//4 # plus leap years, roughly
|
||||
days = days - (year+99)//100 # minus non-leap years every century
|
||||
days = days + (year+399)//400 # plus leap years every 4 centirues
|
||||
for i in range(1, month):
|
||||
if i == 2 and calendar.isleap(year):
|
||||
days = days + 29
|
||||
else:
|
||||
days = days + calendar.mdays[i]
|
||||
days = days + day
|
||||
return days
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,2 +0,0 @@
|
||||
# This is here so I can use 'wh' instead of 'which' in '~/bin/generic_python'
|
||||
import which
|
@ -1,21 +0,0 @@
|
||||
This directory contains some demonstrations of the socket module:
|
||||
|
||||
broadcast.py Broadcast the time to radio.py.
|
||||
echosvr.py About the simplest TCP server possible.
|
||||
finger.py Client for the 'finger' protocol.
|
||||
ftp.py A very simple ftp client.
|
||||
gopher.py A simple gopher client.
|
||||
radio.py Receive time broadcasts from broadcast.py.
|
||||
telnet.py Client for the 'telnet' protocol.
|
||||
throughput.py Client and server to measure TCP throughput.
|
||||
unixclient.py Unix socket example, client side
|
||||
unixserver.py Unix socket example, server side
|
||||
udpecho.py Client and server for the UDP echo protocol.
|
||||
|
||||
The following file is only relevant on SGI machines (or other systems
|
||||
that support multicast):
|
||||
|
||||
mcast.py A Python translation of
|
||||
/usr/people/4Dgifts/examples/network/mcast.c
|
||||
(Note that IN.py is in ../../lib/sgi.)
|
||||
|
@ -1,93 +0,0 @@
|
||||
# Send/receive UDP multicast packets.
|
||||
# Requires that your OS kernel supports IP multicast.
|
||||
# This is built-in on SGI, still optional for most other vendors.
|
||||
#
|
||||
# Usage:
|
||||
# mcast -s (sender)
|
||||
# mcast -b (sender, using broadcast instead multicast)
|
||||
# mcast (receivers)
|
||||
|
||||
MYPORT = 8123
|
||||
MYGROUP = '225.0.0.250'
|
||||
|
||||
import sys
|
||||
import time
|
||||
import struct
|
||||
from socket import *
|
||||
|
||||
|
||||
# Main program
|
||||
def main():
|
||||
flags = sys.argv[1:]
|
||||
#
|
||||
if flags:
|
||||
sender(flags[0])
|
||||
else:
|
||||
receiver()
|
||||
|
||||
|
||||
# Sender subroutine (only one per local area network)
|
||||
def sender(flag):
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
if flag == '-b':
|
||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
mygroup = '<broadcast>'
|
||||
else:
|
||||
mygroup = MYGROUP
|
||||
ttl = struct.pack('b', 1) # Time-to-live
|
||||
s.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, ttl)
|
||||
while 1:
|
||||
data = repr(time.time())
|
||||
## data = data + (1400 - len(data)) * '\0'
|
||||
s.sendto(data, (mygroup, MYPORT))
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
# Receiver subroutine (as many as you like)
|
||||
def receiver():
|
||||
# Open and initialize the socket
|
||||
s = openmcastsock(MYGROUP, MYPORT)
|
||||
#
|
||||
# Loop, printing any data we receive
|
||||
while 1:
|
||||
data, sender = s.recvfrom(1500)
|
||||
while data[-1:] == '\0': data = data[:-1] # Strip trailing \0's
|
||||
print sender, ':', repr(data)
|
||||
|
||||
|
||||
# Open a UDP socket, bind it to a port and select a multicast group
|
||||
def openmcastsock(group, port):
|
||||
# Import modules used only here
|
||||
import string
|
||||
import struct
|
||||
#
|
||||
# Create a socket
|
||||
s = socket(AF_INET, SOCK_DGRAM)
|
||||
#
|
||||
# Allow multiple copies of this program on one machine
|
||||
# (not strictly needed)
|
||||
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
|
||||
#
|
||||
# Bind it to the port
|
||||
s.bind(('', port))
|
||||
#
|
||||
# Look up multicast group address in name server
|
||||
# (doesn't hurt if it is already in ddd.ddd.ddd.ddd format)
|
||||
group = gethostbyname(group)
|
||||
#
|
||||
# Construct binary group address
|
||||
bytes = map(int, string.split(group, "."))
|
||||
grpaddr = 0
|
||||
for byte in bytes: grpaddr = (grpaddr << 8) | byte
|
||||
#
|
||||
# Construct struct mreq from grpaddr and ifaddr
|
||||
ifaddr = INADDR_ANY
|
||||
mreq = struct.pack('ll', htonl(grpaddr), htonl(ifaddr))
|
||||
#
|
||||
# Add group membership
|
||||
s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, mreq)
|
||||
#
|
||||
return s
|
||||
|
||||
|
||||
main()
|
@ -1,603 +0,0 @@
|
||||
# Defines classes that provide synchronization objects. Note that use of
|
||||
# this module requires that your Python support threads.
|
||||
#
|
||||
# condition(lock=None) # a POSIX-like condition-variable object
|
||||
# barrier(n) # an n-thread barrier
|
||||
# event() # an event object
|
||||
# semaphore(n=1) # a semaphore object, with initial count n
|
||||
# mrsw() # a multiple-reader single-writer lock
|
||||
#
|
||||
# CONDITIONS
|
||||
#
|
||||
# A condition object is created via
|
||||
# import this_module
|
||||
# your_condition_object = this_module.condition(lock=None)
|
||||
#
|
||||
# As explained below, a condition object has a lock associated with it,
|
||||
# used in the protocol to protect condition data. You can specify a
|
||||
# lock to use in the constructor, else the constructor will allocate
|
||||
# an anonymous lock for you. Specifying a lock explicitly can be useful
|
||||
# when more than one condition keys off the same set of shared data.
|
||||
#
|
||||
# Methods:
|
||||
# .acquire()
|
||||
# acquire the lock associated with the condition
|
||||
# .release()
|
||||
# release the lock associated with the condition
|
||||
# .wait()
|
||||
# block the thread until such time as some other thread does a
|
||||
# .signal or .broadcast on the same condition, and release the
|
||||
# lock associated with the condition. The lock associated with
|
||||
# the condition MUST be in the acquired state at the time
|
||||
# .wait is invoked.
|
||||
# .signal()
|
||||
# wake up exactly one thread (if any) that previously did a .wait
|
||||
# on the condition; that thread will awaken with the lock associated
|
||||
# with the condition in the acquired state. If no threads are
|
||||
# .wait'ing, this is a nop. If more than one thread is .wait'ing on
|
||||
# the condition, any of them may be awakened.
|
||||
# .broadcast()
|
||||
# wake up all threads (if any) that are .wait'ing on the condition;
|
||||
# the threads are woken up serially, each with the lock in the
|
||||
# acquired state, so should .release() as soon as possible. If no
|
||||
# threads are .wait'ing, this is a nop.
|
||||
#
|
||||
# Note that if a thread does a .wait *while* a signal/broadcast is
|
||||
# in progress, it's guaranteeed to block until a subsequent
|
||||
# signal/broadcast.
|
||||
#
|
||||
# Secret feature: `broadcast' actually takes an integer argument,
|
||||
# and will wake up exactly that many waiting threads (or the total
|
||||
# number waiting, if that's less). Use of this is dubious, though,
|
||||
# and probably won't be supported if this form of condition is
|
||||
# reimplemented in C.
|
||||
#
|
||||
# DIFFERENCES FROM POSIX
|
||||
#
|
||||
# + A separate mutex is not needed to guard condition data. Instead, a
|
||||
# condition object can (must) be .acquire'ed and .release'ed directly.
|
||||
# This eliminates a common error in using POSIX conditions.
|
||||
#
|
||||
# + Because of implementation difficulties, a POSIX `signal' wakes up
|
||||
# _at least_ one .wait'ing thread. Race conditions make it difficult
|
||||
# to stop that. This implementation guarantees to wake up only one,
|
||||
# but you probably shouldn't rely on that.
|
||||
#
|
||||
# PROTOCOL
|
||||
#
|
||||
# Condition objects are used to block threads until "some condition" is
|
||||
# true. E.g., a thread may wish to wait until a producer pumps out data
|
||||
# for it to consume, or a server may wish to wait until someone requests
|
||||
# its services, or perhaps a whole bunch of threads want to wait until a
|
||||
# preceding pass over the data is complete. Early models for conditions
|
||||
# relied on some other thread figuring out when a blocked thread's
|
||||
# condition was true, and made the other thread responsible both for
|
||||
# waking up the blocked thread and guaranteeing that it woke up with all
|
||||
# data in a correct state. This proved to be very delicate in practice,
|
||||
# and gave conditions a bad name in some circles.
|
||||
#
|
||||
# The POSIX model addresses these problems by making a thread responsible
|
||||
# for ensuring that its own state is correct when it wakes, and relies
|
||||
# on a rigid protocol to make this easy; so long as you stick to the
|
||||
# protocol, POSIX conditions are easy to "get right":
|
||||
#
|
||||
# A) The thread that's waiting for some arbitrarily-complex condition
|
||||
# (ACC) to become true does:
|
||||
#
|
||||
# condition.acquire()
|
||||
# while not (code to evaluate the ACC):
|
||||
# condition.wait()
|
||||
# # That blocks the thread, *and* releases the lock. When a
|
||||
# # condition.signal() happens, it will wake up some thread that
|
||||
# # did a .wait, *and* acquire the lock again before .wait
|
||||
# # returns.
|
||||
# #
|
||||
# # Because the lock is acquired at this point, the state used
|
||||
# # in evaluating the ACC is frozen, so it's safe to go back &
|
||||
# # reevaluate the ACC.
|
||||
#
|
||||
# # At this point, ACC is true, and the thread has the condition
|
||||
# # locked.
|
||||
# # So code here can safely muck with the shared state that
|
||||
# # went into evaluating the ACC -- if it wants to.
|
||||
# # When done mucking with the shared state, do
|
||||
# condition.release()
|
||||
#
|
||||
# B) Threads that are mucking with shared state that may affect the
|
||||
# ACC do:
|
||||
#
|
||||
# condition.acquire()
|
||||
# # muck with shared state
|
||||
# condition.release()
|
||||
# if it's possible that ACC is true now:
|
||||
# condition.signal() # or .broadcast()
|
||||
#
|
||||
# Note: You may prefer to put the "if" clause before the release().
|
||||
# That's fine, but do note that anyone waiting on the signal will
|
||||
# stay blocked until the release() is done (since acquiring the
|
||||
# condition is part of what .wait() does before it returns).
|
||||
#
|
||||
# TRICK OF THE TRADE
|
||||
#
|
||||
# With simpler forms of conditions, it can be impossible to know when
|
||||
# a thread that's supposed to do a .wait has actually done it. But
|
||||
# because this form of condition releases a lock as _part_ of doing a
|
||||
# wait, the state of that lock can be used to guarantee it.
|
||||
#
|
||||
# E.g., suppose thread A spawns thread B and later wants to wait for B to
|
||||
# complete:
|
||||
#
|
||||
# In A: In B:
|
||||
#
|
||||
# B_done = condition() ... do work ...
|
||||
# B_done.acquire() B_done.acquire(); B_done.release()
|
||||
# spawn B B_done.signal()
|
||||
# ... some time later ... ... and B exits ...
|
||||
# B_done.wait()
|
||||
#
|
||||
# Because B_done was in the acquire'd state at the time B was spawned,
|
||||
# B's attempt to acquire B_done can't succeed until A has done its
|
||||
# B_done.wait() (which releases B_done). So B's B_done.signal() is
|
||||
# guaranteed to be seen by the .wait(). Without the lock trick, B
|
||||
# may signal before A .waits, and then A would wait forever.
|
||||
#
|
||||
# BARRIERS
|
||||
#
|
||||
# A barrier object is created via
|
||||
# import this_module
|
||||
# your_barrier = this_module.barrier(num_threads)
|
||||
#
|
||||
# Methods:
|
||||
# .enter()
|
||||
# the thread blocks until num_threads threads in all have done
|
||||
# .enter(). Then the num_threads threads that .enter'ed resume,
|
||||
# and the barrier resets to capture the next num_threads threads
|
||||
# that .enter it.
|
||||
#
|
||||
# EVENTS
|
||||
#
|
||||
# An event object is created via
|
||||
# import this_module
|
||||
# your_event = this_module.event()
|
||||
#
|
||||
# An event has two states, `posted' and `cleared'. An event is
|
||||
# created in the cleared state.
|
||||
#
|
||||
# Methods:
|
||||
#
|
||||
# .post()
|
||||
# Put the event in the posted state, and resume all threads
|
||||
# .wait'ing on the event (if any).
|
||||
#
|
||||
# .clear()
|
||||
# Put the event in the cleared state.
|
||||
#
|
||||
# .is_posted()
|
||||
# Returns 0 if the event is in the cleared state, or 1 if the event
|
||||
# is in the posted state.
|
||||
#
|
||||
# .wait()
|
||||
# If the event is in the posted state, returns immediately.
|
||||
# If the event is in the cleared state, blocks the calling thread
|
||||
# until the event is .post'ed by another thread.
|
||||
#
|
||||
# Note that an event, once posted, remains posted until explicitly
|
||||
# cleared. Relative to conditions, this is both the strength & weakness
|
||||
# of events. It's a strength because the .post'ing thread doesn't have to
|
||||
# worry about whether the threads it's trying to communicate with have
|
||||
# already done a .wait (a condition .signal is seen only by threads that
|
||||
# do a .wait _prior_ to the .signal; a .signal does not persist). But
|
||||
# it's a weakness because .clear'ing an event is error-prone: it's easy
|
||||
# to mistakenly .clear an event before all the threads you intended to
|
||||
# see the event get around to .wait'ing on it. But so long as you don't
|
||||
# need to .clear an event, events are easy to use safely.
|
||||
#
|
||||
# SEMAPHORES
|
||||
#
|
||||
# A semaphore object is created via
|
||||
# import this_module
|
||||
# your_semaphore = this_module.semaphore(count=1)
|
||||
#
|
||||
# A semaphore has an integer count associated with it. The initial value
|
||||
# of the count is specified by the optional argument (which defaults to
|
||||
# 1) passed to the semaphore constructor.
|
||||
#
|
||||
# Methods:
|
||||
#
|
||||
# .p()
|
||||
# If the semaphore's count is greater than 0, decrements the count
|
||||
# by 1 and returns.
|
||||
# Else if the semaphore's count is 0, blocks the calling thread
|
||||
# until a subsequent .v() increases the count. When that happens,
|
||||
# the count will be decremented by 1 and the calling thread resumed.
|
||||
#
|
||||
# .v()
|
||||
# Increments the semaphore's count by 1, and wakes up a thread (if
|
||||
# any) blocked by a .p(). It's an (detected) error for a .v() to
|
||||
# increase the semaphore's count to a value larger than the initial
|
||||
# count.
|
||||
#
|
||||
# MULTIPLE-READER SINGLE-WRITER LOCKS
|
||||
#
|
||||
# A mrsw lock is created via
|
||||
# import this_module
|
||||
# your_mrsw_lock = this_module.mrsw()
|
||||
#
|
||||
# This kind of lock is often useful with complex shared data structures.
|
||||
# The object lets any number of "readers" proceed, so long as no thread
|
||||
# wishes to "write". When a (one or more) thread declares its intention
|
||||
# to "write" (e.g., to update a shared structure), all current readers
|
||||
# are allowed to finish, and then a writer gets exclusive access; all
|
||||
# other readers & writers are blocked until the current writer completes.
|
||||
# Finally, if some thread is waiting to write and another is waiting to
|
||||
# read, the writer takes precedence.
|
||||
#
|
||||
# Methods:
|
||||
#
|
||||
# .read_in()
|
||||
# If no thread is writing or waiting to write, returns immediately.
|
||||
# Else blocks until no thread is writing or waiting to write. So
|
||||
# long as some thread has completed a .read_in but not a .read_out,
|
||||
# writers are blocked.
|
||||
#
|
||||
# .read_out()
|
||||
# Use sometime after a .read_in to declare that the thread is done
|
||||
# reading. When all threads complete reading, a writer can proceed.
|
||||
#
|
||||
# .write_in()
|
||||
# If no thread is writing (has completed a .write_in, but hasn't yet
|
||||
# done a .write_out) or reading (similarly), returns immediately.
|
||||
# Else blocks the calling thread, and threads waiting to read, until
|
||||
# the current writer completes writing or all the current readers
|
||||
# complete reading; if then more than one thread is waiting to
|
||||
# write, one of them is allowed to proceed, but which one is not
|
||||
# specified.
|
||||
#
|
||||
# .write_out()
|
||||
# Use sometime after a .write_in to declare that the thread is done
|
||||
# writing. Then if some other thread is waiting to write, it's
|
||||
# allowed to proceed. Else all threads (if any) waiting to read are
|
||||
# allowed to proceed.
|
||||
#
|
||||
# .write_to_read()
|
||||
# Use instead of a .write_in to declare that the thread is done
|
||||
# writing but wants to continue reading without other writers
|
||||
# intervening. If there are other threads waiting to write, they
|
||||
# are allowed to proceed only if the current thread calls
|
||||
# .read_out; threads waiting to read are only allowed to proceed
|
||||
# if there are are no threads waiting to write. (This is a
|
||||
# weakness of the interface!)
|
||||
|
||||
import thread
|
||||
|
||||
class condition:
|
||||
def __init__(self, lock=None):
|
||||
# the lock actually used by .acquire() and .release()
|
||||
if lock is None:
|
||||
self.mutex = thread.allocate_lock()
|
||||
else:
|
||||
if hasattr(lock, 'acquire') and \
|
||||
hasattr(lock, 'release'):
|
||||
self.mutex = lock
|
||||
else:
|
||||
raise TypeError, 'condition constructor requires ' \
|
||||
'a lock argument'
|
||||
|
||||
# lock used to block threads until a signal
|
||||
self.checkout = thread.allocate_lock()
|
||||
self.checkout.acquire()
|
||||
|
||||
# internal critical-section lock, & the data it protects
|
||||
self.idlock = thread.allocate_lock()
|
||||
self.id = 0
|
||||
self.waiting = 0 # num waiters subject to current release
|
||||
self.pending = 0 # num waiters awaiting next signal
|
||||
self.torelease = 0 # num waiters to release
|
||||
self.releasing = 0 # 1 iff release is in progress
|
||||
|
||||
def acquire(self):
|
||||
self.mutex.acquire()
|
||||
|
||||
def release(self):
|
||||
self.mutex.release()
|
||||
|
||||
def wait(self):
|
||||
mutex, checkout, idlock = self.mutex, self.checkout, self.idlock
|
||||
if not mutex.locked():
|
||||
raise ValueError, \
|
||||
"condition must be .acquire'd when .wait() invoked"
|
||||
|
||||
idlock.acquire()
|
||||
myid = self.id
|
||||
self.pending = self.pending + 1
|
||||
idlock.release()
|
||||
|
||||
mutex.release()
|
||||
|
||||
while 1:
|
||||
checkout.acquire(); idlock.acquire()
|
||||
if myid < self.id:
|
||||
break
|
||||
checkout.release(); idlock.release()
|
||||
|
||||
self.waiting = self.waiting - 1
|
||||
self.torelease = self.torelease - 1
|
||||
if self.torelease:
|
||||
checkout.release()
|
||||
else:
|
||||
self.releasing = 0
|
||||
if self.waiting == self.pending == 0:
|
||||
self.id = 0
|
||||
idlock.release()
|
||||
mutex.acquire()
|
||||
|
||||
def signal(self):
|
||||
self.broadcast(1)
|
||||
|
||||
def broadcast(self, num = -1):
|
||||
if num < -1:
|
||||
raise ValueError, '.broadcast called with num %r' % (num,)
|
||||
if num == 0:
|
||||
return
|
||||
self.idlock.acquire()
|
||||
if self.pending:
|
||||
self.waiting = self.waiting + self.pending
|
||||
self.pending = 0
|
||||
self.id = self.id + 1
|
||||
if num == -1:
|
||||
self.torelease = self.waiting
|
||||
else:
|
||||
self.torelease = min( self.waiting,
|
||||
self.torelease + num )
|
||||
if self.torelease and not self.releasing:
|
||||
self.releasing = 1
|
||||
self.checkout.release()
|
||||
self.idlock.release()
|
||||
|
||||
class barrier:
|
||||
def __init__(self, n):
|
||||
self.n = n
|
||||
self.togo = n
|
||||
self.full = condition()
|
||||
|
||||
def enter(self):
|
||||
full = self.full
|
||||
full.acquire()
|
||||
self.togo = self.togo - 1
|
||||
if self.togo:
|
||||
full.wait()
|
||||
else:
|
||||
self.togo = self.n
|
||||
full.broadcast()
|
||||
full.release()
|
||||
|
||||
class event:
|
||||
def __init__(self):
|
||||
self.state = 0
|
||||
self.posted = condition()
|
||||
|
||||
def post(self):
|
||||
self.posted.acquire()
|
||||
self.state = 1
|
||||
self.posted.broadcast()
|
||||
self.posted.release()
|
||||
|
||||
def clear(self):
|
||||
self.posted.acquire()
|
||||
self.state = 0
|
||||
self.posted.release()
|
||||
|
||||
def is_posted(self):
|
||||
self.posted.acquire()
|
||||
answer = self.state
|
||||
self.posted.release()
|
||||
return answer
|
||||
|
||||
def wait(self):
|
||||
self.posted.acquire()
|
||||
if not self.state:
|
||||
self.posted.wait()
|
||||
self.posted.release()
|
||||
|
||||
class semaphore:
|
||||
def __init__(self, count=1):
|
||||
if count <= 0:
|
||||
raise ValueError, 'semaphore count %d; must be >= 1' % count
|
||||
self.count = count
|
||||
self.maxcount = count
|
||||
self.nonzero = condition()
|
||||
|
||||
def p(self):
|
||||
self.nonzero.acquire()
|
||||
while self.count == 0:
|
||||
self.nonzero.wait()
|
||||
self.count = self.count - 1
|
||||
self.nonzero.release()
|
||||
|
||||
def v(self):
|
||||
self.nonzero.acquire()
|
||||
if self.count == self.maxcount:
|
||||
raise ValueError, '.v() tried to raise semaphore count above ' \
|
||||
'initial value %r' % self.maxcount
|
||||
self.count = self.count + 1
|
||||
self.nonzero.signal()
|
||||
self.nonzero.release()
|
||||
|
||||
class mrsw:
|
||||
def __init__(self):
|
||||
# critical-section lock & the data it protects
|
||||
self.rwOK = thread.allocate_lock()
|
||||
self.nr = 0 # number readers actively reading (not just waiting)
|
||||
self.nw = 0 # number writers either waiting to write or writing
|
||||
self.writing = 0 # 1 iff some thread is writing
|
||||
|
||||
# conditions
|
||||
self.readOK = condition(self.rwOK) # OK to unblock readers
|
||||
self.writeOK = condition(self.rwOK) # OK to unblock writers
|
||||
|
||||
def read_in(self):
|
||||
self.rwOK.acquire()
|
||||
while self.nw:
|
||||
self.readOK.wait()
|
||||
self.nr = self.nr + 1
|
||||
self.rwOK.release()
|
||||
|
||||
def read_out(self):
|
||||
self.rwOK.acquire()
|
||||
if self.nr <= 0:
|
||||
raise ValueError, \
|
||||
'.read_out() invoked without an active reader'
|
||||
self.nr = self.nr - 1
|
||||
if self.nr == 0:
|
||||
self.writeOK.signal()
|
||||
self.rwOK.release()
|
||||
|
||||
def write_in(self):
|
||||
self.rwOK.acquire()
|
||||
self.nw = self.nw + 1
|
||||
while self.writing or self.nr:
|
||||
self.writeOK.wait()
|
||||
self.writing = 1
|
||||
self.rwOK.release()
|
||||
|
||||
def write_out(self):
|
||||
self.rwOK.acquire()
|
||||
if not self.writing:
|
||||
raise ValueError, \
|
||||
'.write_out() invoked without an active writer'
|
||||
self.writing = 0
|
||||
self.nw = self.nw - 1
|
||||
if self.nw:
|
||||
self.writeOK.signal()
|
||||
else:
|
||||
self.readOK.broadcast()
|
||||
self.rwOK.release()
|
||||
|
||||
def write_to_read(self):
|
||||
self.rwOK.acquire()
|
||||
if not self.writing:
|
||||
raise ValueError, \
|
||||
'.write_to_read() invoked without an active writer'
|
||||
self.writing = 0
|
||||
self.nw = self.nw - 1
|
||||
self.nr = self.nr + 1
|
||||
if not self.nw:
|
||||
self.readOK.broadcast()
|
||||
self.rwOK.release()
|
||||
|
||||
# The rest of the file is a test case, that runs a number of parallelized
|
||||
# quicksorts in parallel. If it works, you'll get about 600 lines of
|
||||
# tracing output, with a line like
|
||||
# test passed! 209 threads created in all
|
||||
# as the last line. The content and order of preceding lines will
|
||||
# vary across runs.
|
||||
|
||||
def _new_thread(func, *args):
|
||||
global TID
|
||||
tid.acquire(); id = TID = TID+1; tid.release()
|
||||
io.acquire(); alive.append(id); \
|
||||
print 'starting thread', id, '--', len(alive), 'alive'; \
|
||||
io.release()
|
||||
thread.start_new_thread( func, (id,) + args )
|
||||
|
||||
def _qsort(tid, a, l, r, finished):
|
||||
# sort a[l:r]; post finished when done
|
||||
io.acquire(); print 'thread', tid, 'qsort', l, r; io.release()
|
||||
if r-l > 1:
|
||||
pivot = a[l]
|
||||
j = l+1 # make a[l:j] <= pivot, and a[j:r] > pivot
|
||||
for i in range(j, r):
|
||||
if a[i] <= pivot:
|
||||
a[j], a[i] = a[i], a[j]
|
||||
j = j + 1
|
||||
a[l], a[j-1] = a[j-1], pivot
|
||||
|
||||
l_subarray_sorted = event()
|
||||
r_subarray_sorted = event()
|
||||
_new_thread(_qsort, a, l, j-1, l_subarray_sorted)
|
||||
_new_thread(_qsort, a, j, r, r_subarray_sorted)
|
||||
l_subarray_sorted.wait()
|
||||
r_subarray_sorted.wait()
|
||||
|
||||
io.acquire(); print 'thread', tid, 'qsort done'; \
|
||||
alive.remove(tid); io.release()
|
||||
finished.post()
|
||||
|
||||
def _randarray(tid, a, finished):
|
||||
io.acquire(); print 'thread', tid, 'randomizing array'; \
|
||||
io.release()
|
||||
for i in range(1, len(a)):
|
||||
wh.acquire(); j = randint(0,i); wh.release()
|
||||
a[i], a[j] = a[j], a[i]
|
||||
io.acquire(); print 'thread', tid, 'randomizing done'; \
|
||||
alive.remove(tid); io.release()
|
||||
finished.post()
|
||||
|
||||
def _check_sort(a):
|
||||
if a != range(len(a)):
|
||||
raise ValueError, ('a not sorted', a)
|
||||
|
||||
def _run_one_sort(tid, a, bar, done):
|
||||
# randomize a, and quicksort it
|
||||
# for variety, all the threads running this enter a barrier
|
||||
# at the end, and post `done' after the barrier exits
|
||||
io.acquire(); print 'thread', tid, 'randomizing', a; \
|
||||
io.release()
|
||||
finished = event()
|
||||
_new_thread(_randarray, a, finished)
|
||||
finished.wait()
|
||||
|
||||
io.acquire(); print 'thread', tid, 'sorting', a; io.release()
|
||||
finished.clear()
|
||||
_new_thread(_qsort, a, 0, len(a), finished)
|
||||
finished.wait()
|
||||
_check_sort(a)
|
||||
|
||||
io.acquire(); print 'thread', tid, 'entering barrier'; \
|
||||
io.release()
|
||||
bar.enter()
|
||||
io.acquire(); print 'thread', tid, 'leaving barrier'; \
|
||||
io.release()
|
||||
io.acquire(); alive.remove(tid); io.release()
|
||||
bar.enter() # make sure they've all removed themselves from alive
|
||||
## before 'done' is posted
|
||||
bar.enter() # just to be cruel
|
||||
done.post()
|
||||
|
||||
def test():
|
||||
global TID, tid, io, wh, randint, alive
|
||||
import random
|
||||
randint = random.randint
|
||||
|
||||
TID = 0 # thread ID (1, 2, ...)
|
||||
tid = thread.allocate_lock() # for changing TID
|
||||
io = thread.allocate_lock() # for printing, and 'alive'
|
||||
wh = thread.allocate_lock() # for calls to random
|
||||
alive = [] # IDs of active threads
|
||||
|
||||
NSORTS = 5
|
||||
arrays = []
|
||||
for i in range(NSORTS):
|
||||
arrays.append( range( (i+1)*10 ) )
|
||||
|
||||
bar = barrier(NSORTS)
|
||||
finished = event()
|
||||
for i in range(NSORTS):
|
||||
_new_thread(_run_one_sort, arrays[i], bar, finished)
|
||||
finished.wait()
|
||||
|
||||
print 'all threads done, and checking results ...'
|
||||
if alive:
|
||||
raise ValueError, ('threads still alive at end', alive)
|
||||
for i in range(NSORTS):
|
||||
a = arrays[i]
|
||||
if len(a) != (i+1)*10:
|
||||
raise ValueError, ('length of array', i, 'screwed up')
|
||||
_check_sort(a)
|
||||
|
||||
print 'test passed!', TID, 'threads created in all'
|
||||
|
||||
if __name__ == '__main__':
|
||||
test()
|
||||
|
||||
# end of module
|
@ -1,89 +0,0 @@
|
||||
$Id$
|
||||
|
||||
Installing Tix.py
|
||||
----------------
|
||||
|
||||
0) To use Tix.py, you need Tcl/Tk (V8.3.3), Tix (V8.1.1) and Python (V2.1.1).
|
||||
Tix.py has been written and tested on a Intel Pentium running RH Linux 5.2
|
||||
and Mandrake Linux 7.0 and Windows with the above mentioned packages.
|
||||
|
||||
Older versions, e.g. Tix 4.1 and Tk 8.0, might also work.
|
||||
|
||||
There is nothing OS-specific in Tix.py itself so it should work on
|
||||
any machine with Tix and Python installed. You can get Tcl and Tk
|
||||
from http://dev.scriptics.com and Tix from http://tix.sourceforge.net.
|
||||
|
||||
1) Build and install Tcl/Tk 8.3. Build and install Tix 8.1.
|
||||
Ensure that Tix is properly installed by running tixwish and executing
|
||||
the demo programs. Under Unix, use the --enable-shared configure option
|
||||
for all three. We recommend tcl8.3.3 for this release of Tix.py.
|
||||
|
||||
2a) If you have a distribution like ActiveState with a tcl subdirectory
|
||||
of $PYTHONHOME, which contains the directories tcl8.3 and tk8.3,
|
||||
make a directory tix8.1 as well. Recursively copy the files from
|
||||
<tix>/library to $PYTHONHOME/lib/tix8.1, and copy the dynamic library
|
||||
(tix8183.dll or libtix8.1.8.3.so) to the same place as the tcl dynamic
|
||||
libraries ($PYTHONHOME/Dlls or lib/python-2.1/lib-dynload). In this
|
||||
case you are all installed, and you can skip to the end.
|
||||
|
||||
2b) Modify Modules/Setup.dist and setup.py to change the version of the
|
||||
tix library from tix4.1.8.0 to tix8.1.8.3
|
||||
These modified files can be used for Tkinter with or without Tix.
|
||||
|
||||
3) The default is to build dynamically, and use the Tcl 'package require'.
|
||||
To build statically, modify the Modules/Setup file to link in the Tix
|
||||
library according to the comments in the file. On Linux this looks like:
|
||||
|
||||
# *** Always uncomment this (leave the leading underscore in!):
|
||||
_tkinter _tkinter.c tkappinit.c -DWITH_APPINIT \
|
||||
# *** Uncomment and edit to reflect where your Tcl/Tk libraries are:
|
||||
-L/usr/local/lib \
|
||||
# *** Uncomment and edit to reflect where your Tcl/Tk headers are:
|
||||
-I/usr/local/include \
|
||||
# *** Uncomment and edit to reflect where your X11 header files are:
|
||||
-I/usr/X11R6/include \
|
||||
# *** Or uncomment this for Solaris:
|
||||
# -I/usr/openwin/include \
|
||||
# *** Uncomment and edit for BLT extension only:
|
||||
# -DWITH_BLT -I/usr/local/blt/blt8.0-unoff/include -lBLT8.0 \
|
||||
# *** Uncomment and edit for PIL (TkImaging) extension only:
|
||||
# (See http://www.pythonware.com/products/pil/ for more info)
|
||||
# -DWITH_PIL -I../Extensions/Imaging/libImaging tkImaging.c \
|
||||
# *** Uncomment and edit for TOGL extension only:
|
||||
# -DWITH_TOGL togl.c \
|
||||
# *** Uncomment and edit for Tix extension only:
|
||||
-DWITH_TIX -ltix8.1.8.3 \
|
||||
# *** Uncomment and edit to reflect your Tcl/Tk versions:
|
||||
-ltk8.3 -ltcl8.3 \
|
||||
# *** Uncomment and edit to reflect where your X11 libraries are:
|
||||
-L/usr/X11R6/lib \
|
||||
# *** Or uncomment this for Solaris:
|
||||
# -L/usr/openwin/lib \
|
||||
# *** Uncomment these for TOGL extension only:
|
||||
# -lGL -lGLU -lXext -lXmu \
|
||||
# *** Uncomment for AIX:
|
||||
# -lld \
|
||||
# *** Always uncomment this; X11 libraries to link with:
|
||||
-lX11
|
||||
|
||||
4) Rebuild Python and reinstall.
|
||||
|
||||
You should now have a working Tix implementation in Python. To see if all
|
||||
is as it should be, run the 'tixwidgets.py' script in the Demo/tix directory.
|
||||
Under X windows, do
|
||||
/usr/local/bin/python Demo/tix/tixwidgets.py
|
||||
|
||||
If this does not work, you may need to tell python where to find
|
||||
the Tcl, Tk and Tix library files. This is done by setting the
|
||||
TCL_LIBRARY, TK_LIBRARY and TIX_LIBRARY environment variables. Try this:
|
||||
|
||||
env TCL_LIBRARY=/usr/local/lib/tcl8.3 \
|
||||
TK_LIBRARY=/usr/local/lib/tk8.3 \
|
||||
TIX_LIBRARY=/usr/local/lib/tix8.1 \
|
||||
/usr/local/bin/python Demo/tix/tixwidgets.py
|
||||
|
||||
|
||||
If you find any bugs or have suggestions for improvement, please report them
|
||||
via http://tix.sourceforge.net
|
||||
|
||||
|
@ -1,68 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program.
|
||||
|
||||
# This file demonstrates the use of the tixBalloon widget, which provides
|
||||
# a interesting way to give help tips about elements in your user interface.
|
||||
# Your can display the help message in a "balloon" and a status bar widget.
|
||||
#
|
||||
|
||||
import Tix
|
||||
|
||||
TCL_ALL_EVENTS = 0
|
||||
|
||||
def RunSample (root):
|
||||
balloon = DemoBalloon(root)
|
||||
balloon.mainloop()
|
||||
balloon.destroy()
|
||||
|
||||
class DemoBalloon:
|
||||
def __init__(self, w):
|
||||
self.root = w
|
||||
self.exit = -1
|
||||
|
||||
z = w.winfo_toplevel()
|
||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
||||
|
||||
status = Tix.Label(w, width=40, relief=Tix.SUNKEN, bd=1)
|
||||
status.pack(side=Tix.BOTTOM, fill=Tix.Y, padx=2, pady=1)
|
||||
|
||||
# Create two mysterious widgets that need balloon help
|
||||
button1 = Tix.Button(w, text='Something Unexpected',
|
||||
command=self.quitcmd)
|
||||
button2 = Tix.Button(w, text='Something Else Unexpected')
|
||||
button2['command'] = lambda w=button2: w.destroy()
|
||||
button1.pack(side=Tix.TOP, expand=1)
|
||||
button2.pack(side=Tix.TOP, expand=1)
|
||||
|
||||
# Create the balloon widget and associate it with the widgets that we want
|
||||
# to provide tips for:
|
||||
b = Tix.Balloon(w, statusbar=status)
|
||||
|
||||
b.bind_widget(button1, balloonmsg='Close Window',
|
||||
statusmsg='Press this button to close this window')
|
||||
b.bind_widget(button2, balloonmsg='Self-destruct button',
|
||||
statusmsg='Press this button and it will destroy itself')
|
||||
|
||||
def quitcmd (self):
|
||||
self.exit = 0
|
||||
|
||||
def mainloop(self):
|
||||
foundEvent = 1
|
||||
while self.exit < 0 and foundEvent > 0:
|
||||
foundEvent = self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
||||
|
||||
def destroy (self):
|
||||
self.root.destroy()
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
@ -1,44 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program.
|
||||
|
||||
# This file demonstrates the use of the tixButtonBox widget, which is a
|
||||
# group of TK buttons. You can use it to manage the buttons in a dialog box,
|
||||
# for example.
|
||||
#
|
||||
|
||||
import Tix
|
||||
|
||||
def RunSample(w):
|
||||
# Create the label on the top of the dialog box
|
||||
#
|
||||
top = Tix.Label(w, padx=20, pady=10, bd=1, relief=Tix.RAISED,
|
||||
anchor=Tix.CENTER, text='This dialog box is\n a demonstration of the\n tixButtonBox widget')
|
||||
|
||||
# Create the button box and add a few buttons in it. Set the
|
||||
# -width of all the buttons to the same value so that they
|
||||
# appear in the same size.
|
||||
#
|
||||
# Note that the -text, -underline, -command and -width options are all
|
||||
# standard options of the button widgets.
|
||||
#
|
||||
box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
|
||||
box.add('ok', text='OK', underline=0, width=5,
|
||||
command=lambda w=w: w.destroy())
|
||||
box.add('close', text='Cancel', underline=0, width=5,
|
||||
command=lambda w=w: w.destroy())
|
||||
box.pack(side=Tix.BOTTOM, fill=Tix.X)
|
||||
top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
||||
root.mainloop()
|
@ -1,196 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program.
|
||||
|
||||
# This file demonstrates the use of the compound images: it uses compound
|
||||
# images to display a text string together with a pixmap inside
|
||||
# buttons
|
||||
#
|
||||
|
||||
import Tix
|
||||
|
||||
network_pixmap = """/* XPM */
|
||||
static char * netw_xpm[] = {
|
||||
/* width height ncolors chars_per_pixel */
|
||||
"32 32 7 1",
|
||||
/* colors */
|
||||
" s None c None",
|
||||
". c #000000000000",
|
||||
"X c white",
|
||||
"o c #c000c000c000",
|
||||
"O c #404040",
|
||||
"+ c blue",
|
||||
"@ c red",
|
||||
/* pixels */
|
||||
" ",
|
||||
" .............. ",
|
||||
" .XXXXXXXXXXXX. ",
|
||||
" .XooooooooooO. ",
|
||||
" .Xo.......XoO. ",
|
||||
" .Xo.++++o+XoO. ",
|
||||
" .Xo.++++o+XoO. ",
|
||||
" .Xo.++oo++XoO. ",
|
||||
" .Xo.++++++XoO. ",
|
||||
" .Xo.+o++++XoO. ",
|
||||
" .Xo.++++++XoO. ",
|
||||
" .Xo.XXXXXXXoO. ",
|
||||
" .XooooooooooO. ",
|
||||
" .Xo@ooo....oO. ",
|
||||
" .............. .XooooooooooO. ",
|
||||
" .XXXXXXXXXXXX. .XooooooooooO. ",
|
||||
" .XooooooooooO. .OOOOOOOOOOOO. ",
|
||||
" .Xo.......XoO. .............. ",
|
||||
" .Xo.++++o+XoO. @ ",
|
||||
" .Xo.++++o+XoO. @ ",
|
||||
" .Xo.++oo++XoO. @ ",
|
||||
" .Xo.++++++XoO. @ ",
|
||||
" .Xo.+o++++XoO. @ ",
|
||||
" .Xo.++++++XoO. ..... ",
|
||||
" .Xo.XXXXXXXoO. .XXX. ",
|
||||
" .XooooooooooO.@@@@@@.X O. ",
|
||||
" .Xo@ooo....oO. .OOO. ",
|
||||
" .XooooooooooO. ..... ",
|
||||
" .XooooooooooO. ",
|
||||
" .OOOOOOOOOOOO. ",
|
||||
" .............. ",
|
||||
" "};
|
||||
"""
|
||||
|
||||
hard_disk_pixmap = """/* XPM */
|
||||
static char * drivea_xpm[] = {
|
||||
/* width height ncolors chars_per_pixel */
|
||||
"32 32 5 1",
|
||||
/* colors */
|
||||
" s None c None",
|
||||
". c #000000000000",
|
||||
"X c white",
|
||||
"o c #c000c000c000",
|
||||
"O c #800080008000",
|
||||
/* pixels */
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" .......................... ",
|
||||
" .XXXXXXXXXXXXXXXXXXXXXXXo. ",
|
||||
" .XooooooooooooooooooooooO. ",
|
||||
" .Xooooooooooooooooo..oooO. ",
|
||||
" .Xooooooooooooooooo..oooO. ",
|
||||
" .XooooooooooooooooooooooO. ",
|
||||
" .Xoooooooo.......oooooooO. ",
|
||||
" .Xoo...................oO. ",
|
||||
" .Xoooooooo.......oooooooO. ",
|
||||
" .XooooooooooooooooooooooO. ",
|
||||
" .XooooooooooooooooooooooO. ",
|
||||
" .XooooooooooooooooooooooO. ",
|
||||
" .XooooooooooooooooooooooO. ",
|
||||
" .oOOOOOOOOOOOOOOOOOOOOOOO. ",
|
||||
" .......................... ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "};
|
||||
"""
|
||||
|
||||
network_bitmap = """
|
||||
#define netw_width 32
|
||||
#define netw_height 32
|
||||
static unsigned char netw_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00, 0x02, 0x40,
|
||||
0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x52,
|
||||
0x00, 0x00, 0x0a, 0x52, 0x00, 0x00, 0x8a, 0x51, 0x00, 0x00, 0x0a, 0x50,
|
||||
0x00, 0x00, 0x4a, 0x50, 0x00, 0x00, 0x0a, 0x50, 0x00, 0x00, 0x0a, 0x50,
|
||||
0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0x02, 0x40, 0xfe, 0x7f, 0x52, 0x55,
|
||||
0x02, 0x40, 0xaa, 0x6a, 0xfa, 0x5f, 0xfe, 0x7f, 0x0a, 0x50, 0xfe, 0x7f,
|
||||
0x0a, 0x52, 0x80, 0x00, 0x0a, 0x52, 0x80, 0x00, 0x8a, 0x51, 0x80, 0x00,
|
||||
0x0a, 0x50, 0x80, 0x00, 0x4a, 0x50, 0x80, 0x00, 0x0a, 0x50, 0xe0, 0x03,
|
||||
0x0a, 0x50, 0x20, 0x02, 0xfa, 0xdf, 0x3f, 0x03, 0x02, 0x40, 0xa0, 0x02,
|
||||
0x52, 0x55, 0xe0, 0x03, 0xaa, 0x6a, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0x00,
|
||||
0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
"""
|
||||
|
||||
hard_disk_bitmap = """
|
||||
#define drivea_width 32
|
||||
#define drivea_height 32
|
||||
static unsigned char drivea_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xf8, 0xff, 0xff, 0x1f, 0x08, 0x00, 0x00, 0x18, 0xa8, 0xaa, 0xaa, 0x1a,
|
||||
0x48, 0x55, 0xd5, 0x1d, 0xa8, 0xaa, 0xaa, 0x1b, 0x48, 0x55, 0x55, 0x1d,
|
||||
0xa8, 0xfa, 0xaf, 0x1a, 0xc8, 0xff, 0xff, 0x1d, 0xa8, 0xfa, 0xaf, 0x1a,
|
||||
0x48, 0x55, 0x55, 0x1d, 0xa8, 0xaa, 0xaa, 0x1a, 0x48, 0x55, 0x55, 0x1d,
|
||||
0xa8, 0xaa, 0xaa, 0x1a, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
"""
|
||||
|
||||
def RunSample(w):
|
||||
w.img0 = Tix.Image('pixmap', data=network_pixmap)
|
||||
if not w.img0:
|
||||
w.img0 = Tix.Image('bitmap', data=network_bitmap)
|
||||
w.img1 = Tix.Image('pixmap', data=hard_disk_pixmap)
|
||||
if not w.img0:
|
||||
w.img1 = Tix.Image('bitmap', data=hard_disk_bitmap)
|
||||
|
||||
hdd = Tix.Button(w, padx=4, pady=1, width=120)
|
||||
net = Tix.Button(w, padx=4, pady=1, width=120)
|
||||
|
||||
# Create the first image: we create a line, then put a string,
|
||||
# a space and a image into this line, from left to right.
|
||||
# The result: we have a one-line image that consists of three
|
||||
# individual items
|
||||
#
|
||||
# The tk.calls should be methods in Tix ...
|
||||
w.hdd_img = Tix.Image('compound', window=hdd)
|
||||
w.hdd_img.tk.call(str(w.hdd_img), 'add', 'line')
|
||||
w.hdd_img.tk.call(str(w.hdd_img), 'add', 'text', '-text', 'Hard Disk',
|
||||
'-underline', '0')
|
||||
w.hdd_img.tk.call(str(w.hdd_img), 'add', 'space', '-width', '7')
|
||||
w.hdd_img.tk.call(str(w.hdd_img), 'add', 'image', '-image', w.img1)
|
||||
|
||||
# Put this image into the first button
|
||||
#
|
||||
hdd['image'] = w.hdd_img
|
||||
|
||||
# Next button
|
||||
w.net_img = Tix.Image('compound', window=net)
|
||||
w.net_img.tk.call(str(w.net_img), 'add', 'line')
|
||||
w.net_img.tk.call(str(w.net_img), 'add', 'text', '-text', 'Network',
|
||||
'-underline', '0')
|
||||
w.net_img.tk.call(str(w.net_img), 'add', 'space', '-width', '7')
|
||||
w.net_img.tk.call(str(w.net_img), 'add', 'image', '-image', w.img0)
|
||||
|
||||
# Put this image into the first button
|
||||
#
|
||||
net['image'] = w.net_img
|
||||
|
||||
close = Tix.Button(w, pady=1, text='Close',
|
||||
command=lambda w=w: w.destroy())
|
||||
|
||||
hdd.pack(side=Tix.LEFT, padx=10, pady=10, fill=Tix.Y, expand=1)
|
||||
net.pack(side=Tix.LEFT, padx=10, pady=10, fill=Tix.Y, expand=1)
|
||||
close.pack(side=Tix.LEFT, padx=10, pady=10, fill=Tix.Y, expand=1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
||||
root.mainloop()
|
@ -1,102 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program.
|
||||
|
||||
# This file demonstrates the use of the tixComboBox widget, which is close
|
||||
# to the MS Window Combo Box control.
|
||||
#
|
||||
import Tix
|
||||
|
||||
def RunSample(w):
|
||||
global demo_month, demo_year
|
||||
|
||||
top = Tix.Frame(w, bd=1, relief=Tix.RAISED)
|
||||
|
||||
demo_month = Tix.StringVar()
|
||||
demo_year = Tix.StringVar()
|
||||
|
||||
# $w.top.a is a drop-down combo box. It is not editable -- who wants
|
||||
# to invent new months?
|
||||
#
|
||||
# [Hint] The -options switch sets the options of the subwidgets.
|
||||
# [Hint] We set the label.width subwidget option of both comboboxes to
|
||||
# be 10 so that their labels appear to be aligned.
|
||||
#
|
||||
a = Tix.ComboBox(top, label="Month: ", dropdown=1,
|
||||
command=select_month, editable=0, variable=demo_month,
|
||||
options='listbox.height 6 label.width 10 label.anchor e')
|
||||
|
||||
# $w.top.b is a non-drop-down combo box. It is not editable: we provide
|
||||
# four choices for the user, but he can enter an alternative year if he
|
||||
# wants to.
|
||||
#
|
||||
# [Hint] Use the padY and anchor options of the label subwidget to
|
||||
# align the label with the entry subwidget.
|
||||
# [Hint] Notice that you should use padY (the NAME of the option) and not
|
||||
# pady (the SWITCH of the option).
|
||||
#
|
||||
b = Tix.ComboBox(top, label="Year: ", dropdown=0,
|
||||
command=select_year, editable=1, variable=demo_year,
|
||||
options='listbox.height 4 label.padY 5 label.width 10 label.anchor ne')
|
||||
|
||||
a.pack(side=Tix.TOP, anchor=Tix.W)
|
||||
b.pack(side=Tix.TOP, anchor=Tix.W)
|
||||
|
||||
a.insert(Tix.END, 'January')
|
||||
a.insert(Tix.END, 'February')
|
||||
a.insert(Tix.END, 'March')
|
||||
a.insert(Tix.END, 'April')
|
||||
a.insert(Tix.END, 'May')
|
||||
a.insert(Tix.END, 'June')
|
||||
a.insert(Tix.END, 'July')
|
||||
a.insert(Tix.END, 'August')
|
||||
a.insert(Tix.END, 'September')
|
||||
a.insert(Tix.END, 'October')
|
||||
a.insert(Tix.END, 'November')
|
||||
a.insert(Tix.END, 'December')
|
||||
|
||||
b.insert(Tix.END, '1992')
|
||||
b.insert(Tix.END, '1993')
|
||||
b.insert(Tix.END, '1994')
|
||||
b.insert(Tix.END, '1995')
|
||||
b.insert(Tix.END, '1996')
|
||||
|
||||
# Use "tixSetSilent" to set the values of the combo box if you
|
||||
# don't want your -command procedures (cbx:select_month and
|
||||
# cbx:select_year) to be called.
|
||||
#
|
||||
a.set_silent('January')
|
||||
b.set_silent('1995')
|
||||
|
||||
box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
|
||||
box.add('ok', text='Ok', underline=0, width=6,
|
||||
command=lambda w=w: ok_command(w))
|
||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
||||
command=lambda w=w: w.destroy())
|
||||
box.pack(side=Tix.BOTTOM, fill=Tix.X)
|
||||
top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
|
||||
|
||||
def select_month(event=None):
|
||||
# tixDemo:Status "Month = %s" % demo_month.get()
|
||||
pass
|
||||
|
||||
def select_year(event=None):
|
||||
# tixDemo:Status "Year = %s" % demo_year.get()
|
||||
pass
|
||||
|
||||
def ok_command(w):
|
||||
# tixDemo:Status "Month = %s, Year= %s" % (demo_month.get(), demo_year.get())
|
||||
w.destroy()
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
||||
root.mainloop()
|
@ -1,122 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program.
|
||||
|
||||
# This file demonstrates the use of the tixControl widget -- it is an
|
||||
# entry widget with up/down arrow buttons. You can use the arrow buttons
|
||||
# to adjust the value inside the entry widget.
|
||||
#
|
||||
# This example program uses three Control widgets. One lets you select
|
||||
# integer values; one lets you select floating point values and the last
|
||||
# one lets you select a few names.
|
||||
|
||||
import Tix
|
||||
|
||||
TCL_ALL_EVENTS = 0
|
||||
|
||||
def RunSample (root):
|
||||
control = DemoControl(root)
|
||||
control.mainloop()
|
||||
control.destroy()
|
||||
|
||||
class DemoControl:
|
||||
def __init__(self, w):
|
||||
self.root = w
|
||||
self.exit = -1
|
||||
|
||||
global demo_maker, demo_thrust, demo_num_engines
|
||||
|
||||
demo_maker = Tix.StringVar()
|
||||
demo_thrust = Tix.DoubleVar()
|
||||
demo_num_engines = Tix.IntVar()
|
||||
demo_maker.set('P&W')
|
||||
demo_thrust.set(20000.0)
|
||||
demo_num_engines.set(2)
|
||||
|
||||
top = Tix.Frame(w, bd=1, relief=Tix.RAISED)
|
||||
|
||||
# $w.top.a allows only integer values
|
||||
#
|
||||
# [Hint] The -options switch sets the options of the subwidgets.
|
||||
# [Hint] We set the label.width subwidget option of the Controls to
|
||||
# be 16 so that their labels appear to be aligned.
|
||||
#
|
||||
a = Tix.Control(top, label='Number of Engines: ', integer=1,
|
||||
variable=demo_num_engines, min=1, max=4,
|
||||
options='entry.width 10 label.width 20 label.anchor e')
|
||||
|
||||
b = Tix.Control(top, label='Thrust: ', integer=0,
|
||||
min='10000.0', max='60000.0', step=500,
|
||||
variable=demo_thrust,
|
||||
options='entry.width 10 label.width 20 label.anchor e')
|
||||
|
||||
c = Tix.Control(top, label='Engine Maker: ', value='P&W',
|
||||
variable=demo_maker,
|
||||
options='entry.width 10 label.width 20 label.anchor e')
|
||||
|
||||
# We can't define these in the init because the widget 'c' doesn't
|
||||
# exist yet and we need to reference it
|
||||
c['incrcmd'] = lambda w=c: adjust_maker(w, 1)
|
||||
c['decrcmd'] = lambda w=c: adjust_maker(w, -1)
|
||||
c['validatecmd'] = lambda w=c: validate_maker(w)
|
||||
|
||||
a.pack(side=Tix.TOP, anchor=Tix.W)
|
||||
b.pack(side=Tix.TOP, anchor=Tix.W)
|
||||
c.pack(side=Tix.TOP, anchor=Tix.W)
|
||||
|
||||
box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
|
||||
box.add('ok', text='Ok', underline=0, width=6,
|
||||
command=self.okcmd)
|
||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
||||
command=self.quitcmd)
|
||||
box.pack(side=Tix.BOTTOM, fill=Tix.X)
|
||||
top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
|
||||
|
||||
def okcmd (self):
|
||||
# tixDemo:Status "Selected %d of %s engines each of thrust %d", (demo_num_engines.get(), demo_maker.get(), demo_thrust.get())
|
||||
self.quitcmd()
|
||||
|
||||
def quitcmd (self):
|
||||
self.exit = 0
|
||||
|
||||
def mainloop(self):
|
||||
while self.exit < 0:
|
||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
||||
|
||||
def destroy (self):
|
||||
self.root.destroy()
|
||||
|
||||
maker_list = ['P&W', 'GE', 'Rolls Royce']
|
||||
|
||||
def adjust_maker(w, inc):
|
||||
i = maker_list.index(demo_maker.get())
|
||||
i = i + inc
|
||||
if i >= len(maker_list):
|
||||
i = 0
|
||||
elif i < 0:
|
||||
i = len(maker_list) - 1
|
||||
|
||||
# In Tcl/Tix we should return the string maker_list[i]. We can't
|
||||
# do that in Tkinter so we set the global variable. (This works).
|
||||
demo_maker.set(maker_list[i])
|
||||
|
||||
def validate_maker(w):
|
||||
try:
|
||||
i = maker_list.index(demo_maker.get())
|
||||
except ValueError:
|
||||
# Works here though. Why ? Beats me.
|
||||
return maker_list[0]
|
||||
# Works here though. Why ? Beats me.
|
||||
return maker_list[i]
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
@ -1,131 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program using tixwish.
|
||||
|
||||
# This file demonstrates the use of the tixDirList widget -- you can
|
||||
# use it for the user to select a directory. For example, an installation
|
||||
# program can use the tixDirList widget to ask the user to select the
|
||||
# installation directory for an application.
|
||||
#
|
||||
|
||||
import Tix, os, copy
|
||||
from Tkconstants import *
|
||||
|
||||
TCL_ALL_EVENTS = 0
|
||||
|
||||
def RunSample (root):
|
||||
dirlist = DemoDirList(root)
|
||||
dirlist.mainloop()
|
||||
dirlist.destroy()
|
||||
|
||||
class DemoDirList:
|
||||
def __init__(self, w):
|
||||
self.root = w
|
||||
self.exit = -1
|
||||
|
||||
z = w.winfo_toplevel()
|
||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
||||
|
||||
# Create the tixDirList and the tixLabelEntry widgets on the on the top
|
||||
# of the dialog box
|
||||
|
||||
# bg = root.tk.eval('tix option get bg')
|
||||
# adding bg=bg crashes Windows pythonw tk8.3.3 Python 2.1.0
|
||||
|
||||
top = Tix.Frame( w, relief=RAISED, bd=1)
|
||||
|
||||
# Create the DirList widget. By default it will show the current
|
||||
# directory
|
||||
#
|
||||
#
|
||||
top.dir = Tix.DirList(top)
|
||||
top.dir.hlist['width'] = 40
|
||||
|
||||
# When the user presses the ".." button, the selected directory
|
||||
# is "transferred" into the entry widget
|
||||
#
|
||||
top.btn = Tix.Button(top, text = " >> ", pady = 0)
|
||||
|
||||
# We use a LabelEntry to hold the installation directory. The user
|
||||
# can choose from the DirList widget, or he can type in the directory
|
||||
# manually
|
||||
#
|
||||
top.ent = Tix.LabelEntry(top, label="Installation Directory:",
|
||||
labelside = 'top',
|
||||
options = '''
|
||||
entry.width 40
|
||||
label.anchor w
|
||||
''')
|
||||
|
||||
font = self.root.tk.eval('tix option get fixed_font')
|
||||
# font = self.root.master.tix_option_get('fixed_font')
|
||||
top.ent.entry['font'] = font
|
||||
|
||||
self.dlist_dir = copy.copy(os.curdir)
|
||||
# This should work setting the entry's textvariable
|
||||
top.ent.entry['textvariable'] = self.dlist_dir
|
||||
top.btn['command'] = lambda dir=top.dir, ent=top.ent, self=self: \
|
||||
self.copy_name(dir,ent)
|
||||
|
||||
# top.ent.entry.insert(0,'tix'+repr(self))
|
||||
top.ent.entry.bind('<Return>', lambda self=self: self.okcmd () )
|
||||
|
||||
top.pack( expand='yes', fill='both', side=TOP)
|
||||
top.dir.pack( expand=1, fill=BOTH, padx=4, pady=4, side=LEFT)
|
||||
top.btn.pack( anchor='s', padx=4, pady=4, side=LEFT)
|
||||
top.ent.pack( expand=1, fill=X, anchor='s', padx=4, pady=4, side=LEFT)
|
||||
|
||||
# Use a ButtonBox to hold the buttons.
|
||||
#
|
||||
box = Tix.ButtonBox (w, orientation='horizontal')
|
||||
box.add ('ok', text='Ok', underline=0, width=6,
|
||||
command = lambda self=self: self.okcmd () )
|
||||
box.add ('cancel', text='Cancel', underline=0, width=6,
|
||||
command = lambda self=self: self.quitcmd () )
|
||||
|
||||
box.pack( anchor='s', fill='x', side=BOTTOM)
|
||||
|
||||
def copy_name (self, dir, ent):
|
||||
# This should work as it is the entry's textvariable
|
||||
self.dlist_dir = dir.cget('value')
|
||||
# but it isn't so I'll do it manually
|
||||
ent.entry.delete(0,'end')
|
||||
ent.entry.insert(0, self.dlist_dir)
|
||||
|
||||
def okcmd (self):
|
||||
# tixDemo:Status "You have selected the directory" + self.dlist_dir
|
||||
self.quitcmd()
|
||||
|
||||
def quitcmd (self):
|
||||
self.exit = 0
|
||||
|
||||
def mainloop(self):
|
||||
while self.exit < 0:
|
||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
||||
|
||||
def destroy (self):
|
||||
self.root.destroy()
|
||||
|
||||
# This "if" statement makes it possible to run this script file inside or
|
||||
# outside of the main demo program "tixwidgets.py".
|
||||
#
|
||||
if __name__== '__main__' :
|
||||
import tkMessageBox, traceback
|
||||
|
||||
try:
|
||||
root=Tix.Tk()
|
||||
RunSample(root)
|
||||
except:
|
||||
t, v, tb = sys.exc_info()
|
||||
text = "Error running the demo script:\n"
|
||||
for line in traceback.format_exception(t,v,tb):
|
||||
text = text + line + '\n'
|
||||
d = tkMessageBox.showerror ( 'Tix Demo Error', text)
|
@ -1,117 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program using tixwish.
|
||||
|
||||
# This file demonstrates the use of the tixDirTree widget -- you can
|
||||
# use it for the user to select a directory. For example, an installation
|
||||
# program can use the tixDirTree widget to ask the user to select the
|
||||
# installation directory for an application.
|
||||
#
|
||||
|
||||
import Tix, os, copy
|
||||
from Tkconstants import *
|
||||
|
||||
TCL_ALL_EVENTS = 0
|
||||
|
||||
def RunSample (root):
|
||||
dirtree = DemoDirTree(root)
|
||||
dirtree.mainloop()
|
||||
dirtree.destroy()
|
||||
|
||||
class DemoDirTree:
|
||||
def __init__(self, w):
|
||||
self.root = w
|
||||
self.exit = -1
|
||||
|
||||
z = w.winfo_toplevel()
|
||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
||||
|
||||
# Create the tixDirTree and the tixLabelEntry widgets on the on the top
|
||||
# of the dialog box
|
||||
|
||||
# bg = root.tk.eval('tix option get bg')
|
||||
# adding bg=bg crashes Windows pythonw tk8.3.3 Python 2.1.0
|
||||
|
||||
top = Tix.Frame( w, relief=RAISED, bd=1)
|
||||
|
||||
# Create the DirTree widget. By default it will show the current
|
||||
# directory
|
||||
#
|
||||
#
|
||||
top.dir = Tix.DirTree(top)
|
||||
top.dir.hlist['width'] = 40
|
||||
|
||||
# When the user presses the ".." button, the selected directory
|
||||
# is "transferred" into the entry widget
|
||||
#
|
||||
top.btn = Tix.Button(top, text = " >> ", pady = 0)
|
||||
|
||||
# We use a LabelEntry to hold the installation directory. The user
|
||||
# can choose from the DirTree widget, or he can type in the directory
|
||||
# manually
|
||||
#
|
||||
top.ent = Tix.LabelEntry(top, label="Installation Directory:",
|
||||
labelside = 'top',
|
||||
options = '''
|
||||
entry.width 40
|
||||
label.anchor w
|
||||
''')
|
||||
|
||||
self.dlist_dir = copy.copy(os.curdir)
|
||||
top.ent.entry['textvariable'] = self.dlist_dir
|
||||
top.btn['command'] = lambda dir=top.dir, ent=top.ent, self=self: \
|
||||
self.copy_name(dir,ent)
|
||||
|
||||
top.ent.entry.bind('<Return>', lambda self=self: self.okcmd () )
|
||||
|
||||
top.pack( expand='yes', fill='both', side=TOP)
|
||||
top.dir.pack( expand=1, fill=BOTH, padx=4, pady=4, side=LEFT)
|
||||
top.btn.pack( anchor='s', padx=4, pady=4, side=LEFT)
|
||||
top.ent.pack( expand=1, fill=X, anchor='s', padx=4, pady=4, side=LEFT)
|
||||
|
||||
# Use a ButtonBox to hold the buttons.
|
||||
#
|
||||
box = Tix.ButtonBox (w, orientation='horizontal')
|
||||
box.add ('ok', text='Ok', underline=0, width=6,
|
||||
command = lambda self=self: self.okcmd () )
|
||||
box.add ('cancel', text='Cancel', underline=0, width=6,
|
||||
command = lambda self=self: self.quitcmd () )
|
||||
|
||||
box.pack( anchor='s', fill='x', side=BOTTOM)
|
||||
|
||||
def copy_name (self, dir, ent):
|
||||
# This should work as it is the entry's textvariable
|
||||
self.dlist_dir = dir.cget('value')
|
||||
# but it isn't so I'll do it manually
|
||||
ent.entry.delete(0,'end')
|
||||
ent.entry.insert(0, self.dlist_dir)
|
||||
|
||||
def okcmd (self):
|
||||
# tixDemo:Status "You have selected the directory" + self.dlist_dir
|
||||
self.quitcmd()
|
||||
|
||||
def quitcmd (self):
|
||||
# tixDemo:Status "You have selected the directory" + self.dlist_dir
|
||||
self.exit = 0
|
||||
|
||||
def mainloop(self):
|
||||
while self.exit < 0:
|
||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
||||
|
||||
def destroy (self):
|
||||
self.root.destroy()
|
||||
|
||||
# This "if" statement makes it possible to run this script file inside or
|
||||
# outside of the main demo program "tixwidgets.py".
|
||||
#
|
||||
if __name__== '__main__' :
|
||||
root=Tix.Tk()
|
||||
RunSample(root)
|
@ -1,119 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program.
|
||||
|
||||
# This file demonstrates the use of the tixNoteBook widget, which allows
|
||||
# you to lay out your interface using a "notebook" metaphore
|
||||
#
|
||||
import Tix
|
||||
|
||||
def RunSample(w):
|
||||
global root
|
||||
root = w
|
||||
|
||||
# We use these options to set the sizes of the subwidgets inside the
|
||||
# notebook, so that they are well-aligned on the screen.
|
||||
prefix = Tix.OptionName(w)
|
||||
if prefix:
|
||||
prefix = '*'+prefix
|
||||
else:
|
||||
prefix = ''
|
||||
w.option_add(prefix+'*TixControl*entry.width', 10)
|
||||
w.option_add(prefix+'*TixControl*label.width', 18)
|
||||
w.option_add(prefix+'*TixControl*label.anchor', Tix.E)
|
||||
w.option_add(prefix+'*TixNoteBook*tagPadX', 8)
|
||||
|
||||
# Create the notebook widget and set its backpagecolor to gray.
|
||||
# Note that the -backpagecolor option belongs to the "nbframe"
|
||||
# subwidget.
|
||||
nb = Tix.NoteBook(w, name='nb', ipadx=6, ipady=6)
|
||||
nb['bg'] = 'gray'
|
||||
nb.nbframe['backpagecolor'] = 'gray'
|
||||
|
||||
# Create the two tabs on the notebook. The -underline option
|
||||
# puts a underline on the first character of the labels of the tabs.
|
||||
# Keyboard accelerators will be defined automatically according
|
||||
# to the underlined character.
|
||||
nb.add('hard_disk', label="Hard Disk", underline=0)
|
||||
nb.add('network', label="Network", underline=0)
|
||||
|
||||
nb.pack(expand=1, fill=Tix.BOTH, padx=5, pady=5 ,side=Tix.TOP)
|
||||
|
||||
#----------------------------------------
|
||||
# Create the first page
|
||||
#----------------------------------------
|
||||
# Create two frames: one for the common buttons, one for the
|
||||
# other widgets
|
||||
#
|
||||
tab=nb.hard_disk
|
||||
f = Tix.Frame(tab)
|
||||
common = Tix.Frame(tab)
|
||||
|
||||
f.pack(side=Tix.LEFT, padx=2, pady=2, fill=Tix.BOTH, expand=1)
|
||||
common.pack(side=Tix.RIGHT, padx=2, fill=Tix.Y)
|
||||
|
||||
a = Tix.Control(f, value=12, label='Access time: ')
|
||||
w = Tix.Control(f, value=400, label='Write Throughput: ')
|
||||
r = Tix.Control(f, value=400, label='Read Throughput: ')
|
||||
c = Tix.Control(f, value=1021, label='Capacity: ')
|
||||
|
||||
a.pack(side=Tix.TOP, padx=20, pady=2)
|
||||
w.pack(side=Tix.TOP, padx=20, pady=2)
|
||||
r.pack(side=Tix.TOP, padx=20, pady=2)
|
||||
c.pack(side=Tix.TOP, padx=20, pady=2)
|
||||
|
||||
# Create the common buttons
|
||||
createCommonButtons(common)
|
||||
|
||||
#----------------------------------------
|
||||
# Create the second page
|
||||
#----------------------------------------
|
||||
|
||||
tab = nb.network
|
||||
|
||||
f = Tix.Frame(tab)
|
||||
common = Tix.Frame(tab)
|
||||
|
||||
f.pack(side=Tix.LEFT, padx=2, pady=2, fill=Tix.BOTH, expand=1)
|
||||
common.pack(side=Tix.RIGHT, padx=2, fill=Tix.Y)
|
||||
|
||||
a = Tix.Control(f, value=12, label='Access time: ')
|
||||
w = Tix.Control(f, value=400, label='Write Throughput: ')
|
||||
r = Tix.Control(f, value=400, label='Read Throughput: ')
|
||||
c = Tix.Control(f, value=1021, label='Capacity: ')
|
||||
u = Tix.Control(f, value=10, label='Users: ')
|
||||
|
||||
a.pack(side=Tix.TOP, padx=20, pady=2)
|
||||
w.pack(side=Tix.TOP, padx=20, pady=2)
|
||||
r.pack(side=Tix.TOP, padx=20, pady=2)
|
||||
c.pack(side=Tix.TOP, padx=20, pady=2)
|
||||
u.pack(side=Tix.TOP, padx=20, pady=2)
|
||||
|
||||
createCommonButtons(common)
|
||||
|
||||
def doDestroy():
|
||||
global root
|
||||
root.destroy()
|
||||
|
||||
def createCommonButtons(master):
|
||||
ok = Tix.Button(master, name='ok', text='OK', width=6,
|
||||
command=doDestroy)
|
||||
cancel = Tix.Button(master, name='cancel',
|
||||
text='Cancel', width=6,
|
||||
command=doDestroy)
|
||||
|
||||
ok.pack(side=Tix.TOP, padx=2, pady=2)
|
||||
cancel.pack(side=Tix.TOP, padx=2, pady=2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
||||
root.mainloop()
|
@ -1,68 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program.
|
||||
|
||||
# This file demonstrates the use of the tixOptionMenu widget -- you can
|
||||
# use it for the user to choose from a fixed set of options
|
||||
#
|
||||
import Tix
|
||||
|
||||
options = {'text':'Plain Text', 'post':'PostScript', 'html':'HTML',
|
||||
'tex':'LaTeX', 'rtf':'Rich Text Format'}
|
||||
|
||||
def RunSample(w):
|
||||
global demo_opt_from, demo_opt_to
|
||||
|
||||
demo_opt_from = Tix.StringVar()
|
||||
demo_opt_to = Tix.StringVar()
|
||||
|
||||
top = Tix.Frame(w, bd=1, relief=Tix.RAISED)
|
||||
|
||||
from_file = Tix.OptionMenu(top, label="From File Format : ",
|
||||
variable=demo_opt_from,
|
||||
options = 'label.width 19 label.anchor e menubutton.width 15')
|
||||
|
||||
to_file = Tix.OptionMenu(top, label="To File Format : ",
|
||||
variable=demo_opt_to,
|
||||
options='label.width 19 label.anchor e menubutton.width 15')
|
||||
|
||||
# Add the available options to the two OptionMenu widgets
|
||||
#
|
||||
# [Hint] You have to add the options first before you set the
|
||||
# global variables "demo_opt_from" and "demo_opt_to". Otherwise
|
||||
# the OptionMenu widget will complain about "unknown options"!
|
||||
#
|
||||
for opt in options.keys():
|
||||
from_file.add_command(opt, label=options[opt])
|
||||
to_file.add_command(opt, label=options[opt])
|
||||
|
||||
demo_opt_from.set('html')
|
||||
demo_opt_to.set('post')
|
||||
|
||||
from_file.pack(side=Tix.TOP, anchor=Tix.W, pady=3, padx=6)
|
||||
to_file.pack(side=Tix.TOP, anchor=Tix.W, pady=3, padx=6)
|
||||
|
||||
box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
|
||||
box.add('ok', text='Ok', underline=0, width=6,
|
||||
command=lambda w=w: ok_command(w))
|
||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
||||
command=lambda w=w: w.destroy())
|
||||
box.pack(side=Tix.BOTTOM, fill=Tix.X)
|
||||
top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
|
||||
|
||||
def ok_command(w):
|
||||
# tixDemo:Status "Convert file from %s to %s" % ( demo_opt_from.get(), demo_opt_to.get())
|
||||
w.destroy()
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
||||
root.mainloop()
|
@ -1,98 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program.
|
||||
|
||||
# This file demonstrates the use of the tixPanedWindow widget. This program
|
||||
# is a dummy news reader: the user can adjust the sizes of the list
|
||||
# of artical names and the size of the text widget that shows the body
|
||||
# of the article.
|
||||
|
||||
import Tix
|
||||
|
||||
TCL_ALL_EVENTS = 0
|
||||
|
||||
def RunSample (root):
|
||||
panedwin = DemoPanedwin(root)
|
||||
panedwin.mainloop()
|
||||
panedwin.destroy()
|
||||
|
||||
class DemoPanedwin:
|
||||
def __init__(self, w):
|
||||
self.root = w
|
||||
self.exit = -1
|
||||
|
||||
z = w.winfo_toplevel()
|
||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
||||
|
||||
group = Tix.LabelEntry(w, label='Newsgroup:', options='entry.width 25')
|
||||
group.entry.insert(0,'comp.lang.python')
|
||||
pane = Tix.PanedWindow(w, orientation='vertical')
|
||||
|
||||
p1 = pane.add('list', min=70, size=100)
|
||||
p2 = pane.add('text', min=70)
|
||||
list = Tix.ScrolledListBox(p1)
|
||||
list.listbox['width'] = 80
|
||||
list.listbox['height'] = 5
|
||||
text = Tix.ScrolledText(p2)
|
||||
text.text['width'] = 80
|
||||
text.text['height'] = 20
|
||||
|
||||
list.listbox.insert(Tix.END, " 12324 Re: Tkinter is good for your health")
|
||||
list.listbox.insert(Tix.END, "+ 12325 Re: Tkinter is good for your health")
|
||||
list.listbox.insert(Tix.END, "+ 12326 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
||||
list.listbox.insert(Tix.END, " 12327 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
||||
list.listbox.insert(Tix.END, "+ 12328 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
||||
list.listbox.insert(Tix.END, " 12329 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
||||
list.listbox.insert(Tix.END, "+ 12330 Re: Tix is even better for your health (Was: Tkinter is good...)")
|
||||
|
||||
text.text['bg'] = list.listbox['bg']
|
||||
text.text['wrap'] = 'none'
|
||||
text.text.insert(Tix.END, """
|
||||
Mon, 19 Jun 1995 11:39:52 comp.lang.python Thread 34 of 220
|
||||
Lines 353 A new way to put text and bitmaps together iNo responses
|
||||
ioi@blue.seas.upenn.edu Ioi K. Lam at University of Pennsylvania
|
||||
|
||||
Hi,
|
||||
|
||||
I have implemented a new image type called "compound". It allows you
|
||||
to glue together a bunch of bitmaps, images and text strings together
|
||||
to form a bigger image. Then you can use this image with widgets that
|
||||
support the -image option. For example, you can display a text string string
|
||||
together with a bitmap, at the same time, inside a TK button widget.
|
||||
""")
|
||||
text.text['state'] = 'disabled'
|
||||
|
||||
list.pack(expand=1, fill=Tix.BOTH, padx=4, pady=6)
|
||||
text.pack(expand=1, fill=Tix.BOTH, padx=4, pady=6)
|
||||
|
||||
group.pack(side=Tix.TOP, padx=3, pady=3, fill=Tix.BOTH)
|
||||
pane.pack(side=Tix.TOP, padx=3, pady=3, fill=Tix.BOTH, expand=1)
|
||||
|
||||
box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
|
||||
box.add('ok', text='Ok', underline=0, width=6,
|
||||
command=self.quitcmd)
|
||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
||||
command=self.quitcmd)
|
||||
box.pack(side=Tix.BOTTOM, fill=Tix.X)
|
||||
|
||||
def quitcmd (self):
|
||||
self.exit = 0
|
||||
|
||||
def mainloop(self):
|
||||
while self.exit < 0:
|
||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
||||
|
||||
def destroy (self):
|
||||
self.root.destroy()
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
@ -1,57 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program using tixwish.
|
||||
|
||||
# This file demonstrates the use of the tixPopupMenu widget.
|
||||
#
|
||||
import Tix
|
||||
|
||||
def RunSample(w):
|
||||
# We create the frame and the button, then we'll bind the PopupMenu
|
||||
# to both widgets. The result is, when you press the right mouse
|
||||
# button over $w.top or $w.top.but, the PopupMenu will come up.
|
||||
#
|
||||
top = Tix.Frame(w, relief=Tix.RAISED, bd=1)
|
||||
but = Tix.Button(top, text='Press the right mouse button over this button or its surrounding area')
|
||||
but.pack(expand=1, fill=Tix.BOTH, padx=50, pady=50)
|
||||
|
||||
p = Tix.PopupMenu(top, title='Popup Test')
|
||||
p.bind_widget(top)
|
||||
p.bind_widget(but)
|
||||
|
||||
# Set the entries inside the PopupMenu widget.
|
||||
# [Hint] You have to manipulate the "menu" subwidget.
|
||||
# $w.top.p itself is NOT a menu widget.
|
||||
# [Hint] Watch carefully how the sub-menu is created
|
||||
#
|
||||
p.menu.add_command(label='Desktop', underline=0)
|
||||
p.menu.add_command(label='Select', underline=0)
|
||||
p.menu.add_command(label='Find', underline=0)
|
||||
p.menu.add_command(label='System', underline=1)
|
||||
p.menu.add_command(label='Help', underline=0)
|
||||
m1 = Tix.Menu(p.menu)
|
||||
m1.add_command(label='Hello')
|
||||
p.menu.add_cascade(label='More', menu=m1)
|
||||
|
||||
but.pack(side=Tix.TOP, padx=40, pady=50)
|
||||
|
||||
box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
|
||||
box.add('ok', text='Ok', underline=0, width=6,
|
||||
command=lambda w=w: w.destroy())
|
||||
box.add('cancel', text='Cancel', underline=0, width=6,
|
||||
command=lambda w=w: w.destroy())
|
||||
box.pack(side=Tix.BOTTOM, fill=Tix.X)
|
||||
top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
||||
root.mainloop()
|
@ -1,131 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program using tixwish.
|
||||
|
||||
# This file demonstrates the use of the tixScrolledHList widget.
|
||||
#
|
||||
|
||||
import Tix
|
||||
|
||||
TCL_ALL_EVENTS = 0
|
||||
|
||||
def RunSample (root):
|
||||
shlist = DemoSHList(root)
|
||||
shlist.mainloop()
|
||||
shlist.destroy()
|
||||
|
||||
class DemoSHList:
|
||||
def __init__(self, w):
|
||||
self.root = w
|
||||
self.exit = -1
|
||||
|
||||
z = w.winfo_toplevel()
|
||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
||||
|
||||
# We create the frame and the ScrolledHList widget
|
||||
# at the top of the dialog box
|
||||
#
|
||||
top = Tix.Frame( w, relief=Tix.RAISED, bd=1)
|
||||
|
||||
# Put a simple hierachy into the HList (two levels). Use colors and
|
||||
# separator widgets (frames) to make the list look fancy
|
||||
#
|
||||
top.a = Tix.ScrolledHList(top)
|
||||
top.a.pack( expand=1, fill=Tix.BOTH, padx=10, pady=10, side=Tix.TOP)
|
||||
|
||||
# This is our little relational database
|
||||
#
|
||||
bosses = [
|
||||
('jeff', 'Jeff Waxman'),
|
||||
('john', 'John Lee'),
|
||||
('peter', 'Peter Kenson')
|
||||
]
|
||||
|
||||
employees = [
|
||||
('alex', 'john', 'Alex Kellman'),
|
||||
('alan', 'john', 'Alan Adams'),
|
||||
('andy', 'peter', 'Andreas Crawford'),
|
||||
('doug', 'jeff', 'Douglas Bloom'),
|
||||
('jon', 'peter', 'Jon Baraki'),
|
||||
('chris', 'jeff', 'Chris Geoffrey'),
|
||||
('chuck', 'jeff', 'Chuck McLean')
|
||||
]
|
||||
|
||||
hlist=top.a.hlist
|
||||
|
||||
# Let configure the appearance of the HList subwidget
|
||||
#
|
||||
hlist.config( separator='.', width=25, drawbranch=0, indent=10)
|
||||
|
||||
count=0
|
||||
for boss,name in bosses :
|
||||
if count :
|
||||
f=Tix.Frame(hlist, name='sep%d' % count, height=2, width=150,
|
||||
bd=2, relief=Tix.SUNKEN )
|
||||
|
||||
hlist.add_child( itemtype=Tix.WINDOW,
|
||||
window=f, state=Tix.DISABLED )
|
||||
|
||||
hlist.add(boss, itemtype=Tix.TEXT, text=name)
|
||||
count = count+1
|
||||
|
||||
|
||||
for person,boss,name in employees :
|
||||
# '.' is the separator character we chose above
|
||||
#
|
||||
key= boss + '.' + person
|
||||
# ^^^^ ^^^^^^
|
||||
# parent entryPath / child's name
|
||||
|
||||
hlist.add( key, text=name )
|
||||
|
||||
# [Hint] Make sure the keys (e.g. 'boss.person') you choose
|
||||
# are unique names. If you cannot be sure of this (because of
|
||||
# the structure of your database, e.g.) you can use the
|
||||
# "add_child" command instead:
|
||||
#
|
||||
# hlist.addchild( boss, text=name)
|
||||
# ^^^^
|
||||
# parent entryPath
|
||||
|
||||
|
||||
# Use a ButtonBox to hold the buttons.
|
||||
#
|
||||
box= Tix.ButtonBox(top, orientation=Tix.HORIZONTAL )
|
||||
box.add( 'ok', text='Ok', underline=0, width=6,
|
||||
command = self.okcmd)
|
||||
|
||||
box.add( 'cancel', text='Cancel', underline=0, width=6,
|
||||
command = self.quitcmd)
|
||||
|
||||
box.pack( side=Tix.BOTTOM, fill=Tix.X)
|
||||
top.pack( side=Tix.TOP, fill=Tix.BOTH, expand=1 )
|
||||
|
||||
def okcmd (self):
|
||||
self.quitcmd()
|
||||
|
||||
def quitcmd (self):
|
||||
self.exit = 0
|
||||
|
||||
def mainloop(self):
|
||||
while self.exit < 0:
|
||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
||||
|
||||
def destroy (self):
|
||||
self.root.destroy()
|
||||
|
||||
|
||||
# This "if" statement makes it possible to run this script file inside or
|
||||
# outside of the main demo program "tixwidgets.py".
|
||||
#
|
||||
if __name__== '__main__' :
|
||||
root=Tix.Tk()
|
||||
RunSample(root)
|
@ -1,168 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidget": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program using tixwish.
|
||||
|
||||
# This file demonstrates how to use multiple columns and multiple styles
|
||||
# in the tixHList widget
|
||||
#
|
||||
# In a tixHList widget, you can have one ore more columns.
|
||||
#
|
||||
|
||||
import Tix
|
||||
|
||||
TCL_ALL_EVENTS = 0
|
||||
|
||||
def RunSample (root):
|
||||
shlist = DemoSHList(root)
|
||||
shlist.mainloop()
|
||||
shlist.destroy()
|
||||
|
||||
class DemoSHList:
|
||||
def __init__(self, w):
|
||||
self.root = w
|
||||
self.exit = -1
|
||||
|
||||
z = w.winfo_toplevel()
|
||||
z.wm_protocol("WM_DELETE_WINDOW", lambda self=self: self.quitcmd())
|
||||
|
||||
# We create the frame and the ScrolledHList widget
|
||||
# at the top of the dialog box
|
||||
#
|
||||
top = Tix.Frame( w, relief=Tix.RAISED, bd=1)
|
||||
|
||||
# Put a simple hierachy into the HList (two levels). Use colors and
|
||||
# separator widgets (frames) to make the list look fancy
|
||||
#
|
||||
top.a = Tix.ScrolledHList(top, options='hlist.columns 3 hlist.header 1' )
|
||||
top.a.pack( expand=1, fill=Tix.BOTH, padx=10, pady=10, side=Tix.TOP)
|
||||
|
||||
hlist=top.a.hlist
|
||||
|
||||
# Create the title for the HList widget
|
||||
# >> Notice that we have set the hlist.header subwidget option to true
|
||||
# so that the header is displayed
|
||||
#
|
||||
|
||||
boldfont=hlist.tk.call('tix','option','get','bold_font')
|
||||
|
||||
# First some styles for the headers
|
||||
style={}
|
||||
style['header'] = Tix.DisplayStyle(Tix.TEXT, refwindow=hlist,
|
||||
anchor=Tix.CENTER, padx=8, pady=2, font = boldfont )
|
||||
|
||||
hlist.header_create(0, itemtype=Tix.TEXT, text='Name',
|
||||
style=style['header'])
|
||||
hlist.header_create(1, itemtype=Tix.TEXT, text='Position',
|
||||
style=style['header'])
|
||||
|
||||
# Notice that we use 3 columns in the hlist widget. This way when the user
|
||||
# expands the windows wide, the right side of the header doesn't look
|
||||
# chopped off. The following line ensures that the 3 column header is
|
||||
# not shown unless the hlist window is wider than its contents.
|
||||
#
|
||||
hlist.column_width(2,0)
|
||||
|
||||
# This is our little relational database
|
||||
#
|
||||
boss = ('doe', 'John Doe', 'Director')
|
||||
|
||||
managers = [
|
||||
('jeff', 'Jeff Waxman', 'Manager'),
|
||||
('john', 'John Lee', 'Manager'),
|
||||
('peter', 'Peter Kenson', 'Manager')
|
||||
]
|
||||
|
||||
employees = [
|
||||
('alex', 'john', 'Alex Kellman', 'Clerk'),
|
||||
('alan', 'john', 'Alan Adams', 'Clerk'),
|
||||
('andy', 'peter', 'Andreas Crawford', 'Salesman'),
|
||||
('doug', 'jeff', 'Douglas Bloom', 'Clerk'),
|
||||
('jon', 'peter', 'Jon Baraki', 'Salesman'),
|
||||
('chris', 'jeff', 'Chris Geoffrey', 'Clerk'),
|
||||
('chuck', 'jeff', 'Chuck McLean', 'Cleaner')
|
||||
]
|
||||
|
||||
style['mgr_name'] = Tix.DisplayStyle(Tix.TEXT, refwindow=hlist)
|
||||
|
||||
style['mgr_posn'] = Tix.DisplayStyle(Tix.TEXT, padx=8, refwindow=hlist)
|
||||
|
||||
style['empl_name'] = Tix.DisplayStyle(Tix.TEXT, refwindow=hlist)
|
||||
|
||||
style['empl_posn'] = Tix.DisplayStyle(Tix.TEXT, padx=8, refwindow=hlist)
|
||||
|
||||
# Let configure the appearance of the HList subwidget
|
||||
#
|
||||
hlist.config(separator='.', width=25, drawbranch=0, indent=10)
|
||||
hlist.column_width(0, chars=20)
|
||||
|
||||
# Create the boss
|
||||
#
|
||||
hlist.add ('.', itemtype=Tix.TEXT, text=boss[1],
|
||||
style=style['mgr_name'])
|
||||
hlist.item_create('.', 1, itemtype=Tix.TEXT, text=boss[2],
|
||||
style=style['mgr_posn'])
|
||||
|
||||
# Create the managers
|
||||
#
|
||||
|
||||
for key,name,posn in managers :
|
||||
e= '.'+ key
|
||||
hlist.add(e, itemtype=Tix.TEXT, text=name,
|
||||
style=style['mgr_name'])
|
||||
hlist.item_create(e, 1, itemtype=Tix.TEXT, text=posn,
|
||||
style=style['mgr_posn'])
|
||||
|
||||
|
||||
for key,mgr,name,posn in employees :
|
||||
# "." is the separator character we chose above
|
||||
|
||||
entrypath = '.' + mgr + '.' + key
|
||||
|
||||
# ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^
|
||||
# parent entryPath / child's name
|
||||
|
||||
hlist.add(entrypath, text=name, style=style['empl_name'])
|
||||
hlist.item_create(entrypath, 1, itemtype=Tix.TEXT,
|
||||
text = posn, style = style['empl_posn'] )
|
||||
|
||||
|
||||
# Use a ButtonBox to hold the buttons.
|
||||
#
|
||||
box= Tix.ButtonBox(top, orientation=Tix.HORIZONTAL )
|
||||
box.add( 'ok', text='Ok', underline=0, width=6,
|
||||
command = self.okcmd )
|
||||
|
||||
box.add( 'cancel', text='Cancel', underline=0, width=6,
|
||||
command = self.quitcmd )
|
||||
|
||||
box.pack( side=Tix.BOTTOM, fill=Tix.X)
|
||||
top.pack( side=Tix.TOP, fill=Tix.BOTH, expand=1 )
|
||||
|
||||
def okcmd (self):
|
||||
self.quitcmd()
|
||||
|
||||
def quitcmd (self):
|
||||
self.exit = 0
|
||||
|
||||
def mainloop(self):
|
||||
while self.exit < 0:
|
||||
self.root.tk.dooneevent(TCL_ALL_EVENTS)
|
||||
|
||||
def destroy (self):
|
||||
self.root.destroy()
|
||||
|
||||
|
||||
# This "if" statement makes it possible to run this script file inside or
|
||||
# outside of the main demo program "tixwidgets.py".
|
||||
#
|
||||
if __name__== '__main__' :
|
||||
root=Tix.Tk()
|
||||
RunSample(root)
|
@ -1,80 +0,0 @@
|
||||
# -*-mode: python; fill-column: 75; tab-width: 8; coding: iso-latin-1-unix -*-
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# Tix Demostration Program
|
||||
#
|
||||
# This sample program is structured in such a way so that it can be
|
||||
# executed from the Tix demo program "tixwidgets.py": it must have a
|
||||
# procedure called "RunSample". It should also have the "if" statment
|
||||
# at the end of this file so that it can be run as a standalone
|
||||
# program.
|
||||
|
||||
# This file demonstrates how to use the TixTree widget to display
|
||||
# dynamic hierachical data (the files in the Unix file system)
|
||||
#
|
||||
|
||||
import Tix, os
|
||||
|
||||
def RunSample(w):
|
||||
top = Tix.Frame(w, relief=Tix.RAISED, bd=1)
|
||||
tree = Tix.Tree(top, options='separator "/"')
|
||||
tree.pack(expand=1, fill=Tix.BOTH, padx=10, pady=10, side=Tix.LEFT)
|
||||
tree['opencmd'] = lambda dir=None, w=tree: opendir(w, dir)
|
||||
|
||||
# The / directory is added in the "open" mode. The user can open it
|
||||
# and then browse its subdirectories ...
|
||||
adddir(tree, "/")
|
||||
|
||||
box = Tix.ButtonBox(w, orientation=Tix.HORIZONTAL)
|
||||
box.add('ok', text='Ok', underline=0, command=w.destroy, width=6)
|
||||
box.add('cancel', text='Cancel', underline=0, command=w.destroy, width=6)
|
||||
box.pack(side=Tix.BOTTOM, fill=Tix.X)
|
||||
top.pack(side=Tix.TOP, fill=Tix.BOTH, expand=1)
|
||||
|
||||
def adddir(tree, dir):
|
||||
if dir == '/':
|
||||
text = '/'
|
||||
else:
|
||||
text = os.path.basename(dir)
|
||||
tree.hlist.add(dir, itemtype=Tix.IMAGETEXT, text=text,
|
||||
image=tree.tk.call('tix', 'getimage', 'folder'))
|
||||
try:
|
||||
os.listdir(dir)
|
||||
tree.setmode(dir, 'open')
|
||||
except os.error:
|
||||
# No read permission ?
|
||||
pass
|
||||
|
||||
# This function is called whenever the user presses the (+) indicator or
|
||||
# double clicks on a directory whose mode is "open". It loads the files
|
||||
# inside that directory into the Tree widget.
|
||||
#
|
||||
# Note we didn't specify the closecmd option for the Tree widget, so it
|
||||
# performs the default action when the user presses the (-) indicator or
|
||||
# double clicks on a directory whose mode is "close": hide all of its child
|
||||
# entries
|
||||
def opendir(tree, dir):
|
||||
entries = tree.hlist.info_children(dir)
|
||||
if entries:
|
||||
# We have already loaded this directory. Let's just
|
||||
# show all the child entries
|
||||
#
|
||||
# Note: since we load the directory only once, it will not be
|
||||
# refreshed if the you add or remove files from this
|
||||
# directory.
|
||||
#
|
||||
for entry in entries:
|
||||
tree.hlist.show_entry(entry)
|
||||
files = os.listdir(dir)
|
||||
for file in files:
|
||||
if os.path.isdir(dir + '/' + file):
|
||||
adddir(tree, dir + '/' + file)
|
||||
else:
|
||||
tree.hlist.add(dir + '/' + file, itemtype=Tix.IMAGETEXT, text=file,
|
||||
image=tree.tk.call('tix', 'getimage', 'file'))
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tix.Tk()
|
||||
RunSample(root)
|
||||
root.mainloop()
|
File diff suppressed because it is too large
Load Diff
@ -1,10 +0,0 @@
|
||||
Several collections of example code for Tkinter.
|
||||
|
||||
See the toplevel README for an explanation of the difference between
|
||||
Tkinter and _tkinter, how to enable the Python Tk interface, and where
|
||||
to get Matt Conway's lifesaver document.
|
||||
|
||||
Subdirectories:
|
||||
|
||||
guido my original example set (fairly random collection)
|
||||
matt Matt Conway's examples, to go with his lifesaver document
|
@ -1,244 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
|
||||
from Tkinter import *
|
||||
from Canvas import Oval, Group, CanvasText
|
||||
|
||||
|
||||
# Fix a bug in Canvas.Group as distributed in Python 1.4. The
|
||||
# distributed bind() method is broken. This is what should be used:
|
||||
|
||||
class Group(Group):
|
||||
def bind(self, sequence=None, command=None):
|
||||
return self.canvas.tag_bind(self.id, sequence, command)
|
||||
|
||||
class Object:
|
||||
|
||||
"""Base class for composite graphical objects.
|
||||
|
||||
Objects belong to a canvas, and can be moved around on the canvas.
|
||||
They also belong to at most one ``pile'' of objects, and can be
|
||||
transferred between piles (or removed from their pile).
|
||||
|
||||
Objects have a canonical ``x, y'' position which is moved when the
|
||||
object is moved. Where the object is relative to this position
|
||||
depends on the object; for simple objects, it may be their center.
|
||||
|
||||
Objects have mouse sensitivity. They can be clicked, dragged and
|
||||
double-clicked. The behavior may actually determined by the pile
|
||||
they are in.
|
||||
|
||||
All instance attributes are public since the derived class may
|
||||
need them.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, canvas, x=0, y=0, fill='red', text='object'):
|
||||
self.canvas = canvas
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.pile = None
|
||||
self.group = Group(self.canvas)
|
||||
self.createitems(fill, text)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.group)
|
||||
|
||||
def createitems(self, fill, text):
|
||||
self.__oval = Oval(self.canvas,
|
||||
self.x-20, self.y-10, self.x+20, self.y+10,
|
||||
fill=fill, width=3)
|
||||
self.group.addtag_withtag(self.__oval)
|
||||
self.__text = CanvasText(self.canvas,
|
||||
self.x, self.y, text=text)
|
||||
self.group.addtag_withtag(self.__text)
|
||||
|
||||
def moveby(self, dx, dy):
|
||||
if dx == dy == 0:
|
||||
return
|
||||
self.group.move(dx, dy)
|
||||
self.x = self.x + dx
|
||||
self.y = self.y + dy
|
||||
|
||||
def moveto(self, x, y):
|
||||
self.moveby(x - self.x, y - self.y)
|
||||
|
||||
def transfer(self, pile):
|
||||
if self.pile:
|
||||
self.pile.delete(self)
|
||||
self.pile = None
|
||||
self.pile = pile
|
||||
if self.pile:
|
||||
self.pile.add(self)
|
||||
|
||||
def tkraise(self):
|
||||
self.group.tkraise()
|
||||
|
||||
|
||||
class Bottom(Object):
|
||||
|
||||
"""An object to serve as the bottom of a pile."""
|
||||
|
||||
def createitems(self, *args):
|
||||
self.__oval = Oval(self.canvas,
|
||||
self.x-20, self.y-10, self.x+20, self.y+10,
|
||||
fill='gray', outline='')
|
||||
self.group.addtag_withtag(self.__oval)
|
||||
|
||||
|
||||
class Pile:
|
||||
|
||||
"""A group of graphical objects."""
|
||||
|
||||
def __init__(self, canvas, x, y, tag=None):
|
||||
self.canvas = canvas
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.objects = []
|
||||
self.bottom = Bottom(self.canvas, self.x, self.y)
|
||||
self.group = Group(self.canvas, tag=tag)
|
||||
self.group.addtag_withtag(self.bottom.group)
|
||||
self.bindhandlers()
|
||||
|
||||
def bindhandlers(self):
|
||||
self.group.bind('<1>', self.clickhandler)
|
||||
self.group.bind('<Double-1>', self.doubleclickhandler)
|
||||
|
||||
def add(self, object):
|
||||
self.objects.append(object)
|
||||
self.group.addtag_withtag(object.group)
|
||||
self.position(object)
|
||||
|
||||
def delete(self, object):
|
||||
object.group.dtag(self.group)
|
||||
self.objects.remove(object)
|
||||
|
||||
def position(self, object):
|
||||
object.tkraise()
|
||||
i = self.objects.index(object)
|
||||
object.moveto(self.x + i*4, self.y + i*8)
|
||||
|
||||
def clickhandler(self, event):
|
||||
pass
|
||||
|
||||
def doubleclickhandler(self, event):
|
||||
pass
|
||||
|
||||
|
||||
class MovingPile(Pile):
|
||||
|
||||
def bindhandlers(self):
|
||||
Pile.bindhandlers(self)
|
||||
self.group.bind('<B1-Motion>', self.motionhandler)
|
||||
self.group.bind('<ButtonRelease-1>', self.releasehandler)
|
||||
|
||||
movethis = None
|
||||
|
||||
def clickhandler(self, event):
|
||||
tags = self.canvas.gettags('current')
|
||||
for i in range(len(self.objects)):
|
||||
o = self.objects[i]
|
||||
if o.group.tag in tags:
|
||||
break
|
||||
else:
|
||||
self.movethis = None
|
||||
return
|
||||
self.movethis = self.objects[i:]
|
||||
for o in self.movethis:
|
||||
o.tkraise()
|
||||
self.lastx = event.x
|
||||
self.lasty = event.y
|
||||
|
||||
doubleclickhandler = clickhandler
|
||||
|
||||
def motionhandler(self, event):
|
||||
if not self.movethis:
|
||||
return
|
||||
dx = event.x - self.lastx
|
||||
dy = event.y - self.lasty
|
||||
self.lastx = event.x
|
||||
self.lasty = event.y
|
||||
for o in self.movethis:
|
||||
o.moveby(dx, dy)
|
||||
|
||||
def releasehandler(self, event):
|
||||
objects = self.movethis
|
||||
if not objects:
|
||||
return
|
||||
self.movethis = None
|
||||
self.finishmove(objects)
|
||||
|
||||
def finishmove(self, objects):
|
||||
for o in objects:
|
||||
self.position(o)
|
||||
|
||||
|
||||
class Pile1(MovingPile):
|
||||
|
||||
x = 50
|
||||
y = 50
|
||||
tag = 'p1'
|
||||
|
||||
def __init__(self, demo):
|
||||
self.demo = demo
|
||||
MovingPile.__init__(self, self.demo.canvas, self.x, self.y, self.tag)
|
||||
|
||||
def doubleclickhandler(self, event):
|
||||
try:
|
||||
o = self.objects[-1]
|
||||
except IndexError:
|
||||
return
|
||||
o.transfer(self.other())
|
||||
MovingPile.doubleclickhandler(self, event)
|
||||
|
||||
def other(self):
|
||||
return self.demo.p2
|
||||
|
||||
def finishmove(self, objects):
|
||||
o = objects[0]
|
||||
p = self.other()
|
||||
x, y = o.x, o.y
|
||||
if (x-p.x)**2 + (y-p.y)**2 < (x-self.x)**2 + (y-self.y)**2:
|
||||
for o in objects:
|
||||
o.transfer(p)
|
||||
else:
|
||||
MovingPile.finishmove(self, objects)
|
||||
|
||||
class Pile2(Pile1):
|
||||
|
||||
x = 150
|
||||
y = 50
|
||||
tag = 'p2'
|
||||
|
||||
def other(self):
|
||||
return self.demo.p1
|
||||
|
||||
|
||||
class Demo:
|
||||
|
||||
def __init__(self, master):
|
||||
self.master = master
|
||||
self.canvas = Canvas(master,
|
||||
width=200, height=200,
|
||||
background='yellow',
|
||||
relief=SUNKEN, borderwidth=2)
|
||||
self.canvas.pack(expand=1, fill=BOTH)
|
||||
self.p1 = Pile1(self)
|
||||
self.p2 = Pile2(self)
|
||||
o1 = Object(self.canvas, fill='red', text='o1')
|
||||
o2 = Object(self.canvas, fill='green', text='o2')
|
||||
o3 = Object(self.canvas, fill='light blue', text='o3')
|
||||
o1.transfer(self.p1)
|
||||
o2.transfer(self.p1)
|
||||
o3.transfer(self.p2)
|
||||
|
||||
|
||||
# Main function, run when invoked as a stand-alone Python program.
|
||||
|
||||
def main():
|
||||
root = Tk()
|
||||
demo = Demo(root)
|
||||
root.protocol('WM_DELETE_WINDOW', root.quit)
|
||||
root.mainloop()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -1,60 +0,0 @@
|
||||
from Tkinter import *
|
||||
|
||||
# This example program creates a scroling canvas, and demonstrates
|
||||
# how to tie scrollbars and canvses together. The mechanism
|
||||
# is analogus for listboxes and other widgets with
|
||||
# "xscroll" and "yscroll" configuration options.
|
||||
|
||||
class Test(Frame):
|
||||
def printit(self):
|
||||
print "hi"
|
||||
|
||||
def createWidgets(self):
|
||||
self.question = Label(self, text="Can Find The BLUE Square??????")
|
||||
self.question.pack()
|
||||
|
||||
self.QUIT = Button(self, text='QUIT', background='red',
|
||||
height=3, command=self.quit)
|
||||
self.QUIT.pack(side=BOTTOM, fill=BOTH)
|
||||
spacer = Frame(self, height="0.25i")
|
||||
spacer.pack(side=BOTTOM)
|
||||
|
||||
# notice that the scroll region (20" x 20") is larger than
|
||||
# displayed size of the widget (5" x 5")
|
||||
self.draw = Canvas(self, width="5i", height="5i",
|
||||
background="white",
|
||||
scrollregion=(0, 0, "20i", "20i"))
|
||||
|
||||
self.draw.scrollX = Scrollbar(self, orient=HORIZONTAL)
|
||||
self.draw.scrollY = Scrollbar(self, orient=VERTICAL)
|
||||
|
||||
# now tie the three together. This is standard boilerplate text
|
||||
self.draw['xscrollcommand'] = self.draw.scrollX.set
|
||||
self.draw['yscrollcommand'] = self.draw.scrollY.set
|
||||
self.draw.scrollX['command'] = self.draw.xview
|
||||
self.draw.scrollY['command'] = self.draw.yview
|
||||
|
||||
# draw something. Note that the first square
|
||||
# is visible, but you need to scroll to see the second one.
|
||||
self.draw.create_rectangle(0, 0, "3.5i", "3.5i", fill="black")
|
||||
self.draw.create_rectangle("10i", "10i", "13.5i", "13.5i", fill="blue")
|
||||
|
||||
# pack 'em up
|
||||
self.draw.scrollX.pack(side=BOTTOM, fill=X)
|
||||
self.draw.scrollY.pack(side=RIGHT, fill=Y)
|
||||
self.draw.pack(side=LEFT)
|
||||
|
||||
|
||||
def scrollCanvasX(self, *args):
|
||||
print "scrolling", args
|
||||
print self.draw.scrollX.get()
|
||||
|
||||
|
||||
def __init__(self, master=None):
|
||||
Frame.__init__(self, master)
|
||||
Pack.config(self)
|
||||
self.createWidgets()
|
||||
|
||||
test = Test()
|
||||
|
||||
test.mainloop()
|
@ -1,77 +0,0 @@
|
||||
|
||||
========================================================
|
||||
A new turtle module for Python
|
||||
========================================================
|
||||
|
||||
Turtle graphics is a popular way for introducing programming to
|
||||
kids. It was part of the original Logo programming language developed
|
||||
by Wally Feurzig and Seymour Papert in 1966.
|
||||
|
||||
Imagine a robotic turtle starting at (0, 0) in the x-y plane. Give it
|
||||
the command turtle.forward(15), and it moves (on-screen!) 15 pixels in
|
||||
the direction it is facing, drawing a line as it moves. Give it the
|
||||
command turtle.left(25), and it rotates in-place 25 degrees clockwise.
|
||||
|
||||
By combining together these and similar commands, intricate shapes and
|
||||
pictures can easily be drawn.
|
||||
|
||||
----- turtle.py
|
||||
|
||||
This module is an extended reimplementation of turtle.py from the
|
||||
Python standard distribution up to Python 2.5. (See: http:\\www.python.org)
|
||||
|
||||
It tries to keep the merits of turtle.py and to be (nearly) 100%
|
||||
compatible with it. This means in the first place to enable the
|
||||
learning programmer to use all the commands, classes and methods
|
||||
interactively when using the module from within IDLE run with
|
||||
the -n switch.
|
||||
|
||||
Roughly it has the following features added:
|
||||
|
||||
- Better animation of the turtle movements, especially of turning the
|
||||
turtle. So the turtles can more easily be used as a visual feedback
|
||||
instrument by the (beginning) programmer.
|
||||
|
||||
- Different turtle shapes, gif-images as turtle shapes, user defined
|
||||
and user controllable turtle shapes, among them compound
|
||||
(multicolored) shapes. Turtle shapes can be stgretched and tilted, which
|
||||
makes turtles zu very versatile geometrical objects.
|
||||
|
||||
- Fine control over turtle movement and screen updates via delay(),
|
||||
and enhanced tracer() and speed() methods.
|
||||
|
||||
- Aliases for the most commonly used commands, like fd for forward etc.,
|
||||
following the early Logo traditions. This reduces the boring work of
|
||||
typing long sequences of commands, which often occur in a natural way
|
||||
when kids try to program fancy pictures on their first encounter with
|
||||
turtle graphcis.
|
||||
|
||||
- Turtles now have an undo()-method with configurable undo-buffer.
|
||||
|
||||
- Some simple commands/methods for creating event driven programs
|
||||
(mouse-, key-, timer-events). Especially useful for programming games.
|
||||
|
||||
- A scrollable Canvas class. The default scrollable Canvas can be
|
||||
extended interactively as needed while playing around with the turtle(s).
|
||||
|
||||
- A TurtleScreen class with methods controlling background color or
|
||||
background image, window and canvas size and other properties of the
|
||||
TurtleScreen.
|
||||
|
||||
- There is a method, setworldcoordinates(), to install a user defined
|
||||
coordinate-system for the TurtleScreen.
|
||||
|
||||
- The implementation uses a 2-vector class named Vec2D, derived from tuple.
|
||||
This class is public, so it can be imported by the application programmer,
|
||||
which makes certain types of computations very natural and compact.
|
||||
|
||||
- Appearance of the TurtleScreen and the Turtles at startup/import can be
|
||||
configured by means of a turtle.cfg configuration file.
|
||||
The default configuration mimics the appearance of the old turtle module.
|
||||
|
||||
- If configured appropriately the module reads in docstrings from a docstring
|
||||
dictionary in some different language, supplied separately and replaces
|
||||
the english ones by those read in. There is a utility function
|
||||
write_docstringdict() to write a dictionary with the original (english)
|
||||
docstrings to disc, so it can serve as a template for translations.
|
||||
|
@ -1,75 +0,0 @@
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
xturtleDemo - Help
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
This document has two sections:
|
||||
|
||||
(1) How to use the demo viewer
|
||||
(2) How to add your own demos to the demo repository
|
||||
|
||||
|
||||
(1) How to use the demo viewer.
|
||||
|
||||
Select a demoscript from the example menu.
|
||||
The (syntax coloured) source code appears in the left
|
||||
source code window. IT CANNOT BE EDITED, but ONLY VIEWED!
|
||||
|
||||
- Press START button to start the demo.
|
||||
- Stop execution by pressing the STOP button.
|
||||
- Clear screen by pressing the CLEAR button.
|
||||
- Restart by pressing the START button again.
|
||||
|
||||
SPECIAL demos are those which run EVENTDRIVEN.
|
||||
(For example clock.py - or oldTurtleDemo.py which
|
||||
in the end expects a mouse click.):
|
||||
|
||||
Press START button to start the demo.
|
||||
|
||||
- Until the EVENTLOOP is entered everything works
|
||||
as in an ordinary demo script.
|
||||
|
||||
- When the EVENTLOOP is entered, you control the
|
||||
application by using the mouse and/or keys (or it's
|
||||
controlled by some timer events)
|
||||
To stop it you can and must press the STOP button.
|
||||
|
||||
While the EVENTLOOP is running, the examples menu is disabled.
|
||||
|
||||
- Only after having pressed the STOP button, you may
|
||||
restart it or choose another example script.
|
||||
|
||||
* * * * * * * *
|
||||
In some rare situations there may occur interferences/conflicts
|
||||
between events concerning the demo script and those concerning the
|
||||
demo-viewer. (They run in the same process.) Strange behaviour may be
|
||||
the consequence and in the worst case you must close and restart the
|
||||
viewer.
|
||||
* * * * * * * *
|
||||
|
||||
|
||||
(2) How to add your own demos to the demo repository
|
||||
|
||||
- scriptname: must begin with tdemo_ ,
|
||||
so it must have the form tdemo_<your-script-name>.py
|
||||
|
||||
- place: same directory as xturtleDemo.py or some
|
||||
subdirectory, the name of which must also begin with
|
||||
tdemo_.....
|
||||
|
||||
- requirements on source code:
|
||||
code must contain a main() function which will
|
||||
be executed by the viewer (see provided example scripts)
|
||||
main() may return a string which will be displayed
|
||||
in the Label below the source code window (when execution
|
||||
has finished.)
|
||||
|
||||
!! For programs, which are EVENT DRIVEN, main must return
|
||||
!! the string "EVENTLOOP". This informs the viewer, that the
|
||||
!! script is still running and must be stopped by the user!
|
||||
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo-I_dont_like_tiltdemo.py
|
||||
|
||||
Demostrates
|
||||
(a) use of a tilted ellipse as
|
||||
turtle shape
|
||||
(b) stamping that shape
|
||||
|
||||
We can remove it, if you don't like it.
|
||||
Without using reset() ;-)
|
||||
---------------------------------------
|
||||
"""
|
||||
from turtle import *
|
||||
import time
|
||||
|
||||
def main():
|
||||
reset()
|
||||
shape("circle")
|
||||
resizemode("user")
|
||||
|
||||
pu(); bk(24*18/6.283); rt(90); pd()
|
||||
tilt(45)
|
||||
|
||||
pu()
|
||||
|
||||
turtlesize(16,10,5)
|
||||
color("red", "violet")
|
||||
for i in range(18):
|
||||
fd(24)
|
||||
lt(20)
|
||||
stamp()
|
||||
color("red", "")
|
||||
for i in range(18):
|
||||
fd(24)
|
||||
lt(20)
|
||||
stamp()
|
||||
|
||||
tilt(-15)
|
||||
turtlesize(3, 1, 4)
|
||||
color("blue", "yellow")
|
||||
for i in range(17):
|
||||
fd(24)
|
||||
lt(20)
|
||||
if i%2 == 0:
|
||||
stamp()
|
||||
time.sleep(1)
|
||||
while undobufferentries():
|
||||
undo()
|
||||
ht()
|
||||
write("OK, OVER!", align="center", font=("Courier", 18, "bold"))
|
||||
return "Done!"
|
||||
|
||||
if __name__=="__main__":
|
||||
msg = main()
|
||||
print msg
|
||||
mainloop()
|
@ -1,162 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo_bytedesign.py
|
||||
|
||||
An example adapted from the example-suite
|
||||
of PythonCard's turtle graphcis.
|
||||
|
||||
It's based on an article in BYTE magazine
|
||||
Problem Solving with Logo: Using Turtle
|
||||
Graphics to Redraw a Design
|
||||
November 1982, p. 118 - 134
|
||||
|
||||
-------------------------------------------
|
||||
|
||||
Due to the statement
|
||||
|
||||
t.delay(0)
|
||||
|
||||
in line 152, which sets the animation delay
|
||||
to 0, this animation runs in "line per line"
|
||||
mode as fast as possible.
|
||||
"""
|
||||
|
||||
import math
|
||||
from turtle import Turtle, mainloop
|
||||
from time import clock
|
||||
|
||||
# wrapper for any additional drawing routines
|
||||
# that need to know about each other
|
||||
class Designer(Turtle):
|
||||
|
||||
def design(self, homePos, scale):
|
||||
self.up()
|
||||
for i in range(5):
|
||||
self.forward(64.65 * scale)
|
||||
self.down()
|
||||
self.wheel(self.position(), scale)
|
||||
self.up()
|
||||
self.backward(64.65 * scale)
|
||||
self.right(72)
|
||||
self.up()
|
||||
self.goto(homePos)
|
||||
self.right(36)
|
||||
self.forward(24.5 * scale)
|
||||
self.right(198)
|
||||
self.down()
|
||||
self.centerpiece(46 * scale, 143.4, scale)
|
||||
self.tracer(True)
|
||||
|
||||
def wheel(self, initpos, scale):
|
||||
self.right(54)
|
||||
for i in range(4):
|
||||
self.pentpiece(initpos, scale)
|
||||
self.down()
|
||||
self.left(36)
|
||||
for i in range(5):
|
||||
self.tripiece(initpos, scale)
|
||||
self.left(36)
|
||||
for i in range(5):
|
||||
self.down()
|
||||
self.right(72)
|
||||
self.forward(28 * scale)
|
||||
self.up()
|
||||
self.backward(28 * scale)
|
||||
self.left(54)
|
||||
self.getscreen().update()
|
||||
|
||||
def tripiece(self, initpos, scale):
|
||||
oldh = self.heading()
|
||||
self.down()
|
||||
self.backward(2.5 * scale)
|
||||
self.tripolyr(31.5 * scale, scale)
|
||||
self.up()
|
||||
self.goto(initpos)
|
||||
self.setheading(oldh)
|
||||
self.down()
|
||||
self.backward(2.5 * scale)
|
||||
self.tripolyl(31.5 * scale, scale)
|
||||
self.up()
|
||||
self.goto(initpos)
|
||||
self.setheading(oldh)
|
||||
self.left(72)
|
||||
self.getscreen().update()
|
||||
|
||||
def pentpiece(self, initpos, scale):
|
||||
oldh = self.heading()
|
||||
self.up()
|
||||
self.forward(29 * scale)
|
||||
self.down()
|
||||
for i in range(5):
|
||||
self.forward(18 * scale)
|
||||
self.right(72)
|
||||
self.pentr(18 * scale, 75, scale)
|
||||
self.up()
|
||||
self.goto(initpos)
|
||||
self.setheading(oldh)
|
||||
self.forward(29 * scale)
|
||||
self.down()
|
||||
for i in range(5):
|
||||
self.forward(18 * scale)
|
||||
self.right(72)
|
||||
self.pentl(18 * scale, 75, scale)
|
||||
self.up()
|
||||
self.goto(initpos)
|
||||
self.setheading(oldh)
|
||||
self.left(72)
|
||||
self.getscreen().update()
|
||||
|
||||
def pentl(self, side, ang, scale):
|
||||
if side < (2 * scale): return
|
||||
self.forward(side)
|
||||
self.left(ang)
|
||||
self.pentl(side - (.38 * scale), ang, scale)
|
||||
|
||||
def pentr(self, side, ang, scale):
|
||||
if side < (2 * scale): return
|
||||
self.forward(side)
|
||||
self.right(ang)
|
||||
self.pentr(side - (.38 * scale), ang, scale)
|
||||
|
||||
def tripolyr(self, side, scale):
|
||||
if side < (4 * scale): return
|
||||
self.forward(side)
|
||||
self.right(111)
|
||||
self.forward(side / 1.78)
|
||||
self.right(111)
|
||||
self.forward(side / 1.3)
|
||||
self.right(146)
|
||||
self.tripolyr(side * .75, scale)
|
||||
|
||||
def tripolyl(self, side, scale):
|
||||
if side < (4 * scale): return
|
||||
self.forward(side)
|
||||
self.left(111)
|
||||
self.forward(side / 1.78)
|
||||
self.left(111)
|
||||
self.forward(side / 1.3)
|
||||
self.left(146)
|
||||
self.tripolyl(side * .75, scale)
|
||||
|
||||
def centerpiece(self, s, a, scale):
|
||||
self.forward(s); self.left(a)
|
||||
if s < (7.5 * scale):
|
||||
return
|
||||
self.centerpiece(s - (1.2 * scale), a, scale)
|
||||
|
||||
def main():
|
||||
t = Designer()
|
||||
t.speed(0)
|
||||
t.hideturtle()
|
||||
t.getscreen().delay(0)
|
||||
t.tracer(0)
|
||||
at = clock()
|
||||
t.design(t.position(), 2)
|
||||
et = clock()
|
||||
return "runtime: %.2f sec." % (et-at)
|
||||
|
||||
if __name__ == '__main__':
|
||||
msg = main()
|
||||
print msg
|
||||
mainloop()
|
@ -1,59 +0,0 @@
|
||||
# File: tdemo_chaos.py
|
||||
# Author: Gregor Lingl
|
||||
# Date: 2009-06-24
|
||||
|
||||
# A demonstration of chaos
|
||||
|
||||
from turtle import *
|
||||
|
||||
N = 80
|
||||
|
||||
def f(x):
|
||||
return 3.9*x*(1-x)
|
||||
|
||||
def g(x):
|
||||
return 3.9*(x-x**2)
|
||||
|
||||
def h(x):
|
||||
return 3.9*x-3.9*x*x
|
||||
|
||||
def jumpto(x, y):
|
||||
penup(); goto(x,y)
|
||||
|
||||
def line(x1, y1, x2, y2):
|
||||
jumpto(x1, y1)
|
||||
pendown()
|
||||
goto(x2, y2)
|
||||
|
||||
def coosys():
|
||||
line(-1, 0, N+1, 0)
|
||||
line(0, -0.1, 0, 1.1)
|
||||
|
||||
def plot(fun, start, colour):
|
||||
pencolor(colour)
|
||||
x = start
|
||||
jumpto(0, x)
|
||||
pendown()
|
||||
dot(5)
|
||||
for i in range(N):
|
||||
x=fun(x)
|
||||
goto(i+1,x)
|
||||
dot(5)
|
||||
|
||||
def main():
|
||||
reset()
|
||||
setworldcoordinates(-1.0,-0.1, N+1, 1.1)
|
||||
speed(0)
|
||||
hideturtle()
|
||||
coosys()
|
||||
plot(f, 0.35, "blue")
|
||||
plot(g, 0.35, "green")
|
||||
plot(h, 0.35, "red")
|
||||
# Now zoom in:
|
||||
for s in range(100):
|
||||
setworldcoordinates(0.5*s,-0.1, N+1, 1.1)
|
||||
return "Done!"
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
mainloop()
|
@ -1,132 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: cp1252 -*-
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo_clock.py
|
||||
|
||||
Enhanced clock-program, showing date
|
||||
and time
|
||||
------------------------------------
|
||||
Press STOP to exit the program!
|
||||
------------------------------------
|
||||
"""
|
||||
from turtle import *
|
||||
from datetime import datetime
|
||||
|
||||
mode("logo")
|
||||
|
||||
def jump(distanz, winkel=0):
|
||||
penup()
|
||||
right(winkel)
|
||||
forward(distanz)
|
||||
left(winkel)
|
||||
pendown()
|
||||
|
||||
def hand(laenge, spitze):
|
||||
fd(laenge*1.15)
|
||||
rt(90)
|
||||
fd(spitze/2.0)
|
||||
lt(120)
|
||||
fd(spitze)
|
||||
lt(120)
|
||||
fd(spitze)
|
||||
lt(120)
|
||||
fd(spitze/2.0)
|
||||
|
||||
def make_hand_shape(name, laenge, spitze):
|
||||
reset()
|
||||
jump(-laenge*0.15)
|
||||
begin_poly()
|
||||
hand(laenge, spitze)
|
||||
end_poly()
|
||||
hand_form = get_poly()
|
||||
register_shape(name, hand_form)
|
||||
|
||||
|
||||
def clockface(radius):
|
||||
reset()
|
||||
pensize(7)
|
||||
for i in range(60):
|
||||
jump(radius)
|
||||
if i % 5 == 0:
|
||||
fd(25)
|
||||
jump(-radius-25)
|
||||
else:
|
||||
dot(3)
|
||||
jump(-radius)
|
||||
rt(6)
|
||||
|
||||
def setup():
|
||||
global second_hand, minute_hand, hour_hand, writer
|
||||
mode("logo")
|
||||
make_hand_shape("second_hand", 125, 25)
|
||||
make_hand_shape("minute_hand", 130, 25)
|
||||
make_hand_shape("hour_hand", 90, 25)
|
||||
clockface(160)
|
||||
second_hand = Turtle()
|
||||
second_hand.shape("second_hand")
|
||||
second_hand.color("gray20", "gray80")
|
||||
minute_hand = Turtle()
|
||||
minute_hand.shape("minute_hand")
|
||||
minute_hand.color("blue1", "red1")
|
||||
hour_hand = Turtle()
|
||||
hour_hand.shape("hour_hand")
|
||||
hour_hand.color("blue3", "red3")
|
||||
for hand in second_hand, minute_hand, hour_hand:
|
||||
hand.resizemode("user")
|
||||
hand.shapesize(1, 1, 3)
|
||||
hand.speed(0)
|
||||
ht()
|
||||
writer = Turtle()
|
||||
#writer.mode("logo")
|
||||
writer.ht()
|
||||
writer.pu()
|
||||
writer.bk(85)
|
||||
|
||||
|
||||
def wochentag(t):
|
||||
wochentag = ["Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday", "Sunday"]
|
||||
return wochentag[t.weekday()]
|
||||
|
||||
def datum(z):
|
||||
monat = ["Jan.", "Feb.", "Mar.", "Apr.", "May", "June",
|
||||
"July", "Aug.", "Sep.", "Oct.", "Nov.", "Dec."]
|
||||
j = z.year
|
||||
m = monat[z.month - 1]
|
||||
t = z.day
|
||||
return "%s %d %d" % (m, t, j)
|
||||
|
||||
def tick():
|
||||
t = datetime.today()
|
||||
sekunde = t.second + t.microsecond*0.000001
|
||||
minute = t.minute + sekunde/60.0
|
||||
stunde = t.hour + minute/60.0
|
||||
tracer(False)
|
||||
writer.clear()
|
||||
writer.home()
|
||||
writer.forward(65)
|
||||
writer.write(wochentag(t),
|
||||
align="center", font=("Courier", 14, "bold"))
|
||||
writer.back(150)
|
||||
writer.write(datum(t),
|
||||
align="center", font=("Courier", 14, "bold"))
|
||||
writer.forward(85)
|
||||
tracer(True)
|
||||
second_hand.setheading(6*sekunde)
|
||||
minute_hand.setheading(6*minute)
|
||||
hour_hand.setheading(30*stunde)
|
||||
tracer(True)
|
||||
ontimer(tick, 100)
|
||||
|
||||
def main():
|
||||
tracer(False)
|
||||
setup()
|
||||
tracer(True)
|
||||
tick()
|
||||
return "EVENTLOOP"
|
||||
|
||||
if __name__ == "__main__":
|
||||
msg = main()
|
||||
print msg
|
||||
mainloop()
|
@ -1,137 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo_fractalCurves.py
|
||||
|
||||
This program draws two fractal-curve-designs:
|
||||
(1) A hilbert curve (in a box)
|
||||
(2) A combination of Koch-curves.
|
||||
|
||||
The CurvesTurtle class and the fractal-curve-
|
||||
methods are taken from the PythonCard example
|
||||
scripts for turtle-graphics.
|
||||
"""
|
||||
from turtle import *
|
||||
from time import sleep, clock
|
||||
|
||||
class CurvesTurtle(Pen):
|
||||
# example derived from
|
||||
# Turtle Geometry: The Computer as a Medium for Exploring Mathematics
|
||||
# by Harold Abelson and Andrea diSessa
|
||||
# p. 96-98
|
||||
def hilbert(self, size, level, parity):
|
||||
if level == 0:
|
||||
return
|
||||
# rotate and draw first subcurve with opposite parity to big curve
|
||||
self.left(parity * 90)
|
||||
self.hilbert(size, level - 1, -parity)
|
||||
# interface to and draw second subcurve with same parity as big curve
|
||||
self.forward(size)
|
||||
self.right(parity * 90)
|
||||
self.hilbert(size, level - 1, parity)
|
||||
# third subcurve
|
||||
self.forward(size)
|
||||
self.hilbert(size, level - 1, parity)
|
||||
# fourth subcurve
|
||||
self.right(parity * 90)
|
||||
self.forward(size)
|
||||
self.hilbert(size, level - 1, -parity)
|
||||
# a final turn is needed to make the turtle
|
||||
# end up facing outward from the large square
|
||||
self.left(parity * 90)
|
||||
|
||||
# Visual Modeling with Logo: A Structural Approach to Seeing
|
||||
# by James Clayson
|
||||
# Koch curve, after Helge von Koch who introduced this geometric figure in 1904
|
||||
# p. 146
|
||||
def fractalgon(self, n, rad, lev, dir):
|
||||
import math
|
||||
|
||||
# if dir = 1 turn outward
|
||||
# if dir = -1 turn inward
|
||||
edge = 2 * rad * math.sin(math.pi / n)
|
||||
self.pu()
|
||||
self.fd(rad)
|
||||
self.pd()
|
||||
self.rt(180 - (90 * (n - 2) / n))
|
||||
for i in range(n):
|
||||
self.fractal(edge, lev, dir)
|
||||
self.rt(360 / n)
|
||||
self.lt(180 - (90 * (n - 2) / n))
|
||||
self.pu()
|
||||
self.bk(rad)
|
||||
self.pd()
|
||||
|
||||
# p. 146
|
||||
def fractal(self, dist, depth, dir):
|
||||
if depth < 1:
|
||||
self.fd(dist)
|
||||
return
|
||||
self.fractal(dist / 3, depth - 1, dir)
|
||||
self.lt(60 * dir)
|
||||
self.fractal(dist / 3, depth - 1, dir)
|
||||
self.rt(120 * dir)
|
||||
self.fractal(dist / 3, depth - 1, dir)
|
||||
self.lt(60 * dir)
|
||||
self.fractal(dist / 3, depth - 1, dir)
|
||||
|
||||
def main():
|
||||
ft = CurvesTurtle()
|
||||
|
||||
ft.reset()
|
||||
ft.speed(0)
|
||||
ft.ht()
|
||||
ft.tracer(1,0)
|
||||
ft.pu()
|
||||
|
||||
size = 6
|
||||
ft.setpos(-33*size, -32*size)
|
||||
ft.pd()
|
||||
|
||||
ta=clock()
|
||||
ft.fillcolor("red")
|
||||
ft.fill(True)
|
||||
ft.fd(size)
|
||||
|
||||
ft.hilbert(size, 6, 1)
|
||||
|
||||
# frame
|
||||
ft.fd(size)
|
||||
for i in range(3):
|
||||
ft.lt(90)
|
||||
ft.fd(size*(64+i%2))
|
||||
ft.pu()
|
||||
for i in range(2):
|
||||
ft.fd(size)
|
||||
ft.rt(90)
|
||||
ft.pd()
|
||||
for i in range(4):
|
||||
ft.fd(size*(66+i%2))
|
||||
ft.rt(90)
|
||||
ft.fill(False)
|
||||
tb=clock()
|
||||
res = "Hilbert: %.2fsec. " % (tb-ta)
|
||||
|
||||
sleep(3)
|
||||
|
||||
ft.reset()
|
||||
ft.speed(0)
|
||||
ft.ht()
|
||||
ft.tracer(1,0)
|
||||
|
||||
ta=clock()
|
||||
ft.color("black", "blue")
|
||||
ft.fill(True)
|
||||
ft.fractalgon(3, 250, 4, 1)
|
||||
ft.fill(True)
|
||||
ft.color("red")
|
||||
ft.fractalgon(3, 200, 4, -1)
|
||||
ft.fill(False)
|
||||
tb=clock()
|
||||
res += "Koch: %.2fsec." % (tb-ta)
|
||||
return res
|
||||
|
||||
if __name__ == '__main__':
|
||||
msg = main()
|
||||
print msg
|
||||
mainloop()
|
@ -1,119 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
xtx_lindenmayer_indian.py
|
||||
|
||||
Each morning women in Tamil Nadu, in southern
|
||||
India, place designs, created by using rice
|
||||
flour and known as kolam on the thresholds of
|
||||
their homes.
|
||||
|
||||
These can be described by Lindenmayer systems,
|
||||
which can easily be implemented with turtle
|
||||
graphics and Python.
|
||||
|
||||
Two examples are shown here:
|
||||
(1) the snake kolam
|
||||
(2) anklets of Krishna
|
||||
|
||||
Taken from Marcia Ascher: Mathematics
|
||||
Elsewhere, An Exploration of Ideas Across
|
||||
Cultures
|
||||
|
||||
"""
|
||||
################################
|
||||
# Mini Lindenmayer tool
|
||||
###############################
|
||||
|
||||
from turtle import *
|
||||
|
||||
def replace( seq, replacementRules, n ):
|
||||
for i in range(n):
|
||||
newseq = ""
|
||||
for element in seq:
|
||||
newseq = newseq + replacementRules.get(element,element)
|
||||
seq = newseq
|
||||
return seq
|
||||
|
||||
def draw( commands, rules ):
|
||||
for b in commands:
|
||||
try:
|
||||
rules[b]()
|
||||
except TypeError:
|
||||
try:
|
||||
draw(rules[b], rules)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def main():
|
||||
################################
|
||||
# Example 1: Snake kolam
|
||||
################################
|
||||
|
||||
|
||||
def r():
|
||||
right(45)
|
||||
|
||||
def l():
|
||||
left(45)
|
||||
|
||||
def f():
|
||||
forward(7.5)
|
||||
|
||||
snake_rules = {"-":r, "+":l, "f":f, "b":"f+f+f--f--f+f+f"}
|
||||
snake_replacementRules = {"b": "b+f+b--f--b+f+b"}
|
||||
snake_start = "b--f--b--f"
|
||||
|
||||
drawing = replace(snake_start, snake_replacementRules, 3)
|
||||
|
||||
reset()
|
||||
speed(3)
|
||||
tracer(1,0)
|
||||
ht()
|
||||
up()
|
||||
backward(195)
|
||||
down()
|
||||
draw(drawing, snake_rules)
|
||||
|
||||
from time import sleep
|
||||
sleep(3)
|
||||
|
||||
################################
|
||||
# Example 2: Anklets of Krishna
|
||||
################################
|
||||
|
||||
def A():
|
||||
color("red")
|
||||
circle(10,90)
|
||||
|
||||
def B():
|
||||
from math import sqrt
|
||||
color("black")
|
||||
l = 5/sqrt(2)
|
||||
forward(l)
|
||||
circle(l, 270)
|
||||
forward(l)
|
||||
|
||||
def F():
|
||||
color("green")
|
||||
forward(10)
|
||||
|
||||
krishna_rules = {"a":A, "b":B, "f":F}
|
||||
krishna_replacementRules = {"a" : "afbfa", "b" : "afbfbfbfa" }
|
||||
krishna_start = "fbfbfbfb"
|
||||
|
||||
reset()
|
||||
speed(0)
|
||||
tracer(3,0)
|
||||
ht()
|
||||
left(45)
|
||||
drawing = replace(krishna_start, krishna_replacementRules, 3)
|
||||
draw(drawing, krishna_rules)
|
||||
tracer(1)
|
||||
return "Done!"
|
||||
|
||||
if __name__=='__main__':
|
||||
msg = main()
|
||||
print msg
|
||||
mainloop()
|
@ -1,76 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo_minimal_hanoi.py
|
||||
|
||||
A minimal 'Towers of Hanoi' animation:
|
||||
A tower of 6 discs is transferred from the
|
||||
left to the right peg.
|
||||
|
||||
An imho quite elegant and concise
|
||||
implementation using a tower class, which
|
||||
is derived from the built-in type list.
|
||||
|
||||
Discs are turtles with shape "square", but
|
||||
stretched to rectangles by shapesize()
|
||||
---------------------------------------
|
||||
To exit press STOP button
|
||||
---------------------------------------
|
||||
"""
|
||||
from turtle import *
|
||||
|
||||
class Disc(Turtle):
|
||||
def __init__(self, n):
|
||||
Turtle.__init__(self, shape="square", visible=False)
|
||||
self.pu()
|
||||
self.shapesize(1.5, n*1.5, 2) # square-->rectangle
|
||||
self.fillcolor(n/6., 0, 1-n/6.)
|
||||
self.st()
|
||||
|
||||
class Tower(list):
|
||||
"Hanoi tower, a subclass of built-in type list"
|
||||
def __init__(self, x):
|
||||
"create an empty tower. x is x-position of peg"
|
||||
self.x = x
|
||||
def push(self, d):
|
||||
d.setx(self.x)
|
||||
d.sety(-150+34*len(self))
|
||||
self.append(d)
|
||||
def pop(self):
|
||||
d = list.pop(self)
|
||||
d.sety(150)
|
||||
return d
|
||||
|
||||
def hanoi(n, from_, with_, to_):
|
||||
if n > 0:
|
||||
hanoi(n-1, from_, to_, with_)
|
||||
to_.push(from_.pop())
|
||||
hanoi(n-1, with_, from_, to_)
|
||||
|
||||
def play():
|
||||
onkey(None,"space")
|
||||
clear()
|
||||
hanoi(6, t1, t2, t3)
|
||||
write("press STOP button to exit",
|
||||
align="center", font=("Courier", 16, "bold"))
|
||||
|
||||
def main():
|
||||
global t1, t2, t3
|
||||
ht(); penup(); goto(0, -225) # writer turtle
|
||||
t1 = Tower(-250)
|
||||
t2 = Tower(0)
|
||||
t3 = Tower(250)
|
||||
# make tower of 6 discs
|
||||
for i in range(6,0,-1):
|
||||
t1.push(Disc(i))
|
||||
# prepare spartanic user interface ;-)
|
||||
write("press spacebar to start game",
|
||||
align="center", font=("Courier", 16, "bold"))
|
||||
onkey(play, "space")
|
||||
listen()
|
||||
return "EVENTLOOP"
|
||||
|
||||
if __name__=="__main__":
|
||||
msg = main()
|
||||
print msg
|
||||
mainloop()
|
@ -1,50 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo_paint.py
|
||||
|
||||
A simple eventdriven paint program
|
||||
|
||||
- use left mouse button to move turtle
|
||||
- middle mouse button to change color
|
||||
- right mouse button do turn filling on/off
|
||||
-------------------------------------------
|
||||
Play around by clicking into the canvas
|
||||
using all three mouse buttons.
|
||||
-------------------------------------------
|
||||
To exit press STOP button
|
||||
-------------------------------------------
|
||||
"""
|
||||
from turtle import *
|
||||
|
||||
def switchupdown(x=0, y=0):
|
||||
if pen()["pendown"]:
|
||||
end_fill()
|
||||
up()
|
||||
else:
|
||||
down()
|
||||
begin_fill()
|
||||
|
||||
def changecolor(x=0, y=0):
|
||||
global colors
|
||||
colors = colors[1:]+colors[:1]
|
||||
color(colors[0])
|
||||
|
||||
def main():
|
||||
global colors
|
||||
shape("circle")
|
||||
resizemode("user")
|
||||
shapesize(.5)
|
||||
width(3)
|
||||
colors=["red", "green", "blue", "yellow"]
|
||||
color(colors[0])
|
||||
switchupdown()
|
||||
onscreenclick(goto,1)
|
||||
onscreenclick(changecolor,2)
|
||||
onscreenclick(switchupdown,3)
|
||||
return "EVENTLOOP"
|
||||
|
||||
if __name__ == "__main__":
|
||||
msg = main()
|
||||
print msg
|
||||
mainloop()
|
@ -1,65 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo_peace.py
|
||||
|
||||
A very simple drawing suitable as a beginner's
|
||||
programming example.
|
||||
|
||||
Uses only commands, which are also available in
|
||||
old turtle.py.
|
||||
|
||||
Intentionally no variables are used except for the
|
||||
colorloop:
|
||||
"""
|
||||
|
||||
from turtle import *
|
||||
|
||||
def main():
|
||||
peacecolors = ("red3", "orange", "yellow",
|
||||
"seagreen4", "orchid4",
|
||||
"royalblue1", "dodgerblue4")
|
||||
|
||||
reset()
|
||||
s = Screen()
|
||||
up()
|
||||
goto(-320,-195)
|
||||
width(70)
|
||||
|
||||
for pcolor in peacecolors:
|
||||
color(pcolor)
|
||||
down()
|
||||
forward(640)
|
||||
up()
|
||||
backward(640)
|
||||
left(90)
|
||||
forward(66)
|
||||
right(90)
|
||||
|
||||
width(25)
|
||||
color("white")
|
||||
goto(0,-170)
|
||||
down()
|
||||
|
||||
circle(170)
|
||||
left(90)
|
||||
forward(340)
|
||||
up()
|
||||
left(180)
|
||||
forward(170)
|
||||
right(45)
|
||||
down()
|
||||
forward(170)
|
||||
up()
|
||||
backward(170)
|
||||
left(90)
|
||||
down()
|
||||
forward(170)
|
||||
up()
|
||||
|
||||
goto(0,300) # vanish if hideturtle() is not available ;-)
|
||||
return "Done!!"
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
mainloop()
|
@ -1,181 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" xturtle-example-suite:
|
||||
|
||||
xtx_kites_and_darts.py
|
||||
|
||||
Constructs two aperiodic penrose-tilings,
|
||||
consisting of kites and darts, by the method
|
||||
of inflation in six steps.
|
||||
|
||||
Starting points are the patterns "sun"
|
||||
consisting of five kites and "star"
|
||||
consisting of five darts.
|
||||
|
||||
For more information see:
|
||||
http://en.wikipedia.org/wiki/Penrose_tiling
|
||||
-------------------------------------------
|
||||
"""
|
||||
from turtle import *
|
||||
from math import cos, pi
|
||||
from time import clock, sleep
|
||||
|
||||
f = (5**0.5-1)/2.0 # (sqrt(5)-1)/2 -- golden ratio
|
||||
d = 2 * cos(3*pi/10)
|
||||
|
||||
def kite(l):
|
||||
fl = f * l
|
||||
lt(36)
|
||||
fd(l)
|
||||
rt(108)
|
||||
fd(fl)
|
||||
rt(36)
|
||||
fd(fl)
|
||||
rt(108)
|
||||
fd(l)
|
||||
rt(144)
|
||||
|
||||
def dart(l):
|
||||
fl = f * l
|
||||
lt(36)
|
||||
fd(l)
|
||||
rt(144)
|
||||
fd(fl)
|
||||
lt(36)
|
||||
fd(fl)
|
||||
rt(144)
|
||||
fd(l)
|
||||
rt(144)
|
||||
|
||||
def inflatekite(l, n):
|
||||
if n == 0:
|
||||
px, py = pos()
|
||||
h, x, y = int(heading()), round(px,3), round(py,3)
|
||||
tiledict[(h,x,y)] = True
|
||||
return
|
||||
fl = f * l
|
||||
lt(36)
|
||||
inflatedart(fl, n-1)
|
||||
fd(l)
|
||||
rt(144)
|
||||
inflatekite(fl, n-1)
|
||||
lt(18)
|
||||
fd(l*d)
|
||||
rt(162)
|
||||
inflatekite(fl, n-1)
|
||||
lt(36)
|
||||
fd(l)
|
||||
rt(180)
|
||||
inflatedart(fl, n-1)
|
||||
lt(36)
|
||||
|
||||
def inflatedart(l, n):
|
||||
if n == 0:
|
||||
px, py = pos()
|
||||
h, x, y = int(heading()), round(px,3), round(py,3)
|
||||
tiledict[(h,x,y)] = False
|
||||
return
|
||||
fl = f * l
|
||||
inflatekite(fl, n-1)
|
||||
lt(36)
|
||||
fd(l)
|
||||
rt(180)
|
||||
inflatedart(fl, n-1)
|
||||
lt(54)
|
||||
fd(l*d)
|
||||
rt(126)
|
||||
inflatedart(fl, n-1)
|
||||
fd(l)
|
||||
rt(144)
|
||||
|
||||
def draw(l, n, th=2):
|
||||
clear()
|
||||
l = l * f**n
|
||||
shapesize(l/100.0, l/100.0, th)
|
||||
for k in tiledict:
|
||||
h, x, y = k
|
||||
setpos(x, y)
|
||||
setheading(h)
|
||||
if tiledict[k]:
|
||||
shape("kite")
|
||||
color("black", (0, 0.75, 0))
|
||||
else:
|
||||
shape("dart")
|
||||
color("black", (0.75, 0, 0))
|
||||
stamp()
|
||||
|
||||
def sun(l, n):
|
||||
for i in range(5):
|
||||
inflatekite(l, n)
|
||||
lt(72)
|
||||
|
||||
def star(l,n):
|
||||
for i in range(5):
|
||||
inflatedart(l, n)
|
||||
lt(72)
|
||||
|
||||
def makeshapes():
|
||||
tracer(0)
|
||||
begin_poly()
|
||||
kite(100)
|
||||
end_poly()
|
||||
register_shape("kite", get_poly())
|
||||
begin_poly()
|
||||
dart(100)
|
||||
end_poly()
|
||||
register_shape("dart", get_poly())
|
||||
tracer(1)
|
||||
|
||||
def start():
|
||||
reset()
|
||||
ht()
|
||||
pu()
|
||||
makeshapes()
|
||||
resizemode("user")
|
||||
|
||||
def test(l=200, n=4, fun=sun, startpos=(0,0), th=2):
|
||||
global tiledict
|
||||
goto(startpos)
|
||||
setheading(0)
|
||||
tiledict = {}
|
||||
a = clock()
|
||||
tracer(0)
|
||||
fun(l, n)
|
||||
b = clock()
|
||||
draw(l, n, th)
|
||||
tracer(1)
|
||||
c = clock()
|
||||
print "Calculation: %7.4f s" % (b - a)
|
||||
print "Drawing: %7.4f s" % (c - b)
|
||||
print "Together: %7.4f s" % (c - a)
|
||||
nk = len([x for x in tiledict if tiledict[x]])
|
||||
nd = len([x for x in tiledict if not tiledict[x]])
|
||||
print "%d kites and %d darts = %d pieces." % (nk, nd, nk+nd)
|
||||
|
||||
def demo(fun=sun):
|
||||
start()
|
||||
for i in range(8):
|
||||
a = clock()
|
||||
test(300, i, fun)
|
||||
b = clock()
|
||||
t = b - a
|
||||
if t < 2:
|
||||
sleep(2 - t)
|
||||
|
||||
def main():
|
||||
#title("Penrose-tiling with kites and darts.")
|
||||
mode("logo")
|
||||
bgcolor(0.3, 0.3, 0)
|
||||
demo(sun)
|
||||
sleep(2)
|
||||
demo(star)
|
||||
pencolor("black")
|
||||
goto(0,-200)
|
||||
pencolor(0.7,0.7,1)
|
||||
write("Please wait...",
|
||||
align="center", font=('Arial Black', 36, 'bold'))
|
||||
test(600, 8, startpos=(70, 117))
|
||||
return "Done"
|
||||
|
||||
if __name__ == "__main__":
|
||||
msg = main()
|
||||
mainloop()
|
@ -1,113 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo_planets_and_moon.py
|
||||
|
||||
Gravitational system simulation using the
|
||||
approximation method from Feynman-lectures,
|
||||
p.9-8, using turtlegraphics.
|
||||
|
||||
Example: heavy central body, light planet,
|
||||
very light moon!
|
||||
Planet has a circular orbit, moon a stable
|
||||
orbit around the planet.
|
||||
|
||||
You can hold the movement temporarily by pressing
|
||||
the left mouse button with mouse over the
|
||||
scrollbar of the canvas.
|
||||
|
||||
"""
|
||||
from turtle import Shape, Turtle, mainloop, Vec2D as Vec
|
||||
from time import sleep
|
||||
|
||||
G = 8
|
||||
|
||||
class GravSys(object):
|
||||
def __init__(self):
|
||||
self.planets = []
|
||||
self.t = 0
|
||||
self.dt = 0.01
|
||||
def init(self):
|
||||
for p in self.planets:
|
||||
p.init()
|
||||
def start(self):
|
||||
for i in range(10000):
|
||||
self.t += self.dt
|
||||
for p in self.planets:
|
||||
p.step()
|
||||
|
||||
class Star(Turtle):
|
||||
def __init__(self, m, x, v, gravSys, shape):
|
||||
Turtle.__init__(self, shape=shape)
|
||||
self.penup()
|
||||
self.m = m
|
||||
self.setpos(x)
|
||||
self.v = v
|
||||
gravSys.planets.append(self)
|
||||
self.gravSys = gravSys
|
||||
self.resizemode("user")
|
||||
self.pendown()
|
||||
def init(self):
|
||||
dt = self.gravSys.dt
|
||||
self.a = self.acc()
|
||||
self.v = self.v + 0.5*dt*self.a
|
||||
def acc(self):
|
||||
a = Vec(0,0)
|
||||
for planet in self.gravSys.planets:
|
||||
if planet != self:
|
||||
v = planet.pos()-self.pos()
|
||||
a += (G*planet.m/abs(v)**3)*v
|
||||
return a
|
||||
def step(self):
|
||||
dt = self.gravSys.dt
|
||||
self.setpos(self.pos() + dt*self.v)
|
||||
if self.gravSys.planets.index(self) != 0:
|
||||
self.setheading(self.towards(self.gravSys.planets[0]))
|
||||
self.a = self.acc()
|
||||
self.v = self.v + dt*self.a
|
||||
|
||||
## create compound yellow/blue turtleshape for planets
|
||||
|
||||
def main():
|
||||
s = Turtle()
|
||||
s.reset()
|
||||
s.tracer(0,0)
|
||||
s.ht()
|
||||
s.pu()
|
||||
s.fd(6)
|
||||
s.lt(90)
|
||||
s.begin_poly()
|
||||
s.circle(6, 180)
|
||||
s.end_poly()
|
||||
m1 = s.get_poly()
|
||||
s.begin_poly()
|
||||
s.circle(6,180)
|
||||
s.end_poly()
|
||||
m2 = s.get_poly()
|
||||
|
||||
planetshape = Shape("compound")
|
||||
planetshape.addcomponent(m1,"orange")
|
||||
planetshape.addcomponent(m2,"blue")
|
||||
s.getscreen().register_shape("planet", planetshape)
|
||||
s.tracer(1,0)
|
||||
|
||||
## setup gravitational system
|
||||
gs = GravSys()
|
||||
sun = Star(1000000, Vec(0,0), Vec(0,-2.5), gs, "circle")
|
||||
sun.color("yellow")
|
||||
sun.shapesize(1.8)
|
||||
sun.pu()
|
||||
earth = Star(12500, Vec(210,0), Vec(0,195), gs, "planet")
|
||||
earth.pencolor("green")
|
||||
earth.shapesize(0.8)
|
||||
moon = Star(1, Vec(220,0), Vec(0,295), gs, "planet")
|
||||
moon.pencolor("blue")
|
||||
moon.shapesize(0.5)
|
||||
gs.init()
|
||||
gs.start()
|
||||
return "Done!"
|
||||
|
||||
if __name__ == '__main__':
|
||||
msg = main()
|
||||
print msg
|
||||
mainloop()
|
@ -1,63 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo_tree.py
|
||||
|
||||
Displays a 'breadth-first-tree' - in contrast
|
||||
to the classical Logo tree drawing programs,
|
||||
which use a depth-first-algorithm.
|
||||
|
||||
Uses:
|
||||
(1) a tree-generator, where the drawing is
|
||||
quasi the side-effect, whereas the generator
|
||||
always yields None.
|
||||
(2) Turtle-cloning: At each branching point the
|
||||
current pen is cloned. So in the end there
|
||||
are 1024 turtles.
|
||||
"""
|
||||
from turtle import Turtle, mainloop
|
||||
from time import clock
|
||||
|
||||
def tree(plist, l, a, f):
|
||||
""" plist is list of pens
|
||||
l is length of branch
|
||||
a is half of the angle between 2 branches
|
||||
f is factor by which branch is shortened
|
||||
from level to level."""
|
||||
if l > 3:
|
||||
lst = []
|
||||
for p in plist:
|
||||
p.forward(l)
|
||||
q = p.clone()
|
||||
p.left(a)
|
||||
q.right(a)
|
||||
lst.append(p)
|
||||
lst.append(q)
|
||||
for x in tree(lst, l*f, a, f):
|
||||
yield None
|
||||
|
||||
def maketree():
|
||||
p = Turtle()
|
||||
p.setundobuffer(None)
|
||||
p.hideturtle()
|
||||
p.speed(0)
|
||||
p.tracer(30,0)
|
||||
p.left(90)
|
||||
p.penup()
|
||||
p.forward(-210)
|
||||
p.pendown()
|
||||
t = tree([p], 200, 65, 0.6375)
|
||||
for x in t:
|
||||
pass
|
||||
print len(p.getscreen().turtles())
|
||||
|
||||
def main():
|
||||
a=clock()
|
||||
maketree()
|
||||
b=clock()
|
||||
return "done: %.2f sec." % (b-a)
|
||||
|
||||
if __name__ == "__main__":
|
||||
msg = main()
|
||||
print msg
|
||||
mainloop()
|
@ -1,49 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
""" turtle-example-suite:
|
||||
|
||||
tdemo_yinyang.py
|
||||
|
||||
Another drawing suitable as a beginner's
|
||||
programming example.
|
||||
|
||||
The small circles are drawn by the circle
|
||||
command.
|
||||
|
||||
"""
|
||||
|
||||
from turtle import *
|
||||
|
||||
def yin(radius, color1, color2):
|
||||
width(3)
|
||||
color("black")
|
||||
fill(True)
|
||||
circle(radius/2., 180)
|
||||
circle(radius, 180)
|
||||
left(180)
|
||||
circle(-radius/2., 180)
|
||||
color(color1)
|
||||
fill(True)
|
||||
color(color2)
|
||||
left(90)
|
||||
up()
|
||||
forward(radius*0.375)
|
||||
right(90)
|
||||
down()
|
||||
circle(radius*0.125)
|
||||
left(90)
|
||||
fill(False)
|
||||
up()
|
||||
backward(radius*0.375)
|
||||
down()
|
||||
left(90)
|
||||
|
||||
def main():
|
||||
reset()
|
||||
yin(200, "white", "black")
|
||||
yin(200, "black", "white")
|
||||
ht()
|
||||
return "Done!"
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
mainloop()
|
@ -1,280 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
import sys
|
||||
import os
|
||||
|
||||
from Tkinter import *
|
||||
from idlelib.Percolator import Percolator
|
||||
from idlelib.ColorDelegator import ColorDelegator
|
||||
from idlelib.textView import TextViewer
|
||||
|
||||
import turtle
|
||||
import time
|
||||
|
||||
STARTUP = 1
|
||||
READY = 2
|
||||
RUNNING = 3
|
||||
DONE = 4
|
||||
EVENTDRIVEN = 5
|
||||
|
||||
menufont = ("Arial", 12, NORMAL)
|
||||
btnfont = ("Arial", 12, 'bold')
|
||||
txtfont = ('Lucida Console', 8, 'normal')
|
||||
|
||||
def getExampleEntries():
|
||||
cwd = os.getcwd()
|
||||
if "turtleDemo.py" not in os.listdir(cwd):
|
||||
print "Directory of turtleDemo must be current working directory!"
|
||||
print "But in your case this is", cwd
|
||||
sys.exit()
|
||||
entries1 = [entry for entry in os.listdir(cwd) if
|
||||
entry.startswith("tdemo_") and
|
||||
not entry.endswith(".pyc")]
|
||||
entries2 = []
|
||||
for entry in entries1:
|
||||
if entry.endswith(".py"):
|
||||
entries2.append(entry)
|
||||
else:
|
||||
path = os.path.join(cwd,entry)
|
||||
sys.path.append(path)
|
||||
subdir = [entry]
|
||||
scripts = [script for script in os.listdir(path) if
|
||||
script.startswith("tdemo_") and
|
||||
script.endswith(".py")]
|
||||
entries2.append(subdir+scripts)
|
||||
return entries2
|
||||
|
||||
def showDemoHelp():
|
||||
TextViewer(demo.root, "Help on turtleDemo", "demohelp.txt")
|
||||
|
||||
def showAboutDemo():
|
||||
TextViewer(demo.root, "About turtleDemo", "about_turtledemo.txt")
|
||||
|
||||
def showAboutTurtle():
|
||||
TextViewer(demo.root, "About the new turtle module", "about_turtle.txt")
|
||||
|
||||
class DemoWindow(object):
|
||||
|
||||
def __init__(self, filename=None): #, root=None):
|
||||
self.root = root = turtle._root = Tk()
|
||||
root.wm_protocol("WM_DELETE_WINDOW", self._destroy)
|
||||
|
||||
#################
|
||||
self.mBar = Frame(root, relief=RAISED, borderwidth=2)
|
||||
self.mBar.pack(fill=X)
|
||||
|
||||
self.ExamplesBtn = self.makeLoadDemoMenu()
|
||||
self.OptionsBtn = self.makeHelpMenu()
|
||||
self.mBar.tk_menuBar(self.ExamplesBtn, self.OptionsBtn) #, QuitBtn)
|
||||
|
||||
root.title('Python turtle-graphics examples')
|
||||
#################
|
||||
self.left_frame = left_frame = Frame(root)
|
||||
self.text_frame = text_frame = Frame(left_frame)
|
||||
self.vbar = vbar =Scrollbar(text_frame, name='vbar')
|
||||
self.text = text = Text(text_frame,
|
||||
name='text', padx=5, wrap='none',
|
||||
width=45)
|
||||
vbar['command'] = text.yview
|
||||
vbar.pack(side=LEFT, fill=Y)
|
||||
#####################
|
||||
self.hbar = hbar =Scrollbar(text_frame, name='hbar', orient=HORIZONTAL)
|
||||
hbar['command'] = text.xview
|
||||
hbar.pack(side=BOTTOM, fill=X)
|
||||
#####################
|
||||
text['yscrollcommand'] = vbar.set
|
||||
text.config(font=txtfont)
|
||||
text.config(xscrollcommand=hbar.set)
|
||||
text.pack(side=LEFT, fill=Y, expand=1)
|
||||
#####################
|
||||
self.output_lbl = Label(left_frame, height= 1,text=" --- ", bg = "#ddf",
|
||||
font = ("Arial", 16, 'normal'))
|
||||
self.output_lbl.pack(side=BOTTOM, expand=0, fill=X)
|
||||
#####################
|
||||
text_frame.pack(side=LEFT, fill=BOTH, expand=0)
|
||||
left_frame.pack(side=LEFT, fill=BOTH, expand=0)
|
||||
self.graph_frame = g_frame = Frame(root)
|
||||
|
||||
turtle._Screen._root = g_frame
|
||||
turtle._Screen._canvas = turtle.ScrolledCanvas(g_frame, 800, 600, 1000, 800)
|
||||
#xturtle.Screen._canvas.pack(expand=1, fill="both")
|
||||
self.screen = _s_ = turtle.Screen()
|
||||
turtle.TurtleScreen.__init__(_s_, _s_._canvas)
|
||||
self.scanvas = _s_._canvas
|
||||
#xturtle.RawTurtle.canvases = [self.scanvas]
|
||||
turtle.RawTurtle.screens = [_s_]
|
||||
|
||||
self.scanvas.pack(side=TOP, fill=BOTH, expand=1)
|
||||
|
||||
self.btn_frame = btn_frame = Frame(g_frame, height=100)
|
||||
self.start_btn = Button(btn_frame, text=" START ", font=btnfont, fg = "white",
|
||||
disabledforeground = "#fed", command=self.startDemo)
|
||||
self.start_btn.pack(side=LEFT, fill=X, expand=1)
|
||||
self.stop_btn = Button(btn_frame, text=" STOP ", font=btnfont, fg = "white",
|
||||
disabledforeground = "#fed", command = self.stopIt)
|
||||
self.stop_btn.pack(side=LEFT, fill=X, expand=1)
|
||||
self.clear_btn = Button(btn_frame, text=" CLEAR ", font=btnfont, fg = "white",
|
||||
disabledforeground = "#fed", command = self.clearCanvas)
|
||||
self.clear_btn.pack(side=LEFT, fill=X, expand=1)
|
||||
|
||||
self.btn_frame.pack(side=TOP, fill=BOTH, expand=0)
|
||||
self.graph_frame.pack(side=TOP, fill=BOTH, expand=1)
|
||||
|
||||
Percolator(text).insertfilter(ColorDelegator())
|
||||
self.dirty = False
|
||||
self.exitflag = False
|
||||
if filename:
|
||||
self.loadfile(filename)
|
||||
self.configGUI(NORMAL, DISABLED, DISABLED, DISABLED,
|
||||
"Choose example from menu", "black")
|
||||
self.state = STARTUP
|
||||
|
||||
def _destroy(self):
|
||||
self.root.destroy()
|
||||
sys.exit()
|
||||
|
||||
def configGUI(self, menu, start, stop, clear, txt="", color="blue"):
|
||||
self.ExamplesBtn.config(state=menu)
|
||||
|
||||
self.start_btn.config(state=start)
|
||||
if start==NORMAL:
|
||||
self.start_btn.config(bg="#d00")
|
||||
else:
|
||||
self.start_btn.config(bg="#fca")
|
||||
|
||||
self.stop_btn.config(state=stop)
|
||||
if stop==NORMAL:
|
||||
self.stop_btn.config(bg="#d00")
|
||||
else:
|
||||
self.stop_btn.config(bg="#fca")
|
||||
self.clear_btn.config(state=clear)
|
||||
|
||||
self.clear_btn.config(state=clear)
|
||||
if clear==NORMAL:
|
||||
self.clear_btn.config(bg="#d00")
|
||||
else:
|
||||
self.clear_btn.config(bg="#fca")
|
||||
|
||||
self.output_lbl.config(text=txt, fg=color)
|
||||
|
||||
|
||||
def makeLoadDemoMenu(self):
|
||||
CmdBtn = Menubutton(self.mBar, text='Examples', underline=0, font=menufont)
|
||||
CmdBtn.pack(side=LEFT, padx="2m")
|
||||
CmdBtn.menu = Menu(CmdBtn)
|
||||
|
||||
for entry in getExampleEntries():
|
||||
def loadexample(x):
|
||||
def emit():
|
||||
self.loadfile(x)
|
||||
return emit
|
||||
if isinstance(entry,str):
|
||||
CmdBtn.menu.add_command(label=entry[6:-3], underline=0, font=menufont,
|
||||
command=loadexample(entry))
|
||||
else:
|
||||
_dir, entries = entry[0], entry[1:]
|
||||
CmdBtn.menu.choices = Menu(CmdBtn.menu)
|
||||
for e in entries:
|
||||
CmdBtn.menu.choices.add_command(label=e[6:-3], underline=0, font=menufont,
|
||||
command = loadexample(os.path.join(_dir,e)))
|
||||
|
||||
CmdBtn.menu.add_cascade(label=_dir[6:],
|
||||
menu = CmdBtn.menu.choices, font=menufont )
|
||||
|
||||
CmdBtn['menu'] = CmdBtn.menu
|
||||
return CmdBtn
|
||||
|
||||
|
||||
def makeHelpMenu(self):
|
||||
CmdBtn = Menubutton(self.mBar, text='Help', underline=0, font = menufont)
|
||||
CmdBtn.pack(side=LEFT, padx='2m')
|
||||
CmdBtn.menu = Menu(CmdBtn)
|
||||
|
||||
CmdBtn.menu.add_command(label='About turtle.py', font=menufont, command=showAboutTurtle)
|
||||
CmdBtn.menu.add_command(label='turtleDemo - Help', font=menufont, command=showDemoHelp)
|
||||
CmdBtn.menu.add_command(label='About turtleDemo', font=menufont, command=showAboutDemo)
|
||||
|
||||
CmdBtn['menu'] = CmdBtn.menu
|
||||
return CmdBtn
|
||||
|
||||
def refreshCanvas(self):
|
||||
if not self.dirty: return
|
||||
self.screen.clear()
|
||||
#self.screen.mode("standard")
|
||||
self.dirty=False
|
||||
|
||||
def loadfile(self,filename):
|
||||
self.refreshCanvas()
|
||||
if os.path.exists(filename) and not os.path.isdir(filename):
|
||||
# load and display file text
|
||||
f = open(filename,'r')
|
||||
chars = f.read()
|
||||
f.close()
|
||||
self.text.delete("1.0", "end")
|
||||
self.text.insert("1.0",chars)
|
||||
direc, fname = os.path.split(filename)
|
||||
self.root.title(fname[6:-3]+" - an xturtle example")
|
||||
self.module = __import__(fname[:-3])
|
||||
reload(self.module)
|
||||
self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED,
|
||||
"Press start button", "red")
|
||||
self.state = READY
|
||||
|
||||
def startDemo(self):
|
||||
self.refreshCanvas()
|
||||
self.dirty = True
|
||||
turtle.TurtleScreen._RUNNING = True
|
||||
self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED,
|
||||
"demo running...", "black")
|
||||
self.screen.clear()
|
||||
self.screen.mode("standard")
|
||||
self.state = RUNNING
|
||||
|
||||
try:
|
||||
result = self.module.main()
|
||||
if result == "EVENTLOOP":
|
||||
self.state = EVENTDRIVEN
|
||||
else:
|
||||
self.state = DONE
|
||||
except turtle.Terminator:
|
||||
self.state = DONE
|
||||
result = "stopped!"
|
||||
if self.state == DONE:
|
||||
self.configGUI(NORMAL, NORMAL, DISABLED, NORMAL,
|
||||
result)
|
||||
elif self.state == EVENTDRIVEN:
|
||||
self.exitflag = True
|
||||
self.configGUI(DISABLED, DISABLED, NORMAL, DISABLED,
|
||||
"use mouse/keys or STOP", "red")
|
||||
|
||||
def clearCanvas(self):
|
||||
self.refreshCanvas()
|
||||
self.scanvas.config(cursor="")
|
||||
self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED)
|
||||
|
||||
def stopIt(self):
|
||||
if self.exitflag:
|
||||
self.clearCanvas()
|
||||
self.exitflag = False
|
||||
self.configGUI(NORMAL, NORMAL, DISABLED, DISABLED,
|
||||
"STOPPED!", "red")
|
||||
turtle.TurtleScreen._RUNNING = False
|
||||
#print "stopIT: exitflag = True"
|
||||
else:
|
||||
turtle.TurtleScreen._RUNNING = False
|
||||
#print "stopIt: exitflag = False"
|
||||
|
||||
if __name__ == '__main__':
|
||||
demo = DemoWindow()
|
||||
RUN = True
|
||||
while RUN:
|
||||
try:
|
||||
print "ENTERING mainloop"
|
||||
demo.root.mainloop()
|
||||
except AttributeError:
|
||||
print "CRASH!!!- WAIT A MOMENT!"
|
||||
time.sleep(0.3)
|
||||
print "GOING ON .."
|
||||
demo.refreshCanvas()
|
||||
## time.sleep(1)
|
||||
except:
|
||||
RUN = FALSE
|
@ -1,49 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
## DEMONSTRATES USE OF 2 CANVASES, SO CANNOT BE RUN IN DEMOVIEWER!
|
||||
"""turtle example: Using TurtleScreen and RawTurtle
|
||||
for drawing on two distinct canvases.
|
||||
"""
|
||||
from turtle import TurtleScreen, RawTurtle, TK
|
||||
|
||||
root = TK.Tk()
|
||||
cv1 = TK.Canvas(root, width=300, height=200, bg="#ddffff")
|
||||
cv2 = TK.Canvas(root, width=300, height=200, bg="#ffeeee")
|
||||
cv1.pack()
|
||||
cv2.pack()
|
||||
|
||||
s1 = TurtleScreen(cv1)
|
||||
s1.bgcolor(0.85, 0.85, 1)
|
||||
s2 = TurtleScreen(cv2)
|
||||
s2.bgcolor(1, 0.85, 0.85)
|
||||
|
||||
p = RawTurtle(s1)
|
||||
q = RawTurtle(s2)
|
||||
|
||||
p.color("red", "white")
|
||||
p.width(3)
|
||||
q.color("blue", "black")
|
||||
q.width(3)
|
||||
|
||||
for t in p,q:
|
||||
t.shape("turtle")
|
||||
t.lt(36)
|
||||
|
||||
q.lt(180)
|
||||
|
||||
for i in range(5):
|
||||
for t in p, q:
|
||||
t.fd(50)
|
||||
t.lt(72)
|
||||
for t in p,q:
|
||||
t.lt(54)
|
||||
t.pu()
|
||||
t.bk(50)
|
||||
|
||||
## Want to get some info?
|
||||
|
||||
print s1, s2
|
||||
print p, q
|
||||
print s1.turtles()
|
||||
print s2.turtles()
|
||||
|
||||
TK.mainloop()
|
@ -1,36 +0,0 @@
|
||||
import sys
|
||||
|
||||
from xml.sax import make_parser, handler
|
||||
|
||||
class FancyCounter(handler.ContentHandler):
|
||||
|
||||
def __init__(self):
|
||||
self._elems = 0
|
||||
self._attrs = 0
|
||||
self._elem_types = {}
|
||||
self._attr_types = {}
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
self._elems = self._elems + 1
|
||||
self._attrs = self._attrs + len(attrs)
|
||||
self._elem_types[name] = self._elem_types.get(name, 0) + 1
|
||||
|
||||
for name in attrs.keys():
|
||||
self._attr_types[name] = self._attr_types.get(name, 0) + 1
|
||||
|
||||
def endDocument(self):
|
||||
print "There were", self._elems, "elements."
|
||||
print "There were", self._attrs, "attributes."
|
||||
|
||||
print "---ELEMENT TYPES"
|
||||
for pair in self._elem_types.items():
|
||||
print "%20s %d" % pair
|
||||
|
||||
print "---ATTRIBUTE TYPES"
|
||||
for pair in self._attr_types.items():
|
||||
print "%20s %d" % pair
|
||||
|
||||
|
||||
parser = make_parser()
|
||||
parser.setContentHandler(FancyCounter())
|
||||
parser.parse(sys.argv[1])
|
@ -1,45 +0,0 @@
|
||||
"""
|
||||
A simple demo that reads in an XML document and spits out an equivalent,
|
||||
but not necessarily identical, document.
|
||||
"""
|
||||
|
||||
import sys, string
|
||||
|
||||
from xml.sax import saxutils, handler, make_parser
|
||||
|
||||
# --- The ContentHandler
|
||||
|
||||
class ContentGenerator(handler.ContentHandler):
|
||||
|
||||
def __init__(self, out = sys.stdout):
|
||||
handler.ContentHandler.__init__(self)
|
||||
self._out = out
|
||||
|
||||
# ContentHandler methods
|
||||
|
||||
def startDocument(self):
|
||||
self._out.write('<?xml version="1.0" encoding="iso-8859-1"?>\n')
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
self._out.write('<' + name)
|
||||
for (name, value) in attrs.items():
|
||||
self._out.write(' %s="%s"' % (name, saxutils.escape(value)))
|
||||
self._out.write('>')
|
||||
|
||||
def endElement(self, name):
|
||||
self._out.write('</%s>' % name)
|
||||
|
||||
def characters(self, content):
|
||||
self._out.write(saxutils.escape(content))
|
||||
|
||||
def ignorableWhitespace(self, content):
|
||||
self._out.write(content)
|
||||
|
||||
def processingInstruction(self, target, data):
|
||||
self._out.write('<?%s %s?>' % (target, data))
|
||||
|
||||
# --- The main program
|
||||
|
||||
parser = make_parser()
|
||||
parser.setContentHandler(ContentGenerator())
|
||||
parser.parse(sys.argv[1])
|
@ -1,91 +0,0 @@
|
||||
import sys
|
||||
|
||||
from xml.sax import make_parser, handler
|
||||
|
||||
# --- Templates
|
||||
|
||||
top = \
|
||||
"""
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>%s</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY>
|
||||
<H1>%s</H1>
|
||||
"""
|
||||
|
||||
bottom = \
|
||||
"""
|
||||
</ul>
|
||||
|
||||
<HR>
|
||||
<ADDRESS>
|
||||
Converted to HTML by sax_rss2html.py.
|
||||
</ADDRESS>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
||||
"""
|
||||
|
||||
# --- The ContentHandler
|
||||
|
||||
class RSSHandler(handler.ContentHandler):
|
||||
|
||||
def __init__(self, out = sys.stdout):
|
||||
handler.ContentHandler.__init__(self)
|
||||
self._out = out
|
||||
|
||||
self._text = ""
|
||||
self._parent = None
|
||||
self._list_started = 0
|
||||
self._title = None
|
||||
self._link = None
|
||||
self._descr = ""
|
||||
|
||||
# ContentHandler methods
|
||||
|
||||
def startElement(self, name, attrs):
|
||||
if name == "channel" or name == "image" or name == "item":
|
||||
self._parent = name
|
||||
|
||||
self._text = ""
|
||||
|
||||
def endElement(self, name):
|
||||
if self._parent == "channel":
|
||||
if name == "title":
|
||||
self._out.write(top % (self._text, self._text))
|
||||
elif name == "description":
|
||||
self._out.write("<p>%s</p>\n" % self._text)
|
||||
|
||||
elif self._parent == "item":
|
||||
if name == "title":
|
||||
self._title = self._text
|
||||
elif name == "link":
|
||||
self._link = self._text
|
||||
elif name == "description":
|
||||
self._descr = self._text
|
||||
elif name == "item":
|
||||
if not self._list_started:
|
||||
self._out.write("<ul>\n")
|
||||
self._list_started = 1
|
||||
|
||||
self._out.write(' <li><a href="%s">%s</a> %s\n' %
|
||||
(self._link, self._title, self._descr))
|
||||
|
||||
self._title = None
|
||||
self._link = None
|
||||
self._descr = ""
|
||||
|
||||
if name == "rss":
|
||||
self._out.write(bottom)
|
||||
|
||||
def characters(self, content):
|
||||
self._text = self._text + content
|
||||
|
||||
# --- Main program
|
||||
|
||||
parser = make_parser()
|
||||
parser.setContentHandler(RSSHandler())
|
||||
parser.parse(sys.argv[1])
|
@ -1,217 +0,0 @@
|
||||
Contributors to the Python Documentation
|
||||
----------------------------------------
|
||||
|
||||
This section lists people who have contributed in some way to the Python
|
||||
documentation. It is probably not complete -- if you feel that you or
|
||||
anyone else should be on this list, please let us know (send email to
|
||||
docs@python.org), and we'll be glad to correct the problem.
|
||||
|
||||
.. acks::
|
||||
|
||||
* Aahz
|
||||
* Michael Abbott
|
||||
* Steve Alexander
|
||||
* Jim Ahlstrom
|
||||
* Fred Allen
|
||||
* A. Amoroso
|
||||
* Pehr Anderson
|
||||
* Oliver Andrich
|
||||
* Heidi Annexstad
|
||||
* Jesús Cea Avión
|
||||
* Daniel Barclay
|
||||
* Chris Barker
|
||||
* Don Bashford
|
||||
* Anthony Baxter
|
||||
* Alexander Belopolsky
|
||||
* Bennett Benson
|
||||
* Jonathan Black
|
||||
* Robin Boerdijk
|
||||
* Michal Bozon
|
||||
* Aaron Brancotti
|
||||
* Georg Brandl
|
||||
* Keith Briggs
|
||||
* Ian Bruntlett
|
||||
* Lee Busby
|
||||
* Lorenzo M. Catucci
|
||||
* Carl Cerecke
|
||||
* Mauro Cicognini
|
||||
* Gilles Civario
|
||||
* Mike Clarkson
|
||||
* Steve Clift
|
||||
* Dave Cole
|
||||
* Matthew Cowles
|
||||
* Jeremy Craven
|
||||
* Andrew Dalke
|
||||
* Ben Darnell
|
||||
* L. Peter Deutsch
|
||||
* Robert Donohue
|
||||
* Fred L. Drake, Jr.
|
||||
* Josip Dzolonga
|
||||
* Jeff Epler
|
||||
* Michael Ernst
|
||||
* Blame Andy Eskilsson
|
||||
* Carey Evans
|
||||
* Martijn Faassen
|
||||
* Carl Feynman
|
||||
* Dan Finnie
|
||||
* Hernán Martínez Foffani
|
||||
* Stefan Franke
|
||||
* Jim Fulton
|
||||
* Peter Funk
|
||||
* Lele Gaifax
|
||||
* Matthew Gallagher
|
||||
* Gabriel Genellina
|
||||
* Ben Gertzfield
|
||||
* Nadim Ghaznavi
|
||||
* Jonathan Giddy
|
||||
* Shelley Gooch
|
||||
* Nathaniel Gray
|
||||
* Grant Griffin
|
||||
* Thomas Guettler
|
||||
* Anders Hammarquist
|
||||
* Mark Hammond
|
||||
* Harald Hanche-Olsen
|
||||
* Manus Hand
|
||||
* Gerhard Häring
|
||||
* Travis B. Hartwell
|
||||
* Tim Hatch
|
||||
* Janko Hauser
|
||||
* Thomas Heller
|
||||
* Bernhard Herzog
|
||||
* Magnus L. Hetland
|
||||
* Konrad Hinsen
|
||||
* Stefan Hoffmeister
|
||||
* Albert Hofkamp
|
||||
* Gregor Hoffleit
|
||||
* Steve Holden
|
||||
* Thomas Holenstein
|
||||
* Gerrit Holl
|
||||
* Rob Hooft
|
||||
* Brian Hooper
|
||||
* Randall Hopper
|
||||
* Michael Hudson
|
||||
* Eric Huss
|
||||
* Jeremy Hylton
|
||||
* Roger Irwin
|
||||
* Jack Jansen
|
||||
* Philip H. Jensen
|
||||
* Pedro Diaz Jimenez
|
||||
* Kent Johnson
|
||||
* Lucas de Jonge
|
||||
* Andreas Jung
|
||||
* Robert Kern
|
||||
* Jim Kerr
|
||||
* Jan Kim
|
||||
* Greg Kochanski
|
||||
* Guido Kollerie
|
||||
* Peter A. Koren
|
||||
* Daniel Kozan
|
||||
* Andrew M. Kuchling
|
||||
* Dave Kuhlman
|
||||
* Erno Kuusela
|
||||
* Thomas Lamb
|
||||
* Detlef Lannert
|
||||
* Piers Lauder
|
||||
* Glyph Lefkowitz
|
||||
* Robert Lehmann
|
||||
* Marc-André Lemburg
|
||||
* Ross Light
|
||||
* Ulf A. Lindgren
|
||||
* Everett Lipman
|
||||
* Mirko Liss
|
||||
* Martin von Löwis
|
||||
* Fredrik Lundh
|
||||
* Jeff MacDonald
|
||||
* John Machin
|
||||
* Andrew MacIntyre
|
||||
* Vladimir Marangozov
|
||||
* Vincent Marchetti
|
||||
* Laura Matson
|
||||
* Daniel May
|
||||
* Rebecca McCreary
|
||||
* Doug Mennella
|
||||
* Paolo Milani
|
||||
* Skip Montanaro
|
||||
* Paul Moore
|
||||
* Ross Moore
|
||||
* Sjoerd Mullender
|
||||
* Dale Nagata
|
||||
* Ng Pheng Siong
|
||||
* Koray Oner
|
||||
* Tomas Oppelstrup
|
||||
* Denis S. Otkidach
|
||||
* Zooko O'Whielacronx
|
||||
* Shriphani Palakodety
|
||||
* William Park
|
||||
* Joonas Paalasmaa
|
||||
* Harri Pasanen
|
||||
* Bo Peng
|
||||
* Tim Peters
|
||||
* Benjamin Peterson
|
||||
* Christopher Petrilli
|
||||
* Justin D. Pettit
|
||||
* Chris Phoenix
|
||||
* François Pinard
|
||||
* Paul Prescod
|
||||
* Eric S. Raymond
|
||||
* Edward K. Ream
|
||||
* Sean Reifschneider
|
||||
* Bernhard Reiter
|
||||
* Armin Rigo
|
||||
* Wes Rishel
|
||||
* Armin Ronacher
|
||||
* Jim Roskind
|
||||
* Guido van Rossum
|
||||
* Donald Wallace Rouse II
|
||||
* Mark Russell
|
||||
* Nick Russo
|
||||
* Chris Ryland
|
||||
* Constantina S.
|
||||
* Hugh Sasse
|
||||
* Bob Savage
|
||||
* Scott Schram
|
||||
* Neil Schemenauer
|
||||
* Barry Scott
|
||||
* Joakim Sernbrant
|
||||
* Justin Sheehy
|
||||
* Charlie Shepherd
|
||||
* Michael Simcich
|
||||
* Ionel Simionescu
|
||||
* Michael Sloan
|
||||
* Gregory P. Smith
|
||||
* Roy Smith
|
||||
* Clay Spence
|
||||
* Nicholas Spies
|
||||
* Tage Stabell-Kulo
|
||||
* Frank Stajano
|
||||
* Anthony Starks
|
||||
* Greg Stein
|
||||
* Peter Stoehr
|
||||
* Mark Summerfield
|
||||
* Reuben Sumner
|
||||
* Kalle Svensson
|
||||
* Jim Tittsler
|
||||
* David Turner
|
||||
* Ville Vainio
|
||||
* Martijn Vries
|
||||
* Charles G. Waldman
|
||||
* Greg Ward
|
||||
* Barry Warsaw
|
||||
* Corran Webster
|
||||
* Glyn Webster
|
||||
* Bob Weiner
|
||||
* Eddy Welbourne
|
||||
* Jeff Wheeler
|
||||
* Mats Wichmann
|
||||
* Gerry Wiener
|
||||
* Timothy Wild
|
||||
* Collin Winter
|
||||
* Blake Winton
|
||||
* Dan Wolfe
|
||||
* Steven Work
|
||||
* Thomas Wouters
|
||||
* Ka-Ping Yee
|
||||
* Rory Yorke
|
||||
* Moshe Zadka
|
||||
* Milan Zamazal
|
||||
* Cheng Zhang
|
@ -1,175 +0,0 @@
|
||||
#
|
||||
# Makefile for Python documentation
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#
|
||||
|
||||
# You can set these variables from the command line.
|
||||
PYTHON = python
|
||||
SVNROOT = http://svn.python.org/projects
|
||||
SPHINXOPTS =
|
||||
PAPER =
|
||||
SOURCES =
|
||||
DISTVERSION = $(shell $(PYTHON) tools/sphinxext/patchlevel.py)
|
||||
|
||||
ALLSPHINXOPTS = -b $(BUILDER) -d build/doctrees -D latex_paper_size=$(PAPER) \
|
||||
$(SPHINXOPTS) . build/$(BUILDER) $(SOURCES)
|
||||
|
||||
.PHONY: help checkout update build html htmlhelp latex text changes linkcheck \
|
||||
suspicious coverage doctest pydoc-topics htmlview clean dist check serve \
|
||||
autobuild-dev autobuild-stable
|
||||
|
||||
help:
|
||||
@echo "Please use \`make <target>' where <target> is one of"
|
||||
@echo " clean to remove build files"
|
||||
@echo " update to update build tools"
|
||||
@echo " html to make standalone HTML files"
|
||||
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
@echo " text to make plain text files"
|
||||
@echo " changes to make an overview over all changed/added/deprecated items"
|
||||
@echo " linkcheck to check all external links for integrity"
|
||||
@echo " coverage to check documentation coverage for library and C API"
|
||||
@echo " doctest to run doctests in the documentation"
|
||||
@echo " pydoc-topics to regenerate the pydoc topics file"
|
||||
@echo " dist to create a \"dist\" directory with archived docs for download"
|
||||
@echo " suspicious to check for suspicious markup in output text"
|
||||
@echo " check to run a check for frequent markup errors"
|
||||
|
||||
# Note: if you update versions here, do the same in make.bat and README.txt
|
||||
checkout:
|
||||
@if [ ! -d tools/sphinx ]; then \
|
||||
echo "Checking out Sphinx..."; \
|
||||
svn checkout $(SVNROOT)/external/Sphinx-0.6.5/sphinx tools/sphinx; \
|
||||
fi
|
||||
@if [ ! -d tools/docutils ]; then \
|
||||
echo "Checking out Docutils..."; \
|
||||
svn checkout $(SVNROOT)/external/docutils-0.6/docutils tools/docutils; \
|
||||
fi
|
||||
@if [ ! -d tools/jinja2 ]; then \
|
||||
echo "Checking out Jinja..."; \
|
||||
svn checkout $(SVNROOT)/external/Jinja-2.3.1/jinja2 tools/jinja2; \
|
||||
fi
|
||||
@if [ ! -d tools/pygments ]; then \
|
||||
echo "Checking out Pygments..."; \
|
||||
svn checkout $(SVNROOT)/external/Pygments-1.3.1/pygments tools/pygments; \
|
||||
fi
|
||||
|
||||
update: clean checkout
|
||||
|
||||
build: checkout
|
||||
mkdir -p build/$(BUILDER) build/doctrees
|
||||
$(PYTHON) tools/sphinx-build.py $(ALLSPHINXOPTS)
|
||||
@echo
|
||||
|
||||
html: BUILDER = html
|
||||
html: build
|
||||
@echo "Build finished. The HTML pages are in build/html."
|
||||
|
||||
htmlhelp: BUILDER = htmlhelp
|
||||
htmlhelp: build
|
||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||
"build/htmlhelp/pydoc.hhp project file."
|
||||
|
||||
latex: BUILDER = latex
|
||||
latex: build
|
||||
@echo "Build finished; the LaTeX files are in build/latex."
|
||||
@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
|
||||
"run these through (pdf)latex."
|
||||
|
||||
text: BUILDER = text
|
||||
text: build
|
||||
@echo "Build finished; the text files are in build/text."
|
||||
|
||||
changes: BUILDER = changes
|
||||
changes: build
|
||||
@echo "The overview file is in build/changes."
|
||||
|
||||
linkcheck: BUILDER = linkcheck
|
||||
linkcheck: build
|
||||
@echo "Link check complete; look for any errors in the above output " \
|
||||
"or in build/$(BUILDER)/output.txt"
|
||||
|
||||
suspicious: BUILDER = suspicious
|
||||
suspicious: build
|
||||
@echo "Suspicious check complete; look for any errors in the above output " \
|
||||
"or in build/$(BUILDER)/suspicious.txt"
|
||||
|
||||
coverage: BUILDER = coverage
|
||||
coverage: build
|
||||
@echo "Coverage finished; see c.txt and python.txt in build/coverage"
|
||||
|
||||
doctest: BUILDER = doctest
|
||||
doctest: build
|
||||
@echo "Testing of doctests in the sources finished, look at the " \
|
||||
"results in build/doctest/output.txt"
|
||||
|
||||
pydoc-topics: BUILDER = pydoc-topics
|
||||
pydoc-topics: build
|
||||
@echo "Building finished; now copy build/pydoc-topics/pydoc_topics.py " \
|
||||
"into the Lib/ directory"
|
||||
|
||||
htmlview: html
|
||||
$(PYTHON) -c "import webbrowser; webbrowser.open('build/html/index.html')"
|
||||
|
||||
clean:
|
||||
-rm -rf build/*
|
||||
-rm -rf tools/sphinx
|
||||
-rm -rf tools/pygments
|
||||
-rm -rf tools/jinja2
|
||||
-rm -rf tools/docutils
|
||||
|
||||
dist:
|
||||
-rm -rf dist
|
||||
mkdir -p dist
|
||||
|
||||
# archive the HTML
|
||||
make html
|
||||
cp -pPR build/html dist/python-$(DISTVERSION)-docs-html
|
||||
tar -C dist -cf dist/python-$(DISTVERSION)-docs-html.tar python-$(DISTVERSION)-docs-html
|
||||
bzip2 -9 -k dist/python-$(DISTVERSION)-docs-html.tar
|
||||
(cd dist; zip -q -r -9 python-$(DISTVERSION)-docs-html.zip python-$(DISTVERSION)-docs-html)
|
||||
rm -r dist/python-$(DISTVERSION)-docs-html
|
||||
rm dist/python-$(DISTVERSION)-docs-html.tar
|
||||
|
||||
# archive the text build
|
||||
make text
|
||||
cp -pPR build/text dist/python-$(DISTVERSION)-docs-text
|
||||
tar -C dist -cf dist/python-$(DISTVERSION)-docs-text.tar python-$(DISTVERSION)-docs-text
|
||||
bzip2 -9 -k dist/python-$(DISTVERSION)-docs-text.tar
|
||||
(cd dist; zip -q -r -9 python-$(DISTVERSION)-docs-text.zip python-$(DISTVERSION)-docs-text)
|
||||
rm -r dist/python-$(DISTVERSION)-docs-text
|
||||
rm dist/python-$(DISTVERSION)-docs-text.tar
|
||||
|
||||
# archive the A4 latex
|
||||
-rm -r build/latex
|
||||
make latex PAPER=a4
|
||||
-sed -i 's/makeindex/makeindex -q/' build/latex/Makefile
|
||||
(cd build/latex; make clean && make all-pdf && make FMT=pdf zip bz2)
|
||||
cp build/latex/docs-pdf.zip dist/python-$(DISTVERSION)-docs-pdf-a4.zip
|
||||
cp build/latex/docs-pdf.tar.bz2 dist/python-$(DISTVERSION)-docs-pdf-a4.tar.bz2
|
||||
|
||||
# archive the letter latex
|
||||
rm -r build/latex
|
||||
make latex PAPER=letter
|
||||
-sed -i 's/makeindex/makeindex -q/' build/latex/Makefile
|
||||
(cd build/latex; make clean && make all-pdf && make FMT=pdf zip bz2)
|
||||
cp build/latex/docs-pdf.zip dist/python-$(DISTVERSION)-docs-pdf-letter.zip
|
||||
cp build/latex/docs-pdf.tar.bz2 dist/python-$(DISTVERSION)-docs-pdf-letter.tar.bz2
|
||||
|
||||
check:
|
||||
$(PYTHON) tools/rstlint.py -i tools
|
||||
|
||||
# Targets for daily automated doc build
|
||||
|
||||
# for development releases: always build
|
||||
autobuild-dev:
|
||||
make update
|
||||
make dist SPHINXOPTS='-A daily=1 -A versionswitcher=1'
|
||||
|
||||
# for stable releases: only build if not in pre-release stage (alpha, beta, rc)
|
||||
autobuild-stable:
|
||||
@case $(DISTVERSION) in *[abc]*) \
|
||||
echo "Not building; $(DISTVERSION) is not a release version."; \
|
||||
exit 1;; \
|
||||
esac
|
||||
@make autobuild-dev
|
@ -1,144 +0,0 @@
|
||||
Python Documentation README
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This directory contains the reStructuredText (reST) sources to the Python
|
||||
documentation. You don't need to build them yourself, prebuilt versions are
|
||||
available at http://docs.python.org/download/.
|
||||
|
||||
Documentation on the authoring Python documentation, including information about
|
||||
both style and markup, is available in the "Documenting Python" chapter of the
|
||||
documentation. There's also a chapter intended to point out differences to
|
||||
those familiar with the previous docs written in LaTeX.
|
||||
|
||||
|
||||
Building the docs
|
||||
=================
|
||||
|
||||
You need to have Python 2.4 or higher installed; the toolset used to build the
|
||||
docs is written in Python. It is called *Sphinx*, it is not included in this
|
||||
tree, but maintained separately. Also needed are the docutils, supplying the
|
||||
base markup that Sphinx uses, Jinja, a templating engine, and optionally
|
||||
Pygments, a code highlighter.
|
||||
|
||||
|
||||
Using make
|
||||
----------
|
||||
|
||||
Luckily, a Makefile has been prepared so that on Unix, provided you have
|
||||
installed Python and Subversion, you can just run ::
|
||||
|
||||
make html
|
||||
|
||||
to check out the necessary toolset in the `tools/` subdirectory and build the
|
||||
HTML output files. To view the generated HTML, point your favorite browser at
|
||||
the top-level index `build/html/index.html` after running "make".
|
||||
|
||||
Available make targets are:
|
||||
|
||||
* "html", which builds standalone HTML files for offline viewing.
|
||||
|
||||
* "htmlhelp", which builds HTML files and a HTML Help project file usable to
|
||||
convert them into a single Compiled HTML (.chm) file -- these are popular
|
||||
under Microsoft Windows, but very handy on every platform.
|
||||
|
||||
To create the CHM file, you need to run the Microsoft HTML Help Workshop over
|
||||
the generated project (.hhp) file.
|
||||
|
||||
* "latex", which builds LaTeX source files as input to "pdflatex" to produce
|
||||
PDF documents.
|
||||
|
||||
* "text", which builds a plain text file for each source file.
|
||||
|
||||
* "linkcheck", which checks all external references to see whether they are
|
||||
broken, redirected or malformed, and outputs this information to stdout as
|
||||
well as a plain-text (.txt) file.
|
||||
|
||||
* "changes", which builds an overview over all versionadded/versionchanged/
|
||||
deprecated items in the current version. This is meant as a help for the
|
||||
writer of the "What's New" document.
|
||||
|
||||
* "coverage", which builds a coverage overview for standard library modules and
|
||||
C API.
|
||||
|
||||
* "pydoc-topics", which builds a Python module containing a dictionary with
|
||||
plain text documentation for the labels defined in
|
||||
`tools/sphinxext/pyspecific.py` -- pydoc needs these to show topic and
|
||||
keyword help.
|
||||
|
||||
A "make update" updates the Subversion checkouts in `tools/`.
|
||||
|
||||
|
||||
Without make
|
||||
------------
|
||||
|
||||
You'll need to install the Sphinx package, either by checking it out via ::
|
||||
|
||||
svn co http://svn.python.org/projects/external/Sphinx-0.6.5/sphinx tools/sphinx
|
||||
|
||||
or by installing it from PyPI.
|
||||
|
||||
Then, you need to install Docutils, either by checking it out via ::
|
||||
|
||||
svn co http://svn.python.org/projects/external/docutils-0.6/docutils tools/docutils
|
||||
|
||||
or by installing it from http://docutils.sf.net/.
|
||||
|
||||
You also need Jinja2, either by checking it out via ::
|
||||
|
||||
svn co http://svn.python.org/projects/external/Jinja-2.3.1/jinja2 tools/jinja2
|
||||
|
||||
or by installing it from PyPI.
|
||||
|
||||
You can optionally also install Pygments, either as a checkout via ::
|
||||
|
||||
svn co http://svn.python.org/projects/external/Pygments-1.3.1/pygments tools/pygments
|
||||
|
||||
or from PyPI at http://pypi.python.org/pypi/Pygments.
|
||||
|
||||
|
||||
Then, make an output directory, e.g. under `build/`, and run ::
|
||||
|
||||
python tools/sphinx-build.py -b<builder> . build/<outputdirectory>
|
||||
|
||||
where `<builder>` is one of html, text, latex, or htmlhelp (for explanations see
|
||||
the make targets above).
|
||||
|
||||
|
||||
Contributing
|
||||
============
|
||||
|
||||
Bugs in the content should be reported to the Python bug tracker at
|
||||
http://bugs.python.org.
|
||||
|
||||
Bugs in the toolset should be reported in the Sphinx bug tracker at
|
||||
http://www.bitbucket.org/birkenfeld/sphinx/issues/.
|
||||
|
||||
You can also send a mail to the Python Documentation Team at docs@python.org,
|
||||
and we will process your request as soon as possible.
|
||||
|
||||
If you want to help the Documentation Team, you are always welcome. Just send
|
||||
a mail to docs@python.org.
|
||||
|
||||
|
||||
Copyright notice
|
||||
================
|
||||
|
||||
The Python source is copyrighted, but you can freely use and copy it
|
||||
as long as you don't change or remove the copyright notice:
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Copyright (c) 2000-2013 Python Software Foundation.
|
||||
All rights reserved.
|
||||
|
||||
Copyright (c) 2000 BeOpen.com.
|
||||
All rights reserved.
|
||||
|
||||
Copyright (c) 1995-2000 Corporation for National Research Initiatives.
|
||||
All rights reserved.
|
||||
|
||||
Copyright (c) 1991-1995 Stichting Mathematisch Centrum.
|
||||
All rights reserved.
|
||||
|
||||
See the file "license.rst" for information on usage and redistribution
|
||||
of this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
----------------------------------------------------------------------
|
@ -1,36 +0,0 @@
|
||||
=====================
|
||||
About these documents
|
||||
=====================
|
||||
|
||||
|
||||
These documents are generated from `reStructuredText`_ sources by `Sphinx`_, a
|
||||
document processor specifically written for the Python documentation.
|
||||
|
||||
.. _reStructuredText: http://docutils.sf.net/rst.html
|
||||
.. _Sphinx: http://sphinx.pocoo.org/
|
||||
|
||||
.. In the online version of these documents, you can submit comments and suggest
|
||||
changes directly on the documentation pages.
|
||||
|
||||
Development of the documentation and its toolchain takes place on the
|
||||
docs@python.org mailing list. We're always looking for volunteers wanting
|
||||
to help with the docs, so feel free to send a mail there!
|
||||
|
||||
Many thanks go to:
|
||||
|
||||
* Fred L. Drake, Jr., the creator of the original Python documentation toolset
|
||||
and writer of much of the content;
|
||||
* the `Docutils <http://docutils.sf.net/>`_ project for creating
|
||||
reStructuredText and the Docutils suite;
|
||||
* Fredrik Lundh for his `Alternative Python Reference
|
||||
<http://effbot.org/zone/pyref.htm>`_ project from which Sphinx got many good
|
||||
ideas.
|
||||
|
||||
See :ref:`reporting-bugs` for information how to report bugs in this
|
||||
documentation, or Python itself.
|
||||
|
||||
.. including the ACKS file here so that it can be maintained separately
|
||||
.. include:: ACKS.txt
|
||||
|
||||
It is only with the input and contributions of the Python community
|
||||
that Python has such wonderful documentation -- Thank You!
|
@ -1,73 +0,0 @@
|
||||
.. _reporting-bugs:
|
||||
|
||||
**************
|
||||
Reporting Bugs
|
||||
**************
|
||||
|
||||
Python is a mature programming language which has established a reputation for
|
||||
stability. In order to maintain this reputation, the developers would like to
|
||||
know of any deficiencies you find in Python.
|
||||
|
||||
|
||||
Documentation bugs
|
||||
==================
|
||||
|
||||
If you find a bug in this documentation or would like to propose an improvement,
|
||||
please send an e-mail to docs@python.org describing the bug and where you found
|
||||
it. If you have a suggestion how to fix it, include that as well.
|
||||
|
||||
docs@python.org is a mailing list run by volunteers; your request will be
|
||||
noticed, even if it takes a while to be processed.
|
||||
|
||||
Of course, if you want a more persistent record of your issue, you can use the
|
||||
issue tracker for documentation bugs as well.
|
||||
|
||||
|
||||
Using the Python issue tracker
|
||||
==============================
|
||||
|
||||
Bug reports for Python itself should be submitted via the Python Bug Tracker
|
||||
(http://bugs.python.org/). The bug tracker offers a Web form which allows
|
||||
pertinent information to be entered and submitted to the developers.
|
||||
|
||||
The first step in filing a report is to determine whether the problem has
|
||||
already been reported. The advantage in doing so, aside from saving the
|
||||
developers time, is that you learn what has been done to fix it; it may be that
|
||||
the problem has already been fixed for the next release, or additional
|
||||
information is needed (in which case you are welcome to provide it if you can!).
|
||||
To do this, search the bug database using the search box on the top of the page.
|
||||
|
||||
If the problem you're reporting is not already in the bug tracker, go back to
|
||||
the Python Bug Tracker and log in. If you don't already have a tracker account,
|
||||
select the "Register" link or, if you use OpenID, one of the OpenID provider
|
||||
logos in the sidebar. It is not possible to submit a bug report anonymously.
|
||||
|
||||
Being now logged in, you can submit a bug. Select the "Create New" link in the
|
||||
sidebar to open the bug reporting form.
|
||||
|
||||
The submission form has a number of fields. For the "Title" field, enter a
|
||||
*very* short description of the problem; less than ten words is good. In the
|
||||
"Type" field, select the type of your problem; also select the "Component" and
|
||||
"Versions" to which the bug relates.
|
||||
|
||||
In the "Comment" field, describe the problem in detail, including what you
|
||||
expected to happen and what did happen. Be sure to include whether any
|
||||
extension modules were involved, and what hardware and software platform you
|
||||
were using (including version information as appropriate).
|
||||
|
||||
Each bug report will be assigned to a developer who will determine what needs to
|
||||
be done to correct the problem. You will receive an update each time action is
|
||||
taken on the bug. See http://www.python.org/dev/workflow/ for a detailed
|
||||
description of the issue workflow.
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
`How to Report Bugs Effectively <http://www.chiark.greenend.org.uk/~sgtatham/bugs.html>`_
|
||||
Article which goes into some detail about how to create a useful bug report.
|
||||
This describes what kind of information is useful and why it is useful.
|
||||
|
||||
`Bug Writing Guidelines <http://developer.mozilla.org/en/docs/Bug_writing_guidelines>`_
|
||||
Information about writing a good bug report. Some of this is specific to the
|
||||
Mozilla project, but describes general good practices.
|
||||
|
@ -1,26 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
|
||||
.. _abstract:
|
||||
|
||||
**********************
|
||||
Abstract Objects Layer
|
||||
**********************
|
||||
|
||||
The functions in this chapter interact with Python objects regardless of their
|
||||
type, or with wide classes of object types (e.g. all numerical types, or all
|
||||
sequence types). When used on object types for which they do not apply, they
|
||||
will raise a Python exception.
|
||||
|
||||
It is not possible to use these functions on objects that are not properly
|
||||
initialized, such as a list object that has been created by :cfunc:`PyList_New`,
|
||||
but whose items have not been set to some non-\ ``NULL`` value yet.
|
||||
|
||||
.. toctree::
|
||||
|
||||
object.rst
|
||||
number.rst
|
||||
sequence.rst
|
||||
mapping.rst
|
||||
iter.rst
|
||||
objbuffer.rst
|
@ -1,122 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _allocating-objects:
|
||||
|
||||
Allocating Objects on the Heap
|
||||
==============================
|
||||
|
||||
|
||||
.. cfunction:: PyObject* _PyObject_New(PyTypeObject *type)
|
||||
|
||||
|
||||
.. cfunction:: PyVarObject* _PyObject_NewVar(PyTypeObject *type, Py_ssize_t size)
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int` type for *size*. This might require
|
||||
changes in your code for properly supporting 64-bit systems.
|
||||
|
||||
|
||||
.. cfunction:: void _PyObject_Del(PyObject *op)
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyObject_Init(PyObject *op, PyTypeObject *type)
|
||||
|
||||
Initialize a newly-allocated object *op* with its type and initial
|
||||
reference. Returns the initialized object. If *type* indicates that the
|
||||
object participates in the cyclic garbage detector, it is added to the
|
||||
detector's set of observed objects. Other fields of the object are not
|
||||
affected.
|
||||
|
||||
|
||||
.. cfunction:: PyVarObject* PyObject_InitVar(PyVarObject *op, PyTypeObject *type, Py_ssize_t size)
|
||||
|
||||
This does everything :cfunc:`PyObject_Init` does, and also initializes the
|
||||
length information for a variable-size object.
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int` type for *size*. This might require
|
||||
changes in your code for properly supporting 64-bit systems.
|
||||
|
||||
|
||||
.. cfunction:: TYPE* PyObject_New(TYPE, PyTypeObject *type)
|
||||
|
||||
Allocate a new Python object using the C structure type *TYPE* and the
|
||||
Python type object *type*. Fields not defined by the Python object header
|
||||
are not initialized; the object's reference count will be one. The size of
|
||||
the memory allocation is determined from the :attr:`tp_basicsize` field of
|
||||
the type object.
|
||||
|
||||
|
||||
.. cfunction:: TYPE* PyObject_NewVar(TYPE, PyTypeObject *type, Py_ssize_t size)
|
||||
|
||||
Allocate a new Python object using the C structure type *TYPE* and the
|
||||
Python type object *type*. Fields not defined by the Python object header
|
||||
are not initialized. The allocated memory allows for the *TYPE* structure
|
||||
plus *size* fields of the size given by the :attr:`tp_itemsize` field of
|
||||
*type*. This is useful for implementing objects like tuples, which are
|
||||
able to determine their size at construction time. Embedding the array of
|
||||
fields into the same allocation decreases the number of allocations,
|
||||
improving the memory management efficiency.
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int` type for *size*. This might require
|
||||
changes in your code for properly supporting 64-bit systems.
|
||||
|
||||
|
||||
.. cfunction:: void PyObject_Del(PyObject *op)
|
||||
|
||||
Releases memory allocated to an object using :cfunc:`PyObject_New` or
|
||||
:cfunc:`PyObject_NewVar`. This is normally called from the
|
||||
:attr:`tp_dealloc` handler specified in the object's type. The fields of
|
||||
the object should not be accessed after this call as the memory is no
|
||||
longer a valid Python object.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* Py_InitModule(char *name, PyMethodDef *methods)
|
||||
|
||||
Create a new module object based on a name and table of functions,
|
||||
returning the new module object.
|
||||
|
||||
.. versionchanged:: 2.3
|
||||
Older versions of Python did not support *NULL* as the value for the
|
||||
*methods* argument.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* Py_InitModule3(char *name, PyMethodDef *methods, char *doc)
|
||||
|
||||
Create a new module object based on a name and table of functions,
|
||||
returning the new module object. If *doc* is non-*NULL*, it will be used
|
||||
to define the docstring for the module.
|
||||
|
||||
.. versionchanged:: 2.3
|
||||
Older versions of Python did not support *NULL* as the value for the
|
||||
*methods* argument.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* Py_InitModule4(char *name, PyMethodDef *methods, char *doc, PyObject *self, int apiver)
|
||||
|
||||
Create a new module object based on a name and table of functions,
|
||||
returning the new module object. If *doc* is non-*NULL*, it will be used
|
||||
to define the docstring for the module. If *self* is non-*NULL*, it will
|
||||
passed to the functions of the module as their (otherwise *NULL*) first
|
||||
parameter. (This was added as an experimental feature, and there are no
|
||||
known uses in the current version of Python.) For *apiver*, the only value
|
||||
which should be passed is defined by the constant
|
||||
:const:`PYTHON_API_VERSION`.
|
||||
|
||||
.. note::
|
||||
|
||||
Most uses of this function should probably be using the
|
||||
:cfunc:`Py_InitModule3` instead; only use this if you are sure you need
|
||||
it.
|
||||
|
||||
.. versionchanged:: 2.3
|
||||
Older versions of Python did not support *NULL* as the value for the
|
||||
*methods* argument.
|
||||
|
||||
|
||||
.. cvar:: PyObject _Py_NoneStruct
|
||||
|
||||
Object which is visible in Python as ``None``. This should only be
|
||||
accessed using the ``Py_None`` macro, which evaluates to a pointer to this
|
||||
object.
|
@ -1,559 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _arg-parsing:
|
||||
|
||||
Parsing arguments and building values
|
||||
=====================================
|
||||
|
||||
These functions are useful when creating your own extensions functions and
|
||||
methods. Additional information and examples are available in
|
||||
:ref:`extending-index`.
|
||||
|
||||
The first three of these functions described, :cfunc:`PyArg_ParseTuple`,
|
||||
:cfunc:`PyArg_ParseTupleAndKeywords`, and :cfunc:`PyArg_Parse`, all use
|
||||
*format strings* which are used to tell the function about the expected
|
||||
arguments. The format strings use the same syntax for each of these
|
||||
functions.
|
||||
|
||||
A format string consists of zero or more "format units." A format unit
|
||||
describes one Python object; it is usually a single character or a
|
||||
parenthesized sequence of format units. With a few exceptions, a format unit
|
||||
that is not a parenthesized sequence normally corresponds to a single address
|
||||
argument to these functions. In the following description, the quoted form is
|
||||
the format unit; the entry in (round) parentheses is the Python object type
|
||||
that matches the format unit; and the entry in [square] brackets is the type
|
||||
of the C variable(s) whose address should be passed.
|
||||
|
||||
``s`` (string or Unicode) [const char \*]
|
||||
Convert a Python string or Unicode object to a C pointer to a character
|
||||
string. You must not provide storage for the string itself; a pointer to
|
||||
an existing string is stored into the character pointer variable whose
|
||||
address you pass. The C string is NUL-terminated. The Python string must
|
||||
not contain embedded NUL bytes; if it does, a :exc:`TypeError` exception is
|
||||
raised. Unicode objects are converted to C strings using the default
|
||||
encoding. If this conversion fails, a :exc:`UnicodeError` is raised.
|
||||
|
||||
``s#`` (string, Unicode or any read buffer compatible object) [const char \*, int (or :ctype:`Py_ssize_t`, see below)]
|
||||
This variant on ``s`` stores into two C variables, the first one a pointer
|
||||
to a character string, the second one its length. In this case the Python
|
||||
string may contain embedded null bytes. Unicode objects pass back a
|
||||
pointer to the default encoded string version of the object if such a
|
||||
conversion is possible. All other read-buffer compatible objects pass back
|
||||
a reference to the raw internal data representation.
|
||||
|
||||
Starting with Python 2.5 the type of the length argument can be controlled
|
||||
by defining the macro :cmacro:`PY_SSIZE_T_CLEAN` before including
|
||||
:file:`Python.h`. If the macro is defined, length is a :ctype:`Py_ssize_t`
|
||||
rather than an int.
|
||||
|
||||
``s*`` (string, Unicode, or any buffer compatible object) [Py_buffer]
|
||||
Similar to ``s#``, this code fills a Py_buffer structure provided by the
|
||||
caller. The buffer gets locked, so that the caller can subsequently use
|
||||
the buffer even inside a ``Py_BEGIN_ALLOW_THREADS`` block; the caller is
|
||||
responsible for calling ``PyBuffer_Release`` with the structure after it
|
||||
has processed the data.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
``z`` (string, Unicode or ``None``) [const char \*]
|
||||
Like ``s``, but the Python object may also be ``None``, in which case the C
|
||||
pointer is set to *NULL*.
|
||||
|
||||
``z#`` (string, Unicode, ``None`` or any read buffer compatible object) [const char \*, int]
|
||||
This is to ``s#`` as ``z`` is to ``s``.
|
||||
|
||||
``z*`` (string, Unicode, ``None`` or any buffer compatible object) [Py_buffer]
|
||||
This is to ``s*`` as ``z`` is to ``s``.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
``u`` (Unicode) [Py_UNICODE \*]
|
||||
Convert a Python Unicode object to a C pointer to a NUL-terminated buffer
|
||||
of 16-bit Unicode (UTF-16) data. As with ``s``, there is no need to
|
||||
provide storage for the Unicode data buffer; a pointer to the existing
|
||||
Unicode data is stored into the :ctype:`Py_UNICODE` pointer variable whose
|
||||
address you pass.
|
||||
|
||||
``u#`` (Unicode) [Py_UNICODE \*, int]
|
||||
This variant on ``u`` stores into two C variables, the first one a pointer
|
||||
to a Unicode data buffer, the second one its length. Non-Unicode objects
|
||||
are handled by interpreting their read-buffer pointer as pointer to a
|
||||
:ctype:`Py_UNICODE` array.
|
||||
|
||||
``es`` (string, Unicode or character buffer compatible object) [const char \*encoding, char \*\*buffer]
|
||||
This variant on ``s`` is used for encoding Unicode and objects convertible
|
||||
to Unicode into a character buffer. It only works for encoded data without
|
||||
embedded NUL bytes.
|
||||
|
||||
This format requires two arguments. The first is only used as input, and
|
||||
must be a :ctype:`const char\*` which points to the name of an encoding as
|
||||
a NUL-terminated string, or *NULL*, in which case the default encoding is
|
||||
used. An exception is raised if the named encoding is not known to Python.
|
||||
The second argument must be a :ctype:`char\*\*`; the value of the pointer
|
||||
it references will be set to a buffer with the contents of the argument
|
||||
text. The text will be encoded in the encoding specified by the first
|
||||
argument.
|
||||
|
||||
:cfunc:`PyArg_ParseTuple` will allocate a buffer of the needed size, copy
|
||||
the encoded data into this buffer and adjust *\*buffer* to reference the
|
||||
newly allocated storage. The caller is responsible for calling
|
||||
:cfunc:`PyMem_Free` to free the allocated buffer after use.
|
||||
|
||||
``et`` (string, Unicode or character buffer compatible object) [const char \*encoding, char \*\*buffer]
|
||||
Same as ``es`` except that 8-bit string objects are passed through without
|
||||
recoding them. Instead, the implementation assumes that the string object
|
||||
uses the encoding passed in as parameter.
|
||||
|
||||
``es#`` (string, Unicode or character buffer compatible object) [const char \*encoding, char \*\*buffer, int \*buffer_length]
|
||||
This variant on ``s#`` is used for encoding Unicode and objects convertible
|
||||
to Unicode into a character buffer. Unlike the ``es`` format, this variant
|
||||
allows input data which contains NUL characters.
|
||||
|
||||
It requires three arguments. The first is only used as input, and must be
|
||||
a :ctype:`const char\*` which points to the name of an encoding as a
|
||||
NUL-terminated string, or *NULL*, in which case the default encoding is
|
||||
used. An exception is raised if the named encoding is not known to Python.
|
||||
The second argument must be a :ctype:`char\*\*`; the value of the pointer
|
||||
it references will be set to a buffer with the contents of the argument
|
||||
text. The text will be encoded in the encoding specified by the first
|
||||
argument. The third argument must be a pointer to an integer; the
|
||||
referenced integer will be set to the number of bytes in the output buffer.
|
||||
|
||||
There are two modes of operation:
|
||||
|
||||
If *\*buffer* points a *NULL* pointer, the function will allocate a buffer
|
||||
of the needed size, copy the encoded data into this buffer and set
|
||||
*\*buffer* to reference the newly allocated storage. The caller is
|
||||
responsible for calling :cfunc:`PyMem_Free` to free the allocated buffer
|
||||
after usage.
|
||||
|
||||
If *\*buffer* points to a non-*NULL* pointer (an already allocated buffer),
|
||||
:cfunc:`PyArg_ParseTuple` will use this location as the buffer and
|
||||
interpret the initial value of *\*buffer_length* as the buffer size. It
|
||||
will then copy the encoded data into the buffer and NUL-terminate it. If
|
||||
the buffer is not large enough, a :exc:`ValueError` will be set.
|
||||
|
||||
In both cases, *\*buffer_length* is set to the length of the encoded data
|
||||
without the trailing NUL byte.
|
||||
|
||||
``et#`` (string, Unicode or character buffer compatible object) [const char \*encoding, char \*\*buffer, int \*buffer_length]
|
||||
Same as ``es#`` except that string objects are passed through without
|
||||
recoding them. Instead, the implementation assumes that the string object
|
||||
uses the encoding passed in as parameter.
|
||||
|
||||
``b`` (integer) [unsigned char]
|
||||
Convert a nonnegative Python integer to an unsigned tiny int, stored in a C
|
||||
:ctype:`unsigned char`.
|
||||
|
||||
``B`` (integer) [unsigned char]
|
||||
Convert a Python integer to a tiny int without overflow checking, stored in
|
||||
a C :ctype:`unsigned char`.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
``h`` (integer) [short int]
|
||||
Convert a Python integer to a C :ctype:`short int`.
|
||||
|
||||
``H`` (integer) [unsigned short int]
|
||||
Convert a Python integer to a C :ctype:`unsigned short int`, without
|
||||
overflow checking.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
``i`` (integer) [int]
|
||||
Convert a Python integer to a plain C :ctype:`int`.
|
||||
|
||||
``I`` (integer) [unsigned int]
|
||||
Convert a Python integer to a C :ctype:`unsigned int`, without overflow
|
||||
checking.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
``l`` (integer) [long int]
|
||||
Convert a Python integer to a C :ctype:`long int`.
|
||||
|
||||
``k`` (integer) [unsigned long]
|
||||
Convert a Python integer or long integer to a C :ctype:`unsigned long`
|
||||
without overflow checking.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
``L`` (integer) [PY_LONG_LONG]
|
||||
Convert a Python integer to a C :ctype:`long long`. This format is only
|
||||
available on platforms that support :ctype:`long long` (or :ctype:`_int64`
|
||||
on Windows).
|
||||
|
||||
``K`` (integer) [unsigned PY_LONG_LONG]
|
||||
Convert a Python integer or long integer to a C :ctype:`unsigned long long`
|
||||
without overflow checking. This format is only available on platforms that
|
||||
support :ctype:`unsigned long long` (or :ctype:`unsigned _int64` on
|
||||
Windows).
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
``n`` (integer) [Py_ssize_t]
|
||||
Convert a Python integer or long integer to a C :ctype:`Py_ssize_t`.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
``c`` (string of length 1) [char]
|
||||
Convert a Python character, represented as a string of length 1, to a C
|
||||
:ctype:`char`.
|
||||
|
||||
``f`` (float) [float]
|
||||
Convert a Python floating point number to a C :ctype:`float`.
|
||||
|
||||
``d`` (float) [double]
|
||||
Convert a Python floating point number to a C :ctype:`double`.
|
||||
|
||||
``D`` (complex) [Py_complex]
|
||||
Convert a Python complex number to a C :ctype:`Py_complex` structure.
|
||||
|
||||
``O`` (object) [PyObject \*]
|
||||
Store a Python object (without any conversion) in a C object pointer. The
|
||||
C program thus receives the actual object that was passed. The object's
|
||||
reference count is not increased. The pointer stored is not *NULL*.
|
||||
|
||||
``O!`` (object) [*typeobject*, PyObject \*]
|
||||
Store a Python object in a C object pointer. This is similar to ``O``, but
|
||||
takes two C arguments: the first is the address of a Python type object,
|
||||
the second is the address of the C variable (of type :ctype:`PyObject\*`)
|
||||
into which the object pointer is stored. If the Python object does not
|
||||
have the required type, :exc:`TypeError` is raised.
|
||||
|
||||
``O&`` (object) [*converter*, *anything*]
|
||||
Convert a Python object to a C variable through a *converter* function.
|
||||
This takes two arguments: the first is a function, the second is the
|
||||
address of a C variable (of arbitrary type), converted to :ctype:`void \*`.
|
||||
The *converter* function in turn is called as follows::
|
||||
|
||||
status = converter(object, address);
|
||||
|
||||
where *object* is the Python object to be converted and *address* is the
|
||||
:ctype:`void\*` argument that was passed to the :cfunc:`PyArg_Parse\*`
|
||||
function. The returned *status* should be ``1`` for a successful
|
||||
conversion and ``0`` if the conversion has failed. When the conversion
|
||||
fails, the *converter* function should raise an exception and leave the
|
||||
content of *address* unmodified.
|
||||
|
||||
``S`` (string) [PyStringObject \*]
|
||||
Like ``O`` but requires that the Python object is a string object. Raises
|
||||
:exc:`TypeError` if the object is not a string object. The C variable may
|
||||
also be declared as :ctype:`PyObject\*`.
|
||||
|
||||
``U`` (Unicode string) [PyUnicodeObject \*]
|
||||
Like ``O`` but requires that the Python object is a Unicode object. Raises
|
||||
:exc:`TypeError` if the object is not a Unicode object. The C variable may
|
||||
also be declared as :ctype:`PyObject\*`.
|
||||
|
||||
``t#`` (read-only character buffer) [char \*, int]
|
||||
Like ``s#``, but accepts any object which implements the read-only buffer
|
||||
interface. The :ctype:`char\*` variable is set to point to the first byte
|
||||
of the buffer, and the :ctype:`int` is set to the length of the buffer.
|
||||
Only single-segment buffer objects are accepted; :exc:`TypeError` is raised
|
||||
for all others.
|
||||
|
||||
``w`` (read-write character buffer) [char \*]
|
||||
Similar to ``s``, but accepts any object which implements the read-write
|
||||
buffer interface. The caller must determine the length of the buffer by
|
||||
other means, or use ``w#`` instead. Only single-segment buffer objects are
|
||||
accepted; :exc:`TypeError` is raised for all others.
|
||||
|
||||
``w#`` (read-write character buffer) [char \*, Py_ssize_t]
|
||||
Like ``s#``, but accepts any object which implements the read-write buffer
|
||||
interface. The :ctype:`char \*` variable is set to point to the first byte
|
||||
of the buffer, and the :ctype:`Py_ssize_t` is set to the length of the
|
||||
buffer. Only single-segment buffer objects are accepted; :exc:`TypeError`
|
||||
is raised for all others.
|
||||
|
||||
``w*`` (read-write byte-oriented buffer) [Py_buffer]
|
||||
This is to ``w`` what ``s*`` is to ``s``.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
``(items)`` (tuple) [*matching-items*]
|
||||
The object must be a Python sequence whose length is the number of format
|
||||
units in *items*. The C arguments must correspond to the individual format
|
||||
units in *items*. Format units for sequences may be nested.
|
||||
|
||||
.. note::
|
||||
|
||||
Prior to Python version 1.5.2, this format specifier only accepted a
|
||||
tuple containing the individual parameters, not an arbitrary sequence.
|
||||
Code which previously caused :exc:`TypeError` to be raised here may now
|
||||
proceed without an exception. This is not expected to be a problem for
|
||||
existing code.
|
||||
|
||||
It is possible to pass Python long integers where integers are requested;
|
||||
however no proper range checking is done --- the most significant bits are
|
||||
silently truncated when the receiving field is too small to receive the value
|
||||
(actually, the semantics are inherited from downcasts in C --- your mileage
|
||||
may vary).
|
||||
|
||||
A few other characters have a meaning in a format string. These may not occur
|
||||
inside nested parentheses. They are:
|
||||
|
||||
``|``
|
||||
Indicates that the remaining arguments in the Python argument list are
|
||||
optional. The C variables corresponding to optional arguments should be
|
||||
initialized to their default value --- when an optional argument is not
|
||||
specified, :cfunc:`PyArg_ParseTuple` does not touch the contents of the
|
||||
corresponding C variable(s).
|
||||
|
||||
``:``
|
||||
The list of format units ends here; the string after the colon is used as
|
||||
the function name in error messages (the "associated value" of the
|
||||
exception that :cfunc:`PyArg_ParseTuple` raises).
|
||||
|
||||
``;``
|
||||
The list of format units ends here; the string after the semicolon is used
|
||||
as the error message *instead* of the default error message. ``:`` and
|
||||
``;`` mutually exclude each other.
|
||||
|
||||
Note that any Python object references which are provided to the caller are
|
||||
*borrowed* references; do not decrement their reference count!
|
||||
|
||||
Additional arguments passed to these functions must be addresses of variables
|
||||
whose type is determined by the format string; these are used to store values
|
||||
from the input tuple. There are a few cases, as described in the list of
|
||||
format units above, where these parameters are used as input values; they
|
||||
should match what is specified for the corresponding format unit in that case.
|
||||
|
||||
For the conversion to succeed, the *arg* object must match the format and the
|
||||
format must be exhausted. On success, the :cfunc:`PyArg_Parse\*` functions
|
||||
return true, otherwise they return false and raise an appropriate exception.
|
||||
When the :cfunc:`PyArg_Parse\*` functions fail due to conversion failure in
|
||||
one of the format units, the variables at the addresses corresponding to that
|
||||
and the following format units are left untouched.
|
||||
|
||||
|
||||
.. cfunction:: int PyArg_ParseTuple(PyObject *args, const char *format, ...)
|
||||
|
||||
Parse the parameters of a function that takes only positional parameters
|
||||
into local variables. Returns true on success; on failure, it returns
|
||||
false and raises the appropriate exception.
|
||||
|
||||
|
||||
.. cfunction:: int PyArg_VaParse(PyObject *args, const char *format, va_list vargs)
|
||||
|
||||
Identical to :cfunc:`PyArg_ParseTuple`, except that it accepts a va_list
|
||||
rather than a variable number of arguments.
|
||||
|
||||
|
||||
.. cfunction:: int PyArg_ParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], ...)
|
||||
|
||||
Parse the parameters of a function that takes both positional and keyword
|
||||
parameters into local variables. Returns true on success; on failure, it
|
||||
returns false and raises the appropriate exception.
|
||||
|
||||
|
||||
.. cfunction:: int PyArg_VaParseTupleAndKeywords(PyObject *args, PyObject *kw, const char *format, char *keywords[], va_list vargs)
|
||||
|
||||
Identical to :cfunc:`PyArg_ParseTupleAndKeywords`, except that it accepts a
|
||||
va_list rather than a variable number of arguments.
|
||||
|
||||
|
||||
.. cfunction:: int PyArg_Parse(PyObject *args, const char *format, ...)
|
||||
|
||||
Function used to deconstruct the argument lists of "old-style" functions
|
||||
--- these are functions which use the :const:`METH_OLDARGS` parameter
|
||||
parsing method. This is not recommended for use in parameter parsing in
|
||||
new code, and most code in the standard interpreter has been modified to no
|
||||
longer use this for that purpose. It does remain a convenient way to
|
||||
decompose other tuples, however, and may continue to be used for that
|
||||
purpose.
|
||||
|
||||
|
||||
.. cfunction:: int PyArg_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, ...)
|
||||
|
||||
A simpler form of parameter retrieval which does not use a format string to
|
||||
specify the types of the arguments. Functions which use this method to
|
||||
retrieve their parameters should be declared as :const:`METH_VARARGS` in
|
||||
function or method tables. The tuple containing the actual parameters
|
||||
should be passed as *args*; it must actually be a tuple. The length of the
|
||||
tuple must be at least *min* and no more than *max*; *min* and *max* may be
|
||||
equal. Additional arguments must be passed to the function, each of which
|
||||
should be a pointer to a :ctype:`PyObject\*` variable; these will be filled
|
||||
in with the values from *args*; they will contain borrowed references. The
|
||||
variables which correspond to optional parameters not given by *args* will
|
||||
not be filled in; these should be initialized by the caller. This function
|
||||
returns true on success and false if *args* is not a tuple or contains the
|
||||
wrong number of elements; an exception will be set if there was a failure.
|
||||
|
||||
This is an example of the use of this function, taken from the sources for
|
||||
the :mod:`_weakref` helper module for weak references::
|
||||
|
||||
static PyObject *
|
||||
weakref_ref(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *object;
|
||||
PyObject *callback = NULL;
|
||||
PyObject *result = NULL;
|
||||
|
||||
if (PyArg_UnpackTuple(args, "ref", 1, 2, &object, &callback)) {
|
||||
result = PyWeakref_NewRef(object, callback);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
The call to :cfunc:`PyArg_UnpackTuple` in this example is entirely
|
||||
equivalent to this call to :cfunc:`PyArg_ParseTuple`::
|
||||
|
||||
PyArg_ParseTuple(args, "O|O:ref", &object, &callback)
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int` type for *min* and *max*. This might
|
||||
require changes in your code for properly supporting 64-bit systems.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* Py_BuildValue(const char *format, ...)
|
||||
|
||||
Create a new value based on a format string similar to those accepted by
|
||||
the :cfunc:`PyArg_Parse\*` family of functions and a sequence of values.
|
||||
Returns the value or *NULL* in the case of an error; an exception will be
|
||||
raised if *NULL* is returned.
|
||||
|
||||
:cfunc:`Py_BuildValue` does not always build a tuple. It builds a tuple
|
||||
only if its format string contains two or more format units. If the format
|
||||
string is empty, it returns ``None``; if it contains exactly one format
|
||||
unit, it returns whatever object is described by that format unit. To
|
||||
force it to return a tuple of size 0 or one, parenthesize the format
|
||||
string.
|
||||
|
||||
When memory buffers are passed as parameters to supply data to build
|
||||
objects, as for the ``s`` and ``s#`` formats, the required data is copied.
|
||||
Buffers provided by the caller are never referenced by the objects created
|
||||
by :cfunc:`Py_BuildValue`. In other words, if your code invokes
|
||||
:cfunc:`malloc` and passes the allocated memory to :cfunc:`Py_BuildValue`,
|
||||
your code is responsible for calling :cfunc:`free` for that memory once
|
||||
:cfunc:`Py_BuildValue` returns.
|
||||
|
||||
In the following description, the quoted form is the format unit; the entry
|
||||
in (round) parentheses is the Python object type that the format unit will
|
||||
return; and the entry in [square] brackets is the type of the C value(s) to
|
||||
be passed.
|
||||
|
||||
The characters space, tab, colon and comma are ignored in format strings
|
||||
(but not within format units such as ``s#``). This can be used to make
|
||||
long format strings a tad more readable.
|
||||
|
||||
``s`` (string) [char \*]
|
||||
Convert a null-terminated C string to a Python object. If the C string
|
||||
pointer is *NULL*, ``None`` is used.
|
||||
|
||||
``s#`` (string) [char \*, int]
|
||||
Convert a C string and its length to a Python object. If the C string
|
||||
pointer is *NULL*, the length is ignored and ``None`` is returned.
|
||||
|
||||
``z`` (string or ``None``) [char \*]
|
||||
Same as ``s``.
|
||||
|
||||
``z#`` (string or ``None``) [char \*, int]
|
||||
Same as ``s#``.
|
||||
|
||||
``u`` (Unicode string) [Py_UNICODE \*]
|
||||
Convert a null-terminated buffer of Unicode (UCS-2 or UCS-4) data to a
|
||||
Python Unicode object. If the Unicode buffer pointer is *NULL*,
|
||||
``None`` is returned.
|
||||
|
||||
``u#`` (Unicode string) [Py_UNICODE \*, int]
|
||||
Convert a Unicode (UCS-2 or UCS-4) data buffer and its length to a
|
||||
Python Unicode object. If the Unicode buffer pointer is *NULL*, the
|
||||
length is ignored and ``None`` is returned.
|
||||
|
||||
``i`` (integer) [int]
|
||||
Convert a plain C :ctype:`int` to a Python integer object.
|
||||
|
||||
``b`` (integer) [char]
|
||||
Convert a plain C :ctype:`char` to a Python integer object.
|
||||
|
||||
``h`` (integer) [short int]
|
||||
Convert a plain C :ctype:`short int` to a Python integer object.
|
||||
|
||||
``l`` (integer) [long int]
|
||||
Convert a C :ctype:`long int` to a Python integer object.
|
||||
|
||||
``B`` (integer) [unsigned char]
|
||||
Convert a C :ctype:`unsigned char` to a Python integer object.
|
||||
|
||||
``H`` (integer) [unsigned short int]
|
||||
Convert a C :ctype:`unsigned short int` to a Python integer object.
|
||||
|
||||
``I`` (integer/long) [unsigned int]
|
||||
Convert a C :ctype:`unsigned int` to a Python integer object or a Python
|
||||
long integer object, if it is larger than ``sys.maxint``.
|
||||
|
||||
``k`` (integer/long) [unsigned long]
|
||||
Convert a C :ctype:`unsigned long` to a Python integer object or a
|
||||
Python long integer object, if it is larger than ``sys.maxint``.
|
||||
|
||||
``L`` (long) [PY_LONG_LONG]
|
||||
Convert a C :ctype:`long long` to a Python long integer object. Only
|
||||
available on platforms that support :ctype:`long long`.
|
||||
|
||||
``K`` (long) [unsigned PY_LONG_LONG]
|
||||
Convert a C :ctype:`unsigned long long` to a Python long integer object.
|
||||
Only available on platforms that support :ctype:`unsigned long long`.
|
||||
|
||||
``n`` (int) [Py_ssize_t]
|
||||
Convert a C :ctype:`Py_ssize_t` to a Python integer or long integer.
|
||||
|
||||
.. versionadded:: 2.5
|
||||
|
||||
``c`` (string of length 1) [char]
|
||||
Convert a C :ctype:`int` representing a character to a Python string of
|
||||
length 1.
|
||||
|
||||
``d`` (float) [double]
|
||||
Convert a C :ctype:`double` to a Python floating point number.
|
||||
|
||||
``f`` (float) [float]
|
||||
Same as ``d``.
|
||||
|
||||
``D`` (complex) [Py_complex \*]
|
||||
Convert a C :ctype:`Py_complex` structure to a Python complex number.
|
||||
|
||||
``O`` (object) [PyObject \*]
|
||||
Pass a Python object untouched (except for its reference count, which is
|
||||
incremented by one). If the object passed in is a *NULL* pointer, it is
|
||||
assumed that this was caused because the call producing the argument
|
||||
found an error and set an exception. Therefore, :cfunc:`Py_BuildValue`
|
||||
will return *NULL* but won't raise an exception. If no exception has
|
||||
been raised yet, :exc:`SystemError` is set.
|
||||
|
||||
``S`` (object) [PyObject \*]
|
||||
Same as ``O``.
|
||||
|
||||
``N`` (object) [PyObject \*]
|
||||
Same as ``O``, except it doesn't increment the reference count on the
|
||||
object. Useful when the object is created by a call to an object
|
||||
constructor in the argument list.
|
||||
|
||||
``O&`` (object) [*converter*, *anything*]
|
||||
Convert *anything* to a Python object through a *converter* function.
|
||||
The function is called with *anything* (which should be compatible with
|
||||
:ctype:`void \*`) as its argument and should return a "new" Python
|
||||
object, or *NULL* if an error occurred.
|
||||
|
||||
``(items)`` (tuple) [*matching-items*]
|
||||
Convert a sequence of C values to a Python tuple with the same number of
|
||||
items.
|
||||
|
||||
``[items]`` (list) [*matching-items*]
|
||||
Convert a sequence of C values to a Python list with the same number of
|
||||
items.
|
||||
|
||||
``{items}`` (dictionary) [*matching-items*]
|
||||
Convert a sequence of C values to a Python dictionary. Each pair of
|
||||
consecutive C values adds one item to the dictionary, serving as key and
|
||||
value, respectively.
|
||||
|
||||
If there is an error in the format string, the :exc:`SystemError` exception
|
||||
is set and *NULL* returned.
|
||||
|
||||
.. cfunction:: PyObject* Py_VaBuildValue(const char *format, va_list vargs)
|
||||
|
||||
Identical to :cfunc:`Py_BuildValue`, except that it accepts a va_list
|
||||
rather than a variable number of arguments.
|
@ -1,54 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _boolobjects:
|
||||
|
||||
Boolean Objects
|
||||
---------------
|
||||
|
||||
Booleans in Python are implemented as a subclass of integers. There are only
|
||||
two booleans, :const:`Py_False` and :const:`Py_True`. As such, the normal
|
||||
creation and deletion functions don't apply to booleans. The following macros
|
||||
are available, however.
|
||||
|
||||
|
||||
.. cfunction:: int PyBool_Check(PyObject *o)
|
||||
|
||||
Return true if *o* is of type :cdata:`PyBool_Type`.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
|
||||
.. cvar:: PyObject* Py_False
|
||||
|
||||
The Python ``False`` object. This object has no methods. It needs to be
|
||||
treated just like any other object with respect to reference counts.
|
||||
|
||||
|
||||
.. cvar:: PyObject* Py_True
|
||||
|
||||
The Python ``True`` object. This object has no methods. It needs to be treated
|
||||
just like any other object with respect to reference counts.
|
||||
|
||||
|
||||
.. cmacro:: Py_RETURN_FALSE
|
||||
|
||||
Return :const:`Py_False` from a function, properly incrementing its reference
|
||||
count.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cmacro:: Py_RETURN_TRUE
|
||||
|
||||
Return :const:`Py_True` from a function, properly incrementing its reference
|
||||
count.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyBool_FromLong(long v)
|
||||
|
||||
Return a new reference to :const:`Py_True` or :const:`Py_False` depending on the
|
||||
truth value of *v*.
|
||||
|
||||
.. versionadded:: 2.3
|
@ -1,419 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _bufferobjects:
|
||||
|
||||
Buffer Objects
|
||||
--------------
|
||||
|
||||
.. sectionauthor:: Greg Stein <gstein@lyra.org>
|
||||
|
||||
|
||||
.. index::
|
||||
object: buffer
|
||||
single: buffer interface
|
||||
|
||||
Python objects implemented in C can export a group of functions called the
|
||||
"buffer interface." These functions can be used by an object to expose its
|
||||
data in a raw, byte-oriented format. Clients of the object can use the buffer
|
||||
interface to access the object data directly, without needing to copy it
|
||||
first.
|
||||
|
||||
Two examples of objects that support the buffer interface are strings and
|
||||
arrays. The string object exposes the character contents in the buffer
|
||||
interface's byte-oriented form. An array can also expose its contents, but it
|
||||
should be noted that array elements may be multi-byte values.
|
||||
|
||||
An example user of the buffer interface is the file object's :meth:`write`
|
||||
method. Any object that can export a series of bytes through the buffer
|
||||
interface can be written to a file. There are a number of format codes to
|
||||
:cfunc:`PyArg_ParseTuple` that operate against an object's buffer interface,
|
||||
returning data from the target object.
|
||||
|
||||
Starting from version 1.6, Python has been providing Python-level buffer
|
||||
objects and a C-level buffer API so that any built-in or used-defined type can
|
||||
expose its characteristics. Both, however, have been deprecated because of
|
||||
various shortcomings, and have been officially removed in Python 3.0 in favour
|
||||
of a new C-level buffer API and a new Python-level object named
|
||||
:class:`memoryview`.
|
||||
|
||||
The new buffer API has been backported to Python 2.6, and the
|
||||
:class:`memoryview` object has been backported to Python 2.7. It is strongly
|
||||
advised to use them rather than the old APIs, unless you are blocked from
|
||||
doing so for compatibility reasons.
|
||||
|
||||
|
||||
The new-style Py_buffer struct
|
||||
==============================
|
||||
|
||||
|
||||
.. ctype:: Py_buffer
|
||||
|
||||
.. cmember:: void *buf
|
||||
|
||||
A pointer to the start of the memory for the object.
|
||||
|
||||
.. cmember:: Py_ssize_t len
|
||||
:noindex:
|
||||
|
||||
The total length of the memory in bytes.
|
||||
|
||||
.. cmember:: int readonly
|
||||
|
||||
An indicator of whether the buffer is read only.
|
||||
|
||||
.. cmember:: const char *format
|
||||
:noindex:
|
||||
|
||||
A *NULL* terminated string in :mod:`struct` module style syntax giving
|
||||
the contents of the elements available through the buffer. If this is
|
||||
*NULL*, ``"B"`` (unsigned bytes) is assumed.
|
||||
|
||||
.. cmember:: int ndim
|
||||
|
||||
The number of dimensions the memory represents as a multi-dimensional
|
||||
array. If it is 0, :cdata:`strides` and :cdata:`suboffsets` must be
|
||||
*NULL*.
|
||||
|
||||
.. cmember:: Py_ssize_t *shape
|
||||
|
||||
An array of :ctype:`Py_ssize_t`\s the length of :cdata:`ndim` giving the
|
||||
shape of the memory as a multi-dimensional array. Note that
|
||||
``((*shape)[0] * ... * (*shape)[ndims-1])*itemsize`` should be equal to
|
||||
:cdata:`len`.
|
||||
|
||||
.. cmember:: Py_ssize_t *strides
|
||||
|
||||
An array of :ctype:`Py_ssize_t`\s the length of :cdata:`ndim` giving the
|
||||
number of bytes to skip to get to a new element in each dimension.
|
||||
|
||||
.. cmember:: Py_ssize_t *suboffsets
|
||||
|
||||
An array of :ctype:`Py_ssize_t`\s the length of :cdata:`ndim`. If these
|
||||
suboffset numbers are greater than or equal to 0, then the value stored
|
||||
along the indicated dimension is a pointer and the suboffset value
|
||||
dictates how many bytes to add to the pointer after de-referencing. A
|
||||
suboffset value that it negative indicates that no de-referencing should
|
||||
occur (striding in a contiguous memory block).
|
||||
|
||||
Here is a function that returns a pointer to the element in an N-D array
|
||||
pointed to by an N-dimesional index when there are both non-NULL strides
|
||||
and suboffsets::
|
||||
|
||||
void *get_item_pointer(int ndim, void *buf, Py_ssize_t *strides,
|
||||
Py_ssize_t *suboffsets, Py_ssize_t *indices) {
|
||||
char *pointer = (char*)buf;
|
||||
int i;
|
||||
for (i = 0; i < ndim; i++) {
|
||||
pointer += strides[i] * indices[i];
|
||||
if (suboffsets[i] >=0 ) {
|
||||
pointer = *((char**)pointer) + suboffsets[i];
|
||||
}
|
||||
}
|
||||
return (void*)pointer;
|
||||
}
|
||||
|
||||
|
||||
.. cmember:: Py_ssize_t itemsize
|
||||
|
||||
This is a storage for the itemsize (in bytes) of each element of the
|
||||
shared memory. It is technically un-necessary as it can be obtained
|
||||
using :cfunc:`PyBuffer_SizeFromFormat`, however an exporter may know
|
||||
this information without parsing the format string and it is necessary
|
||||
to know the itemsize for proper interpretation of striding. Therefore,
|
||||
storing it is more convenient and faster.
|
||||
|
||||
.. cmember:: void *internal
|
||||
|
||||
This is for use internally by the exporting object. For example, this
|
||||
might be re-cast as an integer by the exporter and used to store flags
|
||||
about whether or not the shape, strides, and suboffsets arrays must be
|
||||
freed when the buffer is released. The consumer should never alter this
|
||||
value.
|
||||
|
||||
|
||||
Buffer related functions
|
||||
========================
|
||||
|
||||
|
||||
.. cfunction:: int PyObject_CheckBuffer(PyObject *obj)
|
||||
|
||||
Return 1 if *obj* supports the buffer interface otherwise 0.
|
||||
|
||||
|
||||
.. cfunction:: int PyObject_GetBuffer(PyObject *obj, Py_buffer *view, int flags)
|
||||
|
||||
Export *obj* into a :ctype:`Py_buffer`, *view*. These arguments must
|
||||
never be *NULL*. The *flags* argument is a bit field indicating what
|
||||
kind of buffer the caller is prepared to deal with and therefore what
|
||||
kind of buffer the exporter is allowed to return. The buffer interface
|
||||
allows for complicated memory sharing possibilities, but some caller may
|
||||
not be able to handle all the complexity but may want to see if the
|
||||
exporter will let them take a simpler view to its memory.
|
||||
|
||||
Some exporters may not be able to share memory in every possible way and
|
||||
may need to raise errors to signal to some consumers that something is
|
||||
just not possible. These errors should be a :exc:`BufferError` unless
|
||||
there is another error that is actually causing the problem. The
|
||||
exporter can use flags information to simplify how much of the
|
||||
:cdata:`Py_buffer` structure is filled in with non-default values and/or
|
||||
raise an error if the object can't support a simpler view of its memory.
|
||||
|
||||
0 is returned on success and -1 on error.
|
||||
|
||||
The following table gives possible values to the *flags* arguments.
|
||||
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| Flag | Description |
|
||||
+==============================+===================================================+
|
||||
| :cmacro:`PyBUF_SIMPLE` | This is the default flag state. The returned |
|
||||
| | buffer may or may not have writable memory. The |
|
||||
| | format of the data will be assumed to be unsigned |
|
||||
| | bytes. This is a "stand-alone" flag constant. It |
|
||||
| | never needs to be '|'d to the others. The exporter|
|
||||
| | will raise an error if it cannot provide such a |
|
||||
| | contiguous buffer of bytes. |
|
||||
| | |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_WRITABLE` | The returned buffer must be writable. If it is |
|
||||
| | not writable, then raise an error. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_STRIDES` | This implies :cmacro:`PyBUF_ND`. The returned |
|
||||
| | buffer must provide strides information (i.e. the |
|
||||
| | strides cannot be NULL). This would be used when |
|
||||
| | the consumer can handle strided, discontiguous |
|
||||
| | arrays. Handling strides automatically assumes |
|
||||
| | you can handle shape. The exporter can raise an |
|
||||
| | error if a strided representation of the data is |
|
||||
| | not possible (i.e. without the suboffsets). |
|
||||
| | |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_ND` | The returned buffer must provide shape |
|
||||
| | information. The memory will be assumed C-style |
|
||||
| | contiguous (last dimension varies the |
|
||||
| | fastest). The exporter may raise an error if it |
|
||||
| | cannot provide this kind of contiguous buffer. If |
|
||||
| | this is not given then shape will be *NULL*. |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
|:cmacro:`PyBUF_C_CONTIGUOUS` | These flags indicate that the contiguity returned |
|
||||
|:cmacro:`PyBUF_F_CONTIGUOUS` | buffer must be respectively, C-contiguous (last |
|
||||
|:cmacro:`PyBUF_ANY_CONTIGUOUS`| dimension varies the fastest), Fortran contiguous |
|
||||
| | (first dimension varies the fastest) or either |
|
||||
| | one. All of these flags imply |
|
||||
| | :cmacro:`PyBUF_STRIDES` and guarantee that the |
|
||||
| | strides buffer info structure will be filled in |
|
||||
| | correctly. |
|
||||
| | |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_INDIRECT` | This flag indicates the returned buffer must have |
|
||||
| | suboffsets information (which can be NULL if no |
|
||||
| | suboffsets are needed). This can be used when |
|
||||
| | the consumer can handle indirect array |
|
||||
| | referencing implied by these suboffsets. This |
|
||||
| | implies :cmacro:`PyBUF_STRIDES`. |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_FORMAT` | The returned buffer must have true format |
|
||||
| | information if this flag is provided. This would |
|
||||
| | be used when the consumer is going to be checking |
|
||||
| | for what 'kind' of data is actually stored. An |
|
||||
| | exporter should always be able to provide this |
|
||||
| | information if requested. If format is not |
|
||||
| | explicitly requested then the format must be |
|
||||
| | returned as *NULL* (which means ``'B'``, or |
|
||||
| | unsigned bytes) |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_STRIDED` | This is equivalent to ``(PyBUF_STRIDES | |
|
||||
| | PyBUF_WRITABLE)``. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_STRIDED_RO` | This is equivalent to ``(PyBUF_STRIDES)``. |
|
||||
| | |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_RECORDS` | This is equivalent to ``(PyBUF_STRIDES | |
|
||||
| | PyBUF_FORMAT | PyBUF_WRITABLE)``. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_RECORDS_RO` | This is equivalent to ``(PyBUF_STRIDES | |
|
||||
| | PyBUF_FORMAT)``. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_FULL` | This is equivalent to ``(PyBUF_INDIRECT | |
|
||||
| | PyBUF_FORMAT | PyBUF_WRITABLE)``. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_FULL_RO` | This is equivalent to ``(PyBUF_INDIRECT | |
|
||||
| | PyBUF_FORMAT)``. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_CONTIG` | This is equivalent to ``(PyBUF_ND | |
|
||||
| | PyBUF_WRITABLE)``. |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
| :cmacro:`PyBUF_CONTIG_RO` | This is equivalent to ``(PyBUF_ND)``. |
|
||||
| | |
|
||||
+------------------------------+---------------------------------------------------+
|
||||
|
||||
|
||||
.. cfunction:: void PyBuffer_Release(Py_buffer *view)
|
||||
|
||||
Release the buffer *view*. This should be called when the buffer
|
||||
is no longer being used as it may free memory from it.
|
||||
|
||||
|
||||
.. cfunction:: Py_ssize_t PyBuffer_SizeFromFormat(const char *)
|
||||
|
||||
Return the implied :cdata:`~Py_buffer.itemsize` from the struct-stype
|
||||
:cdata:`~Py_buffer.format`.
|
||||
|
||||
|
||||
.. cfunction:: int PyObject_CopyToObject(PyObject *obj, void *buf, Py_ssize_t len, char fortran)
|
||||
|
||||
Copy *len* bytes of data pointed to by the contiguous chunk of memory
|
||||
pointed to by *buf* into the buffer exported by obj. The buffer must of
|
||||
course be writable. Return 0 on success and return -1 and raise an error
|
||||
on failure. If the object does not have a writable buffer, then an error
|
||||
is raised. If *fortran* is ``'F'``, then if the object is
|
||||
multi-dimensional, then the data will be copied into the array in
|
||||
Fortran-style (first dimension varies the fastest). If *fortran* is
|
||||
``'C'``, then the data will be copied into the array in C-style (last
|
||||
dimension varies the fastest). If *fortran* is ``'A'``, then it does not
|
||||
matter and the copy will be made in whatever way is more efficient.
|
||||
|
||||
|
||||
.. cfunction:: int PyBuffer_IsContiguous(Py_buffer *view, char fortran)
|
||||
|
||||
Return 1 if the memory defined by the *view* is C-style (*fortran* is
|
||||
``'C'``) or Fortran-style (*fortran* is ``'F'``) contiguous or either one
|
||||
(*fortran* is ``'A'``). Return 0 otherwise.
|
||||
|
||||
|
||||
.. cfunction:: void PyBuffer_FillContiguousStrides(int ndim, Py_ssize_t *shape, Py_ssize_t *strides, Py_ssize_t itemsize, char fortran)
|
||||
|
||||
Fill the *strides* array with byte-strides of a contiguous (C-style if
|
||||
*fortran* is ``'C'`` or Fortran-style if *fortran* is ``'F'`` array of the
|
||||
given shape with the given number of bytes per element.
|
||||
|
||||
|
||||
.. cfunction:: int PyBuffer_FillInfo(Py_buffer *view, PyObject *obj, void *buf, Py_ssize_t len, int readonly, int infoflags)
|
||||
|
||||
Fill in a buffer-info structure, *view*, correctly for an exporter that can
|
||||
only share a contiguous chunk of memory of "unsigned bytes" of the given
|
||||
length. Return 0 on success and -1 (with raising an error) on error.
|
||||
|
||||
|
||||
Old-style buffer objects
|
||||
========================
|
||||
|
||||
.. index:: single: PyBufferProcs
|
||||
|
||||
More information on the buffer interface is provided in the section
|
||||
:ref:`buffer-structs`, under the description for :ctype:`PyBufferProcs`.
|
||||
|
||||
A "buffer object" is defined in the :file:`bufferobject.h` header (included by
|
||||
:file:`Python.h`). These objects look very similar to string objects at the
|
||||
Python programming level: they support slicing, indexing, concatenation, and
|
||||
some other standard string operations. However, their data can come from one
|
||||
of two sources: from a block of memory, or from another object which exports
|
||||
the buffer interface.
|
||||
|
||||
Buffer objects are useful as a way to expose the data from another object's
|
||||
buffer interface to the Python programmer. They can also be used as a
|
||||
zero-copy slicing mechanism. Using their ability to reference a block of
|
||||
memory, it is possible to expose any data to the Python programmer quite
|
||||
easily. The memory could be a large, constant array in a C extension, it could
|
||||
be a raw block of memory for manipulation before passing to an operating
|
||||
system library, or it could be used to pass around structured data in its
|
||||
native, in-memory format.
|
||||
|
||||
|
||||
.. ctype:: PyBufferObject
|
||||
|
||||
This subtype of :ctype:`PyObject` represents a buffer object.
|
||||
|
||||
|
||||
.. cvar:: PyTypeObject PyBuffer_Type
|
||||
|
||||
.. index:: single: BufferType (in module types)
|
||||
|
||||
The instance of :ctype:`PyTypeObject` which represents the Python buffer type;
|
||||
it is the same object as ``buffer`` and ``types.BufferType`` in the Python
|
||||
layer. .
|
||||
|
||||
|
||||
.. cvar:: int Py_END_OF_BUFFER
|
||||
|
||||
This constant may be passed as the *size* parameter to
|
||||
:cfunc:`PyBuffer_FromObject` or :cfunc:`PyBuffer_FromReadWriteObject`. It
|
||||
indicates that the new :ctype:`PyBufferObject` should refer to *base*
|
||||
object from the specified *offset* to the end of its exported buffer.
|
||||
Using this enables the caller to avoid querying the *base* object for its
|
||||
length.
|
||||
|
||||
|
||||
.. cfunction:: int PyBuffer_Check(PyObject *p)
|
||||
|
||||
Return true if the argument has type :cdata:`PyBuffer_Type`.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyBuffer_FromObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
|
||||
|
||||
Return a new read-only buffer object. This raises :exc:`TypeError` if
|
||||
*base* doesn't support the read-only buffer protocol or doesn't provide
|
||||
exactly one buffer segment, or it raises :exc:`ValueError` if *offset* is
|
||||
less than zero. The buffer will hold a reference to the *base* object, and
|
||||
the buffer's contents will refer to the *base* object's buffer interface,
|
||||
starting as position *offset* and extending for *size* bytes. If *size* is
|
||||
:const:`Py_END_OF_BUFFER`, then the new buffer's contents extend to the
|
||||
length of the *base* object's exported buffer data.
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int` type for *offset* and *size*. This
|
||||
might require changes in your code for properly supporting 64-bit
|
||||
systems.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyBuffer_FromReadWriteObject(PyObject *base, Py_ssize_t offset, Py_ssize_t size)
|
||||
|
||||
Return a new writable buffer object. Parameters and exceptions are similar
|
||||
to those for :cfunc:`PyBuffer_FromObject`. If the *base* object does not
|
||||
export the writeable buffer protocol, then :exc:`TypeError` is raised.
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int` type for *offset* and *size*. This
|
||||
might require changes in your code for properly supporting 64-bit
|
||||
systems.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyBuffer_FromMemory(void *ptr, Py_ssize_t size)
|
||||
|
||||
Return a new read-only buffer object that reads from a specified location
|
||||
in memory, with a specified size. The caller is responsible for ensuring
|
||||
that the memory buffer, passed in as *ptr*, is not deallocated while the
|
||||
returned buffer object exists. Raises :exc:`ValueError` if *size* is less
|
||||
than zero. Note that :const:`Py_END_OF_BUFFER` may *not* be passed for the
|
||||
*size* parameter; :exc:`ValueError` will be raised in that case.
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int` type for *size*. This might require
|
||||
changes in your code for properly supporting 64-bit systems.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyBuffer_FromReadWriteMemory(void *ptr, Py_ssize_t size)
|
||||
|
||||
Similar to :cfunc:`PyBuffer_FromMemory`, but the returned buffer is
|
||||
writable.
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int` type for *size*. This might require
|
||||
changes in your code for properly supporting 64-bit systems.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyBuffer_New(Py_ssize_t size)
|
||||
|
||||
Return a new writable buffer object that maintains its own memory buffer of
|
||||
*size* bytes. :exc:`ValueError` is returned if *size* is not zero or
|
||||
positive. Note that the memory buffer (as returned by
|
||||
:cfunc:`PyObject_AsWriteBuffer`) is not specifically aligned.
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int` type for *size*. This might require
|
||||
changes in your code for properly supporting 64-bit systems.
|
@ -1,87 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _bytearrayobjects:
|
||||
|
||||
Byte Array Objects
|
||||
------------------
|
||||
|
||||
.. index:: object: bytearray
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
|
||||
.. ctype:: PyByteArrayObject
|
||||
|
||||
This subtype of :ctype:`PyObject` represents a Python bytearray object.
|
||||
|
||||
|
||||
.. cvar:: PyTypeObject PyByteArray_Type
|
||||
|
||||
This instance of :ctype:`PyTypeObject` represents the Python bytearray type;
|
||||
it is the same object as ``bytearray`` in the Python layer.
|
||||
|
||||
Type check macros
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. cfunction:: int PyByteArray_Check(PyObject *o)
|
||||
|
||||
Return true if the object *o* is a bytearray object or an instance of a
|
||||
subtype of the bytearray type.
|
||||
|
||||
|
||||
.. cfunction:: int PyByteArray_CheckExact(PyObject *o)
|
||||
|
||||
Return true if the object *o* is a bytearray object, but not an instance of a
|
||||
subtype of the bytearray type.
|
||||
|
||||
|
||||
Direct API functions
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. cfunction:: PyObject* PyByteArray_FromObject(PyObject *o)
|
||||
|
||||
Return a new bytearray object from any object, *o*, that implements the
|
||||
buffer protocol.
|
||||
|
||||
.. XXX expand about the buffer protocol, at least somewhere
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyByteArray_FromStringAndSize(const char *string, Py_ssize_t len)
|
||||
|
||||
Create a new bytearray object from *string* and its length, *len*. On
|
||||
failure, *NULL* is returned.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyByteArray_Concat(PyObject *a, PyObject *b)
|
||||
|
||||
Concat bytearrays *a* and *b* and return a new bytearray with the result.
|
||||
|
||||
|
||||
.. cfunction:: Py_ssize_t PyByteArray_Size(PyObject *bytearray)
|
||||
|
||||
Return the size of *bytearray* after checking for a *NULL* pointer.
|
||||
|
||||
|
||||
.. cfunction:: char* PyByteArray_AsString(PyObject *bytearray)
|
||||
|
||||
Return the contents of *bytearray* as a char array after checking for a
|
||||
*NULL* pointer.
|
||||
|
||||
|
||||
.. cfunction:: int PyByteArray_Resize(PyObject *bytearray, Py_ssize_t len)
|
||||
|
||||
Resize the internal buffer of *bytearray* to *len*.
|
||||
|
||||
Macros
|
||||
^^^^^^
|
||||
|
||||
These macros trade safety for speed and they don't check pointers.
|
||||
|
||||
.. cfunction:: char* PyByteArray_AS_STRING(PyObject *bytearray)
|
||||
|
||||
Macro version of :cfunc:`PyByteArray_AsString`.
|
||||
|
||||
|
||||
.. cfunction:: Py_ssize_t PyByteArray_GET_SIZE(PyObject *bytearray)
|
||||
|
||||
Macro version of :cfunc:`PyByteArray_Size`.
|
@ -1,62 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _cell-objects:
|
||||
|
||||
Cell Objects
|
||||
------------
|
||||
|
||||
"Cell" objects are used to implement variables referenced by multiple scopes.
|
||||
For each such variable, a cell object is created to store the value; the local
|
||||
variables of each stack frame that references the value contains a reference to
|
||||
the cells from outer scopes which also use that variable. When the value is
|
||||
accessed, the value contained in the cell is used instead of the cell object
|
||||
itself. This de-referencing of the cell object requires support from the
|
||||
generated byte-code; these are not automatically de-referenced when accessed.
|
||||
Cell objects are not likely to be useful elsewhere.
|
||||
|
||||
|
||||
.. ctype:: PyCellObject
|
||||
|
||||
The C structure used for cell objects.
|
||||
|
||||
|
||||
.. cvar:: PyTypeObject PyCell_Type
|
||||
|
||||
The type object corresponding to cell objects.
|
||||
|
||||
|
||||
.. cfunction:: int PyCell_Check(ob)
|
||||
|
||||
Return true if *ob* is a cell object; *ob* must not be *NULL*.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyCell_New(PyObject *ob)
|
||||
|
||||
Create and return a new cell object containing the value *ob*. The parameter may
|
||||
be *NULL*.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyCell_Get(PyObject *cell)
|
||||
|
||||
Return the contents of the cell *cell*.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyCell_GET(PyObject *cell)
|
||||
|
||||
Return the contents of the cell *cell*, but without checking that *cell* is
|
||||
non-*NULL* and a cell object.
|
||||
|
||||
|
||||
.. cfunction:: int PyCell_Set(PyObject *cell, PyObject *value)
|
||||
|
||||
Set the contents of the cell object *cell* to *value*. This releases the
|
||||
reference to any current content of the cell. *value* may be *NULL*. *cell*
|
||||
must be non-*NULL*; if it is not a cell object, ``-1`` will be returned. On
|
||||
success, ``0`` will be returned.
|
||||
|
||||
|
||||
.. cfunction:: void PyCell_SET(PyObject *cell, PyObject *value)
|
||||
|
||||
Sets the value of the cell object *cell* to *value*. No reference counts are
|
||||
adjusted, and no checks are made for safety; *cell* must be non-*NULL* and must
|
||||
be a cell object.
|
@ -1,65 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _classobjects:
|
||||
|
||||
Class and Instance Objects
|
||||
--------------------------
|
||||
|
||||
.. index:: object: class
|
||||
|
||||
Note that the class objects described here represent old-style classes, which
|
||||
will go away in Python 3. When creating new types for extension modules, you
|
||||
will want to work with type objects (section :ref:`typeobjects`).
|
||||
|
||||
|
||||
.. ctype:: PyClassObject
|
||||
|
||||
The C structure of the objects used to describe built-in classes.
|
||||
|
||||
|
||||
.. cvar:: PyObject* PyClass_Type
|
||||
|
||||
.. index:: single: ClassType (in module types)
|
||||
|
||||
This is the type object for class objects; it is the same object as
|
||||
``types.ClassType`` in the Python layer.
|
||||
|
||||
|
||||
.. cfunction:: int PyClass_Check(PyObject *o)
|
||||
|
||||
Return true if the object *o* is a class object, including instances of types
|
||||
derived from the standard class object. Return false in all other cases.
|
||||
|
||||
|
||||
.. cfunction:: int PyClass_IsSubclass(PyObject *klass, PyObject *base)
|
||||
|
||||
Return true if *klass* is a subclass of *base*. Return false in all other cases.
|
||||
|
||||
|
||||
.. index:: object: instance
|
||||
|
||||
There are very few functions specific to instance objects.
|
||||
|
||||
|
||||
.. cvar:: PyTypeObject PyInstance_Type
|
||||
|
||||
Type object for class instances.
|
||||
|
||||
|
||||
.. cfunction:: int PyInstance_Check(PyObject *obj)
|
||||
|
||||
Return true if *obj* is an instance.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyInstance_New(PyObject *class, PyObject *arg, PyObject *kw)
|
||||
|
||||
Create a new instance of a specific class. The parameters *arg* and *kw* are
|
||||
used as the positional and keyword parameters to the object's constructor.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyInstance_NewRaw(PyObject *class, PyObject *dict)
|
||||
|
||||
Create a new instance of a specific class without calling its constructor.
|
||||
*class* is the class of new object. The *dict* parameter will be used as the
|
||||
object's :attr:`__dict__`; if *NULL*, a new dictionary will be created for the
|
||||
instance.
|
@ -1,56 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _cobjects:
|
||||
|
||||
CObjects
|
||||
--------
|
||||
|
||||
.. index:: object: CObject
|
||||
|
||||
Refer to :ref:`using-cobjects` for more information on using these objects.
|
||||
|
||||
|
||||
.. ctype:: PyCObject
|
||||
|
||||
This subtype of :ctype:`PyObject` represents an opaque value, useful for C
|
||||
extension modules who need to pass an opaque value (as a :ctype:`void\*`
|
||||
pointer) through Python code to other C code. It is often used to make a C
|
||||
function pointer defined in one module available to other modules, so the
|
||||
regular import mechanism can be used to access C APIs defined in dynamically
|
||||
loaded modules.
|
||||
|
||||
|
||||
.. cfunction:: int PyCObject_Check(PyObject *p)
|
||||
|
||||
Return true if its argument is a :ctype:`PyCObject`.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyCObject_FromVoidPtr(void* cobj, void (*destr)(void *))
|
||||
|
||||
Create a :ctype:`PyCObject` from the ``void *`` *cobj*. The *destr* function
|
||||
will be called when the object is reclaimed, unless it is *NULL*.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyCObject_FromVoidPtrAndDesc(void* cobj, void* desc, void (*destr)(void *, void *))
|
||||
|
||||
Create a :ctype:`PyCObject` from the :ctype:`void \*` *cobj*. The *destr*
|
||||
function will be called when the object is reclaimed. The *desc* argument can
|
||||
be used to pass extra callback data for the destructor function.
|
||||
|
||||
|
||||
.. cfunction:: void* PyCObject_AsVoidPtr(PyObject* self)
|
||||
|
||||
Return the object :ctype:`void \*` that the :ctype:`PyCObject` *self* was
|
||||
created with.
|
||||
|
||||
|
||||
.. cfunction:: void* PyCObject_GetDesc(PyObject* self)
|
||||
|
||||
Return the description :ctype:`void \*` that the :ctype:`PyCObject` *self* was
|
||||
created with.
|
||||
|
||||
|
||||
.. cfunction:: int PyCObject_SetVoidPtr(PyObject* self, void* cobj)
|
||||
|
||||
Set the void pointer inside *self* to *cobj*. The :ctype:`PyCObject` must not
|
||||
have an associated destructor. Return true on success, false on failure.
|
@ -1,132 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _complexobjects:
|
||||
|
||||
Complex Number Objects
|
||||
----------------------
|
||||
|
||||
.. index:: object: complex number
|
||||
|
||||
Python's complex number objects are implemented as two distinct types when
|
||||
viewed from the C API: one is the Python object exposed to Python programs, and
|
||||
the other is a C structure which represents the actual complex number value.
|
||||
The API provides functions for working with both.
|
||||
|
||||
|
||||
Complex Numbers as C Structures
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Note that the functions which accept these structures as parameters and return
|
||||
them as results do so *by value* rather than dereferencing them through
|
||||
pointers. This is consistent throughout the API.
|
||||
|
||||
|
||||
.. ctype:: Py_complex
|
||||
|
||||
The C structure which corresponds to the value portion of a Python complex
|
||||
number object. Most of the functions for dealing with complex number objects
|
||||
use structures of this type as input or output values, as appropriate. It is
|
||||
defined as::
|
||||
|
||||
typedef struct {
|
||||
double real;
|
||||
double imag;
|
||||
} Py_complex;
|
||||
|
||||
|
||||
.. cfunction:: Py_complex _Py_c_sum(Py_complex left, Py_complex right)
|
||||
|
||||
Return the sum of two complex numbers, using the C :ctype:`Py_complex`
|
||||
representation.
|
||||
|
||||
|
||||
.. cfunction:: Py_complex _Py_c_diff(Py_complex left, Py_complex right)
|
||||
|
||||
Return the difference between two complex numbers, using the C
|
||||
:ctype:`Py_complex` representation.
|
||||
|
||||
|
||||
.. cfunction:: Py_complex _Py_c_neg(Py_complex complex)
|
||||
|
||||
Return the negation of the complex number *complex*, using the C
|
||||
:ctype:`Py_complex` representation.
|
||||
|
||||
|
||||
.. cfunction:: Py_complex _Py_c_prod(Py_complex left, Py_complex right)
|
||||
|
||||
Return the product of two complex numbers, using the C :ctype:`Py_complex`
|
||||
representation.
|
||||
|
||||
|
||||
.. cfunction:: Py_complex _Py_c_quot(Py_complex dividend, Py_complex divisor)
|
||||
|
||||
Return the quotient of two complex numbers, using the C :ctype:`Py_complex`
|
||||
representation.
|
||||
|
||||
|
||||
.. cfunction:: Py_complex _Py_c_pow(Py_complex num, Py_complex exp)
|
||||
|
||||
Return the exponentiation of *num* by *exp*, using the C :ctype:`Py_complex`
|
||||
representation.
|
||||
|
||||
|
||||
Complex Numbers as Python Objects
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
.. ctype:: PyComplexObject
|
||||
|
||||
This subtype of :ctype:`PyObject` represents a Python complex number object.
|
||||
|
||||
|
||||
.. cvar:: PyTypeObject PyComplex_Type
|
||||
|
||||
This instance of :ctype:`PyTypeObject` represents the Python complex number
|
||||
type. It is the same object as ``complex`` and ``types.ComplexType``.
|
||||
|
||||
|
||||
.. cfunction:: int PyComplex_Check(PyObject *p)
|
||||
|
||||
Return true if its argument is a :ctype:`PyComplexObject` or a subtype of
|
||||
:ctype:`PyComplexObject`.
|
||||
|
||||
.. versionchanged:: 2.2
|
||||
Allowed subtypes to be accepted.
|
||||
|
||||
|
||||
.. cfunction:: int PyComplex_CheckExact(PyObject *p)
|
||||
|
||||
Return true if its argument is a :ctype:`PyComplexObject`, but not a subtype of
|
||||
:ctype:`PyComplexObject`.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyComplex_FromCComplex(Py_complex v)
|
||||
|
||||
Create a new Python complex number object from a C :ctype:`Py_complex` value.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyComplex_FromDoubles(double real, double imag)
|
||||
|
||||
Return a new :ctype:`PyComplexObject` object from *real* and *imag*.
|
||||
|
||||
|
||||
.. cfunction:: double PyComplex_RealAsDouble(PyObject *op)
|
||||
|
||||
Return the real part of *op* as a C :ctype:`double`.
|
||||
|
||||
|
||||
.. cfunction:: double PyComplex_ImagAsDouble(PyObject *op)
|
||||
|
||||
Return the imaginary part of *op* as a C :ctype:`double`.
|
||||
|
||||
|
||||
.. cfunction:: Py_complex PyComplex_AsCComplex(PyObject *op)
|
||||
|
||||
Return the :ctype:`Py_complex` value of the complex number *op*.
|
||||
|
||||
.. versionchanged:: 2.6
|
||||
If *op* is not a Python complex number object but has a :meth:`__complex__`
|
||||
method, this method will first be called to convert *op* to a Python complex
|
||||
number object.
|
@ -1,107 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
|
||||
.. _concrete:
|
||||
|
||||
**********************
|
||||
Concrete Objects Layer
|
||||
**********************
|
||||
|
||||
The functions in this chapter are specific to certain Python object types.
|
||||
Passing them an object of the wrong type is not a good idea; if you receive an
|
||||
object from a Python program and you are not sure that it has the right type,
|
||||
you must perform a type check first; for example, to check that an object is a
|
||||
dictionary, use :cfunc:`PyDict_Check`. The chapter is structured like the
|
||||
"family tree" of Python object types.
|
||||
|
||||
.. warning::
|
||||
|
||||
While the functions described in this chapter carefully check the type of the
|
||||
objects which are passed in, many of them do not check for *NULL* being passed
|
||||
instead of a valid object. Allowing *NULL* to be passed in can cause memory
|
||||
access violations and immediate termination of the interpreter.
|
||||
|
||||
|
||||
.. _fundamental:
|
||||
|
||||
Fundamental Objects
|
||||
===================
|
||||
|
||||
This section describes Python type objects and the singleton object ``None``.
|
||||
|
||||
.. toctree::
|
||||
|
||||
type.rst
|
||||
none.rst
|
||||
|
||||
|
||||
.. _numericobjects:
|
||||
|
||||
Numeric Objects
|
||||
===============
|
||||
|
||||
.. index:: object: numeric
|
||||
|
||||
.. toctree::
|
||||
|
||||
int.rst
|
||||
bool.rst
|
||||
long.rst
|
||||
float.rst
|
||||
complex.rst
|
||||
|
||||
|
||||
.. _sequenceobjects:
|
||||
|
||||
Sequence Objects
|
||||
================
|
||||
|
||||
.. index:: object: sequence
|
||||
|
||||
Generic operations on sequence objects were discussed in the previous chapter;
|
||||
this section deals with the specific kinds of sequence objects that are
|
||||
intrinsic to the Python language.
|
||||
|
||||
.. toctree::
|
||||
|
||||
bytearray.rst
|
||||
string.rst
|
||||
unicode.rst
|
||||
buffer.rst
|
||||
tuple.rst
|
||||
list.rst
|
||||
|
||||
|
||||
.. _mapobjects:
|
||||
|
||||
Mapping Objects
|
||||
===============
|
||||
|
||||
.. index:: object: mapping
|
||||
|
||||
.. toctree::
|
||||
|
||||
dict.rst
|
||||
|
||||
|
||||
.. _otherobjects:
|
||||
|
||||
Other Objects
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
|
||||
class.rst
|
||||
function.rst
|
||||
method.rst
|
||||
file.rst
|
||||
module.rst
|
||||
iterator.rst
|
||||
descriptor.rst
|
||||
slice.rst
|
||||
weakref.rst
|
||||
cobject.rst
|
||||
cell.rst
|
||||
gen.rst
|
||||
datetime.rst
|
||||
set.rst
|
@ -1,103 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _string-conversion:
|
||||
|
||||
String conversion and formatting
|
||||
================================
|
||||
|
||||
Functions for number conversion and formatted string output.
|
||||
|
||||
|
||||
.. cfunction:: int PyOS_snprintf(char *str, size_t size, const char *format, ...)
|
||||
|
||||
Output not more than *size* bytes to *str* according to the format string
|
||||
*format* and the extra arguments. See the Unix man page :manpage:`snprintf(2)`.
|
||||
|
||||
|
||||
.. cfunction:: int PyOS_vsnprintf(char *str, size_t size, const char *format, va_list va)
|
||||
|
||||
Output not more than *size* bytes to *str* according to the format string
|
||||
*format* and the variable argument list *va*. Unix man page
|
||||
:manpage:`vsnprintf(2)`.
|
||||
|
||||
:cfunc:`PyOS_snprintf` and :cfunc:`PyOS_vsnprintf` wrap the Standard C library
|
||||
functions :cfunc:`snprintf` and :cfunc:`vsnprintf`. Their purpose is to
|
||||
guarantee consistent behavior in corner cases, which the Standard C functions do
|
||||
not.
|
||||
|
||||
The wrappers ensure that *str*[*size*-1] is always ``'\0'`` upon return. They
|
||||
never write more than *size* bytes (including the trailing ``'\0'`` into str.
|
||||
Both functions require that ``str != NULL``, ``size > 0`` and ``format !=
|
||||
NULL``.
|
||||
|
||||
If the platform doesn't have :cfunc:`vsnprintf` and the buffer size needed to
|
||||
avoid truncation exceeds *size* by more than 512 bytes, Python aborts with a
|
||||
*Py_FatalError*.
|
||||
|
||||
The return value (*rv*) for these functions should be interpreted as follows:
|
||||
|
||||
* When ``0 <= rv < size``, the output conversion was successful and *rv*
|
||||
characters were written to *str* (excluding the trailing ``'\0'`` byte at
|
||||
*str*[*rv*]).
|
||||
|
||||
* When ``rv >= size``, the output conversion was truncated and a buffer with
|
||||
``rv + 1`` bytes would have been needed to succeed. *str*[*size*-1] is ``'\0'``
|
||||
in this case.
|
||||
|
||||
* When ``rv < 0``, "something bad happened." *str*[*size*-1] is ``'\0'`` in
|
||||
this case too, but the rest of *str* is undefined. The exact cause of the error
|
||||
depends on the underlying platform.
|
||||
|
||||
The following functions provide locale-independent string to number conversions.
|
||||
|
||||
|
||||
.. cfunction:: double PyOS_ascii_strtod(const char *nptr, char **endptr)
|
||||
|
||||
Convert a string to a :ctype:`double`. This function behaves like the Standard C
|
||||
function :cfunc:`strtod` does in the C locale. It does this without changing the
|
||||
current locale, since that would not be thread-safe.
|
||||
|
||||
:cfunc:`PyOS_ascii_strtod` should typically be used for reading configuration
|
||||
files or other non-user input that should be locale independent.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
See the Unix man page :manpage:`strtod(2)` for details.
|
||||
|
||||
|
||||
.. cfunction:: char * PyOS_ascii_formatd(char *buffer, size_t buf_len, const char *format, double d)
|
||||
|
||||
Convert a :ctype:`double` to a string using the ``'.'`` as the decimal
|
||||
separator. *format* is a :cfunc:`printf`\ -style format string specifying the
|
||||
number format. Allowed conversion characters are ``'e'``, ``'E'``, ``'f'``,
|
||||
``'F'``, ``'g'`` and ``'G'``.
|
||||
|
||||
The return value is a pointer to *buffer* with the converted string or NULL if
|
||||
the conversion failed.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: double PyOS_ascii_atof(const char *nptr)
|
||||
|
||||
Convert a string to a :ctype:`double` in a locale-independent way.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
See the Unix man page :manpage:`atof(2)` for details.
|
||||
|
||||
|
||||
.. cfunction:: char * PyOS_stricmp(char *s1, char *s2)
|
||||
|
||||
Case insensitive comparison of strings. The function works almost
|
||||
identically to :cfunc:`strcmp` except that it ignores the case.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
|
||||
.. cfunction:: char * PyOS_strnicmp(char *s1, char *s2, Py_ssize_t size)
|
||||
|
||||
Case insensitive comparison of strings. The function works almost
|
||||
identically to :cfunc:`strncmp` except that it ignores the case.
|
||||
|
||||
.. versionadded:: 2.6
|
@ -1,239 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _datetimeobjects:
|
||||
|
||||
DateTime Objects
|
||||
----------------
|
||||
|
||||
Various date and time objects are supplied by the :mod:`datetime` module.
|
||||
Before using any of these functions, the header file :file:`datetime.h` must be
|
||||
included in your source (note that this is not included by :file:`Python.h`),
|
||||
and the macro :cmacro:`PyDateTime_IMPORT` must be invoked, usually as part of
|
||||
the module initialisation function. The macro puts a pointer to a C structure
|
||||
into a static variable, :cdata:`PyDateTimeAPI`, that is used by the following
|
||||
macros.
|
||||
|
||||
Type-check macros:
|
||||
|
||||
|
||||
.. cfunction:: int PyDate_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_DateType` or a subtype of
|
||||
:cdata:`PyDateTime_DateType`. *ob* must not be *NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDate_CheckExact(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_DateType`. *ob* must not be
|
||||
*NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_DateTimeType` or a subtype of
|
||||
:cdata:`PyDateTime_DateTimeType`. *ob* must not be *NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_CheckExact(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_DateTimeType`. *ob* must not
|
||||
be *NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyTime_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_TimeType` or a subtype of
|
||||
:cdata:`PyDateTime_TimeType`. *ob* must not be *NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyTime_CheckExact(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_TimeType`. *ob* must not be
|
||||
*NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDelta_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_DeltaType` or a subtype of
|
||||
:cdata:`PyDateTime_DeltaType`. *ob* must not be *NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDelta_CheckExact(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_DeltaType`. *ob* must not be
|
||||
*NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyTZInfo_Check(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_TZInfoType` or a subtype of
|
||||
:cdata:`PyDateTime_TZInfoType`. *ob* must not be *NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyTZInfo_CheckExact(PyObject *ob)
|
||||
|
||||
Return true if *ob* is of type :cdata:`PyDateTime_TZInfoType`. *ob* must not be
|
||||
*NULL*.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
Macros to create objects:
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDate_FromDate(int year, int month, int day)
|
||||
|
||||
Return a ``datetime.date`` object with the specified year, month and day.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDateTime_FromDateAndTime(int year, int month, int day, int hour, int minute, int second, int usecond)
|
||||
|
||||
Return a ``datetime.datetime`` object with the specified year, month, day, hour,
|
||||
minute, second and microsecond.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyTime_FromTime(int hour, int minute, int second, int usecond)
|
||||
|
||||
Return a ``datetime.time`` object with the specified hour, minute, second and
|
||||
microsecond.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDelta_FromDSU(int days, int seconds, int useconds)
|
||||
|
||||
Return a ``datetime.timedelta`` object representing the given number of days,
|
||||
seconds and microseconds. Normalization is performed so that the resulting
|
||||
number of microseconds and seconds lie in the ranges documented for
|
||||
``datetime.timedelta`` objects.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
Macros to extract fields from date objects. The argument must be an instance of
|
||||
:cdata:`PyDateTime_Date`, including subclasses (such as
|
||||
:cdata:`PyDateTime_DateTime`). The argument must not be *NULL*, and the type is
|
||||
not checked:
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_GET_YEAR(PyDateTime_Date *o)
|
||||
|
||||
Return the year, as a positive int.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_GET_MONTH(PyDateTime_Date *o)
|
||||
|
||||
Return the month, as an int from 1 through 12.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_GET_DAY(PyDateTime_Date *o)
|
||||
|
||||
Return the day, as an int from 1 through 31.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
Macros to extract fields from datetime objects. The argument must be an
|
||||
instance of :cdata:`PyDateTime_DateTime`, including subclasses. The argument
|
||||
must not be *NULL*, and the type is not checked:
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_DATE_GET_HOUR(PyDateTime_DateTime *o)
|
||||
|
||||
Return the hour, as an int from 0 through 23.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_DATE_GET_MINUTE(PyDateTime_DateTime *o)
|
||||
|
||||
Return the minute, as an int from 0 through 59.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_DATE_GET_SECOND(PyDateTime_DateTime *o)
|
||||
|
||||
Return the second, as an int from 0 through 59.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_DATE_GET_MICROSECOND(PyDateTime_DateTime *o)
|
||||
|
||||
Return the microsecond, as an int from 0 through 999999.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
Macros to extract fields from time objects. The argument must be an instance of
|
||||
:cdata:`PyDateTime_Time`, including subclasses. The argument must not be *NULL*,
|
||||
and the type is not checked:
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_TIME_GET_HOUR(PyDateTime_Time *o)
|
||||
|
||||
Return the hour, as an int from 0 through 23.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_TIME_GET_MINUTE(PyDateTime_Time *o)
|
||||
|
||||
Return the minute, as an int from 0 through 59.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_TIME_GET_SECOND(PyDateTime_Time *o)
|
||||
|
||||
Return the second, as an int from 0 through 59.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: int PyDateTime_TIME_GET_MICROSECOND(PyDateTime_Time *o)
|
||||
|
||||
Return the microsecond, as an int from 0 through 999999.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
Macros for the convenience of modules implementing the DB API:
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDateTime_FromTimestamp(PyObject *args)
|
||||
|
||||
Create and return a new ``datetime.datetime`` object given an argument tuple
|
||||
suitable for passing to ``datetime.datetime.fromtimestamp()``.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDate_FromTimestamp(PyObject *args)
|
||||
|
||||
Create and return a new ``datetime.date`` object given an argument tuple
|
||||
suitable for passing to ``datetime.date.fromtimestamp()``.
|
||||
|
||||
.. versionadded:: 2.4
|
@ -1,55 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _descriptor-objects:
|
||||
|
||||
Descriptor Objects
|
||||
------------------
|
||||
|
||||
"Descriptors" are objects that describe some attribute of an object. They are
|
||||
found in the dictionary of type objects.
|
||||
|
||||
|
||||
.. cvar:: PyTypeObject PyProperty_Type
|
||||
|
||||
The type object for the built-in descriptor types.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDescr_NewGetSet(PyTypeObject *type, struct PyGetSetDef *getset)
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDescr_NewMember(PyTypeObject *type, struct PyMemberDef *meth)
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDescr_NewMethod(PyTypeObject *type, struct PyMethodDef *meth)
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDescr_NewWrapper(PyTypeObject *type, struct wrapperbase *wrapper, void *wrapped)
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDescr_NewClassMethod(PyTypeObject *type, PyMethodDef *method)
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
|
||||
.. cfunction:: int PyDescr_IsData(PyObject *descr)
|
||||
|
||||
Return true if the descriptor objects *descr* describes a data attribute, or
|
||||
false if it describes a method. *descr* must be a descriptor object; there is
|
||||
no error checking.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyWrapper_New(PyObject *, PyObject *)
|
||||
|
||||
.. versionadded:: 2.2
|
@ -1,233 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
.. _dictobjects:
|
||||
|
||||
Dictionary Objects
|
||||
------------------
|
||||
|
||||
.. index:: object: dictionary
|
||||
|
||||
|
||||
.. ctype:: PyDictObject
|
||||
|
||||
This subtype of :ctype:`PyObject` represents a Python dictionary object.
|
||||
|
||||
|
||||
.. cvar:: PyTypeObject PyDict_Type
|
||||
|
||||
.. index::
|
||||
single: DictType (in module types)
|
||||
single: DictionaryType (in module types)
|
||||
|
||||
This instance of :ctype:`PyTypeObject` represents the Python dictionary
|
||||
type. This is exposed to Python programs as ``dict`` and
|
||||
``types.DictType``.
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_Check(PyObject *p)
|
||||
|
||||
Return true if *p* is a dict object or an instance of a subtype of the dict
|
||||
type.
|
||||
|
||||
.. versionchanged:: 2.2
|
||||
Allowed subtypes to be accepted.
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_CheckExact(PyObject *p)
|
||||
|
||||
Return true if *p* is a dict object, but not an instance of a subtype of
|
||||
the dict type.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDict_New()
|
||||
|
||||
Return a new empty dictionary, or *NULL* on failure.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDictProxy_New(PyObject *dict)
|
||||
|
||||
Return a proxy object for a mapping which enforces read-only behavior.
|
||||
This is normally used to create a proxy to prevent modification of the
|
||||
dictionary for non-dynamic class types.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: void PyDict_Clear(PyObject *p)
|
||||
|
||||
Empty an existing dictionary of all key-value pairs.
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_Contains(PyObject *p, PyObject *key)
|
||||
|
||||
Determine if dictionary *p* contains *key*. If an item in *p* is matches
|
||||
*key*, return ``1``, otherwise return ``0``. On error, return ``-1``.
|
||||
This is equivalent to the Python expression ``key in p``.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDict_Copy(PyObject *p)
|
||||
|
||||
Return a new dictionary that contains the same key-value pairs as *p*.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_SetItem(PyObject *p, PyObject *key, PyObject *val)
|
||||
|
||||
Insert *value* into the dictionary *p* with a key of *key*. *key* must be
|
||||
:term:`hashable`; if it isn't, :exc:`TypeError` will be raised. Return
|
||||
``0`` on success or ``-1`` on failure.
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_SetItemString(PyObject *p, const char *key, PyObject *val)
|
||||
|
||||
.. index:: single: PyString_FromString()
|
||||
|
||||
Insert *value* into the dictionary *p* using *key* as a key. *key* should
|
||||
be a :ctype:`char\*`. The key object is created using
|
||||
``PyString_FromString(key)``. Return ``0`` on success or ``-1`` on
|
||||
failure.
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_DelItem(PyObject *p, PyObject *key)
|
||||
|
||||
Remove the entry in dictionary *p* with key *key*. *key* must be hashable;
|
||||
if it isn't, :exc:`TypeError` is raised. Return ``0`` on success or ``-1``
|
||||
on failure.
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_DelItemString(PyObject *p, char *key)
|
||||
|
||||
Remove the entry in dictionary *p* which has a key specified by the string
|
||||
*key*. Return ``0`` on success or ``-1`` on failure.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDict_GetItem(PyObject *p, PyObject *key)
|
||||
|
||||
Return the object from dictionary *p* which has a key *key*. Return *NULL*
|
||||
if the key *key* is not present, but *without* setting an exception.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDict_GetItemString(PyObject *p, const char *key)
|
||||
|
||||
This is the same as :cfunc:`PyDict_GetItem`, but *key* is specified as a
|
||||
:ctype:`char\*`, rather than a :ctype:`PyObject\*`.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDict_Items(PyObject *p)
|
||||
|
||||
Return a :ctype:`PyListObject` containing all the items from the
|
||||
dictionary, as in the dictionary method :meth:`dict.items`.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDict_Keys(PyObject *p)
|
||||
|
||||
Return a :ctype:`PyListObject` containing all the keys from the dictionary,
|
||||
as in the dictionary method :meth:`dict.keys`.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyDict_Values(PyObject *p)
|
||||
|
||||
Return a :ctype:`PyListObject` containing all the values from the
|
||||
dictionary *p*, as in the dictionary method :meth:`dict.values`.
|
||||
|
||||
|
||||
.. cfunction:: Py_ssize_t PyDict_Size(PyObject *p)
|
||||
|
||||
.. index:: builtin: len
|
||||
|
||||
Return the number of items in the dictionary. This is equivalent to
|
||||
``len(p)`` on a dictionary.
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function returned an :ctype:`int` type. This might require changes
|
||||
in your code for properly supporting 64-bit systems.
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_Next(PyObject *p, Py_ssize_t *ppos, PyObject **pkey, PyObject **pvalue)
|
||||
|
||||
Iterate over all key-value pairs in the dictionary *p*. The
|
||||
:ctype:`Py_ssize_t` referred to by *ppos* must be initialized to ``0``
|
||||
prior to the first call to this function to start the iteration; the
|
||||
function returns true for each pair in the dictionary, and false once all
|
||||
pairs have been reported. The parameters *pkey* and *pvalue* should either
|
||||
point to :ctype:`PyObject\*` variables that will be filled in with each key
|
||||
and value, respectively, or may be *NULL*. Any references returned through
|
||||
them are borrowed. *ppos* should not be altered during iteration. Its
|
||||
value represents offsets within the internal dictionary structure, and
|
||||
since the structure is sparse, the offsets are not consecutive.
|
||||
|
||||
For example::
|
||||
|
||||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
|
||||
while (PyDict_Next(self->dict, &pos, &key, &value)) {
|
||||
/* do something interesting with the values... */
|
||||
...
|
||||
}
|
||||
|
||||
The dictionary *p* should not be mutated during iteration. It is safe
|
||||
(since Python 2.1) to modify the values of the keys as you iterate over the
|
||||
dictionary, but only so long as the set of keys does not change. For
|
||||
example::
|
||||
|
||||
PyObject *key, *value;
|
||||
Py_ssize_t pos = 0;
|
||||
|
||||
while (PyDict_Next(self->dict, &pos, &key, &value)) {
|
||||
int i = PyInt_AS_LONG(value) + 1;
|
||||
PyObject *o = PyInt_FromLong(i);
|
||||
if (o == NULL)
|
||||
return -1;
|
||||
if (PyDict_SetItem(self->dict, key, o) < 0) {
|
||||
Py_DECREF(o);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(o);
|
||||
}
|
||||
|
||||
.. versionchanged:: 2.5
|
||||
This function used an :ctype:`int *` type for *ppos*. This might require
|
||||
changes in your code for properly supporting 64-bit systems.
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_Merge(PyObject *a, PyObject *b, int override)
|
||||
|
||||
Iterate over mapping object *b* adding key-value pairs to dictionary *a*.
|
||||
*b* may be a dictionary, or any object supporting :func:`PyMapping_Keys`
|
||||
and :func:`PyObject_GetItem`. If *override* is true, existing pairs in *a*
|
||||
will be replaced if a matching key is found in *b*, otherwise pairs will
|
||||
only be added if there is not a matching key in *a*. Return ``0`` on
|
||||
success or ``-1`` if an exception was raised.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_Update(PyObject *a, PyObject *b)
|
||||
|
||||
This is the same as ``PyDict_Merge(a, b, 1)`` in C, or ``a.update(b)`` in
|
||||
Python. Return ``0`` on success or ``-1`` if an exception was raised.
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. cfunction:: int PyDict_MergeFromSeq2(PyObject *a, PyObject *seq2, int override)
|
||||
|
||||
Update or merge into dictionary *a*, from the key-value pairs in *seq2*.
|
||||
*seq2* must be an iterable object producing iterable objects of length 2,
|
||||
viewed as key-value pairs. In case of duplicate keys, the last wins if
|
||||
*override* is true, else the first wins. Return ``0`` on success or ``-1``
|
||||
if an exception was raised. Equivalent Python (except for the return
|
||||
value)::
|
||||
|
||||
def PyDict_MergeFromSeq2(a, seq2, override):
|
||||
for key, value in seq2:
|
||||
if override or key not in a:
|
||||
a[key] = value
|
||||
|
||||
.. versionadded:: 2.2
|
@ -1,591 +0,0 @@
|
||||
.. highlightlang:: c
|
||||
|
||||
|
||||
.. _exceptionhandling:
|
||||
|
||||
******************
|
||||
Exception Handling
|
||||
******************
|
||||
|
||||
The functions described in this chapter will let you handle and raise Python
|
||||
exceptions. It is important to understand some of the basics of Python
|
||||
exception handling. It works somewhat like the Unix :cdata:`errno` variable:
|
||||
there is a global indicator (per thread) of the last error that occurred. Most
|
||||
functions don't clear this on success, but will set it to indicate the cause of
|
||||
the error on failure. Most functions also return an error indicator, usually
|
||||
*NULL* if they are supposed to return a pointer, or ``-1`` if they return an
|
||||
integer (exception: the :cfunc:`PyArg_\*` functions return ``1`` for success and
|
||||
``0`` for failure).
|
||||
|
||||
When a function must fail because some function it called failed, it generally
|
||||
doesn't set the error indicator; the function it called already set it. It is
|
||||
responsible for either handling the error and clearing the exception or
|
||||
returning after cleaning up any resources it holds (such as object references or
|
||||
memory allocations); it should *not* continue normally if it is not prepared to
|
||||
handle the error. If returning due to an error, it is important to indicate to
|
||||
the caller that an error has been set. If the error is not handled or carefully
|
||||
propagated, additional calls into the Python/C API may not behave as intended
|
||||
and may fail in mysterious ways.
|
||||
|
||||
.. index::
|
||||
single: exc_type (in module sys)
|
||||
single: exc_value (in module sys)
|
||||
single: exc_traceback (in module sys)
|
||||
|
||||
The error indicator consists of three Python objects corresponding to the
|
||||
Python variables ``sys.exc_type``, ``sys.exc_value`` and ``sys.exc_traceback``.
|
||||
API functions exist to interact with the error indicator in various ways. There
|
||||
is a separate error indicator for each thread.
|
||||
|
||||
.. XXX Order of these should be more thoughtful.
|
||||
Either alphabetical or some kind of structure.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_PrintEx(int set_sys_last_vars)
|
||||
|
||||
Print a standard traceback to ``sys.stderr`` and clear the error indicator.
|
||||
Call this function only when the error indicator is set. (Otherwise it will
|
||||
cause a fatal error!)
|
||||
|
||||
If *set_sys_last_vars* is nonzero, the variables :data:`sys.last_type`,
|
||||
:data:`sys.last_value` and :data:`sys.last_traceback` will be set to the
|
||||
type, value and traceback of the printed exception, respectively.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_Print()
|
||||
|
||||
Alias for ``PyErr_PrintEx(1)``.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_Occurred()
|
||||
|
||||
Test whether the error indicator is set. If set, return the exception *type*
|
||||
(the first argument to the last call to one of the :cfunc:`PyErr_Set\*`
|
||||
functions or to :cfunc:`PyErr_Restore`). If not set, return *NULL*. You do not
|
||||
own a reference to the return value, so you do not need to :cfunc:`Py_DECREF`
|
||||
it.
|
||||
|
||||
.. note::
|
||||
|
||||
Do not compare the return value to a specific exception; use
|
||||
:cfunc:`PyErr_ExceptionMatches` instead, shown below. (The comparison could
|
||||
easily fail since the exception may be an instance instead of a class, in the
|
||||
case of a class exception, or it may the a subclass of the expected exception.)
|
||||
|
||||
|
||||
.. cfunction:: int PyErr_ExceptionMatches(PyObject *exc)
|
||||
|
||||
Equivalent to ``PyErr_GivenExceptionMatches(PyErr_Occurred(), exc)``. This
|
||||
should only be called when an exception is actually set; a memory access
|
||||
violation will occur if no exception has been raised.
|
||||
|
||||
|
||||
.. cfunction:: int PyErr_GivenExceptionMatches(PyObject *given, PyObject *exc)
|
||||
|
||||
Return true if the *given* exception matches the exception in *exc*. If
|
||||
*exc* is a class object, this also returns true when *given* is an instance
|
||||
of a subclass. If *exc* is a tuple, all exceptions in the tuple (and
|
||||
recursively in subtuples) are searched for a match.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_NormalizeException(PyObject**exc, PyObject**val, PyObject**tb)
|
||||
|
||||
Under certain circumstances, the values returned by :cfunc:`PyErr_Fetch` below
|
||||
can be "unnormalized", meaning that ``*exc`` is a class object but ``*val`` is
|
||||
not an instance of the same class. This function can be used to instantiate
|
||||
the class in that case. If the values are already normalized, nothing happens.
|
||||
The delayed normalization is implemented to improve performance.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_Clear()
|
||||
|
||||
Clear the error indicator. If the error indicator is not set, there is no
|
||||
effect.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_Fetch(PyObject **ptype, PyObject **pvalue, PyObject **ptraceback)
|
||||
|
||||
Retrieve the error indicator into three variables whose addresses are passed.
|
||||
If the error indicator is not set, set all three variables to *NULL*. If it is
|
||||
set, it will be cleared and you own a reference to each object retrieved. The
|
||||
value and traceback object may be *NULL* even when the type object is not.
|
||||
|
||||
.. note::
|
||||
|
||||
This function is normally only used by code that needs to handle exceptions or
|
||||
by code that needs to save and restore the error indicator temporarily.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_Restore(PyObject *type, PyObject *value, PyObject *traceback)
|
||||
|
||||
Set the error indicator from the three objects. If the error indicator is
|
||||
already set, it is cleared first. If the objects are *NULL*, the error
|
||||
indicator is cleared. Do not pass a *NULL* type and non-*NULL* value or
|
||||
traceback. The exception type should be a class. Do not pass an invalid
|
||||
exception type or value. (Violating these rules will cause subtle problems
|
||||
later.) This call takes away a reference to each object: you must own a
|
||||
reference to each object before the call and after the call you no longer own
|
||||
these references. (If you don't understand this, don't use this function. I
|
||||
warned you.)
|
||||
|
||||
.. note::
|
||||
|
||||
This function is normally only used by code that needs to save and restore the
|
||||
error indicator temporarily; use :cfunc:`PyErr_Fetch` to save the current
|
||||
exception state.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_SetString(PyObject *type, const char *message)
|
||||
|
||||
This is the most common way to set the error indicator. The first argument
|
||||
specifies the exception type; it is normally one of the standard exceptions,
|
||||
e.g. :cdata:`PyExc_RuntimeError`. You need not increment its reference count.
|
||||
The second argument is an error message; it is converted to a string object.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_SetObject(PyObject *type, PyObject *value)
|
||||
|
||||
This function is similar to :cfunc:`PyErr_SetString` but lets you specify an
|
||||
arbitrary Python object for the "value" of the exception.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_Format(PyObject *exception, const char *format, ...)
|
||||
|
||||
This function sets the error indicator and returns *NULL*. *exception* should be
|
||||
a Python exception (class, not an instance). *format* should be a string,
|
||||
containing format codes, similar to :cfunc:`printf`. The ``width.precision``
|
||||
before a format code is parsed, but the width part is ignored.
|
||||
|
||||
.. % This should be exactly the same as the table in PyString_FromFormat.
|
||||
.. % One should just refer to the other.
|
||||
.. % The descriptions for %zd and %zu are wrong, but the truth is complicated
|
||||
.. % because not all compilers support the %z width modifier -- we fake it
|
||||
.. % when necessary via interpolating PY_FORMAT_SIZE_T.
|
||||
.. % %u, %lu, %zu should have "new in Python 2.5" blurbs.
|
||||
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| Format Characters | Type | Comment |
|
||||
+===================+===============+================================+
|
||||
| :attr:`%%` | *n/a* | The literal % character. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%c` | int | A single character, |
|
||||
| | | represented as an C int. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%d` | int | Exactly equivalent to |
|
||||
| | | ``printf("%d")``. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%u` | unsigned int | Exactly equivalent to |
|
||||
| | | ``printf("%u")``. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%ld` | long | Exactly equivalent to |
|
||||
| | | ``printf("%ld")``. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%lu` | unsigned long | Exactly equivalent to |
|
||||
| | | ``printf("%lu")``. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%zd` | Py_ssize_t | Exactly equivalent to |
|
||||
| | | ``printf("%zd")``. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%zu` | size_t | Exactly equivalent to |
|
||||
| | | ``printf("%zu")``. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%i` | int | Exactly equivalent to |
|
||||
| | | ``printf("%i")``. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%x` | int | Exactly equivalent to |
|
||||
| | | ``printf("%x")``. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%s` | char\* | A null-terminated C character |
|
||||
| | | array. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
| :attr:`%p` | void\* | The hex representation of a C |
|
||||
| | | pointer. Mostly equivalent to |
|
||||
| | | ``printf("%p")`` except that |
|
||||
| | | it is guaranteed to start with |
|
||||
| | | the literal ``0x`` regardless |
|
||||
| | | of what the platform's |
|
||||
| | | ``printf`` yields. |
|
||||
+-------------------+---------------+--------------------------------+
|
||||
|
||||
An unrecognized format character causes all the rest of the format string to be
|
||||
copied as-is to the result string, and any extra arguments discarded.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_SetNone(PyObject *type)
|
||||
|
||||
This is a shorthand for ``PyErr_SetObject(type, Py_None)``.
|
||||
|
||||
|
||||
.. cfunction:: int PyErr_BadArgument()
|
||||
|
||||
This is a shorthand for ``PyErr_SetString(PyExc_TypeError, message)``, where
|
||||
*message* indicates that a built-in operation was invoked with an illegal
|
||||
argument. It is mostly for internal use.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_NoMemory()
|
||||
|
||||
This is a shorthand for ``PyErr_SetNone(PyExc_MemoryError)``; it returns *NULL*
|
||||
so an object allocation function can write ``return PyErr_NoMemory();`` when it
|
||||
runs out of memory.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_SetFromErrno(PyObject *type)
|
||||
|
||||
.. index:: single: strerror()
|
||||
|
||||
This is a convenience function to raise an exception when a C library function
|
||||
has returned an error and set the C variable :cdata:`errno`. It constructs a
|
||||
tuple object whose first item is the integer :cdata:`errno` value and whose
|
||||
second item is the corresponding error message (gotten from :cfunc:`strerror`),
|
||||
and then calls ``PyErr_SetObject(type, object)``. On Unix, when the
|
||||
:cdata:`errno` value is :const:`EINTR`, indicating an interrupted system call,
|
||||
this calls :cfunc:`PyErr_CheckSignals`, and if that set the error indicator,
|
||||
leaves it set to that. The function always returns *NULL*, so a wrapper
|
||||
function around a system call can write ``return PyErr_SetFromErrno(type);``
|
||||
when the system call returns an error.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_SetFromErrnoWithFilename(PyObject *type, const char *filename)
|
||||
|
||||
Similar to :cfunc:`PyErr_SetFromErrno`, with the additional behavior that if
|
||||
*filename* is not *NULL*, it is passed to the constructor of *type* as a third
|
||||
parameter. In the case of exceptions such as :exc:`IOError` and :exc:`OSError`,
|
||||
this is used to define the :attr:`filename` attribute of the exception instance.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_SetFromWindowsErr(int ierr)
|
||||
|
||||
This is a convenience function to raise :exc:`WindowsError`. If called with
|
||||
*ierr* of :cdata:`0`, the error code returned by a call to :cfunc:`GetLastError`
|
||||
is used instead. It calls the Win32 function :cfunc:`FormatMessage` to retrieve
|
||||
the Windows description of error code given by *ierr* or :cfunc:`GetLastError`,
|
||||
then it constructs a tuple object whose first item is the *ierr* value and whose
|
||||
second item is the corresponding error message (gotten from
|
||||
:cfunc:`FormatMessage`), and then calls ``PyErr_SetObject(PyExc_WindowsError,
|
||||
object)``. This function always returns *NULL*. Availability: Windows.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_SetExcFromWindowsErr(PyObject *type, int ierr)
|
||||
|
||||
Similar to :cfunc:`PyErr_SetFromWindowsErr`, with an additional parameter
|
||||
specifying the exception type to be raised. Availability: Windows.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_SetFromWindowsErrWithFilename(int ierr, const char *filename)
|
||||
|
||||
Similar to :cfunc:`PyErr_SetFromWindowsErr`, with the additional behavior that
|
||||
if *filename* is not *NULL*, it is passed to the constructor of
|
||||
:exc:`WindowsError` as a third parameter. Availability: Windows.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_SetExcFromWindowsErrWithFilename(PyObject *type, int ierr, char *filename)
|
||||
|
||||
Similar to :cfunc:`PyErr_SetFromWindowsErrWithFilename`, with an additional
|
||||
parameter specifying the exception type to be raised. Availability: Windows.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_BadInternalCall()
|
||||
|
||||
This is a shorthand for ``PyErr_SetString(PyExc_SystemError, message)``,
|
||||
where *message* indicates that an internal operation (e.g. a Python/C API
|
||||
function) was invoked with an illegal argument. It is mostly for internal
|
||||
use.
|
||||
|
||||
|
||||
.. cfunction:: int PyErr_WarnEx(PyObject *category, char *message, int stacklevel)
|
||||
|
||||
Issue a warning message. The *category* argument is a warning category (see
|
||||
below) or *NULL*; the *message* argument is a message string. *stacklevel* is a
|
||||
positive number giving a number of stack frames; the warning will be issued from
|
||||
the currently executing line of code in that stack frame. A *stacklevel* of 1
|
||||
is the function calling :cfunc:`PyErr_WarnEx`, 2 is the function above that,
|
||||
and so forth.
|
||||
|
||||
This function normally prints a warning message to *sys.stderr*; however, it is
|
||||
also possible that the user has specified that warnings are to be turned into
|
||||
errors, and in that case this will raise an exception. It is also possible that
|
||||
the function raises an exception because of a problem with the warning machinery
|
||||
(the implementation imports the :mod:`warnings` module to do the heavy lifting).
|
||||
The return value is ``0`` if no exception is raised, or ``-1`` if an exception
|
||||
is raised. (It is not possible to determine whether a warning message is
|
||||
actually printed, nor what the reason is for the exception; this is
|
||||
intentional.) If an exception is raised, the caller should do its normal
|
||||
exception handling (for example, :cfunc:`Py_DECREF` owned references and return
|
||||
an error value).
|
||||
|
||||
Warning categories must be subclasses of :cdata:`Warning`; the default warning
|
||||
category is :cdata:`RuntimeWarning`. The standard Python warning categories are
|
||||
available as global variables whose names are ``PyExc_`` followed by the Python
|
||||
exception name. These have the type :ctype:`PyObject\*`; they are all class
|
||||
objects. Their names are :cdata:`PyExc_Warning`, :cdata:`PyExc_UserWarning`,
|
||||
:cdata:`PyExc_UnicodeWarning`, :cdata:`PyExc_DeprecationWarning`,
|
||||
:cdata:`PyExc_SyntaxWarning`, :cdata:`PyExc_RuntimeWarning`, and
|
||||
:cdata:`PyExc_FutureWarning`. :cdata:`PyExc_Warning` is a subclass of
|
||||
:cdata:`PyExc_Exception`; the other warning categories are subclasses of
|
||||
:cdata:`PyExc_Warning`.
|
||||
|
||||
For information about warning control, see the documentation for the
|
||||
:mod:`warnings` module and the :option:`-W` option in the command line
|
||||
documentation. There is no C API for warning control.
|
||||
|
||||
|
||||
.. cfunction:: int PyErr_Warn(PyObject *category, char *message)
|
||||
|
||||
Issue a warning message. The *category* argument is a warning category (see
|
||||
below) or *NULL*; the *message* argument is a message string. The warning will
|
||||
appear to be issued from the function calling :cfunc:`PyErr_Warn`, equivalent to
|
||||
calling :cfunc:`PyErr_WarnEx` with a *stacklevel* of 1.
|
||||
|
||||
Deprecated; use :cfunc:`PyErr_WarnEx` instead.
|
||||
|
||||
|
||||
.. cfunction:: int PyErr_WarnExplicit(PyObject *category, const char *message, const char *filename, int lineno, const char *module, PyObject *registry)
|
||||
|
||||
Issue a warning message with explicit control over all warning attributes. This
|
||||
is a straightforward wrapper around the Python function
|
||||
:func:`warnings.warn_explicit`, see there for more information. The *module*
|
||||
and *registry* arguments may be set to *NULL* to get the default effect
|
||||
described there.
|
||||
|
||||
|
||||
.. cfunction:: int PyErr_WarnPy3k(char *message, int stacklevel)
|
||||
|
||||
Issue a :exc:`DeprecationWarning` with the given *message* and *stacklevel*
|
||||
if the :cdata:`Py_Py3kWarningFlag` flag is enabled.
|
||||
|
||||
.. versionadded:: 2.6
|
||||
|
||||
|
||||
.. cfunction:: int PyErr_CheckSignals()
|
||||
|
||||
.. index::
|
||||
module: signal
|
||||
single: SIGINT
|
||||
single: KeyboardInterrupt (built-in exception)
|
||||
|
||||
This function interacts with Python's signal handling. It checks whether a
|
||||
signal has been sent to the processes and if so, invokes the corresponding
|
||||
signal handler. If the :mod:`signal` module is supported, this can invoke a
|
||||
signal handler written in Python. In all cases, the default effect for
|
||||
:const:`SIGINT` is to raise the :exc:`KeyboardInterrupt` exception. If an
|
||||
exception is raised the error indicator is set and the function returns ``-1``;
|
||||
otherwise the function returns ``0``. The error indicator may or may not be
|
||||
cleared if it was previously set.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_SetInterrupt()
|
||||
|
||||
.. index::
|
||||
single: SIGINT
|
||||
single: KeyboardInterrupt (built-in exception)
|
||||
|
||||
This function simulates the effect of a :const:`SIGINT` signal arriving --- the
|
||||
next time :cfunc:`PyErr_CheckSignals` is called, :exc:`KeyboardInterrupt` will
|
||||
be raised. It may be called without holding the interpreter lock.
|
||||
|
||||
.. % XXX This was described as obsolete, but is used in
|
||||
.. % thread.interrupt_main() (used from IDLE), so it's still needed.
|
||||
|
||||
|
||||
.. cfunction:: int PySignal_SetWakeupFd(int fd)
|
||||
|
||||
This utility function specifies a file descriptor to which a ``'\0'`` byte will
|
||||
be written whenever a signal is received. It returns the previous such file
|
||||
descriptor. The value ``-1`` disables the feature; this is the initial state.
|
||||
This is equivalent to :func:`signal.set_wakeup_fd` in Python, but without any
|
||||
error checking. *fd* should be a valid file descriptor. The function should
|
||||
only be called from the main thread.
|
||||
|
||||
|
||||
.. cfunction:: PyObject* PyErr_NewException(char *name, PyObject *base, PyObject *dict)
|
||||
|
||||
This utility function creates and returns a new exception object. The *name*
|
||||
argument must be the name of the new exception, a C string of the form
|
||||
``module.class``. The *base* and *dict* arguments are normally *NULL*. This
|
||||
creates a class object derived from :exc:`Exception` (accessible in C as
|
||||
:cdata:`PyExc_Exception`).
|
||||
|
||||
The :attr:`__module__` attribute of the new class is set to the first part (up
|
||||
to the last dot) of the *name* argument, and the class name is set to the last
|
||||
part (after the last dot). The *base* argument can be used to specify alternate
|
||||
base classes; it can either be only one class or a tuple of classes. The *dict*
|
||||
argument can be used to specify a dictionary of class variables and methods.
|
||||
|
||||
|
||||
.. cfunction:: void PyErr_WriteUnraisable(PyObject *obj)
|
||||
|
||||
This utility function prints a warning message to ``sys.stderr`` when an
|
||||
exception has been set but it is impossible for the interpreter to actually
|
||||
raise the exception. It is used, for example, when an exception occurs in an
|
||||
:meth:`__del__` method.
|
||||
|
||||
The function is called with a single argument *obj* that identifies the context
|
||||
in which the unraisable exception occurred. The repr of *obj* will be printed in
|
||||
the warning message.
|
||||
|
||||
|
||||
Recursion Control
|
||||
=================
|
||||
|
||||
These two functions provide a way to perform safe recursive calls at the C
|
||||
level, both in the core and in extension modules. They are needed if the
|
||||
recursive code does not necessarily invoke Python code (which tracks its
|
||||
recursion depth automatically).
|
||||
|
||||
.. cfunction:: int Py_EnterRecursiveCall(char *where)
|
||||
|
||||
Marks a point where a recursive C-level call is about to be performed.
|
||||
|
||||
If :const:`USE_STACKCHECK` is defined, this function checks if the the OS
|
||||
stack overflowed using :cfunc:`PyOS_CheckStack`. In this is the case, it
|
||||
sets a :exc:`MemoryError` and returns a nonzero value.
|
||||
|
||||
The function then checks if the recursion limit is reached. If this is the
|
||||
case, a :exc:`RuntimeError` is set and a nonzero value is returned.
|
||||
Otherwise, zero is returned.
|
||||
|
||||
*where* should be a string such as ``" in instance check"`` to be
|
||||
concatenated to the :exc:`RuntimeError` message caused by the recursion depth
|
||||
limit.
|
||||
|
||||
.. cfunction:: void Py_LeaveRecursiveCall()
|
||||
|
||||
Ends a :cfunc:`Py_EnterRecursiveCall`. Must be called once for each
|
||||
*successful* invocation of :cfunc:`Py_EnterRecursiveCall`.
|
||||
|
||||
|
||||
.. _standardexceptions:
|
||||
|
||||
Standard Exceptions
|
||||
===================
|
||||
|
||||
All standard Python exceptions are available as global variables whose names are
|
||||
``PyExc_`` followed by the Python exception name. These have the type
|
||||
:ctype:`PyObject\*`; they are all class objects. For completeness, here are all
|
||||
the variables:
|
||||
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| C Name | Python Name | Notes |
|
||||
+====================================+============================+==========+
|
||||
| :cdata:`PyExc_BaseException` | :exc:`BaseException` | (1), (4) |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_Exception` | :exc:`Exception` | \(1) |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_StandardError` | :exc:`StandardError` | \(1) |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_ArithmeticError` | :exc:`ArithmeticError` | \(1) |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_LookupError` | :exc:`LookupError` | \(1) |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_AssertionError` | :exc:`AssertionError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_AttributeError` | :exc:`AttributeError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_EOFError` | :exc:`EOFError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_EnvironmentError` | :exc:`EnvironmentError` | \(1) |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_FloatingPointError` | :exc:`FloatingPointError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_IOError` | :exc:`IOError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_ImportError` | :exc:`ImportError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_IndexError` | :exc:`IndexError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_KeyError` | :exc:`KeyError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_KeyboardInterrupt` | :exc:`KeyboardInterrupt` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_MemoryError` | :exc:`MemoryError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_NameError` | :exc:`NameError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_NotImplementedError` | :exc:`NotImplementedError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_OSError` | :exc:`OSError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_OverflowError` | :exc:`OverflowError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_ReferenceError` | :exc:`ReferenceError` | \(2) |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_RuntimeError` | :exc:`RuntimeError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_SyntaxError` | :exc:`SyntaxError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_SystemError` | :exc:`SystemError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_SystemExit` | :exc:`SystemExit` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_TypeError` | :exc:`TypeError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_ValueError` | :exc:`ValueError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_WindowsError` | :exc:`WindowsError` | \(3) |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
| :cdata:`PyExc_ZeroDivisionError` | :exc:`ZeroDivisionError` | |
|
||||
+------------------------------------+----------------------------+----------+
|
||||
|
||||
.. index::
|
||||
single: PyExc_BaseException
|
||||
single: PyExc_Exception
|
||||
single: PyExc_StandardError
|
||||
single: PyExc_ArithmeticError
|
||||
single: PyExc_LookupError
|
||||
single: PyExc_AssertionError
|
||||
single: PyExc_AttributeError
|
||||
single: PyExc_EOFError
|
||||
single: PyExc_EnvironmentError
|
||||
single: PyExc_FloatingPointError
|
||||
single: PyExc_IOError
|
||||
single: PyExc_ImportError
|
||||
single: PyExc_IndexError
|
||||
single: PyExc_KeyError
|
||||
single: PyExc_KeyboardInterrupt
|
||||
single: PyExc_MemoryError
|
||||
single: PyExc_NameError
|
||||
single: PyExc_NotImplementedError
|
||||
single: PyExc_OSError
|
||||
single: PyExc_OverflowError
|
||||
single: PyExc_ReferenceError
|
||||
single: PyExc_RuntimeError
|
||||
single: PyExc_SyntaxError
|
||||
single: PyExc_SystemError
|
||||
single: PyExc_SystemExit
|
||||
single: PyExc_TypeError
|
||||
single: PyExc_ValueError
|
||||
single: PyExc_WindowsError
|
||||
single: PyExc_ZeroDivisionError
|
||||
|
||||
Notes:
|
||||
|
||||
(1)
|
||||
This is a base class for other standard exceptions.
|
||||
|
||||
(2)
|
||||
This is the same as :exc:`weakref.ReferenceError`.
|
||||
|
||||
(3)
|
||||
Only defined on Windows; protect code that uses this by testing that the
|
||||
preprocessor macro ``MS_WINDOWS`` is defined.
|
||||
|
||||
(4)
|
||||
.. versionadded:: 2.5
|
||||
|
||||
|
||||
Deprecation of String Exceptions
|
||||
================================
|
||||
|
||||
.. index:: single: BaseException (built-in exception)
|
||||
|
||||
All exceptions built into Python or provided in the standard library are derived
|
||||
from :exc:`BaseException`.
|
||||
|
||||
String exceptions are still supported in the interpreter to allow existing code
|
||||
to run unmodified, but this will also change in a future release.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user