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.
Files changed (39) hide show
  1. {optimism-3.1.2 → optimism-3.1.3}/PKG-INFO +1 -1
  2. {optimism-3.1.2 → optimism-3.1.3}/optimism/__init__.py +1 -1
  3. optimism-3.1.3/optimism/examples/memoryReports.py +25 -0
  4. {optimism-3.1.2 → optimism-3.1.3}/optimism/optimism.py +76 -5
  5. {optimism-3.1.2 → optimism-3.1.3}/optimism/test_examples.py +27 -1
  6. {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/PKG-INFO +1 -1
  7. optimism-3.1.2/optimism/examples/memoryReports.py +0 -9
  8. {optimism-3.1.2 → optimism-3.1.3}/LICENSE.txt +0 -0
  9. {optimism-3.1.2 → optimism-3.1.3}/README.md +0 -0
  10. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/a.txt +0 -0
  11. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/b.txt +0 -0
  12. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/bad.py +0 -0
  13. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/basic.py +0 -0
  14. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/bits.py +0 -0
  15. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/block.py +0 -0
  16. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/catch_and_release.py +0 -0
  17. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/code.py +0 -0
  18. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/core.py +0 -0
  19. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/doc_example.py +0 -0
  20. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/doctests.py +0 -0
  21. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/errors.py +0 -0
  22. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/files.py +0 -0
  23. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/fragments.py +0 -0
  24. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/io_example.py +0 -0
  25. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/literals.py +0 -0
  26. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/multi.py +0 -0
  27. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/reverse_tracing.py +0 -0
  28. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/runfile.py +0 -0
  29. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/skip.py +0 -0
  30. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/structure.py +0 -0
  31. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/suites.py +0 -0
  32. {optimism-3.1.2 → optimism-3.1.3}/optimism/examples/tracing.py +0 -0
  33. {optimism-3.1.2 → optimism-3.1.3}/optimism/py.typed +0 -0
  34. {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/SOURCES.txt +0 -0
  35. {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/dependency_links.txt +0 -0
  36. {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/requires.txt +0 -0
  37. {optimism-3.1.2 → optimism-3.1.3}/optimism.egg-info/top_level.txt +0 -0
  38. {optimism-3.1.2 → optimism-3.1.3}/pyproject.toml +0 -0
  39. {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.2
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.2"
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.2"
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({cObj})} is already"
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
- result = copy.deepcopy(obj)
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.2
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
@@ -1,9 +0,0 @@
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))
File without changes
File without changes
File without changes
File without changes
File without changes