Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Vladislav Rykov
THSO.server
Commits
ff4a13ed
Commit
ff4a13ed
authored
Apr 17, 2020
by
Vladislav Rykov
Browse files
major changes
parent
51f76a47
Pipeline
#38
failed with stages
Changes
394
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Too many changes to show.
To preserve performance only
20 of 394+
files are displayed.
Plain diff
Email patch
env/lib/python3.5/site-packages/cffi/parse_c_type.h
0 → 100644
View file @
ff4a13ed
/* This part is from file 'cffi/parse_c_type.h'. It is copied at the
beginning of C sources generated by CFFI's ffi.set_source(). */
typedef
void
*
_cffi_opcode_t
;
#define _CFFI_OP(opcode, arg) (_cffi_opcode_t)(opcode | (((uintptr_t)(arg)) << 8))
#define _CFFI_GETOP(cffi_opcode) ((unsigned char)(uintptr_t)cffi_opcode)
#define _CFFI_GETARG(cffi_opcode) (((intptr_t)cffi_opcode) >> 8)
#define _CFFI_OP_PRIMITIVE 1
#define _CFFI_OP_POINTER 3
#define _CFFI_OP_ARRAY 5
#define _CFFI_OP_OPEN_ARRAY 7
#define _CFFI_OP_STRUCT_UNION 9
#define _CFFI_OP_ENUM 11
#define _CFFI_OP_FUNCTION 13
#define _CFFI_OP_FUNCTION_END 15
#define _CFFI_OP_NOOP 17
#define _CFFI_OP_BITFIELD 19
#define _CFFI_OP_TYPENAME 21
#define _CFFI_OP_CPYTHON_BLTN_V 23 // varargs
#define _CFFI_OP_CPYTHON_BLTN_N 25 // noargs
#define _CFFI_OP_CPYTHON_BLTN_O 27 // O (i.e. a single arg)
#define _CFFI_OP_CONSTANT 29
#define _CFFI_OP_CONSTANT_INT 31
#define _CFFI_OP_GLOBAL_VAR 33
#define _CFFI_OP_DLOPEN_FUNC 35
#define _CFFI_OP_DLOPEN_CONST 37
#define _CFFI_OP_GLOBAL_VAR_F 39
#define _CFFI_OP_EXTERN_PYTHON 41
#define _CFFI_PRIM_VOID 0
#define _CFFI_PRIM_BOOL 1
#define _CFFI_PRIM_CHAR 2
#define _CFFI_PRIM_SCHAR 3
#define _CFFI_PRIM_UCHAR 4
#define _CFFI_PRIM_SHORT 5
#define _CFFI_PRIM_USHORT 6
#define _CFFI_PRIM_INT 7
#define _CFFI_PRIM_UINT 8
#define _CFFI_PRIM_LONG 9
#define _CFFI_PRIM_ULONG 10
#define _CFFI_PRIM_LONGLONG 11
#define _CFFI_PRIM_ULONGLONG 12
#define _CFFI_PRIM_FLOAT 13
#define _CFFI_PRIM_DOUBLE 14
#define _CFFI_PRIM_LONGDOUBLE 15
#define _CFFI_PRIM_WCHAR 16
#define _CFFI_PRIM_INT8 17
#define _CFFI_PRIM_UINT8 18
#define _CFFI_PRIM_INT16 19
#define _CFFI_PRIM_UINT16 20
#define _CFFI_PRIM_INT32 21
#define _CFFI_PRIM_UINT32 22
#define _CFFI_PRIM_INT64 23
#define _CFFI_PRIM_UINT64 24
#define _CFFI_PRIM_INTPTR 25
#define _CFFI_PRIM_UINTPTR 26
#define _CFFI_PRIM_PTRDIFF 27
#define _CFFI_PRIM_SIZE 28
#define _CFFI_PRIM_SSIZE 29
#define _CFFI_PRIM_INT_LEAST8 30
#define _CFFI_PRIM_UINT_LEAST8 31
#define _CFFI_PRIM_INT_LEAST16 32
#define _CFFI_PRIM_UINT_LEAST16 33
#define _CFFI_PRIM_INT_LEAST32 34
#define _CFFI_PRIM_UINT_LEAST32 35
#define _CFFI_PRIM_INT_LEAST64 36
#define _CFFI_PRIM_UINT_LEAST64 37
#define _CFFI_PRIM_INT_FAST8 38
#define _CFFI_PRIM_UINT_FAST8 39
#define _CFFI_PRIM_INT_FAST16 40
#define _CFFI_PRIM_UINT_FAST16 41
#define _CFFI_PRIM_INT_FAST32 42
#define _CFFI_PRIM_UINT_FAST32 43
#define _CFFI_PRIM_INT_FAST64 44
#define _CFFI_PRIM_UINT_FAST64 45
#define _CFFI_PRIM_INTMAX 46
#define _CFFI_PRIM_UINTMAX 47
#define _CFFI_PRIM_FLOATCOMPLEX 48
#define _CFFI_PRIM_DOUBLECOMPLEX 49
#define _CFFI_PRIM_CHAR16 50
#define _CFFI_PRIM_CHAR32 51
#define _CFFI__NUM_PRIM 52
#define _CFFI__UNKNOWN_PRIM (-1)
#define _CFFI__UNKNOWN_FLOAT_PRIM (-2)
#define _CFFI__UNKNOWN_LONG_DOUBLE (-3)
#define _CFFI__IO_FILE_STRUCT (-1)
struct
_cffi_global_s
{
const
char
*
name
;
void
*
address
;
_cffi_opcode_t
type_op
;
void
*
size_or_direct_fn
;
// OP_GLOBAL_VAR: size, or 0 if unknown
// OP_CPYTHON_BLTN_*: addr of direct function
};
struct
_cffi_getconst_s
{
unsigned
long
long
value
;
const
struct
_cffi_type_context_s
*
ctx
;
int
gindex
;
};
struct
_cffi_struct_union_s
{
const
char
*
name
;
int
type_index
;
// -> _cffi_types, on a OP_STRUCT_UNION
int
flags
;
// _CFFI_F_* flags below
size_t
size
;
int
alignment
;
int
first_field_index
;
// -> _cffi_fields array
int
num_fields
;
};
#define _CFFI_F_UNION 0x01 // is a union, not a struct
#define _CFFI_F_CHECK_FIELDS 0x02 // complain if fields are not in the
// "standard layout" or if some are missing
#define _CFFI_F_PACKED 0x04 // for CHECK_FIELDS, assume a packed struct
#define _CFFI_F_EXTERNAL 0x08 // in some other ffi.include()
#define _CFFI_F_OPAQUE 0x10 // opaque
struct
_cffi_field_s
{
const
char
*
name
;
size_t
field_offset
;
size_t
field_size
;
_cffi_opcode_t
field_type_op
;
};
struct
_cffi_enum_s
{
const
char
*
name
;
int
type_index
;
// -> _cffi_types, on a OP_ENUM
int
type_prim
;
// _CFFI_PRIM_xxx
const
char
*
enumerators
;
// comma-delimited string
};
struct
_cffi_typename_s
{
const
char
*
name
;
int
type_index
;
/* if opaque, points to a possibly artificial
OP_STRUCT which is itself opaque */
};
struct
_cffi_type_context_s
{
_cffi_opcode_t
*
types
;
const
struct
_cffi_global_s
*
globals
;
const
struct
_cffi_field_s
*
fields
;
const
struct
_cffi_struct_union_s
*
struct_unions
;
const
struct
_cffi_enum_s
*
enums
;
const
struct
_cffi_typename_s
*
typenames
;
int
num_globals
;
int
num_struct_unions
;
int
num_enums
;
int
num_typenames
;
const
char
*
const
*
includes
;
int
num_types
;
int
flags
;
/* future extension */
};
struct
_cffi_parse_info_s
{
const
struct
_cffi_type_context_s
*
ctx
;
_cffi_opcode_t
*
output
;
unsigned
int
output_size
;
size_t
error_location
;
const
char
*
error_message
;
};
struct
_cffi_externpy_s
{
const
char
*
name
;
size_t
size_of_result
;
void
*
reserved1
,
*
reserved2
;
};
#ifdef _CFFI_INTERNAL
static
int
parse_c_type
(
struct
_cffi_parse_info_s
*
info
,
const
char
*
input
);
static
int
search_in_globals
(
const
struct
_cffi_type_context_s
*
ctx
,
const
char
*
search
,
size_t
search_len
);
static
int
search_in_struct_unions
(
const
struct
_cffi_type_context_s
*
ctx
,
const
char
*
search
,
size_t
search_len
);
#endif
env/lib/python3.5/site-packages/cffi/pkgconfig.py
0 → 100644
View file @
ff4a13ed
# pkg-config, https://www.freedesktop.org/wiki/Software/pkg-config/ integration for cffi
import
sys
,
os
,
subprocess
from
.error
import
PkgConfigError
def
merge_flags
(
cfg1
,
cfg2
):
"""Merge values from cffi config flags cfg2 to cf1
Example:
merge_flags({"libraries": ["one"]}, {"libraries": ["two"]})
{"libraries": ["one", "two"]}
"""
for
key
,
value
in
cfg2
.
items
():
if
key
not
in
cfg1
:
cfg1
[
key
]
=
value
else
:
if
not
isinstance
(
cfg1
[
key
],
list
):
raise
TypeError
(
"cfg1[%r] should be a list of strings"
%
(
key
,))
if
not
isinstance
(
value
,
list
):
raise
TypeError
(
"cfg2[%r] should be a list of strings"
%
(
key
,))
cfg1
[
key
].
extend
(
value
)
return
cfg1
def
call
(
libname
,
flag
,
encoding
=
sys
.
getfilesystemencoding
()):
"""Calls pkg-config and returns the output if found
"""
a
=
[
"pkg-config"
,
"--print-errors"
]
a
.
append
(
flag
)
a
.
append
(
libname
)
try
:
pc
=
subprocess
.
Popen
(
a
,
stdout
=
subprocess
.
PIPE
,
stderr
=
subprocess
.
PIPE
)
except
EnvironmentError
as
e
:
raise
PkgConfigError
(
"cannot run pkg-config: %s"
%
(
str
(
e
).
strip
(),))
bout
,
berr
=
pc
.
communicate
()
if
pc
.
returncode
!=
0
:
try
:
berr
=
berr
.
decode
(
encoding
)
except
Exception
:
pass
raise
PkgConfigError
(
berr
.
strip
())
if
sys
.
version_info
>=
(
3
,)
and
not
isinstance
(
bout
,
str
):
# Python 3.x
try
:
bout
=
bout
.
decode
(
encoding
)
except
UnicodeDecodeError
:
raise
PkgConfigError
(
"pkg-config %s %s returned bytes that cannot "
"be decoded with encoding %r:
\n
%r"
%
(
flag
,
libname
,
encoding
,
bout
))
if
os
.
altsep
!=
'
\\
'
and
'
\\
'
in
bout
:
raise
PkgConfigError
(
"pkg-config %s %s returned an unsupported "
"backslash-escaped output:
\n
%r"
%
(
flag
,
libname
,
bout
))
return
bout
def
flags_from_pkgconfig
(
libs
):
r
"""Return compiler line flags for FFI.set_source based on pkg-config output
Usage
...
ffibuilder.set_source("_foo", pkgconfig = ["libfoo", "libbar >= 1.8.3"])
If pkg-config is installed on build machine, then arguments include_dirs,
library_dirs, libraries, define_macros, extra_compile_args and
extra_link_args are extended with an output of pkg-config for libfoo and
libbar.
Raises PkgConfigError in case the pkg-config call fails.
"""
def
get_include_dirs
(
string
):
return
[
x
[
2
:]
for
x
in
string
.
split
()
if
x
.
startswith
(
"-I"
)]
def
get_library_dirs
(
string
):
return
[
x
[
2
:]
for
x
in
string
.
split
()
if
x
.
startswith
(
"-L"
)]
def
get_libraries
(
string
):
return
[
x
[
2
:]
for
x
in
string
.
split
()
if
x
.
startswith
(
"-l"
)]
# convert -Dfoo=bar to list of tuples [("foo", "bar")] expected by distutils
def
get_macros
(
string
):
def
_macro
(
x
):
x
=
x
[
2
:]
# drop "-D"
if
'='
in
x
:
return
tuple
(
x
.
split
(
"="
,
1
))
# "-Dfoo=bar" => ("foo", "bar")
else
:
return
(
x
,
None
)
# "-Dfoo" => ("foo", None)
return
[
_macro
(
x
)
for
x
in
string
.
split
()
if
x
.
startswith
(
"-D"
)]
def
get_other_cflags
(
string
):
return
[
x
for
x
in
string
.
split
()
if
not
x
.
startswith
(
"-I"
)
and
not
x
.
startswith
(
"-D"
)]
def
get_other_libs
(
string
):
return
[
x
for
x
in
string
.
split
()
if
not
x
.
startswith
(
"-L"
)
and
not
x
.
startswith
(
"-l"
)]
# return kwargs for given libname
def
kwargs
(
libname
):
fse
=
sys
.
getfilesystemencoding
()
all_cflags
=
call
(
libname
,
"--cflags"
)
all_libs
=
call
(
libname
,
"--libs"
)
return
{
"include_dirs"
:
get_include_dirs
(
all_cflags
),
"library_dirs"
:
get_library_dirs
(
all_libs
),
"libraries"
:
get_libraries
(
all_libs
),
"define_macros"
:
get_macros
(
all_cflags
),
"extra_compile_args"
:
get_other_cflags
(
all_cflags
),
"extra_link_args"
:
get_other_libs
(
all_libs
),
}
# merge all arguments together
ret
=
{}
for
libname
in
libs
:
lib_flags
=
kwargs
(
libname
)
merge_flags
(
ret
,
lib_flags
)
return
ret
env/lib/python3.5/site-packages/cffi/recompiler.py
0 → 100644
View file @
ff4a13ed
import
os
,
sys
,
io
from
.
import
ffiplatform
,
model
from
.error
import
VerificationError
from
.cffi_opcode
import
*
VERSION_BASE
=
0x2601
VERSION_EMBEDDED
=
0x2701
VERSION_CHAR16CHAR32
=
0x2801
class
GlobalExpr
:
def
__init__
(
self
,
name
,
address
,
type_op
,
size
=
0
,
check_value
=
0
):
self
.
name
=
name
self
.
address
=
address
self
.
type_op
=
type_op
self
.
size
=
size
self
.
check_value
=
check_value
def
as_c_expr
(
self
):
return
' { "%s", (void *)%s, %s, (void *)%s },'
%
(
self
.
name
,
self
.
address
,
self
.
type_op
.
as_c_expr
(),
self
.
size
)
def
as_python_expr
(
self
):
return
"b'%s%s',%d"
%
(
self
.
type_op
.
as_python_bytes
(),
self
.
name
,
self
.
check_value
)
class
FieldExpr
:
def
__init__
(
self
,
name
,
field_offset
,
field_size
,
fbitsize
,
field_type_op
):
self
.
name
=
name
self
.
field_offset
=
field_offset
self
.
field_size
=
field_size
self
.
fbitsize
=
fbitsize
self
.
field_type_op
=
field_type_op
def
as_c_expr
(
self
):
spaces
=
" "
*
len
(
self
.
name
)
return
(
' { "%s", %s,
\n
'
%
(
self
.
name
,
self
.
field_offset
)
+
' %s %s,
\n
'
%
(
spaces
,
self
.
field_size
)
+
' %s %s },'
%
(
spaces
,
self
.
field_type_op
.
as_c_expr
()))
def
as_python_expr
(
self
):
raise
NotImplementedError
def
as_field_python_expr
(
self
):
if
self
.
field_type_op
.
op
==
OP_NOOP
:
size_expr
=
''
elif
self
.
field_type_op
.
op
==
OP_BITFIELD
:
size_expr
=
format_four_bytes
(
self
.
fbitsize
)
else
:
raise
NotImplementedError
return
"b'%s%s%s'"
%
(
self
.
field_type_op
.
as_python_bytes
(),
size_expr
,
self
.
name
)
class
StructUnionExpr
:
def
__init__
(
self
,
name
,
type_index
,
flags
,
size
,
alignment
,
comment
,
first_field_index
,
c_fields
):
self
.
name
=
name
self
.
type_index
=
type_index
self
.
flags
=
flags
self
.
size
=
size
self
.
alignment
=
alignment
self
.
comment
=
comment
self
.
first_field_index
=
first_field_index
self
.
c_fields
=
c_fields
def
as_c_expr
(
self
):
return
(
' { "%s", %d, %s,'
%
(
self
.
name
,
self
.
type_index
,
self
.
flags
)
+
'
\n
%s, %s, '
%
(
self
.
size
,
self
.
alignment
)
+
'%d, %d '
%
(
self
.
first_field_index
,
len
(
self
.
c_fields
))
+
(
'/* %s */ '
%
self
.
comment
if
self
.
comment
else
''
)
+
'},'
)
def
as_python_expr
(
self
):
flags
=
eval
(
self
.
flags
,
G_FLAGS
)
fields_expr
=
[
c_field
.
as_field_python_expr
()
for
c_field
in
self
.
c_fields
]
return
"(b'%s%s%s',%s)"
%
(
format_four_bytes
(
self
.
type_index
),
format_four_bytes
(
flags
),
self
.
name
,
','
.
join
(
fields_expr
))
class
EnumExpr
:
def
__init__
(
self
,
name
,
type_index
,
size
,
signed
,
allenums
):
self
.
name
=
name
self
.
type_index
=
type_index
self
.
size
=
size
self
.
signed
=
signed
self
.
allenums
=
allenums
def
as_c_expr
(
self
):
return
(
' { "%s", %d, _cffi_prim_int(%s, %s),
\n
'
' "%s" },'
%
(
self
.
name
,
self
.
type_index
,
self
.
size
,
self
.
signed
,
self
.
allenums
))
def
as_python_expr
(
self
):
prim_index
=
{
(
1
,
0
):
PRIM_UINT8
,
(
1
,
1
):
PRIM_INT8
,
(
2
,
0
):
PRIM_UINT16
,
(
2
,
1
):
PRIM_INT16
,
(
4
,
0
):
PRIM_UINT32
,
(
4
,
1
):
PRIM_INT32
,
(
8
,
0
):
PRIM_UINT64
,
(
8
,
1
):
PRIM_INT64
,
}[
self
.
size
,
self
.
signed
]
return
"b'%s%s%s
\\
x00%s'"
%
(
format_four_bytes
(
self
.
type_index
),
format_four_bytes
(
prim_index
),
self
.
name
,
self
.
allenums
)
class
TypenameExpr
:
def
__init__
(
self
,
name
,
type_index
):
self
.
name
=
name
self
.
type_index
=
type_index
def
as_c_expr
(
self
):
return
' { "%s", %d },'
%
(
self
.
name
,
self
.
type_index
)
def
as_python_expr
(
self
):
return
"b'%s%s'"
%
(
format_four_bytes
(
self
.
type_index
),
self
.
name
)
# ____________________________________________________________
class
Recompiler
:
_num_externpy
=
0
def
__init__
(
self
,
ffi
,
module_name
,
target_is_python
=
False
):
self
.
ffi
=
ffi
self
.
module_name
=
module_name
self
.
target_is_python
=
target_is_python
self
.
_version
=
VERSION_BASE
def
needs_version
(
self
,
ver
):
self
.
_version
=
max
(
self
.
_version
,
ver
)
def
collect_type_table
(
self
):
self
.
_typesdict
=
{}
self
.
_generate
(
"collecttype"
)
#
all_decls
=
sorted
(
self
.
_typesdict
,
key
=
str
)
#
# prepare all FUNCTION bytecode sequences first
self
.
cffi_types
=
[]
for
tp
in
all_decls
:
if
tp
.
is_raw_function
:
assert
self
.
_typesdict
[
tp
]
is
None
self
.
_typesdict
[
tp
]
=
len
(
self
.
cffi_types
)
self
.
cffi_types
.
append
(
tp
)
# placeholder
for
tp1
in
tp
.
args
:
assert
isinstance
(
tp1
,
(
model
.
VoidType
,
model
.
BasePrimitiveType
,
model
.
PointerType
,
model
.
StructOrUnionOrEnum
,
model
.
FunctionPtrType
))
if
self
.
_typesdict
[
tp1
]
is
None
:
self
.
_typesdict
[
tp1
]
=
len
(
self
.
cffi_types
)
self
.
cffi_types
.
append
(
tp1
)
# placeholder
self
.
cffi_types
.
append
(
'END'
)
# placeholder
#
# prepare all OTHER bytecode sequences
for
tp
in
all_decls
:
if
not
tp
.
is_raw_function
and
self
.
_typesdict
[
tp
]
is
None
:
self
.
_typesdict
[
tp
]
=
len
(
self
.
cffi_types
)
self
.
cffi_types
.
append
(
tp
)
# placeholder
if
tp
.
is_array_type
and
tp
.
length
is
not
None
:
self
.
cffi_types
.
append
(
'LEN'
)
# placeholder
assert
None
not
in
self
.
_typesdict
.
values
()
#
# collect all structs and unions and enums
self
.
_struct_unions
=
{}
self
.
_enums
=
{}
for
tp
in
all_decls
:
if
isinstance
(
tp
,
model
.
StructOrUnion
):
self
.
_struct_unions
[
tp
]
=
None
elif
isinstance
(
tp
,
model
.
EnumType
):
self
.
_enums
[
tp
]
=
None
for
i
,
tp
in
enumerate
(
sorted
(
self
.
_struct_unions
,
key
=
lambda
tp
:
tp
.
name
)):
self
.
_struct_unions
[
tp
]
=
i
for
i
,
tp
in
enumerate
(
sorted
(
self
.
_enums
,
key
=
lambda
tp
:
tp
.
name
)):
self
.
_enums
[
tp
]
=
i
#
# emit all bytecode sequences now
for
tp
in
all_decls
:
method
=
getattr
(
self
,
'_emit_bytecode_'
+
tp
.
__class__
.
__name__
)
method
(
tp
,
self
.
_typesdict
[
tp
])
#
# consistency check
for
op
in
self
.
cffi_types
:
assert
isinstance
(
op
,
CffiOp
)
self
.
cffi_types
=
tuple
(
self
.
cffi_types
)
# don't change any more
def
_do_collect_type
(
self
,
tp
):
if
not
isinstance
(
tp
,
model
.
BaseTypeByIdentity
):
if
isinstance
(
tp
,
tuple
):
for
x
in
tp
:
self
.
_do_collect_type
(
x
)
return
if
tp
not
in
self
.
_typesdict
:
self
.
_typesdict
[
tp
]
=
None
if
isinstance
(
tp
,
model
.
FunctionPtrType
):
self
.
_do_collect_type
(
tp
.
as_raw_function
())
elif
isinstance
(
tp
,
model
.
StructOrUnion
):
if
tp
.
fldtypes
is
not
None
and
(
tp
not
in
self
.
ffi
.
_parser
.
_included_declarations
):
for
name1
,
tp1
,
_
,
_
in
tp
.
enumfields
():
self
.
_do_collect_type
(
self
.
_field_type
(
tp
,
name1
,
tp1
))
else
:
for
_
,
x
in
tp
.
_get_items
():
self
.
_do_collect_type
(
x
)
def
_generate
(
self
,
step_name
):
lst
=
self
.
ffi
.
_parser
.
_declarations
.
items
()
for
name
,
(
tp
,
quals
)
in
sorted
(
lst
):
kind
,
realname
=
name
.
split
(
' '
,
1
)
try
:
method
=
getattr
(
self
,
'_generate_cpy_%s_%s'
%
(
kind
,
step_name
))
except
AttributeError
:
raise
VerificationError
(
"not implemented in recompile(): %r"
%
name
)
try
:
self
.
_current_quals
=
quals
method
(
tp
,
realname
)
except
Exception
as
e
:
model
.
attach_exception_info
(
e
,
name
)
raise
# ----------
ALL_STEPS
=
[
"global"
,
"field"
,
"struct_union"
,
"enum"
,
"typename"
]
def
collect_step_tables
(
self
):
# collect the declarations for '_cffi_globals', '_cffi_typenames', etc.
self
.
_lsts
=
{}
for
step_name
in
self
.
ALL_STEPS
:
self
.
_lsts
[
step_name
]
=
[]
self
.
_seen_struct_unions
=
set
()
self
.
_generate
(
"ctx"
)
self
.
_add_missing_struct_unions
()
#
for
step_name
in
self
.
ALL_STEPS
:
lst
=
self
.
_lsts
[
step_name
]
if
step_name
!=
"field"
:
lst
.
sort
(
key
=
lambda
entry
:
entry
.
name
)
self
.
_lsts
[
step_name
]
=
tuple
(
lst
)
# don't change any more
#
# check for a possible internal inconsistency: _cffi_struct_unions
# should have been generated with exactly self._struct_unions
lst
=
self
.
_lsts
[
"struct_union"
]
for
tp
,
i
in
self
.
_struct_unions
.
items
():
assert
i
<
len
(
lst
)
assert
lst
[
i
].
name
==
tp
.
name
assert
len
(
lst
)
==
len
(
self
.
_struct_unions
)
# same with enums
lst
=
self
.
_lsts
[
"enum"
]
for
tp
,
i
in
self
.
_enums
.
items
():
assert
i
<
len
(
lst
)
assert
lst
[
i
].
name
==
tp
.
name
assert
len
(
lst
)
==
len
(
self
.
_enums
)
# ----------
def
_prnt
(
self
,
what
=
''
):
self
.
_f
.
write
(
what
+
'
\n
'
)
def
write_source_to_f
(
self
,
f
,
preamble
):
if
self
.
target_is_python
:
assert
preamble
is
None
self
.
write_py_source_to_f
(
f
)
else
:
assert
preamble
is
not
None
self
.
write_c_source_to_f
(
f
,
preamble
)
def
_rel_readlines
(
self
,
filename
):
g
=
open
(
os
.
path
.
join
(
os
.
path
.
dirname
(
__file__
),
filename
),
'r'
)
lines
=
g
.
readlines
()
g
.
close
()
return
lines
def
write_c_source_to_f
(
self
,
f
,
preamble
):
self
.
_f
=
f
prnt
=
self
.
_prnt
if
self
.
ffi
.
_embedding
is
not
None
:
prnt
(
'#define _CFFI_USE_EMBEDDING'
)
#
# first the '#include' (actually done by inlining the file's content)
lines
=
self
.
_rel_readlines
(
'_cffi_include.h'
)
i
=
lines
.
index
(
'#include "parse_c_type.h"
\n
'
)
lines
[
i
:
i
+
1
]
=
self
.
_rel_readlines
(
'parse_c_type.h'
)
prnt
(
''
.
join
(
lines
))
#
# if we have ffi._embedding != None, we give it here as a macro
# and include an extra file
base_module_name
=
self
.
module_name
.
split
(
'.'
)[
-
1
]
if
self
.
ffi
.
_embedding
is
not
None
:
prnt
(
'#define _CFFI_MODULE_NAME "%s"'
%
(
self
.
module_name
,))
prnt
(
'static const char _CFFI_PYTHON_STARTUP_CODE[] = {'
)
self
.
_print_string_literal_in_array
(
self
.
ffi
.
_embedding
)
prnt
(
'0 };'
)
prnt
(
'#ifdef PYPY_VERSION'
)
prnt
(
'# define _CFFI_PYTHON_STARTUP_FUNC _cffi_pypyinit_%s'
%
(
base_module_name
,))
prnt
(
'#elif PY_MAJOR_VERSION >= 3'
)
prnt
(
'# define _CFFI_PYTHON_STARTUP_FUNC PyInit_%s'
%
(
base_module_name
,))
prnt
(
'#else'
)
prnt
(
'# define _CFFI_PYTHON_STARTUP_FUNC init%s'
%
(
base_module_name
,))
prnt
(
'#endif'
)
lines
=
self
.
_rel_readlines
(
'_embedding.h'
)
i
=
lines
.
index
(
'#include "_cffi_errors.h"
\n
'
)
lines
[
i
:
i
+
1
]
=
self
.
_rel_readlines
(
'_cffi_errors.h'
)
prnt
(
''
.
join
(
lines
))
self
.
needs_version
(
VERSION_EMBEDDED
)
#
# then paste the C source given by the user, verbatim.
prnt
(
'/************************************************************/'
)
prnt
()
prnt
(
preamble
)
prnt
()
prnt
(
'/************************************************************/'
)
prnt
()
#
# the declaration of '_cffi_types'
prnt
(
'static void *_cffi_types[] = {'
)
typeindex2type
=
dict
([(
i
,
tp
)
for
(
tp
,
i
)
in
self
.
_typesdict
.
items
()])
for
i
,
op
in
enumerate
(
self
.
cffi_types
):
comment
=
''
if
i
in
typeindex2type
:
comment
=
' // '
+
typeindex2type
[
i
].
_get_c_name
()
prnt
(
'/* %2d */ %s,%s'
%
(
i
,
op
.
as_c_expr
(),
comment
))
if
not
self
.
cffi_types
:
prnt
(
' 0'
)
prnt
(
'};'
)
prnt
()
#
# call generate_cpy_xxx_decl(), for every xxx found from
# ffi._parser._declarations. This generates all the functions.
self
.
_seen_constants
=
set
()
self
.
_generate
(
"decl"
)
#
# the declaration of '_cffi_globals' and '_cffi_typenames'
nums
=
{}
for
step_name
in
self
.
ALL_STEPS
:
lst
=
self
.
_lsts
[
step_name
]
nums
[
step_name
]
=
len
(
lst
)
if
nums
[
step_name
]
>
0
:
prnt
(
'static const struct _cffi_%s_s _cffi_%ss[] = {'
%
(
step_name
,
step_name
))
for
entry
in
lst
:
prnt
(
entry
.
as_c_expr
())
prnt
(
'};'
)
prnt
()
#
# the declaration of '_cffi_includes'
if
self
.
ffi
.
_included_ffis
:
prnt
(
'static const char * const _cffi_includes[] = {'
)
for
ffi_to_include
in
self
.
ffi
.
_included_ffis
:
try
:
included_module_name
,
included_source
=
(
ffi_to_include
.
_assigned_source
[:
2
])
except
AttributeError
:
raise
VerificationError
(
"ffi object %r includes %r, but the latter has not "
"been prepared with set_source()"
%
(
self
.
ffi
,
ffi_to_include
,))
if
included_source
is
None
:
raise
VerificationError
(
"not implemented yet: ffi.include() of a Python-based "
"ffi inside a C-based ffi"
)
prnt
(
' "%s",'
%
(
included_module_name
,))
prnt
(
' NULL'
)
prnt
(
'};'
)
prnt
()
#
# the declaration of '_cffi_type_context'
prnt
(
'static const struct _cffi_type_context_s _cffi_type_context = {'
)
prnt
(
' _cffi_types,'
)
for
step_name
in
self
.
ALL_STEPS
:
if
nums
[
step_name
]
>
0
:
prnt
(
' _cffi_%ss,'
%
step_name
)
else
:
prnt
(
' NULL, /* no %ss */'
%
step_name
)
for
step_name
in
self
.
ALL_STEPS
:
if
step_name
!=
"field"
:
prnt
(
' %d, /* num_%ss */'
%
(
nums
[
step_name
],
step_name
))
if
self
.
ffi
.
_included_ffis
:
prnt
(
' _cffi_includes,'
)
else
:
prnt
(
' NULL, /* no includes */'
)
prnt
(
' %d, /* num_types */'
%
(
len
(
self
.
cffi_types
),))
flags
=
0
if
self
.
_num_externpy
:
flags
|=
1
# set to mean that we use extern "Python"
prnt
(
' %d, /* flags */'
%
flags
)
prnt
(
'};'
)
prnt
()
#
# the init function
prnt
(
'#ifdef __GNUC__'
)
prnt
(
'# pragma GCC visibility push(default) /* for -fvisibility= */'
)
prnt
(
'#endif'
)
prnt
()
prnt
(
'#ifdef PYPY_VERSION'
)
prnt
(
'PyMODINIT_FUNC'
)
prnt
(
'_cffi_pypyinit_%s(const void *p[])'
%
(
base_module_name
,))
prnt
(
'{'
)
if
self
.
_num_externpy
:
prnt
(
' if (((intptr_t)p[0]) >= 0x0A03) {'
)
prnt
(
' _cffi_call_python_org = '
'(void(*)(struct _cffi_externpy_s *, char *))p[1];'
)
prnt
(
' }'
)
prnt
(
' p[0] = (const void *)0x%x;'
%
self
.
_version
)
prnt
(
' p[1] = &_cffi_type_context;'
)
prnt
(
'#if PY_MAJOR_VERSION >= 3'
)
prnt
(
' return NULL;'
)
prnt
(
'#endif'
)
prnt
(
'}'
)
# on Windows, distutils insists on putting init_cffi_xyz in
# 'export_symbols', so instead of fighting it, just give up and
# give it one
prnt
(
'# ifdef _MSC_VER'
)
prnt
(
' PyMODINIT_FUNC'
)
prnt
(
'# if PY_MAJOR_VERSION >= 3'
)
prnt
(
' PyInit_%s(void) { return NULL; }'
%
(
base_module_name
,))
prnt
(
'# else'
)
prnt
(
' init%s(void) { }'
%
(
base_module_name
,))
prnt
(
'# endif'
)
prnt
(
'# endif'
)
prnt
(
'#elif PY_MAJOR_VERSION >= 3'
)
prnt
(
'PyMODINIT_FUNC'
)
prnt
(
'PyInit_%s(void)'
%
(
base_module_name
,))
prnt
(
'{'
)
prnt
(
' return _cffi_init("%s", 0x%x, &_cffi_type_context);'
%
(
self
.
module_name
,
self
.
_version
))
prnt
(
'}'
)
prnt
(
'#else'
)
prnt
(
'PyMODINIT_FUNC'
)
prnt
(
'init%s(void)'
%
(
base_module_name
,))
prnt
(
'{'
)
prnt
(
' _cffi_init("%s", 0x%x, &_cffi_type_context);'
%
(
self
.
module_name
,
self
.
_version
))
prnt
(
'}'
)
prnt
(
'#endif'
)
prnt
()
prnt
(
'#ifdef __GNUC__'
)
prnt
(
'# pragma GCC visibility pop'
)
prnt
(
'#endif'
)
self
.
_version
=
None
def
_to_py
(
self
,
x
):
if
isinstance
(
x
,
str
):
return
"b'%s'"
%
(
x
,)
if
isinstance
(
x
,
(
list
,
tuple
)):
rep
=
[
self
.
_to_py
(
item
)
for
item
in
x
]
if
len
(
rep
)
==
1
:
rep
.
append
(
''
)
return
"(%s)"
%
(
','
.
join
(
rep
),)
return
x
.
as_python_expr
()
# Py2: unicode unexpected; Py3: bytes unexp.
def
write_py_source_to_f
(
self
,
f
):
self
.
_f
=
f
prnt
=
self
.
_prnt
#
# header
prnt
(
"# auto-generated file"
)
prnt
(
"import _cffi_backend"
)
#
# the 'import' of the included ffis
num_includes
=
len
(
self
.
ffi
.
_included_ffis
or
())
for
i
in
range
(
num_includes
):
ffi_to_include
=
self
.
ffi
.
_included_ffis
[
i
]
try
:
included_module_name
,
included_source
=
(
ffi_to_include
.
_assigned_source
[:
2
])
except
AttributeError
:
raise
VerificationError
(
"ffi object %r includes %r, but the latter has not "
"been prepared with set_source()"
%
(
self
.
ffi
,
ffi_to_include
,))
if
included_source
is
not
None
:
raise
VerificationError
(
"not implemented yet: ffi.include() of a C-based "
"ffi inside a Python-based ffi"
)
prnt
(
'from %s import ffi as _ffi%d'
%
(
included_module_name
,
i
))
prnt
()
prnt
(
"ffi = _cffi_backend.FFI('%s',"
%
(
self
.
module_name
,))
prnt
(
" _version = 0x%x,"
%
(
self
.
_version
,))
self
.
_version
=
None
#
# the '_types' keyword argument
self
.
cffi_types
=
tuple
(
self
.
cffi_types
)
# don't change any more
types_lst
=
[
op
.
as_python_bytes
()
for
op
in
self
.
cffi_types
]
prnt
(
' _types = %s,'
%
(
self
.
_to_py
(
''
.
join
(
types_lst
)),))
typeindex2type
=
dict
([(
i
,
tp
)
for
(
tp
,
i
)
in
self
.
_typesdict
.
items
()])
#
# the keyword arguments from ALL_STEPS
for
step_name
in
self
.
ALL_STEPS
:
lst
=
self
.
_lsts
[
step_name
]
if
len
(
lst
)
>
0
and
step_name
!=
"field"
:
prnt
(
' _%ss = %s,'
%
(
step_name
,
self
.
_to_py
(
lst
)))
#
# the '_includes' keyword argument
if
num_includes
>
0
:
prnt
(
' _includes = (%s,),'
%
(
', '
.
join
([
'_ffi%d'
%
i
for
i
in
range
(
num_includes
)]),))
#
# the footer
prnt
(
')'
)
# ----------
def
_gettypenum
(
self
,
type
):
# a KeyError here is a bug. please report it! :-)
return
self
.
_typesdict
[
type
]
def
_convert_funcarg_to_c
(
self
,
tp
,
fromvar
,
tovar
,
errcode
):
extraarg
=
''
if
isinstance
(
tp
,
model
.
BasePrimitiveType
)
and
not
tp
.
is_complex_type
():
if
tp
.
is_integer_type
()
and
tp
.
name
!=
'_Bool'
:
converter
=
'_cffi_to_c_int'
extraarg
=
', %s'
%
tp
.
name
elif
isinstance
(
tp
,
model
.
UnknownFloatType
):
# don't check with is_float_type(): it may be a 'long
# double' here, and _cffi_to_c_double would loose precision
converter
=
'(%s)_cffi_to_c_double'
%
(
tp
.
get_c_name
(
''
),)
else
:
cname
=
tp
.
get_c_name
(
''
)
converter
=
'(%s)_cffi_to_c_%s'
%
(
cname
,
tp
.
name
.
replace
(
' '
,
'_'
))
if
cname
in
(
'char16_t'
,
'char32_t'
):
self
.
needs_version
(
VERSION_CHAR16CHAR32
)
errvalue
=
'-1'
#
elif
isinstance
(
tp
,
model
.
PointerType
):
self
.
_convert_funcarg_to_c_ptr_or_array
(
tp
,
fromvar
,
tovar
,
errcode
)
return
#
elif
(
isinstance
(
tp
,
model
.
StructOrUnionOrEnum
)
or
isinstance
(
tp
,
model
.
BasePrimitiveType
)):
# a struct (not a struct pointer) as a function argument;
# or, a complex (the same code works)
self
.
_prnt
(
' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
%
(
tovar
,
self
.
_gettypenum
(
tp
),
fromvar
))
self
.
_prnt
(
' %s;'
%
errcode
)
return
#
elif
isinstance
(
tp
,
model
.
FunctionPtrType
):
converter
=
'(%s)_cffi_to_c_pointer'
%
tp
.
get_c_name
(
''
)
extraarg
=
', _cffi_type(%d)'
%
self
.
_gettypenum
(
tp
)
errvalue
=
'NULL'
#
else
:
raise
NotImplementedError
(
tp
)
#
self
.
_prnt
(
' %s = %s(%s%s);'
%
(
tovar
,
converter
,
fromvar
,
extraarg
))
self
.
_prnt
(
' if (%s == (%s)%s && PyErr_Occurred())'
%
(
tovar
,
tp
.
get_c_name
(
''
),
errvalue
))
self
.
_prnt
(
' %s;'
%
errcode
)
def
_extra_local_variables
(
self
,
tp
,
localvars
,
freelines
):
if
isinstance
(
tp
,
model
.
PointerType
):
localvars
.
add
(
'Py_ssize_t datasize'
)
localvars
.
add
(
'struct _cffi_freeme_s *large_args_free = NULL'
)
freelines
.
add
(
'if (large_args_free != NULL)'
' _cffi_free_array_arguments(large_args_free);'
)
def
_convert_funcarg_to_c_ptr_or_array
(
self
,
tp
,
fromvar
,
tovar
,
errcode
):
self
.
_prnt
(
' datasize = _cffi_prepare_pointer_call_argument('
)
self
.
_prnt
(
' _cffi_type(%d), %s, (char **)&%s);'
%
(
self
.
_gettypenum
(
tp
),
fromvar
,
tovar
))
self
.
_prnt
(
' if (datasize != 0) {'
)
self
.
_prnt
(
' %s = ((size_t)datasize) <= 640 ? '
'(%s)alloca((size_t)datasize) : NULL;'
%
(
tovar
,
tp
.
get_c_name
(
''
)))
self
.
_prnt
(
' if (_cffi_convert_array_argument(_cffi_type(%d), %s, '
'(char **)&%s,'
%
(
self
.
_gettypenum
(
tp
),
fromvar
,
tovar
))
self
.
_prnt
(
' datasize, &large_args_free) < 0)'
)
self
.
_prnt
(
' %s;'
%
errcode
)
self
.
_prnt
(
' }'
)
def
_convert_expr_from_c
(
self
,
tp
,
var
,
context
):
if
isinstance
(
tp
,
model
.
BasePrimitiveType
):
if
tp
.
is_integer_type
()
and
tp
.
name
!=
'_Bool'
:
return
'_cffi_from_c_int(%s, %s)'
%
(
var
,
tp
.
name
)
elif
isinstance
(
tp
,
model
.
UnknownFloatType
):
return
'_cffi_from_c_double(%s)'
%
(
var
,)
elif
tp
.
name
!=
'long double'
and
not
tp
.
is_complex_type
():
cname
=
tp
.
name
.
replace
(
' '
,
'_'
)
if
cname
in
(
'char16_t'
,
'char32_t'
):
self
.
needs_version
(
VERSION_CHAR16CHAR32
)
return
'_cffi_from_c_%s(%s)'
%
(
cname
,
var
)
else
:
return
'_cffi_from_c_deref((char *)&%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
tp
))
elif
isinstance
(
tp
,
(
model
.
PointerType
,
model
.
FunctionPtrType
)):
return
'_cffi_from_c_pointer((char *)%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
tp
))
elif
isinstance
(
tp
,
model
.
ArrayType
):
return
'_cffi_from_c_pointer((char *)%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
model
.
PointerType
(
tp
.
item
)))
elif
isinstance
(
tp
,
model
.
StructOrUnion
):
if
tp
.
fldnames
is
None
:
raise
TypeError
(
"'%s' is used as %s, but is opaque"
%
(
tp
.
_get_c_name
(),
context
))
return
'_cffi_from_c_struct((char *)&%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
tp
))
elif
isinstance
(
tp
,
model
.
EnumType
):
return
'_cffi_from_c_deref((char *)&%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
tp
))
else
:
raise
NotImplementedError
(
tp
)
# ----------
# typedefs
def
_typedef_type
(
self
,
tp
,
name
):
return
self
.
_global_type
(
tp
,
"(*(%s *)0)"
%
(
name
,))
def
_generate_cpy_typedef_collecttype
(
self
,
tp
,
name
):
self
.
_do_collect_type
(
self
.
_typedef_type
(
tp
,
name
))
def
_generate_cpy_typedef_decl
(
self
,
tp
,
name
):
pass
def
_typedef_ctx
(
self
,
tp
,
name
):
type_index
=
self
.
_typesdict
[
tp
]
self
.
_lsts
[
"typename"
].
append
(
TypenameExpr
(
name
,
type_index
))
def
_generate_cpy_typedef_ctx
(
self
,
tp
,
name
):
tp
=
self
.
_typedef_type
(
tp
,
name
)
self
.
_typedef_ctx
(
tp
,
name
)
if
getattr
(
tp
,
"origin"
,
None
)
==
"unknown_type"
:
self
.
_struct_ctx
(
tp
,
tp
.
name
,
approxname
=
None
)
elif
isinstance
(
tp
,
model
.
NamedPointerType
):
self
.
_struct_ctx
(
tp
.
totype
,
tp
.
totype
.
name
,
approxname
=
tp
.
name
,
named_ptr
=
tp
)
# ----------
# function declarations
def
_generate_cpy_function_collecttype
(
self
,
tp
,
name
):
self
.
_do_collect_type
(
tp
.
as_raw_function
())
if
tp
.
ellipsis
and
not
self
.
target_is_python
:
self
.
_do_collect_type
(
tp
)
def
_generate_cpy_function_decl
(
self
,
tp
,
name
):
assert
not
self
.
target_is_python
assert
isinstance
(
tp
,
model
.
FunctionPtrType
)
if
tp
.
ellipsis
:
# cannot support vararg functions better than this: check for its
# exact type (including the fixed arguments), and build it as a
# constant function pointer (no CPython wrapper)
self
.
_generate_cpy_constant_decl
(
tp
,
name
)
return
prnt
=
self
.
_prnt
numargs
=
len
(
tp
.
args
)
if
numargs
==
0
:
argname
=
'noarg'
elif
numargs
==
1
:
argname
=
'arg0'
else
:
argname
=
'args'
#
# ------------------------------
# the 'd' version of the function, only for addressof(lib, 'func')
arguments
=
[]
call_arguments
=
[]
context
=
'argument of %s'
%
name
for
i
,
type
in
enumerate
(
tp
.
args
):
arguments
.
append
(
type
.
get_c_name
(
' x%d'
%
i
,
context
))
call_arguments
.
append
(
'x%d'
%
i
)
repr_arguments
=
', '
.
join
(
arguments
)
repr_arguments
=
repr_arguments
or
'void'
if
tp
.
abi
:
abi
=
tp
.
abi
+
' '
else
:
abi
=
''
name_and_arguments
=
'%s_cffi_d_%s(%s)'
%
(
abi
,
name
,
repr_arguments
)
prnt
(
'static %s'
%
(
tp
.
result
.
get_c_name
(
name_and_arguments
),))
prnt
(
'{'
)
call_arguments
=
', '
.
join
(
call_arguments
)
result_code
=
'return '
if
isinstance
(
tp
.
result
,
model
.
VoidType
):
result_code
=
''
prnt
(
' %s%s(%s);'
%
(
result_code
,
name
,
call_arguments
))
prnt
(
'}'
)
#
prnt
(
'#ifndef PYPY_VERSION'
)
# ------------------------------
#
prnt
(
'static PyObject *'
)
prnt
(
'_cffi_f_%s(PyObject *self, PyObject *%s)'
%
(
name
,
argname
))
prnt
(
'{'
)
#
context
=
'argument of %s'
%
name
for
i
,
type
in
enumerate
(
tp
.
args
):
arg
=
type
.
get_c_name
(
' x%d'
%
i
,
context
)
prnt
(
' %s;'
%
arg
)
#
localvars
=
set
()
freelines
=
set
()
for
type
in
tp
.
args
:
self
.
_extra_local_variables
(
type
,
localvars
,
freelines
)
for
decl
in
sorted
(
localvars
):
prnt
(
' %s;'
%
(
decl
,))
#
if
not
isinstance
(
tp
.
result
,
model
.
VoidType
):
result_code
=
'result = '
context
=
'result of %s'
%
name
result_decl
=
' %s;'
%
tp
.
result
.
get_c_name
(
' result'
,
context
)
prnt
(
result_decl
)
prnt
(
' PyObject *pyresult;'
)
else
:
result_decl
=
None
result_code
=
''
#
if
len
(
tp
.
args
)
>
1
:
rng
=
range
(
len
(
tp
.
args
))
for
i
in
rng
:
prnt
(
' PyObject *arg%d;'
%
i
)
prnt
()
prnt
(
' if (!PyArg_UnpackTuple(args, "%s", %d, %d, %s))'
%
(
name
,
len
(
rng
),
len
(
rng
),
', '
.
join
([
'&arg%d'
%
i
for
i
in
rng
])))
prnt
(
' return NULL;'
)
prnt
()
#
for
i
,
type
in
enumerate
(
tp
.
args
):
self
.
_convert_funcarg_to_c
(
type
,
'arg%d'
%
i
,
'x%d'
%
i
,
'return NULL'
)
prnt
()
#
prnt
(
' Py_BEGIN_ALLOW_THREADS'
)
prnt
(
' _cffi_restore_errno();'
)
call_arguments
=
[
'x%d'
%
i
for
i
in
range
(
len
(
tp
.
args
))]
call_arguments
=
', '
.
join
(
call_arguments
)
prnt
(
' { %s%s(%s); }'
%
(
result_code
,
name
,
call_arguments
))
prnt
(
' _cffi_save_errno();'
)
prnt
(
' Py_END_ALLOW_THREADS'
)
prnt
()
#
prnt
(
' (void)self; /* unused */'
)
if
numargs
==
0
:
prnt
(
' (void)noarg; /* unused */'
)
if
result_code
:
prnt
(
' pyresult = %s;'
%
self
.
_convert_expr_from_c
(
tp
.
result
,
'result'
,
'result type'
))
for
freeline
in
freelines
:
prnt
(
' '
+
freeline
)
prnt
(
' return pyresult;'
)
else
:
for
freeline
in
freelines
:
prnt
(
' '
+
freeline
)
prnt
(
' Py_INCREF(Py_None);'
)
prnt
(
' return Py_None;'
)
prnt
(
'}'
)
#
prnt
(
'#else'
)
# ------------------------------
#
# the PyPy version: need to replace struct/union arguments with
# pointers, and if the result is a struct/union, insert a first
# arg that is a pointer to the result. We also do that for
# complex args and return type.
def
need_indirection
(
type
):
return
(
isinstance
(
type
,
model
.
StructOrUnion
)
or
(
isinstance
(
type
,
model
.
PrimitiveType
)
and
type
.
is_complex_type
()))
difference
=
False
arguments
=
[]
call_arguments
=
[]
context
=
'argument of %s'
%
name
for
i
,
type
in
enumerate
(
tp
.
args
):
indirection
=
''
if
need_indirection
(
type
):
indirection
=
'*'
difference
=
True
arg
=
type
.
get_c_name
(
' %sx%d'
%
(
indirection
,
i
),
context
)
arguments
.
append
(
arg
)
call_arguments
.
append
(
'%sx%d'
%
(
indirection
,
i
))
tp_result
=
tp
.
result
if
need_indirection
(
tp_result
):
context
=
'result of %s'
%
name
arg
=
tp_result
.
get_c_name
(
' *result'
,
context
)
arguments
.
insert
(
0
,
arg
)
tp_result
=
model
.
void_type
result_decl
=
None
result_code
=
'*result = '
difference
=
True
if
difference
:
repr_arguments
=
', '
.
join
(
arguments
)
repr_arguments
=
repr_arguments
or
'void'
name_and_arguments
=
'%s_cffi_f_%s(%s)'
%
(
abi
,
name
,
repr_arguments
)
prnt
(
'static %s'
%
(
tp_result
.
get_c_name
(
name_and_arguments
),))
prnt
(
'{'
)
if
result_decl
:
prnt
(
result_decl
)
call_arguments
=
', '
.
join
(
call_arguments
)
prnt
(
' { %s%s(%s); }'
%
(
result_code
,
name
,
call_arguments
))
if
result_decl
:
prnt
(
' return result;'
)
prnt
(
'}'
)
else
:
prnt
(
'# define _cffi_f_%s _cffi_d_%s'
%
(
name
,
name
))
#
prnt
(
'#endif'
)
# ------------------------------
prnt
()
def
_generate_cpy_function_ctx
(
self
,
tp
,
name
):
if
tp
.
ellipsis
and
not
self
.
target_is_python
:
self
.
_generate_cpy_constant_ctx
(
tp
,
name
)
return
type_index
=
self
.
_typesdict
[
tp
.
as_raw_function
()]
numargs
=
len
(
tp
.
args
)
if
self
.
target_is_python
:
meth_kind
=
OP_DLOPEN_FUNC
elif
numargs
==
0
:
meth_kind
=
OP_CPYTHON_BLTN_N
# 'METH_NOARGS'
elif
numargs
==
1
:
meth_kind
=
OP_CPYTHON_BLTN_O
# 'METH_O'
else
:
meth_kind
=
OP_CPYTHON_BLTN_V
# 'METH_VARARGS'
self
.
_lsts
[
"global"
].
append
(
GlobalExpr
(
name
,
'_cffi_f_%s'
%
name
,
CffiOp
(
meth_kind
,
type_index
),
size
=
'_cffi_d_%s'
%
name
))
# ----------
# named structs or unions
def
_field_type
(
self
,
tp_struct
,
field_name
,
tp_field
):
if
isinstance
(
tp_field
,
model
.
ArrayType
):
actual_length
=
tp_field
.
length
if
actual_length
==
'...'
:
ptr_struct_name
=
tp_struct
.
get_c_name
(
'*'
)
actual_length
=
'_cffi_array_len(((%s)0)->%s)'
%
(
ptr_struct_name
,
field_name
)
tp_item
=
self
.
_field_type
(
tp_struct
,
'%s[0]'
%
field_name
,
tp_field
.
item
)
tp_field
=
model
.
ArrayType
(
tp_item
,
actual_length
)
return
tp_field
def
_struct_collecttype
(
self
,
tp
):
self
.
_do_collect_type
(
tp
)
if
self
.
target_is_python
:
# also requires nested anon struct/unions in ABI mode, recursively
for
fldtype
in
tp
.
anonymous_struct_fields
():
self
.
_struct_collecttype
(
fldtype
)
def
_struct_decl
(
self
,
tp
,
cname
,
approxname
):
if
tp
.
fldtypes
is
None
:
return
prnt
=
self
.
_prnt
checkfuncname
=
'_cffi_checkfld_%s'
%
(
approxname
,)
prnt
(
'_CFFI_UNUSED_FN'
)
prnt
(
'static void %s(%s *p)'
%
(
checkfuncname
,
cname
))
prnt
(
'{'
)
prnt
(
' /* only to generate compile-time warnings or errors */'
)
prnt
(
' (void)p;'
)
for
fname
,
ftype
,
fbitsize
,
fqual
in
tp
.
enumfields
():
try
:
if
ftype
.
is_integer_type
()
or
fbitsize
>=
0
:
# accept all integers, but complain on float or double
if
fname
!=
''
:
prnt
(
" (void)((p->%s) | 0); /* check that '%s.%s' is "
"an integer */"
%
(
fname
,
cname
,
fname
))
continue
# only accept exactly the type declared, except that '[]'
# is interpreted as a '*' and so will match any array length.
# (It would also match '*', but that's harder to detect...)
while
(
isinstance
(
ftype
,
model
.
ArrayType
)
and
(
ftype
.
length
is
None
or
ftype
.
length
==
'...'
)):
ftype
=
ftype
.
item
fname
=
fname
+
'[0]'
prnt
(
' { %s = &p->%s; (void)tmp; }'
%
(
ftype
.
get_c_name
(
'*tmp'
,
'field %r'
%
fname
,
quals
=
fqual
),
fname
))
except
VerificationError
as
e
:
prnt
(
' /* %s */'
%
str
(
e
))
# cannot verify it, ignore
prnt
(
'}'
)
prnt
(
'struct _cffi_align_%s { char x; %s y; };'
%
(
approxname
,
cname
))
prnt
()
def
_struct_ctx
(
self
,
tp
,
cname
,
approxname
,
named_ptr
=
None
):
type_index
=
self
.
_typesdict
[
tp
]
reason_for_not_expanding
=
None
flags
=
[]
if
isinstance
(
tp
,
model
.
UnionType
):
flags
.
append
(
"_CFFI_F_UNION"
)
if
tp
.
fldtypes
is
None
:
flags
.
append
(
"_CFFI_F_OPAQUE"
)
reason_for_not_expanding
=
"opaque"
if
(
tp
not
in
self
.
ffi
.
_parser
.
_included_declarations
and
(
named_ptr
is
None
or
named_ptr
not
in
self
.
ffi
.
_parser
.
_included_declarations
)):
if
tp
.
fldtypes
is
None
:
pass
# opaque
elif
tp
.
partial
or
any
(
tp
.
anonymous_struct_fields
()):
pass
# field layout obtained silently from the C compiler
else
:
flags
.
append
(
"_CFFI_F_CHECK_FIELDS"
)
if
tp
.
packed
:
if
tp
.
packed
>
1
:
raise
NotImplementedError
(
"%r is declared with 'pack=%r'; only 0 or 1 are "
"supported in API mode (try to use
\"
...;
\"
, which "
"does not require a 'pack' declaration)"
%
(
tp
,
tp
.
packed
))
flags
.
append
(
"_CFFI_F_PACKED"
)
else
:
flags
.
append
(
"_CFFI_F_EXTERNAL"
)
reason_for_not_expanding
=
"external"
flags
=
'|'
.
join
(
flags
)
or
'0'
c_fields
=
[]
if
reason_for_not_expanding
is
None
:
expand_anonymous_struct_union
=
not
self
.
target_is_python
enumfields
=
list
(
tp
.
enumfields
(
expand_anonymous_struct_union
))
for
fldname
,
fldtype
,
fbitsize
,
fqual
in
enumfields
:
fldtype
=
self
.
_field_type
(
tp
,
fldname
,
fldtype
)
self
.
_check_not_opaque
(
fldtype
,
"field '%s.%s'"
%
(
tp
.
name
,
fldname
))
# cname is None for _add_missing_struct_unions() only
op
=
OP_NOOP
if
fbitsize
>=
0
:
op
=
OP_BITFIELD
size
=
'%d /* bits */'
%
fbitsize
elif
cname
is
None
or
(
isinstance
(
fldtype
,
model
.
ArrayType
)
and
fldtype
.
length
is
None
):
size
=
'(size_t)-1'
else
:
size
=
'sizeof(((%s)0)->%s)'
%
(
tp
.
get_c_name
(
'*'
)
if
named_ptr
is
None
else
named_ptr
.
name
,
fldname
)
if
cname
is
None
or
fbitsize
>=
0
:
offset
=
'(size_t)-1'
elif
named_ptr
is
not
None
:
offset
=
'((char *)&((%s)0)->%s) - (char *)0'
%
(
named_ptr
.
name
,
fldname
)
else
:
offset
=
'offsetof(%s, %s)'
%
(
tp
.
get_c_name
(
''
),
fldname
)
c_fields
.
append
(
FieldExpr
(
fldname
,
offset
,
size
,
fbitsize
,
CffiOp
(
op
,
self
.
_typesdict
[
fldtype
])))
first_field_index
=
len
(
self
.
_lsts
[
"field"
])
self
.
_lsts
[
"field"
].
extend
(
c_fields
)
#
if
cname
is
None
:
# unknown name, for _add_missing_struct_unions
size
=
'(size_t)-2'
align
=
-
2
comment
=
"unnamed"
else
:
if
named_ptr
is
not
None
:
size
=
'sizeof(*(%s)0)'
%
(
named_ptr
.
name
,)
align
=
'-1 /* unknown alignment */'
else
:
size
=
'sizeof(%s)'
%
(
cname
,)
align
=
'offsetof(struct _cffi_align_%s, y)'
%
(
approxname
,)
comment
=
None
else
:
size
=
'(size_t)-1'
align
=
-
1
first_field_index
=
-
1
comment
=
reason_for_not_expanding
self
.
_lsts
[
"struct_union"
].
append
(
StructUnionExpr
(
tp
.
name
,
type_index
,
flags
,
size
,
align
,
comment
,
first_field_index
,
c_fields
))
self
.
_seen_struct_unions
.
add
(
tp
)
def
_check_not_opaque
(
self
,
tp
,
location
):
while
isinstance
(
tp
,
model
.
ArrayType
):
tp
=
tp
.
item
if
isinstance
(
tp
,
model
.
StructOrUnion
)
and
tp
.
fldtypes
is
None
:
raise
TypeError
(
"%s is of an opaque type (not declared in cdef())"
%
location
)
def
_add_missing_struct_unions
(
self
):
# not very nice, but some struct declarations might be missing
# because they don't have any known C name. Check that they are
# not partial (we can't complete or verify them!) and emit them
# anonymously.
lst
=
list
(
self
.
_struct_unions
.
items
())
lst
.
sort
(
key
=
lambda
tp_order
:
tp_order
[
1
])
for
tp
,
order
in
lst
:
if
tp
not
in
self
.
_seen_struct_unions
:
if
tp
.
partial
:
raise
NotImplementedError
(
"internal inconsistency: %r is "
"partial but was not seen at "
"this point"
%
(
tp
,))
if
tp
.
name
.
startswith
(
'$'
)
and
tp
.
name
[
1
:].
isdigit
():
approxname
=
tp
.
name
[
1
:]
elif
tp
.
name
==
'_IO_FILE'
and
tp
.
forcename
==
'FILE'
:
approxname
=
'FILE'
self
.
_typedef_ctx
(
tp
,
'FILE'
)
else
:
raise
NotImplementedError
(
"internal inconsistency: %r"
%
(
tp
,))
self
.
_struct_ctx
(
tp
,
None
,
approxname
)
def
_generate_cpy_struct_collecttype
(
self
,
tp
,
name
):
self
.
_struct_collecttype
(
tp
)
_generate_cpy_union_collecttype
=
_generate_cpy_struct_collecttype
def
_struct_names
(
self
,
tp
):
cname
=
tp
.
get_c_name
(
''
)
if
' '
in
cname
:
return
cname
,
cname
.
replace
(
' '
,
'_'
)
else
:
return
cname
,
'_'
+
cname
def
_generate_cpy_struct_decl
(
self
,
tp
,
name
):
self
.
_struct_decl
(
tp
,
*
self
.
_struct_names
(
tp
))
_generate_cpy_union_decl
=
_generate_cpy_struct_decl
def
_generate_cpy_struct_ctx
(
self
,
tp
,
name
):
self
.
_struct_ctx
(
tp
,
*
self
.
_struct_names
(
tp
))
_generate_cpy_union_ctx
=
_generate_cpy_struct_ctx
# ----------
# 'anonymous' declarations. These are produced for anonymous structs
# or unions; the 'name' is obtained by a typedef.
def
_generate_cpy_anonymous_collecttype
(
self
,
tp
,
name
):
if
isinstance
(
tp
,
model
.
EnumType
):
self
.
_generate_cpy_enum_collecttype
(
tp
,
name
)
else
:
self
.
_struct_collecttype
(
tp
)
def
_generate_cpy_anonymous_decl
(
self
,
tp
,
name
):
if
isinstance
(
tp
,
model
.
EnumType
):
self
.
_generate_cpy_enum_decl
(
tp
)
else
:
self
.
_struct_decl
(
tp
,
name
,
'typedef_'
+
name
)
def
_generate_cpy_anonymous_ctx
(
self
,
tp
,
name
):
if
isinstance
(
tp
,
model
.
EnumType
):
self
.
_enum_ctx
(
tp
,
name
)
else
:
self
.
_struct_ctx
(
tp
,
name
,
'typedef_'
+
name
)
# ----------
# constants, declared with "static const ..."
def
_generate_cpy_const
(
self
,
is_int
,
name
,
tp
=
None
,
category
=
'const'
,
check_value
=
None
):
if
(
category
,
name
)
in
self
.
_seen_constants
:
raise
VerificationError
(
"duplicate declaration of %s '%s'"
%
(
category
,
name
))
self
.
_seen_constants
.
add
((
category
,
name
))
#
prnt
=
self
.
_prnt
funcname
=
'_cffi_%s_%s'
%
(
category
,
name
)
if
is_int
:
prnt
(
'static int %s(unsigned long long *o)'
%
funcname
)
prnt
(
'{'
)
prnt
(
' int n = (%s) <= 0;'
%
(
name
,))
prnt
(
' *o = (unsigned long long)((%s) | 0);'
' /* check that %s is an integer */'
%
(
name
,
name
))
if
check_value
is
not
None
:
if
check_value
>
0
:
check_value
=
'%dU'
%
(
check_value
,)
prnt
(
' if (!_cffi_check_int(*o, n, %s))'
%
(
check_value
,))
prnt
(
' n |= 2;'
)
prnt
(
' return n;'
)
prnt
(
'}'
)
else
:
assert
check_value
is
None
prnt
(
'static void %s(char *o)'
%
funcname
)
prnt
(
'{'
)
prnt
(
' *(%s)o = %s;'
%
(
tp
.
get_c_name
(
'*'
),
name
))
prnt
(
'}'
)
prnt
()
def
_generate_cpy_constant_collecttype
(
self
,
tp
,
name
):
is_int
=
tp
.
is_integer_type
()
if
not
is_int
or
self
.
target_is_python
:
self
.
_do_collect_type
(
tp
)
def
_generate_cpy_constant_decl
(
self
,
tp
,
name
):
is_int
=
tp
.
is_integer_type
()
self
.
_generate_cpy_const
(
is_int
,
name
,
tp
)
def
_generate_cpy_constant_ctx
(
self
,
tp
,
name
):
if
not
self
.
target_is_python
and
tp
.
is_integer_type
():
type_op
=
CffiOp
(
OP_CONSTANT_INT
,
-
1
)
else
:
if
self
.
target_is_python
:
const_kind
=
OP_DLOPEN_CONST
else
:
const_kind
=
OP_CONSTANT
type_index
=
self
.
_typesdict
[
tp
]
type_op
=
CffiOp
(
const_kind
,
type_index
)
self
.
_lsts
[
"global"
].
append
(
GlobalExpr
(
name
,
'_cffi_const_%s'
%
name
,
type_op
))
# ----------
# enums
def
_generate_cpy_enum_collecttype
(
self
,
tp
,
name
):
self
.
_do_collect_type
(
tp
)
def
_generate_cpy_enum_decl
(
self
,
tp
,
name
=
None
):
for
enumerator
in
tp
.
enumerators
:
self
.
_generate_cpy_const
(
True
,
enumerator
)
def
_enum_ctx
(
self
,
tp
,
cname
):
type_index
=
self
.
_typesdict
[
tp
]
type_op
=
CffiOp
(
OP_ENUM
,
-
1
)
if
self
.
target_is_python
:
tp
.
check_not_partial
()
for
enumerator
,
enumvalue
in
zip
(
tp
.
enumerators
,
tp
.
enumvalues
):
self
.
_lsts
[
"global"
].
append
(
GlobalExpr
(
enumerator
,
'_cffi_const_%s'
%
enumerator
,
type_op
,
check_value
=
enumvalue
))
#
if
cname
is
not
None
and
'$'
not
in
cname
and
not
self
.
target_is_python
:
size
=
"sizeof(%s)"
%
cname
signed
=
"((%s)-1) <= 0"
%
cname
else
:
basetp
=
tp
.
build_baseinttype
(
self
.
ffi
,
[])
size
=
self
.
ffi
.
sizeof
(
basetp
)
signed
=
int
(
int
(
self
.
ffi
.
cast
(
basetp
,
-
1
))
<
0
)
allenums
=
","
.
join
(
tp
.
enumerators
)
self
.
_lsts
[
"enum"
].
append
(
EnumExpr
(
tp
.
name
,
type_index
,
size
,
signed
,
allenums
))
def
_generate_cpy_enum_ctx
(
self
,
tp
,
name
):
self
.
_enum_ctx
(
tp
,
tp
.
_get_c_name
())
# ----------
# macros: for now only for integers
def
_generate_cpy_macro_collecttype
(
self
,
tp
,
name
):
pass
def
_generate_cpy_macro_decl
(
self
,
tp
,
name
):
if
tp
==
'...'
:
check_value
=
None
else
:
check_value
=
tp
# an integer
self
.
_generate_cpy_const
(
True
,
name
,
check_value
=
check_value
)
def
_generate_cpy_macro_ctx
(
self
,
tp
,
name
):
if
tp
==
'...'
:
if
self
.
target_is_python
:
raise
VerificationError
(
"cannot use the syntax '...' in '#define %s ...' when "
"using the ABI mode"
%
(
name
,))
check_value
=
None
else
:
check_value
=
tp
# an integer
type_op
=
CffiOp
(
OP_CONSTANT_INT
,
-
1
)
self
.
_lsts
[
"global"
].
append
(
GlobalExpr
(
name
,
'_cffi_const_%s'
%
name
,
type_op
,
check_value
=
check_value
))
# ----------
# global variables
def
_global_type
(
self
,
tp
,
global_name
):
if
isinstance
(
tp
,
model
.
ArrayType
):
actual_length
=
tp
.
length
if
actual_length
==
'...'
:
actual_length
=
'_cffi_array_len(%s)'
%
(
global_name
,)
tp_item
=
self
.
_global_type
(
tp
.
item
,
'%s[0]'
%
global_name
)
tp
=
model
.
ArrayType
(
tp_item
,
actual_length
)
return
tp
def
_generate_cpy_variable_collecttype
(
self
,
tp
,
name
):
self
.
_do_collect_type
(
self
.
_global_type
(
tp
,
name
))
def
_generate_cpy_variable_decl
(
self
,
tp
,
name
):
prnt
=
self
.
_prnt
tp
=
self
.
_global_type
(
tp
,
name
)
if
isinstance
(
tp
,
model
.
ArrayType
)
and
tp
.
length
is
None
:
tp
=
tp
.
item
ampersand
=
''
else
:
ampersand
=
'&'
# This code assumes that casts from "tp *" to "void *" is a
# no-op, i.e. a function that returns a "tp *" can be called
# as if it returned a "void *". This should be generally true
# on any modern machine. The only exception to that rule (on
# uncommon architectures, and as far as I can tell) might be
# if 'tp' were a function type, but that is not possible here.
# (If 'tp' is a function _pointer_ type, then casts from "fn_t
# **" to "void *" are again no-ops, as far as I can tell.)
decl
=
'*_cffi_var_%s(void)'
%
(
name
,)
prnt
(
'static '
+
tp
.
get_c_name
(
decl
,
quals
=
self
.
_current_quals
))
prnt
(
'{'
)
prnt
(
' return %s(%s);'
%
(
ampersand
,
name
))
prnt
(
'}'
)
prnt
()
def
_generate_cpy_variable_ctx
(
self
,
tp
,
name
):
tp
=
self
.
_global_type
(
tp
,
name
)
type_index
=
self
.
_typesdict
[
tp
]
if
self
.
target_is_python
:
op
=
OP_GLOBAL_VAR
else
:
op
=
OP_GLOBAL_VAR_F
self
.
_lsts
[
"global"
].
append
(
GlobalExpr
(
name
,
'_cffi_var_%s'
%
name
,
CffiOp
(
op
,
type_index
)))
# ----------
# extern "Python"
def
_generate_cpy_extern_python_collecttype
(
self
,
tp
,
name
):
assert
isinstance
(
tp
,
model
.
FunctionPtrType
)
self
.
_do_collect_type
(
tp
)
_generate_cpy_dllexport_python_collecttype
=
\
_generate_cpy_extern_python_plus_c_collecttype
=
\
_generate_cpy_extern_python_collecttype
def
_extern_python_decl
(
self
,
tp
,
name
,
tag_and_space
):
prnt
=
self
.
_prnt
if
isinstance
(
tp
.
result
,
model
.
VoidType
):
size_of_result
=
'0'
else
:
context
=
'result of %s'
%
name
size_of_result
=
'(int)sizeof(%s)'
%
(
tp
.
result
.
get_c_name
(
''
,
context
),)
prnt
(
'static struct _cffi_externpy_s _cffi_externpy__%s ='
%
name
)
prnt
(
' { "%s.%s", %s, 0, 0 };'
%
(
self
.
module_name
,
name
,
size_of_result
))
prnt
()
#
arguments
=
[]
context
=
'argument of %s'
%
name
for
i
,
type
in
enumerate
(
tp
.
args
):
arg
=
type
.
get_c_name
(
' a%d'
%
i
,
context
)
arguments
.
append
(
arg
)
#
repr_arguments
=
', '
.
join
(
arguments
)
repr_arguments
=
repr_arguments
or
'void'
name_and_arguments
=
'%s(%s)'
%
(
name
,
repr_arguments
)
if
tp
.
abi
==
"__stdcall"
:
name_and_arguments
=
'_cffi_stdcall '
+
name_and_arguments
#
def
may_need_128_bits
(
tp
):
return
(
isinstance
(
tp
,
model
.
PrimitiveType
)
and
tp
.
name
==
'long double'
)
#
size_of_a
=
max
(
len
(
tp
.
args
)
*
8
,
8
)
if
may_need_128_bits
(
tp
.
result
):
size_of_a
=
max
(
size_of_a
,
16
)
if
isinstance
(
tp
.
result
,
model
.
StructOrUnion
):
size_of_a
=
'sizeof(%s) > %d ? sizeof(%s) : %d'
%
(
tp
.
result
.
get_c_name
(
''
),
size_of_a
,
tp
.
result
.
get_c_name
(
''
),
size_of_a
)
prnt
(
'%s%s'
%
(
tag_and_space
,
tp
.
result
.
get_c_name
(
name_and_arguments
)))
prnt
(
'{'
)
prnt
(
' char a[%s];'
%
size_of_a
)
prnt
(
' char *p = a;'
)
for
i
,
type
in
enumerate
(
tp
.
args
):
arg
=
'a%d'
%
i
if
(
isinstance
(
type
,
model
.
StructOrUnion
)
or
may_need_128_bits
(
type
)):
arg
=
'&'
+
arg
type
=
model
.
PointerType
(
type
)
prnt
(
' *(%s)(p + %d) = %s;'
%
(
type
.
get_c_name
(
'*'
),
i
*
8
,
arg
))
prnt
(
' _cffi_call_python(&_cffi_externpy__%s, p);'
%
name
)
if
not
isinstance
(
tp
.
result
,
model
.
VoidType
):
prnt
(
' return *(%s)p;'
%
(
tp
.
result
.
get_c_name
(
'*'
),))
prnt
(
'}'
)
prnt
()
self
.
_num_externpy
+=
1
def
_generate_cpy_extern_python_decl
(
self
,
tp
,
name
):
self
.
_extern_python_decl
(
tp
,
name
,
'static '
)
def
_generate_cpy_dllexport_python_decl
(
self
,
tp
,
name
):
self
.
_extern_python_decl
(
tp
,
name
,
'CFFI_DLLEXPORT '
)
def
_generate_cpy_extern_python_plus_c_decl
(
self
,
tp
,
name
):
self
.
_extern_python_decl
(
tp
,
name
,
''
)
def
_generate_cpy_extern_python_ctx
(
self
,
tp
,
name
):
if
self
.
target_is_python
:
raise
VerificationError
(
"cannot use 'extern
\"
Python
\"
' in the ABI mode"
)
if
tp
.
ellipsis
:
raise
NotImplementedError
(
"a vararg function is extern
\"
Python
\"
"
)
type_index
=
self
.
_typesdict
[
tp
]
type_op
=
CffiOp
(
OP_EXTERN_PYTHON
,
type_index
)
self
.
_lsts
[
"global"
].
append
(
GlobalExpr
(
name
,
'&_cffi_externpy__%s'
%
name
,
type_op
,
name
))
_generate_cpy_dllexport_python_ctx
=
\
_generate_cpy_extern_python_plus_c_ctx
=
\
_generate_cpy_extern_python_ctx
def
_print_string_literal_in_array
(
self
,
s
):
prnt
=
self
.
_prnt
prnt
(
'// # NB. this is not a string because of a size limit in MSVC'
)
for
line
in
s
.
splitlines
(
True
):
prnt
((
'// '
+
line
).
rstrip
())
printed_line
=
''
for
c
in
line
:
if
len
(
printed_line
)
>=
76
:
prnt
(
printed_line
)
printed_line
=
''
printed_line
+=
'%d,'
%
(
ord
(
c
),)
prnt
(
printed_line
)
# ----------
# emitting the opcodes for individual types
def
_emit_bytecode_VoidType
(
self
,
tp
,
index
):
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_PRIMITIVE
,
PRIM_VOID
)
def
_emit_bytecode_PrimitiveType
(
self
,
tp
,
index
):
prim_index
=
PRIMITIVE_TO_INDEX
[
tp
.
name
]
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_PRIMITIVE
,
prim_index
)
def
_emit_bytecode_UnknownIntegerType
(
self
,
tp
,
index
):
s
=
(
'_cffi_prim_int(sizeof(%s), (
\n
'
' ((%s)-1) | 0 /* check that %s is an integer type */
\n
'
' ) <= 0)'
%
(
tp
.
name
,
tp
.
name
,
tp
.
name
))
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_PRIMITIVE
,
s
)
def
_emit_bytecode_UnknownFloatType
(
self
,
tp
,
index
):
s
=
(
'_cffi_prim_float(sizeof(%s) *
\n
'
' (((%s)1) / 2) * 2 /* integer => 0, float => 1 */
\n
'
' )'
%
(
tp
.
name
,
tp
.
name
))
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_PRIMITIVE
,
s
)
def
_emit_bytecode_RawFunctionType
(
self
,
tp
,
index
):
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_FUNCTION
,
self
.
_typesdict
[
tp
.
result
])
index
+=
1
for
tp1
in
tp
.
args
:
realindex
=
self
.
_typesdict
[
tp1
]
if
index
!=
realindex
:
if
isinstance
(
tp1
,
model
.
PrimitiveType
):
self
.
_emit_bytecode_PrimitiveType
(
tp1
,
index
)
else
:
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_NOOP
,
realindex
)
index
+=
1
flags
=
int
(
tp
.
ellipsis
)
if
tp
.
abi
is
not
None
:
if
tp
.
abi
==
'__stdcall'
:
flags
|=
2
else
:
raise
NotImplementedError
(
"abi=%r"
%
(
tp
.
abi
,))
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_FUNCTION_END
,
flags
)
def
_emit_bytecode_PointerType
(
self
,
tp
,
index
):
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_POINTER
,
self
.
_typesdict
[
tp
.
totype
])
_emit_bytecode_ConstPointerType
=
_emit_bytecode_PointerType
_emit_bytecode_NamedPointerType
=
_emit_bytecode_PointerType
def
_emit_bytecode_FunctionPtrType
(
self
,
tp
,
index
):
raw
=
tp
.
as_raw_function
()
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_POINTER
,
self
.
_typesdict
[
raw
])
def
_emit_bytecode_ArrayType
(
self
,
tp
,
index
):
item_index
=
self
.
_typesdict
[
tp
.
item
]
if
tp
.
length
is
None
:
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_OPEN_ARRAY
,
item_index
)
elif
tp
.
length
==
'...'
:
raise
VerificationError
(
"type %s badly placed: the '...' array length can only be "
"used on global arrays or on fields of structures"
%
(
str
(
tp
).
replace
(
'/*...*/'
,
'...'
),))
else
:
assert
self
.
cffi_types
[
index
+
1
]
==
'LEN'
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_ARRAY
,
item_index
)
self
.
cffi_types
[
index
+
1
]
=
CffiOp
(
None
,
str
(
tp
.
length
))
def
_emit_bytecode_StructType
(
self
,
tp
,
index
):
struct_index
=
self
.
_struct_unions
[
tp
]
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_STRUCT_UNION
,
struct_index
)
_emit_bytecode_UnionType
=
_emit_bytecode_StructType
def
_emit_bytecode_EnumType
(
self
,
tp
,
index
):
enum_index
=
self
.
_enums
[
tp
]
self
.
cffi_types
[
index
]
=
CffiOp
(
OP_ENUM
,
enum_index
)
if
sys
.
version_info
>=
(
3
,):
NativeIO
=
io
.
StringIO
else
:
class
NativeIO
(
io
.
BytesIO
):
def
write
(
self
,
s
):
if
isinstance
(
s
,
unicode
):
s
=
s
.
encode
(
'ascii'
)
super
(
NativeIO
,
self
).
write
(
s
)
def
_make_c_or_py_source
(
ffi
,
module_name
,
preamble
,
target_file
,
verbose
):
if
verbose
:
print
(
"generating %s"
%
(
target_file
,))
recompiler
=
Recompiler
(
ffi
,
module_name
,
target_is_python
=
(
preamble
is
None
))
recompiler
.
collect_type_table
()
recompiler
.
collect_step_tables
()
f
=
NativeIO
()
recompiler
.
write_source_to_f
(
f
,
preamble
)
output
=
f
.
getvalue
()
try
:
with
open
(
target_file
,
'r'
)
as
f1
:
if
f1
.
read
(
len
(
output
)
+
1
)
!=
output
:
raise
IOError
if
verbose
:
print
(
"(already up-to-date)"
)
return
False
# already up-to-date
except
IOError
:
tmp_file
=
'%s.~%d'
%
(
target_file
,
os
.
getpid
())
with
open
(
tmp_file
,
'w'
)
as
f1
:
f1
.
write
(
output
)
try
:
os
.
rename
(
tmp_file
,
target_file
)
except
OSError
:
os
.
unlink
(
target_file
)
os
.
rename
(
tmp_file
,
target_file
)
return
True
def
make_c_source
(
ffi
,
module_name
,
preamble
,
target_c_file
,
verbose
=
False
):
assert
preamble
is
not
None
return
_make_c_or_py_source
(
ffi
,
module_name
,
preamble
,
target_c_file
,
verbose
)
def
make_py_source
(
ffi
,
module_name
,
target_py_file
,
verbose
=
False
):
return
_make_c_or_py_source
(
ffi
,
module_name
,
None
,
target_py_file
,
verbose
)
def
_modname_to_file
(
outputdir
,
modname
,
extension
):
parts
=
modname
.
split
(
'.'
)
try
:
os
.
makedirs
(
os
.
path
.
join
(
outputdir
,
*
parts
[:
-
1
]))
except
OSError
:
pass
parts
[
-
1
]
+=
extension
return
os
.
path
.
join
(
outputdir
,
*
parts
),
parts
# Aaargh. Distutils is not tested at all for the purpose of compiling
# DLLs that are not extension modules. Here are some hacks to work
# around that, in the _patch_for_*() functions...
def
_patch_meth
(
patchlist
,
cls
,
name
,
new_meth
):
old
=
getattr
(
cls
,
name
)
patchlist
.
append
((
cls
,
name
,
old
))
setattr
(
cls
,
name
,
new_meth
)
return
old
def
_unpatch_meths
(
patchlist
):
for
cls
,
name
,
old_meth
in
reversed
(
patchlist
):
setattr
(
cls
,
name
,
old_meth
)
def
_patch_for_embedding
(
patchlist
):
if
sys
.
platform
==
'win32'
:
# we must not remove the manifest when building for embedding!
from
distutils.msvc9compiler
import
MSVCCompiler
_patch_meth
(
patchlist
,
MSVCCompiler
,
'_remove_visual_c_ref'
,
lambda
self
,
manifest_file
:
manifest_file
)
if
sys
.
platform
==
'darwin'
:
# we must not make a '-bundle', but a '-dynamiclib' instead
from
distutils.ccompiler
import
CCompiler
def
my_link_shared_object
(
self
,
*
args
,
**
kwds
):
if
'-bundle'
in
self
.
linker_so
:
self
.
linker_so
=
list
(
self
.
linker_so
)
i
=
self
.
linker_so
.
index
(
'-bundle'
)
self
.
linker_so
[
i
]
=
'-dynamiclib'
return
old_link_shared_object
(
self
,
*
args
,
**
kwds
)
old_link_shared_object
=
_patch_meth
(
patchlist
,
CCompiler
,
'link_shared_object'
,
my_link_shared_object
)
def
_patch_for_target
(
patchlist
,
target
):
from
distutils.command.build_ext
import
build_ext
# if 'target' is different from '*', we need to patch some internal
# method to just return this 'target' value, instead of having it
# built from module_name
if
target
.
endswith
(
'.*'
):
target
=
target
[:
-
2
]
if
sys
.
platform
==
'win32'
:
target
+=
'.dll'
elif
sys
.
platform
==
'darwin'
:
target
+=
'.dylib'
else
:
target
+=
'.so'
_patch_meth
(
patchlist
,
build_ext
,
'get_ext_filename'
,
lambda
self
,
ext_name
:
target
)
def
recompile
(
ffi
,
module_name
,
preamble
,
tmpdir
=
'.'
,
call_c_compiler
=
True
,
c_file
=
None
,
source_extension
=
'.c'
,
extradir
=
None
,
compiler_verbose
=
1
,
target
=
None
,
debug
=
None
,
**
kwds
):
if
not
isinstance
(
module_name
,
str
):
module_name
=
module_name
.
encode
(
'ascii'
)
if
ffi
.
_windows_unicode
:
ffi
.
_apply_windows_unicode
(
kwds
)
if
preamble
is
not
None
:
embedding
=
(
ffi
.
_embedding
is
not
None
)
if
embedding
:
ffi
.
_apply_embedding_fix
(
kwds
)
if
c_file
is
None
:
c_file
,
parts
=
_modname_to_file
(
tmpdir
,
module_name
,
source_extension
)
if
extradir
:
parts
=
[
extradir
]
+
parts
ext_c_file
=
os
.
path
.
join
(
*
parts
)
else
:
ext_c_file
=
c_file
#
if
target
is
None
:
if
embedding
:
target
=
'%s.*'
%
module_name
else
:
target
=
'*'
#
ext
=
ffiplatform
.
get_extension
(
ext_c_file
,
module_name
,
**
kwds
)
updated
=
make_c_source
(
ffi
,
module_name
,
preamble
,
c_file
,
verbose
=
compiler_verbose
)
if
call_c_compiler
:
patchlist
=
[]
cwd
=
os
.
getcwd
()
try
:
if
embedding
:
_patch_for_embedding
(
patchlist
)
if
target
!=
'*'
:
_patch_for_target
(
patchlist
,
target
)
if
compiler_verbose
:
if
tmpdir
==
'.'
:
msg
=
'the current directory is'
else
:
msg
=
'setting the current directory to'
print
(
'%s %r'
%
(
msg
,
os
.
path
.
abspath
(
tmpdir
)))
os
.
chdir
(
tmpdir
)
outputfilename
=
ffiplatform
.
compile
(
'.'
,
ext
,
compiler_verbose
,
debug
)
finally
:
os
.
chdir
(
cwd
)
_unpatch_meths
(
patchlist
)
return
outputfilename
else
:
return
ext
,
updated
else
:
if
c_file
is
None
:
c_file
,
_
=
_modname_to_file
(
tmpdir
,
module_name
,
'.py'
)
updated
=
make_py_source
(
ffi
,
module_name
,
c_file
,
verbose
=
compiler_verbose
)
if
call_c_compiler
:
return
c_file
else
:
return
None
,
updated
env/lib/python3.5/site-packages/cffi/setuptools_ext.py
0 → 100644
View file @
ff4a13ed
import
os
import
sys
try
:
basestring
except
NameError
:
# Python 3.x
basestring
=
str
def
error
(
msg
):
from
distutils.errors
import
DistutilsSetupError
raise
DistutilsSetupError
(
msg
)
def
execfile
(
filename
,
glob
):
# We use execfile() (here rewritten for Python 3) instead of
# __import__() to load the build script. The problem with
# a normal import is that in some packages, the intermediate
# __init__.py files may already try to import the file that
# we are generating.
with
open
(
filename
)
as
f
:
src
=
f
.
read
()
src
+=
'
\n
'
# Python 2.6 compatibility
code
=
compile
(
src
,
filename
,
'exec'
)
exec
(
code
,
glob
,
glob
)
def
add_cffi_module
(
dist
,
mod_spec
):
from
cffi.api
import
FFI
if
not
isinstance
(
mod_spec
,
basestring
):
error
(
"argument to 'cffi_modules=...' must be a str or a list of str,"
" not %r"
%
(
type
(
mod_spec
).
__name__
,))
mod_spec
=
str
(
mod_spec
)
try
:
build_file_name
,
ffi_var_name
=
mod_spec
.
split
(
':'
)
except
ValueError
:
error
(
"%r must be of the form 'path/build.py:ffi_variable'"
%
(
mod_spec
,))
if
not
os
.
path
.
exists
(
build_file_name
):
ext
=
''
rewritten
=
build_file_name
.
replace
(
'.'
,
'/'
)
+
'.py'
if
os
.
path
.
exists
(
rewritten
):
ext
=
' (rewrite cffi_modules to [%r])'
%
(
rewritten
+
':'
+
ffi_var_name
,)
error
(
"%r does not name an existing file%s"
%
(
build_file_name
,
ext
))
mod_vars
=
{
'__name__'
:
'__cffi__'
,
'__file__'
:
build_file_name
}
execfile
(
build_file_name
,
mod_vars
)
try
:
ffi
=
mod_vars
[
ffi_var_name
]
except
KeyError
:
error
(
"%r: object %r not found in module"
%
(
mod_spec
,
ffi_var_name
))
if
not
isinstance
(
ffi
,
FFI
):
ffi
=
ffi
()
# maybe it's a function instead of directly an ffi
if
not
isinstance
(
ffi
,
FFI
):
error
(
"%r is not an FFI instance (got %r)"
%
(
mod_spec
,
type
(
ffi
).
__name__
))
if
not
hasattr
(
ffi
,
'_assigned_source'
):
error
(
"%r: the set_source() method was not called"
%
(
mod_spec
,))
module_name
,
source
,
source_extension
,
kwds
=
ffi
.
_assigned_source
if
ffi
.
_windows_unicode
:
kwds
=
kwds
.
copy
()
ffi
.
_apply_windows_unicode
(
kwds
)
if
source
is
None
:
_add_py_module
(
dist
,
ffi
,
module_name
)
else
:
_add_c_module
(
dist
,
ffi
,
module_name
,
source
,
source_extension
,
kwds
)
def
_set_py_limited_api
(
Extension
,
kwds
):
"""
Add py_limited_api to kwds if setuptools >= 26 is in use.
Do not alter the setting if it already exists.
Setuptools takes care of ignoring the flag on Python 2 and PyPy.
CPython itself should ignore the flag in a debugging version
(by not listing .abi3.so in the extensions it supports), but
it doesn't so far, creating troubles. That's why we check
for "not hasattr(sys, 'gettotalrefcount')" (the 2.7 compatible equivalent
of 'd' not in sys.abiflags). (http://bugs.python.org/issue28401)
On Windows, with CPython <= 3.4, it's better not to use py_limited_api
because virtualenv *still* doesn't copy PYTHON3.DLL on these versions.
For now we'll skip py_limited_api on all Windows versions to avoid an
inconsistent mess.
"""
if
(
'py_limited_api'
not
in
kwds
and
not
hasattr
(
sys
,
'gettotalrefcount'
)
and
sys
.
platform
!=
'win32'
):
import
setuptools
try
:
setuptools_major_version
=
int
(
setuptools
.
__version__
.
partition
(
'.'
)[
0
])
if
setuptools_major_version
>=
26
:
kwds
[
'py_limited_api'
]
=
True
except
ValueError
:
# certain development versions of setuptools
# If we don't know the version number of setuptools, we
# try to set 'py_limited_api' anyway. At worst, we get a
# warning.
kwds
[
'py_limited_api'
]
=
True
return
kwds
def
_add_c_module
(
dist
,
ffi
,
module_name
,
source
,
source_extension
,
kwds
):
from
distutils.core
import
Extension
# We are a setuptools extension. Need this build_ext for py_limited_api.
from
setuptools.command.build_ext
import
build_ext
from
distutils.dir_util
import
mkpath
from
distutils
import
log
from
cffi
import
recompiler
allsources
=
[
'$PLACEHOLDER'
]
allsources
.
extend
(
kwds
.
pop
(
'sources'
,
[]))
kwds
=
_set_py_limited_api
(
Extension
,
kwds
)
ext
=
Extension
(
name
=
module_name
,
sources
=
allsources
,
**
kwds
)
def
make_mod
(
tmpdir
,
pre_run
=
None
):
c_file
=
os
.
path
.
join
(
tmpdir
,
module_name
+
source_extension
)
log
.
info
(
"generating cffi module %r"
%
c_file
)
mkpath
(
tmpdir
)
# a setuptools-only, API-only hook: called with the "ext" and "ffi"
# arguments just before we turn the ffi into C code. To use it,
# subclass the 'distutils.command.build_ext.build_ext' class and
# add a method 'def pre_run(self, ext, ffi)'.
if
pre_run
is
not
None
:
pre_run
(
ext
,
ffi
)
updated
=
recompiler
.
make_c_source
(
ffi
,
module_name
,
source
,
c_file
)
if
not
updated
:
log
.
info
(
"already up-to-date"
)
return
c_file
if
dist
.
ext_modules
is
None
:
dist
.
ext_modules
=
[]
dist
.
ext_modules
.
append
(
ext
)
base_class
=
dist
.
cmdclass
.
get
(
'build_ext'
,
build_ext
)
class
build_ext_make_mod
(
base_class
):
def
run
(
self
):
if
ext
.
sources
[
0
]
==
'$PLACEHOLDER'
:
pre_run
=
getattr
(
self
,
'pre_run'
,
None
)
ext
.
sources
[
0
]
=
make_mod
(
self
.
build_temp
,
pre_run
)
base_class
.
run
(
self
)
dist
.
cmdclass
[
'build_ext'
]
=
build_ext_make_mod
# NB. multiple runs here will create multiple 'build_ext_make_mod'
# classes. Even in this case the 'build_ext' command should be
# run once; but just in case, the logic above does nothing if
# called again.
def
_add_py_module
(
dist
,
ffi
,
module_name
):
from
distutils.dir_util
import
mkpath
from
setuptools.command.build_py
import
build_py
from
setuptools.command.build_ext
import
build_ext
from
distutils
import
log
from
cffi
import
recompiler
def
generate_mod
(
py_file
):
log
.
info
(
"generating cffi module %r"
%
py_file
)
mkpath
(
os
.
path
.
dirname
(
py_file
))
updated
=
recompiler
.
make_py_source
(
ffi
,
module_name
,
py_file
)
if
not
updated
:
log
.
info
(
"already up-to-date"
)
base_class
=
dist
.
cmdclass
.
get
(
'build_py'
,
build_py
)
class
build_py_make_mod
(
base_class
):
def
run
(
self
):
base_class
.
run
(
self
)
module_path
=
module_name
.
split
(
'.'
)
module_path
[
-
1
]
+=
'.py'
generate_mod
(
os
.
path
.
join
(
self
.
build_lib
,
*
module_path
))
def
get_source_files
(
self
):
# This is called from 'setup.py sdist' only. Exclude
# the generate .py module in this case.
saved_py_modules
=
self
.
py_modules
try
:
if
saved_py_modules
:
self
.
py_modules
=
[
m
for
m
in
saved_py_modules
if
m
!=
module_name
]
return
base_class
.
get_source_files
(
self
)
finally
:
self
.
py_modules
=
saved_py_modules
dist
.
cmdclass
[
'build_py'
]
=
build_py_make_mod
# distutils and setuptools have no notion I could find of a
# generated python module. If we don't add module_name to
# dist.py_modules, then things mostly work but there are some
# combination of options (--root and --record) that will miss
# the module. So we add it here, which gives a few apparently
# harmless warnings about not finding the file outside the
# build directory.
# Then we need to hack more in get_source_files(); see above.
if
dist
.
py_modules
is
None
:
dist
.
py_modules
=
[]
dist
.
py_modules
.
append
(
module_name
)
# the following is only for "build_ext -i"
base_class_2
=
dist
.
cmdclass
.
get
(
'build_ext'
,
build_ext
)
class
build_ext_make_mod
(
base_class_2
):
def
run
(
self
):
base_class_2
.
run
(
self
)
if
self
.
inplace
:
# from get_ext_fullpath() in distutils/command/build_ext.py
module_path
=
module_name
.
split
(
'.'
)
package
=
'.'
.
join
(
module_path
[:
-
1
])
build_py
=
self
.
get_finalized_command
(
'build_py'
)
package_dir
=
build_py
.
get_package_dir
(
package
)
file_name
=
module_path
[
-
1
]
+
'.py'
generate_mod
(
os
.
path
.
join
(
package_dir
,
file_name
))
dist
.
cmdclass
[
'build_ext'
]
=
build_ext_make_mod
def
cffi_modules
(
dist
,
attr
,
value
):
assert
attr
==
'cffi_modules'
if
isinstance
(
value
,
basestring
):
value
=
[
value
]
for
cffi_module
in
value
:
add_cffi_module
(
dist
,
cffi_module
)
env/lib/python3.5/site-packages/cffi/vengine_cpy.py
0 → 100644
View file @
ff4a13ed
#
# DEPRECATED: implementation for ffi.verify()
#
import
sys
,
imp
from
.
import
model
from
.error
import
VerificationError
class
VCPythonEngine
(
object
):
_class_key
=
'x'
_gen_python_module
=
True
def
__init__
(
self
,
verifier
):
self
.
verifier
=
verifier
self
.
ffi
=
verifier
.
ffi
self
.
_struct_pending_verification
=
{}
self
.
_types_of_builtin_functions
=
{}
def
patch_extension_kwds
(
self
,
kwds
):
pass
def
find_module
(
self
,
module_name
,
path
,
so_suffixes
):
try
:
f
,
filename
,
descr
=
imp
.
find_module
(
module_name
,
path
)
except
ImportError
:
return
None
if
f
is
not
None
:
f
.
close
()
# Note that after a setuptools installation, there are both .py
# and .so files with the same basename. The code here relies on
# imp.find_module() locating the .so in priority.
if
descr
[
0
]
not
in
so_suffixes
:
return
None
return
filename
def
collect_types
(
self
):
self
.
_typesdict
=
{}
self
.
_generate
(
"collecttype"
)
def
_prnt
(
self
,
what
=
''
):
self
.
_f
.
write
(
what
+
'
\n
'
)
def
_gettypenum
(
self
,
type
):
# a KeyError here is a bug. please report it! :-)
return
self
.
_typesdict
[
type
]
def
_do_collect_type
(
self
,
tp
):
if
((
not
isinstance
(
tp
,
model
.
PrimitiveType
)
or
tp
.
name
==
'long double'
)
and
tp
not
in
self
.
_typesdict
):
num
=
len
(
self
.
_typesdict
)
self
.
_typesdict
[
tp
]
=
num
def
write_source_to_f
(
self
):
self
.
collect_types
()
#
# The new module will have a _cffi_setup() function that receives
# objects from the ffi world, and that calls some setup code in
# the module. This setup code is split in several independent
# functions, e.g. one per constant. The functions are "chained"
# by ending in a tail call to each other.
#
# This is further split in two chained lists, depending on if we
# can do it at import-time or if we must wait for _cffi_setup() to
# provide us with the <ctype> objects. This is needed because we
# need the values of the enum constants in order to build the
# <ctype 'enum'> that we may have to pass to _cffi_setup().
#
# The following two 'chained_list_constants' items contains
# the head of these two chained lists, as a string that gives the
# call to do, if any.
self
.
_chained_list_constants
=
[
'((void)lib,0)'
,
'((void)lib,0)'
]
#
prnt
=
self
.
_prnt
# first paste some standard set of lines that are mostly '#define'
prnt
(
cffimod_header
)
prnt
()
# then paste the C source given by the user, verbatim.
prnt
(
self
.
verifier
.
preamble
)
prnt
()
#
# call generate_cpy_xxx_decl(), for every xxx found from
# ffi._parser._declarations. This generates all the functions.
self
.
_generate
(
"decl"
)
#
# implement the function _cffi_setup_custom() as calling the
# head of the chained list.
self
.
_generate_setup_custom
()
prnt
()
#
# produce the method table, including the entries for the
# generated Python->C function wrappers, which are done
# by generate_cpy_function_method().
prnt
(
'static PyMethodDef _cffi_methods[] = {'
)
self
.
_generate
(
"method"
)
prnt
(
' {"_cffi_setup", _cffi_setup, METH_VARARGS, NULL},'
)
prnt
(
' {NULL, NULL, 0, NULL} /* Sentinel */'
)
prnt
(
'};'
)
prnt
()
#
# standard init.
modname
=
self
.
verifier
.
get_module_name
()
constants
=
self
.
_chained_list_constants
[
False
]
prnt
(
'#if PY_MAJOR_VERSION >= 3'
)
prnt
()
prnt
(
'static struct PyModuleDef _cffi_module_def = {'
)
prnt
(
' PyModuleDef_HEAD_INIT,'
)
prnt
(
' "%s",'
%
modname
)
prnt
(
' NULL,'
)
prnt
(
' -1,'
)
prnt
(
' _cffi_methods,'
)
prnt
(
' NULL, NULL, NULL, NULL'
)
prnt
(
'};'
)
prnt
()
prnt
(
'PyMODINIT_FUNC'
)
prnt
(
'PyInit_%s(void)'
%
modname
)
prnt
(
'{'
)
prnt
(
' PyObject *lib;'
)
prnt
(
' lib = PyModule_Create(&_cffi_module_def);'
)
prnt
(
' if (lib == NULL)'
)
prnt
(
' return NULL;'
)
prnt
(
' if (%s < 0 || _cffi_init() < 0) {'
%
(
constants
,))
prnt
(
' Py_DECREF(lib);'
)
prnt
(
' return NULL;'
)
prnt
(
' }'
)
prnt
(
' return lib;'
)
prnt
(
'}'
)
prnt
()
prnt
(
'#else'
)
prnt
()
prnt
(
'PyMODINIT_FUNC'
)
prnt
(
'init%s(void)'
%
modname
)
prnt
(
'{'
)
prnt
(
' PyObject *lib;'
)
prnt
(
' lib = Py_InitModule("%s", _cffi_methods);'
%
modname
)
prnt
(
' if (lib == NULL)'
)
prnt
(
' return;'
)
prnt
(
' if (%s < 0 || _cffi_init() < 0)'
%
(
constants
,))
prnt
(
' return;'
)
prnt
(
' return;'
)
prnt
(
'}'
)
prnt
()
prnt
(
'#endif'
)
def
load_library
(
self
,
flags
=
None
):
# XXX review all usages of 'self' here!
# import it as a new extension module
imp
.
acquire_lock
()
try
:
if
hasattr
(
sys
,
"getdlopenflags"
):
previous_flags
=
sys
.
getdlopenflags
()
try
:
if
hasattr
(
sys
,
"setdlopenflags"
)
and
flags
is
not
None
:
sys
.
setdlopenflags
(
flags
)
module
=
imp
.
load_dynamic
(
self
.
verifier
.
get_module_name
(),
self
.
verifier
.
modulefilename
)
except
ImportError
as
e
:
error
=
"importing %r: %s"
%
(
self
.
verifier
.
modulefilename
,
e
)
raise
VerificationError
(
error
)
finally
:
if
hasattr
(
sys
,
"setdlopenflags"
):
sys
.
setdlopenflags
(
previous_flags
)
finally
:
imp
.
release_lock
()
#
# call loading_cpy_struct() to get the struct layout inferred by
# the C compiler
self
.
_load
(
module
,
'loading'
)
#
# the C code will need the <ctype> objects. Collect them in
# order in a list.
revmapping
=
dict
([(
value
,
key
)
for
(
key
,
value
)
in
self
.
_typesdict
.
items
()])
lst
=
[
revmapping
[
i
]
for
i
in
range
(
len
(
revmapping
))]
lst
=
list
(
map
(
self
.
ffi
.
_get_cached_btype
,
lst
))
#
# build the FFILibrary class and instance and call _cffi_setup().
# this will set up some fields like '_cffi_types', and only then
# it will invoke the chained list of functions that will really
# build (notably) the constant objects, as <cdata> if they are
# pointers, and store them as attributes on the 'library' object.
class
FFILibrary
(
object
):
_cffi_python_module
=
module
_cffi_ffi
=
self
.
ffi
_cffi_dir
=
[]
def
__dir__
(
self
):
return
FFILibrary
.
_cffi_dir
+
list
(
self
.
__dict__
)
library
=
FFILibrary
()
if
module
.
_cffi_setup
(
lst
,
VerificationError
,
library
):
import
warnings
warnings
.
warn
(
"reimporting %r might overwrite older definitions"
%
(
self
.
verifier
.
get_module_name
()))
#
# finally, call the loaded_cpy_xxx() functions. This will perform
# the final adjustments, like copying the Python->C wrapper
# functions from the module to the 'library' object, and setting
# up the FFILibrary class with properties for the global C variables.
self
.
_load
(
module
,
'loaded'
,
library
=
library
)
module
.
_cffi_original_ffi
=
self
.
ffi
module
.
_cffi_types_of_builtin_funcs
=
self
.
_types_of_builtin_functions
return
library
def
_get_declarations
(
self
):
lst
=
[(
key
,
tp
)
for
(
key
,
(
tp
,
qual
))
in
self
.
ffi
.
_parser
.
_declarations
.
items
()]
lst
.
sort
()
return
lst
def
_generate
(
self
,
step_name
):
for
name
,
tp
in
self
.
_get_declarations
():
kind
,
realname
=
name
.
split
(
' '
,
1
)
try
:
method
=
getattr
(
self
,
'_generate_cpy_%s_%s'
%
(
kind
,
step_name
))
except
AttributeError
:
raise
VerificationError
(
"not implemented in verify(): %r"
%
name
)
try
:
method
(
tp
,
realname
)
except
Exception
as
e
:
model
.
attach_exception_info
(
e
,
name
)
raise
def
_load
(
self
,
module
,
step_name
,
**
kwds
):
for
name
,
tp
in
self
.
_get_declarations
():
kind
,
realname
=
name
.
split
(
' '
,
1
)
method
=
getattr
(
self
,
'_%s_cpy_%s'
%
(
step_name
,
kind
))
try
:
method
(
tp
,
realname
,
module
,
**
kwds
)
except
Exception
as
e
:
model
.
attach_exception_info
(
e
,
name
)
raise
def
_generate_nothing
(
self
,
tp
,
name
):
pass
def
_loaded_noop
(
self
,
tp
,
name
,
module
,
**
kwds
):
pass
# ----------
def
_convert_funcarg_to_c
(
self
,
tp
,
fromvar
,
tovar
,
errcode
):
extraarg
=
''
if
isinstance
(
tp
,
model
.
PrimitiveType
):
if
tp
.
is_integer_type
()
and
tp
.
name
!=
'_Bool'
:
converter
=
'_cffi_to_c_int'
extraarg
=
', %s'
%
tp
.
name
else
:
converter
=
'(%s)_cffi_to_c_%s'
%
(
tp
.
get_c_name
(
''
),
tp
.
name
.
replace
(
' '
,
'_'
))
errvalue
=
'-1'
#
elif
isinstance
(
tp
,
model
.
PointerType
):
self
.
_convert_funcarg_to_c_ptr_or_array
(
tp
,
fromvar
,
tovar
,
errcode
)
return
#
elif
isinstance
(
tp
,
(
model
.
StructOrUnion
,
model
.
EnumType
)):
# a struct (not a struct pointer) as a function argument
self
.
_prnt
(
' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)'
%
(
tovar
,
self
.
_gettypenum
(
tp
),
fromvar
))
self
.
_prnt
(
' %s;'
%
errcode
)
return
#
elif
isinstance
(
tp
,
model
.
FunctionPtrType
):
converter
=
'(%s)_cffi_to_c_pointer'
%
tp
.
get_c_name
(
''
)
extraarg
=
', _cffi_type(%d)'
%
self
.
_gettypenum
(
tp
)
errvalue
=
'NULL'
#
else
:
raise
NotImplementedError
(
tp
)
#
self
.
_prnt
(
' %s = %s(%s%s);'
%
(
tovar
,
converter
,
fromvar
,
extraarg
))
self
.
_prnt
(
' if (%s == (%s)%s && PyErr_Occurred())'
%
(
tovar
,
tp
.
get_c_name
(
''
),
errvalue
))
self
.
_prnt
(
' %s;'
%
errcode
)
def
_extra_local_variables
(
self
,
tp
,
localvars
,
freelines
):
if
isinstance
(
tp
,
model
.
PointerType
):
localvars
.
add
(
'Py_ssize_t datasize'
)
localvars
.
add
(
'struct _cffi_freeme_s *large_args_free = NULL'
)
freelines
.
add
(
'if (large_args_free != NULL)'
' _cffi_free_array_arguments(large_args_free);'
)
def
_convert_funcarg_to_c_ptr_or_array
(
self
,
tp
,
fromvar
,
tovar
,
errcode
):
self
.
_prnt
(
' datasize = _cffi_prepare_pointer_call_argument('
)
self
.
_prnt
(
' _cffi_type(%d), %s, (char **)&%s);'
%
(
self
.
_gettypenum
(
tp
),
fromvar
,
tovar
))
self
.
_prnt
(
' if (datasize != 0) {'
)
self
.
_prnt
(
' %s = ((size_t)datasize) <= 640 ? '
'alloca((size_t)datasize) : NULL;'
%
(
tovar
,))
self
.
_prnt
(
' if (_cffi_convert_array_argument(_cffi_type(%d), %s, '
'(char **)&%s,'
%
(
self
.
_gettypenum
(
tp
),
fromvar
,
tovar
))
self
.
_prnt
(
' datasize, &large_args_free) < 0)'
)
self
.
_prnt
(
' %s;'
%
errcode
)
self
.
_prnt
(
' }'
)
def
_convert_expr_from_c
(
self
,
tp
,
var
,
context
):
if
isinstance
(
tp
,
model
.
PrimitiveType
):
if
tp
.
is_integer_type
()
and
tp
.
name
!=
'_Bool'
:
return
'_cffi_from_c_int(%s, %s)'
%
(
var
,
tp
.
name
)
elif
tp
.
name
!=
'long double'
:
return
'_cffi_from_c_%s(%s)'
%
(
tp
.
name
.
replace
(
' '
,
'_'
),
var
)
else
:
return
'_cffi_from_c_deref((char *)&%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
tp
))
elif
isinstance
(
tp
,
(
model
.
PointerType
,
model
.
FunctionPtrType
)):
return
'_cffi_from_c_pointer((char *)%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
tp
))
elif
isinstance
(
tp
,
model
.
ArrayType
):
return
'_cffi_from_c_pointer((char *)%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
model
.
PointerType
(
tp
.
item
)))
elif
isinstance
(
tp
,
model
.
StructOrUnion
):
if
tp
.
fldnames
is
None
:
raise
TypeError
(
"'%s' is used as %s, but is opaque"
%
(
tp
.
_get_c_name
(),
context
))
return
'_cffi_from_c_struct((char *)&%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
tp
))
elif
isinstance
(
tp
,
model
.
EnumType
):
return
'_cffi_from_c_deref((char *)&%s, _cffi_type(%d))'
%
(
var
,
self
.
_gettypenum
(
tp
))
else
:
raise
NotImplementedError
(
tp
)
# ----------
# typedefs: generates no code so far
_generate_cpy_typedef_collecttype
=
_generate_nothing
_generate_cpy_typedef_decl
=
_generate_nothing
_generate_cpy_typedef_method
=
_generate_nothing
_loading_cpy_typedef
=
_loaded_noop
_loaded_cpy_typedef
=
_loaded_noop
# ----------
# function declarations
def
_generate_cpy_function_collecttype
(
self
,
tp
,
name
):
assert
isinstance
(
tp
,
model
.
FunctionPtrType
)
if
tp
.
ellipsis
:
self
.
_do_collect_type
(
tp
)
else
:
# don't call _do_collect_type(tp) in this common case,
# otherwise test_autofilled_struct_as_argument fails
for
type
in
tp
.
args
:
self
.
_do_collect_type
(
type
)
self
.
_do_collect_type
(
tp
.
result
)
def
_generate_cpy_function_decl
(
self
,
tp
,
name
):
assert
isinstance
(
tp
,
model
.
FunctionPtrType
)
if
tp
.
ellipsis
:
# cannot support vararg functions better than this: check for its
# exact type (including the fixed arguments), and build it as a
# constant function pointer (no CPython wrapper)
self
.
_generate_cpy_const
(
False
,
name
,
tp
)
return
prnt
=
self
.
_prnt
numargs
=
len
(
tp
.
args
)
if
numargs
==
0
:
argname
=
'noarg'
elif
numargs
==
1
:
argname
=
'arg0'
else
:
argname
=
'args'
prnt
(
'static PyObject *'
)
prnt
(
'_cffi_f_%s(PyObject *self, PyObject *%s)'
%
(
name
,
argname
))
prnt
(
'{'
)
#
context
=
'argument of %s'
%
name
for
i
,
type
in
enumerate
(
tp
.
args
):
prnt
(
' %s;'
%
type
.
get_c_name
(
' x%d'
%
i
,
context
))
#
localvars
=
set
()
freelines
=
set
()
for
type
in
tp
.
args
:
self
.
_extra_local_variables
(
type
,
localvars
,
freelines
)
for
decl
in
sorted
(
localvars
):
prnt
(
' %s;'
%
(
decl
,))
#
if
not
isinstance
(
tp
.
result
,
model
.
VoidType
):
result_code
=
'result = '
context
=
'result of %s'
%
name
prnt
(
' %s;'
%
tp
.
result
.
get_c_name
(
' result'
,
context
))
prnt
(
' PyObject *pyresult;'
)
else
:
result_code
=
''
#
if
len
(
tp
.
args
)
>
1
:
rng
=
range
(
len
(
tp
.
args
))
for
i
in
rng
:
prnt
(
' PyObject *arg%d;'
%
i
)
prnt
()
prnt
(
' if (!PyArg_ParseTuple(args, "%s:%s", %s))'
%
(
'O'
*
numargs
,
name
,
', '
.
join
([
'&arg%d'
%
i
for
i
in
rng
])))
prnt
(
' return NULL;'
)
prnt
()
#
for
i
,
type
in
enumerate
(
tp
.
args
):
self
.
_convert_funcarg_to_c
(
type
,
'arg%d'
%
i
,
'x%d'
%
i
,
'return NULL'
)
prnt
()
#
prnt
(
' Py_BEGIN_ALLOW_THREADS'
)
prnt
(
' _cffi_restore_errno();'
)
prnt
(
' { %s%s(%s); }'
%
(
result_code
,
name
,
', '
.
join
([
'x%d'
%
i
for
i
in
range
(
len
(
tp
.
args
))])))
prnt
(
' _cffi_save_errno();'
)
prnt
(
' Py_END_ALLOW_THREADS'
)
prnt
()
#
prnt
(
' (void)self; /* unused */'
)
if
numargs
==
0
:
prnt
(
' (void)noarg; /* unused */'
)
if
result_code
:
prnt
(
' pyresult = %s;'
%
self
.
_convert_expr_from_c
(
tp
.
result
,
'result'
,
'result type'
))
for
freeline
in
freelines
:
prnt
(
' '
+
freeline
)
prnt
(
' return pyresult;'
)
else
:
for
freeline
in
freelines
:
prnt
(
' '
+
freeline
)
prnt
(
' Py_INCREF(Py_None);'
)
prnt
(
' return Py_None;'
)
prnt
(
'}'
)
prnt
()
def
_generate_cpy_function_method
(
self
,
tp
,
name
):
if
tp
.
ellipsis
:
return
numargs
=
len
(
tp
.
args
)
if
numargs
==
0
:
meth
=
'METH_NOARGS'
elif
numargs
==
1
:
meth
=
'METH_O'
else
:
meth
=
'METH_VARARGS'
self
.
_prnt
(
' {"%s", _cffi_f_%s, %s, NULL},'
%
(
name
,
name
,
meth
))
_loading_cpy_function
=
_loaded_noop
def
_loaded_cpy_function
(
self
,
tp
,
name
,
module
,
library
):
if
tp
.
ellipsis
:
return
func
=
getattr
(
module
,
name
)
setattr
(
library
,
name
,
func
)
self
.
_types_of_builtin_functions
[
func
]
=
tp
# ----------
# named structs
_generate_cpy_struct_collecttype
=
_generate_nothing
def
_generate_cpy_struct_decl
(
self
,
tp
,
name
):
assert
name
==
tp
.
name
self
.
_generate_struct_or_union_decl
(
tp
,
'struct'
,
name
)
def
_generate_cpy_struct_method
(
self
,
tp
,
name
):
self
.
_generate_struct_or_union_method
(
tp
,
'struct'
,
name
)
def
_loading_cpy_struct
(
self
,
tp
,
name
,
module
):
self
.
_loading_struct_or_union
(
tp
,
'struct'
,
name
,
module
)
def
_loaded_cpy_struct
(
self
,
tp
,
name
,
module
,
**
kwds
):
self
.
_loaded_struct_or_union
(
tp
)
_generate_cpy_union_collecttype
=
_generate_nothing
def
_generate_cpy_union_decl
(
self
,
tp
,
name
):
assert
name
==
tp
.
name
self
.
_generate_struct_or_union_decl
(
tp
,
'union'
,
name
)
def
_generate_cpy_union_method
(
self
,
tp
,
name
):
self
.
_generate_struct_or_union_method
(
tp
,
'union'
,
name
)
def
_loading_cpy_union
(
self
,
tp
,
name
,
module
):
self
.
_loading_struct_or_union
(
tp
,
'union'
,
name
,
module
)
def
_loaded_cpy_union
(
self
,
tp
,
name
,
module
,
**
kwds
):
self
.
_loaded_struct_or_union
(
tp
)
def
_generate_struct_or_union_decl
(
self
,
tp
,
prefix
,
name
):
if
tp
.
fldnames
is
None
:
return
# nothing to do with opaque structs
checkfuncname
=
'_cffi_check_%s_%s'
%
(
prefix
,
name
)
layoutfuncname
=
'_cffi_layout_%s_%s'
%
(
prefix
,
name
)
cname
=
(
'%s %s'
%
(
prefix
,
name
)).
strip
()
#
prnt
=
self
.
_prnt
prnt
(
'static void %s(%s *p)'
%
(
checkfuncname
,
cname
))
prnt
(
'{'
)
prnt
(
' /* only to generate compile-time warnings or errors */'
)
prnt
(
' (void)p;'
)
for
fname
,
ftype
,
fbitsize
,
fqual
in
tp
.
enumfields
():
if
(
isinstance
(
ftype
,
model
.
PrimitiveType
)
and
ftype
.
is_integer_type
())
or
fbitsize
>=
0
:
# accept all integers, but complain on float or double
prnt
(
' (void)((p->%s) << 1);'
%
fname
)
else
:
# only accept exactly the type declared.
try
:
prnt
(
' { %s = &p->%s; (void)tmp; }'
%
(
ftype
.
get_c_name
(
'*tmp'
,
'field %r'
%
fname
,
quals
=
fqual
),
fname
))
except
VerificationError
as
e
:
prnt
(
' /* %s */'
%
str
(
e
))
# cannot verify it, ignore
prnt
(
'}'
)
prnt
(
'static PyObject *'
)
prnt
(
'%s(PyObject *self, PyObject *noarg)'
%
(
layoutfuncname
,))
prnt
(
'{'
)
prnt
(
' struct _cffi_aligncheck { char x; %s y; };'
%
cname
)
prnt
(
' static Py_ssize_t nums[] = {'
)
prnt
(
' sizeof(%s),'
%
cname
)
prnt
(
' offsetof(struct _cffi_aligncheck, y),'
)
for
fname
,
ftype
,
fbitsize
,
fqual
in
tp
.
enumfields
():
if
fbitsize
>=
0
:
continue
# xxx ignore fbitsize for now
prnt
(
' offsetof(%s, %s),'
%
(
cname
,
fname
))
if
isinstance
(
ftype
,
model
.
ArrayType
)
and
ftype
.
length
is
None
:
prnt
(
' 0, /* %s */'
%
ftype
.
_get_c_name
())
else
:
prnt
(
' sizeof(((%s *)0)->%s),'
%
(
cname
,
fname
))
prnt
(
' -1'
)
prnt
(
' };'
)
prnt
(
' (void)self; /* unused */'
)
prnt
(
' (void)noarg; /* unused */'
)
prnt
(
' return _cffi_get_struct_layout(nums);'
)
prnt
(
' /* the next line is not executed, but compiled */'
)
prnt
(
' %s(0);'
%
(
checkfuncname
,))
prnt
(
'}'
)
prnt
()
def
_generate_struct_or_union_method
(
self
,
tp
,
prefix
,
name
):
if
tp
.
fldnames
is
None
:
return
# nothing to do with opaque structs
layoutfuncname
=
'_cffi_layout_%s_%s'
%
(
prefix
,
name
)
self
.
_prnt
(
' {"%s", %s, METH_NOARGS, NULL},'
%
(
layoutfuncname
,
layoutfuncname
))
def
_loading_struct_or_union
(
self
,
tp
,
prefix
,
name
,
module
):
if
tp
.
fldnames
is
None
:
return
# nothing to do with opaque structs
layoutfuncname
=
'_cffi_layout_%s_%s'
%
(
prefix
,
name
)
#
function
=
getattr
(
module
,
layoutfuncname
)
layout
=
function
()
if
isinstance
(
tp
,
model
.
StructOrUnion
)
and
tp
.
partial
:
# use the function()'s sizes and offsets to guide the
# layout of the struct
totalsize
=
layout
[
0
]
totalalignment
=
layout
[
1
]
fieldofs
=
layout
[
2
::
2
]
fieldsize
=
layout
[
3
::
2
]
tp
.
force_flatten
()
assert
len
(
fieldofs
)
==
len
(
fieldsize
)
==
len
(
tp
.
fldnames
)
tp
.
fixedlayout
=
fieldofs
,
fieldsize
,
totalsize
,
totalalignment
else
:
cname
=
(
'%s %s'
%
(
prefix
,
name
)).
strip
()
self
.
_struct_pending_verification
[
tp
]
=
layout
,
cname
def
_loaded_struct_or_union
(
self
,
tp
):
if
tp
.
fldnames
is
None
:
return
# nothing to do with opaque structs
self
.
ffi
.
_get_cached_btype
(
tp
)
# force 'fixedlayout' to be considered
if
tp
in
self
.
_struct_pending_verification
:
# check that the layout sizes and offsets match the real ones
def
check
(
realvalue
,
expectedvalue
,
msg
):
if
realvalue
!=
expectedvalue
:
raise
VerificationError
(
"%s (we have %d, but C compiler says %d)"
%
(
msg
,
expectedvalue
,
realvalue
))
ffi
=
self
.
ffi
BStruct
=
ffi
.
_get_cached_btype
(
tp
)
layout
,
cname
=
self
.
_struct_pending_verification
.
pop
(
tp
)
check
(
layout
[
0
],
ffi
.
sizeof
(
BStruct
),
"wrong total size"
)
check
(
layout
[
1
],
ffi
.
alignof
(
BStruct
),
"wrong total alignment"
)
i
=
2
for
fname
,
ftype
,
fbitsize
,
fqual
in
tp
.
enumfields
():
if
fbitsize
>=
0
:
continue
# xxx ignore fbitsize for now
check
(
layout
[
i
],
ffi
.
offsetof
(
BStruct
,
fname
),
"wrong offset for field %r"
%
(
fname
,))
if
layout
[
i
+
1
]
!=
0
:
BField
=
ffi
.
_get_cached_btype
(
ftype
)
check
(
layout
[
i
+
1
],
ffi
.
sizeof
(
BField
),
"wrong size for field %r"
%
(
fname
,))
i
+=
2
assert
i
==
len
(
layout
)
# ----------
# 'anonymous' declarations. These are produced for anonymous structs
# or unions; the 'name' is obtained by a typedef.
_generate_cpy_anonymous_collecttype
=
_generate_nothing
def
_generate_cpy_anonymous_decl
(
self
,
tp
,
name
):
if
isinstance
(
tp
,
model
.
EnumType
):
self
.
_generate_cpy_enum_decl
(
tp
,
name
,
''
)
else
:
self
.
_generate_struct_or_union_decl
(
tp
,
''
,
name
)
def
_generate_cpy_anonymous_method
(
self
,
tp
,
name
):
if
not
isinstance
(
tp
,
model
.
EnumType
):
self
.
_generate_struct_or_union_method
(
tp
,
''
,
name
)
def
_loading_cpy_anonymous
(
self
,
tp
,
name
,
module
):
if
isinstance
(
tp
,
model
.
EnumType
):
self
.
_loading_cpy_enum
(
tp
,
name
,
module
)
else
:
self
.
_loading_struct_or_union
(
tp
,
''
,
name
,
module
)
def
_loaded_cpy_anonymous
(
self
,
tp
,
name
,
module
,
**
kwds
):
if
isinstance
(
tp
,
model
.
EnumType
):
self
.
_loaded_cpy_enum
(
tp
,
name
,
module
,
**
kwds
)
else
:
self
.
_loaded_struct_or_union
(
tp
)
# ----------
# constants, likely declared with '#define'
def
_generate_cpy_const
(
self
,
is_int
,
name
,
tp
=
None
,
category
=
'const'
,
vartp
=
None
,
delayed
=
True
,
size_too
=
False
,
check_value
=
None
):
prnt
=
self
.
_prnt
funcname
=
'_cffi_%s_%s'
%
(
category
,
name
)
prnt
(
'static int %s(PyObject *lib)'
%
funcname
)
prnt
(
'{'
)
prnt
(
' PyObject *o;'
)
prnt
(
' int res;'
)
if
not
is_int
:
prnt
(
' %s;'
%
(
vartp
or
tp
).
get_c_name
(
' i'
,
name
))
else
:
assert
category
==
'const'
#
if
check_value
is
not
None
:
self
.
_check_int_constant_value
(
name
,
check_value
)
#
if
not
is_int
:
if
category
==
'var'
:
realexpr
=
'&'
+
name
else
:
realexpr
=
name
prnt
(
' i = (%s);'
%
(
realexpr
,))
prnt
(
' o = %s;'
%
(
self
.
_convert_expr_from_c
(
tp
,
'i'
,
'variable type'
),))
assert
delayed
else
:
prnt
(
' o = _cffi_from_c_int_const(%s);'
%
name
)
prnt
(
' if (o == NULL)'
)
prnt
(
' return -1;'
)
if
size_too
:
prnt
(
' {'
)
prnt
(
' PyObject *o1 = o;'
)
prnt
(
' o = Py_BuildValue("On", o1, (Py_ssize_t)sizeof(%s));'
%
(
name
,))
prnt
(
' Py_DECREF(o1);'
)
prnt
(
' if (o == NULL)'
)
prnt
(
' return -1;'
)
prnt
(
' }'
)
prnt
(
' res = PyObject_SetAttrString(lib, "%s", o);'
%
name
)
prnt
(
' Py_DECREF(o);'
)
prnt
(
' if (res < 0)'
)
prnt
(
' return -1;'
)
prnt
(
' return %s;'
%
self
.
_chained_list_constants
[
delayed
])
self
.
_chained_list_constants
[
delayed
]
=
funcname
+
'(lib)'
prnt
(
'}'
)
prnt
()
def
_generate_cpy_constant_collecttype
(
self
,
tp
,
name
):
is_int
=
isinstance
(
tp
,
model
.
PrimitiveType
)
and
tp
.
is_integer_type
()
if
not
is_int
:
self
.
_do_collect_type
(
tp
)
def
_generate_cpy_constant_decl
(
self
,
tp
,
name
):
is_int
=
isinstance
(
tp
,
model
.
PrimitiveType
)
and
tp
.
is_integer_type
()
self
.
_generate_cpy_const
(
is_int
,
name
,
tp
)
_generate_cpy_constant_method
=
_generate_nothing
_loading_cpy_constant
=
_loaded_noop
_loaded_cpy_constant
=
_loaded_noop
# ----------
# enums
def
_check_int_constant_value
(
self
,
name
,
value
,
err_prefix
=
''
):
prnt
=
self
.
_prnt
if
value
<=
0
:
prnt
(
' if ((%s) > 0 || (long)(%s) != %dL) {'
%
(
name
,
name
,
value
))
else
:
prnt
(
' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {'
%
(
name
,
name
,
value
))
prnt
(
' char buf[64];'
)
prnt
(
' if ((%s) <= 0)'
%
name
)
prnt
(
' snprintf(buf, 63, "%%ld", (long)(%s));'
%
name
)
prnt
(
' else'
)
prnt
(
' snprintf(buf, 63, "%%lu", (unsigned long)(%s));'
%
name
)
prnt
(
' PyErr_Format(_cffi_VerificationError,'
)
prnt
(
' "%s%s has the real value %s, not %s",'
)
prnt
(
' "%s", "%s", buf, "%d");'
%
(
err_prefix
,
name
,
value
))
prnt
(
' return -1;'
)
prnt
(
' }'
)
def
_enum_funcname
(
self
,
prefix
,
name
):
# "$enum_$1" => "___D_enum____D_1"
name
=
name
.
replace
(
'$'
,
'___D_'
)
return
'_cffi_e_%s_%s'
%
(
prefix
,
name
)
def
_generate_cpy_enum_decl
(
self
,
tp
,
name
,
prefix
=
'enum'
):
if
tp
.
partial
:
for
enumerator
in
tp
.
enumerators
:
self
.
_generate_cpy_const
(
True
,
enumerator
,
delayed
=
False
)
return
#
funcname
=
self
.
_enum_funcname
(
prefix
,
name
)
prnt
=
self
.
_prnt
prnt
(
'static int %s(PyObject *lib)'
%
funcname
)
prnt
(
'{'
)
for
enumerator
,
enumvalue
in
zip
(
tp
.
enumerators
,
tp
.
enumvalues
):
self
.
_check_int_constant_value
(
enumerator
,
enumvalue
,
"enum %s: "
%
name
)
prnt
(
' return %s;'
%
self
.
_chained_list_constants
[
True
])
self
.
_chained_list_constants
[
True
]
=
funcname
+
'(lib)'
prnt
(
'}'
)
prnt
()
_generate_cpy_enum_collecttype
=
_generate_nothing
_generate_cpy_enum_method
=
_generate_nothing
def
_loading_cpy_enum
(
self
,
tp
,
name
,
module
):
if
tp
.
partial
:
enumvalues
=
[
getattr
(
module
,
enumerator
)
for
enumerator
in
tp
.
enumerators
]
tp
.
enumvalues
=
tuple
(
enumvalues
)
tp
.
partial_resolved
=
True
def
_loaded_cpy_enum
(
self
,
tp
,
name
,
module
,
library
):
for
enumerator
,
enumvalue
in
zip
(
tp
.
enumerators
,
tp
.
enumvalues
):
setattr
(
library
,
enumerator
,
enumvalue
)
# ----------
# macros: for now only for integers
def
_generate_cpy_macro_decl
(
self
,
tp
,
name
):
if
tp
==
'...'
:
check_value
=
None
else
:
check_value
=
tp
# an integer
self
.
_generate_cpy_const
(
True
,
name
,
check_value
=
check_value
)
_generate_cpy_macro_collecttype
=
_generate_nothing
_generate_cpy_macro_method
=
_generate_nothing
_loading_cpy_macro
=
_loaded_noop
_loaded_cpy_macro
=
_loaded_noop
# ----------
# global variables
def
_generate_cpy_variable_collecttype
(
self
,
tp
,
name
):
if
isinstance
(
tp
,
model
.
ArrayType
):
tp_ptr
=
model
.
PointerType
(
tp
.
item
)
else
:
tp_ptr
=
model
.
PointerType
(
tp
)
self
.
_do_collect_type
(
tp_ptr
)
def
_generate_cpy_variable_decl
(
self
,
tp
,
name
):
if
isinstance
(
tp
,
model
.
ArrayType
):
tp_ptr
=
model
.
PointerType
(
tp
.
item
)
self
.
_generate_cpy_const
(
False
,
name
,
tp
,
vartp
=
tp_ptr
,
size_too
=
(
tp
.
length
==
'...'
))
else
:
tp_ptr
=
model
.
PointerType
(
tp
)
self
.
_generate_cpy_const
(
False
,
name
,
tp_ptr
,
category
=
'var'
)
_generate_cpy_variable_method
=
_generate_nothing
_loading_cpy_variable
=
_loaded_noop
def
_loaded_cpy_variable
(
self
,
tp
,
name
,
module
,
library
):
value
=
getattr
(
library
,
name
)
if
isinstance
(
tp
,
model
.
ArrayType
):
# int a[5] is "constant" in the
# sense that "a=..." is forbidden
if
tp
.
length
==
'...'
:
assert
isinstance
(
value
,
tuple
)
(
value
,
size
)
=
value
BItemType
=
self
.
ffi
.
_get_cached_btype
(
tp
.
item
)
length
,
rest
=
divmod
(
size
,
self
.
ffi
.
sizeof
(
BItemType
))
if
rest
!=
0
:
raise
VerificationError
(
"bad size: %r does not seem to be an array of %s"
%
(
name
,
tp
.
item
))
tp
=
tp
.
resolve_length
(
length
)
# 'value' is a <cdata 'type *'> which we have to replace with
# a <cdata 'type[N]'> if the N is actually known
if
tp
.
length
is
not
None
:
BArray
=
self
.
ffi
.
_get_cached_btype
(
tp
)
value
=
self
.
ffi
.
cast
(
BArray
,
value
)
setattr
(
library
,
name
,
value
)
return
# remove ptr=<cdata 'int *'> from the library instance, and replace
# it by a property on the class, which reads/writes into ptr[0].
ptr
=
value
delattr
(
library
,
name
)
def
getter
(
library
):
return
ptr
[
0
]
def
setter
(
library
,
value
):
ptr
[
0
]
=
value
setattr
(
type
(
library
),
name
,
property
(
getter
,
setter
))
type
(
library
).
_cffi_dir
.
append
(
name
)
# ----------
def
_generate_setup_custom
(
self
):
prnt
=
self
.
_prnt
prnt
(
'static int _cffi_setup_custom(PyObject *lib)'
)
prnt
(
'{'
)
prnt
(
' return %s;'
%
self
.
_chained_list_constants
[
True
])
prnt
(
'}'
)
cffimod_header
=
r
'''
#include <Python.h>
#include <stddef.h>
/* this block of #ifs should be kept exactly identical between
c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py
and cffi/_cffi_include.h */
#if defined(_MSC_VER)
# include <malloc.h> /* for alloca() */
# if _MSC_VER < 1600 /* MSVC < 2010 */
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef __int8 int_least8_t;
typedef __int16 int_least16_t;
typedef __int32 int_least32_t;
typedef __int64 int_least64_t;
typedef unsigned __int8 uint_least8_t;
typedef unsigned __int16 uint_least16_t;
typedef unsigned __int32 uint_least32_t;
typedef unsigned __int64 uint_least64_t;
typedef __int8 int_fast8_t;
typedef __int16 int_fast16_t;
typedef __int32 int_fast32_t;
typedef __int64 int_fast64_t;
typedef unsigned __int8 uint_fast8_t;
typedef unsigned __int16 uint_fast16_t;
typedef unsigned __int32 uint_fast32_t;
typedef unsigned __int64 uint_fast64_t;
typedef __int64 intmax_t;
typedef unsigned __int64 uintmax_t;
# else
# include <stdint.h>
# endif
# if _MSC_VER < 1800 /* MSVC < 2013 */
# ifndef __cplusplus
typedef unsigned char _Bool;
# endif
# endif
#else
# include <stdint.h>
# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
# include <alloca.h>
# endif
#endif
#if PY_MAJOR_VERSION < 3
# undef PyCapsule_CheckExact
# undef PyCapsule_GetPointer
# define PyCapsule_CheckExact(capsule) (PyCObject_Check(capsule))
# define PyCapsule_GetPointer(capsule, name) \
(PyCObject_AsVoidPtr(capsule))
#endif
#if PY_MAJOR_VERSION >= 3
# define PyInt_FromLong PyLong_FromLong
#endif
#define _cffi_from_c_double PyFloat_FromDouble
#define _cffi_from_c_float PyFloat_FromDouble
#define _cffi_from_c_long PyInt_FromLong
#define _cffi_from_c_ulong PyLong_FromUnsignedLong
#define _cffi_from_c_longlong PyLong_FromLongLong
#define _cffi_from_c_ulonglong PyLong_FromUnsignedLongLong
#define _cffi_from_c__Bool PyBool_FromLong
#define _cffi_to_c_double PyFloat_AsDouble
#define _cffi_to_c_float PyFloat_AsDouble
#define _cffi_from_c_int_const(x) \
(((x) > 0) ? \
((unsigned long long)(x) <= (unsigned long long)LONG_MAX) ? \
PyInt_FromLong((long)(x)) : \
PyLong_FromUnsignedLongLong((unsigned long long)(x)) : \
((long long)(x) >= (long long)LONG_MIN) ? \
PyInt_FromLong((long)(x)) : \
PyLong_FromLongLong((long long)(x)))
#define _cffi_from_c_int(x, type) \
(((type)-1) > 0 ? /* unsigned */ \
(sizeof(type) < sizeof(long) ? \
PyInt_FromLong((long)x) : \
sizeof(type) == sizeof(long) ? \
PyLong_FromUnsignedLong((unsigned long)x) : \
PyLong_FromUnsignedLongLong((unsigned long long)x)) : \
(sizeof(type) <= sizeof(long) ? \
PyInt_FromLong((long)x) : \
PyLong_FromLongLong((long long)x)))
#define _cffi_to_c_int(o, type) \
((type)( \
sizeof(type) == 1 ? (((type)-1) > 0 ? (type)_cffi_to_c_u8(o) \
: (type)_cffi_to_c_i8(o)) : \
sizeof(type) == 2 ? (((type)-1) > 0 ? (type)_cffi_to_c_u16(o) \
: (type)_cffi_to_c_i16(o)) : \
sizeof(type) == 4 ? (((type)-1) > 0 ? (type)_cffi_to_c_u32(o) \
: (type)_cffi_to_c_i32(o)) : \
sizeof(type) == 8 ? (((type)-1) > 0 ? (type)_cffi_to_c_u64(o) \
: (type)_cffi_to_c_i64(o)) : \
(Py_FatalError("unsupported size for type " #type), (type)0)))
#define _cffi_to_c_i8 \
((int(*)(PyObject *))_cffi_exports[1])
#define _cffi_to_c_u8 \
((int(*)(PyObject *))_cffi_exports[2])
#define _cffi_to_c_i16 \
((int(*)(PyObject *))_cffi_exports[3])
#define _cffi_to_c_u16 \
((int(*)(PyObject *))_cffi_exports[4])
#define _cffi_to_c_i32 \
((int(*)(PyObject *))_cffi_exports[5])
#define _cffi_to_c_u32 \
((unsigned int(*)(PyObject *))_cffi_exports[6])
#define _cffi_to_c_i64 \
((long long(*)(PyObject *))_cffi_exports[7])
#define _cffi_to_c_u64 \
((unsigned long long(*)(PyObject *))_cffi_exports[8])
#define _cffi_to_c_char \
((int(*)(PyObject *))_cffi_exports[9])
#define _cffi_from_c_pointer \
((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[10])
#define _cffi_to_c_pointer \
((char *(*)(PyObject *, CTypeDescrObject *))_cffi_exports[11])
#define _cffi_get_struct_layout \
((PyObject *(*)(Py_ssize_t[]))_cffi_exports[12])
#define _cffi_restore_errno \
((void(*)(void))_cffi_exports[13])
#define _cffi_save_errno \
((void(*)(void))_cffi_exports[14])
#define _cffi_from_c_char \
((PyObject *(*)(char))_cffi_exports[15])
#define _cffi_from_c_deref \
((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[16])
#define _cffi_to_c \
((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[17])
#define _cffi_from_c_struct \
((PyObject *(*)(char *, CTypeDescrObject *))_cffi_exports[18])
#define _cffi_to_c_wchar_t \
((wchar_t(*)(PyObject *))_cffi_exports[19])
#define _cffi_from_c_wchar_t \
((PyObject *(*)(wchar_t))_cffi_exports[20])
#define _cffi_to_c_long_double \
((long double(*)(PyObject *))_cffi_exports[21])
#define _cffi_to_c__Bool \
((_Bool(*)(PyObject *))_cffi_exports[22])
#define _cffi_prepare_pointer_call_argument \
((Py_ssize_t(*)(CTypeDescrObject *, PyObject *, char **))_cffi_exports[23])
#define _cffi_convert_array_from_object \
((int(*)(char *, CTypeDescrObject *, PyObject *))_cffi_exports[24])
#define _CFFI_NUM_EXPORTS 25
typedef struct _ctypedescr CTypeDescrObject;
static void *_cffi_exports[_CFFI_NUM_EXPORTS];
static PyObject *_cffi_types, *_cffi_VerificationError;
static int _cffi_setup_custom(PyObject *lib); /* forward */
static PyObject *_cffi_setup(PyObject *self, PyObject *args)
{
PyObject *library;
int was_alive = (_cffi_types != NULL);
(void)self; /* unused */
if (!PyArg_ParseTuple(args, "OOO", &_cffi_types, &_cffi_VerificationError,
&library))
return NULL;
Py_INCREF(_cffi_types);
Py_INCREF(_cffi_VerificationError);
if (_cffi_setup_custom(library) < 0)
return NULL;
return PyBool_FromLong(was_alive);
}
union _cffi_union_alignment_u {
unsigned char m_char;
unsigned short m_short;
unsigned int m_int;
unsigned long m_long;
unsigned long long m_longlong;
float m_float;
double m_double;
long double m_longdouble;
};
struct _cffi_freeme_s {
struct _cffi_freeme_s *next;
union _cffi_union_alignment_u alignment;
};
#ifdef __GNUC__
__attribute__((unused))
#endif
static int _cffi_convert_array_argument(CTypeDescrObject *ctptr, PyObject *arg,
char **output_data, Py_ssize_t datasize,
struct _cffi_freeme_s **freeme)
{
char *p;
if (datasize < 0)
return -1;
p = *output_data;
if (p == NULL) {
struct _cffi_freeme_s *fp = (struct _cffi_freeme_s *)PyObject_Malloc(
offsetof(struct _cffi_freeme_s, alignment) + (size_t)datasize);
if (fp == NULL)
return -1;
fp->next = *freeme;
*freeme = fp;
p = *output_data = (char *)&fp->alignment;
}
memset((void *)p, 0, (size_t)datasize);
return _cffi_convert_array_from_object(p, ctptr, arg);
}
#ifdef __GNUC__
__attribute__((unused))
#endif
static void _cffi_free_array_arguments(struct _cffi_freeme_s *freeme)
{
do {
void *p = (void *)freeme;
freeme = freeme->next;
PyObject_Free(p);
} while (freeme != NULL);
}
static int _cffi_init(void)
{
PyObject *module, *c_api_object = NULL;
module = PyImport_ImportModule("_cffi_backend");
if (module == NULL)
goto failure;
c_api_object = PyObject_GetAttrString(module, "_C_API");
if (c_api_object == NULL)
goto failure;
if (!PyCapsule_CheckExact(c_api_object)) {
PyErr_SetNone(PyExc_ImportError);
goto failure;
}
memcpy(_cffi_exports, PyCapsule_GetPointer(c_api_object, "cffi"),
_CFFI_NUM_EXPORTS * sizeof(void *));
Py_DECREF(module);
Py_DECREF(c_api_object);
return 0;
failure:
Py_XDECREF(module);
Py_XDECREF(c_api_object);
return -1;
}
#define _cffi_type(num) ((CTypeDescrObject *)PyList_GET_ITEM(_cffi_types, num))
/**********/
'''
env/lib/python3.5/site-packages/cffi/vengine_gen.py
0 → 100644
View file @
ff4a13ed
#
# DEPRECATED: implementation for ffi.verify()
#
import
sys
,
os
import
types
from
.
import
model
from
.error
import
VerificationError
class
VGenericEngine
(
object
):
_class_key
=
'g'
_gen_python_module
=
False
def
__init__
(
self
,
verifier
):
self
.
verifier
=
verifier
self
.
ffi
=
verifier
.
ffi
self
.
export_symbols
=
[]
self
.
_struct_pending_verification
=
{}
def
patch_extension_kwds
(
self
,
kwds
):
# add 'export_symbols' to the dictionary. Note that we add the
# list before filling it. When we fill it, it will thus also show
# up in kwds['export_symbols'].
kwds
.
setdefault
(
'export_symbols'
,
self
.
export_symbols
)
def
find_module
(
self
,
module_name
,
path
,
so_suffixes
):
for
so_suffix
in
so_suffixes
:
basename
=
module_name
+
so_suffix
if
path
is
None
:
path
=
sys
.
path
for
dirname
in
path
:
filename
=
os
.
path
.
join
(
dirname
,
basename
)
if
os
.
path
.
isfile
(
filename
):
return
filename
def
collect_types
(
self
):
pass
# not needed in the generic engine
def
_prnt
(
self
,
what
=
''
):
self
.
_f
.
write
(
what
+
'
\n
'
)
def
write_source_to_f
(
self
):
prnt
=
self
.
_prnt
# first paste some standard set of lines that are mostly '#include'
prnt
(
cffimod_header
)
# then paste the C source given by the user, verbatim.
prnt
(
self
.
verifier
.
preamble
)
#
# call generate_gen_xxx_decl(), for every xxx found from
# ffi._parser._declarations. This generates all the functions.
self
.
_generate
(
'decl'
)
#
# on Windows, distutils insists on putting init_cffi_xyz in
# 'export_symbols', so instead of fighting it, just give up and
# give it one
if
sys
.
platform
==
'win32'
:
if
sys
.
version_info
>=
(
3
,):
prefix
=
'PyInit_'
else
:
prefix
=
'init'
modname
=
self
.
verifier
.
get_module_name
()
prnt
(
"void %s%s(void) { }
\n
"
%
(
prefix
,
modname
))
def
load_library
(
self
,
flags
=
0
):
# import it with the CFFI backend
backend
=
self
.
ffi
.
_backend
# needs to make a path that contains '/', on Posix
filename
=
os
.
path
.
join
(
os
.
curdir
,
self
.
verifier
.
modulefilename
)
module
=
backend
.
load_library
(
filename
,
flags
)
#
# call loading_gen_struct() to get the struct layout inferred by
# the C compiler
self
.
_load
(
module
,
'loading'
)
# build the FFILibrary class and instance, this is a module subclass
# because modules are expected to have usually-constant-attributes and
# in PyPy this means the JIT is able to treat attributes as constant,
# which we want.
class
FFILibrary
(
types
.
ModuleType
):
_cffi_generic_module
=
module
_cffi_ffi
=
self
.
ffi
_cffi_dir
=
[]
def
__dir__
(
self
):
return
FFILibrary
.
_cffi_dir
library
=
FFILibrary
(
""
)
#
# finally, call the loaded_gen_xxx() functions. This will set
# up the 'library' object.
self
.
_load
(
module
,
'loaded'
,
library
=
library
)
return
library
def
_get_declarations
(
self
):
lst
=
[(
key
,
tp
)
for
(
key
,
(
tp
,
qual
))
in
self
.
ffi
.
_parser
.
_declarations
.
items
()]
lst
.
sort
()
return
lst
def
_generate
(
self
,
step_name
):
for
name
,
tp
in
self
.
_get_declarations
():
kind
,
realname
=
name
.
split
(
' '
,
1
)
try
:
method
=
getattr
(
self
,
'_generate_gen_%s_%s'
%
(
kind
,
step_name
))
except
AttributeError
:
raise
VerificationError
(
"not implemented in verify(): %r"
%
name
)
try
:
method
(
tp
,
realname
)
except
Exception
as
e
:
model
.
attach_exception_info
(
e
,
name
)
raise
def
_load
(
self
,
module
,
step_name
,
**
kwds
):
for
name
,
tp
in
self
.
_get_declarations
():
kind
,
realname
=
name
.
split
(
' '
,
1
)
method
=
getattr
(
self
,
'_%s_gen_%s'
%
(
step_name
,
kind
))
try
:
method
(
tp
,
realname
,
module
,
**
kwds
)
except
Exception
as
e
:
model
.
attach_exception_info
(
e
,
name
)
raise
def
_generate_nothing
(
self
,
tp
,
name
):
pass
def
_loaded_noop
(
self
,
tp
,
name
,
module
,
**
kwds
):
pass
# ----------
# typedefs: generates no code so far
_generate_gen_typedef_decl
=
_generate_nothing
_loading_gen_typedef
=
_loaded_noop
_loaded_gen_typedef
=
_loaded_noop
# ----------
# function declarations
def
_generate_gen_function_decl
(
self
,
tp
,
name
):
assert
isinstance
(
tp
,
model
.
FunctionPtrType
)
if
tp
.
ellipsis
:
# cannot support vararg functions better than this: check for its
# exact type (including the fixed arguments), and build it as a
# constant function pointer (no _cffi_f_%s wrapper)
self
.
_generate_gen_const
(
False
,
name
,
tp
)
return
prnt
=
self
.
_prnt
numargs
=
len
(
tp
.
args
)
argnames
=
[]
for
i
,
type
in
enumerate
(
tp
.
args
):
indirection
=
''
if
isinstance
(
type
,
model
.
StructOrUnion
):
indirection
=
'*'
argnames
.
append
(
'%sx%d'
%
(
indirection
,
i
))
context
=
'argument of %s'
%
name
arglist
=
[
type
.
get_c_name
(
' %s'
%
arg
,
context
)
for
type
,
arg
in
zip
(
tp
.
args
,
argnames
)]
tpresult
=
tp
.
result
if
isinstance
(
tpresult
,
model
.
StructOrUnion
):
arglist
.
insert
(
0
,
tpresult
.
get_c_name
(
' *r'
,
context
))
tpresult
=
model
.
void_type
arglist
=
', '
.
join
(
arglist
)
or
'void'
wrappername
=
'_cffi_f_%s'
%
name
self
.
export_symbols
.
append
(
wrappername
)
if
tp
.
abi
:
abi
=
tp
.
abi
+
' '
else
:
abi
=
''
funcdecl
=
' %s%s(%s)'
%
(
abi
,
wrappername
,
arglist
)
context
=
'result of %s'
%
name
prnt
(
tpresult
.
get_c_name
(
funcdecl
,
context
))
prnt
(
'{'
)
#
if
isinstance
(
tp
.
result
,
model
.
StructOrUnion
):
result_code
=
'*r = '
elif
not
isinstance
(
tp
.
result
,
model
.
VoidType
):
result_code
=
'return '
else
:
result_code
=
''
prnt
(
' %s%s(%s);'
%
(
result_code
,
name
,
', '
.
join
(
argnames
)))
prnt
(
'}'
)
prnt
()
_loading_gen_function
=
_loaded_noop
def
_loaded_gen_function
(
self
,
tp
,
name
,
module
,
library
):
assert
isinstance
(
tp
,
model
.
FunctionPtrType
)
if
tp
.
ellipsis
:
newfunction
=
self
.
_load_constant
(
False
,
tp
,
name
,
module
)
else
:
indirections
=
[]
base_tp
=
tp
if
(
any
(
isinstance
(
typ
,
model
.
StructOrUnion
)
for
typ
in
tp
.
args
)
or
isinstance
(
tp
.
result
,
model
.
StructOrUnion
)):
indirect_args
=
[]
for
i
,
typ
in
enumerate
(
tp
.
args
):
if
isinstance
(
typ
,
model
.
StructOrUnion
):
typ
=
model
.
PointerType
(
typ
)
indirections
.
append
((
i
,
typ
))
indirect_args
.
append
(
typ
)
indirect_result
=
tp
.
result
if
isinstance
(
indirect_result
,
model
.
StructOrUnion
):
if
indirect_result
.
fldtypes
is
None
:
raise
TypeError
(
"'%s' is used as result type, "
"but is opaque"
%
(
indirect_result
.
_get_c_name
(),))
indirect_result
=
model
.
PointerType
(
indirect_result
)
indirect_args
.
insert
(
0
,
indirect_result
)
indirections
.
insert
(
0
,
(
"result"
,
indirect_result
))
indirect_result
=
model
.
void_type
tp
=
model
.
FunctionPtrType
(
tuple
(
indirect_args
),
indirect_result
,
tp
.
ellipsis
)
BFunc
=
self
.
ffi
.
_get_cached_btype
(
tp
)
wrappername
=
'_cffi_f_%s'
%
name
newfunction
=
module
.
load_function
(
BFunc
,
wrappername
)
for
i
,
typ
in
indirections
:
newfunction
=
self
.
_make_struct_wrapper
(
newfunction
,
i
,
typ
,
base_tp
)
setattr
(
library
,
name
,
newfunction
)
type
(
library
).
_cffi_dir
.
append
(
name
)
def
_make_struct_wrapper
(
self
,
oldfunc
,
i
,
tp
,
base_tp
):
backend
=
self
.
ffi
.
_backend
BType
=
self
.
ffi
.
_get_cached_btype
(
tp
)
if
i
==
"result"
:
ffi
=
self
.
ffi
def
newfunc
(
*
args
):
res
=
ffi
.
new
(
BType
)
oldfunc
(
res
,
*
args
)
return
res
[
0
]
else
:
def
newfunc
(
*
args
):
args
=
args
[:
i
]
+
(
backend
.
newp
(
BType
,
args
[
i
]),)
+
args
[
i
+
1
:]
return
oldfunc
(
*
args
)
newfunc
.
_cffi_base_type
=
base_tp
return
newfunc
# ----------
# named structs
def
_generate_gen_struct_decl
(
self
,
tp
,
name
):
assert
name
==
tp
.
name
self
.
_generate_struct_or_union_decl
(
tp
,
'struct'
,
name
)
def
_loading_gen_struct
(
self
,
tp
,
name
,
module
):
self
.
_loading_struct_or_union
(
tp
,
'struct'
,
name
,
module
)
def
_loaded_gen_struct
(
self
,
tp
,
name
,
module
,
**
kwds
):
self
.
_loaded_struct_or_union
(
tp
)
def
_generate_gen_union_decl
(
self
,
tp
,
name
):
assert
name
==
tp
.
name
self
.
_generate_struct_or_union_decl
(
tp
,
'union'
,
name
)
def
_loading_gen_union
(
self
,
tp
,
name
,
module
):
self
.
_loading_struct_or_union
(
tp
,
'union'
,
name
,
module
)
def
_loaded_gen_union
(
self
,
tp
,
name
,
module
,
**
kwds
):
self
.
_loaded_struct_or_union
(
tp
)
def
_generate_struct_or_union_decl
(
self
,
tp
,
prefix
,
name
):
if
tp
.
fldnames
is
None
:
return
# nothing to do with opaque structs
checkfuncname
=
'_cffi_check_%s_%s'
%
(
prefix
,
name
)
layoutfuncname
=
'_cffi_layout_%s_%s'
%
(
prefix
,
name
)
cname
=
(
'%s %s'
%
(
prefix
,
name
)).
strip
()
#
prnt
=
self
.
_prnt
prnt
(
'static void %s(%s *p)'
%
(
checkfuncname
,
cname
))
prnt
(
'{'
)
prnt
(
' /* only to generate compile-time warnings or errors */'
)
prnt
(
' (void)p;'
)
for
fname
,
ftype
,
fbitsize
,
fqual
in
tp
.
enumfields
():
if
(
isinstance
(
ftype
,
model
.
PrimitiveType
)
and
ftype
.
is_integer_type
())
or
fbitsize
>=
0
:
# accept all integers, but complain on float or double
prnt
(
' (void)((p->%s) << 1);'
%
fname
)
else
:
# only accept exactly the type declared.
try
:
prnt
(
' { %s = &p->%s; (void)tmp; }'
%
(
ftype
.
get_c_name
(
'*tmp'
,
'field %r'
%
fname
,
quals
=
fqual
),
fname
))
except
VerificationError
as
e
:
prnt
(
' /* %s */'
%
str
(
e
))
# cannot verify it, ignore
prnt
(
'}'
)
self
.
export_symbols
.
append
(
layoutfuncname
)
prnt
(
'intptr_t %s(intptr_t i)'
%
(
layoutfuncname
,))
prnt
(
'{'
)
prnt
(
' struct _cffi_aligncheck { char x; %s y; };'
%
cname
)
prnt
(
' static intptr_t nums[] = {'
)
prnt
(
' sizeof(%s),'
%
cname
)
prnt
(
' offsetof(struct _cffi_aligncheck, y),'
)
for
fname
,
ftype
,
fbitsize
,
fqual
in
tp
.
enumfields
():
if
fbitsize
>=
0
:
continue
# xxx ignore fbitsize for now
prnt
(
' offsetof(%s, %s),'
%
(
cname
,
fname
))
if
isinstance
(
ftype
,
model
.
ArrayType
)
and
ftype
.
length
is
None
:
prnt
(
' 0, /* %s */'
%
ftype
.
_get_c_name
())
else
:
prnt
(
' sizeof(((%s *)0)->%s),'
%
(
cname
,
fname
))
prnt
(
' -1'
)
prnt
(
' };'
)
prnt
(
' return nums[i];'
)
prnt
(
' /* the next line is not executed, but compiled */'
)
prnt
(
' %s(0);'
%
(
checkfuncname
,))
prnt
(
'}'
)
prnt
()
def
_loading_struct_or_union
(
self
,
tp
,
prefix
,
name
,
module
):
if
tp
.
fldnames
is
None
:
return
# nothing to do with opaque structs
layoutfuncname
=
'_cffi_layout_%s_%s'
%
(
prefix
,
name
)
#
BFunc
=
self
.
ffi
.
_typeof_locked
(
"intptr_t(*)(intptr_t)"
)[
0
]
function
=
module
.
load_function
(
BFunc
,
layoutfuncname
)
layout
=
[]
num
=
0
while
True
:
x
=
function
(
num
)
if
x
<
0
:
break
layout
.
append
(
x
)
num
+=
1
if
isinstance
(
tp
,
model
.
StructOrUnion
)
and
tp
.
partial
:
# use the function()'s sizes and offsets to guide the
# layout of the struct
totalsize
=
layout
[
0
]
totalalignment
=
layout
[
1
]
fieldofs
=
layout
[
2
::
2
]
fieldsize
=
layout
[
3
::
2
]
tp
.
force_flatten
()
assert
len
(
fieldofs
)
==
len
(
fieldsize
)
==
len
(
tp
.
fldnames
)
tp
.
fixedlayout
=
fieldofs
,
fieldsize
,
totalsize
,
totalalignment
else
:
cname
=
(
'%s %s'
%
(
prefix
,
name
)).
strip
()
self
.
_struct_pending_verification
[
tp
]
=
layout
,
cname
def
_loaded_struct_or_union
(
self
,
tp
):
if
tp
.
fldnames
is
None
:
return
# nothing to do with opaque structs
self
.
ffi
.
_get_cached_btype
(
tp
)
# force 'fixedlayout' to be considered
if
tp
in
self
.
_struct_pending_verification
:
# check that the layout sizes and offsets match the real ones
def
check
(
realvalue
,
expectedvalue
,
msg
):
if
realvalue
!=
expectedvalue
:
raise
VerificationError
(
"%s (we have %d, but C compiler says %d)"
%
(
msg
,
expectedvalue
,
realvalue
))
ffi
=
self
.
ffi
BStruct
=
ffi
.
_get_cached_btype
(
tp
)
layout
,
cname
=
self
.
_struct_pending_verification
.
pop
(
tp
)
check
(
layout
[
0
],
ffi
.
sizeof
(
BStruct
),
"wrong total size"
)
check
(
layout
[
1
],
ffi
.
alignof
(
BStruct
),
"wrong total alignment"
)
i
=
2
for
fname
,
ftype
,
fbitsize
,
fqual
in
tp
.
enumfields
():
if
fbitsize
>=
0
:
continue
# xxx ignore fbitsize for now
check
(
layout
[
i
],
ffi
.
offsetof
(
BStruct
,
fname
),
"wrong offset for field %r"
%
(
fname
,))
if
layout
[
i
+
1
]
!=
0
:
BField
=
ffi
.
_get_cached_btype
(
ftype
)
check
(
layout
[
i
+
1
],
ffi
.
sizeof
(
BField
),
"wrong size for field %r"
%
(
fname
,))
i
+=
2
assert
i
==
len
(
layout
)
# ----------
# 'anonymous' declarations. These are produced for anonymous structs
# or unions; the 'name' is obtained by a typedef.
def
_generate_gen_anonymous_decl
(
self
,
tp
,
name
):
if
isinstance
(
tp
,
model
.
EnumType
):
self
.
_generate_gen_enum_decl
(
tp
,
name
,
''
)
else
:
self
.
_generate_struct_or_union_decl
(
tp
,
''
,
name
)
def
_loading_gen_anonymous
(
self
,
tp
,
name
,
module
):
if
isinstance
(
tp
,
model
.
EnumType
):
self
.
_loading_gen_enum
(
tp
,
name
,
module
,
''
)
else
:
self
.
_loading_struct_or_union
(
tp
,
''
,
name
,
module
)
def
_loaded_gen_anonymous
(
self
,
tp
,
name
,
module
,
**
kwds
):
if
isinstance
(
tp
,
model
.
EnumType
):
self
.
_loaded_gen_enum
(
tp
,
name
,
module
,
**
kwds
)
else
:
self
.
_loaded_struct_or_union
(
tp
)
# ----------
# constants, likely declared with '#define'
def
_generate_gen_const
(
self
,
is_int
,
name
,
tp
=
None
,
category
=
'const'
,
check_value
=
None
):
prnt
=
self
.
_prnt
funcname
=
'_cffi_%s_%s'
%
(
category
,
name
)
self
.
export_symbols
.
append
(
funcname
)
if
check_value
is
not
None
:
assert
is_int
assert
category
==
'const'
prnt
(
'int %s(char *out_error)'
%
funcname
)
prnt
(
'{'
)
self
.
_check_int_constant_value
(
name
,
check_value
)
prnt
(
' return 0;'
)
prnt
(
'}'
)
elif
is_int
:
assert
category
==
'const'
prnt
(
'int %s(long long *out_value)'
%
funcname
)
prnt
(
'{'
)
prnt
(
' *out_value = (long long)(%s);'
%
(
name
,))
prnt
(
' return (%s) <= 0;'
%
(
name
,))
prnt
(
'}'
)
else
:
assert
tp
is
not
None
assert
check_value
is
None
if
category
==
'var'
:
ampersand
=
'&'
else
:
ampersand
=
''
extra
=
''
if
category
==
'const'
and
isinstance
(
tp
,
model
.
StructOrUnion
):
extra
=
'const *'
ampersand
=
'&'
prnt
(
tp
.
get_c_name
(
' %s%s(void)'
%
(
extra
,
funcname
),
name
))
prnt
(
'{'
)
prnt
(
' return (%s%s);'
%
(
ampersand
,
name
))
prnt
(
'}'
)
prnt
()
def
_generate_gen_constant_decl
(
self
,
tp
,
name
):
is_int
=
isinstance
(
tp
,
model
.
PrimitiveType
)
and
tp
.
is_integer_type
()
self
.
_generate_gen_const
(
is_int
,
name
,
tp
)
_loading_gen_constant
=
_loaded_noop
def
_load_constant
(
self
,
is_int
,
tp
,
name
,
module
,
check_value
=
None
):
funcname
=
'_cffi_const_%s'
%
name
if
check_value
is
not
None
:
assert
is_int
self
.
_load_known_int_constant
(
module
,
funcname
)
value
=
check_value
elif
is_int
:
BType
=
self
.
ffi
.
_typeof_locked
(
"long long*"
)[
0
]
BFunc
=
self
.
ffi
.
_typeof_locked
(
"int(*)(long long*)"
)[
0
]
function
=
module
.
load_function
(
BFunc
,
funcname
)
p
=
self
.
ffi
.
new
(
BType
)
negative
=
function
(
p
)
value
=
int
(
p
[
0
])
if
value
<
0
and
not
negative
:
BLongLong
=
self
.
ffi
.
_typeof_locked
(
"long long"
)[
0
]
value
+=
(
1
<<
(
8
*
self
.
ffi
.
sizeof
(
BLongLong
)))
else
:
assert
check_value
is
None
fntypeextra
=
'(*)(void)'
if
isinstance
(
tp
,
model
.
StructOrUnion
):
fntypeextra
=
'*'
+
fntypeextra
BFunc
=
self
.
ffi
.
_typeof_locked
(
tp
.
get_c_name
(
fntypeextra
,
name
))[
0
]
function
=
module
.
load_function
(
BFunc
,
funcname
)
value
=
function
()
if
isinstance
(
tp
,
model
.
StructOrUnion
):
value
=
value
[
0
]
return
value
def
_loaded_gen_constant
(
self
,
tp
,
name
,
module
,
library
):
is_int
=
isinstance
(
tp
,
model
.
PrimitiveType
)
and
tp
.
is_integer_type
()
value
=
self
.
_load_constant
(
is_int
,
tp
,
name
,
module
)
setattr
(
library
,
name
,
value
)
type
(
library
).
_cffi_dir
.
append
(
name
)
# ----------
# enums
def
_check_int_constant_value
(
self
,
name
,
value
):
prnt
=
self
.
_prnt
if
value
<=
0
:
prnt
(
' if ((%s) > 0 || (long)(%s) != %dL) {'
%
(
name
,
name
,
value
))
else
:
prnt
(
' if ((%s) <= 0 || (unsigned long)(%s) != %dUL) {'
%
(
name
,
name
,
value
))
prnt
(
' char buf[64];'
)
prnt
(
' if ((%s) <= 0)'
%
name
)
prnt
(
' sprintf(buf, "%%ld", (long)(%s));'
%
name
)
prnt
(
' else'
)
prnt
(
' sprintf(buf, "%%lu", (unsigned long)(%s));'
%
name
)
prnt
(
' sprintf(out_error, "%s has the real value %s, not %s",'
)
prnt
(
' "%s", buf, "%d");'
%
(
name
[:
100
],
value
))
prnt
(
' return -1;'
)
prnt
(
' }'
)
def
_load_known_int_constant
(
self
,
module
,
funcname
):
BType
=
self
.
ffi
.
_typeof_locked
(
"char[]"
)[
0
]
BFunc
=
self
.
ffi
.
_typeof_locked
(
"int(*)(char*)"
)[
0
]
function
=
module
.
load_function
(
BFunc
,
funcname
)
p
=
self
.
ffi
.
new
(
BType
,
256
)
if
function
(
p
)
<
0
:
error
=
self
.
ffi
.
string
(
p
)
if
sys
.
version_info
>=
(
3
,):
error
=
str
(
error
,
'utf-8'
)
raise
VerificationError
(
error
)
def
_enum_funcname
(
self
,
prefix
,
name
):
# "$enum_$1" => "___D_enum____D_1"
name
=
name
.
replace
(
'$'
,
'___D_'
)
return
'_cffi_e_%s_%s'
%
(
prefix
,
name
)
def
_generate_gen_enum_decl
(
self
,
tp
,
name
,
prefix
=
'enum'
):
if
tp
.
partial
:
for
enumerator
in
tp
.
enumerators
:
self
.
_generate_gen_const
(
True
,
enumerator
)
return
#
funcname
=
self
.
_enum_funcname
(
prefix
,
name
)
self
.
export_symbols
.
append
(
funcname
)
prnt
=
self
.
_prnt
prnt
(
'int %s(char *out_error)'
%
funcname
)
prnt
(
'{'
)
for
enumerator
,
enumvalue
in
zip
(
tp
.
enumerators
,
tp
.
enumvalues
):
self
.
_check_int_constant_value
(
enumerator
,
enumvalue
)
prnt
(
' return 0;'
)
prnt
(
'}'
)
prnt
()
def
_loading_gen_enum
(
self
,
tp
,
name
,
module
,
prefix
=
'enum'
):
if
tp
.
partial
:
enumvalues
=
[
self
.
_load_constant
(
True
,
tp
,
enumerator
,
module
)
for
enumerator
in
tp
.
enumerators
]
tp
.
enumvalues
=
tuple
(
enumvalues
)
tp
.
partial_resolved
=
True
else
:
funcname
=
self
.
_enum_funcname
(
prefix
,
name
)
self
.
_load_known_int_constant
(
module
,
funcname
)
def
_loaded_gen_enum
(
self
,
tp
,
name
,
module
,
library
):
for
enumerator
,
enumvalue
in
zip
(
tp
.
enumerators
,
tp
.
enumvalues
):
setattr
(
library
,
enumerator
,
enumvalue
)
type
(
library
).
_cffi_dir
.
append
(
enumerator
)
# ----------
# macros: for now only for integers
def
_generate_gen_macro_decl
(
self
,
tp
,
name
):
if
tp
==
'...'
:
check_value
=
None
else
:
check_value
=
tp
# an integer
self
.
_generate_gen_const
(
True
,
name
,
check_value
=
check_value
)
_loading_gen_macro
=
_loaded_noop
def
_loaded_gen_macro
(
self
,
tp
,
name
,
module
,
library
):
if
tp
==
'...'
:
check_value
=
None
else
:
check_value
=
tp
# an integer
value
=
self
.
_load_constant
(
True
,
tp
,
name
,
module
,
check_value
=
check_value
)
setattr
(
library
,
name
,
value
)
type
(
library
).
_cffi_dir
.
append
(
name
)
# ----------
# global variables
def
_generate_gen_variable_decl
(
self
,
tp
,
name
):
if
isinstance
(
tp
,
model
.
ArrayType
):
if
tp
.
length
==
'...'
:
prnt
=
self
.
_prnt
funcname
=
'_cffi_sizeof_%s'
%
(
name
,)
self
.
export_symbols
.
append
(
funcname
)
prnt
(
"size_t %s(void)"
%
funcname
)
prnt
(
"{"
)
prnt
(
" return sizeof(%s);"
%
(
name
,))
prnt
(
"}"
)
tp_ptr
=
model
.
PointerType
(
tp
.
item
)
self
.
_generate_gen_const
(
False
,
name
,
tp_ptr
)
else
:
tp_ptr
=
model
.
PointerType
(
tp
)
self
.
_generate_gen_const
(
False
,
name
,
tp_ptr
,
category
=
'var'
)
_loading_gen_variable
=
_loaded_noop
def
_loaded_gen_variable
(
self
,
tp
,
name
,
module
,
library
):
if
isinstance
(
tp
,
model
.
ArrayType
):
# int a[5] is "constant" in the
# sense that "a=..." is forbidden
if
tp
.
length
==
'...'
:
funcname
=
'_cffi_sizeof_%s'
%
(
name
,)
BFunc
=
self
.
ffi
.
_typeof_locked
(
'size_t(*)(void)'
)[
0
]
function
=
module
.
load_function
(
BFunc
,
funcname
)
size
=
function
()
BItemType
=
self
.
ffi
.
_get_cached_btype
(
tp
.
item
)
length
,
rest
=
divmod
(
size
,
self
.
ffi
.
sizeof
(
BItemType
))
if
rest
!=
0
:
raise
VerificationError
(
"bad size: %r does not seem to be an array of %s"
%
(
name
,
tp
.
item
))
tp
=
tp
.
resolve_length
(
length
)
tp_ptr
=
model
.
PointerType
(
tp
.
item
)
value
=
self
.
_load_constant
(
False
,
tp_ptr
,
name
,
module
)
# 'value' is a <cdata 'type *'> which we have to replace with
# a <cdata 'type[N]'> if the N is actually known
if
tp
.
length
is
not
None
:
BArray
=
self
.
ffi
.
_get_cached_btype
(
tp
)
value
=
self
.
ffi
.
cast
(
BArray
,
value
)
setattr
(
library
,
name
,
value
)
type
(
library
).
_cffi_dir
.
append
(
name
)
return
# remove ptr=<cdata 'int *'> from the library instance, and replace
# it by a property on the class, which reads/writes into ptr[0].
funcname
=
'_cffi_var_%s'
%
name
BFunc
=
self
.
ffi
.
_typeof_locked
(
tp
.
get_c_name
(
'*(*)(void)'
,
name
))[
0
]
function
=
module
.
load_function
(
BFunc
,
funcname
)
ptr
=
function
()
def
getter
(
library
):
return
ptr
[
0
]
def
setter
(
library
,
value
):
ptr
[
0
]
=
value
setattr
(
type
(
library
),
name
,
property
(
getter
,
setter
))
type
(
library
).
_cffi_dir
.
append
(
name
)
cffimod_header
=
r
'''
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
#include <errno.h>
#include <sys/types.h> /* XXX for ssize_t on some platforms */
/* this block of #ifs should be kept exactly identical between
c/_cffi_backend.c, cffi/vengine_cpy.py, cffi/vengine_gen.py
and cffi/_cffi_include.h */
#if defined(_MSC_VER)
# include <malloc.h> /* for alloca() */
# if _MSC_VER < 1600 /* MSVC < 2010 */
typedef __int8 int8_t;
typedef __int16 int16_t;
typedef __int32 int32_t;
typedef __int64 int64_t;
typedef unsigned __int8 uint8_t;
typedef unsigned __int16 uint16_t;
typedef unsigned __int32 uint32_t;
typedef unsigned __int64 uint64_t;
typedef __int8 int_least8_t;
typedef __int16 int_least16_t;
typedef __int32 int_least32_t;
typedef __int64 int_least64_t;
typedef unsigned __int8 uint_least8_t;
typedef unsigned __int16 uint_least16_t;
typedef unsigned __int32 uint_least32_t;
typedef unsigned __int64 uint_least64_t;
typedef __int8 int_fast8_t;
typedef __int16 int_fast16_t;
typedef __int32 int_fast32_t;
typedef __int64 int_fast64_t;
typedef unsigned __int8 uint_fast8_t;
typedef unsigned __int16 uint_fast16_t;
typedef unsigned __int32 uint_fast32_t;
typedef unsigned __int64 uint_fast64_t;
typedef __int64 intmax_t;
typedef unsigned __int64 uintmax_t;
# else
# include <stdint.h>
# endif
# if _MSC_VER < 1800 /* MSVC < 2013 */
# ifndef __cplusplus
typedef unsigned char _Bool;
# endif
# endif
#else
# include <stdint.h>
# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
# include <alloca.h>
# endif
#endif
'''
env/lib/python3.5/site-packages/cffi/verifier.py
0 → 100644
View file @
ff4a13ed
#
# DEPRECATED: implementation for ffi.verify()
#
import
sys
,
os
,
binascii
,
shutil
,
io
from
.
import
__version_verifier_modules__
from
.
import
ffiplatform
from
.error
import
VerificationError
if
sys
.
version_info
>=
(
3
,
3
):
import
importlib.machinery
def
_extension_suffixes
():
return
importlib
.
machinery
.
EXTENSION_SUFFIXES
[:]
else
:
import
imp
def
_extension_suffixes
():
return
[
suffix
for
suffix
,
_
,
type
in
imp
.
get_suffixes
()
if
type
==
imp
.
C_EXTENSION
]
if
sys
.
version_info
>=
(
3
,):
NativeIO
=
io
.
StringIO
else
:
class
NativeIO
(
io
.
BytesIO
):
def
write
(
self
,
s
):
if
isinstance
(
s
,
unicode
):
s
=
s
.
encode
(
'ascii'
)
super
(
NativeIO
,
self
).
write
(
s
)
class
Verifier
(
object
):
def
__init__
(
self
,
ffi
,
preamble
,
tmpdir
=
None
,
modulename
=
None
,
ext_package
=
None
,
tag
=
''
,
force_generic_engine
=
False
,
source_extension
=
'.c'
,
flags
=
None
,
relative_to
=
None
,
**
kwds
):
if
ffi
.
_parser
.
_uses_new_feature
:
raise
VerificationError
(
"feature not supported with ffi.verify(), but only "
"with ffi.set_source(): %s"
%
(
ffi
.
_parser
.
_uses_new_feature
,))
self
.
ffi
=
ffi
self
.
preamble
=
preamble
if
not
modulename
:
flattened_kwds
=
ffiplatform
.
flatten
(
kwds
)
vengine_class
=
_locate_engine_class
(
ffi
,
force_generic_engine
)
self
.
_vengine
=
vengine_class
(
self
)
self
.
_vengine
.
patch_extension_kwds
(
kwds
)
self
.
flags
=
flags
self
.
kwds
=
self
.
make_relative_to
(
kwds
,
relative_to
)
#
if
modulename
:
if
tag
:
raise
TypeError
(
"can't specify both 'modulename' and 'tag'"
)
else
:
key
=
'
\x00
'
.
join
([
sys
.
version
[:
3
],
__version_verifier_modules__
,
preamble
,
flattened_kwds
]
+
ffi
.
_cdefsources
)
if
sys
.
version_info
>=
(
3
,):
key
=
key
.
encode
(
'utf-8'
)
k1
=
hex
(
binascii
.
crc32
(
key
[
0
::
2
])
&
0xffffffff
)
k1
=
k1
.
lstrip
(
'0x'
).
rstrip
(
'L'
)
k2
=
hex
(
binascii
.
crc32
(
key
[
1
::
2
])
&
0xffffffff
)
k2
=
k2
.
lstrip
(
'0'
).
rstrip
(
'L'
)
modulename
=
'_cffi_%s_%s%s%s'
%
(
tag
,
self
.
_vengine
.
_class_key
,
k1
,
k2
)
suffix
=
_get_so_suffixes
()[
0
]
self
.
tmpdir
=
tmpdir
or
_caller_dir_pycache
()
self
.
sourcefilename
=
os
.
path
.
join
(
self
.
tmpdir
,
modulename
+
source_extension
)
self
.
modulefilename
=
os
.
path
.
join
(
self
.
tmpdir
,
modulename
+
suffix
)
self
.
ext_package
=
ext_package
self
.
_has_source
=
False
self
.
_has_module
=
False
def
write_source
(
self
,
file
=
None
):
"""Write the C source code. It is produced in 'self.sourcefilename',
which can be tweaked beforehand."""
with
self
.
ffi
.
_lock
:
if
self
.
_has_source
and
file
is
None
:
raise
VerificationError
(
"source code already written"
)
self
.
_write_source
(
file
)
def
compile_module
(
self
):
"""Write the C source code (if not done already) and compile it.
This produces a dynamic link library in 'self.modulefilename'."""
with
self
.
ffi
.
_lock
:
if
self
.
_has_module
:
raise
VerificationError
(
"module already compiled"
)
if
not
self
.
_has_source
:
self
.
_write_source
()
self
.
_compile_module
()
def
load_library
(
self
):
"""Get a C module from this Verifier instance.
Returns an instance of a FFILibrary class that behaves like the
objects returned by ffi.dlopen(), but that delegates all
operations to the C module. If necessary, the C code is written
and compiled first.
"""
with
self
.
ffi
.
_lock
:
if
not
self
.
_has_module
:
self
.
_locate_module
()
if
not
self
.
_has_module
:
if
not
self
.
_has_source
:
self
.
_write_source
()
self
.
_compile_module
()
return
self
.
_load_library
()
def
get_module_name
(
self
):
basename
=
os
.
path
.
basename
(
self
.
modulefilename
)
# kill both the .so extension and the other .'s, as introduced
# by Python 3: 'basename.cpython-33m.so'
basename
=
basename
.
split
(
'.'
,
1
)[
0
]
# and the _d added in Python 2 debug builds --- but try to be
# conservative and not kill a legitimate _d
if
basename
.
endswith
(
'_d'
)
and
hasattr
(
sys
,
'gettotalrefcount'
):
basename
=
basename
[:
-
2
]
return
basename
def
get_extension
(
self
):
ffiplatform
.
_hack_at_distutils
()
# backward compatibility hack
if
not
self
.
_has_source
:
with
self
.
ffi
.
_lock
:
if
not
self
.
_has_source
:
self
.
_write_source
()
sourcename
=
ffiplatform
.
maybe_relative_path
(
self
.
sourcefilename
)
modname
=
self
.
get_module_name
()
return
ffiplatform
.
get_extension
(
sourcename
,
modname
,
**
self
.
kwds
)
def
generates_python_module
(
self
):
return
self
.
_vengine
.
_gen_python_module
def
make_relative_to
(
self
,
kwds
,
relative_to
):
if
relative_to
and
os
.
path
.
dirname
(
relative_to
):
dirname
=
os
.
path
.
dirname
(
relative_to
)
kwds
=
kwds
.
copy
()
for
key
in
ffiplatform
.
LIST_OF_FILE_NAMES
:
if
key
in
kwds
:
lst
=
kwds
[
key
]
if
not
isinstance
(
lst
,
(
list
,
tuple
)):
raise
TypeError
(
"keyword '%s' should be a list or tuple"
%
(
key
,))
lst
=
[
os
.
path
.
join
(
dirname
,
fn
)
for
fn
in
lst
]
kwds
[
key
]
=
lst
return
kwds
# ----------
def
_locate_module
(
self
):
if
not
os
.
path
.
isfile
(
self
.
modulefilename
):
if
self
.
ext_package
:
try
:
pkg
=
__import__
(
self
.
ext_package
,
None
,
None
,
[
'__doc__'
])
except
ImportError
:
return
# cannot import the package itself, give up
# (e.g. it might be called differently before installation)
path
=
pkg
.
__path__
else
:
path
=
None
filename
=
self
.
_vengine
.
find_module
(
self
.
get_module_name
(),
path
,
_get_so_suffixes
())
if
filename
is
None
:
return
self
.
modulefilename
=
filename
self
.
_vengine
.
collect_types
()
self
.
_has_module
=
True
def
_write_source_to
(
self
,
file
):
self
.
_vengine
.
_f
=
file
try
:
self
.
_vengine
.
write_source_to_f
()
finally
:
del
self
.
_vengine
.
_f
def
_write_source
(
self
,
file
=
None
):
if
file
is
not
None
:
self
.
_write_source_to
(
file
)
else
:
# Write our source file to an in memory file.
f
=
NativeIO
()
self
.
_write_source_to
(
f
)
source_data
=
f
.
getvalue
()
# Determine if this matches the current file
if
os
.
path
.
exists
(
self
.
sourcefilename
):
with
open
(
self
.
sourcefilename
,
"r"
)
as
fp
:
needs_written
=
not
(
fp
.
read
()
==
source_data
)
else
:
needs_written
=
True
# Actually write the file out if it doesn't match
if
needs_written
:
_ensure_dir
(
self
.
sourcefilename
)
with
open
(
self
.
sourcefilename
,
"w"
)
as
fp
:
fp
.
write
(
source_data
)
# Set this flag
self
.
_has_source
=
True
def
_compile_module
(
self
):
# compile this C source
tmpdir
=
os
.
path
.
dirname
(
self
.
sourcefilename
)
outputfilename
=
ffiplatform
.
compile
(
tmpdir
,
self
.
get_extension
())
try
:
same
=
ffiplatform
.
samefile
(
outputfilename
,
self
.
modulefilename
)
except
OSError
:
same
=
False
if
not
same
:
_ensure_dir
(
self
.
modulefilename
)
shutil
.
move
(
outputfilename
,
self
.
modulefilename
)
self
.
_has_module
=
True
def
_load_library
(
self
):
assert
self
.
_has_module
if
self
.
flags
is
not
None
:
return
self
.
_vengine
.
load_library
(
self
.
flags
)
else
:
return
self
.
_vengine
.
load_library
()
# ____________________________________________________________
_FORCE_GENERIC_ENGINE
=
False
# for tests
def
_locate_engine_class
(
ffi
,
force_generic_engine
):
if
_FORCE_GENERIC_ENGINE
:
force_generic_engine
=
True
if
not
force_generic_engine
:
if
'__pypy__'
in
sys
.
builtin_module_names
:
force_generic_engine
=
True
else
:
try
:
import
_cffi_backend
except
ImportError
:
_cffi_backend
=
'?'
if
ffi
.
_backend
is
not
_cffi_backend
:
force_generic_engine
=
True
if
force_generic_engine
:
from
.
import
vengine_gen
return
vengine_gen
.
VGenericEngine
else
:
from
.
import
vengine_cpy
return
vengine_cpy
.
VCPythonEngine
# ____________________________________________________________
_TMPDIR
=
None
def
_caller_dir_pycache
():
if
_TMPDIR
:
return
_TMPDIR
result
=
os
.
environ
.
get
(
'CFFI_TMPDIR'
)
if
result
:
return
result
filename
=
sys
.
_getframe
(
2
).
f_code
.
co_filename
return
os
.
path
.
abspath
(
os
.
path
.
join
(
os
.
path
.
dirname
(
filename
),
'__pycache__'
))
def
set_tmpdir
(
dirname
):
"""Set the temporary directory to use instead of __pycache__."""
global
_TMPDIR
_TMPDIR
=
dirname
def
cleanup_tmpdir
(
tmpdir
=
None
,
keep_so
=
False
):
"""Clean up the temporary directory by removing all files in it
called `_cffi_*.{c,so}` as well as the `build` subdirectory."""
tmpdir
=
tmpdir
or
_caller_dir_pycache
()
try
:
filelist
=
os
.
listdir
(
tmpdir
)
except
OSError
:
return
if
keep_so
:
suffix
=
'.c'
# only remove .c files
else
:
suffix
=
_get_so_suffixes
()[
0
].
lower
()
for
fn
in
filelist
:
if
fn
.
lower
().
startswith
(
'_cffi_'
)
and
(
fn
.
lower
().
endswith
(
suffix
)
or
fn
.
lower
().
endswith
(
'.c'
)):
try
:
os
.
unlink
(
os
.
path
.
join
(
tmpdir
,
fn
))
except
OSError
:
pass
clean_dir
=
[
os
.
path
.
join
(
tmpdir
,
'build'
)]
for
dir
in
clean_dir
:
try
:
for
fn
in
os
.
listdir
(
dir
):
fn
=
os
.
path
.
join
(
dir
,
fn
)
if
os
.
path
.
isdir
(
fn
):
clean_dir
.
append
(
fn
)
else
:
os
.
unlink
(
fn
)
except
OSError
:
pass
def
_get_so_suffixes
():
suffixes
=
_extension_suffixes
()
if
not
suffixes
:
# bah, no C_EXTENSION available. Occurs on pypy without cpyext
if
sys
.
platform
==
'win32'
:
suffixes
=
[
".pyd"
]
else
:
suffixes
=
[
".so"
]
return
suffixes
def
_ensure_dir
(
filename
):
dirname
=
os
.
path
.
dirname
(
filename
)
if
dirname
and
not
os
.
path
.
isdir
(
dirname
):
os
.
makedirs
(
dirname
)
env/lib/python3.5/site-packages/click-7.1.1.dist-info/INSTALLER
0 → 100644
View file @
ff4a13ed
pip
env/lib/python3.5/site-packages/click-7.1.1.dist-info/LICENSE.rst
0 → 100644
View file @
ff4a13ed
Copyright 2014 Pallets
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
env/lib/python3.5/site-packages/click-7.1.1.dist-info/METADATA
0 → 100644
View file @
ff4a13ed
Metadata-Version: 2.1
Name: click
Version: 7.1.1
Summary: Composable command line interface toolkit
Home-page: https://palletsprojects.com/p/click/
Maintainer: Pallets
Maintainer-email: contact@palletsprojects.com
License: BSD-3-Clause
Project-URL: Documentation, https://click.palletsprojects.com/
Project-URL: Code, https://github.com/pallets/click
Project-URL: Issue tracker, https://github.com/pallets/click/issues
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 3
Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*
\$ click\_
==========
Click is a Python package for creating beautiful command line interfaces
in a composable way with as little code as necessary. It's the "Command
Line Interface Creation Kit". It's highly configurable but comes with
sensible defaults out of the box.
It aims to make the process of writing command line tools quick and fun
while also preventing any frustration caused by the inability to
implement an intended CLI API.
Click in three points:
- Arbitrary nesting of commands
- Automatic help page generation
- Supports lazy loading of subcommands at runtime
Installing
----------
Install and update using `pip`_:
.. code-block:: text
$ pip install -U click
.. _pip: https://pip.pypa.io/en/stable/quickstart/
A Simple Example
----------------
.. code-block:: python
import click
@click.command()
@click.option("--count", default=1, help="Number of greetings.")
@click.option("--name", prompt="Your name", help="The person to greet.")
def hello(count, name):
"""Simple program that greets NAME for a total of COUNT times."""
for _ in range(count):
click.echo(f"Hello, {name}!")
if __name__ == '__main__':
hello()
.. code-block:: text
$ python hello.py --count=3
Your name: Click
Hello, Click!
Hello, Click!
Hello, Click!
Donate
------
The Pallets organization develops and supports Click and other popular
packages. In order to grow the community of contributors and users, and
allow the maintainers to devote more time to the projects, `please
donate today`_.
.. _please donate today: https://palletsprojects.com/donate
Links
-----
- Website: https://palletsprojects.com/p/click/
- Documentation: https://click.palletsprojects.com/
- Releases: https://pypi.org/project/click/
- Code: https://github.com/pallets/click
- Issue tracker: https://github.com/pallets/click/issues
- Test status: https://dev.azure.com/pallets/click/_build
- Official chat: https://discord.gg/t6rrQZH
env/lib/python3.5/site-packages/click-7.1.1.dist-info/RECORD
0 → 100644
View file @
ff4a13ed
click-7.1.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
click-7.1.1.dist-info/LICENSE.rst,sha256=morRBqOU6FO_4h9C9OctWSgZoigF2ZG18ydQKSkrZY0,1475
click-7.1.1.dist-info/METADATA,sha256=qGBq4nyx59fI9CN-NY-C_ye4USndxpKszWFLe5KMhQM,2868
click-7.1.1.dist-info/RECORD,,
click-7.1.1.dist-info/WHEEL,sha256=kGT74LWyRUZrL4VgLh6_g12IeVl_9u9ZVhadrgXZUEY,110
click-7.1.1.dist-info/top_level.txt,sha256=J1ZQogalYS4pphY_lPECoNMfw0HzTSrZglC4Yfwo4xA,6
click/__init__.py,sha256=_Mora-ZWjo_kRK3mg_vX3ZmQV3pop8vrCLj-C209TvQ,2463
click/__pycache__/__init__.cpython-35.pyc,,
click/__pycache__/_bashcomplete.cpython-35.pyc,,
click/__pycache__/_compat.cpython-35.pyc,,
click/__pycache__/_termui_impl.cpython-35.pyc,,
click/__pycache__/_textwrap.cpython-35.pyc,,
click/__pycache__/_unicodefun.cpython-35.pyc,,
click/__pycache__/_winconsole.cpython-35.pyc,,
click/__pycache__/core.cpython-35.pyc,,
click/__pycache__/decorators.cpython-35.pyc,,
click/__pycache__/exceptions.cpython-35.pyc,,
click/__pycache__/formatting.cpython-35.pyc,,
click/__pycache__/globals.cpython-35.pyc,,
click/__pycache__/parser.cpython-35.pyc,,
click/__pycache__/termui.cpython-35.pyc,,
click/__pycache__/testing.cpython-35.pyc,,
click/__pycache__/types.cpython-35.pyc,,
click/__pycache__/utils.cpython-35.pyc,,
click/_bashcomplete.py,sha256=9J98IHQYmCAr2Jup6TDshUr5FJEen-AoQCZR0K5nKxQ,12309
click/_compat.py,sha256=CCA3QaccPgx3TL3biRljHNnqELqCSMr3wPIe1kXaOcQ,24257
click/_termui_impl.py,sha256=w2Fgse5XiOSjV72IZLBKG0loK_Q1oogvh9e0spJpRAY,20793
click/_textwrap.py,sha256=ajCzkzFly5tjm9foQ5N9_MOeaYJMBjAltuFa69n4iXY,1197
click/_unicodefun.py,sha256=apLSNEBZgUsQNPMUv072zJ1swqnm0dYVT5TqcIWTt6w,4201
click/_winconsole.py,sha256=6YDu6Rq1Wxx4w9uinBMK2LHvP83aerZM9GQurlk3QDo,10010
click/core.py,sha256=V6DJzastGhrC6WTDwV9MSLwcJUdX2Uf1ypmgkjBdn_Y,77650
click/decorators.py,sha256=3TvEO_BkaHl7k6Eh1G5eC7JK4LKPdpFqH9JP0QDyTlM,11215
click/exceptions.py,sha256=3pQAyyMFzx5A3eV0Y27WtDTyGogZRbrC6_o5DjjKBbw,8118
click/formatting.py,sha256=Wb4gqFEpWaKPgAbOvnkCl8p-bEZx5KpM5ZSByhlnJNk,9281
click/globals.py,sha256=ht7u2kUGI08pAarB4e4yC8Lkkxy6gJfRZyzxEj8EbWQ,1501
click/parser.py,sha256=mFK-k58JtPpqO0AC36WAr0t5UfzEw1mvgVSyn7WCe9M,15691
click/termui.py,sha256=G7QBEKIepRIGLvNdGwBTYiEtSImRxvTO_AglVpyHH2s,23998
click/testing.py,sha256=EUEsDUqNXFgCLhZ0ZFOROpaVDA5I_rijwnNPE6qICgA,12854
click/types.py,sha256=wuubik4VqgqAw5dvbYFkDt-zSAx97y9TQXuXcVaRyQA,25045
click/utils.py,sha256=4VEcJ7iEHwjnFuzEuRtkT99o5VG3zqSD7Q2CVzv13WU,15940
env/lib/python3.5/site-packages/click-7.1.1.dist-info/WHEEL
0 → 100644
View file @
ff4a13ed
Wheel-Version: 1.0
Generator: bdist_wheel (0.34.2)
Root-Is-Purelib: true
Tag: py2-none-any
Tag: py3-none-any
env/lib/python3.5/site-packages/click-7.1.1.dist-info/top_level.txt
0 → 100644
View file @
ff4a13ed
click
env/lib/python3.5/site-packages/click/__init__.py
0 → 100644
View file @
ff4a13ed
"""
Click is a simple Python module inspired by the stdlib optparse to make
writing command line scripts fun. Unlike other modules, it's based
around a simple API that does not come with too much magic and is
composable.
"""
from
.core
import
Argument
from
.core
import
BaseCommand
from
.core
import
Command
from
.core
import
CommandCollection
from
.core
import
Context
from
.core
import
Group
from
.core
import
MultiCommand
from
.core
import
Option
from
.core
import
Parameter
from
.decorators
import
argument
from
.decorators
import
command
from
.decorators
import
confirmation_option
from
.decorators
import
group
from
.decorators
import
help_option
from
.decorators
import
make_pass_decorator
from
.decorators
import
option
from
.decorators
import
pass_context
from
.decorators
import
pass_obj
from
.decorators
import
password_option
from
.decorators
import
version_option
from
.exceptions
import
Abort
from
.exceptions
import
BadArgumentUsage
from
.exceptions
import
BadOptionUsage
from
.exceptions
import
BadParameter
from
.exceptions
import
ClickException
from
.exceptions
import
FileError
from
.exceptions
import
MissingParameter
from
.exceptions
import
NoSuchOption
from
.exceptions
import
UsageError
from
.formatting
import
HelpFormatter
from
.formatting
import
wrap_text
from
.globals
import
get_current_context
from
.parser
import
OptionParser
from
.termui
import
clear
from
.termui
import
confirm
from
.termui
import
echo_via_pager
from
.termui
import
edit
from
.termui
import
get_terminal_size
from
.termui
import
getchar
from
.termui
import
launch
from
.termui
import
pause
from
.termui
import
progressbar
from
.termui
import
prompt
from
.termui
import
secho
from
.termui
import
style
from
.termui
import
unstyle
from
.types
import
BOOL
from
.types
import
Choice
from
.types
import
DateTime
from
.types
import
File
from
.types
import
FLOAT
from
.types
import
FloatRange
from
.types
import
INT
from
.types
import
IntRange
from
.types
import
ParamType
from
.types
import
Path
from
.types
import
STRING
from
.types
import
Tuple
from
.types
import
UNPROCESSED
from
.types
import
UUID
from
.utils
import
echo
from
.utils
import
format_filename
from
.utils
import
get_app_dir
from
.utils
import
get_binary_stream
from
.utils
import
get_os_args
from
.utils
import
get_text_stream
from
.utils
import
open_file
# Controls if click should emit the warning about the use of unicode
# literals.
disable_unicode_literals_warning
=
False
__version__
=
"7.1.1"
env/lib/python3.5/site-packages/click/__pycache__/__init__.cpython-35.pyc
0 → 100644
View file @
ff4a13ed
File added
env/lib/python3.5/site-packages/click/__pycache__/_bashcomplete.cpython-35.pyc
0 → 100644
View file @
ff4a13ed
File added
env/lib/python3.5/site-packages/click/__pycache__/_compat.cpython-35.pyc
0 → 100644
View file @
ff4a13ed
File added
env/lib/python3.5/site-packages/click/__pycache__/_termui_impl.cpython-35.pyc
0 → 100644
View file @
ff4a13ed
File added
env/lib/python3.5/site-packages/click/__pycache__/_textwrap.cpython-35.pyc
0 → 100644
View file @
ff4a13ed
File added
env/lib/python3.5/site-packages/click/__pycache__/_unicodefun.cpython-35.pyc
0 → 100644
View file @
ff4a13ed
File added
Prev
1
…
5
6
7
8
9
10
11
12
13
…
20
Next
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment