Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740

741

""" 

A selection of cross-compatible functions for Python 2 and 3. 

 

This module exports useful functions for 2/3 compatible code: 

 

* bind_method: binds functions to classes 

* ``native_str_to_bytes`` and ``bytes_to_native_str`` 

* ``native_str``: always equal to the native platform string object (because 

this may be shadowed by imports from future.builtins) 

* lists: lrange(), lmap(), lzip(), lfilter() 

* iterable method compatibility: 

- iteritems, iterkeys, itervalues 

- viewitems, viewkeys, viewvalues 

 

These use the original method if available, otherwise they use items, 

keys, values. 

 

* types: 

 

* text_type: unicode in Python 2, str in Python 3 

* binary_type: str in Python 2, bytes in Python 3 

* string_types: basestring in Python 2, str in Python 3 

 

* bchr(c): 

Take an integer and make a 1-character byte string 

* bord(c) 

Take the result of indexing on a byte string and make an integer 

* tobytes(s) 

Take a text string, a byte string, or a sequence of characters taken 

from a byte string, and make a byte string. 

 

* raise_from() 

* raise_with_traceback() 

 

This module also defines these decorators: 

 

* ``python_2_unicode_compatible`` 

* ``with_metaclass`` 

* ``implements_iterator`` 

 

Some of the functions in this module come from the following sources: 

 

* Jinja2 (BSD licensed: see 

https://github.com/mitsuhiko/jinja2/blob/master/LICENSE) 

* Pandas compatibility module pandas.compat 

* six.py by Benjamin Peterson 

* Django 

""" 

 

import types 

import sys 

import numbers 

import functools 

import copy 

import inspect 

 

 

PY3 = sys.version_info[0] == 3 

PY35_PLUS = sys.version_info[0:2] >= (3, 5) 

PY36_PLUS = sys.version_info[0:2] >= (3, 6) 

PY2 = sys.version_info[0] == 2 

PY26 = sys.version_info[0:2] == (2, 6) 

PY27 = sys.version_info[0:2] == (2, 7) 

PYPY = hasattr(sys, 'pypy_translation_info') 

 

 

def python_2_unicode_compatible(cls): 

""" 

A decorator that defines __unicode__ and __str__ methods under Python 

2. Under Python 3, this decorator is a no-op. 

 

To support Python 2 and 3 with a single code base, define a __str__ 

method returning unicode text and apply this decorator to the class, like 

this:: 

 

>>> from future.utils import python_2_unicode_compatible 

 

>>> @python_2_unicode_compatible 

... class MyClass(object): 

... def __str__(self): 

... return u'Unicode string: \u5b54\u5b50' 

 

>>> a = MyClass() 

 

Then, after this import: 

 

>>> from future.builtins import str 

 

the following is ``True`` on both Python 3 and 2:: 

 

>>> str(a) == a.encode('utf-8').decode('utf-8') 

True 

 

and, on a Unicode-enabled terminal with the right fonts, these both print the 

Chinese characters for Confucius:: 

 

>>> print(a) 

>>> print(str(a)) 

 

The implementation comes from django.utils.encoding. 

""" 

if not PY3: 

cls.__unicode__ = cls.__str__ 

cls.__str__ = lambda self: self.__unicode__().encode('utf-8') 

return cls 

 

 

def with_metaclass(meta, *bases): 

""" 

Function from jinja2/_compat.py. License: BSD. 

 

Use it like this:: 

 

class BaseForm(object): 

pass 

 

class FormType(type): 

pass 

 

class Form(with_metaclass(FormType, BaseForm)): 

pass 

 

This requires a bit of explanation: the basic idea is to make a 

dummy metaclass for one level of class instantiation that replaces 

itself with the actual metaclass. Because of internal type checks 

we also need to make sure that we downgrade the custom metaclass 

for one level to something closer to type (that's why __call__ and 

__init__ comes back from type etc.). 

 

This has the advantage over six.with_metaclass of not introducing 

dummy classes into the final MRO. 

""" 

class metaclass(meta): 

__call__ = type.__call__ 

__init__ = type.__init__ 

def __new__(cls, name, this_bases, d): 

