[Checkins] SVN: z3c.filetype/trunk/s code cleanup, added license
Nikolay Kim
fafhrd at datacom.kz
Wed Dec 19 00:10:11 EST 2007
Log message for revision 82354:
code cleanup, added license
Changed:
UU z3c.filetype/trunk/setup.py
U z3c.filetype/trunk/src/z3c/filetype/README.txt
U z3c.filetype/trunk/src/z3c/filetype/adapters.py
U z3c.filetype/trunk/src/z3c/filetype/api.py
U z3c.filetype/trunk/src/z3c/filetype/configure.zcml
U z3c.filetype/trunk/src/z3c/filetype/event.py
U z3c.filetype/trunk/src/z3c/filetype/interfaces/__init__.py
U z3c.filetype/trunk/src/z3c/filetype/interfaces/filetypes.py
U z3c.filetype/trunk/src/z3c/filetype/magic.py
U z3c.filetype/trunk/src/z3c/filetype/size.py
U z3c.filetype/trunk/src/z3c/filetype/tests.py
-=-
Modified: z3c.filetype/trunk/setup.py
===================================================================
--- z3c.filetype/trunk/setup.py 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/setup.py 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,20 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Setup for z3c.filetype package
+
+$Id$
+"""
+import sys, os
from setuptools import setup, find_packages
+version = '1.2.0'
+
setup(
- name="z3c.filetype",
- version="1.1.0",
+ name='z3c.filetype',
+ version=version,
+ description = 'Filetype Package',
+ long_description=(
+ 'Detailed Dcoumentation\n' +
+ '======================\n'
+ + '\n\n' +
+ read('src', 'z3c', 'filetype', 'README.txt')
+ + '\n\n' +
+ read('CHANGES.txt')
+ ),
+ classifiers=[
+ 'Development Status :: 5 - Production/Stable',
+ 'Environment :: Web Environment',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: Zope Public License',
+ 'Programming Language :: Python',
+ 'Natural Language :: English',
+ 'Operating System :: OS Independent',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Framework :: Zope3'],
+ author='Zope Community',
+ author_email='zope3-dev at zope.org',
+ url='http://svn.zope.org/z3c.filetype',
+ license='ZPL 2.1',
namespace_packages=["z3c"],
packages=find_packages("src"),
package_dir={"": "src"},
include_package_data=True,
install_requires=[
"setuptools",
- "zope.cachedescriptors",
"zope.component",
+ "zope.interface",
"zope.contenttype",
"zope.event",
"zope.i18nmessageid",
- "zope.interface",
"zope.lifecycleevent",
"zope.proxy",
"zope.schema",
Property changes on: z3c.filetype/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
+ Id
Modified: z3c.filetype/trunk/src/z3c/filetype/README.txt
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/README.txt 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/README.txt 2007-12-19 05:10:09 UTC (rev 82354)
@@ -229,5 +229,3 @@
>>> notify(ObjectModifiedEvent(foo))
>>> ISized(foo).sizeForDisplay().mapping
{'width': '1600', 'height': '1200', 'size': '499'}
-
-
Modified: z3c.filetype/trunk/src/z3c/filetype/adapters.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/adapters.py 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/adapters.py 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,13 +1,29 @@
-from zope.cachedescriptors.property import Lazy
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+from zope import interface, component
+
import interfaces
from interfaces import filetypes
-from zope import interface
-from zope import component
+
class TypedFileType(object):
-
+ component.adapts(filetypes.ITypedFile)
interface.implements(interfaces.IFileType)
- component.adapts(filetypes.ITypedFile)
def __init__(self, context):
self.context = context
@@ -22,4 +38,3 @@
mt = iface.queryTaggedValue(filetypes.MT)
if mt is not None:
return mt
-
Modified: z3c.filetype/trunk/src/z3c/filetype/api.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/api.py 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/api.py 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,71 +1,97 @@
-from z3c.filetype import magic
-import interfaces
-from interfaces import filetypes
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+from StringIO import StringIO
+from zope import interface, component, event
+from zope.proxy import removeAllProxies
from zope.contenttype import guess_content_type
-from zope import interface, component
+from zope.lifecycleevent.interfaces import IObjectCreatedEvent
from zope.lifecycleevent.interfaces import IObjectModifiedEvent
-from zope.lifecycleevent.interfaces import IObjectCreatedEvent
-from zope.event import notify
-from event import FileTypeModifiedEvent
+from z3c.filetype import magic, interfaces
+from z3c.filetype.interfaces import filetypes
+from z3c.filetype.event import FileTypeModifiedEvent
+
+
magicFile = magic.MagicFile()
-def byMimeType(t):
+def byMimeType(mt):
"""returns interfaces implemented by mimeType"""
-
- ifaces = [iface for name, iface in vars(filetypes).items() \
+ ifaces = [iface for name, iface in vars(filetypes).items()
if name.startswith("I")]
res = InterfaceSet()
for iface in ifaces:
mtm = iface.queryTaggedValue(filetypes.MTM)
if mtm is not None:
- if mtm.match(t):
+ if mtm.match(mt):
res.add(iface)
return res
+
def getInterfacesFor(file=None, filename=None, mimeType=None):
-
"""returns a sequence of interfaces that are provided by file like
- objects (file argument) with an optional filename as name or
- mimeType as mime-type
+ objects (file argument) or string with an optional
+ filename as name or mimeType as mime-type
"""
-
ifaces = set()
if file is not None:
- types = magicFile.detect(file)
- for t in types:
- ifaces.update(byMimeType(t))
+ for mt in magicFile.detect(file):
+ ifaces.update(byMimeType(mt))
+
if mimeType is not None:
ifaces.update(byMimeType(mimeType))
+
if filename is not None and not ifaces:
t = guess_content_type(filename)[0]
# dont trust this here because zope does not recognize some
# binary files.
if t and not t == 'text/x-unknown-content-type':
ifaces.update(byMimeType(t))
+
if not ifaces:
- ifaces.add(interfaces.filetypes.IBinaryFile)
+ ifaces.add(filetypes.IBinaryFile)
return InterfaceSet(*ifaces)
+
def applyInterfaces(obj):
assert(interfaces.ITypeableFile.providedBy(obj))
+
ifaces = InterfaceSet(*getInterfacesFor(obj.data))
provided = set(interface.directlyProvidedBy(obj))
for iface in provided:
- if not issubclass(iface, interfaces.filetypes.ITypedFile):
+ if not issubclass(iface, filetypes.ITypedFile):
ifaces.add(iface)
- if set(ifaces)!=provided:
- from zope.proxy import removeAllProxies
- obj = removeAllProxies(obj)
- for iface in ifaces:
- interface.directlyProvides(obj, iface)
- notify(FileTypeModifiedEvent(obj))
+
+ ifaces = set(ifaces)
+ if ifaces and (ifaces != provided):
+ clean_obj = removeAllProxies(obj)
+
+ for iface in interface.directlyProvidedBy(clean_obj):
+ if not iface.isOrExtends(filetypes.ITypedFile):
+ ifaces.add(iface)
+
+ interface.directlyProvides(clean_obj, ifaces)
+ event.notify(FileTypeModifiedEvent(obj))
return True
return False
+
class InterfaceSet(object):
-
"""a set that only holds most specific interfaces
>>> s = InterfaceSet(filetypes.IBinaryFile, filetypes.IImageFile)
@@ -83,14 +109,13 @@
>>> sorted(s)
[<InterfaceClass z3c.filetype.interfaces.filetypes.IJPGFile>,
<InterfaceClass z3c.filetype.interfaces.filetypes.ITextFile>]
-
"""
def __init__(self, *ifaces):
self._data = set()
for iface in ifaces:
self.add(iface)
-
+
def add(self, iface):
assert(issubclass(iface, interface.Interface))
toDelete = set()
@@ -101,12 +126,12 @@
toDelete.add(i)
self._data.add(iface)
self._data.difference_update(toDelete)
-
+
def __iter__(self):
-
return iter(self._data)
- at component.adapter(interfaces.ITypeableFile,IObjectModifiedEvent)
+
+ at component.adapter(interfaces.ITypeableFile, IObjectModifiedEvent)
def handleModified(typeableFile, event):
"""handles modification of data"""
if interfaces.IFileTypeModifiedEvent.providedBy(event):
@@ -114,7 +139,8 @@
return
applyInterfaces(typeableFile)
- at component.adapter(interfaces.ITypeableFile,IObjectCreatedEvent)
+
+ at component.adapter(interfaces.ITypeableFile, IObjectCreatedEvent)
def handleCreated(typeableFile, event):
"""handles modification of data"""
applyInterfaces(typeableFile)
Modified: z3c.filetype/trunk/src/z3c/filetype/configure.zcml
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/configure.zcml 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/configure.zcml 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,22 +1,19 @@
<configure
- xmlns="http://namespaces.zope.org/zope"
- i18n_domain="zope"
- >
+ xmlns="http://namespaces.zope.org/zope"
+ i18n_domain="zope">
- <subscriber for=".interfaces.ITypeableFile
- zope.lifecycleevent.interfaces.IObjectModifiedEvent"
- handler=".api.handleModified"/>
+ <subscriber for=".interfaces.ITypeableFile
+ zope.lifecycleevent.interfaces.IObjectModifiedEvent"
+ handler=".api.handleModified"/>
- <subscriber for=".interfaces.ITypeableFile
- zope.lifecycleevent.interfaces.IObjectCreatedEvent"
- handler=".api.handleCreated"/>
+ <subscriber for=".interfaces.ITypeableFile
+ zope.lifecycleevent.interfaces.IObjectCreatedEvent"
+ handler=".api.handleCreated"/>
-
- <adapter factory=".adapters.TypedFileType"/>
+ <adapter factory=".adapters.TypedFileType"/>
- <adapter factory=".size.PNGFileSized" />
- <adapter factory=".size.JPGFileSized" />
- <adapter factory=".size.GIFFileSized" />
+ <adapter factory=".size.PNGFileSized" />
+ <adapter factory=".size.JPGFileSized" />
+ <adapter factory=".size.GIFFileSized" />
-
</configure>
Modified: z3c.filetype/trunk/src/z3c/filetype/event.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/event.py 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/event.py 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,7 +1,24 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+from zope import interface
from zope.lifecycleevent import ObjectModifiedEvent
-from zope import interface
-import interfaces
+from z3c.filetype import interfaces
+
class FileTypeModifiedEvent(ObjectModifiedEvent):
interface.implements(interfaces.IFileTypeModifiedEvent)
-
Modified: z3c.filetype/trunk/src/z3c/filetype/interfaces/__init__.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/interfaces/__init__.py 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/interfaces/__init__.py 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,18 +1,61 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+from zope import interface, schema
+from zope.size.interfaces import ISized
from zope.lifecycleevent.interfaces import IObjectModifiedEvent
-from zope import interface, schema
+
+class MagicError(Exception):
+ pass
+
+
+class MagicTestError(MagicError):
+ pass
+
+
+class OffsetError(MagicError):
+ pass
+
+
+class MagicFileError(MagicError):
+ pass
+
+
+class IMimetypeType(interface.interfaces.IInterface):
+ """ mimetype type """
+
+
class IFileType(interface.Interface):
contentType = schema.TextLine(title = u'Content Type')
+
class IFileTypeModifiedEvent(IObjectModifiedEvent):
-
"""This event is fired when the filetypes change on an object"""
+
class ITypeableFile(interface.Interface):
-
"""A file object that is typeable"""
data = interface.Attribute('Data of the file')
-
-
+
+
+class IImageSized(ISized):
+
+ def getImageSize():
+ """ return width, height of image """
Modified: z3c.filetype/trunk/src/z3c/filetype/interfaces/filetypes.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/interfaces/filetypes.py 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/interfaces/filetypes.py 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,117 +1,157 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
+
+$Id$
+"""
+import re
from zope import interface
-import re
# mimeTypeMatch holds regular expression for matching mime-types
MTM = 'mimeTypesMatch'
-# mimeType holds the preferred mime type to be returned for this
-# interface
+
+# mimeType holds the preferred mime type to be returned for this interface
MT = "mimeType"
+
class ITypedFile(interface.Interface):
"""A Type of a file"""
+
class IBinaryFile(ITypedFile):
"""Binary file"""
IBinaryFile.setTaggedValue(MTM,re.compile('application/octet-stream'))
IBinaryFile.setTaggedValue(MT,'application/octet-stream')
+
class IZIPFile(IBinaryFile):
"""Zip file"""
IZIPFile.setTaggedValue(MTM,re.compile('application/x-zip'))
IZIPFile.setTaggedValue(MT,'application/x-zip')
+
class ITARFile(IBinaryFile):
"""Binary file"""
ITARFile.setTaggedValue(MTM,re.compile('application/x-tar'))
ITARFile.setTaggedValue(MT,'application/x-tar')
+
class IBZIP2File(IBinaryFile):
"""BZIP2 file"""
IBZIP2File.setTaggedValue(MTM,re.compile('application/x-bzip2'))
IBZIP2File.setTaggedValue(MT,'application/x-bzip2')
+
class IGZIPFile(IBinaryFile):
"""Binary file"""
IGZIPFile.setTaggedValue(MTM,re.compile('application/x-gzip'))
IGZIPFile.setTaggedValue(MT,'application/x-gzip')
+
class ITextFile(ITypedFile):
"""text files"""
ITextFile.setTaggedValue(MTM,re.compile('^text/.+$'))
ITextFile.setTaggedValue(MT,'text/plain')
+
class IImageFile(ITypedFile):
"""image files"""
IImageFile.setTaggedValue(MTM,re.compile('^image/.+$'))
+
class IPDFFile(IBinaryFile):
"""pdf files"""
IPDFFile.setTaggedValue(MTM,re.compile('application/pdf'))
IPDFFile.setTaggedValue(MT,'application/pdf')
+
class IJPGFile(IImageFile, IBinaryFile):
"""jpeg file"""
IJPGFile.setTaggedValue(MTM,re.compile('image/jpe?g'))
IJPGFile.setTaggedValue(MT,'image/jpeg')
+
class IPNGFile(IImageFile, IBinaryFile):
"""png file"""
IPNGFile.setTaggedValue(MTM,re.compile('image/png'))
IPNGFile.setTaggedValue(MT,'image/png')
+
class IGIFFile(IImageFile, IBinaryFile):
"""gif file"""
IGIFFile.setTaggedValue(MTM,re.compile('image/gif'))
IGIFFile.setTaggedValue(MT,'image/gif')
+
class IVideoFile(IBinaryFile):
"""video file"""
IVideoFile.setTaggedValue(MTM,re.compile('^video/.+$'))
+
class IQuickTimeFile(IVideoFile):
"""Quicktime Video File Format"""
IQuickTimeFile.setTaggedValue(MTM,re.compile('video/quicktime'))
IQuickTimeFile.setTaggedValue(MT,'video/quicktime')
+
class IAVIFile(IVideoFile):
"""Quicktime Video File Format"""
IAVIFile.setTaggedValue(MTM,re.compile('video/x-msvideo'))
IAVIFile.setTaggedValue(MT,'video/x-msvideo')
+
class IMPEGFile(IVideoFile):
"""MPEG Video File Format"""
IMPEGFile.setTaggedValue(MTM,re.compile('video/mpe?g'))
IMPEGFile.setTaggedValue(MT,'video/mpeg')
+
class IMP4File(IQuickTimeFile):
"""IMP4File IPod Video File Format"""
IMP4File.setTaggedValue(MTM,re.compile('video/mp4'))
IMP4File.setTaggedValue(MT,'video/mp4')
+
class IFLVFile(IVideoFile):
"""Macromedia Flash FLV Video File Format"""
IFLVFile.setTaggedValue(MTM,re.compile('video/x-flv'))
IFLVFile.setTaggedValue(MT,'video/x-flv')
+
class IASFFile(IVideoFile):
"""Windows Media File Format"""
IASFFile.setTaggedValue(MTM,re.compile('video/x-ms-asf'))
IASFFile.setTaggedValue(MT,'video/x-ms-asf')
+
class IAudioFile(ITypedFile):
"""audio file"""
IAudioFile.setTaggedValue(MTM,re.compile('^audio/.+$'))
+
class IAudioMPEGFile(IAudioFile):
"""audio file"""
IAudioMPEGFile.setTaggedValue(MTM,re.compile('audio/mpeg'))
IAudioMPEGFile.setTaggedValue(MT,'audio/mpeg')
+
class IHTMLFile(ITextFile):
"""HTML file"""
IHTMLFile.setTaggedValue(MTM,re.compile('text/html'))
IHTMLFile.setTaggedValue(MT,'text/html')
+
class IXMLFile(ITextFile):
"""XML File"""
IXMLFile.setTaggedValue(MTM,re.compile('text/xml'))
Modified: z3c.filetype/trunk/src/z3c/filetype/magic.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/magic.py 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/magic.py 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,11 +1,11 @@
# Found on a russian zope mailing list, and modified to fix bugs in parsing
-# the magic file and string making
+# the magic file and string making, cleanup
# -- Daniel Berlin <dberlin at dberlin.org>
-import sys, struct, time, re, exceptions, pprint, stat, os
+import sys, struct, time, re, pprint, os
-_mew = 0
+from interfaces import OffsetError, MagicFileError, MagicTestError
-_magic = os.path.join(os.path.dirname(__file__),'magic.mime')
+default_magic = os.path.join(os.path.dirname(__file__), 'magic.mime')
mime = 1
@@ -13,10 +13,11 @@
BUFFER_SIZE = 1024 * 128 # 128K should be enough...
-class MagicError(exceptions.Exception): pass
-def _handle(fmt='@x',adj=None): return fmt, struct.calcsize(fmt), adj
+def _handle(fmt='@x',adj=None):
+ return fmt, struct.calcsize(fmt), adj
+
KnownTypes = {
'byte':_handle('@b'),
'byte':_handle('@B'),
@@ -48,16 +49,6 @@
'leldate':_handle('<l',_ldate_adjust),
}
-_mew_cnt = 0
-def mew(x):
- global _mew_cnt
- if _mew :
- if x=='.' :
- _mew_cnt += 1
- if _mew_cnt % 64 == 0 : sys.stderr.write( '\n' )
- sys.stderr.write( '.' )
- else:
- sys.stderr.write( '\b'+x )
def has_format(s):
n = 0
@@ -69,12 +60,12 @@
l = c
return n
-def read_asciiz(file,size=None,pos=None):
+
+def read_asciiz(file, size=None, pos=None):
s = []
if pos :
- mew('s')
file.seek( pos, 0 )
- mew('z')
+
if size is not None :
s = [file.read( size ).split('\0')[0]]
else:
@@ -82,9 +73,10 @@
c = file.read(1)
if (not c) or (ord(c)==0) or (c=='\n') : break
s.append (c)
- mew('Z')
+
return ''.join(s)
+
def a2i(v,base=0):
if v[-1:] in 'lL' : v = v[:-1]
return int( v, base )
@@ -107,10 +99,10 @@
s = s.replace('\\ ',' ')
return eval( '"'+s.replace('"','\\"')+'"')
-class MagicTestError(MagicError): pass
class MagicTest:
- def __init__(self,offset,mtype,test,message,line=None,level=None):
+
+ def __init__(self, offset, mtype, test, message, line=None, level=None):
self.line, self.level = line, level
self.mtype = mtype
self.mtest = test
@@ -119,14 +111,14 @@
self.smod = None
self.nmod = None
self.offset, self.type, self.test, self.message = \
- offset,mtype,test,message
+ offset, mtype, test, message
if self.mtype == 'true' : return # XXX hack to enable level skips
if test[-1:]=='\\' and test[-2:]!='\\\\' :
self.test += 'n' # looks like someone wanted EOL to match?
if mtype[:6]=='string' :
if '/' in mtype : # for strings
self.type, self.smod = \
- mtype[:mtype.find('/')], mtype[mtype.find('/')+1:]
+ mtype[:mtype.find('/')], mtype[mtype.find('/')+1:]
else:
for nm in '&+-' :
if nm in mtype : # for integer-based
@@ -138,25 +130,26 @@
)
break
self.struct, self.size, self.cast = KnownTypes[ self.type ]
+
def __str__(self):
return '%s %s %s %s' % (
- self.offset, self.mtype, self.mtest, self.message
- )
+ self.offset, self.mtype, self.mtest, self.message)
+
def __repr__(self):
return 'MagicTest(%s,%s,%s,%s,line=%s,level=%s,subtests=\n%s%s)' % (
`self.offset`, `self.mtype`, `self.mtest`, `self.message`,
`self.line`, `self.level`,
'\t'*self.level, pprint.pformat(self.subtests)
)
+
def run(self,file):
result = ''
do_close = 0
try:
- if type(file) == type('x') :
- file = open( file, 'r', BUFFER_SIZE )
+ if isinstance(file, basestring):
+ file = open(file, 'r', BUFFER_SIZE)
do_close = 1
-# else:
-# saved_pos = file.tell()
+
if self.mtype != 'true' :
data = self.read(file)
try:
@@ -167,7 +160,8 @@
pass
else:
data = last = None
- if self.check( data ) :
+
+ if self.check(data) :
result = self.message+' '
if has_format( result ) : result %= data
for test in self.subtests :
@@ -177,13 +171,9 @@
finally:
if do_close :
file.close()
-# else:
-# file.seek( saved_pos, 0 )
+
def get_mod_and_value(self):
if self.type[-6:] == 'string' :
-# if 'ustar' in self.test:
-# import pdb;pdb.set_trace()
- # "something like\tthis\n"
if self.test[0] in '=<>' :
mod, value = self.test[0], make_string( self.test[1:] )
else:
@@ -197,10 +187,9 @@
else:
mod, value = '=', a2i(self.test)
return mod, value
- def read(self,file):
- mew( 's' )
+
+ def read(self, file):
file.seek( self.offset(file), 0 ) # SEEK_SET
- mew( 'r' )
try:
data = rdata = None
# XXX self.size might be 0 here...
@@ -216,28 +205,30 @@
if not rdata or (len(rdata)!=self.size) : return None
data = struct.unpack( self.struct, rdata )[0] # XXX hack??
except:
- print >>sys.stderr, self
- print >>sys.stderr, '@%s struct=%s size=%d rdata=%s' % (
- self.offset, `self.struct`, self.size,`rdata`)
- raise
- mew( 'R' )
+ raise MagicTestError('@%s struct=%s size=%d rdata=%s' % (
+ self.offset, `self.struct`, self.size, `rdata`))
+
if self.cast : data = self.cast( data )
if self.mask :
try:
- if self.nmod == '&' : data &= self.mask
- elif self.nmod == '+' : data += self.mask
- elif self.nmod == '-' : data -= self.mask
- else: raise MagicTestError(self.nmod)
+ if self.nmod == '&':
+ data &= self.mask
+ elif self.nmod == '+':
+ data += self.mask
+ elif self.nmod == '-':
+ data -= self.mask
+ else:
+ raise MagicTestError(self.nmod)
except:
- print >>sys.stderr,'data=%s nmod=%s mask=%s' % (
- `data`, `self.nmod`, `self.mask`
- )
- raise
+ raise MagicTestError('data=%s nmod=%s mask=%s' % (
+ `data`, `self.nmod`, `self.mask`))
+
return data
+
def check(self,data):
- mew('.')
if self.mtype == 'true' :
return '' # not None !
+
mod, value = self.get_mod_and_value()
if self.type[-6:] == 'string' :
# "something like\tthis\n"
@@ -275,10 +266,9 @@
)
return result
except:
- print >>sys.stderr,'mtype=%s data=%s mod=%s value=%s' % (
- `self.mtype`, `data`, `mod`, `value`
- )
- raise
+ raise MagicTestError('mtype=%s data=%s mod=%s value=%s' % (
+ `self.mtype`, `data`, `mod`, `value`))
+
def add(self,mt):
if not isinstance(mt,MagicTest) :
raise MagicTestError((mt,'incorrect subtest type %s'%(type(mt),)))
@@ -297,11 +287,10 @@
self.add( mt ) # retry...
else:
raise MagicTestError((mt,'incorrect subtest level %s'%(`mt.level`,)))
+
def last_test(self):
return self.subtests[-1]
-#end class MagicTest
-class OffsetError(MagicError): pass
class Offset:
pos_format = {'b':'<B','B':'>B','s':'<H','S':'>H','l':'<I','L':'>I',}
@@ -337,6 +326,7 @@
)?
\)$''', re.X|re.I
)
+
def __init__(self,s):
self.source = s
self.value = None
@@ -366,105 +356,94 @@
raise
return
raise OffsetError(`s`)
- def __call__(self,file=None):
- if self.value is not None : return self.value
+
+ def __call__(self, file=None):
+ if self.value is not None:
+ return self.value
+
pos = file.tell()
try:
- if not self.relative : file.seek( self.offset, 0 )
- frmt = Offset.pos_format.get( self.type, 'I' )
- size = struct.calcsize( frmt )
- data = struct.unpack( frmt, file.read( size ) )
+ if not self.relative:
+ file.seek(self.offset, 0)
+
+ frmt = Offset.pos_format.get(self.type, 'I')
+ size = struct.calcsize(frmt)
+ data = struct.unpack(frmt, file.read(size))
if self.offs : data += self.offs
return data
finally:
- file.seek( pos, 0 )
- def __str__(self): return self.source
- def __repr__(self): return 'Offset(%s)' % `self.source`
-#end class Offset
+ file.seek(pos, 0)
-class MagicFileError(MagicError): pass
+ def __str__(self):
+ return self.source
-class MagicFile:
- def __init__(self,filename=_magic):
- self.file = None
+ def __repr__(self):
+ return 'Offset(%s)' % `self.source`
+
+
+class MagicFile(object):
+
+ def __init__(self, filename=default_magic):
self.tests = []
self.total_tests = 0
- self.load( filename )
- self.ack_tests = None
- self.nak_tests = None
- def __del__(self):
- self.close()
- def load(self,filename=None):
- self.open( filename )
- self.parse()
- self.close()
- def open(self,filename=None):
- self.close()
- if filename is not None :
- self.filename = filename
- self.file = open( self.filename, 'r', BUFFER_SIZE )
- def close(self):
- if self.file :
- self.file.close()
- self.file = None
- def parse(self):
+ self.load(filename)
+
+ def load(self, filename=None):
+ file = open(filename, 'r', BUFFER_SIZE)
+ self.parse(file)
+ file.close()
+
+ def parse(self, data):
line_no = 0
- for line in self.file.xreadlines() :
+ for line in data:
line_no += 1
- if not line or line[0]=='#' : continue
- line = line.lstrip().rstrip('\r\n')
- if not line or line[0]=='#' : continue
- try:
- x = self.parse_line( line )
- if x is None :
- print >>sys.stderr, '#[%04d]#'%line_no, line
- continue
- except:
- print >>sys.stderr, '###[%04d]###'%line_no, line
- raise
+
+ data = self.parse_line(line)
+ if data is None:
+ continue
+
self.total_tests += 1
- level, offset, mtype, test, message = x
- new_test = MagicTest(offset,mtype,test,message,
- line=line_no,level=level)
+
+ level = data[0]
+ new_test = MagicTest(*data[1:], **{'line': line_no, 'level': data[0]})
try:
if level == 0 :
self.tests.append( new_test )
else:
self.tests[-1].add( new_test )
except:
- if 1 :
- print >>sys.stderr, 'total tests=%s' % (
- `self.total_tests`,
- )
- print >>sys.stderr, 'level=%s' % (
- `level`,
- )
- print >>sys.stderr, 'tests=%s' % (
- pprint.pformat(self.tests),
- )
- raise
+ raise MagicFileError('total tests=%s, level=%s, tests=%s'%(
+ len(self.total_tests),
+ level, pprint.pformat(self.tests)))
else:
while self.tests[-1].level > 0 :
self.tests.pop()
- def parse_line(self,line):
- # print >>sys.stderr, 'line=[%s]' % line
- if (not line) or line[0]=='#' : return None
+
+ def parse_line(self, line):
+ line = line.lstrip().rstrip('\r\n')
+
+ if not line or line[0]=='#':
+ return None
+
level = 0
offset = mtype = test = message = ''
- mask = None
+
# get optional level (count leading '>')
- while line and line[0]=='>' :
+ while line and line[0]=='>':
line, level = line[1:], level+1
+
# get offset
- while line and not line[0].isspace() :
+ while line and not line[0].isspace():
offset, line = offset+line[0], line[1:]
+
try:
offset = Offset(offset)
except:
- print >>sys.stderr, 'line=[%s]' % line
- raise
+ raise MagicFileError('line=[%s]' % line)
+
# skip spaces
line = line.lstrip()
+
# get type
c = None
while line :
@@ -475,8 +454,10 @@
mtype += c
if last_c == '\\' :
c = None # don't fuck my brain with sequential backslashes
+
# skip spaces
line = line.lstrip()
+
# get test
c = None
while line :
@@ -487,235 +468,23 @@
test += c
if last_c == '\\' :
c = None # don't fuck my brain with sequential backslashes
+
# skip spaces
line = line.lstrip()
+
# get message
message = line
if mime and line.find("\t") != -1:
- message=line[0:line.find("\t")]
- #
- # print '>>', level, offset, mtype, test, message
+ message = line[0:line.find("\t")]
+
return level, offset, mtype, test, message
- def detect(self,file):
- self.ack_tests = 0
- self.nak_tests = 0
+
+ def detect(self, file):
answers = set()
- for test in self.tests :
- message = test.run( file )
+ for test in self.tests:
+ message = test.run(file)
if message and message.strip():
- self.ack_tests += 1
- answers.add( message.strip().split()[0] )
- else:
- self.nak_tests += 1
- return answers
-
-#end class MagicFile
-
-def username(uid):
- try:
- import pwd
- return pwd.getpwuid( uid )[0]
- except:
- return '#%s'%uid
-
-def groupname(gid):
- try:
- import grp
- return grp.getgrgid( gid )[0]
- except:
- return '#%s'%gid
-
-def get_file_type(fname,follow):
- t = None
- if not follow :
- try:
- st = os.lstat( fname ) # stat that entry, don't follow links!
- except os.error, why :
- pass
- else:
- if stat.S_ISLNK(st[stat.ST_MODE]) :
- t = 'symbolic link'
- try:
- lnk = os.readlink( fname )
- except:
- t += ' (unreadable)'
- else:
- t += ' to '+lnk
- if t is None :
- try:
- st = os.stat( fname )
- except os.error, why :
- return "can't stat `%s' (%s)." % (why.filename,why.strerror)
-
- dmaj, dmin = (st.st_rdev>>8)&0x0FF, st.st_rdev&0x0FF
-
- if 0 : pass
- elif stat.S_ISSOCK(st.st_mode) : t = 'socket'
- elif stat.S_ISLNK (st.st_mode) : t = follow and 'symbolic link' or t
- elif stat.S_ISREG (st.st_mode) : t = 'file'
- elif stat.S_ISBLK (st.st_mode) : t = 'block special (%d/%d)'%(dmaj,dmin)
- elif stat.S_ISDIR (st.st_mode) : t = 'directory'
- elif stat.S_ISCHR (st.st_mode) : t = 'character special (%d/%d)'%(dmaj,dmin)
- elif stat.S_ISFIFO(st.st_mode) : t = 'pipe'
- else: t = '<unknown>'
-
- if st.st_mode & stat.S_ISUID :
- t = 'setuid(%d=%s) %s'%(st.st_uid,username(st.st_uid),t)
- if st.st_mode & stat.S_ISGID :
- t = 'setgid(%d=%s) %s'%(st.st_gid,groupname(st.st_gid),t)
- if st.st_mode & stat.S_ISVTX :
- t = 'sticky '+t
-
- return t
-
-HELP = '''%s [options] [files...]
-
-Options:
-
- -?, --help -- this help
- -m, --magic=<file> -- use this magic <file> instead of %s
- -f, --files=<namefile> -- read filenames for <namefile>
-* -C, --compile -- write "compiled" magic file
- -b, --brief -- don't prepend filenames to output lines
-+ -c, --check -- check the magic file
- -i, --mime -- output MIME types
-* -k, --keep-going -- don't stop st the first match
- -n, --flush -- flush stdout after each line
- -v, --verson -- print version and exit
-* -z, --compressed -- try to look inside compressed files
- -L, --follow -- follow symlinks
- -s, --special -- don't skip special files
-
-* -- not implemented so far ;-)
-+ -- implemented, but in another way...
-'''
-
-def main():
- import getopt
- global _magic
- try:
- brief = 0
- flush = 0
- follow= 0
- mime = 0
- check = 0
- special=0
- try:
- opts, args = getopt.getopt(
- sys.argv[1:],
- '?m:f:CbciknvzLs',
- ( 'help',
- 'magic=',
- 'names=',
- 'compile',
- 'brief',
- 'check',
- 'mime',
- 'keep-going',
- 'flush',
- 'version',
- 'compressed',
- 'follow',
- 'special',
- )
- )
- except getopt.error, why:
- print >>sys.stderr, sys.argv[0], why
- return 1
- else:
- files = None
- for o,v in opts :
- if o in ('-?','--help'):
- print HELP % (
- sys.argv[0],
- _magic,
- )
- return 0
- elif o in ('-f','--files='):
- files = v
- elif o in ('-m','--magic='):
- _magic = v[:]
- elif o in ('-C','--compile'):
- pass
- elif o in ('-b','--brief'):
- brief = 1
- elif o in ('-c','--check'):
- check = 1
- elif o in ('-i','--mime'):
- mime = 1
- if os.path.exists( _magic+'.mime' ) :
- _magic += '.mime'
- print >>sys.stderr,sys.argv[0]+':',\
- "Using regular magic file `%s'" % _magic
- elif o in ('-k','--keep-going'):
- pass
- elif o in ('-n','--flush'):
- flush = 1
- elif o in ('-v','--version'):
- print 'VERSION'
- return 0
- elif o in ('-z','--compressed'):
- pass
- elif o in ('-L','--follow'):
- follow = 1
- elif o in ('-s','--special'):
- special = 1
- else:
- if files :
- files = map(lambda x: x.strip(), v.split(','))
- if '-' in files and '-' in args :
- error( 1, 'cannot use STDIN simultaneously for file list and data' )
- for file in files :
- for name in (
- (file=='-')
- and sys.stdin
- or open(file,'r',BUFFER_SIZE)
- ).xreadlines():
- name = name.strip()
- if name not in args :
- args.append( name )
- try:
- if check : print >>sys.stderr, 'Loading magic database...'
- t0 = time.time()
- m = MagicFile(_magic)
- t1 = time.time()
- if check :
- print >>sys.stderr, \
- m.total_tests, 'tests loaded', \
- 'for', '%.2f' % (t1-t0), 'seconds'
- print >>sys.stderr, len(m.tests), 'tests at top level'
- return 0 # XXX "shortened" form ;-)
-
- mlen = max( map(len, args) )+1
- for arg in args :
- if not brief : print (arg + ':').ljust(mlen),
- ftype = get_file_type( arg, follow )
- if (special and ftype.find('special')>=0) \
- or ftype[-4:] == 'file' :
- t0 = time.time()
- try:
- t = m.detect( arg )
- except (IOError,os.error), why:
- t = "can't read `%s' (%s)" % (why.filename,why.strerror)
- if ftype[-4:] == 'file' : t = ftype[:-4] + t
- t1 = time.time()
- print t and t or 'data'
- if 0 : print \
- '#\t%d tests ok, %d tests failed for %.2f seconds'%\
- (m.ack_tests, m.nak_tests, t1-t0)
- else:
- print mime and 'application/x-not-regular-file' or ftype
- if flush : sys.stdout.flush()
- # print >>sys.stderr, 'DONE'
- except:
- if check : return 1
- raise
- else:
- return 0
- finally:
- pass
-
-if __name__ == '__main__' :
- sys.exit( main() )
-# vim:ai
-# EOF #
+ msg = message.strip().split()[0]
+ if msg not in answers:
+ answers.add(msg)
+ yield msg
Modified: z3c.filetype/trunk/src/z3c/filetype/size.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/size.py 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/size.py 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,21 +1,33 @@
-import zope.i18nmessageid
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""
-from zope.size.interfaces import ISized
-
-from zope.size import byteDisplay
-from interfaces import filetypes
-from zope import component, interface
+$Id$
+"""
import os
import stat
import struct
+import zope.i18nmessageid
+from zope import component, interface
+from zope.size import byteDisplay
+from z3c.filetype.interfaces import filetypes, IImageSized
-
_ = zope.i18nmessageid.MessageFactory("zope")
class ImageFileSized(object):
-
- interface.implements(ISized)
+ interface.implements(IImageSized)
def __init__(self, image):
self._image = image
@@ -27,8 +39,7 @@
except TypeError:
data = self._image.data
return int(os.fstat(data.fileno())[stat.ST_SIZE])
- raise NotImplementedError
-
+
def sizeForSorting(self):
'''See `ISized`'''
return ('byte', self.bytes)
@@ -38,7 +49,6 @@
def sizeForDisplay(self):
'''See `ISized`'''
-
w, h = self.getImageSize()
if w < 0:
w = '?'
@@ -55,8 +65,6 @@
class GIFFileSized(ImageFileSized):
-
- interface.implements(ISized)
component.adapts(filetypes.IGIFFile)
def getImageSize(self):
@@ -72,12 +80,11 @@
width = int(w)
height = int(h)
return width, height
-
+
+
class PNGFileSized(ImageFileSized):
+ component.adapts(filetypes.IPNGFile)
- interface.implements(ISized)
- component.adapts(filetypes.IPNGFile)
-
def getImageSize(self):
data = self._image.data
data.seek(0)
@@ -100,11 +107,10 @@
height = int(h)
return width, height
+
class JPGFileSized(ImageFileSized):
+ component.adapts(filetypes.IJPGFile)
- interface.implements(ISized)
- component.adapts(filetypes.IJPGFile)
-
def getImageSize(self):
data = self._image.data
data.seek(2)
@@ -116,8 +122,10 @@
w = -1
h = -1
while (b and ord(b) != 0xDA):
- while (ord(b) != 0xFF): b = data.read(1)
- while (ord(b) == 0xFF): b = data.read(1)
+ while (ord(b) != 0xFF):
+ b = data.read(1)
+ while (ord(b) == 0xFF):
+ b = data.read(1)
if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
data.read(3)
h, w = struct.unpack(">HH", data.read(4))
@@ -127,8 +135,10 @@
b = data.read(1)
width = int(w)
height = int(h)
+
except struct.error:
pass
except ValueError:
pass
+
return width, height
Modified: z3c.filetype/trunk/src/z3c/filetype/tests.py
===================================================================
--- z3c.filetype/trunk/src/z3c/filetype/tests.py 2007-12-19 01:08:06 UTC (rev 82353)
+++ z3c.filetype/trunk/src/z3c/filetype/tests.py 2007-12-19 05:10:09 UTC (rev 82354)
@@ -1,22 +1,36 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+""" tests setup
+
+$Id$
+"""
import doctest
import unittest
-from zope.testing.doctestunit import DocFileSuite, DocTestSuite
+
def test_suite():
-
- return unittest.TestSuite(
- (
- DocFileSuite('README.txt',
- optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
- ),
- DocFileSuite('magic.txt',
- optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
- ),
- DocTestSuite('z3c.filetype.api',
- optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
- ),
- ))
-
-if __name__ == '__main__':
- unittest.main(defaultTest='test_suite')
-
+ return unittest.TestSuite((
+ doctest.DocFileSuite(
+ 'README.txt',
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+ ),
+ doctest.DocFileSuite(
+ 'magic.txt',
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+ ),
+ doctest.DocTestSuite(
+ 'z3c.filetype.api',
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+ ),
+ ))
More information about the Checkins
mailing list