optimism 3.1.2__tar.gz → 3.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {optimism-3.1.2 → optimism-3.1.3}/PKG-INFO +1 -1
- {optimism-3.1.2 → optimism-3.1.3}/optimism/__init__.py +1 -1
- optimism-3.1.3/optimism/examples/memoryReports.py +25 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/optimism.py +76 -5
- {optimism-3.1.2 → optimism-3.1.3}/optimism/test_examples.py +27 -1
- {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/PKG-INFO +1 -1
- optimism-3.1.2/optimism/examples/memoryReports.py +0 -9
- {optimism-3.1.2 → optimism-3.1.3}/LICENSE.txt +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/README.md +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/a.txt +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/b.txt +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/bad.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/basic.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/bits.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/block.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/catch_and_release.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/code.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/core.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/doc_example.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/doctests.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/errors.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/files.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/fragments.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/io_example.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/literals.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/multi.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/reverse_tracing.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/runfile.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/skip.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/structure.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/suites.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/tracing.py +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism/py.typed +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/SOURCES.txt +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/dependency_links.txt +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/requires.txt +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/top_level.txt +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/pyproject.toml +0 -0
- {optimism-3.1.2 → optimism-3.1.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: optimism
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.3
|
|
4
4
|
Summary: Very simple testing framework suitable for beginner programmers, with easy functions for accomplishing most common testing tasks like providing input. Requires Python 3.8+.
|
|
5
5
|
Home-page: https://cs.wellesley.edu/~pmwh/optimism/docs/optimism.html
|
|
6
6
|
Author: Peter Mawhorter
|
|
@@ -13,7 +13,7 @@ from .optimism import *
|
|
|
13
13
|
# version from optimism, but we want the version to be defined in that
|
|
14
14
|
# file so that a single-file distribution is equivalent to this packaged
|
|
15
15
|
# distribution. So we define a version here as well, but...
|
|
16
|
-
__version__ = "3.1.
|
|
16
|
+
__version__ = "3.1.3"
|
|
17
17
|
|
|
18
18
|
# ...then we assert it matches so testing will catch it if I forget to
|
|
19
19
|
# keep them in sync before a release. T_T
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import optimism as opt
|
|
2
|
+
|
|
3
|
+
words = ['hi', 'bye']
|
|
4
|
+
pair = [words, words]
|
|
5
|
+
print(opt.memoryReport(words=words, pair=pair))
|
|
6
|
+
|
|
7
|
+
knot = [pair, words]
|
|
8
|
+
knot.append(knot)
|
|
9
|
+
print(opt.memoryReport(pair=pair, words=words, knot=knot))
|
|
10
|
+
|
|
11
|
+
code = """\
|
|
12
|
+
a = []
|
|
13
|
+
b = []
|
|
14
|
+
b.append([])
|
|
15
|
+
a.append(b)
|
|
16
|
+
a.append([])
|
|
17
|
+
import math # don't allow deep copy of env for this code
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
tester = opt.testBlock(code)
|
|
21
|
+
case = tester.case()
|
|
22
|
+
case.checkVariableStructure('a', [[[]], []])
|
|
23
|
+
case.checkCustom(
|
|
24
|
+
lambda result: result['scope']['a'][0] is result['scope']['b']
|
|
25
|
+
)
|
|
@@ -200,6 +200,13 @@ TODO: Workaround for tracing in interactive console?
|
|
|
200
200
|
|
|
201
201
|
## Changelog
|
|
202
202
|
|
|
203
|
+
- Version 3.1.3 Fixes a numbering bug with memory reports and also fixes
|
|
204
|
+
a pernicious `deepish_copy` bug: Structures that were supposed to be
|
|
205
|
+
duplicated would have their top levels duplicated twice separately
|
|
206
|
+
because the memo from `deepish_copy` was not being passed into
|
|
207
|
+
`deepcopy` (of course, fixing that the simple way caused more problems
|
|
208
|
+
when `deepcopy` would update the memo before erroring out). New tests
|
|
209
|
+
to catch these bugs were added, including doctests for `deepish_copy`.
|
|
203
210
|
- Version 3.1.2 Adds shims to support Python versions 3.8-3.10 again,
|
|
204
211
|
rather than just 3.11+.
|
|
205
212
|
- Version 3.1.1 reformulates the module as a package so that it can add
|
|
@@ -346,7 +353,7 @@ TODO: Workaround for tracing in interactive console?
|
|
|
346
353
|
|
|
347
354
|
# TODO: Cache compiled ASTs!
|
|
348
355
|
|
|
349
|
-
__version__ = "3.1.
|
|
356
|
+
__version__ = "3.1.3"
|
|
350
357
|
|
|
351
358
|
from typing import (
|
|
352
359
|
Any, Dict, List, Optional, Tuple, Literal as LiteralType, Callable,
|
|
@@ -7270,7 +7277,7 @@ def memoryMap(
|
|
|
7270
7277
|
# not made shallow
|
|
7271
7278
|
assigned[id(obj)] = (my_ref, obj)
|
|
7272
7279
|
if count_from > 0:
|
|
7273
|
-
return count_from, my_ref
|
|
7280
|
+
return count_from - 1, my_ref
|
|
7274
7281
|
else:
|
|
7275
7282
|
return None, my_ref
|
|
7276
7283
|
|
|
@@ -7341,6 +7348,16 @@ def memoryReport(*objs: Any, **named: Any) -> str:
|
|
|
7341
7348
|
>>> print(memoryReport(x=5, y=12.0), end='')
|
|
7342
7349
|
x: 5
|
|
7343
7350
|
y: 12.0
|
|
7351
|
+
>>> a = ['hi', 'bye']
|
|
7352
|
+
>>> b = [a, a]
|
|
7353
|
+
>>> inlineStringsInMemoryReports(False)
|
|
7354
|
+
>>> print(memoryReport(a=a, b=b), end='')
|
|
7355
|
+
a: @0
|
|
7356
|
+
b: @3
|
|
7357
|
+
@0: [@1, @2]
|
|
7358
|
+
@3: [@0, @0]
|
|
7359
|
+
@1: 'hi'
|
|
7360
|
+
@2: 'bye'
|
|
7344
7361
|
"""
|
|
7345
7362
|
refs: MemoryMap = {}
|
|
7346
7363
|
top = -1
|
|
@@ -7358,6 +7375,7 @@ def memoryReport(*objs: Any, **named: Any) -> str:
|
|
|
7358
7375
|
|
|
7359
7376
|
# Order by named values (in order given) and then numeric values (by
|
|
7360
7377
|
# number assigned)
|
|
7378
|
+
# TODO: Consider ordering name refs by their names?
|
|
7361
7379
|
|
|
7362
7380
|
result = ''
|
|
7363
7381
|
handled = set()
|
|
@@ -7861,7 +7879,7 @@ def reportObjDiffs(
|
|
|
7861
7879
|
rev = [key for key in env if env[key] == cObj][0]
|
|
7862
7880
|
yield (
|
|
7863
7881
|
f"{prefix}: reference {repr(aObj)} cannot match"
|
|
7864
|
-
f" {repr(cObj)} because {repr(
|
|
7882
|
+
f" {repr(cObj)} because {repr(cObj)} is already"
|
|
7865
7883
|
f" assigned as the match for {repr(rev)}. This"
|
|
7866
7884
|
f" means you have used two references to"
|
|
7867
7885
|
f" different objects where the correct solution"
|
|
@@ -9913,16 +9931,69 @@ def deepish_copy(obj: T, memo: Optional[dict] = None) -> T:
|
|
|
9913
9931
|
copy.deepcopy wherever possible and making shallower copies
|
|
9914
9932
|
elsewhere. Basically a middle-ground between copy.deepcopy and
|
|
9915
9933
|
copy.copy.
|
|
9934
|
+
|
|
9935
|
+
TODO: Why does this break in a notebook?!?
|
|
9936
|
+
|
|
9937
|
+
For example:
|
|
9938
|
+
|
|
9939
|
+
>>> import math # copy module is not deep-copyable
|
|
9940
|
+
>>> stuff = ['a', math]
|
|
9941
|
+
>>> outside = [stuff, math, stuff]
|
|
9942
|
+
>>> copy.deepcopy(outside) # can't copy list w/ module inside
|
|
9943
|
+
Traceback (most recent call last):
|
|
9944
|
+
...
|
|
9945
|
+
TypeError...
|
|
9946
|
+
>>> clone = deepish_copy(outside)
|
|
9947
|
+
>>> clone is outside
|
|
9948
|
+
False
|
|
9949
|
+
>>> clone # doctest: +ELLIPSIS
|
|
9950
|
+
[['a', <module 'math'...>], <module 'math'...>, ['a', <module 'math'...>]]
|
|
9951
|
+
>>> outside # doctest: +ELLIPSIS
|
|
9952
|
+
[['a', <module 'math'...>], <module 'math'...>, ['a', <module 'math'...>]]
|
|
9953
|
+
>>> clone == outside
|
|
9954
|
+
True
|
|
9955
|
+
>>> clone[0] is stuff
|
|
9956
|
+
False
|
|
9957
|
+
>>> clone[0] == stuff
|
|
9958
|
+
True
|
|
9959
|
+
>>> clone[1] is math # can't copy modules, so it is tangled
|
|
9960
|
+
True
|
|
9961
|
+
>>> clone[1] == math
|
|
9962
|
+
True
|
|
9963
|
+
>>> clone[0][0] == 'a'
|
|
9964
|
+
True
|
|
9965
|
+
>>> clone[0][1] is math
|
|
9966
|
+
True
|
|
9967
|
+
>>> clone[1] is clone[0][1] # alias preserved
|
|
9968
|
+
True
|
|
9969
|
+
>>> clone[0] is clone[2]
|
|
9970
|
+
True
|
|
9971
|
+
>>> # Now a test with a dictionary
|
|
9972
|
+
>>> d = {'a': outside, 'b': stuff}
|
|
9973
|
+
>>> copy.deepcopy(d) # can't copy dictionary w/ module inside
|
|
9974
|
+
Traceback (most recent call last):
|
|
9975
|
+
...
|
|
9976
|
+
TypeError...
|
|
9977
|
+
>>> dc = deepish_copy(d)
|
|
9978
|
+
>>> dc['a'] is outside
|
|
9979
|
+
False
|
|
9980
|
+
>>> dc['a'] == outside
|
|
9981
|
+
True
|
|
9982
|
+
>>> dc['a'][0] is dc['b']
|
|
9983
|
+
True
|
|
9984
|
+
>>> dc['a'][2] is dc['b']
|
|
9985
|
+
True
|
|
9916
9986
|
"""
|
|
9917
9987
|
if memo is None:
|
|
9918
9988
|
memo = {}
|
|
9919
9989
|
if id(obj) in memo:
|
|
9920
9990
|
return memo[id(obj)]
|
|
9921
|
-
|
|
9922
9991
|
result: T
|
|
9923
9992
|
try:
|
|
9924
|
-
|
|
9993
|
+
save = copy.copy(memo)
|
|
9994
|
+
result = copy.deepcopy(obj, save) # TODO: Is memo always compatible?
|
|
9925
9995
|
# not sure about memo dict compatibility
|
|
9996
|
+
memo.update(save) # if we didn't crash out, update real memo
|
|
9926
9997
|
memo[id(obj)] = result
|
|
9927
9998
|
return result
|
|
9928
9999
|
|
|
@@ -29,7 +29,8 @@ EXAMPLES = [
|
|
|
29
29
|
("suites", []),
|
|
30
30
|
("literals", []),
|
|
31
31
|
("structure", []),
|
|
32
|
-
("doctests", [])
|
|
32
|
+
("doctests", []),
|
|
33
|
+
("memoryReports", [])
|
|
33
34
|
#("reverse_tracing", []),
|
|
34
35
|
# TODO: Include this once the machinery for it is there
|
|
35
36
|
]
|
|
@@ -1247,6 +1248,10 @@ All 4 expectation(s) were met.
|
|
|
1247
1248
|
Found only 2 matching distinct doctest example(s) (required 3).
|
|
1248
1249
|
checked code in file 'doc_example.py'
|
|
1249
1250
|
"""
|
|
1251
|
+
],
|
|
1252
|
+
"memoryReports": [
|
|
1253
|
+
"✓ {file}:22",
|
|
1254
|
+
"✓ {file}:23",
|
|
1250
1255
|
]
|
|
1251
1256
|
}
|
|
1252
1257
|
|
|
@@ -1290,6 +1295,27 @@ Outcomes in suite A (again):
|
|
|
1290
1295
|
"No more outcomes in suite A: []",
|
|
1291
1296
|
"No more outcomes in suite B: []",
|
|
1292
1297
|
"No more suite B.",
|
|
1298
|
+
],
|
|
1299
|
+
|
|
1300
|
+
"memoryReports": [
|
|
1301
|
+
"""\
|
|
1302
|
+
words: @0
|
|
1303
|
+
pair: @3
|
|
1304
|
+
@0: [@1, @2]
|
|
1305
|
+
@3: [@0, @0]
|
|
1306
|
+
@1: 'hi'
|
|
1307
|
+
@2: 'bye'
|
|
1308
|
+
""",
|
|
1309
|
+
"""\
|
|
1310
|
+
pair: @0
|
|
1311
|
+
words: @1
|
|
1312
|
+
knot: @4
|
|
1313
|
+
@0: [@1, @1]
|
|
1314
|
+
@1: [@2, @3]
|
|
1315
|
+
@4: [@0, @1, @4]
|
|
1316
|
+
@2: 'hi'
|
|
1317
|
+
@3: 'bye'
|
|
1318
|
+
""",
|
|
1293
1319
|
]
|
|
1294
1320
|
}
|
|
1295
1321
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: optimism
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.3
|
|
4
4
|
Summary: Very simple testing framework suitable for beginner programmers, with easy functions for accomplishing most common testing tasks like providing input. Requires Python 3.8+.
|
|
5
5
|
Home-page: https://cs.wellesley.edu/~pmwh/optimism/docs/optimism.html
|
|
6
6
|
Author: Peter Mawhorter
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|