if this_bases is None: 

return type.__new__(cls, name, (), d) 

return meta(name, bases, d) 

return metaclass('temporary_class', None, {}) 

 

 

# Definitions from pandas.compat and six.py follow: 

if PY3: 

def bchr(s): 

return bytes([s]) 

def bstr(s): 

if isinstance(s, str): 

return bytes(s, 'latin-1') 

else: 

return bytes(s) 

def bord(s): 

return s 

 

string_types = str, 

integer_types = int, 

class_types = type, 

text_type = str 

binary_type = bytes 

 

else: 

# Python 2 

def bchr(s): 

return chr(s) 

def bstr(s): 

return str(s) 

def bord(s): 

return ord(s) 

 

string_types = basestring, 

integer_types = (int, long) 

class_types = (type, types.ClassType) 

text_type = unicode 

binary_type = str 

 

### 

 

if PY3: 

def tobytes(s): 

if isinstance(s, bytes): 

return s 

else: 

if isinstance(s, str): 

return s.encode('latin-1') 

else: 

return bytes(s) 

else: 

# Python 2 

def tobytes(s): 

if isinstance(s, unicode): 

return s.encode('latin-1') 

else: 

return ''.join(s) 

 

tobytes.__doc__ = """ 

Encodes to latin-1 (where the first 256 chars are the same as 

ASCII.) 

""" 

 

if PY3: 

def native_str_to_bytes(s, encoding='utf-8'): 

return s.encode(encoding) 

 

def bytes_to_native_str(b, encoding='utf-8'): 

return b.decode(encoding) 

 

def text_to_native_str(t, encoding=None): 

return t 

else: 

# Python 2 

def native_str_to_bytes(s, encoding=None): 

from future.types import newbytes # to avoid a circular import 

return newbytes(s) 

 

def bytes_to_native_str(b, encoding=None): 

return native(b) 

 

def text_to_native_str(t, encoding='ascii'): 

""" 

Use this to create a Py2 native string when "from __future__ import 

unicode_literals" is in effect. 

""" 

return unicode(t).encode(encoding) 

 

native_str_to_bytes.__doc__ = """ 

On Py3, returns an encoded string. 

On Py2, returns a newbytes type, ignoring the ``encoding`` argument. 

""" 

 

if PY3: 

# list-producing versions of the major Python iterating functions 

def lrange(*args, **kwargs): 

return list(range(*args, **kwargs)) 

 

def lzip(*args, **kwargs): 

return list(zip(*args, **kwargs)) 

 

def lmap(*args, **kwargs): 

return list(map(*args, **kwargs)) 

 

def lfilter(*args, **kwargs): 

return list(filter(*args, **kwargs)) 

else: 

import __builtin__ 

# Python 2-builtin ranges produce lists 

lrange = __builtin__.range 

lzip = __builtin__.zip 

lmap = __builtin__.map 

lfilter = __builtin__.filter 

 

 

def isidentifier(s, dotted=False): 

''' 

A function equivalent to the str.isidentifier method on Py3 

''' 

if dotted: 

return all(isidentifier(a) for a in s.split('.')) 

if PY3: 

return s.isidentifier() 

else: 

import re 

_name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*$") 

return bool(_name_re.match(s)) 

 

 

def viewitems(obj, **kwargs): 

""" 

Function for iterating over dictionary items with the same set-like 

behaviour on Py2.7 as on Py3. 

 

Passes kwargs to method.""" 

func = getattr(obj, "viewitems", None) 

if not func: 

func = obj.items 

return func(**kwargs) 

 

 

def viewkeys(obj, **kwargs): 

""" 

Function for iterating over dictionary keys with the same set-like 

behaviour on Py2.7 as on Py3. 

 

Passes kwargs to method.""" 

func = getattr(obj, "viewkeys", None) 

if not func: 

func = obj.keys 

return func(**kwargs) 

 

 

def viewvalues(obj, **kwargs): 

""" 

Function for iterating over dictionary values with the same set-like 

behaviour on Py2.7 as on Py3. 

 

Passes kwargs to method.""" 

func = getattr(obj, "viewvalues", None) 

