Comments to docstrings (+flake8)

This commit is contained in:
hugovk 2016-05-24 10:36:14 +03:00
parent 55c20731d1
commit 934485269c
9 changed files with 184 additions and 213 deletions

View File

@ -18,6 +18,16 @@
from __future__ import print_function from __future__ import print_function
import sys import sys
from PIL import Image
try:
from PIL import _imagingcms
except ImportError as ex:
# Allow error import for doc purposes, but error out when accessing
# anything in core.
from _util import deferred_error
_imagingcms = deferred_error(ex)
from PIL._util import isStringType
DESCRIPTION = """ DESCRIPTION = """
pyCMS pyCMS
@ -85,16 +95,6 @@ VERSION = "1.0.0 pil"
# --------------------------------------------------------------------. # --------------------------------------------------------------------.
from PIL import Image
try:
from PIL import _imagingcms
except ImportError as ex:
# Allow error import for doc purposes, but error out when accessing
# anything in core.
from _util import deferred_error
_imagingcms = deferred_error(ex)
from PIL._util import isStringType
core = _imagingcms core = _imagingcms
# #
@ -188,10 +188,12 @@ class ImageCmsProfile(object):
class ImageCmsTransform(Image.ImagePointHandler): class ImageCmsTransform(Image.ImagePointHandler):
# Transform. This can be used with the procedural API, or with the """
# standard Image.point() method. Transform. This can be used with the procedural API, or with the standard
# Image.point() method.
# Will return the output profile in the output.info['icc_profile'].
Will return the output profile in the output.info['icc_profile'].
"""
def __init__(self, input, output, input_mode, output_mode, def __init__(self, input, output, input_mode, output_mode,
intent=INTENT_PERCEPTUAL, proof=None, intent=INTENT_PERCEPTUAL, proof=None,
@ -590,7 +592,8 @@ def applyTransform(im, transform, inPlace=0):
with the transform applied is returned (and im is not changed). The with the transform applied is returned (and im is not changed). The
default is False. default is False.
:returns: Either None, or a new PIL Image object, depending on the value of :returns: Either None, or a new PIL Image object, depending on the value of
inPlace. The profile will be returned in the image's info['icc_profile']. inPlace. The profile will be returned in the image's
info['icc_profile'].
:exception PyCMSError: :exception PyCMSError:
""" """

View File

@ -36,26 +36,27 @@ import warnings
from PIL import Image, ImageColor from PIL import Image, ImageColor
from PIL._util import isStringType from PIL._util import isStringType
## """
# A simple 2D drawing interface for PIL images. A simple 2D drawing interface for PIL images.
# <p> <p>
# Application code should use the <b>Draw</b> factory, instead of Application code should use the <b>Draw</b> factory, instead of
# directly. directly.
"""
class ImageDraw(object): class ImageDraw(object):
##
# Create a drawing instance.
#
# @param im The image to draw in.
# @param mode Optional mode to use for color values. For RGB
# images, this argument can be RGB or RGBA (to blend the
# drawing into the image). For all other modes, this argument
# must be the same as the image mode. If omitted, the mode
# defaults to the mode of the image.
def __init__(self, im, mode=None): def __init__(self, im, mode=None):
"""
Create a drawing instance.
@param im The image to draw in.
@param mode Optional mode to use for color values. For RGB
images, this argument can be RGB or RGBA (to blend the
drawing into the image). For all other modes, this argument
must be the same as the image mode. If omitted, the mode
defaults to the mode of the image.
"""
im.load() im.load()
if im.readonly: if im.readonly:
im._copy() # make it writeable im._copy() # make it writeable
@ -100,10 +101,8 @@ class ImageDraw(object):
# compatibility # compatibility
self.font = font self.font = font
##
# Get the current default font.
def getfont(self): def getfont(self):
"""Get the current default font."""
if not self.font: if not self.font:
# FIXME: should add a font repository # FIXME: should add a font repository
from PIL import ImageFont from PIL import ImageFont
@ -131,18 +130,14 @@ class ImageDraw(object):
fill = self.draw.draw_ink(fill, self.mode) fill = self.draw.draw_ink(fill, self.mode)
return ink, fill return ink, fill
##
# Draw an arc.
def arc(self, xy, start, end, fill=None): def arc(self, xy, start, end, fill=None):
"""Draw an arc."""
ink, fill = self._getink(fill) ink, fill = self._getink(fill)
if ink is not None: if ink is not None:
self.draw.draw_arc(xy, start, end, ink) self.draw.draw_arc(xy, start, end, ink)
##
# Draw a bitmap.
def bitmap(self, xy, bitmap, fill=None): def bitmap(self, xy, bitmap, fill=None):
"""Draw a bitmap."""
bitmap.load() bitmap.load()
ink, fill = self._getink(fill) ink, fill = self._getink(fill)
if ink is None: if ink is None:
@ -150,39 +145,30 @@ class ImageDraw(object):
if ink is not None: if ink is not None:
self.draw.draw_bitmap(xy, bitmap.im, ink) self.draw.draw_bitmap(xy, bitmap.im, ink)
##
# Draw a chord.
def chord(self, xy, start, end, fill=None, outline=None): def chord(self, xy, start, end, fill=None, outline=None):
"""Draw a chord."""
ink, fill = self._getink(outline, fill) ink, fill = self._getink(outline, fill)
if fill is not None: if fill is not None:
self.draw.draw_chord(xy, start, end, fill, 1) self.draw.draw_chord(xy, start, end, fill, 1)
if ink is not None: if ink is not None:
self.draw.draw_chord(xy, start, end, ink, 0) self.draw.draw_chord(xy, start, end, ink, 0)
##
# Draw an ellipse.
def ellipse(self, xy, fill=None, outline=None): def ellipse(self, xy, fill=None, outline=None):
"""Draw an ellipse."""
ink, fill = self._getink(outline, fill) ink, fill = self._getink(outline, fill)
if fill is not None: if fill is not None:
self.draw.draw_ellipse(xy, fill, 1) self.draw.draw_ellipse(xy, fill, 1)
if ink is not None: if ink is not None:
self.draw.draw_ellipse(xy, ink, 0) self.draw.draw_ellipse(xy, ink, 0)
##
# Draw a line, or a connected sequence of line segments.
def line(self, xy, fill=None, width=0): def line(self, xy, fill=None, width=0):
"""Draw a line, or a connected sequence of line segments."""
ink, fill = self._getink(fill) ink, fill = self._getink(fill)
if ink is not None: if ink is not None:
self.draw.draw_lines(xy, ink, width) self.draw.draw_lines(xy, ink, width)
##
# (Experimental) Draw a shape.
def shape(self, shape, fill=None, outline=None): def shape(self, shape, fill=None, outline=None):
# experimental """(Experimental) Draw a shape."""
shape.close() shape.close()
ink, fill = self._getink(outline, fill) ink, fill = self._getink(outline, fill)
if fill is not None: if fill is not None:
@ -190,48 +176,38 @@ class ImageDraw(object):
if ink is not None: if ink is not None:
self.draw.draw_outline(shape, ink, 0) self.draw.draw_outline(shape, ink, 0)
##
# Draw a pieslice.
def pieslice(self, xy, start, end, fill=None, outline=None): def pieslice(self, xy, start, end, fill=None, outline=None):
"""Draw a pieslice."""
ink, fill = self._getink(outline, fill) ink, fill = self._getink(outline, fill)
if fill is not None: if fill is not None:
self.draw.draw_pieslice(xy, start, end, fill, 1) self.draw.draw_pieslice(xy, start, end, fill, 1)
if ink is not None: if ink is not None:
self.draw.draw_pieslice(xy, start, end, ink, 0) self.draw.draw_pieslice(xy, start, end, ink, 0)
##
# Draw one or more individual pixels.
def point(self, xy, fill=None): def point(self, xy, fill=None):
"""Draw one or more individual pixels."""
ink, fill = self._getink(fill) ink, fill = self._getink(fill)
if ink is not None: if ink is not None:
self.draw.draw_points(xy, ink) self.draw.draw_points(xy, ink)
##
# Draw a polygon.
def polygon(self, xy, fill=None, outline=None): def polygon(self, xy, fill=None, outline=None):
"""Draw a polygon."""
ink, fill = self._getink(outline, fill) ink, fill = self._getink(outline, fill)
if fill is not None: if fill is not None:
self.draw.draw_polygon(xy, fill, 1) self.draw.draw_polygon(xy, fill, 1)
if ink is not None: if ink is not None:
self.draw.draw_polygon(xy, ink, 0) self.draw.draw_polygon(xy, ink, 0)
##
# Draw a rectangle.
def rectangle(self, xy, fill=None, outline=None): def rectangle(self, xy, fill=None, outline=None):
"""Draw a rectangle."""
ink, fill = self._getink(outline, fill) ink, fill = self._getink(outline, fill)
if fill is not None: if fill is not None:
self.draw.draw_rectangle(xy, fill, 1) self.draw.draw_rectangle(xy, fill, 1)
if ink is not None: if ink is not None:
self.draw.draw_rectangle(xy, ink, 0) self.draw.draw_rectangle(xy, ink, 0)
##
# Draw text.
def _multiline_check(self, text): def _multiline_check(self, text):
"""Draw text."""
split_character = "\n" if isinstance(text, type("")) else b"\n" split_character = "\n" if isinstance(text, type("")) else b"\n"
return split_character in text return split_character in text
@ -241,9 +217,11 @@ class ImageDraw(object):
return text.split(split_character) return text.split(split_character)
def text(self, xy, text, fill=None, font=None, anchor=None, *args, **kwargs): def text(self, xy, text, fill=None, font=None, anchor=None,
*args, **kwargs):
if self._multiline_check(text): if self._multiline_check(text):
return self.multiline_text(xy, text, fill, font, anchor, *args, **kwargs) return self.multiline_text(xy, text, fill, font, anchor,
*args, **kwargs)
ink, fill = self._getink(fill) ink, fill = self._getink(fill)
if font is None: if font is None:
@ -285,10 +263,8 @@ class ImageDraw(object):
top += line_spacing top += line_spacing
left = xy[0] left = xy[0]
##
# Get the size of a given string, in pixels.
def textsize(self, text, font=None, *args, **kwargs): def textsize(self, text, font=None, *args, **kwargs):
"""Get the size of a given string, in pixels."""
if self._multiline_check(text): if self._multiline_check(text):
return self.multiline_textsize(text, font, *args, **kwargs) return self.multiline_textsize(text, font, *args, **kwargs)
@ -306,17 +282,17 @@ class ImageDraw(object):
return max_width, len(lines)*line_spacing return max_width, len(lines)*line_spacing
##
# A simple 2D drawing interface for PIL images.
#
# @param im The image to draw in.
# @param mode Optional mode to use for color values. For RGB
# images, this argument can be RGB or RGBA (to blend the
# drawing into the image). For all other modes, this argument
# must be the same as the image mode. If omitted, the mode
# defaults to the mode of the image.
def Draw(im, mode=None): def Draw(im, mode=None):
"""
A simple 2D drawing interface for PIL images.
@param im The image to draw in.
@param mode Optional mode to use for color values. For RGB
images, this argument can be RGB or RGBA (to blend the
drawing into the image). For all other modes, this argument
must be the same as the image mode. If omitted, the mode
defaults to the mode of the image.
"""
try: try:
return im.getdraw(mode) return im.getdraw(mode)
except AttributeError: except AttributeError:
@ -329,15 +305,15 @@ except AttributeError:
Outline = None Outline = None
##
# (Experimental) A more advanced 2D drawing interface for PIL images,
# based on the WCK interface.
#
# @param im The image to draw in.
# @param hints An optional list of hints.
# @return A (drawing context, drawing resource factory) tuple.
def getdraw(im=None, hints=None): def getdraw(im=None, hints=None):
"""
(Experimental) A more advanced 2D drawing interface for PIL images,
based on the WCK interface.
@param im The image to draw in.
@param hints An optional list of hints.
@return A (drawing context, drawing resource factory) tuple.
"""
# FIXME: this needs more work! # FIXME: this needs more work!
# FIXME: come up with a better 'hints' scheme. # FIXME: come up with a better 'hints' scheme.
handler = None handler = None
@ -353,19 +329,18 @@ def getdraw(im=None, hints=None):
return im, handler return im, handler
##
# (experimental) Fills a bounded region with a given color.
#
# @param image Target image.
# @param xy Seed position (a 2-item coordinate tuple).
# @param value Fill color.
# @param border Optional border value. If given, the region consists of
# pixels with a color different from the border color. If not given,
# the region consists of pixels having the same color as the seed
# pixel.
def floodfill(image, xy, value, border=None): def floodfill(image, xy, value, border=None):
"Fill bounded region." """
(experimental) Fills a bounded region with a given color.
@param image Target image.
@param xy Seed position (a 2-item coordinate tuple).
@param value Fill color.
@param border Optional border value. If given, the region consists of
pixels with a color different from the border color. If not given,
the region consists of pixels having the same color as the seed
pixel.
"""
# based on an implementation by Eric S. Raymond # based on an implementation by Eric S. Raymond
pixel = image.load() pixel = image.load()
x, y = xy x, y = xy
@ -405,3 +380,5 @@ def floodfill(image, xy, value, border=None):
pixel[s, t] = value pixel[s, t] = value
newedge.append((s, t)) newedge.append((s, t))
edge = newedge edge = newedge
# End of file

View File

@ -32,7 +32,7 @@ def _isconstant(v):
class _Operand(object): class _Operand(object):
# wraps an image operand, providing standard operators """Wraps an image operand, providing standard operators"""
def __init__(self, im): def __init__(self, im):
self.im = im self.im = im
@ -268,3 +268,5 @@ def eval(expression, _dict={}, **kw):
return out.im return out.im
except AttributeError: except AttributeError:
return out return out
# End of file

View File

@ -17,10 +17,8 @@
_modes = {} _modes = {}
##
# Wrapper for mode strings.
class ModeDescriptor(object): class ModeDescriptor(object):
"""Wrapper for mode strings."""
def __init__(self, mode, bands, basemode, basetype): def __init__(self, mode, bands, basemode, basetype):
self.mode = mode self.mode = mode
@ -32,10 +30,8 @@ class ModeDescriptor(object):
return self.mode return self.mode
##
# Gets a mode descriptor for the given mode.
def getmode(mode): def getmode(mode):
"""Gets a mode descriptor for the given mode."""
if not _modes: if not _modes:
# initialize mode cache # initialize mode cache
from PIL import Image from PIL import Image
@ -50,3 +46,5 @@ def getmode(mode):
_modes["I;16L"] = ModeDescriptor("I;16L", "I", "L", "L") _modes["I;16L"] = ModeDescriptor("I;16L", "I", "L", "L")
_modes["I;16B"] = ModeDescriptor("I;16B", "I", "L", "L") _modes["I;16B"] = ModeDescriptor("I;16B", "I", "L", "L")
return _modes[mode] return _modes[mode]
# End of file

View File

@ -25,42 +25,38 @@ class Path(object):
def __init__(self, xy): def __init__(self, xy):
pass pass
##
# Compacts the path, by removing points that are close to each
# other. This method modifies the path in place.
def compact(self, distance=2): def compact(self, distance=2):
"""
Compacts the path, by removing points that are close to each other.
This method modifies the path in place.
"""
pass pass
##
# Gets the bounding box.
def getbbox(self): def getbbox(self):
"""Gets the bounding box."""
pass pass
##
# Maps the path through a function.
def map(self, function): def map(self, function):
"""Maps the path through a function."""
pass pass
##
# Converts the path to Python list.
#
# @param flat By default, this function returns a list of 2-tuples
# [(x, y), ...]. If this argument is true, it returns a flat
# list [x, y, ...] instead.
# @return A list of coordinates.
def tolist(self, flat=0): def tolist(self, flat=0):
"""
Converts the path to Python list.
#
@param flat By default, this function returns a list of 2-tuples
[(x, y), ...]. If this argument is true, it returns a flat list
[x, y, ...] instead.
@return A list of coordinates.
"""
pass pass
##
# Transforms the path.
def transform(self, matrix): def transform(self, matrix):
"""Transforms the path."""
pass pass
# override with C implementation # override with C implementation
Path = Image.core.path Path = Image.core.path
# End of file

View File

@ -38,25 +38,23 @@ def register(viewer, order=1):
_viewers.insert(0, viewer) _viewers.insert(0, viewer)
##
# Displays a given image.
#
# @param image An image object.
# @param title Optional title. Not all viewers can display the title.
# @param **options Additional viewer options.
# @return True if a suitable viewer was found, false otherwise.
def show(image, title=None, **options): def show(image, title=None, **options):
"""
Display a given image.
@param image An image object.
@param title Optional title. Not all viewers can display the title.
@param **options Additional viewer options.
@return True if a suitable viewer was found, false otherwise.
"""
for viewer in _viewers: for viewer in _viewers:
if viewer.show(image, title=title, **options): if viewer.show(image, title=title, **options):
return 1 return 1
return 0 return 0
##
# Base class for viewers.
class Viewer(object): class Viewer(object):
"""Base class for viewers."""
# main api # main api
@ -81,22 +79,22 @@ class Viewer(object):
format = None format = None
def get_format(self, image): def get_format(self, image):
# return format name, or None to save as PGM/PPM """Return format name, or None to save as PGM/PPM"""
return self.format return self.format
def get_command(self, file, **options): def get_command(self, file, **options):
raise NotImplementedError raise NotImplementedError
def save_image(self, image): def save_image(self, image):
# save to temporary file, and return filename """Save to temporary file, and return filename"""
return image._dump(format=self.get_format(image)) return image._dump(format=self.get_format(image))
def show_image(self, image, **options): def show_image(self, image, **options):
# display given image """Display given image"""
return self.show_file(self.save_image(image), **options) return self.show_file(self.save_image(image), **options)
def show_file(self, file, **options): def show_file(self, file, **options):
# display given file """Display given file"""
os.system(self.get_command(file, **options)) os.system(self.get_command(file, **options))
return 1 return 1
@ -176,3 +174,5 @@ else:
if __name__ == "__main__": if __name__ == "__main__":
# usage: python ImageShow.py imagefile [title] # usage: python ImageShow.py imagefile [title]
print(show(Image.open(sys.argv[1]), *sys.argv[2:])) print(show(Image.open(sys.argv[1]), *sys.argv[2:]))
# End of file

View File

@ -53,6 +53,7 @@ def _pilbitmap_check():
_pilbitmap_ok = 0 _pilbitmap_ok = 0
return _pilbitmap_ok return _pilbitmap_ok
def _get_image_from_kw(kw): def _get_image_from_kw(kw):
source = None source = None
if "file" in kw: if "file" in kw:
@ -196,7 +197,6 @@ class PhotoImage(object):
class BitmapImage(object): class BitmapImage(object):
""" """
A Tkinter-compatible bitmap image. This can be used everywhere Tkinter A Tkinter-compatible bitmap image. This can be used everywhere Tkinter
expects an image object. expects an image object.
@ -268,10 +268,8 @@ def getimage(photo):
photo.tk.call("PyImagingPhotoGet", photo) photo.tk.call("PyImagingPhotoGet", photo)
# --------------------------------------------------------------------
# Helper for the Image.show method.
def _show(image, title): def _show(image, title):
"""Helper for the Image.show method."""
class UI(tkinter.Label): class UI(tkinter.Label):
def __init__(self, master, im): def __init__(self, master, im):
@ -288,3 +286,5 @@ def _show(image, title):
if title: if title:
top.title(title) top.title(title)
UI(top, image).pack() UI(top, image).pack()
# End of file

View File

@ -29,75 +29,72 @@ class Transform(Image.ImageTransformHandler):
return image.transform(size, method, data, **options) return image.transform(size, method, data, **options)
##
# Define an affine image transform.
# <p>
# This function takes a 6-tuple (<i>a, b, c, d, e, f</i>) which
# contain the first two rows from an affine transform matrix. For
# each pixel (<i>x, y</i>) in the output image, the new value is
# taken from a position (a <i>x</i> + b <i>y</i> + c,
# d <i>x</i> + e <i>y</i> + f) in the input image, rounded to
# nearest pixel.
# <p>
# This function can be used to scale, translate, rotate, and shear the
# original image.
#
# @def AffineTransform(matrix)
# @param matrix A 6-tuple (<i>a, b, c, d, e, f</i>) containing
# the first two rows from an affine transform matrix.
# @see Image#Image.transform
class AffineTransform(Transform): class AffineTransform(Transform):
"""
Define an affine image transform.
This function takes a 6-tuple (a, b, c, d, e, f) which contain the first
two rows from an affine transform matrix. For each pixel (x, y) in the
output image, the new value is taken from a position (a x + b y + c,
d x + e y + f) in the input image, rounded to nearest pixel.
This function can be used to scale, translate, rotate, and shear the
original image.
@def AffineTransform(matrix)
@param matrix A 6-tuple (a, b, c, d, e, f) containing the first two rows
from an affine transform matrix.
@see Image#Image.transform
"""
method = Image.AFFINE method = Image.AFFINE
##
# Define a transform to extract a subregion from an image.
# <p>
# Maps a rectangle (defined by two corners) from the image to a
# rectangle of the given size. The resulting image will contain
# data sampled from between the corners, such that (<i>x0, y0</i>)
# in the input image will end up at (0,0) in the output image,
# and (<i>x1, y1</i>) at <i>size</i>.
# <p>
# This method can be used to crop, stretch, shrink, or mirror an
# arbitrary rectangle in the current image. It is slightly slower than
# <b>crop</b>, but about as fast as a corresponding <b>resize</b>
# operation.
#
# @def ExtentTransform(bbox)
# @param bbox A 4-tuple (<i>x0, y0, x1, y1</i>) which specifies
# two points in the input image's coordinate system.
# @see Image#Image.transform
class ExtentTransform(Transform): class ExtentTransform(Transform):
"""
Define a transform to extract a subregion from an image.
Maps a rectangle (defined by two corners) from the image to a rectangle of
the given size. The resulting image will contain data sampled from between
the corners, such that (x0, y0) in the input image will end up at (0,0) in
the output image, and (x1, y1) at size.
This method can be used to crop, stretch, shrink, or mirror an arbitrary
rectangle in the current image. It is slightly slower than crop, but about
as fast as a corresponding resize operation.
@def ExtentTransform(bbox)
@param bbox A 4-tuple (x0, y0, x1, y1) which specifies two points in the
input image's coordinate system.
@see Image#Image.transform
"""
method = Image.EXTENT method = Image.EXTENT
##
# Define a quad image transform.
# <p>
# Maps a quadrilateral (a region defined by four corners) from the
# image to a rectangle of the given size.
#
# @def QuadTransform(xy)
# @param xy An 8-tuple (<i>x0, y0, x1, y1, x2, y2, y3, y3</i>) which
# contain the upper left, lower left, lower right, and upper right
# corner of the source quadrilateral.
# @see Image#Image.transform
class QuadTransform(Transform): class QuadTransform(Transform):
"""
Define a quad image transform.
Maps a quadrilateral (a region defined by four corners) from the image to a
rectangle of the given size.
@def QuadTransform(xy)
@param xy An 8-tuple (x0, y0, x1, y1, x2, y2, y3, y3) which contain the
upper left, lower left, lower right, and upper right corner of the
source quadrilateral.
@see Image#Image.transform
"""
method = Image.QUAD method = Image.QUAD
##
# Define a mesh image transform. A mesh transform consists of one
# or more individual quad transforms.
#
# @def MeshTransform(data)
# @param data A list of (bbox, quad) tuples.
# @see Image#Image.transform
class MeshTransform(Transform): class MeshTransform(Transform):
"""
Define a mesh image transform. A mesh transform consists of one or more
individual quad transforms.
@def MeshTransform(data)
@param data A list of (bbox, quad) tuples.
@see Image#Image.transform
"""
method = Image.MESH method = Image.MESH
# End of file

View File

@ -191,10 +191,8 @@ class Dib(object):
"Please use tobytes() instead.") "Please use tobytes() instead.")
##
# Create a Window with the given title size.
class Window(object): class Window(object):
"""Create a Window with the given title size."""
def __init__(self, title="PIL", width=None, height=None): def __init__(self, title="PIL", width=None, height=None):
self.hwnd = Image.core.createwindow( self.hwnd = Image.core.createwindow(
@ -223,10 +221,8 @@ class Window(object):
Image.core.eventloop() Image.core.eventloop()
##
# Create an image window which displays the given image.
class ImageWindow(Window): class ImageWindow(Window):
"""Create an image window which displays the given image."""
def __init__(self, image, title="PIL"): def __init__(self, image, title="PIL"):
if not isinstance(image, Dib): if not isinstance(image, Dib):
@ -237,3 +233,5 @@ class ImageWindow(Window):
def ui_handle_repair(self, dc, x0, y0, x1, y1): def ui_handle_repair(self, dc, x0, y0, x1, y1):
self.image.draw(dc, (x0, y0, x1, y1)) self.image.draw(dc, (x0, y0, x1, y1))
# End of file