mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Merge pull request #1751 from RustPython/master
Merge to release again to fix demo performance issues
This commit is contained in:
7
.github/workflows/ci.yaml
vendored
7
.github/workflows/ci.yaml
vendored
@@ -124,6 +124,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Cache cargo dependencies
|
||||
uses: actions/cache@v1
|
||||
with:
|
||||
key: ${{ runner.os }}-wasm-${{ hashFiles('**/Cargo.lock') }}
|
||||
path: target
|
||||
restore-keys: |
|
||||
${{ runner.os }}-wasm-
|
||||
- name: install wasm-pack
|
||||
run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh
|
||||
- name: install geckodriver
|
||||
|
||||
11
Cargo.lock
generated
11
Cargo.lock
generated
@@ -1245,15 +1245,6 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_distr"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96977acbdd3a6576fb1d27391900035bf3863d4a16422973a409b488cf29ffb2"
|
||||
dependencies = [
|
||||
"rand 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.1.0"
|
||||
@@ -1539,7 +1530,7 @@ dependencies = [
|
||||
"paste",
|
||||
"pwd",
|
||||
"rand 0.7.3",
|
||||
"rand_distr",
|
||||
"rand_core 0.5.1",
|
||||
"regex",
|
||||
"result-like",
|
||||
"rustc_version_runtime",
|
||||
|
||||
772
Lib/random.py
vendored
Normal file
772
Lib/random.py
vendored
Normal file
@@ -0,0 +1,772 @@
|
||||
"""Random variable generators.
|
||||
|
||||
integers
|
||||
--------
|
||||
uniform within range
|
||||
|
||||
sequences
|
||||
---------
|
||||
pick random element
|
||||
pick random sample
|
||||
pick weighted random sample
|
||||
generate random permutation
|
||||
|
||||
distributions on the real line:
|
||||
------------------------------
|
||||
uniform
|
||||
triangular
|
||||
normal (Gaussian)
|
||||
lognormal
|
||||
negative exponential
|
||||
gamma
|
||||
beta
|
||||
pareto
|
||||
Weibull
|
||||
|
||||
distributions on the circle (angles 0 to 2pi)
|
||||
---------------------------------------------
|
||||
circular uniform
|
||||
von Mises
|
||||
|
||||
General notes on the underlying Mersenne Twister core generator:
|
||||
|
||||
* The period is 2**19937-1.
|
||||
* It is one of the most extensively tested generators in existence.
|
||||
* The random() method is implemented in C, executes in a single Python step,
|
||||
and is, therefore, threadsafe.
|
||||
|
||||
"""
|
||||
|
||||
from warnings import warn as _warn
|
||||
from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType
|
||||
from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil
|
||||
from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin
|
||||
from os import urandom as _urandom
|
||||
from _collections_abc import Set as _Set, Sequence as _Sequence
|
||||
from hashlib import sha512 as _sha512
|
||||
import itertools as _itertools
|
||||
import bisect as _bisect
|
||||
|
||||
__all__ = ["Random","seed","random","uniform","randint","choice","sample",
|
||||
"randrange","shuffle","normalvariate","lognormvariate",
|
||||
"expovariate","vonmisesvariate","gammavariate","triangular",
|
||||
"gauss","betavariate","paretovariate","weibullvariate",
|
||||
"getstate","setstate", "getrandbits", "choices",
|
||||
"SystemRandom"]
|
||||
|
||||
NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0)
|
||||
TWOPI = 2.0*_pi
|
||||
LOG4 = _log(4.0)
|
||||
SG_MAGICCONST = 1.0 + _log(4.5)
|
||||
BPF = 53 # Number of bits in a float
|
||||
RECIP_BPF = 2**-BPF
|
||||
|
||||
|
||||
# Translated by Guido van Rossum from C source provided by
|
||||
# Adrian Baddeley. Adapted by Raymond Hettinger for use with
|
||||
# the Mersenne Twister and os.urandom() core generators.
|
||||
|
||||
import _random
|
||||
|
||||
class Random(_random.Random):
|
||||
"""Random number generator base class used by bound module functions.
|
||||
|
||||
Used to instantiate instances of Random to get generators that don't
|
||||
share state.
|
||||
|
||||
Class Random can also be subclassed if you want to use a different basic
|
||||
generator of your own devising: in that case, override the following
|
||||
methods: random(), seed(), getstate(), and setstate().
|
||||
Optionally, implement a getrandbits() method so that randrange()
|
||||
can cover arbitrarily large ranges.
|
||||
|
||||
"""
|
||||
|
||||
VERSION = 3 # used by getstate/setstate
|
||||
|
||||
def __init__(self, x=None):
|
||||
"""Initialize an instance.
|
||||
|
||||
Optional argument x controls seeding, as for Random.seed().
|
||||
"""
|
||||
|
||||
self.seed(x)
|
||||
self.gauss_next = None
|
||||
|
||||
def seed(self, a=None, version=2):
|
||||
"""Initialize internal state from hashable object.
|
||||
|
||||
None or no argument seeds from current time or from an operating
|
||||
system specific randomness source if available.
|
||||
|
||||
If *a* is an int, all bits are used.
|
||||
|
||||
For version 2 (the default), all of the bits are used if *a* is a str,
|
||||
bytes, or bytearray. For version 1 (provided for reproducing random
|
||||
sequences from older versions of Python), the algorithm for str and
|
||||
bytes generates a narrower range of seeds.
|
||||
|
||||
"""
|
||||
|
||||
if version == 1 and isinstance(a, (str, bytes)):
|
||||
a = a.decode('latin-1') if isinstance(a, bytes) else a
|
||||
x = ord(a[0]) << 7 if a else 0
|
||||
for c in map(ord, a):
|
||||
x = ((1000003 * x) ^ c) & 0xFFFFFFFFFFFFFFFF
|
||||
x ^= len(a)
|
||||
a = -2 if x == -1 else x
|
||||
|
||||
if version == 2 and isinstance(a, (str, bytes, bytearray)):
|
||||
if isinstance(a, str):
|
||||
a = a.encode()
|
||||
a += _sha512(a).digest()
|
||||
a = int.from_bytes(a, 'big')
|
||||
|
||||
super().seed(a)
|
||||
self.gauss_next = None
|
||||
|
||||
def getstate(self):
|
||||
"""Return internal state; can be passed to setstate() later."""
|
||||
return self.VERSION, super().getstate(), self.gauss_next
|
||||
|
||||
def setstate(self, state):
|
||||
"""Restore internal state from object returned by getstate()."""
|
||||
version = state[0]
|
||||
if version == 3:
|
||||
version, internalstate, self.gauss_next = state
|
||||
super().setstate(internalstate)
|
||||
elif version == 2:
|
||||
version, internalstate, self.gauss_next = state
|
||||
# In version 2, the state was saved as signed ints, which causes
|
||||
# inconsistencies between 32/64-bit systems. The state is
|
||||
# really unsigned 32-bit ints, so we convert negative ints from
|
||||
# version 2 to positive longs for version 3.
|
||||
try:
|
||||
internalstate = tuple(x % (2**32) for x in internalstate)
|
||||
except ValueError as e:
|
||||
raise TypeError from e
|
||||
super().setstate(internalstate)
|
||||
else:
|
||||
raise ValueError("state with version %s passed to "
|
||||
"Random.setstate() of version %s" %
|
||||
(version, self.VERSION))
|
||||
|
||||
## ---- Methods below this point do not need to be overridden when
|
||||
## ---- subclassing for the purpose of using a different core generator.
|
||||
|
||||
## -------------------- pickle support -------------------
|
||||
|
||||
# Issue 17489: Since __reduce__ was defined to fix #759889 this is no
|
||||
# longer called; we leave it here because it has been here since random was
|
||||
# rewritten back in 2001 and why risk breaking something.
|
||||
def __getstate__(self): # for pickle
|
||||
return self.getstate()
|
||||
|
||||
def __setstate__(self, state): # for pickle
|
||||
self.setstate(state)
|
||||
|
||||
def __reduce__(self):
|
||||
return self.__class__, (), self.getstate()
|
||||
|
||||
## -------------------- integer methods -------------------
|
||||
|
||||
def randrange(self, start, stop=None, step=1, _int=int):
|
||||
"""Choose a random item from range(start, stop[, step]).
|
||||
|
||||
This fixes the problem with randint() which includes the
|
||||
endpoint; in Python this is usually not what you want.
|
||||
|
||||
"""
|
||||
|
||||
# This code is a bit messy to make it fast for the
|
||||
# common case while still doing adequate error checking.
|
||||
istart = _int(start)
|
||||
if istart != start:
|
||||
raise ValueError("non-integer arg 1 for randrange()")
|
||||
if stop is None:
|
||||
if istart > 0:
|
||||
return self._randbelow(istart)
|
||||
raise ValueError("empty range for randrange()")
|
||||
|
||||
# stop argument supplied.
|
||||
istop = _int(stop)
|
||||
if istop != stop:
|
||||
raise ValueError("non-integer stop for randrange()")
|
||||
width = istop - istart
|
||||
if step == 1 and width > 0:
|
||||
return istart + self._randbelow(width)
|
||||
if step == 1:
|
||||
raise ValueError("empty range for randrange() (%d,%d, %d)" % (istart, istop, width))
|
||||
|
||||
# Non-unit step argument supplied.
|
||||
istep = _int(step)
|
||||
if istep != step:
|
||||
raise ValueError("non-integer step for randrange()")
|
||||
if istep > 0:
|
||||
n = (width + istep - 1) // istep
|
||||
elif istep < 0:
|
||||
n = (width + istep + 1) // istep
|
||||
else:
|
||||
raise ValueError("zero step for randrange()")
|
||||
|
||||
if n <= 0:
|
||||
raise ValueError("empty range for randrange()")
|
||||
|
||||
return istart + istep*self._randbelow(n)
|
||||
|
||||
def randint(self, a, b):
|
||||
"""Return random integer in range [a, b], including both end points.
|
||||
"""
|
||||
|
||||
return self.randrange(a, b+1)
|
||||
|
||||
def _randbelow(self, n, int=int, maxsize=1<<BPF, type=type,
|
||||
Method=_MethodType, BuiltinMethod=_BuiltinMethodType):
|
||||
"Return a random int in the range [0,n). Raises ValueError if n==0."
|
||||
|
||||
random = self.random
|
||||
getrandbits = self.getrandbits
|
||||
# Only call self.getrandbits if the original random() builtin method
|
||||
# has not been overridden or if a new getrandbits() was supplied.
|
||||
if type(random) is BuiltinMethod or type(getrandbits) is Method:
|
||||
k = n.bit_length() # don't use (n-1) here because n can be 1
|
||||
r = getrandbits(k) # 0 <= r < 2**k
|
||||
while r >= n:
|
||||
r = getrandbits(k)
|
||||
return r
|
||||
# There's an overridden random() method but no new getrandbits() method,
|
||||
# so we can only use random() from here.
|
||||
if n >= maxsize:
|
||||
_warn("Underlying random() generator does not supply \n"
|
||||
"enough bits to choose from a population range this large.\n"
|
||||
"To remove the range limitation, add a getrandbits() method.")
|
||||
return int(random() * n)
|
||||
if n == 0:
|
||||
raise ValueError("Boundary cannot be zero")
|
||||
rem = maxsize % n
|
||||
limit = (maxsize - rem) / maxsize # int(limit * maxsize) % n == 0
|
||||
r = random()
|
||||
while r >= limit:
|
||||
r = random()
|
||||
return int(r*maxsize) % n
|
||||
|
||||
## -------------------- sequence methods -------------------
|
||||
|
||||
def choice(self, seq):
|
||||
"""Choose a random element from a non-empty sequence."""
|
||||
try:
|
||||
i = self._randbelow(len(seq))
|
||||
except ValueError:
|
||||
raise IndexError('Cannot choose from an empty sequence') from None
|
||||
return seq[i]
|
||||
|
||||
def shuffle(self, x, random=None):
|
||||
"""Shuffle list x in place, and return None.
|
||||
|
||||
Optional argument random is a 0-argument function returning a
|
||||
random float in [0.0, 1.0); if it is the default None, the
|
||||
standard random.random will be used.
|
||||
|
||||
"""
|
||||
|
||||
if random is None:
|
||||
randbelow = self._randbelow
|
||||
for i in reversed(range(1, len(x))):
|
||||
# pick an element in x[:i+1] with which to exchange x[i]
|
||||
j = randbelow(i+1)
|
||||
x[i], x[j] = x[j], x[i]
|
||||
else:
|
||||
_int = int
|
||||
for i in reversed(range(1, len(x))):
|
||||
# pick an element in x[:i+1] with which to exchange x[i]
|
||||
j = _int(random() * (i+1))
|
||||
x[i], x[j] = x[j], x[i]
|
||||
|
||||
def sample(self, population, k):
|
||||
"""Chooses k unique random elements from a population sequence or set.
|
||||
|
||||
Returns a new list containing elements from the population while
|
||||
leaving the original population unchanged. The resulting list is
|
||||
in selection order so that all sub-slices will also be valid random
|
||||
samples. This allows raffle winners (the sample) to be partitioned
|
||||
into grand prize and second place winners (the subslices).
|
||||
|
||||
Members of the population need not be hashable or unique. If the
|
||||
population contains repeats, then each occurrence is a possible
|
||||
selection in the sample.
|
||||
|
||||
To choose a sample in a range of integers, use range as an argument.
|
||||
This is especially fast and space efficient for sampling from a
|
||||
large population: sample(range(10000000), 60)
|
||||
"""
|
||||
|
||||
# Sampling without replacement entails tracking either potential
|
||||
# selections (the pool) in a list or previous selections in a set.
|
||||
|
||||
# When the number of selections is small compared to the
|
||||
# population, then tracking selections is efficient, requiring
|
||||
# only a small set and an occasional reselection. For
|
||||
# a larger number of selections, the pool tracking method is
|
||||
# preferred since the list takes less space than the
|
||||
# set and it doesn't suffer from frequent reselections.
|
||||
|
||||
if isinstance(population, _Set):
|
||||
population = tuple(population)
|
||||
if not isinstance(population, _Sequence):
|
||||
raise TypeError("Population must be a sequence or set. For dicts, use list(d).")
|
||||
randbelow = self._randbelow
|
||||
n = len(population)
|
||||
if not 0 <= k <= n:
|
||||
raise ValueError("Sample larger than population or is negative")
|
||||
result = [None] * k
|
||||
setsize = 21 # size of a small set minus size of an empty list
|
||||
if k > 5:
|
||||
setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets
|
||||
if n <= setsize:
|
||||
# An n-length list is smaller than a k-length set
|
||||
pool = list(population)
|
||||
for i in range(k): # invariant: non-selected at [0,n-i)
|
||||
j = randbelow(n-i)
|
||||
result[i] = pool[j]
|
||||
pool[j] = pool[n-i-1] # move non-selected item into vacancy
|
||||
else:
|
||||
selected = set()
|
||||
selected_add = selected.add
|
||||
for i in range(k):
|
||||
j = randbelow(n)
|
||||
while j in selected:
|
||||
j = randbelow(n)
|
||||
selected_add(j)
|
||||
result[i] = population[j]
|
||||
return result
|
||||
|
||||
def choices(self, population, weights=None, *, cum_weights=None, k=1):
|
||||
"""Return a k sized list of population elements chosen with replacement.
|
||||
|
||||
If the relative weights or cumulative weights are not specified,
|
||||
the selections are made with equal probability.
|
||||
|
||||
"""
|
||||
random = self.random
|
||||
if cum_weights is None:
|
||||
if weights is None:
|
||||
_int = int
|
||||
total = len(population)
|
||||
return [population[_int(random() * total)] for i in range(k)]
|
||||
cum_weights = list(_itertools.accumulate(weights))
|
||||
elif weights is not None:
|
||||
raise TypeError('Cannot specify both weights and cumulative weights')
|
||||
if len(cum_weights) != len(population):
|
||||
raise ValueError('The number of weights does not match the population')
|
||||
bisect = _bisect.bisect
|
||||
total = cum_weights[-1]
|
||||
hi = len(cum_weights) - 1
|
||||
return [population[bisect(cum_weights, random() * total, 0, hi)]
|
||||
for i in range(k)]
|
||||
|
||||
## -------------------- real-valued distributions -------------------
|
||||
|
||||
## -------------------- uniform distribution -------------------
|
||||
|
||||
def uniform(self, a, b):
|
||||
"Get a random number in the range [a, b) or [a, b] depending on rounding."
|
||||
return a + (b-a) * self.random()
|
||||
|
||||
## -------------------- triangular --------------------
|
||||
|
||||
def triangular(self, low=0.0, high=1.0, mode=None):
|
||||
"""Triangular distribution.
|
||||
|
||||
Continuous distribution bounded by given lower and upper limits,
|
||||
and having a given mode value in-between.
|
||||
|
||||
http://en.wikipedia.org/wiki/Triangular_distribution
|
||||
|
||||
"""
|
||||
u = self.random()
|
||||
try:
|
||||
c = 0.5 if mode is None else (mode - low) / (high - low)
|
||||
except ZeroDivisionError:
|
||||
return low
|
||||
if u > c:
|
||||
u = 1.0 - u
|
||||
c = 1.0 - c
|
||||
low, high = high, low
|
||||
return low + (high - low) * (u * c) ** 0.5
|
||||
|
||||
## -------------------- normal distribution --------------------
|
||||
|
||||
def normalvariate(self, mu, sigma):
|
||||
"""Normal distribution.
|
||||
|
||||
mu is the mean, and sigma is the standard deviation.
|
||||
|
||||
"""
|
||||
# mu = mean, sigma = standard deviation
|
||||
|
||||
# Uses Kinderman and Monahan method. Reference: Kinderman,
|
||||
# A.J. and Monahan, J.F., "Computer generation of random
|
||||
# variables using the ratio of uniform deviates", ACM Trans
|
||||
# Math Software, 3, (1977), pp257-260.
|
||||
|
||||
random = self.random
|
||||
while 1:
|
||||
u1 = random()
|
||||
u2 = 1.0 - random()
|
||||
z = NV_MAGICCONST*(u1-0.5)/u2
|
||||
zz = z*z/4.0
|
||||
if zz <= -_log(u2):
|
||||
break
|
||||
return mu + z*sigma
|
||||
|
||||
## -------------------- lognormal distribution --------------------
|
||||
|
||||
def lognormvariate(self, mu, sigma):
|
||||
"""Log normal distribution.
|
||||
|
||||
If you take the natural logarithm of this distribution, you'll get a
|
||||
normal distribution with mean mu and standard deviation sigma.
|
||||
mu can have any value, and sigma must be greater than zero.
|
||||
|
||||
"""
|
||||
return _exp(self.normalvariate(mu, sigma))
|
||||
|
||||
## -------------------- exponential distribution --------------------
|
||||
|
||||
def expovariate(self, lambd):
|
||||
"""Exponential distribution.
|
||||
|
||||
lambd is 1.0 divided by the desired mean. It should be
|
||||
nonzero. (The parameter would be called "lambda", but that is
|
||||
a reserved word in Python.) Returned values range from 0 to
|
||||
positive infinity if lambd is positive, and from negative
|
||||
infinity to 0 if lambd is negative.
|
||||
|
||||
"""
|
||||
# lambd: rate lambd = 1/mean
|
||||
# ('lambda' is a Python reserved word)
|
||||
|
||||
# we use 1-random() instead of random() to preclude the
|
||||
# possibility of taking the log of zero.
|
||||
return -_log(1.0 - self.random())/lambd
|
||||
|
||||
## -------------------- von Mises distribution --------------------
|
||||
|
||||
def vonmisesvariate(self, mu, kappa):
|
||||
"""Circular data distribution.
|
||||
|
||||
mu is the mean angle, expressed in radians between 0 and 2*pi, and
|
||||
kappa is the concentration parameter, which must be greater than or
|
||||
equal to zero. If kappa is equal to zero, this distribution reduces
|
||||
to a uniform random angle over the range 0 to 2*pi.
|
||||
|
||||
"""
|
||||
# mu: mean angle (in radians between 0 and 2*pi)
|
||||
# kappa: concentration parameter kappa (>= 0)
|
||||
# if kappa = 0 generate uniform random angle
|
||||
|
||||
# Based upon an algorithm published in: Fisher, N.I.,
|
||||
# "Statistical Analysis of Circular Data", Cambridge
|
||||
# University Press, 1993.
|
||||
|
||||
# Thanks to Magnus Kessler for a correction to the
|
||||
# implementation of step 4.
|
||||
|
||||
random = self.random
|
||||
if kappa <= 1e-6:
|
||||
return TWOPI * random()
|
||||
|
||||
s = 0.5 / kappa
|
||||
r = s + _sqrt(1.0 + s * s)
|
||||
|
||||
while 1:
|
||||
u1 = random()
|
||||
z = _cos(_pi * u1)
|
||||
|
||||
d = z / (r + z)
|
||||
u2 = random()
|
||||
if u2 < 1.0 - d * d or u2 <= (1.0 - d) * _exp(d):
|
||||
break
|
||||
|
||||
q = 1.0 / r
|
||||
f = (q + z) / (1.0 + q * z)
|
||||
u3 = random()
|
||||
if u3 > 0.5:
|
||||
theta = (mu + _acos(f)) % TWOPI
|
||||
else:
|
||||
theta = (mu - _acos(f)) % TWOPI
|
||||
|
||||
return theta
|
||||
|
||||
## -------------------- gamma distribution --------------------
|
||||
|
||||
def gammavariate(self, alpha, beta):
|
||||
"""Gamma distribution. Not the gamma function!
|
||||
|
||||
Conditions on the parameters are alpha > 0 and beta > 0.
|
||||
|
||||
The probability distribution function is:
|
||||
|
||||
x ** (alpha - 1) * math.exp(-x / beta)
|
||||
pdf(x) = --------------------------------------
|
||||
math.gamma(alpha) * beta ** alpha
|
||||
|
||||
"""
|
||||
|
||||
# alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2
|
||||
|
||||
# Warning: a few older sources define the gamma distribution in terms
|
||||
# of alpha > -1.0
|
||||
if alpha <= 0.0 or beta <= 0.0:
|
||||
raise ValueError('gammavariate: alpha and beta must be > 0.0')
|
||||
|
||||
random = self.random
|
||||
if alpha > 1.0:
|
||||
|
||||
# Uses R.C.H. Cheng, "The generation of Gamma
|
||||
# variables with non-integral shape parameters",
|
||||
# Applied Statistics, (1977), 26, No. 1, p71-74
|
||||
|
||||
ainv = _sqrt(2.0 * alpha - 1.0)
|
||||
bbb = alpha - LOG4
|
||||
ccc = alpha + ainv
|
||||
|
||||
while 1:
|
||||
u1 = random()
|
||||
if not 1e-7 < u1 < .9999999:
|
||||
continue
|
||||
u2 = 1.0 - random()
|
||||
v = _log(u1/(1.0-u1))/ainv
|
||||
x = alpha*_exp(v)
|
||||
z = u1*u1*u2
|
||||
r = bbb+ccc*v-x
|
||||
if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z):
|
||||
return x * beta
|
||||
|
||||
elif alpha == 1.0:
|
||||
# expovariate(1)
|
||||
u = random()
|
||||
while u <= 1e-7:
|
||||
u = random()
|
||||
return -_log(u) * beta
|
||||
|
||||
else: # alpha is between 0 and 1 (exclusive)
|
||||
|
||||
# Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle
|
||||
|
||||
while 1:
|
||||
u = random()
|
||||
b = (_e + alpha)/_e
|
||||
p = b*u
|
||||
if p <= 1.0:
|
||||
x = p ** (1.0/alpha)
|
||||
else:
|
||||
x = -_log((b-p)/alpha)
|
||||
u1 = random()
|
||||
if p > 1.0:
|
||||
if u1 <= x ** (alpha - 1.0):
|
||||
break
|
||||
elif u1 <= _exp(-x):
|
||||
break
|
||||
return x * beta
|
||||
|
||||
## -------------------- Gauss (faster alternative) --------------------
|
||||
|
||||
def gauss(self, mu, sigma):
|
||||
"""Gaussian distribution.
|
||||
|
||||
mu is the mean, and sigma is the standard deviation. This is
|
||||
slightly faster than the normalvariate() function.
|
||||
|
||||
Not thread-safe without a lock around calls.
|
||||
|
||||
"""
|
||||
|
||||
# When x and y are two variables from [0, 1), uniformly
|
||||
# distributed, then
|
||||
#
|
||||
# cos(2*pi*x)*sqrt(-2*log(1-y))
|
||||
# sin(2*pi*x)*sqrt(-2*log(1-y))
|
||||
#
|
||||
# are two *independent* variables with normal distribution
|
||||
# (mu = 0, sigma = 1).
|
||||
# (Lambert Meertens)
|
||||
# (corrected version; bug discovered by Mike Miller, fixed by LM)
|
||||
|
||||
# Multithreading note: When two threads call this function
|
||||
# simultaneously, it is possible that they will receive the
|
||||
# same return value. The window is very small though. To
|
||||
# avoid this, you have to use a lock around all calls. (I
|
||||
# didn't want to slow this down in the serial case by using a
|
||||
# lock here.)
|
||||
|
||||
random = self.random
|
||||
z = self.gauss_next
|
||||
self.gauss_next = None
|
||||
if z is None:
|
||||
x2pi = random() * TWOPI
|
||||
g2rad = _sqrt(-2.0 * _log(1.0 - random()))
|
||||
z = _cos(x2pi) * g2rad
|
||||
self.gauss_next = _sin(x2pi) * g2rad
|
||||
|
||||
return mu + z*sigma
|
||||
|
||||
## -------------------- beta --------------------
|
||||
## See
|
||||
## http://mail.python.org/pipermail/python-bugs-list/2001-January/003752.html
|
||||
## for Ivan Frohne's insightful analysis of why the original implementation:
|
||||
##
|
||||
## def betavariate(self, alpha, beta):
|
||||
## # Discrete Event Simulation in C, pp 87-88.
|
||||
##
|
||||
## y = self.expovariate(alpha)
|
||||
## z = self.expovariate(1.0/beta)
|
||||
## return z/(y+z)
|
||||
##
|
||||
## was dead wrong, and how it probably got that way.
|
||||
|
||||
def betavariate(self, alpha, beta):
|
||||
"""Beta distribution.
|
||||
|
||||
Conditions on the parameters are alpha > 0 and beta > 0.
|
||||
Returned values range between 0 and 1.
|
||||
|
||||
"""
|
||||
|
||||
# This version due to Janne Sinkkonen, and matches all the std
|
||||
# texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution").
|
||||
y = self.gammavariate(alpha, 1.0)
|
||||
if y == 0:
|
||||
return 0.0
|
||||
else:
|
||||
return y / (y + self.gammavariate(beta, 1.0))
|
||||
|
||||
## -------------------- Pareto --------------------
|
||||
|
||||
def paretovariate(self, alpha):
|
||||
"""Pareto distribution. alpha is the shape parameter."""
|
||||
# Jain, pg. 495
|
||||
|
||||
u = 1.0 - self.random()
|
||||
return 1.0 / u ** (1.0/alpha)
|
||||
|
||||
## -------------------- Weibull --------------------
|
||||
|
||||
def weibullvariate(self, alpha, beta):
|
||||
"""Weibull distribution.
|
||||
|
||||
alpha is the scale parameter and beta is the shape parameter.
|
||||
|
||||
"""
|
||||
# Jain, pg. 499; bug fix courtesy Bill Arms
|
||||
|
||||
u = 1.0 - self.random()
|
||||
return alpha * (-_log(u)) ** (1.0/beta)
|
||||
|
||||
## --------------- Operating System Random Source ------------------
|
||||
|
||||
class SystemRandom(Random):
|
||||
"""Alternate random number generator using sources provided
|
||||
by the operating system (such as /dev/urandom on Unix or
|
||||
CryptGenRandom on Windows).
|
||||
|
||||
Not available on all systems (see os.urandom() for details).
|
||||
"""
|
||||
|
||||
def random(self):
|
||||
"""Get the next random number in the range [0.0, 1.0)."""
|
||||
return (int.from_bytes(_urandom(7), 'big') >> 3) * RECIP_BPF
|
||||
|
||||
def getrandbits(self, k):
|
||||
"""getrandbits(k) -> x. Generates an int with k random bits."""
|
||||
if k <= 0:
|
||||
raise ValueError('number of bits must be greater than zero')
|
||||
if k != int(k):
|
||||
raise TypeError('number of bits should be an integer')
|
||||
numbytes = (k + 7) // 8 # bits / 8 and rounded up
|
||||
x = int.from_bytes(_urandom(numbytes), 'big')
|
||||
return x >> (numbytes * 8 - k) # trim excess bits
|
||||
|
||||
def seed(self, *args, **kwds):
|
||||
"Stub method. Not used for a system random number generator."
|
||||
return None
|
||||
|
||||
def _notimplemented(self, *args, **kwds):
|
||||
"Method should not be called for a system random number generator."
|
||||
raise NotImplementedError('System entropy source does not have state.')
|
||||
getstate = setstate = _notimplemented
|
||||
|
||||
## -------------------- test program --------------------
|
||||
|
||||
def _test_generator(n, func, args):
|
||||
import time
|
||||
print(n, 'times', func.__name__)
|
||||
total = 0.0
|
||||
sqsum = 0.0
|
||||
smallest = 1e10
|
||||
largest = -1e10
|
||||
t0 = time.time()
|
||||
for i in range(n):
|
||||
x = func(*args)
|
||||
total += x
|
||||
sqsum = sqsum + x*x
|
||||
smallest = min(x, smallest)
|
||||
largest = max(x, largest)
|
||||
t1 = time.time()
|
||||
print(round(t1-t0, 3), 'sec,', end=' ')
|
||||
avg = total/n
|
||||
stddev = _sqrt(sqsum/n - avg*avg)
|
||||
print('avg %g, stddev %g, min %g, max %g\n' % \
|
||||
(avg, stddev, smallest, largest))
|
||||
|
||||
|
||||
def _test(N=2000):
|
||||
_test_generator(N, random, ())
|
||||
_test_generator(N, normalvariate, (0.0, 1.0))
|
||||
_test_generator(N, lognormvariate, (0.0, 1.0))
|
||||
_test_generator(N, vonmisesvariate, (0.0, 1.0))
|
||||
_test_generator(N, gammavariate, (0.01, 1.0))
|
||||
_test_generator(N, gammavariate, (0.1, 1.0))
|
||||
_test_generator(N, gammavariate, (0.1, 2.0))
|
||||
_test_generator(N, gammavariate, (0.5, 1.0))
|
||||
_test_generator(N, gammavariate, (0.9, 1.0))
|
||||
_test_generator(N, gammavariate, (1.0, 1.0))
|
||||
_test_generator(N, gammavariate, (2.0, 1.0))
|
||||
_test_generator(N, gammavariate, (20.0, 1.0))
|
||||
_test_generator(N, gammavariate, (200.0, 1.0))
|
||||
_test_generator(N, gauss, (0.0, 1.0))
|
||||
_test_generator(N, betavariate, (3.0, 3.0))
|
||||
_test_generator(N, triangular, (0.0, 1.0, 1.0/3.0))
|
||||
|
||||
# Create one instance, seeded from current time, and export its methods
|
||||
# as module-level functions. The functions share state across all uses
|
||||
#(both in the user's code and in the Python libraries), but that's fine
|
||||
# for most programs and is easier for the casual user than making them
|
||||
# instantiate their own Random() instance.
|
||||
|
||||
_inst = Random()
|
||||
seed = _inst.seed
|
||||
random = _inst.random
|
||||
uniform = _inst.uniform
|
||||
triangular = _inst.triangular
|
||||
randint = _inst.randint
|
||||
choice = _inst.choice
|
||||
randrange = _inst.randrange
|
||||
sample = _inst.sample
|
||||
shuffle = _inst.shuffle
|
||||
choices = _inst.choices
|
||||
normalvariate = _inst.normalvariate
|
||||
lognormvariate = _inst.lognormvariate
|
||||
expovariate = _inst.expovariate
|
||||
vonmisesvariate = _inst.vonmisesvariate
|
||||
gammavariate = _inst.gammavariate
|
||||
gauss = _inst.gauss
|
||||
betavariate = _inst.betavariate
|
||||
paretovariate = _inst.paretovariate
|
||||
weibullvariate = _inst.weibullvariate
|
||||
getstate = _inst.getstate
|
||||
setstate = _inst.setstate
|
||||
getrandbits = _inst.getrandbits
|
||||
|
||||
if __name__ == '__main__':
|
||||
_test()
|
||||
9
Lib/tempfile.py
vendored
9
Lib/tempfile.py
vendored
@@ -42,8 +42,7 @@ import io as _io
|
||||
import os as _os
|
||||
import shutil as _shutil
|
||||
import errno as _errno
|
||||
# XXX RustPython TODO: _random
|
||||
#from random import Random as _Random
|
||||
from random import Random as _Random
|
||||
import weakref as _weakref
|
||||
|
||||
try:
|
||||
@@ -157,11 +156,7 @@ class _RandomNameSequence:
|
||||
|
||||
def __next__(self):
|
||||
c = self.characters
|
||||
def choose(s):
|
||||
import math, random
|
||||
return s[math.floor(random.random() * len(s))]
|
||||
# XXX RustPython TODO: proper random impl
|
||||
# choose = self.rng.choose
|
||||
choose = self.rng.choice
|
||||
letters = [choose(c) for dummy in range(8)]
|
||||
return ''.join(letters)
|
||||
|
||||
|
||||
@@ -7,15 +7,12 @@ jobs:
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
strategy:
|
||||
matrix:
|
||||
Python36:
|
||||
python.version: '3.6'
|
||||
maxParallel: 10
|
||||
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '$(python.version)'
|
||||
versionSpec: '3.7'
|
||||
architecture: 'x64'
|
||||
|
||||
- script: |
|
||||
|
||||
@@ -94,7 +94,7 @@ fn bench_rustpy_nbody(b: &mut test::Bencher) {
|
||||
|
||||
let vm = VirtualMachine::default();
|
||||
|
||||
let code = match vm.compile(source, compile::Mode::Single, "<stdin>".to_string()) {
|
||||
let code = match vm.compile(source, compile::Mode::Single, "<stdin>".to_owned()) {
|
||||
Ok(code) => code,
|
||||
Err(e) => panic!("{:?}", e),
|
||||
};
|
||||
@@ -113,7 +113,7 @@ fn bench_rustpy_mandelbrot(b: &mut test::Bencher) {
|
||||
|
||||
let vm = VirtualMachine::default();
|
||||
|
||||
let code = match vm.compile(source, compile::Mode::Single, "<stdin>".to_string()) {
|
||||
let code = match vm.compile(source, compile::Mode::Single, "<stdin>".to_owned()) {
|
||||
Ok(code) => code,
|
||||
Err(e) => panic!("{:?}", e),
|
||||
};
|
||||
|
||||
@@ -88,7 +88,7 @@ fn with_compiler(
|
||||
) -> Result<CodeObject, CompileError> {
|
||||
let mut compiler = Compiler::new(optimize);
|
||||
compiler.source_path = Some(source_path);
|
||||
compiler.push_new_code_object("<module>".to_string());
|
||||
compiler.push_new_code_object("<module>".to_owned());
|
||||
f(&mut compiler)?;
|
||||
let code = compiler.pop_code_object();
|
||||
trace!("Compilation completed: {:?}", code);
|
||||
@@ -290,7 +290,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
fn load_name(&mut self, name: &str) {
|
||||
let scope = self.scope_for_name(name);
|
||||
self.emit(Instruction::LoadName {
|
||||
name: name.to_string(),
|
||||
name: name.to_owned(),
|
||||
scope,
|
||||
});
|
||||
}
|
||||
@@ -298,7 +298,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
fn store_name(&mut self, name: &str) {
|
||||
let scope = self.scope_for_name(name);
|
||||
self.emit(Instruction::StoreName {
|
||||
name: name.to_string(),
|
||||
name: name.to_owned(),
|
||||
scope,
|
||||
});
|
||||
}
|
||||
@@ -359,7 +359,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
for name in names {
|
||||
// import symbol from module:
|
||||
self.emit(Instruction::ImportFrom {
|
||||
name: name.symbol.to_string(),
|
||||
name: name.symbol.to_owned(),
|
||||
});
|
||||
|
||||
// Store module under proper name:
|
||||
@@ -619,13 +619,13 @@ impl<O: OutputStream> Compiler<O> {
|
||||
match &expression.node {
|
||||
ast::ExpressionType::Identifier { name } => {
|
||||
self.emit(Instruction::DeleteName {
|
||||
name: name.to_string(),
|
||||
name: name.to_owned(),
|
||||
});
|
||||
}
|
||||
ast::ExpressionType::Attribute { value, name } => {
|
||||
self.compile_expression(value)?;
|
||||
self.emit(Instruction::DeleteAttr {
|
||||
name: name.to_string(),
|
||||
name: name.to_owned(),
|
||||
});
|
||||
}
|
||||
ast::ExpressionType::Subscript { a, b } => {
|
||||
@@ -701,7 +701,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
compile_varargs(&args.kwarg),
|
||||
self.source_path.clone().unwrap(),
|
||||
line_number,
|
||||
name.to_string(),
|
||||
name.to_owned(),
|
||||
));
|
||||
self.enter_scope();
|
||||
|
||||
@@ -897,7 +897,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
// key:
|
||||
self.emit(Instruction::LoadConst {
|
||||
value: bytecode::Constant::String {
|
||||
value: "return".to_string(),
|
||||
value: "return".to_owned(),
|
||||
},
|
||||
});
|
||||
// value:
|
||||
@@ -909,7 +909,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
if let Some(annotation) = &arg.annotation {
|
||||
self.emit(Instruction::LoadConst {
|
||||
value: bytecode::Constant::String {
|
||||
value: arg.arg.to_string(),
|
||||
value: arg.arg.to_owned(),
|
||||
},
|
||||
});
|
||||
self.compile_expression(&annotation)?;
|
||||
@@ -982,18 +982,18 @@ impl<O: OutputStream> Compiler<O> {
|
||||
Varargs::None,
|
||||
self.source_path.clone().unwrap(),
|
||||
line_number,
|
||||
name.to_string(),
|
||||
name.to_owned(),
|
||||
));
|
||||
self.enter_scope();
|
||||
|
||||
let (new_body, doc_str) = get_doc(body);
|
||||
|
||||
self.emit(Instruction::LoadName {
|
||||
name: "__name__".to_string(),
|
||||
name: "__name__".to_owned(),
|
||||
scope: bytecode::NameScope::Global,
|
||||
});
|
||||
self.emit(Instruction::StoreName {
|
||||
name: "__module__".to_string(),
|
||||
name: "__module__".to_owned(),
|
||||
scope: bytecode::NameScope::Free,
|
||||
});
|
||||
self.emit(Instruction::LoadConst {
|
||||
@@ -1002,7 +1002,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
},
|
||||
});
|
||||
self.emit(Instruction::StoreName {
|
||||
name: "__qualname__".to_string(),
|
||||
name: "__qualname__".to_owned(),
|
||||
scope: bytecode::NameScope::Free,
|
||||
});
|
||||
self.compile_statements(new_body)?;
|
||||
@@ -1022,7 +1022,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
});
|
||||
self.emit(Instruction::LoadConst {
|
||||
value: bytecode::Constant::String {
|
||||
value: name.to_string(),
|
||||
value: name.to_owned(),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1044,7 +1044,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
for keyword in keywords {
|
||||
if let Some(name) = &keyword.name {
|
||||
kwarg_names.push(bytecode::Constant::String {
|
||||
value: name.to_string(),
|
||||
value: name.to_owned(),
|
||||
});
|
||||
} else {
|
||||
// This means **kwargs!
|
||||
@@ -1090,7 +1090,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
|
||||
self.emit(Instruction::Rotate { amount: 2 });
|
||||
self.emit(Instruction::StoreAttr {
|
||||
name: "__doc__".to_string(),
|
||||
name: "__doc__".to_owned(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1171,7 +1171,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
self.set_label(check_asynciter_label);
|
||||
self.emit(Instruction::Duplicate);
|
||||
self.emit(Instruction::LoadName {
|
||||
name: "StopAsyncIteration".to_string(),
|
||||
name: "StopAsyncIteration".to_owned(),
|
||||
scope: bytecode::NameScope::Global,
|
||||
});
|
||||
self.emit(Instruction::CompareOperation {
|
||||
@@ -1308,7 +1308,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
});
|
||||
self.emit(Instruction::LoadConst {
|
||||
value: bytecode::Constant::String {
|
||||
value: name.to_string(),
|
||||
value: name.to_owned(),
|
||||
},
|
||||
});
|
||||
self.emit(Instruction::StoreSubscript);
|
||||
@@ -1332,7 +1332,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
ast::ExpressionType::Attribute { value, name } => {
|
||||
self.compile_expression(value)?;
|
||||
self.emit(Instruction::StoreAttr {
|
||||
name: name.to_string(),
|
||||
name: name.to_owned(),
|
||||
});
|
||||
}
|
||||
ast::ExpressionType::List { elements } | ast::ExpressionType::Tuple { elements } => {
|
||||
@@ -1605,7 +1605,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
Attribute { value, name } => {
|
||||
self.compile_expression(value)?;
|
||||
self.emit(Instruction::LoadAttr {
|
||||
name: name.to_string(),
|
||||
name: name.to_owned(),
|
||||
});
|
||||
}
|
||||
Compare { vals, ops } => {
|
||||
@@ -1732,7 +1732,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
func: FunctionContext::Function,
|
||||
};
|
||||
|
||||
let name = "<lambda>".to_string();
|
||||
let name = "<lambda>".to_owned();
|
||||
self.enter_function(&name, args)?;
|
||||
self.compile_expression(body)?;
|
||||
self.emit(Instruction::ReturnValue);
|
||||
@@ -1795,7 +1795,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
if let Some(name) = &keyword.name {
|
||||
self.emit(Instruction::LoadConst {
|
||||
value: bytecode::Constant::String {
|
||||
value: name.to_string(),
|
||||
value: name.to_owned(),
|
||||
},
|
||||
});
|
||||
self.compile_expression(&keyword.value)?;
|
||||
@@ -1858,7 +1858,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
for keyword in keywords {
|
||||
if let Some(name) = &keyword.name {
|
||||
kwarg_names.push(bytecode::Constant::String {
|
||||
value: name.to_string(),
|
||||
value: name.to_owned(),
|
||||
});
|
||||
} else {
|
||||
// This means **kwargs!
|
||||
@@ -1927,13 +1927,13 @@ impl<O: OutputStream> Compiler<O> {
|
||||
ast::ComprehensionKind::Set { .. } => "<setcomp>",
|
||||
ast::ComprehensionKind::Dict { .. } => "<dictcomp>",
|
||||
}
|
||||
.to_string();
|
||||
.to_owned();
|
||||
|
||||
let line_number = self.get_source_line_number();
|
||||
// Create magnificent function <listcomp>:
|
||||
self.push_output(CodeObject::new(
|
||||
Default::default(),
|
||||
vec![".0".to_string()],
|
||||
vec![".0".to_owned()],
|
||||
Varargs::None,
|
||||
vec![],
|
||||
Varargs::None,
|
||||
@@ -2099,7 +2099,7 @@ impl<O: OutputStream> Compiler<O> {
|
||||
ast::StringGroup::Constant { value } => {
|
||||
self.emit(Instruction::LoadConst {
|
||||
value: bytecode::Constant::String {
|
||||
value: value.to_string(),
|
||||
value: value.to_owned(),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -2264,9 +2264,9 @@ mod tests {
|
||||
|
||||
fn compile_exec(source: &str) -> CodeObject {
|
||||
let mut compiler: Compiler = Default::default();
|
||||
compiler.source_path = Some("source_path".to_string());
|
||||
compiler.push_new_code_object("<module>".to_string());
|
||||
let ast = parser::parse_program(&source.to_string()).unwrap();
|
||||
compiler.source_path = Some("source_path".to_owned());
|
||||
compiler.push_new_code_object("<module>".to_owned());
|
||||
let ast = parser::parse_program(source).unwrap();
|
||||
let symbol_scope = make_symbol_table(&ast).unwrap();
|
||||
compiler.compile_program(&ast, symbol_scope).unwrap();
|
||||
compiler.pop_code_object()
|
||||
|
||||
@@ -62,7 +62,7 @@ impl CompileError {
|
||||
match parse {
|
||||
ParseErrorType::Lexical(LexicalErrorType::IndentationError) => true,
|
||||
ParseErrorType::UnrecognizedToken(token, expected) => {
|
||||
*token == Tok::Indent || expected.clone() == Some("Indent".to_string())
|
||||
*token == Tok::Indent || expected.clone() == Some("Indent".to_owned())
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
@@ -88,14 +88,14 @@ impl fmt::Display for CompileError {
|
||||
let error_desc = match &self.error {
|
||||
CompileErrorType::Assign(target) => format!("can't assign to {}", target),
|
||||
CompileErrorType::Delete(target) => format!("can't delete {}", target),
|
||||
CompileErrorType::ExpectExpr => "Expecting expression, got statement".to_string(),
|
||||
CompileErrorType::ExpectExpr => "Expecting expression, got statement".to_owned(),
|
||||
CompileErrorType::Parse(err) => err.to_string(),
|
||||
CompileErrorType::SyntaxError(err) => err.to_string(),
|
||||
CompileErrorType::StarArgs => "Two starred expressions in assignment".to_string(),
|
||||
CompileErrorType::InvalidBreak => "'break' outside loop".to_string(),
|
||||
CompileErrorType::InvalidContinue => "'continue' outside loop".to_string(),
|
||||
CompileErrorType::InvalidReturn => "'return' outside function".to_string(),
|
||||
CompileErrorType::InvalidYield => "'yield' outside function".to_string(),
|
||||
CompileErrorType::StarArgs => "Two starred expressions in assignment".to_owned(),
|
||||
CompileErrorType::InvalidBreak => "'break' outside loop".to_owned(),
|
||||
CompileErrorType::InvalidContinue => "'continue' outside loop".to_owned(),
|
||||
CompileErrorType::InvalidReturn => "'return' outside function".to_owned(),
|
||||
CompileErrorType::InvalidYield => "'yield' outside function".to_owned(),
|
||||
};
|
||||
|
||||
if let Some(statement) = &self.statement {
|
||||
|
||||
@@ -105,7 +105,7 @@ pub struct Symbol {
|
||||
impl Symbol {
|
||||
fn new(name: &str) -> Self {
|
||||
Symbol {
|
||||
name: name.to_string(),
|
||||
name: name.to_owned(),
|
||||
// table,
|
||||
scope: SymbolScope::Unknown,
|
||||
is_param: false,
|
||||
@@ -304,7 +304,7 @@ impl SymbolTableBuilder {
|
||||
}
|
||||
|
||||
fn enter_scope(&mut self, name: &str, typ: SymbolTableType, line_number: usize) {
|
||||
let table = SymbolTable::new(name.to_string(), typ, line_number);
|
||||
let table = SymbolTable::new(name.to_owned(), typ, line_number);
|
||||
self.tables.push(table);
|
||||
}
|
||||
|
||||
@@ -793,7 +793,7 @@ impl SymbolTableBuilder {
|
||||
// Insert symbol when required:
|
||||
if !containing {
|
||||
let symbol = Symbol::new(name);
|
||||
table.symbols.insert(name.to_string(), symbol);
|
||||
table.symbols.insert(name.to_owned(), symbol);
|
||||
}
|
||||
|
||||
// Set proper flags on symbol:
|
||||
|
||||
@@ -128,7 +128,7 @@ impl CompilationSource {
|
||||
let module_name = if is_init {
|
||||
parent.clone()
|
||||
} else if parent.is_empty() {
|
||||
stem.to_string()
|
||||
stem.to_owned()
|
||||
} else {
|
||||
format!("{}.{}", parent, stem)
|
||||
};
|
||||
@@ -235,7 +235,7 @@ impl PyCompileInput {
|
||||
})?
|
||||
.compile(
|
||||
mode.unwrap_or(compile::Mode::Exec),
|
||||
module_name.unwrap_or_else(|| "frozen".to_string()),
|
||||
module_name.unwrap_or_else(|| "frozen".to_owned()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ impl Class {
|
||||
} else {
|
||||
Err(Diagnostic::span_error(
|
||||
span,
|
||||
"Duplicate #[py*] attribute on pyimpl".to_string(),
|
||||
"Duplicate #[py*] attribute on pyimpl".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -337,17 +337,16 @@ impl Class {
|
||||
};
|
||||
if name == "pymethod" {
|
||||
self.add_item(Self::extract_method(sig, meta)?, meta_span)?;
|
||||
attr_idxs.push(i);
|
||||
} else if name == "pyclassmethod" {
|
||||
self.add_item(Self::extract_classmethod(sig, meta)?, meta_span)?;
|
||||
attr_idxs.push(i);
|
||||
} else if name == "pyproperty" {
|
||||
self.add_item(Self::extract_property(sig, meta)?, meta_span)?;
|
||||
attr_idxs.push(i);
|
||||
} else if name == "pyslot" {
|
||||
self.add_item(Self::extract_slot(sig, meta)?, meta_span)?;
|
||||
attr_idxs.push(i);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
attr_idxs.push(i);
|
||||
}
|
||||
let mut i = 0;
|
||||
let mut attr_idxs = &*attr_idxs;
|
||||
@@ -406,8 +405,8 @@ fn extract_impl_items(mut items: Vec<ItemSig>) -> Result<TokenStream2, Diagnosti
|
||||
let properties = properties
|
||||
.into_iter()
|
||||
.map(|(name, prop)| {
|
||||
let getter = match prop.0 {
|
||||
Some(getter) => getter,
|
||||
let getter_func = match prop.0 {
|
||||
Some(func) => func,
|
||||
None => {
|
||||
push_err_span!(
|
||||
diagnostics,
|
||||
@@ -418,14 +417,17 @@ fn extract_impl_items(mut items: Vec<ItemSig>) -> Result<TokenStream2, Diagnosti
|
||||
return TokenStream2::new();
|
||||
}
|
||||
};
|
||||
let add_setter = prop.1.map(|setter| quote!(.add_setter(Self::#setter)));
|
||||
let (new, setter) = match prop.1 {
|
||||
Some(func) => (quote! { with_get_set }, quote! { , &Self::#func }),
|
||||
None => (quote! { with_get }, quote! { }),
|
||||
};
|
||||
let str_name = name.to_string();
|
||||
quote! {
|
||||
class.set_str_attr(
|
||||
#name,
|
||||
::rustpython_vm::obj::objproperty::PropertyBuilder::new(ctx)
|
||||
.add_getter(Self::#getter)
|
||||
#add_setter
|
||||
.create(),
|
||||
::rustpython_vm::pyobject::PyObject::new(
|
||||
::rustpython_vm::obj::objgetset::PyGetSet::#new(#str_name.into(), &Self::#getter_func #setter),
|
||||
ctx.getset_type(), None)
|
||||
);
|
||||
}
|
||||
})
|
||||
@@ -453,8 +455,13 @@ fn extract_impl_items(mut items: Vec<ItemSig>) -> Result<TokenStream2, Diagnosti
|
||||
slot_ident,
|
||||
item_ident,
|
||||
} => {
|
||||
let transform = if vec!["new", "call"].contains(&slot_ident.to_string().as_str()) {
|
||||
quote! { ::rustpython_vm::function::IntoPyNativeFunc::into_func }
|
||||
} else {
|
||||
quote! { Box::new }
|
||||
};
|
||||
let into_func = quote_spanned! {item_ident.span()=>
|
||||
::rustpython_vm::function::IntoPyNativeFunc::into_func(Self::#item_ident)
|
||||
#transform(Self::#item_ident)
|
||||
};
|
||||
Some(quote! {
|
||||
(*class.slots.borrow_mut()).#slot_ident = Some(#into_func);
|
||||
@@ -620,7 +627,7 @@ fn generate_class_def(
|
||||
let meta = attr.parse_meta().expect("expected doc attr to be a meta");
|
||||
if let Meta::NameValue(name_value) = meta {
|
||||
if let Lit::Str(s) = name_value.lit {
|
||||
let val = s.value().trim().to_string();
|
||||
let val = s.value().trim().to_owned();
|
||||
match doc {
|
||||
Some(ref mut doc) => doc.push(val),
|
||||
None => doc = Some(vec![val]),
|
||||
@@ -685,7 +692,8 @@ pub fn impl_pystruct_sequence(attr: AttributeArgs, item: Item) -> Result<TokenSt
|
||||
let property = quote! {
|
||||
class.set_str_attr(
|
||||
#field_name_str,
|
||||
ctx.new_property(
|
||||
ctx.new_readonly_getset(
|
||||
#field_name_str,
|
||||
|zelf: &::rustpython_vm::obj::objtuple::PyTuple,
|
||||
_vm: &::rustpython_vm::VirtualMachine| {
|
||||
zelf.fast_getitem(#idx)
|
||||
|
||||
@@ -10,7 +10,7 @@ fn main() -> vm::pyobject::PyResult<()> {
|
||||
.compile(
|
||||
r#"print("Hello World!")"#,
|
||||
compiler::compile::Mode::Exec,
|
||||
"<embedded>".to_string(),
|
||||
"<embedded>".to_owned(),
|
||||
)
|
||||
.map_err(|err| vm.new_syntax_error(&err))?;
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ fn main() -> vm::pyobject::PyResult<()> {
|
||||
.compile(
|
||||
&input,
|
||||
compiler::compile::Mode::Single,
|
||||
"<embedded>".to_string(),
|
||||
"<embedded>".to_owned(),
|
||||
)
|
||||
.map_err(|err| vm.new_syntax_error(&err))
|
||||
.and_then(|code_obj| vm.run_code_obj(code_obj, scope.clone()))
|
||||
|
||||
@@ -78,7 +78,7 @@ fn parse_python_file(filename: &Path) -> ParsedFile {
|
||||
match std::fs::read_to_string(filename) {
|
||||
Err(e) => ParsedFile {
|
||||
// filename: Box::new(filename.to_path_buf()),
|
||||
// code: "".to_string(),
|
||||
// code: "".to_owned(),
|
||||
num_lines: 0,
|
||||
result: Err(e.to_string()),
|
||||
},
|
||||
|
||||
@@ -191,7 +191,7 @@ impl fmt::Display for ParseErrorType {
|
||||
ParseErrorType::UnrecognizedToken(ref tok, ref expected) => {
|
||||
if *tok == Tok::Indent {
|
||||
write!(f, "unexpected indent")
|
||||
} else if expected.clone() == Some("Indent".to_string()) {
|
||||
} else if expected.clone() == Some("Indent".to_owned()) {
|
||||
write!(f, "expected an indented block")
|
||||
} else {
|
||||
write!(f, "Got unexpected token {}", tok)
|
||||
|
||||
@@ -83,7 +83,7 @@ impl<'a> FStringParser<'a> {
|
||||
}))
|
||||
} else {
|
||||
spec = Some(Box::new(Constant {
|
||||
value: spec_expression.to_string(),
|
||||
value: spec_expression.to_owned(),
|
||||
}))
|
||||
}
|
||||
}
|
||||
@@ -274,7 +274,7 @@ mod tests {
|
||||
value: Box::new(mk_ident("foo", 1, 1)),
|
||||
conversion: None,
|
||||
spec: Some(Box::new(Constant {
|
||||
value: "spec".to_string(),
|
||||
value: "spec".to_owned(),
|
||||
})),
|
||||
}
|
||||
);
|
||||
|
||||
@@ -303,7 +303,7 @@ where
|
||||
if self.chr0 == Some('.') {
|
||||
if self.chr1 == Some('_') {
|
||||
return Err(LexicalError {
|
||||
error: LexicalErrorType::OtherError("Invalid Syntax".to_string()),
|
||||
error: LexicalErrorType::OtherError("Invalid Syntax".to_owned()),
|
||||
location: self.get_pos(),
|
||||
});
|
||||
}
|
||||
@@ -352,7 +352,7 @@ where
|
||||
let value = value_text.parse::<BigInt>().unwrap();
|
||||
if start_is_zero && !value.is_zero() {
|
||||
return Err(LexicalError {
|
||||
error: LexicalErrorType::OtherError("Invalid Token".to_string()),
|
||||
error: LexicalErrorType::OtherError("Invalid Token".to_owned()),
|
||||
location: self.get_pos(),
|
||||
});
|
||||
}
|
||||
@@ -643,7 +643,7 @@ where
|
||||
// This is technically stricter than python3 but spaces after
|
||||
// tabs is even more insane than mixing spaces and tabs.
|
||||
return Some(Err(LexicalError {
|
||||
error: LexicalErrorType::OtherError("Spaces not allowed as part of indentation after tabs".to_string()),
|
||||
error: LexicalErrorType::OtherError("Spaces not allowed as part of indentation after tabs".to_owned()),
|
||||
location: self.get_pos(),
|
||||
}));
|
||||
}
|
||||
@@ -658,7 +658,7 @@ where
|
||||
// tabs is even more insane than mixing spaces and tabs.
|
||||
return Err(LexicalError {
|
||||
error: LexicalErrorType::OtherError(
|
||||
"Tabs not allowed as part of indentation after spaces".to_string(),
|
||||
"Tabs not allowed as part of indentation after spaces".to_owned(),
|
||||
),
|
||||
location: self.get_pos(),
|
||||
});
|
||||
@@ -1313,11 +1313,11 @@ mod tests {
|
||||
tokens,
|
||||
vec![
|
||||
Tok::String {
|
||||
value: "\\\\".to_string(),
|
||||
value: "\\\\".to_owned(),
|
||||
is_fstring: false,
|
||||
},
|
||||
Tok::String {
|
||||
value: "\\".to_string(),
|
||||
value: "\\".to_owned(),
|
||||
is_fstring: false,
|
||||
},
|
||||
Tok::Newline,
|
||||
|
||||
@@ -213,7 +213,7 @@ mod tests {
|
||||
function: Box::new(mk_ident("my_func", 1, 1)),
|
||||
args: vec![make_string("positional", 1, 10)],
|
||||
keywords: vec![ast::Keyword {
|
||||
name: Some("keyword".to_string()),
|
||||
name: Some("keyword".to_owned()),
|
||||
value: make_int(2, 1, 31),
|
||||
}],
|
||||
}
|
||||
|
||||
10
src/main.rs
10
src/main.rs
@@ -57,7 +57,7 @@ fn main() {
|
||||
1 => match_class!(match args.as_slice()[0].clone() {
|
||||
i @ PyInt => {
|
||||
use num_traits::cast::ToPrimitive;
|
||||
process::exit(i.as_bigint().to_i32().unwrap());
|
||||
process::exit(i.as_bigint().to_i32().unwrap_or(0));
|
||||
}
|
||||
arg => {
|
||||
if vm.is_none(&arg) {
|
||||
@@ -364,7 +364,7 @@ fn run_rustpython(vm: &VirtualMachine, matches: &ArgMatches) -> PyResult<()> {
|
||||
|
||||
// Figure out if a -c option was given:
|
||||
if let Some(command) = matches.value_of("c") {
|
||||
run_command(&vm, scope, command.to_string())?;
|
||||
run_command(&vm, scope, command.to_owned())?;
|
||||
} else if let Some(module) = matches.value_of("m") {
|
||||
run_module(&vm, module)?;
|
||||
} else if let Some(filename) = matches.value_of("script") {
|
||||
@@ -389,7 +389,7 @@ fn _run_string(vm: &VirtualMachine, scope: Scope, source: &str, source_path: Str
|
||||
|
||||
fn run_command(vm: &VirtualMachine, scope: Scope, source: String) -> PyResult<()> {
|
||||
debug!("Running command {}", source);
|
||||
_run_string(vm, scope, &source, "<stdin>".to_string())?;
|
||||
_run_string(vm, scope, &source, "<stdin>".to_owned())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -426,13 +426,13 @@ fn run_script(vm: &VirtualMachine, scope: Scope, script_file: &str) -> PyResult<
|
||||
process::exit(1);
|
||||
};
|
||||
|
||||
let dir = file_path.parent().unwrap().to_str().unwrap().to_string();
|
||||
let dir = file_path.parent().unwrap().to_str().unwrap().to_owned();
|
||||
let sys_path = vm.get_attribute(vm.sys_module.clone(), "path").unwrap();
|
||||
vm.call_method(&sys_path, "insert", vec![vm.new_int(0), vm.new_str(dir)])?;
|
||||
|
||||
match util::read_file(&file_path) {
|
||||
Ok(source) => {
|
||||
_run_string(vm, scope, &source, file_path.to_str().unwrap().to_string())?;
|
||||
_run_string(vm, scope, &source, file_path.to_str().unwrap().to_owned())?;
|
||||
}
|
||||
Err(err) => {
|
||||
error!(
|
||||
|
||||
@@ -21,7 +21,7 @@ enum ShellExecResult {
|
||||
}
|
||||
|
||||
fn shell_exec(vm: &VirtualMachine, source: &str, scope: Scope) -> ShellExecResult {
|
||||
match vm.compile(source, compile::Mode::Single, "<stdin>".to_string()) {
|
||||
match vm.compile(source, compile::Mode::Single, "<stdin>".to_owned()) {
|
||||
Ok(code) => {
|
||||
match vm.run_code_obj(code, scope.clone()) {
|
||||
Ok(value) => {
|
||||
|
||||
@@ -159,7 +159,7 @@ impl Completer for ShellHelper<'_> {
|
||||
.complete_opt(&line[0..pos])
|
||||
// as far as I can tell, there's no better way to do both completion
|
||||
// and indentation (or even just indentation)
|
||||
.unwrap_or_else(|| (line.len(), vec!["\t".to_string()])))
|
||||
.unwrap_or_else(|| (line.len(), vec!["\t".to_owned()])))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,3 +65,11 @@ try:
|
||||
raise NewException("test")
|
||||
except NewException as e:
|
||||
assert e.value == "test"
|
||||
|
||||
|
||||
exc = SyntaxError('msg', 1, 2, 3, 4, 5)
|
||||
assert exc.msg == 'msg'
|
||||
assert exc.filename is None
|
||||
assert exc.lineno is None
|
||||
assert exc.offset is None
|
||||
assert exc.text is None
|
||||
|
||||
29
tests/snippets/stdlib_random.py
Normal file
29
tests/snippets/stdlib_random.py
Normal file
@@ -0,0 +1,29 @@
|
||||
import random
|
||||
|
||||
random.seed(1234)
|
||||
|
||||
# random.randint
|
||||
assert random.randint(1, 11) == 8
|
||||
|
||||
# random.shuffle
|
||||
left = list(range(10))
|
||||
right = [2, 7, 3, 5, 8, 4, 6, 9, 0, 1]
|
||||
random.shuffle(left)
|
||||
assert left == right
|
||||
|
||||
# random.choice
|
||||
assert random.choice(left) == 5
|
||||
|
||||
# random.choices
|
||||
expected = ['red', 'green', 'red', 'black', 'black', 'red']
|
||||
result = random.choices(['red', 'black', 'green'], [18, 18, 2], k=6)
|
||||
assert expected == result
|
||||
|
||||
# random.sample
|
||||
sampled = [0, 2, 1]
|
||||
assert random.sample(list(range(3)), 3) == sampled
|
||||
|
||||
# TODO : random.random(), random.uniform(), random.triangular(),
|
||||
# random.betavariate, random.expovariate, random.gammavariate,
|
||||
# random.gauss, random.lognormvariate, random.normalvariate,
|
||||
# random.vonmisesvariate, random.paretovariate, random.weibullvariate
|
||||
@@ -86,3 +86,7 @@ class C(B, BB):
|
||||
pass
|
||||
|
||||
assert C.mro() == [C, B, A, BB, AA, object]
|
||||
|
||||
|
||||
assert type(Exception.args).__name__ == 'getset_descriptor'
|
||||
assert type(None).__bool__(None) is False
|
||||
|
||||
@@ -31,7 +31,7 @@ num-integer = "0.1.41"
|
||||
num-rational = "0.2.2"
|
||||
num-iter = "0.1.39"
|
||||
rand = "0.7"
|
||||
rand_distr = "0.2"
|
||||
rand_core = "0.5"
|
||||
getrandom = "0.1"
|
||||
log = "0.4"
|
||||
rustpython-derive = {path = "../derive", version = "0.1.1"}
|
||||
|
||||
@@ -87,7 +87,7 @@ pub fn to_ascii(value: &str) -> String {
|
||||
ascii
|
||||
}
|
||||
|
||||
fn builtin_bin(x: PyIntRef, _vm: &VirtualMachine) -> String {
|
||||
fn builtin_bin(x: PyIntRef) -> String {
|
||||
let x = x.as_bigint();
|
||||
if x.is_negative() {
|
||||
format!("-0b{:b}", x.abs())
|
||||
@@ -105,7 +105,7 @@ fn builtin_callable(obj: PyObjectRef, vm: &VirtualMachine) -> bool {
|
||||
fn builtin_chr(i: u32, vm: &VirtualMachine) -> PyResult<String> {
|
||||
match char::from_u32(i) {
|
||||
Some(value) => Ok(value.to_string()),
|
||||
None => Err(vm.new_value_error("chr() arg not in range(0x110000)".to_string())),
|
||||
None => Err(vm.new_value_error("chr() arg not in range(0x110000)".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ fn builtin_compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult {
|
||||
.parse::<compile::Mode>()
|
||||
.map_err(|err| vm.new_value_error(err.to_string()))?;
|
||||
|
||||
vm.compile(&source, mode, args.filename.as_str().to_string())
|
||||
vm.compile(&source, mode, args.filename.as_str().to_owned())
|
||||
.map(|o| o.into_object())
|
||||
.map_err(|err| vm.new_syntax_error(&err))
|
||||
}
|
||||
@@ -229,7 +229,7 @@ fn run_code(
|
||||
// Determine code object:
|
||||
let code_obj = match source {
|
||||
Either::A(string) => vm
|
||||
.compile(string.as_str(), mode, "<string>".to_string())
|
||||
.compile(string.as_str(), mode, "<string>".to_owned())
|
||||
.map_err(|err| vm.new_syntax_error(&err))?,
|
||||
Either::B(code_obj) => code_obj,
|
||||
};
|
||||
@@ -343,7 +343,7 @@ fn builtin_hex(number: PyIntRef, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.new_str(s))
|
||||
}
|
||||
|
||||
fn builtin_id(obj: PyObjectRef, _vm: &VirtualMachine) -> usize {
|
||||
fn builtin_id(obj: PyObjectRef) -> usize {
|
||||
obj.get_id()
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ fn builtin_len(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
|
||||
fn builtin_locals(vm: &VirtualMachine) -> PyDictRef {
|
||||
let locals = vm.get_locals();
|
||||
locals.copy(vm).into_ref(vm)
|
||||
locals.copy().into_ref(vm)
|
||||
}
|
||||
|
||||
fn builtin_max(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
@@ -400,14 +400,14 @@ fn builtin_max(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
std::cmp::Ordering::Equal => vm.extract_elements(&args.args[0])?,
|
||||
std::cmp::Ordering::Less => {
|
||||
// zero arguments means type error:
|
||||
return Err(vm.new_type_error("Expected 1 or more arguments".to_string()));
|
||||
return Err(vm.new_type_error("Expected 1 or more arguments".to_owned()));
|
||||
}
|
||||
};
|
||||
|
||||
if candidates.is_empty() {
|
||||
let default = args.get_optional_kwarg("default");
|
||||
return default
|
||||
.ok_or_else(|| vm.new_value_error("max() arg is an empty sequence".to_string()));
|
||||
.ok_or_else(|| vm.new_value_error("max() arg is an empty sequence".to_owned()));
|
||||
}
|
||||
|
||||
let key_func = args.get_optional_kwarg("key");
|
||||
@@ -446,14 +446,14 @@ fn builtin_min(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
std::cmp::Ordering::Equal => vm.extract_elements(&args.args[0])?,
|
||||
std::cmp::Ordering::Less => {
|
||||
// zero arguments means type error:
|
||||
return Err(vm.new_type_error("Expected 1 or more arguments".to_string()));
|
||||
return Err(vm.new_type_error("Expected 1 or more arguments".to_owned()));
|
||||
}
|
||||
};
|
||||
|
||||
if candidates.is_empty() {
|
||||
let default = args.get_optional_kwarg("default");
|
||||
return default
|
||||
.ok_or_else(|| vm.new_value_error("min() arg is an empty sequence".to_string()));
|
||||
.ok_or_else(|| vm.new_value_error("min() arg is an empty sequence".to_owned()));
|
||||
}
|
||||
|
||||
let key_func = args.get_optional_kwarg("key");
|
||||
@@ -540,7 +540,7 @@ fn builtin_ord(string: Either<PyByteInner, PyStringRef>, vm: &VirtualMachine) ->
|
||||
match string.chars().next() {
|
||||
Some(character) => Ok(character as u32),
|
||||
None => Err(vm.new_type_error(
|
||||
"ord() could not guess the integer representing this character".to_string(),
|
||||
"ord() could not guess the integer representing this character".to_owned(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
@@ -565,18 +565,18 @@ fn builtin_pow(
|
||||
&& objtype::isinstance(&y, &vm.ctx.int_type()))
|
||||
{
|
||||
return Err(vm.new_type_error(
|
||||
"pow() 3rd argument not allowed unless all arguments are integers".to_string(),
|
||||
"pow() 3rd argument not allowed unless all arguments are integers".to_owned(),
|
||||
));
|
||||
}
|
||||
let y = objint::get_value(&y);
|
||||
if y.sign() == Sign::Minus {
|
||||
return Err(vm.new_value_error(
|
||||
"pow() 2nd argument cannot be negative when 3rd argument specified".to_string(),
|
||||
"pow() 2nd argument cannot be negative when 3rd argument specified".to_owned(),
|
||||
));
|
||||
}
|
||||
let m = m.as_bigint();
|
||||
if m.is_zero() {
|
||||
return Err(vm.new_value_error("pow() 3rd argument cannot be 0".to_string()));
|
||||
return Err(vm.new_value_error("pow() 3rd argument cannot be 0".to_owned()));
|
||||
}
|
||||
let x = objint::get_value(&x);
|
||||
Ok(vm.new_int(x.modpow(&y, &m)))
|
||||
@@ -675,7 +675,7 @@ fn builtin_reversed(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
vm.invoke(&reversed_method?, PyFuncArgs::default())
|
||||
} else {
|
||||
vm.get_method_or_type_error(obj.clone(), "__getitem__", || {
|
||||
"argument to reversed() must be a sequence".to_string()
|
||||
"argument to reversed() must be a sequence".to_owned()
|
||||
})?;
|
||||
let len = vm.call_method(&obj.clone(), "__len__", PyFuncArgs::default())?;
|
||||
let obj_iterator = objiter::PySequenceIterator {
|
||||
@@ -920,7 +920,7 @@ pub fn builtin_build_class_(
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
let name = qualified_name.as_str().split('.').next_back().unwrap();
|
||||
let name_obj = vm.new_str(name.to_string());
|
||||
let name_obj = vm.new_str(name.to_owned());
|
||||
|
||||
let mut metaclass = if let Some(metaclass) = kwargs.pop_kwarg("metaclass") {
|
||||
PyClassRef::try_from_object(vm, metaclass)?
|
||||
|
||||
@@ -236,10 +236,10 @@ impl CFormatSpec {
|
||||
format!("{:.*}", precision, magnitude)
|
||||
}
|
||||
CFormatType::Float(CFloatType::Exponent(_)) => {
|
||||
return Err("Not yet implemented for %e and %E".to_string())
|
||||
return Err("Not yet implemented for %e and %E".to_owned())
|
||||
}
|
||||
CFormatType::Float(CFloatType::General(_)) => {
|
||||
return Err("Not yet implemented for %g and %G".to_string())
|
||||
return Err("Not yet implemented for %g and %G".to_owned())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
@@ -623,36 +623,36 @@ mod tests {
|
||||
"%10s"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_string("test".to_string()),
|
||||
" test".to_string()
|
||||
.format_string("test".to_owned()),
|
||||
" test".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"%-10s"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_string("test".to_string()),
|
||||
"test ".to_string()
|
||||
.format_string("test".to_owned()),
|
||||
"test ".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"%#10x"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(0x1337)),
|
||||
" 0x1337".to_string()
|
||||
" 0x1337".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"%-#10x"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(0x1337)),
|
||||
"0x1337 ".to_string()
|
||||
"0x1337 ".to_owned()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_key() {
|
||||
let expected = Ok(CFormatSpec {
|
||||
mapping_key: Some("amount".to_string()),
|
||||
mapping_key: Some("amount".to_owned()),
|
||||
format_type: CFormatType::Number(CNumberType::Decimal),
|
||||
format_char: 'd',
|
||||
chars_consumed: 10,
|
||||
@@ -663,7 +663,7 @@ mod tests {
|
||||
assert_eq!("%(amount)d".parse::<CFormatSpec>(), expected);
|
||||
|
||||
let expected = Ok(CFormatSpec {
|
||||
mapping_key: Some("m((u(((l((((ti))))p)))l))e".to_string()),
|
||||
mapping_key: Some("m((u(((l((((ti))))p)))l))e".to_owned()),
|
||||
format_type: CFormatType::Number(CNumberType::Decimal),
|
||||
format_char: 'd',
|
||||
chars_consumed: 30,
|
||||
@@ -725,7 +725,7 @@ mod tests {
|
||||
assert_eq!(parsed, expected);
|
||||
assert_eq!(
|
||||
parsed.unwrap().format_number(&BigInt::from(12)),
|
||||
"+12 ".to_string()
|
||||
"+12 ".to_owned()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -735,15 +735,15 @@ mod tests {
|
||||
"%5.4s"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_string("Hello, World!".to_string()),
|
||||
" Hell".to_string()
|
||||
.format_string("Hello, World!".to_owned()),
|
||||
" Hell".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"%-5.4s"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_string("Hello, World!".to_string()),
|
||||
"Hell ".to_string()
|
||||
.format_string("Hello, World!".to_owned()),
|
||||
"Hell ".to_owned()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -753,8 +753,8 @@ mod tests {
|
||||
"%.2s"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_string("❤❤❤❤❤❤❤❤".to_string()),
|
||||
"❤❤".to_string()
|
||||
.format_string("❤❤❤❤❤❤❤❤".to_owned()),
|
||||
"❤❤".to_owned()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -765,56 +765,56 @@ mod tests {
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(27)),
|
||||
"00027".to_string()
|
||||
"00027".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"%+05d"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(27)),
|
||||
"+0027".to_string()
|
||||
"+0027".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"%-d"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(-27)),
|
||||
"-27".to_string()
|
||||
"-27".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"% d"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(27)),
|
||||
" 27".to_string()
|
||||
" 27".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"% d"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(-27)),
|
||||
"-27".to_string()
|
||||
"-27".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"%08x"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(0x1337)),
|
||||
"00001337".to_string()
|
||||
"00001337".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"%#010x"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(0x1337)),
|
||||
"0x00001337".to_string()
|
||||
"0x00001337".to_owned()
|
||||
);
|
||||
assert_eq!(
|
||||
"%-#010x"
|
||||
.parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_number(&BigInt::from(0x1337)),
|
||||
"0x1337 ".to_string()
|
||||
"0x1337 ".to_owned()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -825,7 +825,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.format_float(f64::from(1.2345))
|
||||
.ok(),
|
||||
Some("1.234500".to_string())
|
||||
Some("1.234500".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
"%+f"
|
||||
@@ -833,7 +833,7 @@ mod tests {
|
||||
.unwrap()
|
||||
.format_float(f64::from(1.2345))
|
||||
.ok(),
|
||||
Some("+1.234500".to_string())
|
||||
Some("+1.234500".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
"% f"
|
||||
@@ -841,21 +841,21 @@ mod tests {
|
||||
.unwrap()
|
||||
.format_float(f64::from(1.2345))
|
||||
.ok(),
|
||||
Some(" 1.234500".to_string())
|
||||
Some(" 1.234500".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
"%f".parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_float(f64::from(-1.2345))
|
||||
.ok(),
|
||||
Some("-1.234500".to_string())
|
||||
Some("-1.234500".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
"%f".parse::<CFormatSpec>()
|
||||
.unwrap()
|
||||
.format_float(f64::from(1.2345678901))
|
||||
.ok(),
|
||||
Some("1.234568".to_string())
|
||||
Some("1.234568".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -864,7 +864,7 @@ mod tests {
|
||||
let fmt = "Hello, my name is %s and I'm %d years old";
|
||||
let expected = Ok(CFormatString {
|
||||
format_parts: vec![
|
||||
(0, CFormatPart::Literal("Hello, my name is ".to_string())),
|
||||
(0, CFormatPart::Literal("Hello, my name is ".to_owned())),
|
||||
(
|
||||
18,
|
||||
CFormatPart::Spec(CFormatSpec {
|
||||
@@ -877,7 +877,7 @@ mod tests {
|
||||
flags: CConversionFlags::empty(),
|
||||
}),
|
||||
),
|
||||
(20, CFormatPart::Literal(" and I'm ".to_string())),
|
||||
(20, CFormatPart::Literal(" and I'm ".to_owned())),
|
||||
(
|
||||
29,
|
||||
CFormatPart::Spec(CFormatSpec {
|
||||
@@ -890,7 +890,7 @@ mod tests {
|
||||
flags: CConversionFlags::empty(),
|
||||
}),
|
||||
),
|
||||
(31, CFormatPart::Literal(" years old".to_string())),
|
||||
(31, CFormatPart::Literal(" years old".to_owned())),
|
||||
],
|
||||
});
|
||||
let result = fmt.parse::<CFormatString>();
|
||||
|
||||
@@ -344,7 +344,7 @@ impl DictKey for &PyObjectRef {
|
||||
impl DictKey for &str {
|
||||
fn do_hash(self, _vm: &VirtualMachine) -> PyResult<HashValue> {
|
||||
// follow a similar route as the hashing of PyStringRef
|
||||
let raw_hash = pyhash::hash_value(&self.to_string()).to_bigint().unwrap();
|
||||
let raw_hash = pyhash::hash_value(&self.to_owned()).to_bigint().unwrap();
|
||||
let raw_hash = pyhash::hash_bigint(&raw_hash);
|
||||
let mut hasher = DefaultHasher::new();
|
||||
raw_hash.hash(&mut hasher);
|
||||
@@ -362,7 +362,7 @@ impl DictKey for &str {
|
||||
Ok(py_str_value.as_str() == self)
|
||||
} else {
|
||||
// Fall back to PyString implementation.
|
||||
let s = vm.new_str(self.to_string());
|
||||
let s = vm.new_str(self.to_owned());
|
||||
s.do_eq(vm, other_key)
|
||||
}
|
||||
}
|
||||
@@ -393,12 +393,12 @@ mod tests {
|
||||
assert_eq!(0, dict.len());
|
||||
|
||||
let key1 = vm.new_bool(true);
|
||||
let value1 = vm.new_str("abc".to_string());
|
||||
let value1 = vm.new_str("abc".to_owned());
|
||||
dict.insert(&vm, &key1, value1.clone()).unwrap();
|
||||
assert_eq!(1, dict.len());
|
||||
|
||||
let key2 = vm.new_str("x".to_string());
|
||||
let value2 = vm.new_str("def".to_string());
|
||||
let key2 = vm.new_str("x".to_owned());
|
||||
let value2 = vm.new_str("def".to_owned());
|
||||
dict.insert(&vm, &key2, value2.clone()).unwrap();
|
||||
assert_eq!(2, dict.len());
|
||||
|
||||
@@ -438,7 +438,7 @@ mod tests {
|
||||
fn check_hash_equivalence(text: &str) {
|
||||
let vm: VirtualMachine = Default::default();
|
||||
let value1 = text;
|
||||
let value2 = vm.new_str(value1.to_string());
|
||||
let value2 = vm.new_str(value1.to_owned());
|
||||
|
||||
let hash1 = value1.do_hash(&vm).expect("Hash should not fail.");
|
||||
let hash2 = value2.do_hash(&vm).expect("Hash should not fail.");
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::vm::VirtualMachine;
|
||||
use rustpython_compiler::compile;
|
||||
|
||||
pub fn eval(vm: &VirtualMachine, source: &str, scope: Scope, source_path: &str) -> PyResult {
|
||||
match vm.compile(source, compile::Mode::Eval, source_path.to_string()) {
|
||||
match vm.compile(source, compile::Mode::Eval, source_path.to_owned()) {
|
||||
Ok(bytecode) => {
|
||||
debug!("Code object: {:?}", bytecode);
|
||||
vm.run_code_obj(bytecode, scope)
|
||||
|
||||
@@ -67,8 +67,8 @@ impl PyBaseException {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pyproperty(name = "args")]
|
||||
fn get_args(&self, _vm: &VirtualMachine) -> PyTupleRef {
|
||||
#[pyproperty]
|
||||
pub fn args(&self) -> PyTupleRef {
|
||||
self.args.borrow().clone()
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ impl PyBaseException {
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__traceback__")]
|
||||
fn get_traceback(&self, _vm: &VirtualMachine) -> Option<PyTracebackRef> {
|
||||
pub fn traceback(&self) -> Option<PyTracebackRef> {
|
||||
self.traceback.borrow().clone()
|
||||
}
|
||||
|
||||
@@ -90,41 +90,37 @@ impl PyBaseException {
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__cause__")]
|
||||
fn get_cause(&self, _vm: &VirtualMachine) -> Option<PyBaseExceptionRef> {
|
||||
pub fn cause(&self) -> Option<PyBaseExceptionRef> {
|
||||
self.cause.borrow().clone()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__cause__", setter)]
|
||||
fn setter_cause(&self, cause: Option<PyBaseExceptionRef>, _vm: &VirtualMachine) {
|
||||
pub fn set_cause(&self, cause: Option<PyBaseExceptionRef>) {
|
||||
self.cause.replace(cause);
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__context__")]
|
||||
fn get_context(&self, _vm: &VirtualMachine) -> Option<PyBaseExceptionRef> {
|
||||
pub fn context(&self) -> Option<PyBaseExceptionRef> {
|
||||
self.context.borrow().clone()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__context__", setter)]
|
||||
fn setter_context(&self, context: Option<PyBaseExceptionRef>, _vm: &VirtualMachine) {
|
||||
pub fn set_context(&self, context: Option<PyBaseExceptionRef>) {
|
||||
self.context.replace(context);
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__suppress_context__")]
|
||||
fn get_suppress_context(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn get_suppress_context(&self) -> bool {
|
||||
self.suppress_context.get()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__suppress_context__", setter)]
|
||||
fn set_suppress_context(&self, suppress_context: bool, _vm: &VirtualMachine) {
|
||||
fn set_suppress_context(&self, suppress_context: bool) {
|
||||
self.suppress_context.set(suppress_context);
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn with_traceback(
|
||||
zelf: PyRef<Self>,
|
||||
tb: Option<PyTracebackRef>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
fn with_traceback(zelf: PyRef<Self>, tb: Option<PyTracebackRef>) -> PyResult {
|
||||
zelf.traceback.replace(tb);
|
||||
Ok(zelf.as_object().clone())
|
||||
}
|
||||
@@ -148,28 +144,6 @@ impl PyBaseException {
|
||||
Err(i) => format!("{}({})", cls.name, i.format(", ")),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn args(&self) -> PyTupleRef {
|
||||
self.args.borrow().clone()
|
||||
}
|
||||
|
||||
pub fn traceback(&self) -> Option<PyTracebackRef> {
|
||||
self.traceback.borrow().clone()
|
||||
}
|
||||
|
||||
pub fn cause(&self) -> Option<PyBaseExceptionRef> {
|
||||
self.cause.borrow().clone()
|
||||
}
|
||||
pub fn set_cause(&self, cause: Option<PyBaseExceptionRef>) {
|
||||
self.cause.replace(cause);
|
||||
}
|
||||
|
||||
pub fn context(&self) -> Option<PyBaseExceptionRef> {
|
||||
self.context.borrow().clone()
|
||||
}
|
||||
pub fn set_context(&self, context: Option<PyBaseExceptionRef>) {
|
||||
self.context.replace(context);
|
||||
}
|
||||
}
|
||||
|
||||
/// Print exception chain
|
||||
@@ -225,7 +199,7 @@ fn print_source_line<W: Write>(output: &mut W, filename: &str, lineno: usize) ->
|
||||
|
||||
/// Print exception occurrence location from traceback element
|
||||
fn write_traceback_entry<W: Write>(output: &mut W, tb_entry: &PyTracebackRef) -> io::Result<()> {
|
||||
let filename = tb_entry.frame.code.source_path.to_string();
|
||||
let filename = tb_entry.frame.code.source_path.to_owned();
|
||||
writeln!(
|
||||
output,
|
||||
r##" File "{}", line {}, in {}"##,
|
||||
@@ -347,7 +321,7 @@ impl ExceptionCtor {
|
||||
// both are instances; which would we choose?
|
||||
(Self::Instance(_exc_a), Some(_exc_b)) => {
|
||||
Err(vm
|
||||
.new_type_error("instance exception may not have a separate value".to_string()))
|
||||
.new_type_error("instance exception may not have a separate value".to_owned()))
|
||||
}
|
||||
// if the "type" is an instance and the value isn't, use the "type"
|
||||
(Self::Instance(exc), None) => Ok(exc),
|
||||
@@ -634,20 +608,21 @@ pub fn init(ctx: &PyContext) {
|
||||
PyBaseException::extend_class(ctx, &excs.base_exception_type);
|
||||
|
||||
extend_class!(ctx, &excs.syntax_error, {
|
||||
"msg" => ctx.new_property(make_arg_getter(0)),
|
||||
"filename" => ctx.new_property(make_arg_getter(1)),
|
||||
"lineno" => ctx.new_property(make_arg_getter(2)),
|
||||
"offset" => ctx.new_property(make_arg_getter(3)),
|
||||
"text" => ctx.new_property(make_arg_getter(4)),
|
||||
"msg" => ctx.new_readonly_getset("msg", make_arg_getter(0)),
|
||||
// TODO: members
|
||||
"filename" => ctx.none(),
|
||||
"lineno" => ctx.none(),
|
||||
"offset" => ctx.none(),
|
||||
"text" => ctx.none(),
|
||||
});
|
||||
|
||||
extend_class!(ctx, &excs.import_error, {
|
||||
"__init__" => ctx.new_method(import_error_init),
|
||||
"msg" => ctx.new_property(make_arg_getter(0)),
|
||||
"msg" => ctx.new_readonly_getset("msg", make_arg_getter(0)),
|
||||
});
|
||||
|
||||
extend_class!(ctx, &excs.stop_iteration, {
|
||||
"value" => ctx.new_property(make_arg_getter(0)),
|
||||
"value" => ctx.new_readonly_getset("value", make_arg_getter(0)),
|
||||
});
|
||||
|
||||
extend_class!(ctx, &excs.key_error, {
|
||||
@@ -655,27 +630,27 @@ pub fn init(ctx: &PyContext) {
|
||||
});
|
||||
|
||||
extend_class!(ctx, &excs.unicode_decode_error, {
|
||||
"encoding" => ctx.new_property(make_arg_getter(0)),
|
||||
"object" => ctx.new_property(make_arg_getter(1)),
|
||||
"start" => ctx.new_property(make_arg_getter(2)),
|
||||
"end" => ctx.new_property(make_arg_getter(3)),
|
||||
"reason" => ctx.new_property(make_arg_getter(4)),
|
||||
"encoding" => ctx.new_readonly_getset("encoding", make_arg_getter(0)),
|
||||
"object" => ctx.new_readonly_getset("object", make_arg_getter(1)),
|
||||
"start" => ctx.new_readonly_getset("start", make_arg_getter(2)),
|
||||
"end" => ctx.new_readonly_getset("end", make_arg_getter(3)),
|
||||
"reason" => ctx.new_readonly_getset("reason", make_arg_getter(4)),
|
||||
});
|
||||
|
||||
extend_class!(ctx, &excs.unicode_encode_error, {
|
||||
"encoding" => ctx.new_property(make_arg_getter(0)),
|
||||
"object" => ctx.new_property(make_arg_getter(1)),
|
||||
"start" => ctx.new_property(make_arg_getter(2)),
|
||||
"end" => ctx.new_property(make_arg_getter(3)),
|
||||
"reason" => ctx.new_property(make_arg_getter(4)),
|
||||
"encoding" => ctx.new_readonly_getset("encoding", make_arg_getter(0)),
|
||||
"object" => ctx.new_readonly_getset("object", make_arg_getter(1)),
|
||||
"start" => ctx.new_readonly_getset("start", make_arg_getter(2)),
|
||||
"end" => ctx.new_readonly_getset("end", make_arg_getter(3)),
|
||||
"reason" => ctx.new_readonly_getset("reason", make_arg_getter(4)),
|
||||
});
|
||||
|
||||
extend_class!(ctx, &excs.unicode_translate_error, {
|
||||
"encoding" => ctx.new_property(none_getter),
|
||||
"object" => ctx.new_property(make_arg_getter(0)),
|
||||
"start" => ctx.new_property(make_arg_getter(1)),
|
||||
"end" => ctx.new_property(make_arg_getter(2)),
|
||||
"reason" => ctx.new_property(make_arg_getter(3)),
|
||||
"encoding" => ctx.new_readonly_getset("encoding", none_getter),
|
||||
"object" => ctx.new_readonly_getset("object", make_arg_getter(0)),
|
||||
"start" => ctx.new_readonly_getset("start", make_arg_getter(1)),
|
||||
"end" => ctx.new_readonly_getset("end", make_arg_getter(2)),
|
||||
"reason" => ctx.new_readonly_getset("reason", make_arg_getter(3)),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -343,13 +343,13 @@ impl FormatSpec {
|
||||
let magnitude = num.abs();
|
||||
let raw_magnitude_string_result: Result<String, &'static str> = match self.format_type {
|
||||
Some(FormatType::FixedPointUpper) => match magnitude {
|
||||
magnitude if magnitude.is_nan() => Ok("NAN".to_string()),
|
||||
magnitude if magnitude.is_infinite() => Ok("INF".to_string()),
|
||||
magnitude if magnitude.is_nan() => Ok("NAN".to_owned()),
|
||||
magnitude if magnitude.is_infinite() => Ok("INF".to_owned()),
|
||||
_ => Ok(format!("{:.*}", precision, magnitude)),
|
||||
},
|
||||
Some(FormatType::FixedPointLower) => match magnitude {
|
||||
magnitude if magnitude.is_nan() => Ok("nan".to_string()),
|
||||
magnitude if magnitude.is_infinite() => Ok("inf".to_string()),
|
||||
magnitude if magnitude.is_nan() => Ok("nan".to_owned()),
|
||||
magnitude if magnitude.is_infinite() => Ok("inf".to_owned()),
|
||||
_ => Ok(format!("{:.*}", precision, magnitude)),
|
||||
},
|
||||
Some(FormatType::Decimal) => Err("Unknown format code 'd' for object of type 'float'"),
|
||||
@@ -377,14 +377,14 @@ impl FormatSpec {
|
||||
Err("Format code 'e' for object of type 'float' not implemented yet")
|
||||
}
|
||||
Some(FormatType::Percentage) => match magnitude {
|
||||
magnitude if magnitude.is_nan() => Ok("nan%".to_string()),
|
||||
magnitude if magnitude.is_infinite() => Ok("inf%".to_string()),
|
||||
magnitude if magnitude.is_nan() => Ok("nan%".to_owned()),
|
||||
magnitude if magnitude.is_infinite() => Ok("inf%".to_owned()),
|
||||
_ => Ok(format!("{:.*}%", precision, magnitude * 100.0)),
|
||||
},
|
||||
None => {
|
||||
match magnitude {
|
||||
magnitude if magnitude.is_nan() => Ok("nan".to_string()),
|
||||
magnitude if magnitude.is_infinite() => Ok("inf".to_string()),
|
||||
magnitude if magnitude.is_nan() => Ok("nan".to_owned()),
|
||||
magnitude if magnitude.is_infinite() => Ok("inf".to_owned()),
|
||||
// Using the Debug format here to prevent the automatic conversion of floats
|
||||
// ending in .0 to their integer representation (e.g., 1.0 -> 1)
|
||||
_ => Ok(format!("{:?}", magnitude)),
|
||||
@@ -614,7 +614,7 @@ impl FormatString {
|
||||
let arg_part = parts[0];
|
||||
|
||||
let format_spec = if parts.len() > 1 {
|
||||
parts[1].to_string()
|
||||
parts[1].to_owned()
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
@@ -625,7 +625,7 @@ impl FormatString {
|
||||
let arg_part = parts[0];
|
||||
|
||||
let preconversor_spec = if parts.len() > 1 {
|
||||
"!".to_string() + parts[1]
|
||||
"!".to_owned() + parts[1]
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
@@ -638,7 +638,7 @@ impl FormatString {
|
||||
if let Ok(index) = arg_part.parse::<usize>() {
|
||||
Ok(FormatPart::IndexSpec(index, format_spec))
|
||||
} else {
|
||||
Ok(FormatPart::KeywordSpec(arg_part.to_string(), format_spec))
|
||||
Ok(FormatPart::KeywordSpec(arg_part.to_owned(), format_spec))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,43 +766,43 @@ mod tests {
|
||||
parse_format_spec("d")
|
||||
.unwrap()
|
||||
.format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")),
|
||||
Ok("16".to_string())
|
||||
Ok("16".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
parse_format_spec("x")
|
||||
.unwrap()
|
||||
.format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")),
|
||||
Ok("10".to_string())
|
||||
Ok("10".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
parse_format_spec("b")
|
||||
.unwrap()
|
||||
.format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")),
|
||||
Ok("10000".to_string())
|
||||
Ok("10000".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
parse_format_spec("o")
|
||||
.unwrap()
|
||||
.format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")),
|
||||
Ok("20".to_string())
|
||||
Ok("20".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
parse_format_spec("+d")
|
||||
.unwrap()
|
||||
.format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")),
|
||||
Ok("+16".to_string())
|
||||
Ok("+16".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
parse_format_spec("^ 5d")
|
||||
.unwrap()
|
||||
.format_int(&BigInt::from_bytes_be(Sign::Minus, b"\x10")),
|
||||
Ok(" -16 ".to_string())
|
||||
Ok(" -16 ".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
parse_format_spec("0>+#10x")
|
||||
.unwrap()
|
||||
.format_int(&BigInt::from_bytes_be(Sign::Plus, b"\x10")),
|
||||
Ok("00000+0x10".to_string())
|
||||
Ok("00000+0x10".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -810,10 +810,10 @@ mod tests {
|
||||
fn test_format_parse() {
|
||||
let expected = Ok(FormatString {
|
||||
format_parts: vec![
|
||||
FormatPart::Literal("abcd".to_string()),
|
||||
FormatPart::Literal("abcd".to_owned()),
|
||||
FormatPart::IndexSpec(1, String::new()),
|
||||
FormatPart::Literal(":".to_string()),
|
||||
FormatPart::KeywordSpec("key".to_string(), String::new()),
|
||||
FormatPart::Literal(":".to_owned()),
|
||||
FormatPart::KeywordSpec("key".to_owned(), String::new()),
|
||||
],
|
||||
});
|
||||
|
||||
@@ -832,9 +832,9 @@ mod tests {
|
||||
fn test_format_parse_escape() {
|
||||
let expected = Ok(FormatString {
|
||||
format_parts: vec![
|
||||
FormatPart::Literal("{".to_string()),
|
||||
FormatPart::KeywordSpec("key".to_string(), String::new()),
|
||||
FormatPart::Literal("}ddfe".to_string()),
|
||||
FormatPart::Literal("{".to_owned()),
|
||||
FormatPart::KeywordSpec("key".to_owned(), String::new()),
|
||||
FormatPart::Literal("}ddfe".to_owned()),
|
||||
],
|
||||
});
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@ impl Frame {
|
||||
bytecode::Instruction::ListAppend { i } => {
|
||||
let list_obj = self.nth_value(*i);
|
||||
let item = self.pop_value();
|
||||
objlist::PyListRef::try_from_object(vm, list_obj)?.append(item, vm);
|
||||
objlist::PyListRef::try_from_object(vm, list_obj)?.append(item);
|
||||
Ok(None)
|
||||
}
|
||||
bytecode::Instruction::SetAdd { i } => {
|
||||
@@ -586,7 +586,7 @@ impl Frame {
|
||||
let value = self.pop_value();
|
||||
let elements = vm.extract_elements(&value)?;
|
||||
if elements.len() != *size {
|
||||
Err(vm.new_value_error("Wrong number of values to unpack".to_string()))
|
||||
Err(vm.new_value_error("Wrong number of values to unpack".to_owned()))
|
||||
} else {
|
||||
for element in elements.into_iter().rev() {
|
||||
self.push_value(element);
|
||||
@@ -985,7 +985,7 @@ impl Frame {
|
||||
None => {
|
||||
return Err(vm.new_exception_msg(
|
||||
vm.ctx.exceptions.runtime_error.clone(),
|
||||
"No active exception to reraise".to_string(),
|
||||
"No active exception to reraise".to_owned(),
|
||||
))
|
||||
}
|
||||
},
|
||||
@@ -1154,7 +1154,7 @@ impl Frame {
|
||||
.new_pyfunction(code_obj, scope, defaults, kw_only_defaults);
|
||||
|
||||
let name = qualified_name.as_str().split('.').next_back().unwrap();
|
||||
vm.set_attr(&func_obj, "__name__", vm.new_str(name.to_string()))?;
|
||||
vm.set_attr(&func_obj, "__name__", vm.new_str(name.to_owned()))?;
|
||||
vm.set_attr(&func_obj, "__qualname__", qualified_name)?;
|
||||
let module = self
|
||||
.scope
|
||||
@@ -1319,13 +1319,13 @@ impl Frame {
|
||||
fn store_attr(&self, vm: &VirtualMachine, attr_name: &str) -> FrameResult {
|
||||
let parent = self.pop_value();
|
||||
let value = self.pop_value();
|
||||
vm.set_attr(&parent, vm.new_str(attr_name.to_string()), value)?;
|
||||
vm.set_attr(&parent, vm.new_str(attr_name.to_owned()), value)?;
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn delete_attr(&self, vm: &VirtualMachine, attr_name: &str) -> FrameResult {
|
||||
let parent = self.pop_value();
|
||||
let name = vm.ctx.new_str(attr_name.to_string());
|
||||
let name = vm.ctx.new_str(attr_name.to_owned());
|
||||
vm.del_attr(&parent, name)?;
|
||||
Ok(None)
|
||||
}
|
||||
@@ -1390,7 +1390,7 @@ impl fmt::Debug for Frame {
|
||||
.iter()
|
||||
.map(|elem| {
|
||||
if elem.payload.as_any().is::<Frame>() {
|
||||
"\n > {frame}".to_string()
|
||||
"\n > {frame}".to_owned()
|
||||
} else {
|
||||
format!("\n > {:?}", elem)
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ pub fn import_codeobj(
|
||||
set_file_attr: bool,
|
||||
) -> PyResult {
|
||||
let attrs = vm.ctx.new_dict();
|
||||
attrs.set_item("__name__", vm.new_str(module_name.to_string()), vm)?;
|
||||
attrs.set_item("__name__", vm.new_str(module_name.to_owned()), vm)?;
|
||||
if set_file_attr {
|
||||
attrs.set_item("__file__", vm.new_str(code_obj.source_path.to_owned()), vm)?;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ pub mod objfloat;
|
||||
pub mod objframe;
|
||||
pub mod objfunction;
|
||||
pub mod objgenerator;
|
||||
pub mod objgetset;
|
||||
pub mod objint;
|
||||
pub mod objiter;
|
||||
pub mod objlist;
|
||||
|
||||
@@ -58,7 +58,7 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
|
||||
let len_val = int_obj.as_bigint();
|
||||
if len_val.sign() == Sign::Minus {
|
||||
return Err(
|
||||
vm.new_value_error("__len__() should return >= 0".to_string())
|
||||
vm.new_value_error("__len__() should return >= 0".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ The class bool is a subclass of the class int, and cannot be subclassed.";
|
||||
"__rand__" => context.new_method(bool_and),
|
||||
"__xor__" => context.new_method(bool_xor),
|
||||
"__rxor__" => context.new_method(bool_xor),
|
||||
"__doc__" => context.new_str(bool_doc.to_string()),
|
||||
"__doc__" => context.new_str(bool_doc.to_owned()),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -118,11 +118,11 @@ pub fn get_py_int(obj: &PyObjectRef) -> &PyInt {
|
||||
&obj.payload::<PyInt>().unwrap()
|
||||
}
|
||||
|
||||
fn bool_repr(obj: bool, _vm: &VirtualMachine) -> String {
|
||||
fn bool_repr(obj: bool) -> String {
|
||||
if obj {
|
||||
"True".to_string()
|
||||
"True".to_owned()
|
||||
} else {
|
||||
"False".to_string()
|
||||
"False".to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ fn bool_format(
|
||||
if format_spec.as_str().is_empty() {
|
||||
vm.to_str(&obj)
|
||||
} else {
|
||||
Err(vm.new_type_error("unsupported format string passed to bool.__format__".to_string()))
|
||||
Err(vm.new_type_error("unsupported format string passed to bool.__format__".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@ use std::fmt;
|
||||
use crate::function::{OptionalArg, PyFuncArgs, PyNativeFunc};
|
||||
use crate::obj::objtype::PyClassRef;
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
|
||||
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol,
|
||||
};
|
||||
use crate::slots::{PyBuiltinCallable, PyBuiltinDescriptor};
|
||||
use crate::slots::{SlotCall, SlotDescriptor};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass]
|
||||
@@ -35,13 +35,13 @@ impl PyBuiltinFunction {
|
||||
}
|
||||
}
|
||||
|
||||
impl PyBuiltinCallable for PyBuiltinFunction {
|
||||
impl SlotCall for PyBuiltinFunction {
|
||||
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
(self.value)(vm, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinCallable))]
|
||||
#[pyimpl(with(SlotCall))]
|
||||
impl PyBuiltinFunction {}
|
||||
|
||||
#[pyclass]
|
||||
@@ -73,13 +73,17 @@ impl PyBuiltinMethod {
|
||||
}
|
||||
}
|
||||
|
||||
impl PyBuiltinDescriptor for PyBuiltinMethod {
|
||||
fn get(
|
||||
zelf: PyRef<Self>,
|
||||
obj: PyObjectRef,
|
||||
cls: OptionalArg<PyObjectRef>,
|
||||
impl SlotDescriptor for PyBuiltinMethod {
|
||||
fn descr_get(
|
||||
vm: &VirtualMachine,
|
||||
zelf: PyObjectRef,
|
||||
obj: Option<PyObjectRef>,
|
||||
cls: OptionalArg<PyObjectRef>,
|
||||
) -> PyResult {
|
||||
let (zelf, obj) = match Self::_check(zelf, obj, vm) {
|
||||
Ok(obj) => obj,
|
||||
Err(result) => return result,
|
||||
};
|
||||
if obj.is(&vm.get_none()) && !Self::_cls_is(&cls, &obj.class()) {
|
||||
Ok(zelf.into_object())
|
||||
} else {
|
||||
@@ -88,13 +92,13 @@ impl PyBuiltinDescriptor for PyBuiltinMethod {
|
||||
}
|
||||
}
|
||||
|
||||
impl PyBuiltinCallable for PyBuiltinMethod {
|
||||
impl SlotCall for PyBuiltinMethod {
|
||||
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
(self.function.value)(vm, args)
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinDescriptor, PyBuiltinCallable))]
|
||||
#[pyimpl(with(SlotDescriptor, SlotCall))]
|
||||
impl PyBuiltinMethod {}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
|
||||
@@ -99,17 +99,17 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(&self, _vm: &VirtualMachine) -> PyResult<String> {
|
||||
fn repr(&self) -> PyResult<String> {
|
||||
Ok(format!("bytearray(b'{}')", self.inner.borrow().repr()?))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(&self) -> usize {
|
||||
self.inner.borrow().len()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn sizeof(&self) -> usize {
|
||||
size_of::<Self>() + self.inner.borrow().len() * size_of::<u8>()
|
||||
}
|
||||
|
||||
@@ -140,11 +140,11 @@ impl PyByteArray {
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
fn hash(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Err(vm.new_type_error("unhashable type: bytearray".to_string()))
|
||||
Err(vm.new_type_error("unhashable type: bytearray".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyByteArrayIterator {
|
||||
fn iter(zelf: PyRef<Self>) -> PyByteArrayIterator {
|
||||
PyByteArrayIterator {
|
||||
position: Cell::new(0),
|
||||
bytearray: zelf,
|
||||
@@ -190,67 +190,67 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "isalnum")]
|
||||
fn isalnum(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isalnum(&self) -> bool {
|
||||
self.inner.borrow().isalnum()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isalpha")]
|
||||
fn isalpha(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isalpha(&self) -> bool {
|
||||
self.inner.borrow().isalpha()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isascii")]
|
||||
fn isascii(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isascii(&self) -> bool {
|
||||
self.inner.borrow().isascii()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isdigit")]
|
||||
fn isdigit(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isdigit(&self) -> bool {
|
||||
self.inner.borrow().isdigit()
|
||||
}
|
||||
|
||||
#[pymethod(name = "islower")]
|
||||
fn islower(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn islower(&self) -> bool {
|
||||
self.inner.borrow().islower()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isspace")]
|
||||
fn isspace(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isspace(&self) -> bool {
|
||||
self.inner.borrow().isspace()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isupper")]
|
||||
fn isupper(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isupper(&self) -> bool {
|
||||
self.inner.borrow().isupper()
|
||||
}
|
||||
|
||||
#[pymethod(name = "istitle")]
|
||||
fn istitle(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn istitle(&self) -> bool {
|
||||
self.inner.borrow().istitle()
|
||||
}
|
||||
|
||||
#[pymethod(name = "lower")]
|
||||
fn lower(&self, _vm: &VirtualMachine) -> PyByteArray {
|
||||
fn lower(&self) -> PyByteArray {
|
||||
self.inner.borrow().lower().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "upper")]
|
||||
fn upper(&self, _vm: &VirtualMachine) -> PyByteArray {
|
||||
fn upper(&self) -> PyByteArray {
|
||||
self.inner.borrow().upper().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "capitalize")]
|
||||
fn capitalize(&self, _vm: &VirtualMachine) -> PyByteArray {
|
||||
fn capitalize(&self) -> PyByteArray {
|
||||
self.inner.borrow().capitalize().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "swapcase")]
|
||||
fn swapcase(&self, _vm: &VirtualMachine) -> PyByteArray {
|
||||
fn swapcase(&self) -> PyByteArray {
|
||||
self.inner.borrow().swapcase().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "hex")]
|
||||
fn hex(&self, _vm: &VirtualMachine) -> String {
|
||||
fn hex(&self) -> String {
|
||||
self.inner.borrow().hex()
|
||||
}
|
||||
|
||||
@@ -331,7 +331,7 @@ impl PyByteArray {
|
||||
fn index(&self, options: ByteInnerFindOptions, vm: &VirtualMachine) -> PyResult<isize> {
|
||||
let res = self.inner.borrow().find(options, false, vm)?;
|
||||
if res == -1 {
|
||||
return Err(vm.new_value_error("substring not found".to_string()));
|
||||
return Err(vm.new_value_error("substring not found".to_owned()));
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
@@ -345,7 +345,7 @@ impl PyByteArray {
|
||||
fn rindex(&self, options: ByteInnerFindOptions, vm: &VirtualMachine) -> PyResult<isize> {
|
||||
let res = self.inner.borrow().find(options, true, vm)?;
|
||||
if res == -1 {
|
||||
return Err(vm.new_value_error("substring not found".to_string()));
|
||||
return Err(vm.new_value_error("substring not found".to_owned()));
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
@@ -358,7 +358,7 @@ impl PyByteArray {
|
||||
let pos = bytes
|
||||
.iter()
|
||||
.position(|b| *b == x)
|
||||
.ok_or_else(|| vm.new_value_error("value not found in bytearray".to_string()))?;
|
||||
.ok_or_else(|| vm.new_value_error("value not found in bytearray".to_owned()))?;
|
||||
|
||||
bytes.remove(pos);
|
||||
|
||||
@@ -375,11 +375,7 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "strip")]
|
||||
fn strip(
|
||||
&self,
|
||||
chars: OptionalArg<PyByteInner>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult<PyByteArray> {
|
||||
fn strip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyByteArray> {
|
||||
Ok(self
|
||||
.inner
|
||||
.borrow()
|
||||
@@ -388,11 +384,7 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "lstrip")]
|
||||
fn lstrip(
|
||||
&self,
|
||||
chars: OptionalArg<PyByteInner>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult<PyByteArray> {
|
||||
fn lstrip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyByteArray> {
|
||||
Ok(self
|
||||
.inner
|
||||
.borrow()
|
||||
@@ -401,11 +393,7 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "rstrip")]
|
||||
fn rstrip(
|
||||
&self,
|
||||
chars: OptionalArg<PyByteInner>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult<PyByteArray> {
|
||||
fn rstrip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyByteArray> {
|
||||
Ok(self
|
||||
.inner
|
||||
.borrow()
|
||||
@@ -460,7 +448,7 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "expandtabs")]
|
||||
fn expandtabs(&self, options: ByteInnerExpandtabsOptions, _vm: &VirtualMachine) -> PyByteArray {
|
||||
fn expandtabs(&self, options: ByteInnerExpandtabsOptions) -> PyByteArray {
|
||||
self.inner.borrow().expandtabs(options).into()
|
||||
}
|
||||
|
||||
@@ -477,7 +465,7 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "zfill")]
|
||||
fn zfill(&self, width: PyIntRef, _vm: &VirtualMachine) -> PyByteArray {
|
||||
fn zfill(&self, width: PyIntRef) -> PyByteArray {
|
||||
self.inner.borrow().zfill(width).into()
|
||||
}
|
||||
|
||||
@@ -487,18 +475,17 @@ impl PyByteArray {
|
||||
old: PyByteInner,
|
||||
new: PyByteInner,
|
||||
count: OptionalArg<PyIntRef>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult<PyByteArray> {
|
||||
Ok(self.inner.borrow().replace(old, new, count)?.into())
|
||||
}
|
||||
|
||||
#[pymethod(name = "clear")]
|
||||
fn clear(&self, _vm: &VirtualMachine) {
|
||||
fn clear(&self) {
|
||||
self.inner.borrow_mut().elements.clear();
|
||||
}
|
||||
|
||||
#[pymethod(name = "copy")]
|
||||
fn copy(&self, _vm: &VirtualMachine) -> PyByteArray {
|
||||
fn copy(&self) -> PyByteArray {
|
||||
self.inner.borrow().elements.clone().into()
|
||||
}
|
||||
|
||||
@@ -529,7 +516,7 @@ impl PyByteArray {
|
||||
fn insert(&self, mut index: isize, x: PyIntRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let bytes = &mut self.inner.borrow_mut().elements;
|
||||
let len = isize::try_from(bytes.len())
|
||||
.map_err(|_e| vm.new_overflow_error("bytearray too big".to_string()))?;
|
||||
.map_err(|_e| vm.new_overflow_error("bytearray too big".to_owned()))?;
|
||||
|
||||
let x = x.as_bigint().byte_or(vm)?;
|
||||
|
||||
@@ -544,7 +531,7 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
let index = usize::try_from(index)
|
||||
.map_err(|_e| vm.new_overflow_error("overflow in index calculation".to_string()))?;
|
||||
.map_err(|_e| vm.new_overflow_error("overflow in index calculation".to_owned()))?;
|
||||
|
||||
bytes.insert(index, x);
|
||||
|
||||
@@ -556,26 +543,26 @@ impl PyByteArray {
|
||||
let bytes = &mut self.inner.borrow_mut().elements;
|
||||
bytes
|
||||
.pop()
|
||||
.ok_or_else(|| vm.new_index_error("pop from empty bytearray".to_string()))
|
||||
.ok_or_else(|| vm.new_index_error("pop from empty bytearray".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "title")]
|
||||
fn title(&self, _vm: &VirtualMachine) -> PyByteArray {
|
||||
fn title(&self) -> PyByteArray {
|
||||
self.inner.borrow().title().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mul__")]
|
||||
fn repeat(&self, n: isize, _vm: &VirtualMachine) -> PyByteArray {
|
||||
fn repeat(&self, n: isize) -> PyByteArray {
|
||||
self.inner.borrow().repeat(n).into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmul__")]
|
||||
fn rmul(&self, n: isize, vm: &VirtualMachine) -> PyByteArray {
|
||||
self.repeat(n, vm)
|
||||
fn rmul(&self, n: isize) -> PyByteArray {
|
||||
self.repeat(n)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__imul__")]
|
||||
fn irepeat(&self, n: isize, _vm: &VirtualMachine) {
|
||||
fn irepeat(&self, n: isize) {
|
||||
self.inner.borrow_mut().irepeat(n)
|
||||
}
|
||||
|
||||
@@ -603,7 +590,7 @@ impl PyByteArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "reverse")]
|
||||
fn reverse(&self, _vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn reverse(&self) -> PyResult<()> {
|
||||
self.inner.borrow_mut().elements.reverse();
|
||||
Ok(())
|
||||
}
|
||||
@@ -640,7 +627,7 @@ impl PyByteArrayIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,10 +67,10 @@ impl ByteInnerNewOptions {
|
||||
elements: bytes.get_value().to_vec(),
|
||||
})
|
||||
} else {
|
||||
Err(vm.new_type_error("encoding without a string argument".to_string()))
|
||||
Err(vm.new_type_error("encoding without a string argument".to_owned()))
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_type_error("encoding without a string argument".to_string()))
|
||||
Err(vm.new_type_error("encoding without a string argument".to_owned()))
|
||||
}
|
||||
// Only one argument
|
||||
} else {
|
||||
@@ -79,12 +79,12 @@ impl ByteInnerNewOptions {
|
||||
i @ PyInt => {
|
||||
let size = objint::get_value(&i.into_object())
|
||||
.to_usize()
|
||||
.ok_or_else(|| vm.new_value_error("negative count".to_string()))?;
|
||||
.ok_or_else(|| vm.new_value_error("negative count".to_owned()))?;
|
||||
Ok(vec![0; size])
|
||||
}
|
||||
_l @ PyString => {
|
||||
return Err(
|
||||
vm.new_type_error("string argument without an encoding".to_string())
|
||||
vm.new_type_error("string argument without an encoding".to_owned())
|
||||
);
|
||||
}
|
||||
i @ PyBytes => Ok(i.get_value().to_vec()),
|
||||
@@ -108,9 +108,9 @@ impl ByteInnerNewOptions {
|
||||
if let Some(i) = v.to_u8() {
|
||||
data_bytes.push(i);
|
||||
} else {
|
||||
return Err(vm.new_value_error(
|
||||
"bytes must be in range(0, 256)".to_string(),
|
||||
));
|
||||
return Err(
|
||||
vm.new_value_error("bytes must be in range(0, 256)".to_owned())
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(data_bytes)
|
||||
@@ -230,7 +230,7 @@ impl ByteInnerTranslateOptions {
|
||||
|
||||
if table.len() != 256 {
|
||||
return Err(
|
||||
vm.new_value_error("translation table must be 256 characters long".to_string())
|
||||
vm.new_value_error("translation table must be 256 characters long".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -395,7 +395,7 @@ impl PyByteInner {
|
||||
if let Some(idx) = self.elements.get_pos(int) {
|
||||
Ok(vm.new_int(self.elements[idx]))
|
||||
} else {
|
||||
Err(vm.new_index_error("index out of range".to_string()))
|
||||
Err(vm.new_index_error("index out of range".to_owned()))
|
||||
}
|
||||
}
|
||||
Either::B(slice) => Ok(vm
|
||||
@@ -411,16 +411,16 @@ impl PyByteInner {
|
||||
if let Some(value) = i.as_bigint().to_u8() {
|
||||
Ok(value)
|
||||
} else {
|
||||
Err(vm.new_value_error("byte must be in range(0, 256)".to_string()))
|
||||
Err(vm.new_value_error("byte must be in range(0, 256)".to_owned()))
|
||||
}
|
||||
}
|
||||
_ => Err(vm.new_type_error("an integer is required".to_string())),
|
||||
_ => Err(vm.new_type_error("an integer is required".to_owned())),
|
||||
});
|
||||
let value = result?;
|
||||
self.elements[idx] = value;
|
||||
Ok(vm.new_int(value))
|
||||
} else {
|
||||
Err(vm.new_index_error("index out of range".to_string()))
|
||||
Err(vm.new_index_error("index out of range".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -442,7 +442,7 @@ impl PyByteInner {
|
||||
i @ PyMemoryView => Ok(i.try_value().unwrap()),
|
||||
_ => Err(vm.new_index_error(
|
||||
"can assign only bytes, buffers, or iterables of ints in range(0, 256)"
|
||||
.to_string()
|
||||
.to_owned()
|
||||
)),
|
||||
}),
|
||||
};
|
||||
@@ -479,7 +479,7 @@ impl PyByteInner {
|
||||
self.elements.remove(idx);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(vm.new_index_error("index out of range".to_string()))
|
||||
Err(vm.new_index_error("index out of range".to_owned()))
|
||||
}
|
||||
}
|
||||
Either::B(slice) => self.delslice(slice, vm),
|
||||
@@ -493,7 +493,7 @@ impl PyByteInner {
|
||||
let step = slice.step_index(vm)?.unwrap_or_else(BigInt::one);
|
||||
|
||||
if step.is_zero() {
|
||||
Err(vm.new_value_error("slice step cannot be zero".to_string()))
|
||||
Err(vm.new_value_error("slice step cannot be zero".to_owned()))
|
||||
} else if step.is_positive() {
|
||||
let range = self.elements.get_slice_range(&start, &stop);
|
||||
if range.start < range.end {
|
||||
@@ -1215,7 +1215,7 @@ pub trait ByteOr: ToPrimitive {
|
||||
fn byte_or(&self, vm: &VirtualMachine) -> PyResult<u8> {
|
||||
match self.to_u8() {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(vm.new_value_error("byte must be in range(0, 256)".to_string())),
|
||||
None => Err(vm.new_value_error("byte must be in range(0, 256)".to_owned())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
|
||||
@@ -135,12 +135,12 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
fn hash(&self, _vm: &VirtualMachine) -> pyhash::PyHash {
|
||||
fn hash(&self) -> pyhash::PyHash {
|
||||
self.inner.hash()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyBytesIterator {
|
||||
fn iter(zelf: PyRef<Self>) -> PyBytesIterator {
|
||||
PyBytesIterator {
|
||||
position: Cell::new(0),
|
||||
bytes: zelf,
|
||||
@@ -148,7 +148,7 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self, _vm: &VirtualMachine) -> PyResult<usize> {
|
||||
fn sizeof(&self) -> PyResult<usize> {
|
||||
Ok(size_of::<Self>() + self.inner.elements.len() * size_of::<u8>())
|
||||
}
|
||||
|
||||
@@ -176,67 +176,67 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "isalnum")]
|
||||
fn isalnum(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isalnum(&self) -> bool {
|
||||
self.inner.isalnum()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isalpha")]
|
||||
fn isalpha(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isalpha(&self) -> bool {
|
||||
self.inner.isalpha()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isascii")]
|
||||
fn isascii(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isascii(&self) -> bool {
|
||||
self.inner.isascii()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isdigit")]
|
||||
fn isdigit(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isdigit(&self) -> bool {
|
||||
self.inner.isdigit()
|
||||
}
|
||||
|
||||
#[pymethod(name = "islower")]
|
||||
fn islower(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn islower(&self) -> bool {
|
||||
self.inner.islower()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isspace")]
|
||||
fn isspace(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isspace(&self) -> bool {
|
||||
self.inner.isspace()
|
||||
}
|
||||
|
||||
#[pymethod(name = "isupper")]
|
||||
fn isupper(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isupper(&self) -> bool {
|
||||
self.inner.isupper()
|
||||
}
|
||||
|
||||
#[pymethod(name = "istitle")]
|
||||
fn istitle(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn istitle(&self) -> bool {
|
||||
self.inner.istitle()
|
||||
}
|
||||
|
||||
#[pymethod(name = "lower")]
|
||||
fn lower(&self, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn lower(&self) -> PyBytes {
|
||||
self.inner.lower().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "upper")]
|
||||
fn upper(&self, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn upper(&self) -> PyBytes {
|
||||
self.inner.upper().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "capitalize")]
|
||||
fn capitalize(&self, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn capitalize(&self) -> PyBytes {
|
||||
self.inner.capitalize().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "swapcase")]
|
||||
fn swapcase(&self, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn swapcase(&self) -> PyBytes {
|
||||
self.inner.swapcase().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "hex")]
|
||||
fn hex(&self, _vm: &VirtualMachine) -> String {
|
||||
fn hex(&self) -> String {
|
||||
self.inner.hex()
|
||||
}
|
||||
|
||||
@@ -301,7 +301,7 @@ impl PyBytes {
|
||||
fn index(&self, options: ByteInnerFindOptions, vm: &VirtualMachine) -> PyResult<isize> {
|
||||
let res = self.inner.find(options, false, vm)?;
|
||||
if res == -1 {
|
||||
return Err(vm.new_value_error("substring not found".to_string()));
|
||||
return Err(vm.new_value_error("substring not found".to_owned()));
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
@@ -315,7 +315,7 @@ impl PyBytes {
|
||||
fn rindex(&self, options: ByteInnerFindOptions, vm: &VirtualMachine) -> PyResult<isize> {
|
||||
let res = self.inner.find(options, true, vm)?;
|
||||
if res == -1 {
|
||||
return Err(vm.new_value_error("substring not found".to_string()));
|
||||
return Err(vm.new_value_error("substring not found".to_owned()));
|
||||
}
|
||||
Ok(res)
|
||||
}
|
||||
@@ -330,17 +330,17 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "strip")]
|
||||
fn strip(&self, chars: OptionalArg<PyByteInner>, _vm: &VirtualMachine) -> PyResult<PyBytes> {
|
||||
fn strip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyBytes> {
|
||||
Ok(self.inner.strip(chars, ByteInnerPosition::All)?.into())
|
||||
}
|
||||
|
||||
#[pymethod(name = "lstrip")]
|
||||
fn lstrip(&self, chars: OptionalArg<PyByteInner>, _vm: &VirtualMachine) -> PyResult<PyBytes> {
|
||||
fn lstrip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyBytes> {
|
||||
Ok(self.inner.strip(chars, ByteInnerPosition::Left)?.into())
|
||||
}
|
||||
|
||||
#[pymethod(name = "rstrip")]
|
||||
fn rstrip(&self, chars: OptionalArg<PyByteInner>, _vm: &VirtualMachine) -> PyResult<PyBytes> {
|
||||
fn rstrip(&self, chars: OptionalArg<PyByteInner>) -> PyResult<PyBytes> {
|
||||
Ok(self.inner.strip(chars, ByteInnerPosition::Right)?.into())
|
||||
}
|
||||
|
||||
@@ -386,7 +386,7 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "expandtabs")]
|
||||
fn expandtabs(&self, options: ByteInnerExpandtabsOptions, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn expandtabs(&self, options: ByteInnerExpandtabsOptions) -> PyBytes {
|
||||
self.inner.expandtabs(options).into()
|
||||
}
|
||||
|
||||
@@ -402,7 +402,7 @@ impl PyBytes {
|
||||
}
|
||||
|
||||
#[pymethod(name = "zfill")]
|
||||
fn zfill(&self, width: PyIntRef, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn zfill(&self, width: PyIntRef) -> PyBytes {
|
||||
self.inner.zfill(width).into()
|
||||
}
|
||||
|
||||
@@ -412,24 +412,23 @@ impl PyBytes {
|
||||
old: PyByteInner,
|
||||
new: PyByteInner,
|
||||
count: OptionalArg<PyIntRef>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult<PyBytes> {
|
||||
Ok(self.inner.replace(old, new, count)?.into())
|
||||
}
|
||||
|
||||
#[pymethod(name = "title")]
|
||||
fn title(&self, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn title(&self) -> PyBytes {
|
||||
self.inner.title().into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mul__")]
|
||||
fn repeat(&self, n: isize, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn repeat(&self, n: isize) -> PyBytes {
|
||||
self.inner.repeat(n).into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmul__")]
|
||||
fn rmul(&self, n: isize, vm: &VirtualMachine) -> PyBytes {
|
||||
self.repeat(n, vm)
|
||||
fn rmul(&self, n: isize) -> PyBytes {
|
||||
self.repeat(n)
|
||||
}
|
||||
|
||||
fn do_cformat(
|
||||
@@ -512,7 +511,7 @@ impl PyBytesIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::function::OptionalArg;
|
||||
use crate::pyobject::{
|
||||
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
|
||||
};
|
||||
use crate::slots::PyBuiltinDescriptor;
|
||||
use crate::slots::SlotDescriptor;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
/// classmethod(function) -> method
|
||||
@@ -47,19 +47,20 @@ impl PyValue for PyClassMethod {
|
||||
}
|
||||
}
|
||||
|
||||
impl PyBuiltinDescriptor for PyClassMethod {
|
||||
fn get(
|
||||
zelf: PyRef<Self>,
|
||||
obj: PyObjectRef,
|
||||
cls: OptionalArg<PyObjectRef>,
|
||||
impl SlotDescriptor for PyClassMethod {
|
||||
fn descr_get(
|
||||
vm: &VirtualMachine,
|
||||
zelf: PyObjectRef,
|
||||
obj: Option<PyObjectRef>,
|
||||
cls: OptionalArg<PyObjectRef>,
|
||||
) -> PyResult {
|
||||
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
|
||||
let cls = cls.unwrap_or_else(|| obj.class().into_object());
|
||||
Ok(vm.ctx.new_bound_method(zelf.callable.clone(), cls))
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinDescriptor), flags(BASETYPE))]
|
||||
#[pyimpl(with(SlotDescriptor), flags(BASETYPE))]
|
||||
impl PyClassMethod {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
@@ -74,7 +75,7 @@ impl PyClassMethod {
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__func__")]
|
||||
fn func(&self, _vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn func(&self) -> PyObjectRef {
|
||||
self.callable.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +44,10 @@ impl PyValue for PyCode {
|
||||
impl PyCodeRef {
|
||||
#[allow(clippy::new_ret_no_self)]
|
||||
fn new(_cls: PyClassRef, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("Cannot directly create code object".to_string()))
|
||||
Err(vm.new_type_error("Cannot directly create code object".to_owned()))
|
||||
}
|
||||
|
||||
fn repr(self, _vm: &VirtualMachine) -> String {
|
||||
fn repr(self) -> String {
|
||||
let code = &self.code;
|
||||
format!(
|
||||
"<code object {} at 0x{:x} file {:?}, line {}>",
|
||||
@@ -58,19 +58,19 @@ impl PyCodeRef {
|
||||
)
|
||||
}
|
||||
|
||||
fn co_argcount(self, _vm: &VirtualMachine) -> usize {
|
||||
fn co_argcount(self) -> usize {
|
||||
self.code.arg_names.len()
|
||||
}
|
||||
|
||||
fn co_filename(self, _vm: &VirtualMachine) -> String {
|
||||
fn co_filename(self) -> String {
|
||||
self.code.source_path.clone()
|
||||
}
|
||||
|
||||
fn co_firstlineno(self, _vm: &VirtualMachine) -> usize {
|
||||
fn co_firstlineno(self) -> usize {
|
||||
self.code.first_line_number
|
||||
}
|
||||
|
||||
fn co_kwonlyargcount(self, _vm: &VirtualMachine) -> usize {
|
||||
fn co_kwonlyargcount(self) -> usize {
|
||||
self.code.kwonlyarg_names.len()
|
||||
}
|
||||
|
||||
@@ -83,26 +83,26 @@ impl PyCodeRef {
|
||||
vm.ctx.new_tuple(consts)
|
||||
}
|
||||
|
||||
fn co_name(self, _vm: &VirtualMachine) -> String {
|
||||
fn co_name(self) -> String {
|
||||
self.code.obj_name.clone()
|
||||
}
|
||||
|
||||
fn co_flags(self, _vm: &VirtualMachine) -> u8 {
|
||||
fn co_flags(self) -> u8 {
|
||||
self.code.flags.bits()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
extend_class!(context, &context.types.code_type, {
|
||||
pub fn init(ctx: &PyContext) {
|
||||
extend_class!(ctx, &ctx.types.code_type, {
|
||||
(slot new) => PyCodeRef::new,
|
||||
"__repr__" => context.new_method(PyCodeRef::repr),
|
||||
"__repr__" => ctx.new_method(PyCodeRef::repr),
|
||||
|
||||
"co_argcount" => context.new_property(PyCodeRef::co_argcount),
|
||||
"co_consts" => context.new_property(PyCodeRef::co_consts),
|
||||
"co_filename" => context.new_property(PyCodeRef::co_filename),
|
||||
"co_firstlineno" => context.new_property(PyCodeRef::co_firstlineno),
|
||||
"co_kwonlyargcount" => context.new_property(PyCodeRef::co_kwonlyargcount),
|
||||
"co_name" => context.new_property(PyCodeRef::co_name),
|
||||
"co_flags" => context.new_property(PyCodeRef::co_flags),
|
||||
"co_argcount" => ctx.new_readonly_getset("co_argcount", PyCodeRef::co_argcount),
|
||||
"co_consts" => ctx.new_readonly_getset("co_consts", PyCodeRef::co_consts),
|
||||
"co_filename" => ctx.new_readonly_getset("co_filename", PyCodeRef::co_filename),
|
||||
"co_firstlineno" => ctx.new_readonly_getset("co_firstlineno", PyCodeRef::co_firstlineno),
|
||||
"co_kwonlyargcount" => ctx.new_readonly_getset("co_kwonlyargcount", PyCodeRef::co_kwonlyargcount),
|
||||
"co_name" => ctx.new_readonly_getset("co_name", PyCodeRef::co_name),
|
||||
"co_flags" => ctx.new_readonly_getset("co_flags", PyCodeRef::co_flags),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -57,17 +57,17 @@ fn try_complex(value: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<Comp
|
||||
#[pyimpl(flags(BASETYPE))]
|
||||
impl PyComplex {
|
||||
#[pyproperty(name = "real")]
|
||||
fn real(&self, _vm: &VirtualMachine) -> f64 {
|
||||
fn real(&self) -> f64 {
|
||||
self.value.re
|
||||
}
|
||||
|
||||
#[pyproperty(name = "imag")]
|
||||
fn imag(&self, _vm: &VirtualMachine) -> f64 {
|
||||
fn imag(&self) -> f64 {
|
||||
self.value.im
|
||||
}
|
||||
|
||||
#[pymethod(name = "__abs__")]
|
||||
fn abs(&self, _vm: &VirtualMachine) -> f64 {
|
||||
fn abs(&self) -> f64 {
|
||||
let Complex64 { im, re } = self.value;
|
||||
re.hypot(im)
|
||||
}
|
||||
@@ -104,7 +104,7 @@ impl PyComplex {
|
||||
}
|
||||
|
||||
#[pymethod(name = "conjugate")]
|
||||
fn conjugate(&self, _vm: &VirtualMachine) -> Complex64 {
|
||||
fn conjugate(&self) -> Complex64 {
|
||||
self.value.conj()
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ impl PyComplex {
|
||||
|
||||
#[pymethod(name = "__mod__")]
|
||||
fn mod_(&self, _other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("can't mod complex numbers.".to_string()))
|
||||
Err(vm.new_type_error("can't mod complex numbers.".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmod__")]
|
||||
@@ -165,7 +165,7 @@ impl PyComplex {
|
||||
|
||||
#[pymethod(name = "__floordiv__")]
|
||||
fn floordiv(&self, _other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("can't take floor of complex number.".to_string()))
|
||||
Err(vm.new_type_error("can't take floor of complex number.".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rfloordiv__")]
|
||||
@@ -175,7 +175,7 @@ impl PyComplex {
|
||||
|
||||
#[pymethod(name = "__divmod__")]
|
||||
fn divmod(&self, _other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
Err(vm.new_type_error("can't take floor or mod of complex number.".to_string()))
|
||||
Err(vm.new_type_error("can't take floor or mod of complex number.".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rdivmod__")]
|
||||
@@ -184,12 +184,12 @@ impl PyComplex {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__neg__")]
|
||||
fn neg(&self, _vm: &VirtualMachine) -> Complex64 {
|
||||
fn neg(&self) -> Complex64 {
|
||||
-self.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(&self, _vm: &VirtualMachine) -> String {
|
||||
fn repr(&self) -> String {
|
||||
let Complex64 { re, im } = self.value;
|
||||
if re == 0.0 {
|
||||
format!("{}j", im)
|
||||
@@ -209,7 +209,7 @@ impl PyComplex {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn bool(&self) -> bool {
|
||||
!Complex64::is_zero(&self.value)
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ impl PyComplex {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
fn hash(&self, _vm: &VirtualMachine) -> pyhash::PyHash {
|
||||
fn hash(&self) -> pyhash::PyHash {
|
||||
let re_hash = pyhash::hash_float(self.value.re);
|
||||
let im_hash = pyhash::hash_float(self.value.im);
|
||||
let ret = Wrapping(re_hash) + Wrapping(im_hash) * Wrapping(pyhash::IMAG);
|
||||
|
||||
@@ -91,7 +91,7 @@ impl PyCoroutine {
|
||||
match result {
|
||||
Ok(ExecutionResult::Yield(_)) => Err(vm.new_exception_msg(
|
||||
vm.ctx.exceptions.runtime_error.clone(),
|
||||
"generator ignored GeneratorExit".to_string(),
|
||||
"generator ignored GeneratorExit".to_owned(),
|
||||
)),
|
||||
Err(e) => {
|
||||
if isinstance(&e, &vm.ctx.exceptions.generator_exit) {
|
||||
@@ -105,7 +105,7 @@ impl PyCoroutine {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__await__")]
|
||||
fn r#await(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyCoroutineWrapper {
|
||||
fn r#await(zelf: PyRef<Self>) -> PyCoroutineWrapper {
|
||||
PyCoroutineWrapper { coro: zelf }
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@ impl PyValue for PyCoroutineWrapper {
|
||||
#[pyimpl]
|
||||
impl PyCoroutineWrapper {
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ impl PyDictRef {
|
||||
let iter = objiter::get_iter(vm, &dict_obj)?;
|
||||
loop {
|
||||
fn err(vm: &VirtualMachine) -> PyBaseExceptionRef {
|
||||
vm.new_type_error("Iterator must have exactly two elements".to_string())
|
||||
vm.new_type_error("Iterator must have exactly two elements".to_owned())
|
||||
}
|
||||
let element = match objiter::get_next_object(vm, &iter)? {
|
||||
Some(obj) => obj,
|
||||
@@ -121,7 +121,7 @@ impl PyDictRef {
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn bool(self, _vm: &VirtualMachine) -> bool {
|
||||
fn bool(self) -> bool {
|
||||
!self.entries.borrow().is_empty()
|
||||
}
|
||||
|
||||
@@ -168,12 +168,12 @@ impl PyDictRef {
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn len(self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(self) -> usize {
|
||||
self.entries.borrow().len()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn sizeof(self, _vm: &VirtualMachine) -> usize {
|
||||
fn sizeof(self) -> usize {
|
||||
size_of::<Self>() + self.entries.borrow().sizeof()
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ impl PyDictRef {
|
||||
|
||||
format!("{{{}}}", str_parts.join(", "))
|
||||
} else {
|
||||
"{...}".to_string()
|
||||
"{...}".to_owned()
|
||||
};
|
||||
Ok(s)
|
||||
}
|
||||
@@ -205,27 +205,27 @@ impl PyDictRef {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn clear(self, _vm: &VirtualMachine) {
|
||||
fn clear(self) {
|
||||
self.entries.borrow_mut().clear()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn iter(self, _vm: &VirtualMachine) -> PyDictKeyIterator {
|
||||
fn iter(self) -> PyDictKeyIterator {
|
||||
PyDictKeyIterator::new(self)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn keys(self, _vm: &VirtualMachine) -> PyDictKeys {
|
||||
fn keys(self) -> PyDictKeys {
|
||||
PyDictKeys::new(self)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn values(self, _vm: &VirtualMachine) -> PyDictValues {
|
||||
fn values(self) -> PyDictValues {
|
||||
PyDictValues::new(self)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn items(self, _vm: &VirtualMachine) -> PyDictItems {
|
||||
fn items(self) -> PyDictItems {
|
||||
PyDictItems::new(self)
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ impl PyDictRef {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
pub fn copy(self, _vm: &VirtualMachine) -> PyDict {
|
||||
pub fn copy(self) -> PyDict {
|
||||
PyDict {
|
||||
entries: self.entries.clone(),
|
||||
}
|
||||
@@ -343,7 +343,7 @@ impl PyDictRef {
|
||||
if let Some((key, value)) = entries.pop_front() {
|
||||
Ok(vm.ctx.new_tuple(vec![key, value]))
|
||||
} else {
|
||||
let err_msg = vm.new_str("popitem(): dictionary is empty".to_string());
|
||||
let err_msg = vm.new_str("popitem(): dictionary is empty".to_owned());
|
||||
Err(vm.new_key_error(err_msg))
|
||||
}
|
||||
}
|
||||
@@ -371,7 +371,7 @@ impl PyDictRef {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn hash(self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Err(vm.new_type_error("unhashable type".to_string()))
|
||||
Err(vm.new_type_error("unhashable type".to_owned()))
|
||||
}
|
||||
|
||||
pub fn contains_key<T: IntoPyObject>(&self, key: T, vm: &VirtualMachine) -> bool {
|
||||
@@ -508,13 +508,13 @@ macro_rules! dict_iterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(&self, _vm: &VirtualMachine) -> $iter_name {
|
||||
fn iter(&self) -> $iter_name {
|
||||
$iter_name::new(self.dict.clone())
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, vm: &VirtualMachine) -> usize {
|
||||
self.dict.clone().len(vm)
|
||||
fn len(&self) -> usize {
|
||||
self.dict.clone().len()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
@@ -524,11 +524,11 @@ macro_rules! dict_iterator {
|
||||
let mut str_parts = vec![];
|
||||
for (key, value) in zelf.dict.clone() {
|
||||
let s = vm.to_repr(&$result_fn(vm, &key, &value))?;
|
||||
str_parts.push(s.as_str().to_string());
|
||||
str_parts.push(s.as_str().to_owned());
|
||||
}
|
||||
format!("{}([{}])", $class_name, str_parts.join(", "))
|
||||
} else {
|
||||
"{...}".to_string()
|
||||
"{...}".to_owned()
|
||||
};
|
||||
Ok(s)
|
||||
}
|
||||
@@ -566,7 +566,7 @@ macro_rules! dict_iterator {
|
||||
if dict.has_changed_size(&self.size) {
|
||||
return Err(vm.new_exception_msg(
|
||||
vm.ctx.exceptions.runtime_error.clone(),
|
||||
"dictionary changed size during iteration".to_string(),
|
||||
"dictionary changed size during iteration".to_owned(),
|
||||
));
|
||||
}
|
||||
match dict.next_entry(&mut position) {
|
||||
@@ -579,12 +579,12 @@ macro_rules! dict_iterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__length_hint__")]
|
||||
fn length_hint(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn length_hint(&self) -> usize {
|
||||
self.dict
|
||||
.entries
|
||||
.borrow()
|
||||
|
||||
@@ -21,10 +21,10 @@ fn ellipsis_new(cls: PyClassRef, vm: &VirtualMachine) -> PyResult {
|
||||
}
|
||||
}
|
||||
|
||||
fn ellipsis_repr(_self: PyEllipsisRef, _vm: &VirtualMachine) -> String {
|
||||
"Ellipsis".to_string()
|
||||
fn ellipsis_repr(_self: PyEllipsisRef) -> String {
|
||||
"Ellipsis".to_owned()
|
||||
}
|
||||
|
||||
fn ellipsis_reduce(_self: PyEllipsisRef, _vm: &VirtualMachine) -> String {
|
||||
"Ellipsis".to_string()
|
||||
fn ellipsis_reduce(_self: PyEllipsisRef) -> String {
|
||||
"Ellipsis".to_owned()
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ impl PyEnumerate {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ impl PyFilter {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ fn inner_div(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
if v2 != 0.0 {
|
||||
Ok(v1 / v2)
|
||||
} else {
|
||||
Err(vm.new_zero_division_error("float division by zero".to_string()))
|
||||
Err(vm.new_zero_division_error("float division by zero".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ fn inner_mod(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
if v2 != 0.0 {
|
||||
Ok(v1 % v2)
|
||||
} else {
|
||||
Err(vm.new_zero_division_error("float mod by zero".to_string()))
|
||||
Err(vm.new_zero_division_error("float mod by zero".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,11 +98,11 @@ pub fn try_bigint(value: f64, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
None => {
|
||||
if value.is_infinite() {
|
||||
Err(vm.new_overflow_error(
|
||||
"OverflowError: cannot convert float infinity to integer".to_string(),
|
||||
"OverflowError: cannot convert float infinity to integer".to_owned(),
|
||||
))
|
||||
} else if value.is_nan() {
|
||||
Err(vm
|
||||
.new_value_error("ValueError: cannot convert float NaN to integer".to_string()))
|
||||
.new_value_error("ValueError: cannot convert float NaN to integer".to_owned()))
|
||||
} else {
|
||||
// unreachable unless BigInt has a bug
|
||||
unreachable!(
|
||||
@@ -118,7 +118,7 @@ fn inner_floordiv(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
if v2 != 0.0 {
|
||||
Ok((v1 / v2).floor())
|
||||
} else {
|
||||
Err(vm.new_zero_division_error("float floordiv by zero".to_string()))
|
||||
Err(vm.new_zero_division_error("float floordiv by zero".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ fn inner_divmod(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult<(f64, f64)> {
|
||||
if v2 != 0.0 {
|
||||
Ok(((v1 / v2).floor(), v1 % v2))
|
||||
} else {
|
||||
Err(vm.new_zero_division_error("float divmod()".to_string()))
|
||||
Err(vm.new_zero_division_error("float divmod()".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,7 +273,7 @@ impl PyFloat {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__abs__")]
|
||||
fn abs(&self, _vm: &VirtualMachine) -> f64 {
|
||||
fn abs(&self) -> f64 {
|
||||
self.value.abs()
|
||||
}
|
||||
|
||||
@@ -315,7 +315,7 @@ impl PyFloat {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn bool(&self) -> bool {
|
||||
self.value != 0.0
|
||||
}
|
||||
|
||||
@@ -350,12 +350,12 @@ impl PyFloat {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__pos__")]
|
||||
fn pos(&self, _vm: &VirtualMachine) -> f64 {
|
||||
fn pos(&self) -> f64 {
|
||||
self.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__neg__")]
|
||||
fn neg(&self, _vm: &VirtualMachine) -> f64 {
|
||||
fn neg(&self) -> f64 {
|
||||
-self.value
|
||||
}
|
||||
|
||||
@@ -380,14 +380,14 @@ impl PyFloat {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(&self, vm: &VirtualMachine) -> String {
|
||||
fn repr(&self) -> String {
|
||||
let value = format!("{:e}", self.value);
|
||||
if let Some(position) = value.find('e') {
|
||||
let significand = &value[..position];
|
||||
let exponent = &value[position + 1..];
|
||||
let exponent = exponent.parse::<i32>().unwrap();
|
||||
if exponent < 16 && exponent > -5 {
|
||||
if self.is_integer(vm) {
|
||||
if self.is_integer() {
|
||||
format!("{:.1?}", self.value)
|
||||
} else {
|
||||
self.value.to_string()
|
||||
@@ -489,32 +489,32 @@ impl PyFloat {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__float__")]
|
||||
fn float(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyFloatRef {
|
||||
fn float(zelf: PyRef<Self>) -> PyFloatRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
fn hash(&self, _vm: &VirtualMachine) -> pyhash::PyHash {
|
||||
fn hash(&self) -> pyhash::PyHash {
|
||||
pyhash::hash_float(self.value)
|
||||
}
|
||||
|
||||
#[pyproperty(name = "real")]
|
||||
fn real(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyFloatRef {
|
||||
#[pyproperty]
|
||||
fn real(zelf: PyRef<Self>) -> PyFloatRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pyproperty(name = "imag")]
|
||||
fn imag(&self, _vm: &VirtualMachine) -> f64 {
|
||||
#[pyproperty]
|
||||
fn imag(&self) -> f64 {
|
||||
0.0f64
|
||||
}
|
||||
|
||||
#[pymethod(name = "conjugate")]
|
||||
fn conjugate(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyFloatRef {
|
||||
fn conjugate(zelf: PyRef<Self>) -> PyFloatRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "is_integer")]
|
||||
fn is_integer(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn is_integer(&self) -> bool {
|
||||
let v = self.value;
|
||||
(v - v.round()).abs() < std::f64::EPSILON
|
||||
}
|
||||
@@ -524,11 +524,11 @@ impl PyFloat {
|
||||
let value = self.value;
|
||||
if value.is_infinite() {
|
||||
return Err(
|
||||
vm.new_overflow_error("cannot convert Infinity to integer ratio".to_string())
|
||||
vm.new_overflow_error("cannot convert Infinity to integer ratio".to_owned())
|
||||
);
|
||||
}
|
||||
if value.is_nan() {
|
||||
return Err(vm.new_value_error("cannot convert NaN to integer ratio".to_string()));
|
||||
return Err(vm.new_value_error("cannot convert NaN to integer ratio".to_owned()));
|
||||
}
|
||||
|
||||
let ratio = Ratio::from_float(value).unwrap();
|
||||
@@ -584,7 +584,7 @@ impl PyFloat {
|
||||
}
|
||||
|
||||
hexf_parse::parse_hexf64(hex.as_str(), false).map_err(|_| {
|
||||
vm.new_value_error("invalid hexadecimal floating-point string".to_string())
|
||||
vm.new_value_error("invalid hexadecimal floating-point string".to_owned())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -592,7 +592,7 @@ impl PyFloat {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn hex(&self, _vm: &VirtualMachine) -> String {
|
||||
fn hex(&self) -> String {
|
||||
to_hex(self.value)
|
||||
}
|
||||
}
|
||||
@@ -661,7 +661,7 @@ fn to_hex(value: f64) -> String {
|
||||
match value {
|
||||
value if value.is_zero() => format!("{}0x0.0p+0", sign_fmt),
|
||||
value if value.is_infinite() => format!("{}inf", sign_fmt),
|
||||
value if value.is_nan() => "nan".to_string(),
|
||||
value if value.is_nan() => "nan".to_owned(),
|
||||
_ => {
|
||||
const BITS: i16 = 52;
|
||||
const FRACT_MASK: u64 = 0xf_ffff_ffff_ffff;
|
||||
|
||||
@@ -16,31 +16,31 @@ pub fn init(context: &PyContext) {
|
||||
impl FrameRef {
|
||||
#[pyslot]
|
||||
fn tp_new(_cls: FrameRef, vm: &VirtualMachine) -> PyResult<Self> {
|
||||
Err(vm.new_type_error("Cannot directly create frame object".to_string()))
|
||||
Err(vm.new_type_error("Cannot directly create frame object".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(self, _vm: &VirtualMachine) -> String {
|
||||
"<frame object at .. >".to_string()
|
||||
fn repr(self) -> String {
|
||||
"<frame object at .. >".to_owned()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn clear(self, _vm: &VirtualMachine) {
|
||||
fn clear(self) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn f_globals(self, _vm: &VirtualMachine) -> PyDictRef {
|
||||
fn f_globals(self) -> PyDictRef {
|
||||
self.scope.globals.clone()
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn f_locals(self, _vm: &VirtualMachine) -> PyDictRef {
|
||||
fn f_locals(self) -> PyDictRef {
|
||||
self.scope.get_locals()
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn f_code(self, _vm: &VirtualMachine) -> PyCodeRef {
|
||||
fn f_code(self) -> PyCodeRef {
|
||||
self.code.clone()
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::pyobject::{
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::scope::Scope;
|
||||
use crate::slots::{PyBuiltinCallable, PyBuiltinDescriptor};
|
||||
use crate::slots::{SlotCall, SlotDescriptor};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub type PyFunctionRef = PyRef<PyFunction>;
|
||||
@@ -27,13 +27,14 @@ pub struct PyFunction {
|
||||
kw_only_defaults: Option<PyDictRef>,
|
||||
}
|
||||
|
||||
impl PyBuiltinDescriptor for PyFunction {
|
||||
fn get(
|
||||
zelf: PyRef<Self>,
|
||||
obj: PyObjectRef,
|
||||
cls: OptionalArg<PyObjectRef>,
|
||||
impl SlotDescriptor for PyFunction {
|
||||
fn descr_get(
|
||||
vm: &VirtualMachine,
|
||||
zelf: PyObjectRef,
|
||||
obj: Option<PyObjectRef>,
|
||||
cls: OptionalArg<PyObjectRef>,
|
||||
) -> PyResult {
|
||||
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
|
||||
if obj.is(&vm.get_none()) && !Self::_cls_is(&cls, &obj.class()) {
|
||||
Ok(zelf.into_object())
|
||||
} else {
|
||||
@@ -240,7 +241,7 @@ impl PyValue for PyFunction {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinDescriptor))]
|
||||
#[pyimpl(with(SlotDescriptor))]
|
||||
impl PyFunction {
|
||||
#[pyslot]
|
||||
#[pymethod(magic)]
|
||||
@@ -248,18 +249,18 @@ impl PyFunction {
|
||||
self.invoke(args, vm)
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__code__")]
|
||||
fn code(&self, _vm: &VirtualMachine) -> PyCodeRef {
|
||||
#[pyproperty(magic)]
|
||||
fn code(&self) -> PyCodeRef {
|
||||
self.code.clone()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__defaults__")]
|
||||
fn defaults(&self, _vm: &VirtualMachine) -> Option<PyTupleRef> {
|
||||
#[pyproperty(magic)]
|
||||
fn defaults(&self) -> Option<PyTupleRef> {
|
||||
self.defaults.clone()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__kwdefaults__")]
|
||||
fn kwdefaults(&self, _vm: &VirtualMachine) -> Option<PyDictRef> {
|
||||
#[pyproperty(magic)]
|
||||
fn kwdefaults(&self) -> Option<PyDictRef> {
|
||||
self.kw_only_defaults.clone()
|
||||
}
|
||||
}
|
||||
@@ -272,7 +273,7 @@ pub struct PyBoundMethod {
|
||||
pub function: PyObjectRef,
|
||||
}
|
||||
|
||||
impl PyBuiltinCallable for PyBoundMethod {
|
||||
impl SlotCall for PyBoundMethod {
|
||||
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
let args = args.insert(self.object.clone());
|
||||
vm.invoke(&self.function, args)
|
||||
@@ -285,7 +286,7 @@ impl PyBoundMethod {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinCallable))]
|
||||
#[pyimpl(with(SlotCall))]
|
||||
impl PyBoundMethod {
|
||||
#[pymethod(magic)]
|
||||
fn getattribute(&self, name: PyStringRef, vm: &VirtualMachine) -> PyResult {
|
||||
|
||||
@@ -45,7 +45,7 @@ impl PyGenerator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyGeneratorRef, _vm: &VirtualMachine) -> PyGeneratorRef {
|
||||
fn iter(zelf: PyGeneratorRef) -> PyGeneratorRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ impl PyGenerator {
|
||||
match result {
|
||||
Ok(ExecutionResult::Yield(_)) => Err(vm.new_exception_msg(
|
||||
vm.ctx.exceptions.runtime_error.clone(),
|
||||
"generator ignored GeneratorExit".to_string(),
|
||||
"generator ignored GeneratorExit".to_owned(),
|
||||
)),
|
||||
Err(e) => {
|
||||
if isinstance(&e, &vm.ctx.exceptions.generator_exit) {
|
||||
|
||||
249
vm/src/obj/objgetset.rs
Normal file
249
vm/src/obj/objgetset.rs
Normal file
@@ -0,0 +1,249 @@
|
||||
/*! Python `attribute` descriptor class. (PyGetSet)
|
||||
|
||||
*/
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::{OptionalArg, OwnedParam, RefParam};
|
||||
use crate::pyobject::{
|
||||
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
|
||||
};
|
||||
use crate::slots::SlotDescriptor;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub type PyGetterFunc = Box<dyn Fn(&VirtualMachine, PyObjectRef) -> PyResult>;
|
||||
pub type PySetterFunc = Box<dyn Fn(&VirtualMachine, PyObjectRef, PyObjectRef) -> PyResult<()>>;
|
||||
|
||||
pub trait IntoPyGetterFunc<T> {
|
||||
fn into_getter(self) -> PyGetterFunc;
|
||||
}
|
||||
|
||||
impl<F, T, R> IntoPyGetterFunc<(OwnedParam<T>, R, VirtualMachine)> for F
|
||||
where
|
||||
F: Fn(T, &VirtualMachine) -> R + 'static,
|
||||
T: TryFromObject,
|
||||
R: IntoPyObject,
|
||||
{
|
||||
fn into_getter(self) -> PyGetterFunc {
|
||||
Box::new(move |vm, obj| {
|
||||
let obj = T::try_from_object(vm, obj)?;
|
||||
(self)(obj, vm).into_pyobject(vm)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, R> IntoPyGetterFunc<(RefParam<S>, R, VirtualMachine)> for F
|
||||
where
|
||||
F: Fn(&S, &VirtualMachine) -> R + 'static,
|
||||
S: PyValue,
|
||||
R: IntoPyObject,
|
||||
{
|
||||
fn into_getter(self) -> PyGetterFunc {
|
||||
Box::new(move |vm, obj| {
|
||||
let zelf = PyRef::<S>::try_from_object(vm, obj)?;
|
||||
(self)(&zelf, vm).into_pyobject(vm)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T, R> IntoPyGetterFunc<(OwnedParam<T>, R)> for F
|
||||
where
|
||||
F: Fn(T) -> R + 'static,
|
||||
T: TryFromObject,
|
||||
R: IntoPyObject,
|
||||
{
|
||||
fn into_getter(self) -> PyGetterFunc {
|
||||
IntoPyGetterFunc::into_getter(move |obj, _vm: &VirtualMachine| (self)(obj))
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, R> IntoPyGetterFunc<(RefParam<S>, R)> for F
|
||||
where
|
||||
F: Fn(&S) -> R + 'static,
|
||||
S: PyValue,
|
||||
R: IntoPyObject,
|
||||
{
|
||||
fn into_getter(self) -> PyGetterFunc {
|
||||
IntoPyGetterFunc::into_getter(move |zelf: &S, _vm: &VirtualMachine| (self)(zelf))
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoPyNoResult {
|
||||
fn into_noresult(self) -> PyResult<()>;
|
||||
}
|
||||
|
||||
impl IntoPyNoResult for () {
|
||||
fn into_noresult(self) -> PyResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoPyNoResult for PyResult<()> {
|
||||
fn into_noresult(self) -> PyResult<()> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
pub trait IntoPySetterFunc<T> {
|
||||
fn into_setter(self) -> PySetterFunc;
|
||||
}
|
||||
|
||||
impl<F, T, V, R> IntoPySetterFunc<(OwnedParam<T>, V, R, VirtualMachine)> for F
|
||||
where
|
||||
F: Fn(T, V, &VirtualMachine) -> R + 'static,
|
||||
T: TryFromObject,
|
||||
V: TryFromObject,
|
||||
R: IntoPyNoResult,
|
||||
{
|
||||
fn into_setter(self) -> PySetterFunc {
|
||||
Box::new(move |vm, obj, value| {
|
||||
let obj = T::try_from_object(vm, obj)?;
|
||||
let value = V::try_from_object(vm, value)?;
|
||||
(self)(obj, value, vm).into_noresult()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, V, R> IntoPySetterFunc<(RefParam<S>, V, R, VirtualMachine)> for F
|
||||
where
|
||||
F: Fn(&S, V, &VirtualMachine) -> R + 'static,
|
||||
S: PyValue,
|
||||
V: TryFromObject,
|
||||
R: IntoPyNoResult,
|
||||
{
|
||||
fn into_setter(self) -> PySetterFunc {
|
||||
Box::new(move |vm, obj, value| {
|
||||
let zelf = PyRef::<S>::try_from_object(vm, obj)?;
|
||||
let value = V::try_from_object(vm, value)?;
|
||||
(self)(&zelf, value, vm).into_noresult()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, T, V, R> IntoPySetterFunc<(OwnedParam<T>, V, R)> for F
|
||||
where
|
||||
F: Fn(T, V) -> R + 'static,
|
||||
T: TryFromObject,
|
||||
V: TryFromObject,
|
||||
R: IntoPyNoResult,
|
||||
{
|
||||
fn into_setter(self) -> PySetterFunc {
|
||||
IntoPySetterFunc::into_setter(move |obj, v, _vm: &VirtualMachine| (self)(obj, v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<F, S, V, R> IntoPySetterFunc<(RefParam<S>, V, R)> for F
|
||||
where
|
||||
F: Fn(&S, V) -> R + 'static,
|
||||
S: PyValue,
|
||||
V: TryFromObject,
|
||||
R: IntoPyNoResult,
|
||||
{
|
||||
fn into_setter(self) -> PySetterFunc {
|
||||
IntoPySetterFunc::into_setter(move |zelf: &S, v, _vm: &VirtualMachine| (self)(zelf, v))
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
pub struct PyGetSet {
|
||||
name: String,
|
||||
getter: Option<PyGetterFunc>,
|
||||
setter: Option<PySetterFunc>,
|
||||
// doc: Option<String>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for PyGetSet {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"PyGetSet {{ name: {}, getter: {}, setter: {} }}",
|
||||
self.name,
|
||||
if self.getter.is_some() {
|
||||
"Some"
|
||||
} else {
|
||||
"None"
|
||||
},
|
||||
if self.setter.is_some() {
|
||||
"Some"
|
||||
} else {
|
||||
"None"
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl PyValue for PyGetSet {
|
||||
fn class(vm: &VirtualMachine) -> PyClassRef {
|
||||
vm.ctx.getset_type()
|
||||
}
|
||||
}
|
||||
|
||||
pub type PyGetSetRef = PyRef<PyGetSet>;
|
||||
|
||||
impl SlotDescriptor for PyGetSet {
|
||||
fn descr_get(
|
||||
vm: &VirtualMachine,
|
||||
zelf: PyObjectRef,
|
||||
obj: Option<PyObjectRef>,
|
||||
_cls: OptionalArg<PyObjectRef>,
|
||||
) -> PyResult {
|
||||
let (zelf, obj) = match Self::_check(zelf, obj, vm) {
|
||||
Ok(obj) => obj,
|
||||
Err(result) => return result,
|
||||
};
|
||||
if let Some(ref f) = zelf.getter {
|
||||
f(vm, obj)
|
||||
} else {
|
||||
Err(vm.new_attribute_error(format!(
|
||||
"attribute '{}' of '{}' objects is not readable",
|
||||
zelf.name,
|
||||
Self::class(vm).name
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PyGetSet {
|
||||
pub fn with_get<G, X>(name: String, getter: G) -> Self
|
||||
where
|
||||
G: IntoPyGetterFunc<X>,
|
||||
{
|
||||
Self {
|
||||
name,
|
||||
getter: Some(getter.into_getter()),
|
||||
setter: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_get_set<G, S, X, Y>(name: String, getter: G, setter: S) -> Self
|
||||
where
|
||||
G: IntoPyGetterFunc<X>,
|
||||
S: IntoPySetterFunc<Y>,
|
||||
{
|
||||
Self {
|
||||
name,
|
||||
getter: Some(getter.into_getter()),
|
||||
setter: Some(setter.into_setter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(SlotDescriptor))]
|
||||
impl PyGetSet {
|
||||
// Descriptor methods
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn set(&self, obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
if let Some(ref f) = self.setter {
|
||||
f(vm, obj, value)
|
||||
} else {
|
||||
Err(vm.new_attribute_error(format!(
|
||||
"attribute '{}' of '{}' objects is not writable",
|
||||
self.name,
|
||||
Self::class(vm).name
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn init(context: &PyContext) {
|
||||
PyGetSet::extend_class(context, &context.types.getset_type);
|
||||
}
|
||||
@@ -94,7 +94,7 @@ macro_rules! impl_try_from_object_int {
|
||||
vm.new_overflow_error(concat!(
|
||||
"Int value cannot fit into Rust ",
|
||||
stringify!($t)
|
||||
).to_string())
|
||||
).to_owned())
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,7 @@ fn inner_pow(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
|
||||
fn inner_mod(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
if int2.is_zero() {
|
||||
Err(vm.new_zero_division_error("integer modulo by zero".to_string()))
|
||||
Err(vm.new_zero_division_error("integer modulo by zero".to_owned()))
|
||||
} else {
|
||||
Ok(vm.ctx.new_int(int1.mod_floor(int2)))
|
||||
}
|
||||
@@ -152,7 +152,7 @@ fn inner_mod(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
|
||||
fn inner_floordiv(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
if int2.is_zero() {
|
||||
Err(vm.new_zero_division_error("integer division by zero".to_string()))
|
||||
Err(vm.new_zero_division_error("integer division by zero".to_owned()))
|
||||
} else {
|
||||
Ok(vm.ctx.new_int(int1.div_floor(&int2)))
|
||||
}
|
||||
@@ -160,7 +160,7 @@ fn inner_floordiv(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult
|
||||
|
||||
fn inner_divmod(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
if int2.is_zero() {
|
||||
Err(vm.new_zero_division_error("integer division or modulo by zero".to_string()))
|
||||
Err(vm.new_zero_division_error("integer division or modulo by zero".to_owned()))
|
||||
} else {
|
||||
let (div, modulo) = int1.div_mod_floor(int2);
|
||||
Ok(vm
|
||||
@@ -182,7 +182,7 @@ fn inner_rshift(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
#[inline]
|
||||
fn inner_truediv(i1: &BigInt, i2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
if i2.is_zero() {
|
||||
return Err(vm.new_zero_division_error("integer division by zero".to_string()));
|
||||
return Err(vm.new_zero_division_error("integer division by zero".to_owned()));
|
||||
}
|
||||
|
||||
if let (Some(f1), Some(f2)) = (i1.to_f64(), i2.to_f64()) {
|
||||
@@ -206,7 +206,7 @@ fn inner_truediv(i1: &BigInt, i2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
|
||||
Ok(vm.ctx.new_float(quotient + rem_part))
|
||||
} else {
|
||||
Err(vm.new_overflow_error("int too large to convert to float".to_string()))
|
||||
Err(vm.new_overflow_error("int too large to convert to float".to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -413,17 +413,17 @@ impl PyInt {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__neg__")]
|
||||
fn neg(&self, _vm: &VirtualMachine) -> BigInt {
|
||||
fn neg(&self) -> BigInt {
|
||||
-(&self.value)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
pub fn hash(&self, _vm: &VirtualMachine) -> pyhash::PyHash {
|
||||
pub fn hash(&self) -> pyhash::PyHash {
|
||||
pyhash::hash_bigint(&self.value)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__abs__")]
|
||||
fn abs(&self, _vm: &VirtualMachine) -> BigInt {
|
||||
fn abs(&self) -> BigInt {
|
||||
self.value.abs()
|
||||
}
|
||||
|
||||
@@ -457,12 +457,12 @@ impl PyInt {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__int__")]
|
||||
fn int(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn int(zelf: PyRef<Self>) -> PyIntRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__pos__")]
|
||||
fn pos(&self, _vm: &VirtualMachine) -> BigInt {
|
||||
fn pos(&self) -> BigInt {
|
||||
self.value.clone()
|
||||
}
|
||||
|
||||
@@ -472,32 +472,32 @@ impl PyInt {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__trunc__")]
|
||||
fn trunc(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn trunc(zelf: PyRef<Self>) -> PyIntRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__floor__")]
|
||||
fn floor(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn floor(zelf: PyRef<Self>) -> PyIntRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__ceil__")]
|
||||
fn ceil(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn ceil(zelf: PyRef<Self>) -> PyIntRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__index__")]
|
||||
fn index(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn index(zelf: PyRef<Self>) -> PyIntRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__invert__")]
|
||||
fn invert(&self, _vm: &VirtualMachine) -> BigInt {
|
||||
fn invert(&self) -> BigInt {
|
||||
!(&self.value)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(&self, _vm: &VirtualMachine) -> String {
|
||||
fn repr(&self) -> String {
|
||||
self.value.to_string()
|
||||
}
|
||||
|
||||
@@ -512,22 +512,22 @@ impl PyInt {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn bool(&self) -> bool {
|
||||
!self.value.is_zero()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn sizeof(&self) -> usize {
|
||||
size_of::<Self>() + ((self.value.bits() + 7) & !7) / 8
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn bit_length(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn bit_length(&self) -> usize {
|
||||
self.value.bits()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn conjugate(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn conjugate(zelf: PyRef<Self>) -> PyIntRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
@@ -555,7 +555,7 @@ impl PyInt {
|
||||
},
|
||||
_ => {
|
||||
return Err(
|
||||
vm.new_value_error("byteorder must be either 'little' or 'big'".to_string())
|
||||
vm.new_value_error("byteorder must be either 'little' or 'big'".to_owned())
|
||||
)
|
||||
}
|
||||
};
|
||||
@@ -573,14 +573,14 @@ impl PyInt {
|
||||
|
||||
let value = self.as_bigint();
|
||||
if value.sign() == Sign::Minus && !signed {
|
||||
return Err(vm.new_overflow_error("can't convert negative int to unsigned".to_string()));
|
||||
return Err(vm.new_overflow_error("can't convert negative int to unsigned".to_owned()));
|
||||
}
|
||||
|
||||
let byte_len = if let Some(byte_len) = args.length.as_bigint().to_usize() {
|
||||
byte_len
|
||||
} else {
|
||||
return Err(
|
||||
vm.new_overflow_error("Python int too large to convert to C ssize_t".to_string())
|
||||
vm.new_overflow_error("Python int too large to convert to C ssize_t".to_owned())
|
||||
);
|
||||
};
|
||||
|
||||
@@ -595,14 +595,14 @@ impl PyInt {
|
||||
},
|
||||
_ => {
|
||||
return Err(
|
||||
vm.new_value_error("byteorder must be either 'little' or 'big'".to_string())
|
||||
vm.new_value_error("byteorder must be either 'little' or 'big'".to_owned())
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
let origin_len = origin_bytes.len();
|
||||
if origin_len > byte_len {
|
||||
return Err(vm.new_overflow_error("int too big to convert".to_string()));
|
||||
return Err(vm.new_overflow_error("int too big to convert".to_owned()));
|
||||
}
|
||||
|
||||
let mut append_bytes = match value.sign() {
|
||||
@@ -626,21 +626,22 @@ impl PyInt {
|
||||
}
|
||||
#[pyproperty]
|
||||
fn real(&self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
// subclasses must return int here
|
||||
vm.ctx.new_bigint(&self.value)
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn imag(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn imag(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn numerator(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn numerator(zelf: PyRef<Self>) -> PyIntRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn denominator(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn denominator(&self) -> usize {
|
||||
1
|
||||
}
|
||||
}
|
||||
@@ -661,7 +662,7 @@ impl IntOptions {
|
||||
|| objtype::isinstance(&val, &vm.ctx.bytes_type()))
|
||||
{
|
||||
return Err(vm.new_type_error(
|
||||
"int() can't convert non-string with explicit base".to_string(),
|
||||
"int() can't convert non-string with explicit base".to_owned(),
|
||||
));
|
||||
}
|
||||
base
|
||||
@@ -670,7 +671,7 @@ impl IntOptions {
|
||||
};
|
||||
to_int(vm, &val, base.as_bigint())
|
||||
} else if let OptionalArg::Present(_) = self.base {
|
||||
Err(vm.new_type_error("int() missing string argument".to_string()))
|
||||
Err(vm.new_type_error("int() missing string argument".to_owned()))
|
||||
} else {
|
||||
Ok(Zero::zero())
|
||||
}
|
||||
@@ -702,11 +703,11 @@ pub fn to_int(vm: &VirtualMachine, obj: &PyObjectRef, base: &BigInt) -> PyResult
|
||||
let base_u32 = match base.to_u32() {
|
||||
Some(base_u32) => base_u32,
|
||||
None => {
|
||||
return Err(vm.new_value_error("int() base must be >= 2 and <= 36, or 0".to_string()))
|
||||
return Err(vm.new_value_error("int() base must be >= 2 and <= 36, or 0".to_owned()))
|
||||
}
|
||||
};
|
||||
if base_u32 != 0 && (base_u32 < 2 || base_u32 > 36) {
|
||||
return Err(vm.new_value_error("int() base must be >= 2 and <= 36, or 0".to_string()));
|
||||
return Err(vm.new_value_error("int() base must be >= 2 and <= 36, or 0".to_owned()));
|
||||
}
|
||||
|
||||
match_class!(match obj.clone() {
|
||||
@@ -834,7 +835,7 @@ pub fn get_value(obj: &PyObjectRef) -> &BigInt {
|
||||
|
||||
pub fn try_float(int: &BigInt, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
int.to_f64()
|
||||
.ok_or_else(|| vm.new_overflow_error("int too large to convert to float".to_string()))
|
||||
.ok_or_else(|| vm.new_overflow_error("int too large to convert to float".to_owned()))
|
||||
}
|
||||
|
||||
fn get_shift_amount(amount: &BigInt, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
@@ -842,9 +843,9 @@ fn get_shift_amount(amount: &BigInt, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
Ok(n_bits)
|
||||
} else {
|
||||
match amount {
|
||||
v if *v < BigInt::zero() => Err(vm.new_value_error("negative shift count".to_string())),
|
||||
v if *v < BigInt::zero() => Err(vm.new_value_error("negative shift count".to_owned())),
|
||||
v if *v > BigInt::from(usize::max_value()) => {
|
||||
Err(vm.new_overflow_error("the number is too large to convert to int".to_string()))
|
||||
Err(vm.new_overflow_error("the number is too large to convert to int".to_owned()))
|
||||
}
|
||||
_ => panic!("Failed converting {} to rust usize", amount),
|
||||
}
|
||||
|
||||
@@ -128,10 +128,10 @@ pub fn length_hint(vm: &VirtualMachine, iter: PyObjectRef) -> PyResult<Option<us
|
||||
})?
|
||||
.as_bigint();
|
||||
if result.is_negative() {
|
||||
return Err(vm.new_value_error("__length_hint__() should return >= 0".to_string()));
|
||||
return Err(vm.new_value_error("__length_hint__() should return >= 0".to_owned()));
|
||||
}
|
||||
let hint = result.to_usize().ok_or_else(|| {
|
||||
vm.new_value_error("Python int too large to convert to Rust usize".to_string())
|
||||
vm.new_value_error("Python int too large to convert to Rust usize".to_owned())
|
||||
})?;
|
||||
Ok(Some(hint))
|
||||
}
|
||||
@@ -174,7 +174,7 @@ impl PySequenceIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ impl PySequenceIterator {
|
||||
pos + 1
|
||||
} else {
|
||||
let len = objsequence::opt_len(&self.obj, vm).unwrap_or_else(|| {
|
||||
Err(vm.new_type_error("sequence has no __len__ method".to_string()))
|
||||
Err(vm.new_type_error("sequence has no __len__ method".to_owned()))
|
||||
})?;
|
||||
len as isize - pos
|
||||
};
|
||||
@@ -193,7 +193,7 @@ impl PySequenceIterator {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn seq_iter_method(obj: PyObjectRef, _vm: &VirtualMachine) -> PySequenceIterator {
|
||||
pub fn seq_iter_method(obj: PyObjectRef) -> PySequenceIterator {
|
||||
PySequenceIterator {
|
||||
position: Cell::new(0),
|
||||
obj,
|
||||
|
||||
@@ -119,9 +119,7 @@ impl PyList {
|
||||
Ok(result) => match result.as_bigint().to_u8() {
|
||||
Some(result) => elements.push(result),
|
||||
None => {
|
||||
return Err(
|
||||
vm.new_value_error("bytes must be in range (0, 256)".to_string())
|
||||
)
|
||||
return Err(vm.new_value_error("bytes must be in range (0, 256)".to_owned()))
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
@@ -149,7 +147,7 @@ pub type PyListRef = PyRef<PyList>;
|
||||
#[pyimpl(flags(BASETYPE))]
|
||||
impl PyList {
|
||||
#[pymethod]
|
||||
pub(crate) fn append(&self, x: PyObjectRef, _vm: &VirtualMachine) {
|
||||
pub(crate) fn append(&self, x: PyObjectRef) {
|
||||
self.elements.borrow_mut().push(x);
|
||||
}
|
||||
|
||||
@@ -161,7 +159,7 @@ impl PyList {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn insert(&self, position: isize, element: PyObjectRef, _vm: &VirtualMachine) {
|
||||
fn insert(&self, position: isize, element: PyObjectRef) {
|
||||
let mut vec = self.elements.borrow_mut();
|
||||
let vec_len = vec.len().to_isize().unwrap();
|
||||
// This unbounded position can be < 0 or > vec.len()
|
||||
@@ -203,12 +201,12 @@ impl PyList {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn bool(&self) -> bool {
|
||||
!self.elements.borrow().is_empty()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn clear(&self, _vm: &VirtualMachine) {
|
||||
fn clear(&self) {
|
||||
self.elements.borrow_mut().clear();
|
||||
}
|
||||
|
||||
@@ -218,22 +216,22 @@ impl PyList {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(&self) -> usize {
|
||||
self.elements.borrow().len()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn sizeof(&self) -> usize {
|
||||
size_of::<Self>() + self.elements.borrow().capacity() * size_of::<PyObjectRef>()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn reverse(&self, _vm: &VirtualMachine) {
|
||||
fn reverse(&self) {
|
||||
self.elements.borrow_mut().reverse();
|
||||
}
|
||||
|
||||
#[pymethod(name = "__reversed__")]
|
||||
fn reversed(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyListReverseIterator {
|
||||
fn reversed(zelf: PyRef<Self>) -> PyListReverseIterator {
|
||||
let final_position = zelf.elements.borrow().len();
|
||||
PyListReverseIterator {
|
||||
position: Cell::new(final_position),
|
||||
@@ -252,7 +250,7 @@ impl PyList {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyListIterator {
|
||||
fn iter(zelf: PyRef<Self>) -> PyListIterator {
|
||||
PyListIterator {
|
||||
position: Cell::new(0),
|
||||
list: zelf,
|
||||
@@ -272,7 +270,7 @@ impl PyList {
|
||||
if let Ok(sec) = PyIterable::try_from_object(vm, value) {
|
||||
return self.setslice(slice, sec, vm);
|
||||
}
|
||||
Err(vm.new_type_error("can only assign an iterable to a slice".to_string()))
|
||||
Err(vm.new_type_error("can only assign an iterable to a slice".to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +280,7 @@ impl PyList {
|
||||
self.elements.borrow_mut()[pos_index] = value;
|
||||
Ok(vm.get_none())
|
||||
} else {
|
||||
Err(vm.new_index_error("list assignment index out of range".to_string()))
|
||||
Err(vm.new_index_error("list assignment index out of range".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +288,7 @@ impl PyList {
|
||||
let step = slice.step_index(vm)?.unwrap_or_else(BigInt::one);
|
||||
|
||||
if step.is_zero() {
|
||||
Err(vm.new_value_error("slice step cannot be zero".to_string()))
|
||||
Err(vm.new_value_error("slice step cannot be zero".to_owned()))
|
||||
} else if step.is_positive() {
|
||||
let range = self.get_slice_range(&slice.start_index(vm)?, &slice.stop_index(vm)?);
|
||||
if range.start < range.end {
|
||||
@@ -455,18 +453,18 @@ impl PyList {
|
||||
let mut str_parts = Vec::with_capacity(zelf.elements.borrow().len());
|
||||
for elem in zelf.elements.borrow().iter() {
|
||||
let s = vm.to_repr(elem)?;
|
||||
str_parts.push(s.as_str().to_string());
|
||||
str_parts.push(s.as_str().to_owned());
|
||||
}
|
||||
format!("[{}]", str_parts.join(", "))
|
||||
} else {
|
||||
"[...]".to_string()
|
||||
"[...]".to_owned()
|
||||
};
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
fn hash(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Err(vm.new_type_error("unhashable type".to_string()))
|
||||
Err(vm.new_type_error("unhashable type".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mul__")]
|
||||
@@ -483,7 +481,7 @@ impl PyList {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__imul__")]
|
||||
fn imul(zelf: PyRef<Self>, counter: isize, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn imul(zelf: PyRef<Self>, counter: isize) -> PyRef<Self> {
|
||||
let new_elements = sequence::seq_mul(&zelf.borrow_sequence(), counter)
|
||||
.cloned()
|
||||
.collect();
|
||||
@@ -532,9 +530,9 @@ impl PyList {
|
||||
i += elements.len() as isize;
|
||||
}
|
||||
if elements.is_empty() {
|
||||
Err(vm.new_index_error("pop from empty list".to_string()))
|
||||
Err(vm.new_index_error("pop from empty list".to_owned()))
|
||||
} else if i < 0 || i as usize >= elements.len() {
|
||||
Err(vm.new_index_error("pop index out of range".to_string()))
|
||||
Err(vm.new_index_error("pop index out of range".to_owned()))
|
||||
} else {
|
||||
Ok(elements.remove(i as usize))
|
||||
}
|
||||
@@ -627,7 +625,7 @@ impl PyList {
|
||||
self.elements.borrow_mut().remove(pos_index);
|
||||
Ok(())
|
||||
} else {
|
||||
Err(vm.new_index_error("Index out of bounds!".to_string()))
|
||||
Err(vm.new_index_error("Index out of bounds!".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -637,7 +635,7 @@ impl PyList {
|
||||
let step = slice.step_index(vm)?.unwrap_or_else(BigInt::one);
|
||||
|
||||
if step.is_zero() {
|
||||
Err(vm.new_value_error("slice step cannot be zero".to_string()))
|
||||
Err(vm.new_value_error("slice step cannot be zero".to_owned()))
|
||||
} else if step.is_positive() {
|
||||
let range = self.get_slice_range(&start, &stop);
|
||||
if range.start < range.end {
|
||||
@@ -756,7 +754,7 @@ impl PyList {
|
||||
let temp_elements = self.elements.replace(elements);
|
||||
|
||||
if !temp_elements.is_empty() {
|
||||
return Err(vm.new_value_error("list modified during sort".to_string()));
|
||||
return Err(vm.new_value_error("list modified during sort".to_owned()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -870,12 +868,12 @@ impl PyListIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__length_hint__")]
|
||||
fn length_hint(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn length_hint(&self) -> usize {
|
||||
self.list.elements.borrow().len() - self.position.get()
|
||||
}
|
||||
}
|
||||
@@ -908,12 +906,12 @@ impl PyListReverseIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__length_hint__")]
|
||||
fn length_hint(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn length_hint(&self) -> usize {
|
||||
self.position.get()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ impl PyMap {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
use super::objproperty::PyPropertyRef;
|
||||
use super::objstr::PyStringRef;
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::pyobject::{
|
||||
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
|
||||
TypeProtocol,
|
||||
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
@@ -43,75 +40,15 @@ impl PyNone {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(&self, _vm: &VirtualMachine) -> PyResult<String> {
|
||||
Ok("None".to_string())
|
||||
fn repr(&self) -> PyResult<String> {
|
||||
Ok("None".to_owned())
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(&self, _vm: &VirtualMachine) -> PyResult<bool> {
|
||||
fn bool(&self) -> PyResult<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__getattribute__")]
|
||||
fn get_attribute(zelf: PyRef<Self>, name: PyStringRef, vm: &VirtualMachine) -> PyResult {
|
||||
vm_trace!("None.__getattribute__({:?}, {:?})", self, name);
|
||||
let cls = zelf.class();
|
||||
|
||||
// Properties use a comparision with None to determine if they are either invoked by am
|
||||
// instance binding or a class binding. But if the object itself is None then this detection
|
||||
// won't work. Instead we call a special function on property that bypasses this check, as
|
||||
// we are invoking it as a instance binding.
|
||||
//
|
||||
// In CPython they instead call the slot tp_descr_get with NULL to indicates it's an
|
||||
// instance binding.
|
||||
// https://github.com/python/cpython/blob/master/Objects/typeobject.c#L3281
|
||||
fn call_descriptor(
|
||||
descriptor: PyObjectRef,
|
||||
get_func: PyObjectRef,
|
||||
obj: PyObjectRef,
|
||||
cls: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
if let Ok(property) = PyPropertyRef::try_from_object(vm, descriptor.clone()) {
|
||||
property.instance_binding_get(obj, vm)
|
||||
} else {
|
||||
vm.invoke(&get_func, vec![descriptor, obj, cls])
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(attr) = cls.get_attr(name.as_str()) {
|
||||
let attr_class = attr.class();
|
||||
if attr_class.has_attr("__set__") {
|
||||
if let Some(get_func) = attr_class.get_attr("__get__") {
|
||||
return call_descriptor(
|
||||
attr,
|
||||
get_func,
|
||||
zelf.into_object(),
|
||||
cls.into_object(),
|
||||
vm,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// None has no attributes and cannot have attributes set on it.
|
||||
// if let Some(obj_attr) = zelf.as_object().get_attr(name.as_str()) {
|
||||
// Ok(obj_attr)
|
||||
// } else
|
||||
if let Some(attr) = cls.get_attr(name.as_str()) {
|
||||
let attr_class = attr.class();
|
||||
if let Some(get_func) = attr_class.get_attr("__get__") {
|
||||
call_descriptor(attr, get_func, zelf.into_object(), cls.into_object(), vm)
|
||||
} else {
|
||||
Ok(attr)
|
||||
}
|
||||
} else if let Some(getter) = cls.get_attr("__getattr__") {
|
||||
vm.invoke(&getter, vec![zelf.into_object(), name.into_object()])
|
||||
} else {
|
||||
Err(vm.new_attribute_error(format!("{} has no attribute '{}'", zelf.as_object(), name)))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(name = "__eq__")]
|
||||
fn eq(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
if vm.is_none(&rhs) {
|
||||
|
||||
@@ -37,7 +37,7 @@ impl PyBaseObject {
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn eq(zelf: PyObjectRef, other: PyObjectRef, _vm: &VirtualMachine) -> PyComparisonValue {
|
||||
fn eq(zelf: PyObjectRef, other: PyObjectRef) -> PyComparisonValue {
|
||||
if zelf.is(&other) {
|
||||
Implemented(true)
|
||||
} else {
|
||||
@@ -64,27 +64,27 @@ impl PyBaseObject {
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn lt(_zelf: PyObjectRef, _other: PyObjectRef, _vm: &VirtualMachine) -> PyComparisonValue {
|
||||
fn lt(_zelf: PyObjectRef, _other: PyObjectRef) -> PyComparisonValue {
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn le(_zelf: PyObjectRef, _other: PyObjectRef, _vm: &VirtualMachine) -> PyComparisonValue {
|
||||
fn le(_zelf: PyObjectRef, _other: PyObjectRef) -> PyComparisonValue {
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn gt(_zelf: PyObjectRef, _other: PyObjectRef, _vm: &VirtualMachine) -> PyComparisonValue {
|
||||
fn gt(_zelf: PyObjectRef, _other: PyObjectRef) -> PyComparisonValue {
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn ge(_zelf: PyObjectRef, _other: PyObjectRef, _vm: &VirtualMachine) -> PyComparisonValue {
|
||||
fn ge(_zelf: PyObjectRef, _other: PyObjectRef) -> PyComparisonValue {
|
||||
NotImplemented
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn hash(zelf: PyObjectRef, _vm: &VirtualMachine) -> pyhash::PyHash {
|
||||
fn hash(zelf: PyObjectRef) -> pyhash::PyHash {
|
||||
zelf.get_id() as pyhash::PyHash
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ impl PyBaseObject {
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(zelf: PyObjectRef, _vm: &VirtualMachine) -> String {
|
||||
fn repr(zelf: PyObjectRef) -> String {
|
||||
format!("<{} object at 0x{:x}>", zelf.class().name, zelf.get_id())
|
||||
}
|
||||
|
||||
@@ -175,12 +175,12 @@ impl PyBaseObject {
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__class__")]
|
||||
fn _class(obj: PyObjectRef, _vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn get_class(obj: PyObjectRef) -> PyObjectRef {
|
||||
obj.class().into_object()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "__class__", setter)]
|
||||
fn _set_class(instance: PyObjectRef, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
fn set_class(instance: PyObjectRef, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
let type_repr = vm.to_pystr(&instance.class())?;
|
||||
Err(vm.new_type_error(format!("can't change class of type '{}'", type_repr)))
|
||||
}
|
||||
|
||||
@@ -4,51 +4,13 @@
|
||||
use std::cell::RefCell;
|
||||
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::{IntoPyNativeFunc, OptionalArg};
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyClassImpl, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
TypeProtocol,
|
||||
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
|
||||
};
|
||||
use crate::slots::PyBuiltinDescriptor;
|
||||
use crate::slots::SlotDescriptor;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
// Read-only property, doesn't have __set__ or __delete__
|
||||
#[pyclass]
|
||||
#[derive(Debug)]
|
||||
pub struct PyReadOnlyProperty {
|
||||
getter: PyObjectRef,
|
||||
}
|
||||
|
||||
impl PyValue for PyReadOnlyProperty {
|
||||
fn class(vm: &VirtualMachine) -> PyClassRef {
|
||||
vm.ctx.readonly_property_type()
|
||||
}
|
||||
}
|
||||
|
||||
pub type PyReadOnlyPropertyRef = PyRef<PyReadOnlyProperty>;
|
||||
|
||||
impl PyBuiltinDescriptor for PyReadOnlyProperty {
|
||||
fn get(
|
||||
zelf: PyRef<Self>,
|
||||
obj: PyObjectRef,
|
||||
cls: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
if vm.is_none(&obj) {
|
||||
if Self::_cls_is(&cls, &vm.ctx.types.type_type) {
|
||||
vm.invoke(&zelf.getter, cls.unwrap())
|
||||
} else {
|
||||
Ok(zelf.into_object())
|
||||
}
|
||||
} else {
|
||||
vm.invoke(&zelf.getter, obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinDescriptor))]
|
||||
impl PyReadOnlyProperty {}
|
||||
|
||||
/// Property attribute.
|
||||
///
|
||||
/// fget
|
||||
@@ -110,26 +72,28 @@ struct PropertyArgs {
|
||||
doc: Option<PyObjectRef>,
|
||||
}
|
||||
|
||||
impl PyBuiltinDescriptor for PyProperty {
|
||||
fn get(
|
||||
zelf: PyRef<Self>,
|
||||
obj: PyObjectRef,
|
||||
_cls: OptionalArg<PyObjectRef>,
|
||||
impl SlotDescriptor for PyProperty {
|
||||
#[allow(clippy::collapsible_if)]
|
||||
fn descr_get(
|
||||
vm: &VirtualMachine,
|
||||
zelf: PyObjectRef,
|
||||
obj: Option<PyObjectRef>,
|
||||
_cls: OptionalArg<PyObjectRef>,
|
||||
) -> PyResult {
|
||||
if let Some(getter) = zelf.getter.as_ref() {
|
||||
if obj.is(vm.ctx.none.as_object()) {
|
||||
Ok(zelf.into_object())
|
||||
} else {
|
||||
vm.invoke(&getter, obj)
|
||||
}
|
||||
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
|
||||
if vm.is_none(&obj) {
|
||||
Ok(zelf.into_object())
|
||||
} else {
|
||||
Err(vm.new_attribute_error("unreadable attribute".to_string()))
|
||||
if let Some(getter) = zelf.getter.as_ref() {
|
||||
vm.invoke(&getter, obj)
|
||||
} else {
|
||||
Err(vm.new_attribute_error("unreadable attribute".to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinDescriptor), flags(BASETYPE))]
|
||||
#[pyimpl(with(SlotDescriptor), flags(BASETYPE))]
|
||||
impl PyProperty {
|
||||
#[pyslot]
|
||||
fn tp_new(cls: PyClassRef, args: PropertyArgs, vm: &VirtualMachine) -> PyResult<PyPropertyRef> {
|
||||
@@ -144,21 +108,12 @@ impl PyProperty {
|
||||
|
||||
// Descriptor methods
|
||||
|
||||
// specialised version that doesn't check for None
|
||||
pub(crate) fn instance_binding_get(&self, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if let Some(ref getter) = self.getter.as_ref() {
|
||||
vm.invoke(getter, obj)
|
||||
} else {
|
||||
Err(vm.new_attribute_error("unreadable attribute".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(name = "__set__")]
|
||||
fn set(&self, obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if let Some(ref setter) = self.setter.as_ref() {
|
||||
vm.invoke(setter, vec![obj, value])
|
||||
} else {
|
||||
Err(vm.new_attribute_error("can't set attribute".to_string()))
|
||||
Err(vm.new_attribute_error("can't set attribute".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,28 +122,28 @@ impl PyProperty {
|
||||
if let Some(ref deleter) = self.deleter.as_ref() {
|
||||
vm.invoke(deleter, obj)
|
||||
} else {
|
||||
Err(vm.new_attribute_error("can't delete attribute".to_string()))
|
||||
Err(vm.new_attribute_error("can't delete attribute".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
// Access functions
|
||||
|
||||
#[pyproperty]
|
||||
fn fget(&self, _vm: &VirtualMachine) -> Option<PyObjectRef> {
|
||||
fn fget(&self) -> Option<PyObjectRef> {
|
||||
self.getter.clone()
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn fset(&self, _vm: &VirtualMachine) -> Option<PyObjectRef> {
|
||||
fn fset(&self) -> Option<PyObjectRef> {
|
||||
self.setter.clone()
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn fdel(&self, _vm: &VirtualMachine) -> Option<PyObjectRef> {
|
||||
fn fdel(&self) -> Option<PyObjectRef> {
|
||||
self.deleter.clone()
|
||||
}
|
||||
|
||||
fn doc_getter(&self, _vm: &VirtualMachine) -> Option<PyObjectRef> {
|
||||
fn doc_getter(&self) -> Option<PyObjectRef> {
|
||||
self.doc.borrow().clone()
|
||||
}
|
||||
|
||||
@@ -253,81 +208,12 @@ fn py_none_to_option(vm: &VirtualMachine, value: &PyObjectRef) -> Option<PyObjec
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PropertyBuilder<'a> {
|
||||
ctx: &'a PyContext,
|
||||
getter: Option<PyObjectRef>,
|
||||
setter: Option<PyObjectRef>,
|
||||
}
|
||||
|
||||
pub trait PropertySetterResult {}
|
||||
|
||||
impl PropertySetterResult for PyResult<()> {}
|
||||
impl PropertySetterResult for () {}
|
||||
|
||||
impl<'a> PropertyBuilder<'a> {
|
||||
pub fn new(ctx: &'a PyContext) -> Self {
|
||||
Self {
|
||||
ctx,
|
||||
getter: None,
|
||||
setter: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_getter<I, V, VM, F: IntoPyNativeFunc<I, V, VM>>(self, func: F) -> Self {
|
||||
let func = self.ctx.new_method(func);
|
||||
Self {
|
||||
ctx: self.ctx,
|
||||
getter: Some(func),
|
||||
setter: self.setter,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_setter<I, V, VM, F: IntoPyNativeFunc<(I, V), impl PropertySetterResult, VM>>(
|
||||
self,
|
||||
func: F,
|
||||
) -> Self {
|
||||
let func = self.ctx.new_method(func);
|
||||
Self {
|
||||
ctx: self.ctx,
|
||||
getter: self.getter,
|
||||
setter: Some(func),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create(self) -> PyObjectRef {
|
||||
if self.setter.is_some() {
|
||||
let payload = PyProperty {
|
||||
getter: self.getter.clone(),
|
||||
setter: self.setter.clone(),
|
||||
deleter: None,
|
||||
doc: RefCell::new(None),
|
||||
};
|
||||
|
||||
PyObject::new(payload, self.ctx.property_type(), None)
|
||||
} else {
|
||||
let payload = PyReadOnlyProperty {
|
||||
getter: self.getter.expect(
|
||||
"One of add_getter/add_setter must be called when constructing a property",
|
||||
),
|
||||
};
|
||||
|
||||
PyObject::new(payload, self.ctx.readonly_property_type(), None)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
PyReadOnlyProperty::extend_class(context, &context.types.readonly_property_type);
|
||||
|
||||
pub(crate) fn init(context: &PyContext) {
|
||||
PyProperty::extend_class(context, &context.types.property_type);
|
||||
|
||||
// This is a bit unfortunate, but this instance attribute overlaps with the
|
||||
// class __doc__ string..
|
||||
extend_class!(context, &context.types.property_type, {
|
||||
"__doc__" =>
|
||||
PropertyBuilder::new(context)
|
||||
.add_getter(PyProperty::doc_getter)
|
||||
.add_setter(PyProperty::doc_setter)
|
||||
.create(),
|
||||
"__doc__" => context.new_getset("__doc__", PyProperty::doc_getter, PyProperty::doc_setter),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -148,28 +148,28 @@ impl PyRange {
|
||||
) -> PyResult<PyRangeRef> {
|
||||
let step = step.unwrap_or_else(|| PyInt::new(BigInt::one()).into_ref(vm));
|
||||
if step.as_bigint().is_zero() {
|
||||
return Err(vm.new_value_error("range() arg 3 must not be zero".to_string()));
|
||||
return Err(vm.new_value_error("range() arg 3 must not be zero".to_owned()));
|
||||
}
|
||||
PyRange { start, stop, step }.into_ref_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pyproperty(name = "start")]
|
||||
fn start(&self, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn start(&self) -> PyIntRef {
|
||||
self.start.clone()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "stop")]
|
||||
fn stop(&self, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn stop(&self) -> PyIntRef {
|
||||
self.stop.clone()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "step")]
|
||||
fn step(&self, _vm: &VirtualMachine) -> PyIntRef {
|
||||
fn step(&self) -> PyIntRef {
|
||||
self.step.clone()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRangeIterator {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRangeIterator {
|
||||
PyRangeIterator {
|
||||
position: Cell::new(0),
|
||||
range: zelf,
|
||||
@@ -210,12 +210,12 @@ impl PyRange {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> BigInt {
|
||||
fn len(&self) -> BigInt {
|
||||
self.length()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(&self, _vm: &VirtualMachine) -> String {
|
||||
fn repr(&self) -> String {
|
||||
if self.step.as_bigint().is_one() {
|
||||
format!("range({}, {})", self.start, self.stop)
|
||||
} else {
|
||||
@@ -224,12 +224,12 @@ impl PyRange {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn bool(&self) -> bool {
|
||||
!self.is_empty()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__contains__")]
|
||||
fn contains(&self, needle: PyObjectRef, _vm: &VirtualMachine) -> bool {
|
||||
fn contains(&self, needle: PyObjectRef) -> bool {
|
||||
if let Ok(int) = needle.downcast::<PyInt>() {
|
||||
match self.offset(int.as_bigint()) {
|
||||
Some(ref offset) => offset.is_multiple_of(self.step.as_bigint()),
|
||||
@@ -318,12 +318,12 @@ impl PyRange {
|
||||
None => Err(vm.new_value_error(format!("{} is not in range", int))),
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_value_error("sequence.index(x): x not in sequence".to_string()))
|
||||
Err(vm.new_value_error("sequence.index(x): x not in sequence".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(name = "count")]
|
||||
fn count(&self, item: PyObjectRef, _vm: &VirtualMachine) -> usize {
|
||||
fn count(&self, item: PyObjectRef) -> usize {
|
||||
if let Ok(int) = item.downcast::<PyInt>() {
|
||||
if self.index_of(int.as_bigint()).is_some() {
|
||||
1
|
||||
@@ -341,8 +341,8 @@ impl PyRange {
|
||||
RangeIndex::Slice(slice) => {
|
||||
let (mut substart, mut substop, mut substep) =
|
||||
slice.inner_indices(&self.length(), vm)?;
|
||||
let range_step = self.step(vm);
|
||||
let range_start = self.start(vm);
|
||||
let range_step = &self.step;
|
||||
let range_start = &self.start;
|
||||
|
||||
substep *= range_step.as_bigint();
|
||||
substart = (substart * range_step.as_bigint()) + range_start.as_bigint();
|
||||
@@ -358,7 +358,7 @@ impl PyRange {
|
||||
}
|
||||
RangeIndex::Int(index) => match self.get(index.as_bigint()) {
|
||||
Some(value) => Ok(PyInt::new(value).into_ref(vm).into_object()),
|
||||
None => Err(vm.new_index_error("range object index out of range".to_string())),
|
||||
None => Err(vm.new_index_error("range object index out of range".to_owned())),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -371,14 +371,14 @@ impl PyRange {
|
||||
} else if length.is_one() {
|
||||
vec![
|
||||
vm.ctx.new_int(length),
|
||||
zelf.start(vm).into_object(),
|
||||
zelf.start().into_object(),
|
||||
vm.get_none(),
|
||||
]
|
||||
} else {
|
||||
vec![
|
||||
vm.ctx.new_int(length),
|
||||
zelf.start(vm).into_object(),
|
||||
zelf.step(vm).into_object(),
|
||||
zelf.start().into_object(),
|
||||
zelf.step().into_object(),
|
||||
]
|
||||
};
|
||||
pyhash::hash_iter(elements.iter(), vm)
|
||||
@@ -427,7 +427,7 @@ impl PyRangeIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRangeIteratorRef {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRangeIteratorRef {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ pub trait PySliceableSequence {
|
||||
let stop = slice.stop_index(vm)?;
|
||||
let step = slice.step_index(vm)?.unwrap_or_else(BigInt::one);
|
||||
if step.is_zero() {
|
||||
Err(vm.new_value_error("slice step cannot be zero".to_string()))
|
||||
Err(vm.new_value_error("slice step cannot be zero".to_owned()))
|
||||
} else if step.is_positive() {
|
||||
let range = self.get_slice_range(&start, &stop);
|
||||
if range.start < range.end {
|
||||
@@ -182,7 +182,7 @@ pub fn get_sequence_index(vm: &VirtualMachine, index: &PyIntRef, length: usize)
|
||||
if value < 0 {
|
||||
let from_end: usize = -value as usize;
|
||||
if from_end > length {
|
||||
Err(vm.new_index_error("Index out of bounds!".to_string()))
|
||||
Err(vm.new_index_error("Index out of bounds!".to_owned()))
|
||||
} else {
|
||||
let index = length - from_end;
|
||||
Ok(index)
|
||||
@@ -190,13 +190,13 @@ pub fn get_sequence_index(vm: &VirtualMachine, index: &PyIntRef, length: usize)
|
||||
} else {
|
||||
let index = value as usize;
|
||||
if index >= length {
|
||||
Err(vm.new_index_error("Index out of bounds!".to_string()))
|
||||
Err(vm.new_index_error("Index out of bounds!".to_owned()))
|
||||
} else {
|
||||
Ok(index)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_index_error("cannot fit 'int' into an index-sized integer".to_string()))
|
||||
Err(vm.new_index_error("cannot fit 'int' into an index-sized integer".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,11 +213,11 @@ pub fn get_item(
|
||||
let obj = elements[pos_index].clone();
|
||||
Ok(obj)
|
||||
} else {
|
||||
Err(vm.new_index_error("Index out of bounds!".to_string()))
|
||||
Err(vm.new_index_error("Index out of bounds!".to_owned()))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
Err(vm.new_index_error("cannot fit 'int' into an index-sized integer".to_string()))
|
||||
Err(vm.new_index_error("cannot fit 'int' into an index-sized integer".to_owned()))
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -256,7 +256,7 @@ pub fn is_valid_slice_arg(
|
||||
i @ PyInt => Ok(Some(i.as_bigint().clone())),
|
||||
_obj @ PyNone => Ok(None),
|
||||
_ => Err(vm.new_type_error(
|
||||
"slice indices must be integers or None or have an __index__ method".to_string()
|
||||
"slice indices must be integers or None or have an __index__ method".to_owned()
|
||||
)), // TODO: check for an __index__ method
|
||||
})
|
||||
} else {
|
||||
@@ -277,10 +277,10 @@ pub fn opt_len(obj: &PyObjectRef, vm: &VirtualMachine) -> Option<PyResult<usize>
|
||||
})?
|
||||
.as_bigint();
|
||||
if len.is_negative() {
|
||||
return Err(vm.new_value_error("__len__() should return >= 0".to_string()));
|
||||
return Err(vm.new_value_error("__len__() should return >= 0".to_owned()));
|
||||
}
|
||||
len.to_usize().ok_or_else(|| {
|
||||
vm.new_overflow_error("cannot fit __len__() result into usize".to_string())
|
||||
vm.new_overflow_error("cannot fit __len__() result into usize".to_owned())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ impl PySetInner {
|
||||
if let Some((key, _)) = self.content.pop_front() {
|
||||
Ok(key)
|
||||
} else {
|
||||
let err_msg = vm.new_str("pop from an empty set".to_string());
|
||||
let err_msg = vm.new_str("pop from an empty set".to_owned());
|
||||
Err(vm.new_key_error(err_msg))
|
||||
}
|
||||
}
|
||||
@@ -343,17 +343,17 @@ impl PySet {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(&self) -> usize {
|
||||
self.inner.borrow().len()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn sizeof(&self) -> usize {
|
||||
std::mem::size_of::<Self>() + self.inner.borrow().sizeof()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn copy(&self, _vm: &VirtualMachine) -> Self {
|
||||
fn copy(&self) -> Self {
|
||||
Self {
|
||||
inner: RefCell::new(self.inner.borrow().copy()),
|
||||
}
|
||||
@@ -486,11 +486,11 @@ impl PySet {
|
||||
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let inner = zelf.inner.borrow();
|
||||
let s = if inner.len() == 0 {
|
||||
"set()".to_string()
|
||||
"set()".to_owned()
|
||||
} else if let Some(_guard) = ReprGuard::enter(zelf.as_object()) {
|
||||
inner.repr(vm)?
|
||||
} else {
|
||||
"set(...)".to_string()
|
||||
"set(...)".to_owned()
|
||||
};
|
||||
Ok(vm.new_str(s))
|
||||
}
|
||||
@@ -513,7 +513,7 @@ impl PySet {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn clear(&self, _vm: &VirtualMachine) {
|
||||
fn clear(&self) {
|
||||
self.inner.borrow_mut().clear()
|
||||
}
|
||||
|
||||
@@ -580,7 +580,7 @@ impl PySet {
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
fn hash(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Err(vm.new_type_error("unhashable type".to_string()))
|
||||
Err(vm.new_type_error("unhashable type".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,17 +599,17 @@ impl PyFrozenSet {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn sizeof(&self) -> usize {
|
||||
std::mem::size_of::<Self>() + self.inner.sizeof()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn copy(&self, _vm: &VirtualMachine) -> Self {
|
||||
fn copy(&self) -> Self {
|
||||
Self {
|
||||
inner: self.inner.copy(),
|
||||
}
|
||||
@@ -742,11 +742,11 @@ impl PyFrozenSet {
|
||||
fn repr(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult {
|
||||
let inner = &zelf.inner;
|
||||
let s = if inner.len() == 0 {
|
||||
"frozenset()".to_string()
|
||||
"frozenset()".to_owned()
|
||||
} else if let Some(_guard) = ReprGuard::enter(zelf.as_object()) {
|
||||
format!("frozenset({})", inner.repr(vm)?)
|
||||
} else {
|
||||
"frozenset(...)".to_string()
|
||||
"frozenset(...)".to_owned()
|
||||
};
|
||||
Ok(vm.new_str(s))
|
||||
}
|
||||
|
||||
@@ -51,14 +51,14 @@ impl PySlice {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(&self, _vm: &VirtualMachine) -> PyResult<String> {
|
||||
let start = self.start(_vm);
|
||||
let stop = self.stop(_vm);
|
||||
let step = self.step(_vm);
|
||||
fn repr(&self, vm: &VirtualMachine) -> PyResult<String> {
|
||||
let start = self.start(vm);
|
||||
let stop = self.stop(vm);
|
||||
let step = self.step(vm);
|
||||
|
||||
let start_repr = _vm.to_repr(&start)?;
|
||||
let stop_repr = _vm.to_repr(&stop)?;
|
||||
let step_repr = _vm.to_repr(&step)?;
|
||||
let start_repr = vm.to_repr(&start)?;
|
||||
let stop_repr = vm.to_repr(&stop)?;
|
||||
let step_repr = vm.to_repr(&step)?;
|
||||
|
||||
Ok(format!(
|
||||
"slice({}, {}, {})",
|
||||
@@ -302,7 +302,7 @@ impl PySlice {
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
fn hash(&self, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Err(vm.new_type_error("unhashable type".to_string()))
|
||||
Err(vm.new_type_error("unhashable type".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "indices")]
|
||||
@@ -332,11 +332,11 @@ fn to_index_value(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Option<Big
|
||||
if let Some(val) = index_result.payload::<PyInt>() {
|
||||
Ok(Some(val.as_bigint().clone()))
|
||||
} else {
|
||||
Err(vm.new_type_error("__index__ method returned non integer".to_string()))
|
||||
Err(vm.new_type_error("__index__ method returned non integer".to_owned()))
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_type_error(
|
||||
"slice indices must be integers or None or have an __index__ method".to_string(),
|
||||
"slice indices must be integers or None or have an __index__ method".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::slots::PyBuiltinDescriptor;
|
||||
use crate::slots::SlotDescriptor;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "staticmethod")]
|
||||
@@ -17,18 +17,19 @@ impl PyValue for PyStaticMethod {
|
||||
}
|
||||
}
|
||||
|
||||
impl PyBuiltinDescriptor for PyStaticMethod {
|
||||
fn get(
|
||||
zelf: PyRef<Self>,
|
||||
_obj: PyObjectRef,
|
||||
impl SlotDescriptor for PyStaticMethod {
|
||||
fn descr_get(
|
||||
vm: &VirtualMachine,
|
||||
zelf: PyObjectRef,
|
||||
_obj: Option<PyObjectRef>,
|
||||
_cls: OptionalArg<PyObjectRef>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
let zelf = Self::_zelf(zelf, vm)?;
|
||||
Ok(zelf.callable.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinDescriptor), flags(BASETYPE))]
|
||||
#[pyimpl(with(SlotDescriptor), flags(BASETYPE))]
|
||||
impl PyStaticMethod {
|
||||
#[pyslot]
|
||||
fn tp_new(
|
||||
|
||||
@@ -61,7 +61,7 @@ impl PyString {
|
||||
|
||||
impl From<&str> for PyString {
|
||||
fn from(s: &str) -> PyString {
|
||||
s.to_string().into()
|
||||
s.to_owned().into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ impl PyStringIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -163,7 +163,7 @@ impl PyStringReverseIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn bool(&self) -> bool {
|
||||
!self.value.is_empty()
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__contains__")]
|
||||
fn contains(&self, needle: PyStringRef, _vm: &VirtualMachine) -> bool {
|
||||
fn contains(&self, needle: PyStringRef) -> bool {
|
||||
self.value.contains(&needle.value)
|
||||
}
|
||||
|
||||
@@ -266,17 +266,18 @@ impl PyString {
|
||||
if let Some(character) = self.value.chars().nth(index) {
|
||||
Ok(vm.new_str(character.to_string()))
|
||||
} else {
|
||||
Err(vm.new_index_error("string index out of range".to_string()))
|
||||
Err(vm.new_index_error("string index out of range".to_owned()))
|
||||
}
|
||||
}
|
||||
None => Err(
|
||||
vm.new_index_error("cannot fit 'int' into an index-sized integer".to_string())
|
||||
),
|
||||
None => {
|
||||
Err(vm
|
||||
.new_index_error("cannot fit 'int' into an index-sized integer".to_owned()))
|
||||
}
|
||||
},
|
||||
Either::B(slice) => {
|
||||
let string = self
|
||||
.value
|
||||
.to_string()
|
||||
.to_owned()
|
||||
.get_slice_items(vm, slice.as_object())?;
|
||||
Ok(vm.new_str(string))
|
||||
}
|
||||
@@ -284,27 +285,27 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__gt__")]
|
||||
fn gt(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool {
|
||||
fn gt(&self, other: PyStringRef) -> bool {
|
||||
self.value > other.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__ge__")]
|
||||
fn ge(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool {
|
||||
fn ge(&self, other: PyStringRef) -> bool {
|
||||
self.value >= other.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__lt__")]
|
||||
fn lt(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool {
|
||||
fn lt(&self, other: PyStringRef) -> bool {
|
||||
self.value < other.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__le__")]
|
||||
fn le(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool {
|
||||
fn le(&self, other: PyStringRef) -> bool {
|
||||
self.value <= other.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
fn hash(&self, _vm: &VirtualMachine) -> pyhash::PyHash {
|
||||
fn hash(&self) -> pyhash::PyHash {
|
||||
match self.hash.get() {
|
||||
Some(hash) => hash,
|
||||
None => {
|
||||
@@ -316,12 +317,12 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(&self) -> usize {
|
||||
self.value.chars().count()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__sizeof__")]
|
||||
fn sizeof(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn sizeof(&self) -> usize {
|
||||
size_of::<Self>() + self.value.capacity() * size_of::<u8>()
|
||||
}
|
||||
|
||||
@@ -332,7 +333,7 @@ impl PyString {
|
||||
.to_usize()
|
||||
.map(|multiplier| self.value.repeat(multiplier))
|
||||
.ok_or_else(|| {
|
||||
vm.new_overflow_error("cannot fit 'int' into an index-sized integer".to_string())
|
||||
vm.new_overflow_error("cannot fit 'int' into an index-sized integer".to_owned())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -342,12 +343,12 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__str__")]
|
||||
fn str(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyStringRef {
|
||||
fn str(zelf: PyRef<Self>) -> PyStringRef {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(&self, _vm: &VirtualMachine) -> String {
|
||||
fn repr(&self) -> String {
|
||||
let value = &self.value;
|
||||
let quote_char = if count_char(value, '\'') > count_char(value, '"') {
|
||||
'"'
|
||||
@@ -389,23 +390,23 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn lower(&self, _vm: &VirtualMachine) -> String {
|
||||
fn lower(&self) -> String {
|
||||
self.value.to_lowercase()
|
||||
}
|
||||
|
||||
// casefold is much more aggressive than lower
|
||||
#[pymethod]
|
||||
fn casefold(&self, _vm: &VirtualMachine) -> String {
|
||||
fn casefold(&self) -> String {
|
||||
caseless::default_case_fold_str(&self.value)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn upper(&self, _vm: &VirtualMachine) -> String {
|
||||
fn upper(&self) -> String {
|
||||
self.value.to_uppercase()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn capitalize(&self, _vm: &VirtualMachine) -> String {
|
||||
fn capitalize(&self) -> String {
|
||||
let (first_part, lower_str) = self.value.split_at(1);
|
||||
format!("{}{}", first_part.to_uppercase(), lower_str)
|
||||
}
|
||||
@@ -418,21 +419,21 @@ impl PyString {
|
||||
let elements: Vec<_> = match (pattern, num_splits.is_negative()) {
|
||||
(Some(pattern), true) => value
|
||||
.split(pattern)
|
||||
.map(|o| vm.ctx.new_str(o.to_string()))
|
||||
.map(|o| vm.ctx.new_str(o.to_owned()))
|
||||
.collect(),
|
||||
(Some(pattern), false) => value
|
||||
.splitn(num_splits as usize + 1, pattern)
|
||||
.map(|o| vm.ctx.new_str(o.to_string()))
|
||||
.map(|o| vm.ctx.new_str(o.to_owned()))
|
||||
.collect(),
|
||||
(None, true) => value
|
||||
.split(|c: char| c.is_ascii_whitespace())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|o| vm.ctx.new_str(o.to_string()))
|
||||
.map(|o| vm.ctx.new_str(o.to_owned()))
|
||||
.collect(),
|
||||
(None, false) => value
|
||||
.splitn(num_splits as usize + 1, |c: char| c.is_ascii_whitespace())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|o| vm.ctx.new_str(o.to_string()))
|
||||
.map(|o| vm.ctx.new_str(o.to_owned()))
|
||||
.collect(),
|
||||
};
|
||||
vm.ctx.new_list(elements)
|
||||
@@ -446,21 +447,21 @@ impl PyString {
|
||||
let mut elements: Vec<_> = match (pattern, num_splits.is_negative()) {
|
||||
(Some(pattern), true) => value
|
||||
.rsplit(pattern)
|
||||
.map(|o| vm.ctx.new_str(o.to_string()))
|
||||
.map(|o| vm.ctx.new_str(o.to_owned()))
|
||||
.collect(),
|
||||
(Some(pattern), false) => value
|
||||
.rsplitn(num_splits as usize + 1, pattern)
|
||||
.map(|o| vm.ctx.new_str(o.to_string()))
|
||||
.map(|o| vm.ctx.new_str(o.to_owned()))
|
||||
.collect(),
|
||||
(None, true) => value
|
||||
.rsplit(|c: char| c.is_ascii_whitespace())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|o| vm.ctx.new_str(o.to_string()))
|
||||
.map(|o| vm.ctx.new_str(o.to_owned()))
|
||||
.collect(),
|
||||
(None, false) => value
|
||||
.rsplitn(num_splits as usize + 1, |c: char| c.is_ascii_whitespace())
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(|o| vm.ctx.new_str(o.to_string()))
|
||||
.map(|o| vm.ctx.new_str(o.to_owned()))
|
||||
.collect(),
|
||||
};
|
||||
// Unlike Python rsplit, Rust rsplitn returns an iterator that
|
||||
@@ -470,34 +471,34 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn strip(&self, chars: OptionalArg<PyStringRef>, _vm: &VirtualMachine) -> String {
|
||||
fn strip(&self, chars: OptionalArg<PyStringRef>) -> String {
|
||||
let chars = match chars {
|
||||
OptionalArg::Present(ref chars) => &chars.value,
|
||||
OptionalArg::Missing => return self.value.trim().to_string(),
|
||||
OptionalArg::Missing => return self.value.trim().to_owned(),
|
||||
};
|
||||
self.value.trim_matches(|c| chars.contains(c)).to_string()
|
||||
self.value.trim_matches(|c| chars.contains(c)).to_owned()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn lstrip(&self, chars: OptionalArg<PyStringRef>, _vm: &VirtualMachine) -> String {
|
||||
fn lstrip(&self, chars: OptionalArg<PyStringRef>) -> String {
|
||||
let chars = match chars {
|
||||
OptionalArg::Present(ref chars) => &chars.value,
|
||||
OptionalArg::Missing => return self.value.trim_start().to_string(),
|
||||
OptionalArg::Missing => return self.value.trim_start().to_owned(),
|
||||
};
|
||||
self.value
|
||||
.trim_start_matches(|c| chars.contains(c))
|
||||
.to_string()
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn rstrip(&self, chars: OptionalArg<PyStringRef>, _vm: &VirtualMachine) -> String {
|
||||
fn rstrip(&self, chars: OptionalArg<PyStringRef>) -> String {
|
||||
let chars = match chars {
|
||||
OptionalArg::Present(ref chars) => &chars.value,
|
||||
OptionalArg::Missing => return self.value.trim_end().to_string(),
|
||||
OptionalArg::Missing => return self.value.trim_end().to_owned(),
|
||||
};
|
||||
self.value
|
||||
.trim_end_matches(|c| chars.contains(c))
|
||||
.to_string()
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -553,17 +554,17 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn isalnum(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isalnum(&self) -> bool {
|
||||
!self.value.is_empty() && self.value.chars().all(char::is_alphanumeric)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn isnumeric(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isnumeric(&self) -> bool {
|
||||
!self.value.is_empty() && self.value.chars().all(char::is_numeric)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn isdigit(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isdigit(&self) -> bool {
|
||||
// python's isdigit also checks if exponents are digits, these are the unicodes for exponents
|
||||
let valid_unicodes: [u16; 10] = [
|
||||
0x2070, 0x00B9, 0x00B2, 0x00B3, 0x2074, 0x2075, 0x2076, 0x2077, 0x2078, 0x2079,
|
||||
@@ -580,7 +581,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn isdecimal(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isdecimal(&self) -> bool {
|
||||
if self.value.is_empty() {
|
||||
false
|
||||
} else {
|
||||
@@ -605,7 +606,7 @@ impl PyString {
|
||||
fn format(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
if args.args.is_empty() {
|
||||
return Err(vm.new_type_error(
|
||||
"descriptor 'format' of 'str' object needs an argument".to_string(),
|
||||
"descriptor 'format' of 'str' object needs an argument".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -623,9 +624,9 @@ impl PyString {
|
||||
Ok(format_string) => perform_format(vm, &format_string, &args),
|
||||
Err(err) => match err {
|
||||
FormatParseError::UnmatchedBracket => {
|
||||
Err(vm.new_value_error("expected '}' before end of string".to_string()))
|
||||
Err(vm.new_value_error("expected '}' before end of string".to_owned()))
|
||||
}
|
||||
_ => Err(vm.new_value_error("Unexpected error parsing format string".to_string())),
|
||||
_ => Err(vm.new_value_error("Unexpected error parsing format string".to_owned())),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -649,9 +650,9 @@ impl PyString {
|
||||
Ok(format_string) => perform_format_map(vm, &format_string, &args.args[1]),
|
||||
Err(err) => match err {
|
||||
FormatParseError::UnmatchedBracket => {
|
||||
Err(vm.new_value_error("expected '}' before end of string".to_string()))
|
||||
Err(vm.new_value_error("expected '}' before end of string".to_owned()))
|
||||
}
|
||||
_ => Err(vm.new_value_error("Unexpected error parsing format string".to_string())),
|
||||
_ => Err(vm.new_value_error("Unexpected error parsing format string".to_owned())),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -659,7 +660,7 @@ impl PyString {
|
||||
/// Return a titlecased version of the string where words start with an
|
||||
/// uppercase character and the remaining characters are lowercase.
|
||||
#[pymethod]
|
||||
fn title(&self, _vm: &VirtualMachine) -> String {
|
||||
fn title(&self) -> String {
|
||||
let mut title = String::with_capacity(self.value.len());
|
||||
let mut previous_is_cased = false;
|
||||
for c in self.value.chars() {
|
||||
@@ -686,7 +687,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn swapcase(&self, _vm: &VirtualMachine) -> String {
|
||||
fn swapcase(&self) -> String {
|
||||
let mut swapped_str = String::with_capacity(self.value.len());
|
||||
for c in self.value.chars() {
|
||||
// to_uppercase returns an iterator, to_ascii_uppercase returns the char
|
||||
@@ -702,18 +703,12 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn isalpha(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isalpha(&self) -> bool {
|
||||
!self.value.is_empty() && self.value.chars().all(char::is_alphanumeric)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn replace(
|
||||
&self,
|
||||
old: PyStringRef,
|
||||
new: PyStringRef,
|
||||
num: OptionalArg<usize>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> String {
|
||||
fn replace(&self, old: PyStringRef, new: PyStringRef, num: OptionalArg<usize>) -> String {
|
||||
match num.into_option() {
|
||||
Some(num) => self.value.replacen(&old.value, &new.value, num),
|
||||
None => self.value.replace(&old.value, &new.value),
|
||||
@@ -736,7 +731,7 @@ impl PyString {
|
||||
/// * Zp Separator, Paragraph ('\u2029', PARAGRAPH SEPARATOR)
|
||||
/// * Zs (Separator, Space) other than ASCII space('\x20').
|
||||
#[pymethod]
|
||||
fn isprintable(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isprintable(&self) -> bool {
|
||||
self.value
|
||||
.chars()
|
||||
.all(|c| c == '\u{0020}' || char_is_printable(c))
|
||||
@@ -745,13 +740,13 @@ impl PyString {
|
||||
// cpython's isspace ignores whitespace, including \t and \n, etc, unless the whole string is empty
|
||||
// which is why isspace is using is_ascii_whitespace. Same for isupper & islower
|
||||
#[pymethod]
|
||||
fn isspace(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isspace(&self) -> bool {
|
||||
!self.value.is_empty() && self.value.chars().all(|c| c.is_ascii_whitespace())
|
||||
}
|
||||
|
||||
// Return true if all cased characters in the string are uppercase and there is at least one cased character, false otherwise.
|
||||
#[pymethod]
|
||||
fn isupper(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isupper(&self) -> bool {
|
||||
let mut cased = false;
|
||||
for c in self.value.chars() {
|
||||
if is_cased(c) && c.is_uppercase() {
|
||||
@@ -765,7 +760,7 @@ impl PyString {
|
||||
|
||||
// Return true if all cased characters in the string are lowercase and there is at least one cased character, false otherwise.
|
||||
#[pymethod]
|
||||
fn islower(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn islower(&self) -> bool {
|
||||
let mut cased = false;
|
||||
for c in self.value.chars() {
|
||||
if is_cased(c) && c.is_lowercase() {
|
||||
@@ -778,7 +773,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn isascii(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isascii(&self) -> bool {
|
||||
!self.value.is_empty() && self.value.chars().all(|c| c.is_ascii())
|
||||
}
|
||||
|
||||
@@ -786,7 +781,7 @@ impl PyString {
|
||||
fn splitlines(&self, args: SplitLineArgs, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let keepends = args.keepends.unwrap_or(false);
|
||||
let mut elements = vec![];
|
||||
let mut curr = "".to_string();
|
||||
let mut curr = "".to_owned();
|
||||
for ch in self.value.chars() {
|
||||
if ch == '\n' {
|
||||
if keepends {
|
||||
@@ -820,13 +815,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn find(
|
||||
&self,
|
||||
sub: PyStringRef,
|
||||
start: OptionalArg<isize>,
|
||||
end: OptionalArg<isize>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> isize {
|
||||
fn find(&self, sub: PyStringRef, start: OptionalArg<isize>, end: OptionalArg<isize>) -> isize {
|
||||
let value = &self.value;
|
||||
if let Some((start, end)) = adjust_indices(start, end, value.len()) {
|
||||
match value[start..end].find(&sub.value) {
|
||||
@@ -839,13 +828,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn rfind(
|
||||
&self,
|
||||
sub: PyStringRef,
|
||||
start: OptionalArg<isize>,
|
||||
end: OptionalArg<isize>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> isize {
|
||||
fn rfind(&self, sub: PyStringRef, start: OptionalArg<isize>, end: OptionalArg<isize>) -> isize {
|
||||
let value = &self.value;
|
||||
if let Some((start, end)) = adjust_indices(start, end, value.len()) {
|
||||
match value[start..end].rfind(&sub.value) {
|
||||
@@ -869,10 +852,10 @@ impl PyString {
|
||||
if let Some((start, end)) = adjust_indices(start, end, value.len()) {
|
||||
match value[start..end].find(&sub.value) {
|
||||
Some(num) => Ok(start + num),
|
||||
None => Err(vm.new_value_error("substring not found".to_string())),
|
||||
None => Err(vm.new_value_error("substring not found".to_owned())),
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_value_error("substring not found".to_string()))
|
||||
Err(vm.new_value_error("substring not found".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,10 +871,10 @@ impl PyString {
|
||||
if let Some((start, end)) = adjust_indices(start, end, value.len()) {
|
||||
match value[start..end].rfind(&sub.value) {
|
||||
Some(num) => Ok(start + num),
|
||||
None => Err(vm.new_value_error("substring not found".to_string())),
|
||||
None => Err(vm.new_value_error("substring not found".to_owned())),
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_value_error("substring not found".to_string()))
|
||||
Err(vm.new_value_error("substring not found".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -903,13 +886,13 @@ impl PyString {
|
||||
if value.contains(sub) {
|
||||
new_tup = value
|
||||
.splitn(2, sub)
|
||||
.map(|s| vm.ctx.new_str(s.to_string()))
|
||||
.map(|s| vm.ctx.new_str(s.to_owned()))
|
||||
.collect();
|
||||
new_tup.insert(1, vm.ctx.new_str(sub.clone()));
|
||||
} else {
|
||||
new_tup.push(vm.ctx.new_str(value.clone()));
|
||||
new_tup.push(vm.ctx.new_str("".to_string()));
|
||||
new_tup.push(vm.ctx.new_str("".to_string()));
|
||||
new_tup.push(vm.ctx.new_str("".to_owned()));
|
||||
new_tup.push(vm.ctx.new_str("".to_owned()));
|
||||
}
|
||||
vm.ctx.new_tuple(new_tup)
|
||||
}
|
||||
@@ -922,13 +905,13 @@ impl PyString {
|
||||
if value.contains(sub) {
|
||||
new_tup = value
|
||||
.rsplitn(2, sub)
|
||||
.map(|s| vm.ctx.new_str(s.to_string()))
|
||||
.map(|s| vm.ctx.new_str(s.to_owned()))
|
||||
.collect();
|
||||
new_tup.swap(0, 1); // so it's in the right order
|
||||
new_tup.insert(1, vm.ctx.new_str(sub.clone()));
|
||||
} else {
|
||||
new_tup.push(vm.ctx.new_str("".to_string()));
|
||||
new_tup.push(vm.ctx.new_str("".to_string()));
|
||||
new_tup.push(vm.ctx.new_str("".to_owned()));
|
||||
new_tup.push(vm.ctx.new_str("".to_owned()));
|
||||
new_tup.push(vm.ctx.new_str(value.clone()));
|
||||
}
|
||||
vm.ctx.new_tuple(new_tup)
|
||||
@@ -937,7 +920,7 @@ impl PyString {
|
||||
/// Return `true` if the sequence is ASCII titlecase and the sequence is not
|
||||
/// empty, `false` otherwise.
|
||||
#[pymethod]
|
||||
fn istitle(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn istitle(&self) -> bool {
|
||||
if self.value.is_empty() {
|
||||
return false;
|
||||
}
|
||||
@@ -965,13 +948,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn count(
|
||||
&self,
|
||||
sub: PyStringRef,
|
||||
start: OptionalArg<isize>,
|
||||
end: OptionalArg<isize>,
|
||||
_vm: &VirtualMachine,
|
||||
) -> usize {
|
||||
fn count(&self, sub: PyStringRef, start: OptionalArg<isize>, end: OptionalArg<isize>) -> usize {
|
||||
let value = &self.value;
|
||||
if let Some((start, end)) = adjust_indices(start, end, value.len()) {
|
||||
self.value[start..end].matches(&sub.value).count()
|
||||
@@ -981,10 +958,10 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn zfill(&self, len: usize, _vm: &VirtualMachine) -> String {
|
||||
fn zfill(&self, len: usize) -> String {
|
||||
let value = &self.value;
|
||||
if len <= value.len() {
|
||||
value.to_string()
|
||||
value.to_owned()
|
||||
} else {
|
||||
format!("{}{}", "0".repeat(len - value.len()), value)
|
||||
}
|
||||
@@ -1001,9 +978,8 @@ impl PyString {
|
||||
if rep_str.len() == 1 {
|
||||
Ok(rep_str)
|
||||
} else {
|
||||
Err(vm.new_type_error(
|
||||
"The fill character must be exactly one character long".to_string(),
|
||||
))
|
||||
Err(vm
|
||||
.new_type_error("The fill character must be exactly one character long".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1017,7 +993,7 @@ impl PyString {
|
||||
let value = &self.value;
|
||||
let rep_char = Self::get_fill_char(&rep, vm)?;
|
||||
if len <= value.len() {
|
||||
Ok(value.to_string())
|
||||
Ok(value.to_owned())
|
||||
} else {
|
||||
Ok(format!("{}{}", value, rep_char.repeat(len - value.len())))
|
||||
}
|
||||
@@ -1033,7 +1009,7 @@ impl PyString {
|
||||
let value = &self.value;
|
||||
let rep_char = Self::get_fill_char(&rep, vm)?;
|
||||
if len <= value.len() {
|
||||
Ok(value.to_string())
|
||||
Ok(value.to_owned())
|
||||
} else {
|
||||
Ok(format!("{}{}", rep_char.repeat(len - value.len()), value))
|
||||
}
|
||||
@@ -1051,7 +1027,7 @@ impl PyString {
|
||||
let value_len = self.value.chars().count();
|
||||
|
||||
if len <= value_len {
|
||||
return Ok(value.to_string());
|
||||
return Ok(value.to_owned());
|
||||
}
|
||||
let diff: usize = len - value_len;
|
||||
let mut left_buff: usize = diff / 2;
|
||||
@@ -1073,7 +1049,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn expandtabs(&self, tab_stop: OptionalArg<usize>, _vm: &VirtualMachine) -> String {
|
||||
fn expandtabs(&self, tab_stop: OptionalArg<usize>) -> String {
|
||||
let tab_stop = tab_stop.into_option().unwrap_or(8 as usize);
|
||||
let mut expanded_str = String::with_capacity(self.value.len());
|
||||
let mut tab_size = tab_stop;
|
||||
@@ -1097,7 +1073,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn isidentifier(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn isidentifier(&self) -> bool {
|
||||
let mut chars = self.value.chars();
|
||||
let is_identifier_start = chars.next().map_or(false, |c| c == '_' || is_xid_start(c));
|
||||
// a string is not an identifier if it has whitespace or starts with a number
|
||||
@@ -1151,7 +1127,7 @@ impl PyString {
|
||||
if let OptionalArg::Present(to_str) = to_str {
|
||||
match dict_or_str.downcast::<PyString>() {
|
||||
Ok(from_str) => {
|
||||
if to_str.len(vm) == from_str.len(vm) {
|
||||
if to_str.len() == from_str.len() {
|
||||
for (c1, c2) in from_str.value.chars().zip(to_str.value.chars()) {
|
||||
new_dict.set_item(&vm.new_int(c1 as u32), vm.new_int(c2 as u32), vm)?;
|
||||
}
|
||||
@@ -1184,7 +1160,7 @@ impl PyString {
|
||||
vm,
|
||||
)?;
|
||||
} else if let Some(string) = key.payload::<PyString>() {
|
||||
if string.len(vm) == 1 {
|
||||
if string.len() == 1 {
|
||||
let num_value = string.value.chars().next().unwrap() as u32;
|
||||
new_dict.set_item(&num_value.into_pyobject(vm)?, val, vm)?;
|
||||
} else {
|
||||
@@ -1214,7 +1190,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyStringIterator {
|
||||
fn iter(zelf: PyRef<Self>) -> PyStringIterator {
|
||||
PyStringIterator {
|
||||
byte_position: Cell::new(0),
|
||||
string: zelf,
|
||||
@@ -1222,7 +1198,7 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__reversed__")]
|
||||
fn reversed(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyStringReverseIterator {
|
||||
fn reversed(zelf: PyRef<Self>) -> PyStringReverseIterator {
|
||||
let begin = zelf.value.chars().count();
|
||||
|
||||
PyStringReverseIterator {
|
||||
@@ -1264,7 +1240,7 @@ impl IntoPyObject for String {
|
||||
|
||||
impl IntoPyObject for &str {
|
||||
fn into_pyobject(self, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.ctx.new_str(self.to_string()))
|
||||
Ok(vm.ctx.new_str(self.to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1314,7 +1290,7 @@ fn call_object_format(vm: &VirtualMachine, argument: PyObjectRef, format_spec: &
|
||||
Some(FormatPreconversor::Bytes) => vm.call_method(&argument, "decode", vec![])?,
|
||||
None => argument,
|
||||
};
|
||||
let returned_type = vm.ctx.new_str(new_format_spec.to_string());
|
||||
let returned_type = vm.ctx.new_str(new_format_spec.to_owned());
|
||||
|
||||
let result = vm.call_method(&argument, "__format__", vec![returned_type])?;
|
||||
if !objtype::isinstance(&result, &vm.ctx.str_type()) {
|
||||
@@ -1381,20 +1357,20 @@ fn do_cformat_specifier(
|
||||
match objint::get_value(&obj).to_u32().and_then(char::from_u32) {
|
||||
Some(value) => Ok(value.to_string()),
|
||||
None => {
|
||||
Err(vm.new_overflow_error("%c arg not in range(0x110000)".to_string()))
|
||||
Err(vm.new_overflow_error("%c arg not in range(0x110000)".to_owned()))
|
||||
}
|
||||
}
|
||||
} else if objtype::isinstance(&obj, &vm.ctx.str_type()) {
|
||||
let s = borrow_value(&obj);
|
||||
let num_chars = s.chars().count();
|
||||
if num_chars != 1 {
|
||||
Err(vm.new_type_error("%c requires int or char".to_string()))
|
||||
Err(vm.new_type_error("%c requires int or char".to_owned()))
|
||||
} else {
|
||||
Ok(s.chars().next().unwrap().to_string())
|
||||
}
|
||||
} else {
|
||||
// TODO re-arrange this block so this error is only created once
|
||||
Err(vm.new_type_error("%c requires int or char".to_string()))
|
||||
Err(vm.new_type_error("%c requires int or char".to_owned()))
|
||||
}
|
||||
}?;
|
||||
format_spec.precision = Some(CFormatQuantity::Amount(1));
|
||||
@@ -1415,7 +1391,7 @@ fn try_update_quantity_from_tuple(
|
||||
Some(width_obj) => {
|
||||
tuple_index += 1;
|
||||
if !objtype::isinstance(&width_obj, &vm.ctx.int_type()) {
|
||||
Err(vm.new_type_error("* wants int".to_string()))
|
||||
Err(vm.new_type_error("* wants int".to_owned()))
|
||||
} else {
|
||||
// TODO: handle errors when truncating BigInt to usize
|
||||
*q = Some(CFormatQuantity::Amount(
|
||||
@@ -1424,9 +1400,7 @@ fn try_update_quantity_from_tuple(
|
||||
Ok(tuple_index)
|
||||
}
|
||||
}
|
||||
None => {
|
||||
Err(vm.new_type_error("not enough arguments for format string".to_string()))
|
||||
}
|
||||
None => Err(vm.new_type_error("not enough arguments for format string".to_owned())),
|
||||
}
|
||||
}
|
||||
_ => Ok(tuple_index),
|
||||
@@ -1456,7 +1430,7 @@ pub fn do_cformat_string(
|
||||
|
||||
let values = if mapping_required {
|
||||
if !objtype::isinstance(&values_obj, &vm.ctx.dict_type()) {
|
||||
return Err(vm.new_type_error("format requires a mapping".to_string()));
|
||||
return Err(vm.new_type_error("format requires a mapping".to_owned()));
|
||||
}
|
||||
values_obj.clone()
|
||||
} else {
|
||||
@@ -1467,7 +1441,7 @@ pub fn do_cformat_string(
|
||||
&& !objtype::isinstance(&values_obj, &vm.ctx.types.dict_type)
|
||||
{
|
||||
return Err(vm.new_type_error(
|
||||
"not all arguments converted during string formatting".to_string(),
|
||||
"not all arguments converted during string formatting".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1487,7 +1461,7 @@ pub fn do_cformat_string(
|
||||
let obj: PyObjectRef = match &format_spec.mapping_key {
|
||||
Some(key) => {
|
||||
// TODO: change the KeyError message to match the one in cpython
|
||||
call_getitem(vm, &values, &vm.ctx.new_str(key.to_string()))?
|
||||
call_getitem(vm, &values, &vm.ctx.new_str(key.to_owned()))?
|
||||
}
|
||||
None => {
|
||||
let mut elements = objtuple::get_value(&values)
|
||||
@@ -1511,7 +1485,7 @@ pub fn do_cformat_string(
|
||||
let obj = match elements.next() {
|
||||
Some(obj) => Ok(obj),
|
||||
None => Err(vm.new_type_error(
|
||||
"not enough arguments for format string".to_string(),
|
||||
"not enough arguments for format string".to_owned(),
|
||||
)),
|
||||
}?;
|
||||
tuple_index += 1;
|
||||
@@ -1531,7 +1505,7 @@ pub fn do_cformat_string(
|
||||
&& !objtype::isinstance(&values_obj, &vm.ctx.types.dict_type)
|
||||
{
|
||||
return Err(
|
||||
vm.new_type_error("not all arguments converted during string formatting".to_string())
|
||||
vm.new_type_error("not all arguments converted during string formatting".to_owned())
|
||||
);
|
||||
}
|
||||
Ok(final_string)
|
||||
@@ -1557,8 +1531,7 @@ fn perform_format(
|
||||
&& format_string.format_parts.iter().any(FormatPart::is_index)
|
||||
{
|
||||
return Err(vm.new_value_error(
|
||||
"cannot switch from automatic field numbering to manual field specification"
|
||||
.to_string(),
|
||||
"cannot switch from automatic field numbering to manual field specification".to_owned(),
|
||||
));
|
||||
}
|
||||
let mut auto_argument_index: usize = 1;
|
||||
@@ -1568,7 +1541,7 @@ fn perform_format(
|
||||
let result = match arguments.args.get(auto_argument_index) {
|
||||
Some(argument) => call_object_format(vm, argument.clone(), &format_spec)?,
|
||||
None => {
|
||||
return Err(vm.new_index_error("tuple index out of range".to_string()));
|
||||
return Err(vm.new_index_error("tuple index out of range".to_owned()));
|
||||
}
|
||||
};
|
||||
auto_argument_index += 1;
|
||||
@@ -1578,7 +1551,7 @@ fn perform_format(
|
||||
let result = match arguments.args.get(*index + 1) {
|
||||
Some(argument) => call_object_format(vm, argument.clone(), &format_spec)?,
|
||||
None => {
|
||||
return Err(vm.new_index_error("tuple index out of range".to_string()));
|
||||
return Err(vm.new_index_error("tuple index out of range".to_owned()));
|
||||
}
|
||||
};
|
||||
clone_value(&result)
|
||||
@@ -1587,7 +1560,7 @@ fn perform_format(
|
||||
let result = match arguments.get_optional_kwarg(&keyword) {
|
||||
Some(argument) => call_object_format(vm, argument.clone(), &format_spec)?,
|
||||
None => {
|
||||
return Err(vm.new_key_error(vm.new_str(keyword.to_string())));
|
||||
return Err(vm.new_key_error(vm.new_str(keyword.to_owned())));
|
||||
}
|
||||
};
|
||||
clone_value(&result)
|
||||
@@ -1609,7 +1582,7 @@ fn perform_format_map(
|
||||
let result_string: String = match part {
|
||||
FormatPart::AutoSpec(_) | FormatPart::IndexSpec(_, _) => {
|
||||
return Err(
|
||||
vm.new_value_error("Format string contains positional fields".to_string())
|
||||
vm.new_value_error("Format string contains positional fields".to_owned())
|
||||
);
|
||||
}
|
||||
FormatPart::KeywordSpec(keyword, format_spec) => {
|
||||
@@ -1738,7 +1711,7 @@ mod tests {
|
||||
("Greek ῼitlecases ...", "greek ῳitlecases ..."),
|
||||
];
|
||||
for (title, input) in tests {
|
||||
assert_eq!(PyString::from(input).title(&vm).as_str(), title);
|
||||
assert_eq!(PyString::from(input).title().as_str(), title);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1756,7 +1729,7 @@ mod tests {
|
||||
];
|
||||
|
||||
for s in pos {
|
||||
assert!(PyString::from(s).istitle(&vm));
|
||||
assert!(PyString::from(s).istitle());
|
||||
}
|
||||
|
||||
let neg = vec![
|
||||
@@ -1769,7 +1742,7 @@ mod tests {
|
||||
"NOT",
|
||||
];
|
||||
for s in neg {
|
||||
assert!(!PyString::from(s).istitle(&vm));
|
||||
assert!(!PyString::from(s).istitle());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,11 +35,11 @@ impl PyValue for PySuper {
|
||||
#[pyimpl]
|
||||
impl PySuper {
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(&self, _vm: &VirtualMachine) -> String {
|
||||
fn repr(&self) -> String {
|
||||
let class_type_str = if let Ok(type_class) = self.typ.clone().downcast::<PyClass>() {
|
||||
type_class.name.clone()
|
||||
} else {
|
||||
"NONE".to_string()
|
||||
"NONE".to_owned()
|
||||
};
|
||||
match self.obj_type.clone().downcast::<PyClass>() {
|
||||
Ok(obj_class_typ) => format!(
|
||||
@@ -63,7 +63,7 @@ impl PySuper {
|
||||
// This is a classmethod
|
||||
return Ok(item);
|
||||
}
|
||||
return vm.call_get_descriptor(item, inst.clone());
|
||||
return vm.call_if_get_descriptor(item, inst.clone());
|
||||
}
|
||||
}
|
||||
Err(vm.new_attribute_error(format!(
|
||||
@@ -92,7 +92,7 @@ impl PySuper {
|
||||
_ => {
|
||||
return Err(vm.new_type_error(
|
||||
"super must be called with 1 argument or from inside class method"
|
||||
.to_string(),
|
||||
.to_owned(),
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,7 @@ impl PySuper {
|
||||
}
|
||||
} else {
|
||||
return Err(vm.new_type_error(
|
||||
"super must be called with 1 argument or from inside class method".to_string(),
|
||||
"super must be called with 1 argument or from inside class method".to_owned(),
|
||||
));
|
||||
}
|
||||
};
|
||||
@@ -137,7 +137,7 @@ impl PySuper {
|
||||
};
|
||||
if !is_subclass {
|
||||
return Err(vm.new_type_error(
|
||||
"super(type, obj): obj must be an instance or subtype of type".to_string(),
|
||||
"super(type, obj): obj must be an instance or subtype of type".to_owned(),
|
||||
));
|
||||
}
|
||||
PyClassRef::try_from_object(vm, py_obj.clone())?
|
||||
@@ -172,6 +172,6 @@ pub fn init(context: &PyContext) {
|
||||
super().cmeth(arg)\n";
|
||||
|
||||
extend_class!(context, super_type, {
|
||||
"__doc__" => context.new_str(super_doc.to_string()),
|
||||
"__doc__" => context.new_str(super_doc.to_owned()),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -32,22 +32,22 @@ impl PyTraceback {
|
||||
}
|
||||
|
||||
#[pyproperty(name = "tb_frame")]
|
||||
fn frame(&self, _vm: &VirtualMachine) -> FrameRef {
|
||||
fn frame(&self) -> FrameRef {
|
||||
self.frame.clone()
|
||||
}
|
||||
|
||||
#[pyproperty(name = "tb_lasti")]
|
||||
fn lasti(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn lasti(&self) -> usize {
|
||||
self.lasti
|
||||
}
|
||||
|
||||
#[pyproperty(name = "tb_lineno")]
|
||||
fn lineno(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn lineno(&self) -> usize {
|
||||
self.lineno
|
||||
}
|
||||
|
||||
#[pyproperty(name = "tb_next")]
|
||||
fn next_get(&self, _vm: &VirtualMachine) -> Option<PyTracebackRef> {
|
||||
fn next_get(&self) -> Option<PyTracebackRef> {
|
||||
self.next.as_ref().cloned()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ impl PyTuple {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(&self, _vm: &VirtualMachine) -> bool {
|
||||
fn bool(&self) -> bool {
|
||||
!self.elements.is_empty()
|
||||
}
|
||||
|
||||
@@ -158,7 +158,7 @@ impl PyTuple {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyTupleIterator {
|
||||
fn iter(zelf: PyRef<Self>) -> PyTupleIterator {
|
||||
PyTupleIterator {
|
||||
position: Cell::new(0),
|
||||
tuple: zelf,
|
||||
@@ -166,7 +166,7 @@ impl PyTuple {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(&self) -> usize {
|
||||
self.elements.len()
|
||||
}
|
||||
|
||||
@@ -185,24 +185,20 @@ impl PyTuple {
|
||||
format!("({})", str_parts.join(", "))
|
||||
}
|
||||
} else {
|
||||
"(...)".to_string()
|
||||
"(...)".to_owned()
|
||||
};
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mul__")]
|
||||
fn mul(&self, counter: isize, _vm: &VirtualMachine) -> PyTuple {
|
||||
#[pymethod(name = "__rmul__")]
|
||||
fn mul(&self, counter: isize) -> PyTuple {
|
||||
let new_elements: Vec<_> = sequence::seq_mul(&self.elements, counter)
|
||||
.cloned()
|
||||
.collect();
|
||||
new_elements.into()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmul__")]
|
||||
fn rmul(&self, counter: isize, vm: &VirtualMachine) -> PyTuple {
|
||||
self.mul(counter, vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__getitem__")]
|
||||
fn getitem(zelf: PyRef<Self>, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
get_item(vm, zelf.as_object(), &zelf.elements, needle.clone())
|
||||
@@ -215,7 +211,7 @@ impl PyTuple {
|
||||
return Ok(index);
|
||||
}
|
||||
}
|
||||
Err(vm.new_value_error("tuple.index(x): x not in tuple".to_string()))
|
||||
Err(vm.new_value_error("tuple.index(x): x not in tuple".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__contains__")]
|
||||
@@ -271,7 +267,7 @@ impl PyTupleIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,11 +5,10 @@ use std::fmt;
|
||||
use super::objdict::PyDictRef;
|
||||
use super::objlist::PyList;
|
||||
use super::objmappingproxy::PyMappingProxy;
|
||||
use super::objproperty::PropertyBuilder;
|
||||
use super::objstr::PyStringRef;
|
||||
use super::objtuple::PyTuple;
|
||||
use super::objweakref::PyWeak;
|
||||
use crate::function::PyFuncArgs;
|
||||
use crate::function::{OptionalArg, PyFuncArgs};
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyAttributes, PyClassImpl, PyContext, PyIterable, PyObject, PyObjectRef, PyRef,
|
||||
PyResult, PyValue, TypeProtocol,
|
||||
@@ -80,16 +79,13 @@ impl PyClassRef {
|
||||
}
|
||||
}
|
||||
|
||||
fn _mro(self, _vm: &VirtualMachine) -> PyTuple {
|
||||
#[pyproperty(name = "__mro__")]
|
||||
fn get_mro(self) -> PyTuple {
|
||||
let elements: Vec<PyObjectRef> =
|
||||
_mro(&self).iter().map(|x| x.as_object().clone()).collect();
|
||||
PyTuple::from(elements)
|
||||
}
|
||||
|
||||
fn _set_mro(self, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Err(vm.new_attribute_error("read-only attribute".to_string()))
|
||||
}
|
||||
|
||||
#[pyproperty(magic)]
|
||||
fn bases(self, vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.ctx
|
||||
@@ -101,28 +97,28 @@ impl PyClassRef {
|
||||
let attributes = self.get_attributes();
|
||||
let attributes: Vec<PyObjectRef> = attributes
|
||||
.keys()
|
||||
.map(|k| vm.ctx.new_str(k.to_string()))
|
||||
.map(|k| vm.ctx.new_str(k.to_owned()))
|
||||
.collect();
|
||||
PyList::from(attributes)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn instancecheck(self, obj: PyObjectRef, _vm: &VirtualMachine) -> bool {
|
||||
fn instancecheck(self, obj: PyObjectRef) -> bool {
|
||||
isinstance(&obj, &self)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn subclasscheck(self, subclass: PyClassRef, _vm: &VirtualMachine) -> bool {
|
||||
fn subclasscheck(self, subclass: PyClassRef) -> bool {
|
||||
issubclass(&subclass, &self)
|
||||
}
|
||||
|
||||
#[pyproperty(magic)]
|
||||
fn name(self, _vm: &VirtualMachine) -> String {
|
||||
fn name(self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn repr(self, _vm: &VirtualMachine) -> String {
|
||||
fn repr(self) -> String {
|
||||
format!("<class '{}'>", self.name)
|
||||
}
|
||||
|
||||
@@ -145,6 +141,13 @@ impl PyClassRef {
|
||||
.unwrap_or_else(|| vm.ctx.new_str("builtins".to_owned()))
|
||||
}
|
||||
|
||||
#[pyproperty(magic, setter)]
|
||||
fn set_module(self, value: PyObjectRef) {
|
||||
self.attributes
|
||||
.borrow_mut()
|
||||
.insert("__module__".to_owned(), value);
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn prepare(_name: PyStringRef, _bases: PyObjectRef, vm: &VirtualMachine) -> PyDictRef {
|
||||
vm.ctx.new_dict()
|
||||
@@ -170,7 +173,11 @@ impl PyClassRef {
|
||||
|
||||
if let Some(attr) = self.get_attr(&name) {
|
||||
let attr_class = attr.class();
|
||||
if let Some(ref descriptor) = attr_class.get_attr("__get__") {
|
||||
let slots = attr_class.slots.borrow();
|
||||
if let Some(ref descr_get) = slots.descr_get {
|
||||
return descr_get(vm, attr, None, OptionalArg::Present(self.into_object()));
|
||||
} else if let Some(ref descriptor) = attr_class.get_attr("__get__") {
|
||||
// TODO: is this nessessary?
|
||||
return vm.invoke(descriptor, vec![attr, vm.get_none(), self.into_object()]);
|
||||
}
|
||||
}
|
||||
@@ -178,7 +185,7 @@ impl PyClassRef {
|
||||
if let Some(cls_attr) = self.get_attr(&name) {
|
||||
Ok(cls_attr)
|
||||
} else if let Some(attr) = mcl.get_attr(&name) {
|
||||
vm.call_get_descriptor(attr, self.into_object())
|
||||
vm.call_if_get_descriptor(attr, self.into_object())
|
||||
} else if let Some(ref getter) = self.get_attr("__getattr__") {
|
||||
vm.invoke(getter, vec![mcl.into_object(), name_ref.into_object()])
|
||||
} else {
|
||||
@@ -220,7 +227,7 @@ impl PyClassRef {
|
||||
self.attributes.borrow_mut().remove(attr_name.as_str());
|
||||
Ok(())
|
||||
} else {
|
||||
Err(vm.new_attribute_error(attr_name.as_str().to_string()))
|
||||
Err(vm.new_attribute_error(attr_name.as_str().to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,11 +235,11 @@ impl PyClassRef {
|
||||
pub fn set_str_attr<V: Into<PyObjectRef>>(&self, attr_name: &str, value: V) {
|
||||
self.attributes
|
||||
.borrow_mut()
|
||||
.insert(attr_name.to_string(), value.into());
|
||||
.insert(attr_name.to_owned(), value.into());
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn subclasses(self, _vm: &VirtualMachine) -> PyList {
|
||||
fn subclasses(self) -> PyList {
|
||||
let mut subclasses = self.subclasses.borrow_mut();
|
||||
subclasses.retain(|x| x.upgrade().is_some());
|
||||
PyList::from(
|
||||
@@ -261,7 +268,7 @@ impl PyClassRef {
|
||||
|
||||
if args.args.len() != 3 {
|
||||
return Err(vm.new_type_error(if is_type_type {
|
||||
"type() takes 1 or 3 arguments".to_string()
|
||||
"type() takes 1 or 3 arguments".to_owned()
|
||||
} else {
|
||||
format!(
|
||||
"type.__new__() takes exactly 3 arguments ({} given)",
|
||||
@@ -322,11 +329,23 @@ impl PyClassRef {
|
||||
let init_method = init_method_or_err?;
|
||||
let res = vm.invoke(&init_method, args)?;
|
||||
if !res.is(&vm.get_none()) {
|
||||
return Err(vm.new_type_error("__init__ must return None".to_string()));
|
||||
return Err(vm.new_type_error("__init__ must return None".to_owned()));
|
||||
}
|
||||
}
|
||||
Ok(obj)
|
||||
}
|
||||
|
||||
#[pyproperty(magic)]
|
||||
fn dict(self) -> PyMappingProxy {
|
||||
PyMappingProxy::new(self)
|
||||
}
|
||||
|
||||
#[pyproperty(magic, setter)]
|
||||
fn set_dict(self, _value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
Err(vm.new_not_implemented_error(
|
||||
"Setting __dict__ attribute on a type isn't yet implemented".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -335,18 +354,6 @@ impl PyClassRef {
|
||||
|
||||
pub(crate) fn init(ctx: &PyContext) {
|
||||
PyClassRef::extend_class(ctx, &ctx.types.type_type);
|
||||
extend_class!(&ctx, &ctx.types.type_type, {
|
||||
"__dict__" =>
|
||||
PropertyBuilder::new(ctx)
|
||||
.add_getter(type_dict)
|
||||
.add_setter(type_dict_setter)
|
||||
.create(),
|
||||
"__mro__" =>
|
||||
PropertyBuilder::new(ctx)
|
||||
.add_getter(PyClassRef::_mro)
|
||||
.add_setter(PyClassRef::_set_mro)
|
||||
.create(),
|
||||
});
|
||||
}
|
||||
|
||||
fn _mro(cls: &PyClassRef) -> Vec<PyClassRef> {
|
||||
@@ -398,20 +405,6 @@ pub fn type_new(
|
||||
new(vm, args.insert(cls.into_object()))
|
||||
}
|
||||
|
||||
fn type_dict(class: PyClassRef, _vm: &VirtualMachine) -> PyMappingProxy {
|
||||
PyMappingProxy::new(class)
|
||||
}
|
||||
|
||||
fn type_dict_setter(
|
||||
_instance: PyClassRef,
|
||||
_value: PyObjectRef,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<()> {
|
||||
Err(vm.new_not_implemented_error(
|
||||
"Setting __dict__ attribute on a type isn't yet implemented".to_string(),
|
||||
))
|
||||
}
|
||||
|
||||
impl PyClassRef {
|
||||
/// This is the internal get_attr implementation for fast lookup on a class.
|
||||
pub fn get_attr(&self, attr_name: &str) -> Option<PyObjectRef> {
|
||||
@@ -448,7 +441,7 @@ impl PyClassRef {
|
||||
|
||||
for bc in base_classes {
|
||||
for (name, value) in bc.attributes.borrow().iter() {
|
||||
attributes.insert(name.to_string(), value.clone());
|
||||
attributes.insert(name.to_owned(), value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,7 +541,7 @@ fn calculate_meta_class(
|
||||
return Err(vm.new_type_error(
|
||||
"metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass \
|
||||
of the metaclasses of all its bases"
|
||||
.to_string(),
|
||||
.to_owned(),
|
||||
));
|
||||
}
|
||||
Ok(winner)
|
||||
|
||||
@@ -43,7 +43,7 @@ impl PyWeakProxy {
|
||||
Some(obj) => vm.get_attribute(obj, attr_name),
|
||||
None => Err(vm.new_exception_msg(
|
||||
vm.ctx.exceptions.reference_error.clone(),
|
||||
"weakly-referenced object no longer exists".to_string(),
|
||||
"weakly-referenced object no longer exists".to_owned(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ impl PyWeakProxy {
|
||||
Some(obj) => vm.set_attr(&obj, attr_name, value),
|
||||
None => Err(vm.new_exception_msg(
|
||||
vm.ctx.exceptions.reference_error.clone(),
|
||||
"weakly-referenced object no longer exists".to_string(),
|
||||
"weakly-referenced object no longer exists".to_owned(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::function::{OptionalArg, PyFuncArgs};
|
||||
use crate::pyobject::{
|
||||
PyClassImpl, PyContext, PyObject, PyObjectPayload, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
};
|
||||
use crate::slots::PyBuiltinCallable;
|
||||
use crate::slots::SlotCall;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
use std::rc::{Rc, Weak};
|
||||
@@ -34,14 +34,14 @@ impl PyValue for PyWeak {
|
||||
|
||||
pub type PyWeakRef = PyRef<PyWeak>;
|
||||
|
||||
impl PyBuiltinCallable for PyWeak {
|
||||
impl SlotCall for PyWeak {
|
||||
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
|
||||
args.bind::<()>(vm)?;
|
||||
Ok(self.referent.upgrade().unwrap_or_else(|| vm.get_none()))
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(with(PyBuiltinCallable), flags(BASETYPE))]
|
||||
#[pyimpl(with(SlotCall), flags(BASETYPE))]
|
||||
impl PyWeak {
|
||||
// TODO callbacks
|
||||
#[pyslot]
|
||||
|
||||
@@ -45,7 +45,7 @@ impl PyZip {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
|
||||
E: serde::de::Error,
|
||||
{
|
||||
// Owned value needed anyway, delegate to visit_string
|
||||
self.visit_string(value.to_string())
|
||||
self.visit_string(value.to_owned())
|
||||
}
|
||||
|
||||
fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
|
||||
|
||||
@@ -25,13 +25,13 @@ use crate::obj::objcomplex::PyComplex;
|
||||
use crate::obj::objdict::{PyDict, PyDictRef};
|
||||
use crate::obj::objfloat::PyFloat;
|
||||
use crate::obj::objfunction::{PyBoundMethod, PyFunction};
|
||||
use crate::obj::objgetset::{IntoPyGetterFunc, IntoPySetterFunc, PyGetSet};
|
||||
use crate::obj::objint::{PyInt, PyIntRef};
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objlist::PyList;
|
||||
use crate::obj::objnamespace::PyNamespace;
|
||||
use crate::obj::objnone::{PyNone, PyNoneRef};
|
||||
use crate::obj::objobject;
|
||||
use crate::obj::objproperty::PropertyBuilder;
|
||||
use crate::obj::objset::PySet;
|
||||
use crate::obj::objstr;
|
||||
use crate::obj::objtuple::{PyTuple, PyTupleRef};
|
||||
@@ -330,6 +330,10 @@ impl PyContext {
|
||||
self.types.readonly_property_type.clone()
|
||||
}
|
||||
|
||||
pub fn getset_type(&self) -> PyClassRef {
|
||||
self.types.getset_type.clone()
|
||||
}
|
||||
|
||||
pub fn classmethod_type(&self) -> PyClassRef {
|
||||
self.types.classmethod_type.clone()
|
||||
}
|
||||
@@ -499,11 +503,23 @@ impl PyContext {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_property<F, I, V, VM>(&self, f: F) -> PyObjectRef
|
||||
pub fn new_readonly_getset<F, T>(&self, name: impl Into<String>, f: F) -> PyObjectRef
|
||||
where
|
||||
F: IntoPyNativeFunc<I, V, VM>,
|
||||
F: IntoPyGetterFunc<T>,
|
||||
{
|
||||
PropertyBuilder::new(self).add_getter(f).create()
|
||||
PyObject::new(PyGetSet::with_get(name.into(), f), self.getset_type(), None)
|
||||
}
|
||||
|
||||
pub fn new_getset<G, S, T, U>(&self, name: impl Into<String>, g: G, s: S) -> PyObjectRef
|
||||
where
|
||||
G: IntoPyGetterFunc<T>,
|
||||
S: IntoPySetterFunc<U>,
|
||||
{
|
||||
PyObject::new(
|
||||
PyGetSet::with_get_set(name.into(), g, s),
|
||||
self.getset_type(),
|
||||
None,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new_code_object(&self, code: bytecode::CodeObject) -> PyCodeRef {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use crate::function::{OptionalArg, PyFuncArgs, PyNativeFunc};
|
||||
use crate::pyobject::{IdProtocol, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::pyobject::{IdProtocol, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject};
|
||||
use crate::VirtualMachine;
|
||||
|
||||
bitflags! {
|
||||
@@ -28,7 +28,7 @@ pub struct PyClassSlots {
|
||||
pub flags: PyTpFlags,
|
||||
pub new: Option<PyNativeFunc>,
|
||||
pub call: Option<PyNativeFunc>,
|
||||
pub descr_get: Option<PyNativeFunc>,
|
||||
pub descr_get: Option<PyDescrGetFunc>,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for PyClassSlots {
|
||||
@@ -38,22 +38,73 @@ impl std::fmt::Debug for PyClassSlots {
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
pub trait PyBuiltinCallable: PyValue {
|
||||
pub trait SlotCall: PyValue {
|
||||
#[pymethod(magic)]
|
||||
#[pyslot]
|
||||
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult;
|
||||
}
|
||||
|
||||
pub type PyDescrGetFunc = Box<
|
||||
dyn Fn(&VirtualMachine, PyObjectRef, Option<PyObjectRef>, OptionalArg<PyObjectRef>) -> PyResult,
|
||||
>;
|
||||
|
||||
#[pyimpl]
|
||||
pub trait PyBuiltinDescriptor: PyValue {
|
||||
pub trait SlotDescriptor: PyValue {
|
||||
#[pyslot]
|
||||
fn descr_get(
|
||||
vm: &VirtualMachine,
|
||||
zelf: PyObjectRef,
|
||||
obj: Option<PyObjectRef>,
|
||||
cls: OptionalArg<PyObjectRef>,
|
||||
) -> PyResult;
|
||||
|
||||
#[pymethod(magic)]
|
||||
#[pyslot(descr_get)]
|
||||
fn get(
|
||||
zelf: PyRef<Self>,
|
||||
zelf: PyObjectRef,
|
||||
obj: PyObjectRef,
|
||||
cls: OptionalArg<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult;
|
||||
) -> PyResult {
|
||||
Self::descr_get(vm, zelf, Some(obj), cls)
|
||||
}
|
||||
|
||||
fn _zelf(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PyRef::<Self>::try_from_object(vm, zelf)
|
||||
}
|
||||
|
||||
fn _unwrap(
|
||||
zelf: PyObjectRef,
|
||||
obj: Option<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyResult<(PyRef<Self>, PyObjectRef)> {
|
||||
let zelf = Self::_zelf(zelf, vm)?;
|
||||
let obj = obj.unwrap_or_else(|| vm.get_none());
|
||||
Ok((zelf, obj))
|
||||
}
|
||||
|
||||
fn _check(
|
||||
zelf: PyObjectRef,
|
||||
obj: Option<PyObjectRef>,
|
||||
vm: &VirtualMachine,
|
||||
) -> Result<(PyRef<Self>, PyObjectRef), PyResult> {
|
||||
// CPython descr_check
|
||||
if let Some(obj) = obj {
|
||||
// if (!PyObject_TypeCheck(obj, descr->d_type)) {
|
||||
// PyErr_Format(PyExc_TypeError,
|
||||
// "descriptor '%V' for '%.100s' objects "
|
||||
// "doesn't apply to a '%.100s' object",
|
||||
// descr_name((PyDescrObject *)descr), "?",
|
||||
// descr->d_type->tp_name,
|
||||
// obj->ob_type->tp_name);
|
||||
// *pres = NULL;
|
||||
// return 1;
|
||||
// } else {
|
||||
Ok((Self::_zelf(zelf, vm).unwrap(), obj))
|
||||
// }
|
||||
} else {
|
||||
Err(Ok(zelf))
|
||||
}
|
||||
}
|
||||
|
||||
fn _cls_is<T>(cls: &OptionalArg<PyObjectRef>, other: &T) -> bool
|
||||
where
|
||||
|
||||
@@ -217,12 +217,12 @@ impl PyArray {
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn typecode(&self, _vm: &VirtualMachine) -> String {
|
||||
fn typecode(&self) -> String {
|
||||
self.array.borrow().typecode().to_string()
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn itemsize(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn itemsize(&self) -> usize {
|
||||
self.array.borrow().itemsize()
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ impl PyArray {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn buffer_info(&self, _vm: &VirtualMachine) -> (usize, usize) {
|
||||
fn buffer_info(&self) -> (usize, usize) {
|
||||
let array = self.array.borrow();
|
||||
(array.addr(), array.len())
|
||||
}
|
||||
@@ -301,7 +301,7 @@ impl PyArray {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn tobytes(&self, _vm: &VirtualMachine) -> Vec<u8> {
|
||||
fn tobytes(&self) -> Vec<u8> {
|
||||
self.array.borrow().tobytes()
|
||||
}
|
||||
|
||||
@@ -316,7 +316,7 @@ impl PyArray {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn reverse(&self, _vm: &VirtualMachine) {
|
||||
fn reverse(&self) {
|
||||
self.array.borrow_mut().reverse()
|
||||
}
|
||||
|
||||
@@ -349,12 +349,12 @@ impl PyArray {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(&self) -> usize {
|
||||
self.array.borrow().len()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyArrayIter {
|
||||
fn iter(zelf: PyRef<Self>) -> PyArrayIter {
|
||||
PyArrayIter {
|
||||
position: Cell::new(0),
|
||||
array: zelf,
|
||||
@@ -394,7 +394,7 @@ impl PyArrayIter {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ macro_rules! node {
|
||||
$(
|
||||
let field_name = stringify!($attr_name);
|
||||
$vm.set_attr(node.as_object(), field_name, $attr_value)?;
|
||||
field_names.push($vm.ctx.new_str(field_name.to_string()));
|
||||
field_names.push($vm.ctx.new_str(field_name.to_owned()));
|
||||
)*
|
||||
$vm.set_attr(node.as_object(), "_fields", $vm.ctx.new_tuple(field_names))?;
|
||||
node
|
||||
@@ -81,7 +81,7 @@ fn statement_to_ast(vm: &VirtualMachine, statement: &ast::Statement) -> PyResult
|
||||
decorator_list,
|
||||
..
|
||||
} => node!(vm, ClassDef, {
|
||||
name => vm.ctx.new_str(name.to_string()),
|
||||
name => vm.ctx.new_str(name.to_owned()),
|
||||
keywords => map_ast(keyword_to_ast, vm, keywords)?,
|
||||
body => statements_to_ast(vm, body)?,
|
||||
decorator_list => expressions_to_ast(vm, decorator_list)?,
|
||||
@@ -96,7 +96,7 @@ fn statement_to_ast(vm: &VirtualMachine, statement: &ast::Statement) -> PyResult
|
||||
} => {
|
||||
if *is_async {
|
||||
node!(vm, AsyncFunctionDef, {
|
||||
name => vm.ctx.new_str(name.to_string()),
|
||||
name => vm.ctx.new_str(name.to_owned()),
|
||||
args => parameters_to_ast(vm, args)?,
|
||||
body => statements_to_ast(vm, body)?,
|
||||
decorator_list => expressions_to_ast(vm, decorator_list)?,
|
||||
@@ -104,7 +104,7 @@ fn statement_to_ast(vm: &VirtualMachine, statement: &ast::Statement) -> PyResult
|
||||
})
|
||||
} else {
|
||||
node!(vm, FunctionDef, {
|
||||
name => vm.ctx.new_str(name.to_string()),
|
||||
name => vm.ctx.new_str(name.to_owned()),
|
||||
args => parameters_to_ast(vm, args)?,
|
||||
body => statements_to_ast(vm, body)?,
|
||||
decorator_list => expressions_to_ast(vm, decorator_list)?,
|
||||
@@ -245,7 +245,7 @@ fn statement_to_ast(vm: &VirtualMachine, statement: &ast::Statement) -> PyResult
|
||||
|
||||
fn alias_to_ast(vm: &VirtualMachine, alias: &ast::ImportSymbol) -> PyResult<AstNodeRef> {
|
||||
Ok(node!(vm, alias, {
|
||||
name => vm.ctx.new_str(alias.symbol.to_string()),
|
||||
name => vm.ctx.new_str(alias.symbol.to_owned()),
|
||||
asname => optional_string_to_py_obj(vm, &alias.alias)
|
||||
}))
|
||||
}
|
||||
@@ -280,12 +280,8 @@ fn handler_to_ast(vm: &VirtualMachine, handler: &ast::ExceptHandler) -> PyResult
|
||||
}
|
||||
|
||||
fn make_string_list(vm: &VirtualMachine, names: &[String]) -> PyObjectRef {
|
||||
vm.ctx.new_list(
|
||||
names
|
||||
.iter()
|
||||
.map(|x| vm.ctx.new_str(x.to_string()))
|
||||
.collect(),
|
||||
)
|
||||
vm.ctx
|
||||
.new_list(names.iter().map(|x| vm.ctx.new_str(x.to_owned())).collect())
|
||||
}
|
||||
|
||||
fn optional_expressions_to_ast(
|
||||
@@ -344,7 +340,7 @@ fn expression_to_ast(vm: &VirtualMachine, expression: &ast::Expression) -> PyRes
|
||||
ast::UnaryOperator::Pos => "UAdd",
|
||||
};
|
||||
node!(vm, UnaryOp, {
|
||||
op => vm.ctx.new_str(op.to_string()),
|
||||
op => vm.ctx.new_str(op.to_owned()),
|
||||
operand => expression_to_ast(vm, a)?,
|
||||
})
|
||||
}
|
||||
@@ -355,7 +351,7 @@ fn expression_to_ast(vm: &VirtualMachine, expression: &ast::Expression) -> PyRes
|
||||
ast::BooleanOperator::And => "And",
|
||||
ast::BooleanOperator::Or => "Or",
|
||||
};
|
||||
let py_op = vm.ctx.new_str(str_op.to_string());
|
||||
let py_op = vm.ctx.new_str(str_op.to_owned());
|
||||
|
||||
node!(vm, BoolOp, {
|
||||
op => py_op,
|
||||
@@ -380,7 +376,7 @@ fn expression_to_ast(vm: &VirtualMachine, expression: &ast::Expression) -> PyRes
|
||||
};
|
||||
let ops = vm.ctx.new_list(
|
||||
ops.iter()
|
||||
.map(|x| vm.ctx.new_str(to_operator(x).to_string()))
|
||||
.map(|x| vm.ctx.new_str(to_operator(x).to_owned()))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
@@ -510,7 +506,7 @@ fn expression_to_ast(vm: &VirtualMachine, expression: &ast::Expression) -> PyRes
|
||||
}),
|
||||
Attribute { value, name } => node!(vm, Attribute, {
|
||||
value => expression_to_ast(vm, value)?,
|
||||
attr => vm.ctx.new_str(name.to_string()),
|
||||
attr => vm.ctx.new_str(name.to_owned()),
|
||||
ctx => vm.ctx.none()
|
||||
}),
|
||||
Starred { value } => node!(vm, Starred, {
|
||||
@@ -545,7 +541,7 @@ fn operator_string(op: &ast::Operator) -> String {
|
||||
BitAnd => "BitAnd",
|
||||
FloorDiv => "FloorDiv",
|
||||
}
|
||||
.to_string()
|
||||
.to_owned()
|
||||
}
|
||||
|
||||
fn parameters_to_ast(vm: &VirtualMachine, args: &ast::Parameters) -> PyResult<AstNodeRef> {
|
||||
@@ -576,7 +572,7 @@ fn parameter_to_ast(vm: &VirtualMachine, parameter: &ast::Parameter) -> PyResult
|
||||
};
|
||||
|
||||
let py_node = node!(vm, arg, {
|
||||
arg => vm.ctx.new_str(parameter.arg.to_string()),
|
||||
arg => vm.ctx.new_str(parameter.arg.to_owned()),
|
||||
annotation => py_annotation
|
||||
});
|
||||
|
||||
@@ -588,7 +584,7 @@ fn parameter_to_ast(vm: &VirtualMachine, parameter: &ast::Parameter) -> PyResult
|
||||
|
||||
fn optional_string_to_py_obj(vm: &VirtualMachine, name: &Option<String>) -> PyObjectRef {
|
||||
if let Some(name) = name {
|
||||
vm.ctx.new_str(name.to_string())
|
||||
vm.ctx.new_str(name.to_owned())
|
||||
} else {
|
||||
vm.ctx.none()
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ impl TryFromObject for SerializedData {
|
||||
Ok(SerializedData::Ascii(a))
|
||||
} else {
|
||||
Err(vm.new_value_error(
|
||||
"string argument should contain only ASCII characters".to_string(),
|
||||
"string argument should contain only ASCII characters".to_owned(),
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ fn hex_nibble(n: u8) -> u8 {
|
||||
}
|
||||
}
|
||||
|
||||
fn binascii_hexlify(data: PyBytesLike, _vm: &VirtualMachine) -> Vec<u8> {
|
||||
fn binascii_hexlify(data: PyBytesLike) -> Vec<u8> {
|
||||
data.with_ref(|bytes| {
|
||||
let mut hex = Vec::<u8>::with_capacity(bytes.len() * 2);
|
||||
for b in bytes.iter() {
|
||||
@@ -79,7 +79,7 @@ fn unhex_nibble(c: u8) -> Option<u8> {
|
||||
fn binascii_unhexlify(data: SerializedData, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
|
||||
data.with_ref(|hex_bytes| {
|
||||
if hex_bytes.len() % 2 != 0 {
|
||||
return Err(vm.new_value_error("Odd-length string".to_string()));
|
||||
return Err(vm.new_value_error("Odd-length string".to_owned()));
|
||||
}
|
||||
|
||||
let mut unhex = Vec::<u8>::with_capacity(hex_bytes.len() / 2);
|
||||
@@ -87,7 +87,7 @@ fn binascii_unhexlify(data: SerializedData, vm: &VirtualMachine) -> PyResult<Vec
|
||||
if let (Some(n1), Some(n2)) = (unhex_nibble(*n1), unhex_nibble(*n2)) {
|
||||
unhex.push(n1 << 4 | n2);
|
||||
} else {
|
||||
return Err(vm.new_value_error("Non-hexadecimal digit found".to_string()));
|
||||
return Err(vm.new_value_error("Non-hexadecimal digit found".to_owned()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,11 +124,7 @@ fn binascii_a2b_base64(s: SerializedData, vm: &VirtualMachine) -> PyResult<Vec<u
|
||||
.map_err(|err| vm.new_value_error(format!("error decoding base64: {}", err)))
|
||||
}
|
||||
|
||||
fn binascii_b2a_base64(
|
||||
data: PyBytesLike,
|
||||
NewlineArg { newline }: NewlineArg,
|
||||
_vm: &VirtualMachine,
|
||||
) -> Vec<u8> {
|
||||
fn binascii_b2a_base64(data: PyBytesLike, NewlineArg { newline }: NewlineArg) -> Vec<u8> {
|
||||
let mut encoded = data.with_ref(base64::encode).into_bytes();
|
||||
if newline {
|
||||
encoded.push(b'\n');
|
||||
|
||||
@@ -57,7 +57,7 @@ impl PyDeque {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn append(&self, obj: PyObjectRef, _vm: &VirtualMachine) {
|
||||
fn append(&self, obj: PyObjectRef) {
|
||||
let mut deque = self.deque.borrow_mut();
|
||||
if self.maxlen.get() == Some(deque.len()) {
|
||||
deque.pop_front();
|
||||
@@ -66,7 +66,7 @@ impl PyDeque {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn appendleft(&self, obj: PyObjectRef, _vm: &VirtualMachine) {
|
||||
fn appendleft(&self, obj: PyObjectRef) {
|
||||
let mut deque = self.deque.borrow_mut();
|
||||
if self.maxlen.get() == Some(deque.len()) {
|
||||
deque.pop_back();
|
||||
@@ -75,12 +75,12 @@ impl PyDeque {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn clear(&self, _vm: &VirtualMachine) {
|
||||
fn clear(&self) {
|
||||
self.deque.borrow_mut().clear()
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn copy(&self, _vm: &VirtualMachine) -> Self {
|
||||
fn copy(&self) -> Self {
|
||||
self.clone()
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ impl PyDeque {
|
||||
fn extend(&self, iter: PyIterable, vm: &VirtualMachine) -> PyResult<()> {
|
||||
// TODO: use length_hint here and for extendleft
|
||||
for elem in iter.iter(vm)? {
|
||||
self.append(elem?, vm);
|
||||
self.append(elem?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -107,7 +107,7 @@ impl PyDeque {
|
||||
#[pymethod]
|
||||
fn extendleft(&self, iter: PyIterable, vm: &VirtualMachine) -> PyResult<()> {
|
||||
for elem in iter.iter(vm)? {
|
||||
self.appendleft(elem?, vm);
|
||||
self.appendleft(elem?);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -140,7 +140,7 @@ impl PyDeque {
|
||||
let mut deque = self.deque.borrow_mut();
|
||||
|
||||
if self.maxlen.get() == Some(deque.len()) {
|
||||
return Err(vm.new_index_error("deque already at its maximum size".to_string()));
|
||||
return Err(vm.new_index_error("deque already at its maximum size".to_owned()));
|
||||
}
|
||||
|
||||
let idx = if idx < 0 {
|
||||
@@ -165,7 +165,7 @@ impl PyDeque {
|
||||
self.deque
|
||||
.borrow_mut()
|
||||
.pop_back()
|
||||
.ok_or_else(|| vm.new_index_error("pop from an empty deque".to_string()))
|
||||
.ok_or_else(|| vm.new_index_error("pop from an empty deque".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -173,7 +173,7 @@ impl PyDeque {
|
||||
self.deque
|
||||
.borrow_mut()
|
||||
.pop_front()
|
||||
.ok_or_else(|| vm.new_index_error("pop from an empty deque".to_string()))
|
||||
.ok_or_else(|| vm.new_index_error("pop from an empty deque".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -187,17 +187,17 @@ impl PyDeque {
|
||||
}
|
||||
}
|
||||
idx.map(|idx| deque.remove(idx).unwrap())
|
||||
.ok_or_else(|| vm.new_value_error("deque.remove(x): x not in deque".to_string()))
|
||||
.ok_or_else(|| vm.new_value_error("deque.remove(x): x not in deque".to_owned()))
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn reverse(&self, _vm: &VirtualMachine) {
|
||||
fn reverse(&self) {
|
||||
self.deque
|
||||
.replace_with(|deque| deque.iter().cloned().rev().collect());
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn rotate(&self, mid: OptionalArg<isize>, _vm: &VirtualMachine) {
|
||||
fn rotate(&self, mid: OptionalArg<isize>) {
|
||||
let mut deque = self.deque.borrow_mut();
|
||||
let mid = mid.unwrap_or(1);
|
||||
if mid < 0 {
|
||||
@@ -208,12 +208,12 @@ impl PyDeque {
|
||||
}
|
||||
|
||||
#[pyproperty]
|
||||
fn maxlen(&self, _vm: &VirtualMachine) -> Option<usize> {
|
||||
fn maxlen(&self) -> Option<usize> {
|
||||
self.maxlen.get()
|
||||
}
|
||||
|
||||
#[pyproperty(setter)]
|
||||
fn set_maxlen(&self, maxlen: Option<usize>, _vm: &VirtualMachine) {
|
||||
fn set_maxlen(&self, maxlen: Option<usize>) {
|
||||
self.maxlen.set(maxlen);
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ impl PyDeque {
|
||||
.unwrap_or_default();
|
||||
format!("deque([{}]{})", elements.into_iter().format(", "), maxlen)
|
||||
} else {
|
||||
"[...]".to_string()
|
||||
"[...]".to_owned()
|
||||
};
|
||||
Ok(repr)
|
||||
}
|
||||
@@ -326,7 +326,7 @@ impl PyDeque {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mul__")]
|
||||
fn mul(&self, n: isize, _vm: &VirtualMachine) -> Self {
|
||||
fn mul(&self, n: isize) -> Self {
|
||||
let deque: &VecDeque<_> = &self.deque.borrow();
|
||||
let mul = sequence::seq_mul(deque, n);
|
||||
let skipped = if let Some(maxlen) = self.maxlen.get() {
|
||||
@@ -342,12 +342,12 @@ impl PyDeque {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__len__")]
|
||||
fn len(&self, _vm: &VirtualMachine) -> usize {
|
||||
fn len(&self) -> usize {
|
||||
self.deque.borrow().len()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyDequeIterator {
|
||||
fn iter(zelf: PyRef<Self>) -> PyDequeIterator {
|
||||
PyDequeIterator {
|
||||
position: Cell::new(0),
|
||||
deque: zelf,
|
||||
@@ -382,7 +382,7 @@ impl PyDequeIterator {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ impl ReaderOption {
|
||||
1 => bytes[0],
|
||||
_ => {
|
||||
let msg = r#""delimiter" must be a 1-character string"#;
|
||||
return Err(vm.new_type_error(msg.to_string()));
|
||||
return Err(vm.new_type_error(msg.to_owned()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -48,7 +48,7 @@ impl ReaderOption {
|
||||
1 => bytes[0],
|
||||
_ => {
|
||||
let msg = r#""quotechar" must be a 1-character string"#;
|
||||
return Err(vm.new_type_error(msg.to_string()));
|
||||
return Err(vm.new_type_error(msg.to_owned()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -190,7 +190,7 @@ fn csv_reader(fp: PyObjectRef, args: PyFuncArgs, vm: &VirtualMachine) -> PyResul
|
||||
if let Ok(iterable) = PyIterable::<PyObjectRef>::try_from_object(vm, fp) {
|
||||
build_reader(iterable, args, vm)
|
||||
} else {
|
||||
Err(vm.new_type_error("argument 1 must be an iterator".to_string()))
|
||||
Err(vm.new_type_error("argument 1 must be an iterator".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ fn dis_compiler_flag_names(vm: &VirtualMachine) -> PyObjectRef {
|
||||
for (name, flag) in CodeFlags::NAME_MAPPING {
|
||||
dict.set_item(
|
||||
&vm.ctx.new_int(flag.bits()),
|
||||
vm.ctx.new_str((*name).to_string()),
|
||||
vm.ctx.new_str((*name).to_owned()),
|
||||
vm,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -20,7 +20,7 @@ fn dump_traceback(_file: OptionalArg<i64>, _all_threads: OptionalArg<bool>, vm:
|
||||
}
|
||||
}
|
||||
|
||||
fn enable(_file: OptionalArg<i64>, _all_threads: OptionalArg<bool>, _vm: &VirtualMachine) {
|
||||
fn enable(_file: OptionalArg<i64>, _all_threads: OptionalArg<bool>) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ fn register(
|
||||
_file: OptionalArg<i64>,
|
||||
_all_threads: OptionalArg<bool>,
|
||||
_chain: OptionalArg<bool>,
|
||||
_vm: &VirtualMachine,
|
||||
) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ fn functools_reduce(
|
||||
let exc_type = vm.ctx.exceptions.type_error.clone();
|
||||
vm.new_exception_msg(
|
||||
exc_type,
|
||||
"reduce() of empty sequence with no initial value".to_string(),
|
||||
"reduce() of empty sequence with no initial value".to_owned(),
|
||||
)
|
||||
} else {
|
||||
err
|
||||
|
||||
@@ -36,7 +36,7 @@ impl PyValue for PyHasher {
|
||||
impl PyHasher {
|
||||
fn new(name: &str, d: HashWrapper) -> Self {
|
||||
PyHasher {
|
||||
name: name.to_string(),
|
||||
name: name.to_owned(),
|
||||
buffer: RefCell::new(d),
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ impl PyHasher {
|
||||
}
|
||||
|
||||
#[pyproperty(name = "name")]
|
||||
fn name(&self, _vm: &VirtualMachine) -> String {
|
||||
fn name(&self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
@@ -65,13 +65,13 @@ impl PyHasher {
|
||||
}
|
||||
|
||||
#[pymethod(name = "digest")]
|
||||
fn digest(&self, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn digest(&self) -> PyBytes {
|
||||
let result = self.get_digest();
|
||||
PyBytes::new(result)
|
||||
}
|
||||
|
||||
#[pymethod(name = "hexdigest")]
|
||||
fn hexdigest(&self, _vm: &VirtualMachine) -> String {
|
||||
fn hexdigest(&self) -> String {
|
||||
let result = self.get_digest();
|
||||
hex::encode(result)
|
||||
}
|
||||
@@ -158,11 +158,11 @@ fn sha3_512(data: OptionalArg<PyBytesRef>, vm: &VirtualMachine) -> PyResult<PyHa
|
||||
}
|
||||
|
||||
fn shake128(_data: OptionalArg<PyBytesRef>, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
Err(vm.new_not_implemented_error("shake256".to_string()))
|
||||
Err(vm.new_not_implemented_error("shake256".to_owned()))
|
||||
}
|
||||
|
||||
fn shake256(_data: OptionalArg<PyBytesRef>, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
Err(vm.new_not_implemented_error("shake256".to_string()))
|
||||
Err(vm.new_not_implemented_error("shake256".to_owned()))
|
||||
}
|
||||
|
||||
fn blake2b(data: OptionalArg<PyBytesRef>, vm: &VirtualMachine) -> PyResult<PyHasher> {
|
||||
|
||||
@@ -47,7 +47,7 @@ fn imp_create_builtin(spec: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
}
|
||||
}
|
||||
|
||||
fn imp_exec_builtin(_mod: PyModuleRef, _vm: &VirtualMachine) -> i32 {
|
||||
fn imp_exec_builtin(_mod: PyModuleRef) -> i32 {
|
||||
// TOOD: Should we do something here?
|
||||
0
|
||||
}
|
||||
@@ -80,7 +80,7 @@ fn imp_is_frozen_package(name: PyStringRef, vm: &VirtualMachine) -> PyResult<boo
|
||||
})
|
||||
}
|
||||
|
||||
fn imp_fix_co_filename(_code: PyObjectRef, _path: PyStringRef, _vm: &VirtualMachine) {
|
||||
fn imp_fix_co_filename(_code: PyObjectRef, _path: PyStringRef) {
|
||||
// TODO:
|
||||
}
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ impl PyStringIORef {
|
||||
if buffer.is_some() {
|
||||
Ok(RefMut::map(buffer, |opt| opt.as_mut().unwrap()))
|
||||
} else {
|
||||
Err(vm.new_value_error("I/O operation on closed file.".to_string()))
|
||||
Err(vm.new_value_error("I/O operation on closed file.".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ impl PyStringIORef {
|
||||
|
||||
match self.buffer(vm)?.write(bytes) {
|
||||
Some(value) => Ok(vm.ctx.new_int(value)),
|
||||
None => Err(vm.new_type_error("Error Writing String".to_string())),
|
||||
None => Err(vm.new_type_error("Error Writing String".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ impl PyStringIORef {
|
||||
fn getvalue(self, vm: &VirtualMachine) -> PyResult {
|
||||
match String::from_utf8(self.buffer(vm)?.getvalue()) {
|
||||
Ok(result) => Ok(vm.ctx.new_str(result)),
|
||||
Err(_) => Err(vm.new_value_error("Error Retrieving Value".to_string())),
|
||||
Err(_) => Err(vm.new_value_error("Error Retrieving Value".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,11 +145,11 @@ impl PyStringIORef {
|
||||
fn seek(self, offset: u64, vm: &VirtualMachine) -> PyResult {
|
||||
match self.buffer(vm)?.seek(offset) {
|
||||
Some(value) => Ok(vm.ctx.new_int(value)),
|
||||
None => Err(vm.new_value_error("Error Performing Operation".to_string())),
|
||||
None => Err(vm.new_value_error("Error Performing Operation".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
fn seekable(self, _vm: &VirtualMachine) -> bool {
|
||||
fn seekable(self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ impl PyStringIORef {
|
||||
|
||||
match String::from_utf8(data) {
|
||||
Ok(value) => Ok(vm.ctx.new_str(value)),
|
||||
Err(_) => Err(vm.new_value_error("Error Retrieving Value".to_string())),
|
||||
Err(_) => Err(vm.new_value_error("Error Retrieving Value".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ impl PyStringIORef {
|
||||
fn readline(self, vm: &VirtualMachine) -> PyResult<String> {
|
||||
match self.buffer(vm)?.readline() {
|
||||
Some(line) => Ok(line),
|
||||
None => Err(vm.new_value_error("Error Performing Operation".to_string())),
|
||||
None => Err(vm.new_value_error("Error Performing Operation".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,11 +186,11 @@ impl PyStringIORef {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn closed(self, _vm: &VirtualMachine) -> bool {
|
||||
fn closed(self) -> bool {
|
||||
self.buffer.borrow().is_none()
|
||||
}
|
||||
|
||||
fn close(self, _vm: &VirtualMachine) {
|
||||
fn close(self) {
|
||||
self.buffer.replace(None);
|
||||
}
|
||||
}
|
||||
@@ -237,7 +237,7 @@ impl PyBytesIORef {
|
||||
if buffer.is_some() {
|
||||
Ok(RefMut::map(buffer, |opt| opt.as_mut().unwrap()))
|
||||
} else {
|
||||
Err(vm.new_value_error("I/O operation on closed file.".to_string()))
|
||||
Err(vm.new_value_error("I/O operation on closed file.".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ impl PyBytesIORef {
|
||||
let mut buffer = self.buffer(vm)?;
|
||||
match data.with_ref(|b| buffer.write(b)) {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(vm.new_type_error("Error Writing Bytes".to_string())),
|
||||
None => Err(vm.new_type_error("Error Writing Bytes".to_owned())),
|
||||
}
|
||||
}
|
||||
//Retrieves the entire bytes object value from the underlying buffer
|
||||
@@ -259,7 +259,7 @@ impl PyBytesIORef {
|
||||
fn read(self, bytes: OptionalOption<i64>, vm: &VirtualMachine) -> PyResult {
|
||||
match self.buffer(vm)?.read(byte_count(bytes)) {
|
||||
Some(value) => Ok(vm.ctx.new_bytes(value)),
|
||||
None => Err(vm.new_value_error("Error Retrieving Value".to_string())),
|
||||
None => Err(vm.new_value_error("Error Retrieving Value".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,11 +267,11 @@ impl PyBytesIORef {
|
||||
fn seek(self, offset: u64, vm: &VirtualMachine) -> PyResult {
|
||||
match self.buffer(vm)?.seek(offset) {
|
||||
Some(value) => Ok(vm.ctx.new_int(value)),
|
||||
None => Err(vm.new_value_error("Error Performing Operation".to_string())),
|
||||
None => Err(vm.new_value_error("Error Performing Operation".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
fn seekable(self, _vm: &VirtualMachine) -> bool {
|
||||
fn seekable(self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ impl PyBytesIORef {
|
||||
fn readline(self, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
|
||||
match self.buffer(vm)?.readline() {
|
||||
Some(line) => Ok(line.as_bytes().to_vec()),
|
||||
None => Err(vm.new_value_error("Error Performing Operation".to_string())),
|
||||
None => Err(vm.new_value_error("Error Performing Operation".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,11 +293,11 @@ impl PyBytesIORef {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn closed(self, _vm: &VirtualMachine) -> bool {
|
||||
fn closed(self) -> bool {
|
||||
self.buffer.borrow().is_none()
|
||||
}
|
||||
|
||||
fn close(self, _vm: &VirtualMachine) {
|
||||
fn close(self) {
|
||||
self.buffer.replace(None);
|
||||
}
|
||||
}
|
||||
@@ -318,7 +318,7 @@ fn bytes_io_new(
|
||||
.into_ref_with_type(vm, cls)
|
||||
}
|
||||
|
||||
fn io_base_cm_enter(instance: PyObjectRef, _vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn io_base_cm_enter(instance: PyObjectRef) -> PyObjectRef {
|
||||
instance.clone()
|
||||
}
|
||||
|
||||
@@ -328,15 +328,15 @@ fn io_base_cm_exit(instance: PyObjectRef, _args: PyFuncArgs, vm: &VirtualMachine
|
||||
}
|
||||
|
||||
// TODO Check if closed, then if so raise ValueError
|
||||
fn io_base_flush(_self: PyObjectRef, _vm: &VirtualMachine) {}
|
||||
fn io_base_flush(_self: PyObjectRef) {}
|
||||
|
||||
fn io_base_seekable(_self: PyObjectRef, _vm: &VirtualMachine) -> bool {
|
||||
fn io_base_seekable(_self: PyObjectRef) -> bool {
|
||||
false
|
||||
}
|
||||
fn io_base_readable(_self: PyObjectRef, _vm: &VirtualMachine) -> bool {
|
||||
fn io_base_readable(_self: PyObjectRef) -> bool {
|
||||
false
|
||||
}
|
||||
fn io_base_writable(_self: PyObjectRef, _vm: &VirtualMachine) -> bool {
|
||||
fn io_base_writable(_self: PyObjectRef) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ fn io_base_checkclosed(
|
||||
if objbool::boolval(vm, vm.get_attribute(instance, "closed")?)? {
|
||||
let msg = msg
|
||||
.flat_option()
|
||||
.unwrap_or_else(|| vm.new_str("I/O operation on closed file.".to_string()));
|
||||
.unwrap_or_else(|| vm.new_str("I/O operation on closed file.".to_owned()));
|
||||
Err(vm.new_exception(vm.ctx.exceptions.value_error.clone(), vec![msg]))
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -398,7 +398,7 @@ fn io_base_checkreadable(
|
||||
if !objbool::boolval(vm, vm.call_method(&instance, "readable", vec![])?)? {
|
||||
let msg = msg
|
||||
.flat_option()
|
||||
.unwrap_or_else(|| vm.new_str("File or stream is not readable.".to_string()));
|
||||
.unwrap_or_else(|| vm.new_str("File or stream is not readable.".to_owned()));
|
||||
Err(vm.new_exception(vm.ctx.exceptions.value_error.clone(), vec![msg]))
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -413,7 +413,7 @@ fn io_base_checkwritable(
|
||||
if !objbool::boolval(vm, vm.call_method(&instance, "writable", vec![])?)? {
|
||||
let msg = msg
|
||||
.flat_option()
|
||||
.unwrap_or_else(|| vm.new_str("File or stream is not writable.".to_string()));
|
||||
.unwrap_or_else(|| vm.new_str("File or stream is not writable.".to_owned()));
|
||||
Err(vm.new_exception(vm.ctx.exceptions.value_error.clone(), vec![msg]))
|
||||
} else {
|
||||
Ok(())
|
||||
@@ -428,14 +428,14 @@ fn io_base_checkseekable(
|
||||
if !objbool::boolval(vm, vm.call_method(&instance, "seekable", vec![])?)? {
|
||||
let msg = msg
|
||||
.flat_option()
|
||||
.unwrap_or_else(|| vm.new_str("File or stream is not seekable.".to_string()));
|
||||
.unwrap_or_else(|| vm.new_str("File or stream is not seekable.".to_owned()));
|
||||
Err(vm.new_exception(vm.ctx.exceptions.value_error.clone(), vec![msg]))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn io_base_iter(instance: PyObjectRef, _vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn io_base_iter(instance: PyObjectRef) -> PyObjectRef {
|
||||
instance
|
||||
}
|
||||
fn io_base_next(instance: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
@@ -505,7 +505,7 @@ fn buffered_reader_read(
|
||||
)
|
||||
}
|
||||
|
||||
fn buffered_reader_seekable(_self: PyObjectRef, _vm: &VirtualMachine) -> bool {
|
||||
fn buffered_reader_seekable(_self: PyObjectRef) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -564,7 +564,7 @@ mod fileio {
|
||||
vm.set_attr(&file_io, "name", name)?;
|
||||
vm.set_attr(&file_io, "__fileno", vm.new_int(file_no))?;
|
||||
vm.set_attr(&file_io, "closefd", vm.new_bool(false))?;
|
||||
vm.set_attr(&file_io, "closed", vm.new_bool(false))?;
|
||||
vm.set_attr(&file_io, "__closed", vm.new_bool(false))?;
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
@@ -614,7 +614,7 @@ mod fileio {
|
||||
) -> PyResult<()> {
|
||||
if !obj.readonly() {
|
||||
return Err(vm.new_type_error(
|
||||
"readinto() argument must be read-write bytes-like object".to_string(),
|
||||
"readinto() argument must be read-write bytes-like object".to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
@@ -632,7 +632,7 @@ mod fileio {
|
||||
value_mut.clear();
|
||||
match f.read_to_end(value_mut) {
|
||||
Ok(_) => {}
|
||||
Err(_) => return Err(vm.new_value_error("Error reading from Take".to_string())),
|
||||
Err(_) => return Err(vm.new_value_error("Error reading from Take".to_owned())),
|
||||
}
|
||||
};
|
||||
|
||||
@@ -665,7 +665,7 @@ mod fileio {
|
||||
winapi::um::handleapi::CloseHandle(raw_handle as _);
|
||||
}
|
||||
vm.set_attr(&instance, "closefd", vm.new_bool(true))?;
|
||||
vm.set_attr(&instance, "closed", vm.new_bool(true))?;
|
||||
vm.set_attr(&instance, "__closed", vm.new_bool(true))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -676,11 +676,11 @@ mod fileio {
|
||||
libc::close(raw_fd as _);
|
||||
}
|
||||
vm.set_attr(&instance, "closefd", vm.new_bool(true))?;
|
||||
vm.set_attr(&instance, "closed", vm.new_bool(true))?;
|
||||
vm.set_attr(&instance, "__closed", vm.new_bool(true))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn file_io_seekable(_self: PyObjectRef, _vm: &VirtualMachine) -> bool {
|
||||
fn file_io_seekable(_self: PyObjectRef) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -709,7 +709,7 @@ fn buffered_writer_write(instance: PyObjectRef, obj: PyObjectRef, vm: &VirtualMa
|
||||
vm.call_method(&raw, "write", vec![obj.clone()])
|
||||
}
|
||||
|
||||
fn buffered_writer_seekable(_self: PyObjectRef, _vm: &VirtualMachine) -> bool {
|
||||
fn buffered_writer_seekable(_self: PyObjectRef) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -722,7 +722,7 @@ fn text_io_wrapper_init(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn text_io_wrapper_seekable(_self: PyObjectRef, _vm: &VirtualMachine) -> bool {
|
||||
fn text_io_wrapper_seekable(_self: PyObjectRef) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
@@ -736,7 +736,7 @@ fn text_io_wrapper_read(
|
||||
|
||||
if !objtype::isinstance(&raw, &buffered_reader_class) {
|
||||
// TODO: this should be io.UnsupportedOperation error which derives both from ValueError *and* OSError
|
||||
return Err(vm.new_value_error("not readable".to_string()));
|
||||
return Err(vm.new_value_error("not readable".to_owned()));
|
||||
}
|
||||
|
||||
let bytes = vm.call_method(
|
||||
@@ -767,15 +767,15 @@ fn text_io_wrapper_write(
|
||||
|
||||
if !objtype::isinstance(&raw, &buffered_writer_class) {
|
||||
// TODO: this should be io.UnsupportedOperation error which derives from ValueError and OSError
|
||||
return Err(vm.new_value_error("not writable".to_string()));
|
||||
return Err(vm.new_value_error("not writable".to_owned()));
|
||||
}
|
||||
|
||||
let bytes = obj.as_str().to_string().into_bytes();
|
||||
let bytes = obj.as_str().to_owned().into_bytes();
|
||||
|
||||
let len = vm.call_method(&raw, "write", vec![vm.ctx.new_bytes(bytes.clone())])?;
|
||||
let len = objint::get_value(&len).to_usize().ok_or_else(|| {
|
||||
vm.new_overflow_error("int to large to convert to Rust usize".to_string())
|
||||
})?;
|
||||
let len = objint::get_value(&len)
|
||||
.to_usize()
|
||||
.ok_or_else(|| vm.new_overflow_error("int to large to convert to Rust usize".to_owned()))?;
|
||||
|
||||
// returns the count of unicode code points written
|
||||
let len = from_utf8(&bytes[..len])
|
||||
@@ -795,7 +795,7 @@ fn text_io_wrapper_readline(
|
||||
|
||||
if !objtype::isinstance(&raw, &buffered_reader_class) {
|
||||
// TODO: this should be io.UnsupportedOperation error which derives both from ValueError *and* OSError
|
||||
return Err(vm.new_value_error("not readable".to_string()));
|
||||
return Err(vm.new_value_error("not readable".to_owned()));
|
||||
}
|
||||
|
||||
let bytes = vm.call_method(
|
||||
@@ -833,7 +833,7 @@ fn split_mode_string(mode_string: &str) -> Result<(String, String), String> {
|
||||
// no duplicates allowed
|
||||
return Err(format!("invalid mode: '{}'", mode_string));
|
||||
} else {
|
||||
return Err("can't have text and binary mode at once".to_string());
|
||||
return Err("can't have text and binary mode at once".to_owned());
|
||||
}
|
||||
}
|
||||
typ = ch;
|
||||
@@ -845,7 +845,7 @@ fn split_mode_string(mode_string: &str) -> Result<(String, String), String> {
|
||||
return Err(format!("invalid mode: '{}'", mode_string));
|
||||
} else {
|
||||
return Err(
|
||||
"must have exactly one of create/read/write/append mode".to_string()
|
||||
"must have exactly one of create/read/write/append mode".to_owned()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -858,7 +858,7 @@ fn split_mode_string(mode_string: &str) -> Result<(String, String), String> {
|
||||
if mode == '\0' {
|
||||
return Err(
|
||||
"Must have exactly one of create/read/write/append mode and at most one plus"
|
||||
.to_string(),
|
||||
.to_owned(),
|
||||
);
|
||||
}
|
||||
let mut mode = mode.to_string();
|
||||
@@ -896,7 +896,7 @@ pub fn io_open(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
let file_io_class = vm.get_attribute(io_module.clone(), "FileIO").map_err(|_| {
|
||||
// TODO: UnsupportedOperation here
|
||||
vm.new_os_error(
|
||||
"Couldn't get FileIO, io.open likely isn't supported on your platform".to_string(),
|
||||
"Couldn't get FileIO, io.open likely isn't supported on your platform".to_owned(),
|
||||
)
|
||||
})?;
|
||||
let file_io_obj = vm.invoke(
|
||||
@@ -952,7 +952,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
"readable" => ctx.new_method(io_base_readable),
|
||||
"writable" => ctx.new_method(io_base_writable),
|
||||
"flush" => ctx.new_method(io_base_flush),
|
||||
"closed" => ctx.new_property(io_base_closed),
|
||||
"closed" => ctx.new_readonly_getset("closed", io_base_closed),
|
||||
"__closed" => ctx.new_bool(false),
|
||||
"close" => ctx.new_method(io_base_close),
|
||||
"readline" => ctx.new_method(io_base_readline),
|
||||
@@ -1017,7 +1017,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
"tell" => ctx.new_method(PyStringIORef::tell),
|
||||
"readline" => ctx.new_method(PyStringIORef::readline),
|
||||
"truncate" => ctx.new_method(PyStringIORef::truncate),
|
||||
"closed" => ctx.new_property(PyStringIORef::closed),
|
||||
"closed" => ctx.new_readonly_getset("closed", PyStringIORef::closed),
|
||||
"close" => ctx.new_method(PyStringIORef::close),
|
||||
});
|
||||
|
||||
@@ -1033,7 +1033,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
"tell" => ctx.new_method(PyBytesIORef::tell),
|
||||
"readline" => ctx.new_method(PyBytesIORef::readline),
|
||||
"truncate" => ctx.new_method(PyBytesIORef::truncate),
|
||||
"closed" => ctx.new_property(PyBytesIORef::closed),
|
||||
"closed" => ctx.new_readonly_getset("closed", PyBytesIORef::closed),
|
||||
"close" => ctx.new_method(PyBytesIORef::close),
|
||||
});
|
||||
|
||||
@@ -1084,15 +1084,15 @@ mod tests {
|
||||
fn test_invalid_mode() {
|
||||
assert_eq!(
|
||||
split_mode_string("rbsss"),
|
||||
Err("invalid mode: 'rbsss'".to_string())
|
||||
Err("invalid mode: 'rbsss'".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
split_mode_string("rrb"),
|
||||
Err("invalid mode: 'rrb'".to_string())
|
||||
Err("invalid mode: 'rrb'".to_owned())
|
||||
);
|
||||
assert_eq!(
|
||||
split_mode_string("rbb"),
|
||||
Err("invalid mode: 'rbb'".to_string())
|
||||
Err("invalid mode: 'rbb'".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1102,21 +1102,21 @@ mod tests {
|
||||
split_mode_string(""),
|
||||
Err(
|
||||
"Must have exactly one of create/read/write/append mode and at most one plus"
|
||||
.to_string()
|
||||
.to_owned()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
split_mode_string("b"),
|
||||
Err(
|
||||
"Must have exactly one of create/read/write/append mode and at most one plus"
|
||||
.to_string()
|
||||
.to_owned()
|
||||
)
|
||||
);
|
||||
assert_eq!(
|
||||
split_mode_string("t"),
|
||||
Err(
|
||||
"Must have exactly one of create/read/write/append mode and at most one plus"
|
||||
.to_string()
|
||||
.to_owned()
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -1125,7 +1125,7 @@ mod tests {
|
||||
fn test_text_and_binary_at_once() {
|
||||
assert_eq!(
|
||||
split_mode_string("rbt"),
|
||||
Err("can't have text and binary mode at once".to_string())
|
||||
Err("can't have text and binary mode at once".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1133,7 +1133,7 @@ mod tests {
|
||||
fn test_exactly_one_mode() {
|
||||
assert_eq!(
|
||||
split_mode_string("rwb"),
|
||||
Err("must have exactly one of create/read/write/append mode".to_string())
|
||||
Err("must have exactly one of create/read/write/append mode".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1141,7 +1141,7 @@ mod tests {
|
||||
fn test_at_most_one_plus() {
|
||||
assert_eq!(
|
||||
split_mode_string("a++"),
|
||||
Err("invalid mode: 'a++'".to_string())
|
||||
Err("invalid mode: 'a++'".to_owned())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ impl PyItertoolsChain {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ impl PyItertoolsCompress {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -178,14 +178,14 @@ impl PyItertoolsCount {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__next__")]
|
||||
fn next(&self, _vm: &VirtualMachine) -> PyResult<PyInt> {
|
||||
fn next(&self) -> PyResult<PyInt> {
|
||||
let result = self.cur.borrow().clone();
|
||||
*self.cur.borrow_mut() += &self.step;
|
||||
Ok(PyInt::new(result))
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -252,7 +252,7 @@ impl PyItertoolsCycle {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -304,7 +304,7 @@ impl PyItertoolsRepeat {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ impl PyItertoolsStarmap {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -412,7 +412,7 @@ impl PyItertoolsTakewhile {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -470,7 +470,7 @@ impl PyItertoolsDropwhile {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -528,7 +528,7 @@ impl PyItertoolsIslice {
|
||||
let start = if !start.is(&vm.get_none()) {
|
||||
pyobject_to_opt_usize(start, &vm).ok_or_else(|| {
|
||||
vm.new_value_error(
|
||||
"Indices for islice() must be None or an integer: 0 <= x <= sys.maxsize.".to_string(),
|
||||
"Indices for islice() must be None or an integer: 0 <= x <= sys.maxsize.".to_owned(),
|
||||
)
|
||||
})?
|
||||
} else {
|
||||
@@ -538,7 +538,7 @@ impl PyItertoolsIslice {
|
||||
let step = if !step.is(&vm.get_none()) {
|
||||
pyobject_to_opt_usize(step, &vm).ok_or_else(|| {
|
||||
vm.new_value_error(
|
||||
"Step for islice() must be a positive integer or None.".to_string(),
|
||||
"Step for islice() must be a positive integer or None.".to_owned(),
|
||||
)
|
||||
})?
|
||||
} else {
|
||||
@@ -553,7 +553,7 @@ impl PyItertoolsIslice {
|
||||
Some(pyobject_to_opt_usize(stop, &vm).ok_or_else(|| {
|
||||
vm.new_value_error(
|
||||
"Stop argument for islice() must be None or an integer: 0 <= x <= sys.maxsize."
|
||||
.to_string(),
|
||||
.to_owned(),
|
||||
)
|
||||
})?)
|
||||
} else {
|
||||
@@ -596,7 +596,7 @@ impl PyItertoolsIslice {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -652,7 +652,7 @@ impl PyItertoolsFilterFalse {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -711,7 +711,7 @@ impl PyItertoolsAccumulate {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -810,7 +810,7 @@ impl PyItertoolsTee {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -927,7 +927,7 @@ impl PyItertoolsProduct {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
@@ -961,7 +961,7 @@ impl PyItertoolsCombinations {
|
||||
|
||||
let r = r.as_bigint();
|
||||
if r.is_negative() {
|
||||
return Err(vm.new_value_error("r must be non-negative".to_string()));
|
||||
return Err(vm.new_value_error("r must be non-negative".to_owned()));
|
||||
}
|
||||
let r = r.to_usize().unwrap();
|
||||
|
||||
@@ -977,7 +977,7 @@ impl PyItertoolsCombinations {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
@@ -1060,7 +1060,7 @@ impl PyItertoolsCombinationsWithReplacement {
|
||||
|
||||
let r = r.as_bigint();
|
||||
if r.is_negative() {
|
||||
return Err(vm.new_value_error("r must be non-negative".to_string()));
|
||||
return Err(vm.new_value_error("r must be non-negative".to_owned()));
|
||||
}
|
||||
let r = r.to_usize().unwrap();
|
||||
|
||||
@@ -1076,7 +1076,7 @@ impl PyItertoolsCombinationsWithReplacement {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
@@ -1161,11 +1161,11 @@ impl PyItertoolsPermutations {
|
||||
Some(r) => {
|
||||
let val = r
|
||||
.payload::<PyInt>()
|
||||
.ok_or_else(|| vm.new_type_error("Expected int as r".to_string()))?
|
||||
.ok_or_else(|| vm.new_type_error("Expected int as r".to_owned()))?
|
||||
.as_bigint();
|
||||
|
||||
if val.is_negative() {
|
||||
return Err(vm.new_value_error("r must be non-negative".to_string()));
|
||||
return Err(vm.new_value_error("r must be non-negative".to_owned()));
|
||||
}
|
||||
val.to_usize().unwrap()
|
||||
}
|
||||
@@ -1184,7 +1184,7 @@ impl PyItertoolsPermutations {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
@@ -1333,7 +1333,7 @@ impl PyItertoolsZiplongest {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let keyword_kwlist = ctx.new_list(
|
||||
lexer::get_keywords()
|
||||
.keys()
|
||||
.map(|k| ctx.new_str(k.to_string()))
|
||||
.map(|k| ctx.new_str(k.to_owned()))
|
||||
.collect(),
|
||||
);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::obj::objcode::{PyCode, PyCodeRef};
|
||||
use crate::pyobject::{PyObjectRef, PyResult};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
fn marshal_dumps(co: PyCodeRef, _vm: &VirtualMachine) -> PyBytes {
|
||||
fn marshal_dumps(co: PyCodeRef) -> PyBytes {
|
||||
PyBytes::new(co.code.to_bytes())
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ use std::cmp::Ordering;
|
||||
// Helper macro:
|
||||
macro_rules! make_math_func {
|
||||
( $fname:ident, $fun:ident ) => {
|
||||
fn $fname(value: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn $fname(value: IntoPyFloat) -> f64 {
|
||||
value.to_f64().$fun()
|
||||
}
|
||||
};
|
||||
@@ -33,7 +33,7 @@ macro_rules! make_math_func {
|
||||
|
||||
macro_rules! make_math_func_bool {
|
||||
( $fname:ident, $fun:ident ) => {
|
||||
fn $fname(value: IntoPyFloat, _vm: &VirtualMachine) -> bool {
|
||||
fn $fname(value: IntoPyFloat) -> bool {
|
||||
value.to_f64().$fun()
|
||||
}
|
||||
};
|
||||
@@ -72,7 +72,7 @@ fn math_isclose(args: IsCloseArgs, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
};
|
||||
|
||||
if rel_tol < 0.0 || abs_tol < 0.0 {
|
||||
return Err(vm.new_value_error("tolerances must be non-negative".to_string()));
|
||||
return Err(vm.new_value_error("tolerances must be non-negative".to_owned()));
|
||||
}
|
||||
|
||||
if a == b {
|
||||
@@ -98,7 +98,7 @@ fn math_isclose(args: IsCloseArgs, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
Ok((diff <= (rel_tol * b).abs()) || (diff <= (rel_tol * a).abs()) || (diff <= abs_tol))
|
||||
}
|
||||
|
||||
fn math_copysign(a: IntoPyFloat, b: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_copysign(a: IntoPyFloat, b: IntoPyFloat) -> f64 {
|
||||
let a = a.to_f64();
|
||||
let b = b.to_f64();
|
||||
if a.is_nan() || b.is_nan() {
|
||||
@@ -112,18 +112,18 @@ fn math_copysign(a: IntoPyFloat, b: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
make_math_func!(math_exp, exp);
|
||||
make_math_func!(math_expm1, exp_m1);
|
||||
|
||||
fn math_log(x: IntoPyFloat, base: OptionalArg<IntoPyFloat>, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_log(x: IntoPyFloat, base: OptionalArg<IntoPyFloat>) -> f64 {
|
||||
base.map_or_else(|| x.to_f64().ln(), |base| x.to_f64().log(base.to_f64()))
|
||||
}
|
||||
|
||||
fn math_log1p(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_log1p(x: IntoPyFloat) -> f64 {
|
||||
(x.to_f64() + 1.0).ln()
|
||||
}
|
||||
|
||||
make_math_func!(math_log2, log2);
|
||||
make_math_func!(math_log10, log10);
|
||||
|
||||
fn math_pow(x: IntoPyFloat, y: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_pow(x: IntoPyFloat, y: IntoPyFloat) -> f64 {
|
||||
x.to_f64().powf(y.to_f64())
|
||||
}
|
||||
|
||||
@@ -134,24 +134,24 @@ make_math_func!(math_acos, acos);
|
||||
make_math_func!(math_asin, asin);
|
||||
make_math_func!(math_atan, atan);
|
||||
|
||||
fn math_atan2(y: IntoPyFloat, x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_atan2(y: IntoPyFloat, x: IntoPyFloat) -> f64 {
|
||||
y.to_f64().atan2(x.to_f64())
|
||||
}
|
||||
|
||||
make_math_func!(math_cos, cos);
|
||||
|
||||
fn math_hypot(x: IntoPyFloat, y: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_hypot(x: IntoPyFloat, y: IntoPyFloat) -> f64 {
|
||||
x.to_f64().hypot(y.to_f64())
|
||||
}
|
||||
|
||||
make_math_func!(math_sin, sin);
|
||||
make_math_func!(math_tan, tan);
|
||||
|
||||
fn math_degrees(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_degrees(x: IntoPyFloat) -> f64 {
|
||||
x.to_f64() * (180.0 / std::f64::consts::PI)
|
||||
}
|
||||
|
||||
fn math_radians(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_radians(x: IntoPyFloat) -> f64 {
|
||||
x.to_f64() * (std::f64::consts::PI / 180.0)
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ make_math_func!(math_sinh, sinh);
|
||||
make_math_func!(math_tanh, tanh);
|
||||
|
||||
// Special functions:
|
||||
fn math_erf(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_erf(x: IntoPyFloat) -> f64 {
|
||||
let x = x.to_f64();
|
||||
if x.is_nan() {
|
||||
x
|
||||
@@ -173,7 +173,7 @@ fn math_erf(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
fn math_erfc(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_erfc(x: IntoPyFloat) -> f64 {
|
||||
let x = x.to_f64();
|
||||
if x.is_nan() {
|
||||
x
|
||||
@@ -182,7 +182,7 @@ fn math_erfc(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
fn math_gamma(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_gamma(x: IntoPyFloat) -> f64 {
|
||||
let x = x.to_f64();
|
||||
if x.is_finite() {
|
||||
gamma(x)
|
||||
@@ -193,7 +193,7 @@ fn math_gamma(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
}
|
||||
}
|
||||
|
||||
fn math_lgamma(x: IntoPyFloat, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_lgamma(x: IntoPyFloat) -> f64 {
|
||||
let x = x.to_f64();
|
||||
if x.is_finite() {
|
||||
ln_gamma(x)
|
||||
@@ -251,7 +251,7 @@ fn math_floor(value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
}
|
||||
}
|
||||
|
||||
fn math_frexp(value: IntoPyFloat, _vm: &VirtualMachine) -> (f64, i32) {
|
||||
fn math_frexp(value: IntoPyFloat) -> (f64, i32) {
|
||||
let value = value.to_f64();
|
||||
if value.is_finite() {
|
||||
let (m, e) = objfloat::ufrexp(value);
|
||||
@@ -261,11 +261,11 @@ fn math_frexp(value: IntoPyFloat, _vm: &VirtualMachine) -> (f64, i32) {
|
||||
}
|
||||
}
|
||||
|
||||
fn math_ldexp(value: PyFloatRef, i: PyIntRef, _vm: &VirtualMachine) -> f64 {
|
||||
fn math_ldexp(value: PyFloatRef, i: PyIntRef) -> f64 {
|
||||
value.to_f64() * (2_f64).powf(i.as_bigint().to_f64().unwrap())
|
||||
}
|
||||
|
||||
fn math_gcd(a: PyIntRef, b: PyIntRef, _vm: &VirtualMachine) -> BigInt {
|
||||
fn math_gcd(a: PyIntRef, b: PyIntRef) -> BigInt {
|
||||
use num_integer::Integer;
|
||||
a.as_bigint().gcd(b.as_bigint())
|
||||
}
|
||||
@@ -273,7 +273,7 @@ fn math_gcd(a: PyIntRef, b: PyIntRef, _vm: &VirtualMachine) -> BigInt {
|
||||
fn math_factorial(value: PyIntRef, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
let value = value.as_bigint();
|
||||
if *value < BigInt::zero() {
|
||||
return Err(vm.new_value_error("factorial() not defined for negative values".to_string()));
|
||||
return Err(vm.new_value_error("factorial() not defined for negative values".to_owned()));
|
||||
} else if *value <= BigInt::one() {
|
||||
return Ok(BigInt::from(1u64));
|
||||
}
|
||||
@@ -281,7 +281,7 @@ fn math_factorial(value: PyIntRef, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
fn math_modf(x: IntoPyFloat, _vm: &VirtualMachine) -> (f64, f64) {
|
||||
fn math_modf(x: IntoPyFloat) -> (f64, f64) {
|
||||
let x = x.to_f64();
|
||||
if !x.is_finite() {
|
||||
if x.is_infinite() {
|
||||
@@ -306,7 +306,7 @@ fn math_nextafter(x: IntoPyFloat, y: IntoPyFloat) -> PyResult<f64> {
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn math_nextafter(x: IntoPyFloat, y: IntoPyFloat, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
Err(vm.new_not_implemented_error("not implemented for this platform".to_string()))
|
||||
Err(vm.new_not_implemented_error("not implemented for this platform".to_owned()))
|
||||
}
|
||||
|
||||
fn fmod(x: f64, y: f64) -> f64 {
|
||||
@@ -324,7 +324,7 @@ fn math_fmod(x: IntoPyFloat, y: IntoPyFloat, vm: &VirtualMachine) -> PyResult<f6
|
||||
let r = fmod(x, y);
|
||||
|
||||
if r.is_nan() && !x.is_nan() && !y.is_nan() {
|
||||
return Err(vm.new_value_error("math domain error".to_string()));
|
||||
return Err(vm.new_value_error("math domain error".to_owned()));
|
||||
}
|
||||
|
||||
Ok(r)
|
||||
@@ -362,7 +362,7 @@ fn math_remainder(x: IntoPyFloat, y: IntoPyFloat, vm: &VirtualMachine) -> PyResu
|
||||
return Ok(std::f64::NAN);
|
||||
}
|
||||
if y.is_infinite() {
|
||||
return Err(vm.new_value_error("math domain error".to_string()));
|
||||
return Err(vm.new_value_error("math domain error".to_owned()));
|
||||
}
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
@@ -62,65 +62,65 @@ pub type StdlibInitFunc = Box<dyn Fn(&VirtualMachine) -> PyObjectRef>;
|
||||
pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
|
||||
#[allow(unused_mut)]
|
||||
let mut modules = hashmap! {
|
||||
"array".to_string() => Box::new(array::make_module) as StdlibInitFunc,
|
||||
"binascii".to_string() => Box::new(binascii::make_module),
|
||||
"dis".to_string() => Box::new(dis::make_module),
|
||||
"_collections".to_string() => Box::new(collections::make_module),
|
||||
"_csv".to_string() => Box::new(csv::make_module),
|
||||
"_functools".to_string() => Box::new(functools::make_module),
|
||||
"errno".to_string() => Box::new(errno::make_module),
|
||||
"hashlib".to_string() => Box::new(hashlib::make_module),
|
||||
"itertools".to_string() => Box::new(itertools::make_module),
|
||||
"_io".to_string() => Box::new(io::make_module),
|
||||
"json".to_string() => Box::new(json::make_module),
|
||||
"marshal".to_string() => Box::new(marshal::make_module),
|
||||
"math".to_string() => Box::new(math::make_module),
|
||||
"_operator".to_string() => Box::new(operator::make_module),
|
||||
"platform".to_string() => Box::new(platform::make_module),
|
||||
"regex_crate".to_string() => Box::new(re::make_module),
|
||||
"random".to_string() => Box::new(random::make_module),
|
||||
"_string".to_string() => Box::new(string::make_module),
|
||||
"struct".to_string() => Box::new(pystruct::make_module),
|
||||
"_thread".to_string() => Box::new(thread::make_module),
|
||||
"time".to_string() => Box::new(time_module::make_module),
|
||||
"_weakref".to_string() => Box::new(weakref::make_module),
|
||||
"_imp".to_string() => Box::new(imp::make_module),
|
||||
"unicodedata".to_string() => Box::new(unicodedata::make_module),
|
||||
"_warnings".to_string() => Box::new(warnings::make_module),
|
||||
"array".to_owned() => Box::new(array::make_module) as StdlibInitFunc,
|
||||
"binascii".to_owned() => Box::new(binascii::make_module),
|
||||
"dis".to_owned() => Box::new(dis::make_module),
|
||||
"_collections".to_owned() => Box::new(collections::make_module),
|
||||
"_csv".to_owned() => Box::new(csv::make_module),
|
||||
"_functools".to_owned() => Box::new(functools::make_module),
|
||||
"errno".to_owned() => Box::new(errno::make_module),
|
||||
"hashlib".to_owned() => Box::new(hashlib::make_module),
|
||||
"itertools".to_owned() => Box::new(itertools::make_module),
|
||||
"_io".to_owned() => Box::new(io::make_module),
|
||||
"json".to_owned() => Box::new(json::make_module),
|
||||
"marshal".to_owned() => Box::new(marshal::make_module),
|
||||
"math".to_owned() => Box::new(math::make_module),
|
||||
"_operator".to_owned() => Box::new(operator::make_module),
|
||||
"platform".to_owned() => Box::new(platform::make_module),
|
||||
"regex_crate".to_owned() => Box::new(re::make_module),
|
||||
"_random".to_owned() => Box::new(random::make_module),
|
||||
"_string".to_owned() => Box::new(string::make_module),
|
||||
"struct".to_owned() => Box::new(pystruct::make_module),
|
||||
"_thread".to_owned() => Box::new(thread::make_module),
|
||||
"time".to_owned() => Box::new(time_module::make_module),
|
||||
"_weakref".to_owned() => Box::new(weakref::make_module),
|
||||
"_imp".to_owned() => Box::new(imp::make_module),
|
||||
"unicodedata".to_owned() => Box::new(unicodedata::make_module),
|
||||
"_warnings".to_owned() => Box::new(warnings::make_module),
|
||||
};
|
||||
|
||||
// Insert parser related modules:
|
||||
#[cfg(feature = "rustpython-parser")]
|
||||
{
|
||||
modules.insert(
|
||||
"_ast".to_string(),
|
||||
"_ast".to_owned(),
|
||||
Box::new(ast::make_module) as StdlibInitFunc,
|
||||
);
|
||||
modules.insert("keyword".to_string(), Box::new(keyword::make_module));
|
||||
modules.insert("tokenize".to_string(), Box::new(tokenize::make_module));
|
||||
modules.insert("keyword".to_owned(), Box::new(keyword::make_module));
|
||||
modules.insert("tokenize".to_owned(), Box::new(tokenize::make_module));
|
||||
}
|
||||
|
||||
// Insert compiler related modules:
|
||||
#[cfg(feature = "rustpython-compiler")]
|
||||
{
|
||||
modules.insert("symtable".to_string(), Box::new(symtable::make_module));
|
||||
modules.insert("symtable".to_owned(), Box::new(symtable::make_module));
|
||||
}
|
||||
|
||||
// disable some modules on WASM
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
modules.insert("_os".to_string(), Box::new(os::make_module));
|
||||
modules.insert("_socket".to_string(), Box::new(socket::make_module));
|
||||
modules.insert("_os".to_owned(), Box::new(os::make_module));
|
||||
modules.insert("_socket".to_owned(), Box::new(socket::make_module));
|
||||
modules.insert(
|
||||
"_multiprocessing".to_string(),
|
||||
"_multiprocessing".to_owned(),
|
||||
Box::new(multiprocessing::make_module),
|
||||
);
|
||||
modules.insert("signal".to_string(), Box::new(signal::make_module));
|
||||
modules.insert("select".to_string(), Box::new(select::make_module));
|
||||
modules.insert("_subprocess".to_string(), Box::new(subprocess::make_module));
|
||||
modules.insert("zlib".to_string(), Box::new(zlib::make_module));
|
||||
modules.insert("signal".to_owned(), Box::new(signal::make_module));
|
||||
modules.insert("select".to_owned(), Box::new(select::make_module));
|
||||
modules.insert("_subprocess".to_owned(), Box::new(subprocess::make_module));
|
||||
modules.insert("zlib".to_owned(), Box::new(zlib::make_module));
|
||||
modules.insert(
|
||||
"faulthandler".to_string(),
|
||||
"faulthandler".to_owned(),
|
||||
Box::new(faulthandler::make_module),
|
||||
);
|
||||
}
|
||||
@@ -128,13 +128,13 @@ pub fn get_module_inits() -> HashMap<String, StdlibInitFunc> {
|
||||
// Unix-only
|
||||
#[cfg(all(unix, not(any(target_os = "android", target_os = "redox"))))]
|
||||
{
|
||||
modules.insert("pwd".to_string(), Box::new(pwd::make_module));
|
||||
modules.insert("pwd".to_owned(), Box::new(pwd::make_module));
|
||||
}
|
||||
|
||||
// Windows-only
|
||||
#[cfg(windows)]
|
||||
{
|
||||
modules.insert("_winapi".to_string(), Box::new(winapi::make_module));
|
||||
modules.insert("_winapi".to_owned(), Box::new(winapi::make_module));
|
||||
}
|
||||
|
||||
modules
|
||||
|
||||
@@ -78,16 +78,15 @@ fn operator_compare_digest(
|
||||
(Either::A(a), Either::A(b)) => {
|
||||
if !a.as_str().is_ascii() || !b.as_str().is_ascii() {
|
||||
return Err(vm.new_type_error(
|
||||
"comparing strings with non-ASCII characters is not supported".to_string(),
|
||||
"comparing strings with non-ASCII characters is not supported".to_owned(),
|
||||
));
|
||||
}
|
||||
timing_safe_cmp(a.as_str().as_bytes(), b.as_str().as_bytes())
|
||||
}
|
||||
(Either::B(a), Either::B(b)) => a.with_ref(|a| b.with_ref(|b| timing_safe_cmp(a, b))),
|
||||
_ => {
|
||||
return Err(vm.new_type_error(
|
||||
"unsupported operand types(s) or combination of types".to_string(),
|
||||
))
|
||||
return Err(vm
|
||||
.new_type_error("unsupported operand types(s) or combination of types".to_owned()))
|
||||
}
|
||||
};
|
||||
Ok(res)
|
||||
|
||||
@@ -87,7 +87,7 @@ fn make_path(_vm: &VirtualMachine, path: PyStringRef, dir_fd: &DirFd) -> PyStrin
|
||||
}
|
||||
}
|
||||
|
||||
fn os_close(fileno: i64, _vm: &VirtualMachine) {
|
||||
fn os_close(fileno: i64) {
|
||||
//The File type automatically closes when it goes out of scope.
|
||||
//To enable us to close these file descriptors (and hence prevent leaks)
|
||||
//we seek to create the relevant File and simply let it pass out of scope!
|
||||
@@ -312,7 +312,7 @@ fn os_access(path: PyStringRef, mode: u8, vm: &VirtualMachine) -> PyResult<bool>
|
||||
let flags = AccessFlags::from_bits(mode).ok_or_else(|| {
|
||||
vm.new_value_error(
|
||||
"One of the flags is wrong, there are only 4 possibilities F_OK, R_OK, W_OK and X_OK"
|
||||
.to_string(),
|
||||
.to_owned(),
|
||||
)
|
||||
})?;
|
||||
|
||||
@@ -340,7 +340,7 @@ fn os_access(path: PyStringRef, mode: u8, vm: &VirtualMachine) -> PyResult<bool>
|
||||
}
|
||||
|
||||
fn os_error(message: OptionalArg<PyStringRef>, vm: &VirtualMachine) -> PyResult {
|
||||
let msg = message.map_or("".to_string(), |msg| msg.as_str().to_string());
|
||||
let msg = message.map_or("".to_owned(), |msg| msg.as_str().to_owned());
|
||||
|
||||
Err(vm.new_os_error(msg))
|
||||
}
|
||||
@@ -519,12 +519,12 @@ struct FollowSymlinks {
|
||||
}
|
||||
|
||||
impl DirEntryRef {
|
||||
fn name(self, _vm: &VirtualMachine) -> String {
|
||||
fn name(self) -> String {
|
||||
self.entry.file_name().into_string().unwrap()
|
||||
}
|
||||
|
||||
fn path(self, _vm: &VirtualMachine) -> String {
|
||||
self.entry.path().to_str().unwrap().to_string()
|
||||
fn path(self) -> String {
|
||||
self.entry.path().to_str().unwrap().to_owned()
|
||||
}
|
||||
|
||||
#[allow(clippy::match_bool)]
|
||||
@@ -568,7 +568,7 @@ impl DirEntryRef {
|
||||
|
||||
fn stat(self, dir_fd: DirFd, follow_symlinks: FollowSymlinks, vm: &VirtualMachine) -> PyResult {
|
||||
os_stat(
|
||||
Either::A(self.path(vm).try_into_ref(vm)?),
|
||||
Either::A(self.path().try_into_ref(vm)?),
|
||||
dir_fd,
|
||||
follow_symlinks,
|
||||
vm,
|
||||
@@ -610,23 +610,23 @@ impl ScandirIterator {
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn close(&self, _vm: &VirtualMachine) {
|
||||
fn close(&self) {
|
||||
self.exhausted.set(true);
|
||||
}
|
||||
|
||||
#[pymethod(name = "__iter__")]
|
||||
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn iter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__enter__")]
|
||||
fn enter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
|
||||
fn enter(zelf: PyRef<Self>) -> PyRef<Self> {
|
||||
zelf
|
||||
}
|
||||
|
||||
#[pymethod(name = "__exit__")]
|
||||
fn exit(zelf: PyRef<Self>, _args: PyFuncArgs, vm: &VirtualMachine) {
|
||||
zelf.close(vm)
|
||||
fn exit(zelf: PyRef<Self>, _args: PyFuncArgs) {
|
||||
zelf.close()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,7 +814,6 @@ fn os_stat(
|
||||
_file: Either<PyStringRef, i64>,
|
||||
_dir_fd: DirFd,
|
||||
_follow_symlinks: FollowSymlinks,
|
||||
_vm: &VirtualMachine,
|
||||
) -> PyResult {
|
||||
unimplemented!();
|
||||
}
|
||||
@@ -877,7 +876,7 @@ fn os_getcwd(vm: &VirtualMachine) -> PyResult<String> {
|
||||
.as_path()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string())
|
||||
.to_owned())
|
||||
}
|
||||
|
||||
fn os_chdir(path: PyStringRef, vm: &VirtualMachine) -> PyResult<()> {
|
||||
@@ -980,7 +979,7 @@ fn os_pipe2(flags: libc::c_int, vm: &VirtualMachine) -> PyResult<(RawFd, RawFd)>
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
fn os_system(command: PyStringRef, _vm: &VirtualMachine) -> PyResult<i32> {
|
||||
fn os_system(command: PyStringRef) -> PyResult<i32> {
|
||||
use libc::system;
|
||||
use std::ffi::CString;
|
||||
|
||||
@@ -1039,7 +1038,7 @@ fn os_cpu_count(vm: &VirtualMachine) -> PyObjectRef {
|
||||
vm.new_int(cpu_count)
|
||||
}
|
||||
|
||||
fn os_exit(code: i32, _vm: &VirtualMachine) {
|
||||
fn os_exit(code: i32) {
|
||||
std::process::exit(code)
|
||||
}
|
||||
|
||||
@@ -1150,7 +1149,7 @@ fn os_urandom(size: usize, vm: &VirtualMachine) -> PyResult<Vec<u8>> {
|
||||
Ok(()) => Ok(buf),
|
||||
Err(e) => match e.raw_os_error() {
|
||||
Some(errno) => Err(convert_io_error(vm, io::Error::from_raw_os_error(errno))),
|
||||
None => Err(vm.new_os_error("Getting random failed".to_string())),
|
||||
None => Err(vm.new_os_error("Getting random failed".to_owned())),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1203,7 +1202,7 @@ macro_rules! suppress_iph {
|
||||
}};
|
||||
}
|
||||
|
||||
fn os_isatty(fd: i32, _vm: &VirtualMachine) -> bool {
|
||||
fn os_isatty(fd: i32) -> bool {
|
||||
unsafe { suppress_iph!(libc::isatty(fd)) != 0 }
|
||||
}
|
||||
|
||||
@@ -1224,9 +1223,9 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
let os_name = if cfg!(windows) {
|
||||
"nt".to_string()
|
||||
"nt".to_owned()
|
||||
} else {
|
||||
"posix".to_string()
|
||||
"posix".to_owned()
|
||||
};
|
||||
|
||||
let environ = _os_environ(vm);
|
||||
@@ -1235,8 +1234,8 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
ScandirIterator::extend_class(ctx, &scandir_iter);
|
||||
|
||||
let dir_entry = py_class!(ctx, "DirEntry", ctx.object(), {
|
||||
"name" => ctx.new_property(DirEntryRef::name),
|
||||
"path" => ctx.new_property(DirEntryRef::path),
|
||||
"name" => ctx.new_readonly_getset("name", DirEntryRef::name),
|
||||
"path" => ctx.new_readonly_getset("path", DirEntryRef::path),
|
||||
"is_dir" => ctx.new_method(DirEntryRef::is_dir),
|
||||
"is_file" => ctx.new_method(DirEntryRef::is_file),
|
||||
"is_symlink" => ctx.new_method(DirEntryRef::is_symlink),
|
||||
|
||||
@@ -15,7 +15,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
}
|
||||
|
||||
fn platform_python_implementation(_vm: &VirtualMachine) -> String {
|
||||
"RustPython".to_string()
|
||||
"RustPython".to_owned()
|
||||
}
|
||||
|
||||
fn platform_python_version(_vm: &VirtualMachine) -> String {
|
||||
|
||||
@@ -14,31 +14,31 @@ impl PyValue for Passwd {
|
||||
type PasswdRef = PyRef<Passwd>;
|
||||
|
||||
impl PasswdRef {
|
||||
fn pw_name(self, _vm: &VirtualMachine) -> String {
|
||||
fn pw_name(self) -> String {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn pw_passwd(self, _vm: &VirtualMachine) -> Option<String> {
|
||||
fn pw_passwd(self) -> Option<String> {
|
||||
self.passwd.clone()
|
||||
}
|
||||
|
||||
fn pw_uid(self, _vm: &VirtualMachine) -> u32 {
|
||||
fn pw_uid(self) -> u32 {
|
||||
self.uid
|
||||
}
|
||||
|
||||
fn pw_gid(self, _vm: &VirtualMachine) -> u32 {
|
||||
fn pw_gid(self) -> u32 {
|
||||
self.gid
|
||||
}
|
||||
|
||||
fn pw_gecos(self, _vm: &VirtualMachine) -> Option<String> {
|
||||
fn pw_gecos(self) -> Option<String> {
|
||||
self.gecos.clone()
|
||||
}
|
||||
|
||||
fn pw_dir(self, _vm: &VirtualMachine) -> String {
|
||||
fn pw_dir(self) -> String {
|
||||
self.dir.clone()
|
||||
}
|
||||
|
||||
fn pw_shell(self, _vm: &VirtualMachine) -> String {
|
||||
fn pw_shell(self) -> String {
|
||||
self.shell.clone()
|
||||
}
|
||||
}
|
||||
@@ -68,13 +68,13 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
let passwd_type = py_class!(ctx, "struct_passwd", ctx.object(), {
|
||||
"pw_name" => ctx.new_property(PasswdRef::pw_name),
|
||||
"pw_passwd" => ctx.new_property(PasswdRef::pw_passwd),
|
||||
"pw_uid" => ctx.new_property(PasswdRef::pw_uid),
|
||||
"pw_gid" => ctx.new_property(PasswdRef::pw_gid),
|
||||
"pw_gecos" => ctx.new_property(PasswdRef::pw_gecos),
|
||||
"pw_dir" => ctx.new_property(PasswdRef::pw_dir),
|
||||
"pw_shell" => ctx.new_property(PasswdRef::pw_shell),
|
||||
"pw_name" => ctx.new_readonly_getset("pw_name", PasswdRef::pw_name),
|
||||
"pw_passwd" => ctx.new_readonly_getset("pw_passwd", PasswdRef::pw_passwd),
|
||||
"pw_uid" => ctx.new_readonly_getset("pw_uid", PasswdRef::pw_uid),
|
||||
"pw_gid" => ctx.new_readonly_getset("pw_gid", PasswdRef::pw_gid),
|
||||
"pw_gecos" => ctx.new_readonly_getset("pw_gecos", PasswdRef::pw_gecos),
|
||||
"pw_dir" => ctx.new_readonly_getset("pw_dir", PasswdRef::pw_dir),
|
||||
"pw_shell" => ctx.new_readonly_getset("pw_shell", PasswdRef::pw_shell),
|
||||
});
|
||||
|
||||
py_module!(vm, "pwd", {
|
||||
|
||||
@@ -252,7 +252,7 @@ fn struct_pack(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
)))
|
||||
}
|
||||
} else {
|
||||
Err(vm.new_type_error("First argument must be of str type".to_string()))
|
||||
Err(vm.new_type_error("First argument must be of str type".to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +1,129 @@
|
||||
//! Random module.
|
||||
|
||||
use rand::distributions::Distribution;
|
||||
use rand_distr::Normal;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use crate::pyobject::{PyObjectRef, PyResult};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::{BigInt, Sign};
|
||||
use num_traits::Signed;
|
||||
use rand::RngCore;
|
||||
|
||||
use crate::function::OptionalOption;
|
||||
use crate::obj::objint::PyIntRef;
|
||||
use crate::obj::objtype::PyClassRef;
|
||||
use crate::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::VirtualMachine;
|
||||
|
||||
mod mersenne;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum PyRng {
|
||||
Std(rand::rngs::ThreadRng),
|
||||
MT(Box<mersenne::MT19937>),
|
||||
}
|
||||
|
||||
impl Default for PyRng {
|
||||
fn default() -> Self {
|
||||
PyRng::Std(rand::thread_rng())
|
||||
}
|
||||
}
|
||||
|
||||
impl RngCore for PyRng {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
match self {
|
||||
Self::Std(s) => s.next_u32(),
|
||||
Self::MT(m) => m.next_u32(),
|
||||
}
|
||||
}
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
match self {
|
||||
Self::Std(s) => s.next_u64(),
|
||||
Self::MT(m) => m.next_u64(),
|
||||
}
|
||||
}
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
match self {
|
||||
Self::Std(s) => s.fill_bytes(dest),
|
||||
Self::MT(m) => m.fill_bytes(dest),
|
||||
}
|
||||
}
|
||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
|
||||
match self {
|
||||
Self::Std(s) => s.try_fill_bytes(dest),
|
||||
Self::MT(m) => m.try_fill_bytes(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "Random")]
|
||||
#[derive(Debug)]
|
||||
struct PyRandom {
|
||||
rng: RefCell<PyRng>,
|
||||
}
|
||||
|
||||
impl PyValue for PyRandom {
|
||||
fn class(vm: &VirtualMachine) -> PyClassRef {
|
||||
vm.class("_random", "Random")
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl(flags(BASETYPE))]
|
||||
impl PyRandom {
|
||||
#[pyslot(new)]
|
||||
fn new(cls: PyClassRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
|
||||
PyRandom {
|
||||
rng: RefCell::new(PyRng::default()),
|
||||
}
|
||||
.into_ref_with_type(vm, cls)
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn random(&self) -> f64 {
|
||||
mersenne::gen_res53(&mut *self.rng.borrow_mut())
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn seed(&self, n: OptionalOption<PyIntRef>) {
|
||||
let new_rng = match n.flat_option() {
|
||||
None => PyRng::default(),
|
||||
Some(n) => {
|
||||
let (_, mut key) = n.as_bigint().abs().to_u32_digits();
|
||||
if cfg!(target_endian = "big") {
|
||||
key.reverse();
|
||||
}
|
||||
PyRng::MT(Box::new(mersenne::MT19937::new_with_slice_seed(&key)))
|
||||
}
|
||||
};
|
||||
|
||||
*self.rng.borrow_mut() = new_rng;
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
fn getrandbits(&self, mut k: usize) -> BigInt {
|
||||
let mut rng = self.rng.borrow_mut();
|
||||
|
||||
let mut gen_u32 = |k| rng.next_u32() >> (32 - k) as u32;
|
||||
|
||||
if k <= 32 {
|
||||
return gen_u32(k).into();
|
||||
}
|
||||
|
||||
let words = (k - 1) / 8 + 1;
|
||||
let mut wordarray = vec![0u32; words];
|
||||
|
||||
let it = wordarray.iter_mut();
|
||||
#[cfg(target_endian = "big")]
|
||||
let it = it.rev();
|
||||
for word in it {
|
||||
*word = gen_u32(k);
|
||||
k -= 32;
|
||||
}
|
||||
|
||||
BigInt::from_slice(Sign::NoSign, &wordarray)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
py_module!(vm, "random", {
|
||||
"gauss" => ctx.new_function(random_normalvariate), // TODO: is this the same?
|
||||
"normalvariate" => ctx.new_function(random_normalvariate),
|
||||
"random" => ctx.new_function(random_random),
|
||||
// "weibull", ctx.new_function(random_weibullvariate),
|
||||
py_module!(vm, "_random", {
|
||||
"Random" => PyRandom::make_class(ctx),
|
||||
})
|
||||
}
|
||||
|
||||
fn random_normalvariate(mu: f64, sigma: f64, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
let normal = Normal::new(mu, sigma).map_err(|rand_err| {
|
||||
vm.new_exception_msg(
|
||||
vm.ctx.exceptions.arithmetic_error.clone(),
|
||||
format!("invalid normal distribution: {:?}", rand_err),
|
||||
)
|
||||
})?;
|
||||
let value = normal.sample(&mut rand::thread_rng());
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
fn random_random(_vm: &VirtualMachine) -> f64 {
|
||||
rand::random()
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: enable this function:
|
||||
fn random_weibullvariate(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(alpha, Some(vm.ctx.float_type())), (beta, Some(vm.ctx.float_type()))]);
|
||||
let alpha = objfloat::get_value(alpha);
|
||||
let beta = objfloat::get_value(beta);
|
||||
let weibull = Weibull::new(alpha, beta);
|
||||
let value = weibull.sample(&mut rand::thread_rng());
|
||||
let py_value = vm.ctx.new_float(value);
|
||||
Ok(py_value)
|
||||
}
|
||||
*/
|
||||
|
||||
211
vm/src/stdlib/random/mersenne.rs
Normal file
211
vm/src/stdlib/random/mersenne.rs
Normal file
@@ -0,0 +1,211 @@
|
||||
#![allow(clippy::unreadable_literal)]
|
||||
|
||||
/*
|
||||
A C-program for MT19937, with initialization improved 2002/1/26.
|
||||
Coded by Takuji Nishimura and Makoto Matsumoto.
|
||||
|
||||
Before using, initialize the state by using init_genrand(seed)
|
||||
or init_by_array(init_key, key_length).
|
||||
|
||||
Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
|
||||
All rights reserved.
|
||||
|
||||
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. The names of its contributors may not 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 OWNER 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.
|
||||
|
||||
|
||||
Any feedback is very welcome.
|
||||
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
|
||||
email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
|
||||
*/
|
||||
|
||||
// this was translated from c; all rights go to copyright holders listed above
|
||||
// https://gist.github.com/coolreader18/b56d510f1b0551d2954d74ad289f7d2e
|
||||
|
||||
/* Period parameters */
|
||||
const N: usize = 624;
|
||||
const M: usize = 397;
|
||||
const MATRIX_A: u32 = 0x9908b0dfu32; /* constant vector a */
|
||||
const UPPER_MASK: u32 = 0x80000000u32; /* most significant w-r bits */
|
||||
const LOWER_MASK: u32 = 0x7fffffffu32; /* least significant r bits */
|
||||
|
||||
pub struct MT19937 {
|
||||
mt: [u32; N], /* the array for the state vector */
|
||||
mti: usize, /* mti==N+1 means mt[N] is not initialized */
|
||||
}
|
||||
impl Default for MT19937 {
|
||||
fn default() -> Self {
|
||||
MT19937 {
|
||||
mt: [0; N],
|
||||
mti: N + 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl std::fmt::Debug for MT19937 {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
f.pad("MT19937")
|
||||
}
|
||||
}
|
||||
|
||||
impl MT19937 {
|
||||
pub fn new_with_slice_seed(init_key: &[u32]) -> Self {
|
||||
let mut state = Self::default();
|
||||
state.seed_slice(init_key);
|
||||
state
|
||||
}
|
||||
|
||||
/* initializes self.mt[N] with a seed */
|
||||
fn seed(&mut self, s: u32) {
|
||||
self.mt[0] = s;
|
||||
self.mti = 1;
|
||||
while self.mti < N {
|
||||
self.mt[self.mti] = 1812433253u32
|
||||
.wrapping_mul(self.mt[self.mti - 1] ^ (self.mt[self.mti - 1] >> 30))
|
||||
+ self.mti as u32;
|
||||
/* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
|
||||
/* In the previous versions, MSBs of the seed affect */
|
||||
/* only MSBs of the array self.mt[]. */
|
||||
/* 2002/01/09 modified by Makoto Matsumoto */
|
||||
self.mti += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize by an array with array-length */
|
||||
/* init_key is the array for initializing keys */
|
||||
/* key_length is its length */
|
||||
/* slight change for C++, 2004/2/26 */
|
||||
pub fn seed_slice(&mut self, init_key: &[u32]) {
|
||||
let mut i;
|
||||
let mut j;
|
||||
let mut k;
|
||||
self.seed(19650218);
|
||||
i = 1;
|
||||
j = 0;
|
||||
k = if N > init_key.len() {
|
||||
N
|
||||
} else {
|
||||
init_key.len()
|
||||
};
|
||||
while k != 0 {
|
||||
self.mt[i] = (self.mt[i]
|
||||
^ ((self.mt[i - 1] ^ (self.mt[i - 1] >> 30)).wrapping_mul(1664525u32)))
|
||||
+ init_key[j]
|
||||
+ j as u32; /* non linear */
|
||||
self.mt[i] &= 0xffffffffu32; /* for WORDSIZE > 32 machines */
|
||||
i += 1;
|
||||
j += 1;
|
||||
if i >= N {
|
||||
self.mt[0] = self.mt[N - 1];
|
||||
i = 1;
|
||||
}
|
||||
if j >= init_key.len() {
|
||||
j = 0;
|
||||
}
|
||||
k -= 1;
|
||||
}
|
||||
k = N - 1;
|
||||
while k != 0 {
|
||||
self.mt[i] = (self.mt[i]
|
||||
^ ((self.mt[i - 1] ^ (self.mt[i - 1] >> 30)).wrapping_mul(1566083941u32)))
|
||||
- i as u32; /* non linear */
|
||||
self.mt[i] &= 0xffffffffu32; /* for WORDSIZE > 32 machines */
|
||||
i += 1;
|
||||
if i >= N {
|
||||
self.mt[0] = self.mt[N - 1];
|
||||
i = 1;
|
||||
}
|
||||
k -= 1;
|
||||
}
|
||||
|
||||
self.mt[0] = 0x80000000u32; /* MSB is 1; assuring non-zero initial array */
|
||||
}
|
||||
|
||||
/* generates a random number on [0,0xffffffff]-interval */
|
||||
fn gen_u32(&mut self) -> u32 {
|
||||
let mut y: u32;
|
||||
let mag01 = |x| if (x & 0x1) == 1 { MATRIX_A } else { 0 };
|
||||
/* mag01[x] = x * MATRIX_A for x=0,1 */
|
||||
|
||||
if self.mti >= N {
|
||||
/* generate N words at one time */
|
||||
|
||||
if self.mti == N + 1
|
||||
/* if seed() has not been called, */
|
||||
{
|
||||
self.seed(5489u32);
|
||||
} /* a default initial seed is used */
|
||||
|
||||
for kk in 0..N - M {
|
||||
y = (self.mt[kk] & UPPER_MASK) | (self.mt[kk + 1] & LOWER_MASK);
|
||||
self.mt[kk] = self.mt[kk + M] ^ (y >> 1) ^ mag01(y);
|
||||
}
|
||||
for kk in N - M..N - 1 {
|
||||
y = (self.mt[kk] & UPPER_MASK) | (self.mt[kk + 1] & LOWER_MASK);
|
||||
self.mt[kk] = self.mt[kk.wrapping_add(M.wrapping_sub(N))] ^ (y >> 1) ^ mag01(y);
|
||||
}
|
||||
y = (self.mt[N - 1] & UPPER_MASK) | (self.mt[0] & LOWER_MASK);
|
||||
self.mt[N - 1] = self.mt[M - 1] ^ (y >> 1) ^ mag01(y);
|
||||
|
||||
self.mti = 0;
|
||||
}
|
||||
|
||||
y = self.mt[self.mti];
|
||||
self.mti += 1;
|
||||
|
||||
/* Tempering */
|
||||
y ^= y >> 11;
|
||||
y ^= (y << 7) & 0x9d2c5680u32;
|
||||
y ^= (y << 15) & 0xefc60000u32;
|
||||
y ^= y >> 18;
|
||||
|
||||
y
|
||||
}
|
||||
}
|
||||
|
||||
/* generates a random number on [0,1) with 53-bit resolution*/
|
||||
pub fn gen_res53<R: rand::RngCore>(rng: &mut R) -> f64 {
|
||||
let a = rng.next_u32() >> 5;
|
||||
let b = rng.next_u32() >> 6;
|
||||
(a as f64 * 67108864.0 + b as f64) * (1.0 / 9007199254740992.0)
|
||||
}
|
||||
/* These real versions are due to Isaku Wada, 2002/01/09 added */
|
||||
|
||||
impl rand::RngCore for MT19937 {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
self.gen_u32()
|
||||
}
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
rand_core::impls::next_u64_via_u32(self)
|
||||
}
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
rand_core::impls::fill_bytes_via_next(self, dest)
|
||||
}
|
||||
fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand::Error> {
|
||||
self.fill_bytes(dest);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -266,7 +266,7 @@ fn do_split(
|
||||
|
||||
fn make_regex(vm: &VirtualMachine, pattern: &str, flags: PyRegexFlags) -> PyResult<PyPattern> {
|
||||
let unicode = if flags.unicode && flags.ascii {
|
||||
return Err(vm.new_value_error("ASCII and UNICODE flags are incompatible".to_string()));
|
||||
return Err(vm.new_value_error("ASCII and UNICODE flags are incompatible".to_owned()));
|
||||
} else {
|
||||
!flags.ascii
|
||||
};
|
||||
@@ -283,7 +283,7 @@ fn make_regex(vm: &VirtualMachine, pattern: &str, flags: PyRegexFlags) -> PyResu
|
||||
})?;
|
||||
Ok(PyPattern {
|
||||
regex: r,
|
||||
pattern: pattern.to_string(),
|
||||
pattern: pattern.to_owned(),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ fn re_compile(
|
||||
make_regex(vm, pattern.as_str(), flags)
|
||||
}
|
||||
|
||||
fn re_escape(pattern: PyStringRef, _vm: &VirtualMachine) -> String {
|
||||
fn re_escape(pattern: PyStringRef) -> String {
|
||||
regex::escape(pattern.as_str())
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ impl TryFromObject for Selectable {
|
||||
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
let fno = RawFd::try_from_object(vm, obj.clone()).or_else(|_| {
|
||||
let meth = vm.get_method_or_type_error(obj.clone(), "fileno", || {
|
||||
"select arg must be an int or object with a fileno() method".to_string()
|
||||
"select arg must be an int or object with a fileno() method".to_owned()
|
||||
})?;
|
||||
RawFd::try_from_object(vm, vm.invoke(&meth, vec![])?)
|
||||
})?;
|
||||
@@ -119,7 +119,7 @@ fn select_select(
|
||||
});
|
||||
if let Some(timeout) = timeout {
|
||||
if timeout < 0.0 {
|
||||
return Err(vm.new_value_error("timeout must be positive".to_string()));
|
||||
return Err(vm.new_value_error("timeout must be positive".to_owned()));
|
||||
}
|
||||
}
|
||||
let deadline = timeout.map(|s| super::time_module::get_time() + s);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user