if not func: 

func = obj.values 

return func(**kwargs) 

 

 

def iteritems(obj, **kwargs): 

"""Use this only if compatibility with Python versions before 2.7 is 

required. Otherwise, prefer viewitems(). 

""" 

func = getattr(obj, "iteritems", None) 

if not func: 

func = obj.items 

return func(**kwargs) 

 

 

def iterkeys(obj, **kwargs): 

"""Use this only if compatibility with Python versions before 2.7 is 

required. Otherwise, prefer viewkeys(). 

""" 

func = getattr(obj, "iterkeys", None) 

if not func: 

func = obj.keys 

return func(**kwargs) 

 

 

def itervalues(obj, **kwargs): 

"""Use this only if compatibility with Python versions before 2.7 is 

required. Otherwise, prefer viewvalues(). 

""" 

func = getattr(obj, "itervalues", None) 

if not func: 

func = obj.values 

return func(**kwargs) 

 

 

def bind_method(cls, name, func): 

"""Bind a method to class, python 2 and python 3 compatible. 

 

Parameters 

---------- 

 

cls : type 

class to receive bound method 

name : basestring 

name of method on class instance 

func : function 

function to be bound as method 

 

Returns 

------- 

None 

""" 

# only python 2 has an issue with bound/unbound methods 

if not PY3: 

setattr(cls, name, types.MethodType(func, None, cls)) 

else: 

setattr(cls, name, func) 

 

 

def getexception(): 

return sys.exc_info()[1] 

 

 

def _get_caller_globals_and_locals(): 

""" 

Returns the globals and locals of the calling frame. 

 

Is there an alternative to frame hacking here? 

""" 

caller_frame = inspect.stack()[2] 

myglobals = caller_frame[0].f_globals 

mylocals = caller_frame[0].f_locals 

return myglobals, mylocals 

 

 

def _repr_strip(mystring): 

""" 

Returns the string without any initial or final quotes. 

""" 

r = repr(mystring) 

if r.startswith("'") and r.endswith("'"): 

return r[1:-1] 

else: 

return r 

 

 

if PY3: 

def raise_from(exc, cause): 

""" 

Equivalent to: 

 

raise EXCEPTION from CAUSE 

 

on Python 3. (See PEP 3134). 

""" 

myglobals, mylocals = _get_caller_globals_and_locals() 

 

# We pass the exception and cause along with other globals 

# when we exec(): 

myglobals = myglobals.copy() 

myglobals['__python_future_raise_from_exc'] = exc 

myglobals['__python_future_raise_from_cause'] = cause 

execstr = "raise __python_future_raise_from_exc from __python_future_raise_from_cause" 

exec(execstr, myglobals, mylocals) 

 

def raise_(tp, value=None, tb=None): 

""" 

A function that matches the Python 2.x ``raise`` statement. This 

allows re-raising exceptions with the cls value and traceback on 

Python 2 and 3. 

""" 

if value is not None and isinstance(tp, Exception): 

raise TypeError("instance exception may not have a separate value") 

if value is not None: 

exc = tp(value) 

else: 

exc = tp 

if exc.__traceback__ is not tb: 

raise exc.with_traceback(tb) 

raise exc 

 

def raise_with_traceback(exc, traceback=Ellipsis): 

if traceback == Ellipsis: 

_, _, traceback = sys.exc_info() 

raise exc.with_traceback(traceback) 

 

else: 

def raise_from(exc, cause): 

""" 

Equivalent to: 

 

raise EXCEPTION from CAUSE 

 

on Python 3. (See PEP 3134). 

""" 

# Is either arg an exception class (e.g. IndexError) rather than 

# instance (e.g. IndexError('my message here')? If so, pass the 

# name of the class undisturbed through to "raise ... from ...". 

if isinstance(exc, type) and issubclass(exc, Exception): 

e = exc() 

# exc = exc.__name__ 

# execstr = "e = " + _repr_strip(exc) + "()" 

# myglobals, mylocals = _get_caller_globals_and_locals() 

# exec(execstr, myglobals, mylocals) 

else: 

e = exc 

e.__suppress_context__ = False 

if isinstance(cause, type) and issubclass(cause, Exception): 

e.__cause__ = cause() 

e.__suppress_context__ = True 

elif cause is None: 

e.__cause__ = None 

e.__suppress_context__ = True 

elif isinstance(cause, BaseException): 

e.__cause__ = cause 

e.__suppress_context__ = True 

else: 

raise TypeError("exception causes must derive from BaseException") 

e.__context__ = sys.exc_info()[1] 

raise e 

 

exec(''' 

def raise_(tp, value=None, tb=None): 

raise tp, value, tb 

 

def raise_with_traceback(exc, traceback=Ellipsis): 

if traceback == Ellipsis: 

_, _, traceback = sys.exc_info() 

raise exc, None, traceback 

'''.strip()) 

 

 

raise_with_traceback.__doc__ = ( 

"""Raise exception with existing traceback. 

If traceback is not passed, uses sys.exc_info() to get traceback.""" 

) 

 

 

# Deprecated alias for backward compatibility with ``future`` versions < 0.11: 

reraise = raise_ 

 

 

def implements_iterator(cls): 

''' 

From jinja2/_compat.py. License: BSD. 

 

Use as a decorator like this:: 

 

@implements_iterator 

class UppercasingIterator(object): 

def __init__(self, iterable): 

self._iter = iter(iterable) 

def __iter__(self): 

return self 

def __next__(self): 

return next(self._iter).upper() 

 

''' 

if PY3: 

return cls 

else: 

cls.next = cls.__next__ 

del cls.__next__ 

return cls 

 

if PY3: 

get_next = lambda x: x.next 

else: 

get_next = lambda x: x.__next__ 

 

 

def encode_filename(filename): 

if PY3: 

return filename 

else: 

if isinstance(filename, unicode): 

return filename.encode('utf-8') 

return filename 

 

 

def is_new_style(cls): 

""" 

Python 2.7 has both new-style and old-style classes. Old-style classes can 

be pesky in some circumstances, such as when using inheritance. Use this 

function to test for whether a class is new-style. (Python 3 only has 

new-style classes.) 

""" 

return hasattr(cls, '__class__') and ('__dict__' in dir(cls) 

or hasattr(cls, '__slots__')) 

 

# The native platform string and bytes types. Useful because ``str`` and 

# ``bytes`` are redefined on Py2 by ``from future.builtins import *``. 

native_str = str 

native_bytes = bytes 

 

 

def istext(obj): 

""" 

Deprecated. Use:: 

>>> isinstance(obj, str) 

after this import: 

>>> from future.builtins import str 

""" 

return isinstance(obj, type(u'')) 

 

 

def isbytes(obj): 

""" 

Deprecated. Use:: 

>>> isinstance(obj, bytes) 

after this import: 

>>> from future.builtins import bytes 

""" 

return isinstance(obj, type(b'')) 

 

 

def isnewbytes(obj): 

""" 

Equivalent to the result of ``isinstance(obj, newbytes)`` were 

``__instancecheck__`` not overridden on the newbytes subclass. In 

other words, it is REALLY a newbytes instance, not a Py2 native str 

object? 

""" 

# TODO: generalize this so that it works with subclasses of newbytes 

# Import is here to avoid circular imports: 

from future.types.newbytes import newbytes 

return type(obj) == newbytes 

 

 

def isint(obj): 

""" 

Deprecated. Tests whether an object is a Py3 ``int`` or either a Py2 ``int`` or 

``long``. 

 

Instead of using this function, you can use: 

 

>>> from future.builtins import int 

>>> isinstance(obj, int) 

 

The following idiom is equivalent: 

 

>>> from numbers import Integral 

>>> isinstance(obj, Integral) 

""" 

 

return isinstance(obj, numbers.Integral) 

 

 

def native(obj): 

""" 

On Py3, this is a no-op: native(obj) -> obj 

 

On Py2, returns the corresponding native Py2 types that are 

superclasses for backported objects from Py3: 

 

>>> from builtins import str, bytes, int 

 

>>> native(str(u'ABC')) 

u'ABC' 

>>> type(native(str(u'ABC'))) 

unicode 

 

>>> native(bytes(b'ABC')) 

b'ABC' 

>>> type(native(bytes(b'ABC'))) 

bytes 

 

>>> native(int(10**20)) 

100000000000000000000L 

>>> type(native(int(10**20))) 

long 

 

Existing native types on Py2 will be returned unchanged: 

 

>>> type(native(u'ABC')) 

unicode 

""" 

if hasattr(obj, '__native__'): 

return obj.__native__() 

else: 

return obj 

 

 

# Implementation of exec_ is from ``six``: 

if PY3: 

import builtins 

exec_ = getattr(builtins, "exec") 

else: 

def exec_(code, globs=None, locs=None): 

"""Execute code in a namespace.""" 

if globs is None: 

frame = sys._getframe(1) 

globs = frame.f_globals 

if locs is None: 

locs = frame.f_locals 

del frame 

elif locs is None: 

locs = globs 

exec("""exec code in globs, locs""") 

 

 

# Defined here for backward compatibility: 

def old_div(a, b): 

""" 

DEPRECATED: import ``old_div`` from ``past.utils`` instead. 

 

Equivalent to ``a / b`` on Python 2 without ``from __future__ import 

division``. 

 

TODO: generalize this to other objects (like arrays etc.) 

""" 

if isinstance(a, numbers.Integral) and isinstance(b, numbers.Integral): 

return a // b 

else: 

return a / b 

 

 

def as_native_str(encoding='utf-8'): 

''' 

A decorator to turn a function or method call that returns text, i.e. 

unicode, into one that returns a native platform str. 

 

Use it as a decorator like this:: 

 

from __future__ import unicode_literals 

 

class MyClass(object): 

@as_native_str(encoding='ascii') 

def __repr__(self): 

return next(self._iter).upper() 

''' 

if PY3: 

return lambda f: f 

else: 

def encoder(f): 

@functools.wraps(f) 

def wrapper(*args, **kwargs): 

return f(*args, **kwargs).encode(encoding=encoding) 

return wrapper 

return encoder 

 

# listvalues and listitems definitions from Nick Coghlan's (withdrawn) 

# PEP 496: 

try: 

dict.iteritems 

except AttributeError: 

# Python 3 

def listvalues(d): 

return list(d.values()) 

def listitems(d): 

return list(d.items()) 

else: 

# Python 2 

def listvalues(d): 

return d.values() 

def listitems(d): 

return d.items() 

 

if PY3: 

def ensure_new_type(obj): 

return obj 

else: 

def ensure_new_type(obj): 

from future.types.newbytes import newbytes 

from future.types.newstr import newstr 

from future.types.newint import newint 

from future.types.newdict import newdict 

 

native_type = type(native(obj)) 

 

# Upcast only if the type is already a native (non-future) type 

if issubclass(native_type, type(obj)): 

# Upcast 

if native_type == str: # i.e. Py2 8-bit str 

return newbytes(obj) 

elif native_type == unicode: 

return newstr(obj) 

elif native_type == int: 

return newint(obj) 

elif native_type == long: 

return newint(obj) 

elif native_type == dict: 

return newdict(obj) 

else: 

return obj 

else: 

# Already a new type 

assert type(obj) in [newbytes, newstr] 

return obj 

 

 

__all__ = ['PY2', 'PY26', 'PY3', 'PYPY', 

'as_native_str', 'bind_method', 'bord', 'bstr', 

'bytes_to_native_str', 'encode_filename', 'ensure_new_type', 

'exec_', 'get_next', 'getexception', 'implements_iterator', 

'is_new_style', 'isbytes', 'isidentifier', 'isint', 

'isnewbytes', 'istext', 'iteritems', 'iterkeys', 'itervalues', 

'lfilter', 'listitems', 'listvalues', 'lmap', 'lrange', 

'lzip', 'native', 'native_bytes', 'native_str', 

'native_str_to_bytes', 'old_div', 

'python_2_unicode_compatible', 'raise_', 

'raise_with_traceback', 'reraise', 'text_to_native_str', 

'tobytes', 'viewitems', 'viewkeys', 'viewvalues', 

'with_metaclass' 

]